aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-21 00:14:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-21 00:14:42 -0400
commitf894d18380e7e7ff05f6622ccb75d2881922c6e9 (patch)
treee3c11b831b68096239a49dec539a49e49c1d90b7
parentd13ff0559fea73f237a01669887d2c10e11d7662 (diff)
parentd20b27478d6ccf7c4c8de4f09db2bdbaec82a6c0 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (277 commits) V4L/DVB (8415): gspca: Infinite loop in i2c_w() of etoms. V4L/DVB (8414): videodev/cx18: fix get_index bug and error-handling lock-ups V4L/DVB (8411): videobuf-dma-contig.c: fix 64-bit build for pre-2.6.24 kernels V4L/DVB (8410): sh_mobile_ceu_camera: fix 64-bit compiler warnings V4L/DVB (8397): video: convert select VIDEO_ZORAN_ZR36060 into depends on V4L/DVB (8396): video: Fix Kbuild dependency for VIDEO_IR_I2C V4L/DVB (8395): saa7134: Fix Kbuild dependency of ir-kbd-i2c V4L/DVB (8394): ir-common: CodingStyle fix: move EXPORT_SYMBOL_GPL to their proper places V4L/DVB (8393): media/video: Fix depencencies for VIDEOBUF V4L/DVB (8392): media/Kconfig: Convert V4L1_COMPAT select into "depends on" V4L/DVB (8390): videodev: add comment and remove magic number. V4L/DVB (8389): videodev: simplify get_index() V4L/DVB (8387): Some cosmetic changes V4L/DVB (8381): ov7670: fix compile warnings V4L/DVB (8380): saa7115: use saa7115_auto instead of saa711x as the autodetect driver name. V4L/DVB (8379): saa7127: Make device detection optional V4L/DVB (8378): cx18: move cx18_av_vbi_setup to av-core.c and rename to cx18_av_std_setup V4L/DVB (8377): ivtv/cx18: ensure the default control values are correct V4L/DVB (8376): cx25840: move cx25840_vbi_setup to core.c and rename to cx25840_std_setup V4L/DVB (8374): gspca: No conflict of 0c45:6011 with the sn9c102 driver. ...
-rw-r--r--Documentation/video4linux/CARDLIST.cx238851
-rw-r--r--Documentation/video4linux/CARDLIST.em28xx5
-rw-r--r--Documentation/video4linux/CARDLIST.saa71348
-rw-r--r--Documentation/video4linux/cx18.txt36
-rw-r--r--Documentation/video4linux/gspca.txt243
-rw-r--r--drivers/media/Kconfig5
-rw-r--r--drivers/media/common/ir-functions.c26
-rw-r--r--drivers/media/common/saa7146_core.c4
-rw-r--r--drivers/media/common/saa7146_hlp.c2
-rw-r--r--drivers/media/common/saa7146_i2c.c34
-rw-r--r--drivers/media/common/saa7146_video.c4
-rw-r--r--drivers/media/common/tuners/Kconfig1
-rw-r--r--drivers/media/common/tuners/tda18271-maps.c2
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.c25
-rw-r--r--drivers/media/common/tuners/xc5000.c7
-rw-r--r--drivers/media/dvb/Kconfig1
-rw-r--r--drivers/media/dvb/Makefile2
-rw-r--r--drivers/media/dvb/bt8xx/bt878.h2
-rw-r--r--drivers/media/dvb/dvb-core/demux.h2
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c8
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c17
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c2
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.c78
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ringbuffer.h12
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig15
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile3
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.c553
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.h304
-rw-r--r--drivers/media/dvb/dvb-usb/au6610.c83
-rw-r--r--drivers/media/dvb/dvb-usb/au6610.h22
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.c146
-rw-r--r--drivers/media/dvb/dvb-usb/cxusb.h3
-rw-r--r--drivers/media/dvb/dvb-usb/dib0700_devices.c7
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c4
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h8
-rw-r--r--drivers/media/dvb/dvb-usb/gl861.c38
-rw-r--r--drivers/media/dvb/dvb-usb/gl861.h2
-rw-r--r--drivers/media/dvb/frontends/au8522.c1
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c47
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h1
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c24
-rw-r--r--drivers/media/dvb/frontends/s5h1409.c1
-rw-r--r--drivers/media/dvb/frontends/s5h1411.c1
-rw-r--r--drivers/media/dvb/frontends/tda10023.c197
-rw-r--r--drivers/media/dvb/frontends/tda1002x.h41
-rw-r--r--drivers/media/dvb/pluto2/pluto2.c2
-rw-r--r--drivers/media/dvb/siano/Kconfig26
-rw-r--r--drivers/media/dvb/siano/Makefile8
-rw-r--r--drivers/media/dvb/siano/sms-cards.c102
-rw-r--r--drivers/media/dvb/siano/sms-cards.h45
-rw-r--r--drivers/media/dvb/siano/smscoreapi.c1251
-rw-r--r--drivers/media/dvb/siano/smscoreapi.h434
-rw-r--r--drivers/media/dvb/siano/smsdvb.c449
-rw-r--r--drivers/media/dvb/siano/smsusb.c459
-rw-r--r--drivers/media/dvb/ttpci/Kconfig2
-rw-r--r--drivers/media/dvb/ttpci/Makefile7
-rw-r--r--drivers/media/dvb/ttpci/av7110.c47
-rw-r--r--drivers/media/dvb/ttpci/av7110.h1
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c2
-rw-r--r--drivers/media/dvb/ttpci/av7110_ca.c2
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.h3
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c12
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c24
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c4
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c44
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c22
-rw-r--r--drivers/media/radio/radio-si470x.c483
-rw-r--r--drivers/media/video/Kconfig99
-rw-r--r--drivers/media/video/Makefile5
-rw-r--r--drivers/media/video/bt819.c2
-rw-r--r--drivers/media/video/bt8xx/bt832.c1
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c51
-rw-r--r--drivers/media/video/bt8xx/bttv-i2c.c49
-rw-r--r--drivers/media/video/bt8xx/bttv-vbi.c6
-rw-r--r--drivers/media/video/bt8xx/bttv.h1
-rw-r--r--drivers/media/video/bt8xx/bttvp.h9
-rw-r--r--drivers/media/video/cafe_ccic.c18
-rw-r--r--drivers/media/video/compat_ioctl32.c1
-rw-r--r--drivers/media/video/cs5345.c1
-rw-r--r--drivers/media/video/cs53l32a.c2
-rw-r--r--drivers/media/video/cx18/cx18-audio.c15
-rw-r--r--drivers/media/video/cx18/cx18-av-audio.c12
-rw-r--r--drivers/media/video/cx18/cx18-av-core.c225
-rw-r--r--drivers/media/video/cx18/cx18-av-core.h16
-rw-r--r--drivers/media/video/cx18/cx18-av-firmware.c72
-rw-r--r--drivers/media/video/cx18/cx18-av-vbi.c152
-rw-r--r--drivers/media/video/cx18/cx18-cards.c89
-rw-r--r--drivers/media/video/cx18/cx18-cards.h9
-rw-r--r--drivers/media/video/cx18/cx18-controls.c216
-rw-r--r--drivers/media/video/cx18/cx18-controls.h7
-rw-r--r--drivers/media/video/cx18/cx18-driver.c21
-rw-r--r--drivers/media/video/cx18/cx18-driver.h7
-rw-r--r--drivers/media/video/cx18/cx18-firmware.c10
-rw-r--r--drivers/media/video/cx18/cx18-gpio.c90
-rw-r--r--drivers/media/video/cx18/cx18-gpio.h2
-rw-r--r--drivers/media/video/cx18/cx18-i2c.c25
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c1179
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.h6
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c1
-rw-r--r--drivers/media/video/cx18/cx18-streams.c12
-rw-r--r--drivers/media/video/cx18/cx23418.h5
-rw-r--r--drivers/media/video/cx2341x.c180
-rw-r--r--drivers/media/video/cx23885/Kconfig2
-rw-r--r--drivers/media/video/cx23885/cx23885-417.c701
-rw-r--r--drivers/media/video/cx23885/cx23885-cards.c13
-rw-r--r--drivers/media/video/cx23885/cx23885-core.c10
-rw-r--r--drivers/media/video/cx23885/cx23885-dvb.c42
-rw-r--r--drivers/media/video/cx23885/cx23885-video.c24
-rw-r--r--drivers/media/video/cx23885/cx23885.h1
-rw-r--r--drivers/media/video/cx25840/cx25840-core.c158
-rw-r--r--drivers/media/video/cx25840/cx25840-core.h3
-rw-r--r--drivers/media/video/cx25840/cx25840-vbi.c152
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c1
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c19
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c1
-rw-r--r--drivers/media/video/cx88/cx88-video.c24
-rw-r--r--drivers/media/video/cx88/cx88-vp3054-i2c.c1
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c74
-rw-r--r--drivers/media/video/em28xx/em28xx-dvb.c25
-rw-r--r--drivers/media/video/em28xx/em28xx-i2c.c1
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c87
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c32
-rw-r--r--drivers/media/video/em28xx/em28xx.h12
-rw-r--r--drivers/media/video/gspca/Kconfig13
-rw-r--r--drivers/media/video/gspca/Makefile29
-rw-r--r--drivers/media/video/gspca/conex.c1051
-rw-r--r--drivers/media/video/gspca/etoms.c956
-rw-r--r--drivers/media/video/gspca/gspca.c1905
-rw-r--r--drivers/media/video/gspca/gspca.h176
-rw-r--r--drivers/media/video/gspca/jpeg.h301
-rw-r--r--drivers/media/video/gspca/mars.c464
-rw-r--r--drivers/media/video/gspca/ov519.c2186
-rw-r--r--drivers/media/video/gspca/pac207.c622
-rw-r--r--drivers/media/video/gspca/pac7311.c760
-rw-r--r--drivers/media/video/gspca/sonixb.c1477
-rw-r--r--drivers/media/video/gspca/sonixj.c1671
-rw-r--r--drivers/media/video/gspca/spca500.c1216
-rw-r--r--drivers/media/video/gspca/spca501.c2229
-rw-r--r--drivers/media/video/gspca/spca505.c951
-rw-r--r--drivers/media/video/gspca/spca506.c847
-rw-r--r--drivers/media/video/gspca/spca508.c1791
-rw-r--r--drivers/media/video/gspca/spca561.c1052
-rw-r--r--drivers/media/video/gspca/stk014.c592
-rw-r--r--drivers/media/video/gspca/sunplus.c1677
-rw-r--r--drivers/media/video/gspca/t613.c1038
-rw-r--r--drivers/media/video/gspca/tv8532.c670
-rw-r--r--drivers/media/video/gspca/vc032x.c1818
-rw-r--r--drivers/media/video/gspca/zc3xx-reg.h261
-rw-r--r--drivers/media/video/gspca/zc3xx.c7623
-rw-r--r--drivers/media/video/ir-kbd-i2c.c82
-rw-r--r--drivers/media/video/ivtv/ivtv-cards.c75
-rw-r--r--drivers/media/video/ivtv/ivtv-cards.h3
-rw-r--r--drivers/media/video/ivtv/ivtv-controls.c225
-rw-r--r--drivers/media/video/ivtv/ivtv-controls.h6
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c19
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h1
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c25
-rw-r--r--drivers/media/video/ivtv/ivtv-gpio.c11
-rw-r--r--drivers/media/video/ivtv/ivtv-i2c.c6
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c2184
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.h9
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c3
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c86
-rw-r--r--drivers/media/video/m52790.c1
-rw-r--r--drivers/media/video/meye.c18
-rw-r--r--drivers/media/video/msp3400-driver.c3
-rw-r--r--drivers/media/video/msp3400-kthreads.c1
-rw-r--r--drivers/media/video/mt9v022.c1
-rw-r--r--drivers/media/video/ov7670.c28
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-audio.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-audio.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-context.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-context.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ctrl.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ctrl.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-debug.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-debugifc.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-debugifc.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.c11
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-eeprom.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-eeprom.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-encoder.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-encoder.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.c75
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-hdw.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-core.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-i2c-core.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-io.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-io.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ioread.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-ioread.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-main.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-std.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-std.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-sysfs.c461
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-sysfs.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-tuner.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-tuner.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-util.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-video-v4l.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-video-v4l.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-wm8775.c1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-wm8775.h1
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2.h1
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c2
-rw-r--r--drivers/media/video/pwc/pwc-ioctl.h1
-rw-r--r--drivers/media/video/pxa_camera.c27
-rw-r--r--drivers/media/video/s2255drv.c2495
-rw-r--r--drivers/media/video/saa5246a.c1
-rw-r--r--drivers/media/video/saa5249.c1
-rw-r--r--drivers/media/video/saa6588.c1
-rw-r--r--drivers/media/video/saa7115.c4
-rw-r--r--drivers/media/video/saa711x.c584
-rw-r--r--drivers/media/video/saa7127.c43
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c105
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c4
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c181
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c1
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c10
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c86
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c81
-rw-r--r--drivers/media/video/saa7134/saa7134-reg.h1
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c35
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c82
-rw-r--r--drivers/media/video/saa7134/saa7134.h6
-rw-r--r--drivers/media/video/sh_mobile_ceu_camera.c657
-rw-r--r--drivers/media/video/sn9c102/sn9c102_devtable.h2
-rw-r--r--drivers/media/video/soc_camera.c64
-rw-r--r--drivers/media/video/soc_camera_platform.c198
-rw-r--r--drivers/media/video/stk-webcam.c18
-rw-r--r--drivers/media/video/tcm825x.c6
-rw-r--r--drivers/media/video/tcm825x.h1
-rw-r--r--drivers/media/video/tda7432.c1
-rw-r--r--drivers/media/video/tda9840.c1
-rw-r--r--drivers/media/video/tda9875.c2
-rw-r--r--drivers/media/video/tea6415c.c1
-rw-r--r--drivers/media/video/tea6420.c1
-rw-r--r--drivers/media/video/tlv320aic23b.c1
-rw-r--r--drivers/media/video/tuner-core.c1
-rw-r--r--drivers/media/video/tvaudio.c13
-rw-r--r--drivers/media/video/usbvision/usbvision-core.c4
-rw-r--r--drivers/media/video/usbvision/usbvision-i2c.c5
-rw-r--r--drivers/media/video/usbvision/usbvision-video.c30
-rw-r--r--drivers/media/video/uvc/Kconfig17
-rw-r--r--drivers/media/video/uvc/uvc_ctrl.c1
-rw-r--r--drivers/media/video/uvc/uvc_driver.c31
-rw-r--r--drivers/media/video/uvc/uvc_queue.c1
-rw-r--r--drivers/media/video/uvc/uvc_status.c20
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c3
-rw-r--r--drivers/media/video/uvc/uvc_video.c117
-rw-r--r--drivers/media/video/uvc/uvcvideo.h3
-rw-r--r--drivers/media/video/videobuf-dma-contig.c418
-rw-r--r--drivers/media/video/videobuf-dma-sg.c8
-rw-r--r--drivers/media/video/videobuf-dvb.c2
-rw-r--r--drivers/media/video/videobuf-vmalloc.c2
-rw-r--r--drivers/media/video/videodev.c735
-rw-r--r--drivers/media/video/vivi.c37
-rw-r--r--drivers/media/video/vp27smpx.c1
-rw-r--r--drivers/media/video/wm8739.c1
-rw-r--r--drivers/media/video/wm8775.c2
-rw-r--r--drivers/media/video/zoran_card.c34
-rw-r--r--drivers/media/video/zoran_driver.c5
-rw-r--r--drivers/media/video/zr364xx.c16
-rw-r--r--include/linux/i2c-id.h8
-rw-r--r--include/linux/videodev2.h14
-rw-r--r--include/media/cx2341x.h7
-rw-r--r--include/media/ir-kbd-i2c.h3
-rw-r--r--include/media/pwc-ioctl.h3
-rw-r--r--include/media/saa7146.h4
-rw-r--r--include/media/sh_mobile_ceu.h12
-rw-r--r--include/media/soc_camera.h16
-rw-r--r--include/media/soc_camera_platform.h15
-rw-r--r--include/media/v4l2-dev.h83
-rw-r--r--include/media/v4l2-i2c-drv-legacy.h1
-rw-r--r--include/media/videobuf-dma-contig.h32
-rw-r--r--include/media/videobuf-dma-sg.h2
-rw-r--r--include/media/videobuf-vmalloc.h2
290 files changed, 47416 insertions, 5190 deletions
diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885
index 191194ea1e25..f0e613ba55b8 100644
--- a/Documentation/video4linux/CARDLIST.cx23885
+++ b/Documentation/video4linux/CARDLIST.cx23885
@@ -8,3 +8,4 @@
8 7 -> Hauppauge WinTV-HVR1200 [0070:71d1,0070:71d3] 8 7 -> Hauppauge WinTV-HVR1200 [0070:71d1,0070:71d3]
9 8 -> Hauppauge WinTV-HVR1700 [0070:8101] 9 8 -> Hauppauge WinTV-HVR1700 [0070:8101]
10 9 -> Hauppauge WinTV-HVR1400 [0070:8010] 10 9 -> Hauppauge WinTV-HVR1400 [0070:8010]
11 10 -> DViCO FusionHDTV7 Dual Express [18ac:d618]
diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
index 1d6a245c828f..10591467ef16 100644
--- a/Documentation/video4linux/CARDLIST.em28xx
+++ b/Documentation/video4linux/CARDLIST.em28xx
@@ -8,10 +8,13 @@
8 7 -> Leadtek Winfast USB II (em2800) 8 7 -> Leadtek Winfast USB II (em2800)
9 8 -> Kworld USB2800 (em2800) 9 8 -> Kworld USB2800 (em2800)
10 9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a] 10 9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a]
11 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500,2040:6502] 11 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
12 11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 12 11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
13 12 -> Kworld PVR TV 2800 RF (em2820/em2840) 13 12 -> Kworld PVR TV 2800 RF (em2820/em2840)
14 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] 14 13 -> Terratec Prodigy XS (em2880) [0ccd:0047]
15 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) 15 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
16 15 -> V-Gear PocketTV (em2800) 16 15 -> V-Gear PocketTV (em2800)
17 16 -> Hauppauge WinTV HVR 950 (em2880) [2040:6513,2040:6517,2040:651b,2040:651f] 17 16 -> Hauppauge WinTV HVR 950 (em2880) [2040:6513,2040:6517,2040:651b,2040:651f]
18 17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227]
19 18 -> Hauppauge WinTV HVR 900 (R2) (em2880) [2040:6502]
20 19 -> PointNix Intra-Oral Camera (em2860)
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 67937df1e974..39868af9cf9f 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -37,7 +37,7 @@
37 36 -> UPMOST PURPLE TV [12ab:0800] 37 36 -> UPMOST PURPLE TV [12ab:0800]
38 37 -> Items MuchTV Plus / IT-005 38 37 -> Items MuchTV Plus / IT-005
39 38 -> Terratec Cinergy 200 TV [153b:1152] 39 38 -> Terratec Cinergy 200 TV [153b:1152]
40 39 -> LifeView FlyTV Platinum Mini [5168:0212,4e42:0212] 40 39 -> LifeView FlyTV Platinum Mini [5168:0212,4e42:0212,5169:1502]
41 40 -> Compro VideoMate TV PVR/FM [185b:c100] 41 40 -> Compro VideoMate TV PVR/FM [185b:c100]
42 41 -> Compro VideoMate TV Gold+ [185b:c100] 42 41 -> Compro VideoMate TV Gold+ [185b:c100]
43 42 -> Sabrent SBT-TVFM (saa7130) 43 42 -> Sabrent SBT-TVFM (saa7130)
@@ -128,7 +128,7 @@
128127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090] 128127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090]
129128 -> Beholder BeholdTV Columbus TVFM [0000:5201] 129128 -> Beholder BeholdTV Columbus TVFM [0000:5201]
130129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093] 130129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093]
131130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193,5ace:6191] 131130 -> Beholder BeholdTV M6 [5ace:6190]
132131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022] 132131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022]
133132 -> Genius TVGO AM11MCE 133132 -> Genius TVGO AM11MCE
134133 -> NXP Snake DVB-S reference design 134133 -> NXP Snake DVB-S reference design
@@ -141,3 +141,7 @@
141140 -> Avermedia DVB-S Pro A700 [1461:a7a1] 141140 -> Avermedia DVB-S Pro A700 [1461:a7a1]
142141 -> Avermedia DVB-S Hybrid+FM A700 [1461:a7a2] 142141 -> Avermedia DVB-S Hybrid+FM A700 [1461:a7a2]
143142 -> Beholder BeholdTV H6 [5ace:6290] 143142 -> Beholder BeholdTV H6 [5ace:6290]
144143 -> Beholder BeholdTV M63 [5ace:6191]
145144 -> Beholder BeholdTV M6 Extra [5ace:6193]
146145 -> AVerMedia MiniPCI DVB-T Hybrid M103 [1461:f636]
147146 -> ASUSTeK P7131 Analog
diff --git a/Documentation/video4linux/cx18.txt b/Documentation/video4linux/cx18.txt
index 6842c262890f..914cb7e734a2 100644
--- a/Documentation/video4linux/cx18.txt
+++ b/Documentation/video4linux/cx18.txt
@@ -1,36 +1,30 @@
1Some notes regarding the cx18 driver for the Conexant CX23418 MPEG 1Some notes regarding the cx18 driver for the Conexant CX23418 MPEG
2encoder chip: 2encoder chip:
3 3
41) The only hardware currently supported is the Hauppauge HVR-1600 41) Currently supported are:
5 card and the Compro VideoMate H900 (note that this card only
6 supports analog input, it has no digital tuner!).
7 5
82) Some people have problems getting the i2c bus to work. Cause unknown. 6 - Hauppauge HVR-1600
9 The symptom is that the eeprom cannot be read and the card is 7 - Compro VideoMate H900
10 unusable. 8 - Yuan MPC718
9 - Conexant Raptor PAL/SECAM devkit
11 10
123) The audio from the analog tuner is mono only. Probably caused by 112) Some people have problems getting the i2c bus to work.
13 incorrect audio register information in the datasheet. We are 12 The symptom is that the eeprom cannot be read and the card is
14 waiting for updated information from Conexant. 13 unusable. This is probably fixed, but if you have problems
14 then post to the video4linux or ivtv-users mailinglist.
15 15
164) VBI (raw or sliced) has not yet been implemented. 163) VBI (raw or sliced) has not yet been implemented.
17 17
185) MPEG indexing is not yet implemented. 184) MPEG indexing is not yet implemented.
19 19
206) The driver is still a bit rough around the edges, this should 205) The driver is still a bit rough around the edges, this should
21 improve over time. 21 improve over time.
22 22
23 23
24Firmware: 24Firmware:
25 25
26The firmware needs to be extracted from the Windows Hauppauge HVR-1600 26You can obtain the firmware files here:
27driver, available here:
28
29http://hauppauge.lightpath.net/software/install_cd/hauppauge_cd_3.4d1.zip
30 27
31Unzip, then copy the following files to the firmware directory 28http://dl.ivtvdriver.org/ivtv/firmware/cx18-firmware.tar.gz
32and rename them as follows:
33 29
34Drivers/Driver18/hcw18apu.rom -> v4l-cx23418-apu.fw 30Untar and copy the .fw files to your firmware directory.
35Drivers/Driver18/hcw18enc.rom -> v4l-cx23418-cpu.fw
36Drivers/Driver18/hcw18mlC.rom -> v4l-cx23418-dig.fw
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
new file mode 100644
index 000000000000..0c4880af57a3
--- /dev/null
+++ b/Documentation/video4linux/gspca.txt
@@ -0,0 +1,243 @@
1List of the webcams know by gspca.
2
3The modules are:
4 gspca_main main driver
5 gspca_xxxx subdriver module with xxxx as follows
6
7xxxx vend:prod
8----
9spca501 0000:0000 MystFromOri Unknow Camera
10spca501 040a:0002 Kodak DVC-325
11spca500 040a:0300 Kodak EZ200
12zc3xx 041e:041e Creative WebCam Live!
13spca500 041e:400a Creative PC-CAM 300
14sunplus 041e:400b Creative PC-CAM 600
15sunplus 041e:4012 PC-Cam350
16sunplus 041e:4013 Creative Pccam750
17zc3xx 041e:4017 Creative Webcam Mobile PD1090
18spca508 041e:4018 Creative Webcam Vista (PD1100)
19spca561 041e:401a Creative Webcam Vista (PD1100)
20zc3xx 041e:401c Creative NX
21spca505 041e:401d Creative Webcam NX ULTRA
22zc3xx 041e:401e Creative Nx Pro
23zc3xx 041e:401f Creative Webcam Notebook PD1171
24pac207 041e:4028 Creative Webcam Vista Plus
25zc3xx 041e:4029 Creative WebCam Vista Pro
26zc3xx 041e:4034 Creative Instant P0620
27zc3xx 041e:4035 Creative Instant P0620D
28zc3xx 041e:4036 Creative Live !
29zc3xx 041e:403a Creative Nx Pro 2
30spca561 041e:403b Creative Webcam Vista (VF0010)
31zc3xx 041e:4051 Creative Live!Cam Notebook Pro (VF0250)
32ov519 041e:4052 Creative Live! VISTA IM
33zc3xx 041e:4053 Creative Live!Cam Video IM
34ov519 041e:405f Creative Live! VISTA VF0330
35ov519 041e:4060 Creative Live! VISTA VF0350
36ov519 041e:4061 Creative Live! VISTA VF0400
37ov519 041e:4064 Creative Live! VISTA VF0420
38ov519 041e:4068 Creative Live! VISTA VF0470
39spca561 0458:7004 Genius VideoCAM Express V2
40sunplus 0458:7006 Genius Dsc 1.3 Smart
41zc3xx 0458:7007 Genius VideoCam V2
42zc3xx 0458:700c Genius VideoCam V3
43zc3xx 0458:700f Genius VideoCam Web V2
44sonixj 0458:7025 Genius Eye 311Q
45sonixj 045e:00f5 MicroSoft VX3000
46sonixj 045e:00f7 MicroSoft VX1000
47ov519 045e:028c Micro$oft xbox cam
48spca508 0461:0815 Micro Innovation IC200
49sunplus 0461:0821 Fujifilm MV-1
50zc3xx 0461:0a00 MicroInnovation WebCam320
51spca500 046d:0890 Logitech QuickCam traveler
52vc032x 046d:0892 Logitech Orbicam
53vc032x 046d:0896 Logitech Orbicam
54zc3xx 046d:08a0 Logitech QC IM
55zc3xx 046d:08a1 Logitech QC IM 0x08A1 +sound
56zc3xx 046d:08a2 Labtec Webcam Pro
57zc3xx 046d:08a3 Logitech QC Chat
58zc3xx 046d:08a6 Logitech QCim
59zc3xx 046d:08a7 Logitech QuickCam Image
60zc3xx 046d:08a9 Logitech Notebook Deluxe
61zc3xx 046d:08aa Labtec Webcam Notebook
62zc3xx 046d:08ac Logitech QuickCam Cool
63zc3xx 046d:08ad Logitech QCCommunicate STX
64zc3xx 046d:08ae Logitech QuickCam for Notebooks
65zc3xx 046d:08af Logitech QuickCam Cool
66zc3xx 046d:08b9 Logitech QC IM ???
67zc3xx 046d:08d7 Logitech QCam STX
68zc3xx 046d:08d9 Logitech QuickCam IM/Connect
69zc3xx 046d:08d8 Logitech Notebook Deluxe
70zc3xx 046d:08da Logitech QuickCam Messenger
71zc3xx 046d:08dd Logitech QuickCam for Notebooks
72spca500 046d:0900 Logitech Inc. ClickSmart 310
73spca500 046d:0901 Logitech Inc. ClickSmart 510
74sunplus 046d:0905 Logitech ClickSmart 820
75tv8532 046d:0920 QC Express
76tv8532 046d:0921 Labtec Webcam
77spca561 046d:0928 Logitech QC Express Etch2
78spca561 046d:0929 Labtec Webcam Elch2
79spca561 046d:092a Logitech QC for Notebook
80spca561 046d:092b Labtec Webcam Plus
81spca561 046d:092c Logitech QC chat Elch2
82spca561 046d:092d Logitech QC Elch2
83spca561 046d:092e Logitech QC Elch2
84spca561 046d:092f Logitech QC Elch2
85sunplus 046d:0960 Logitech ClickSmart 420
86sunplus 0471:0322 Philips DMVC1300K
87zc3xx 0471:0325 Philips SPC 200 NC
88zc3xx 0471:0326 Philips SPC 300 NC
89sonixj 0471:0327 Philips SPC 600 NC
90sonixj 0471:0328 Philips SPC 700 NC
91zc3xx 0471:032d Philips spc210nc
92zc3xx 0471:032e Philips spc315nc
93sonixj 0471:0330 Philips SPC 710NC
94spca501 0497:c001 Smile International
95sunplus 04a5:3003 Benq DC 1300
96sunplus 04a5:3008 Benq DC 1500
97sunplus 04a5:300a Benq DC3410
98spca500 04a5:300c Benq DC1016
99sunplus 04f1:1001 JVC GC A50
100spca561 04fc:0561 Flexcam 100
101sunplus 04fc:500c Sunplus CA500C
102sunplus 04fc:504a Aiptek Mini PenCam 1.3
103sunplus 04fc:504b Maxell MaxPocket LE 1.3
104sunplus 04fc:5330 Digitrex 2110
105sunplus 04fc:5360 Sunplus Generic
106spca500 04fc:7333 PalmPixDC85
107sunplus 04fc:ffff Pure DigitalDakota
108spca501 0506:00df 3Com HomeConnect Lite
109sunplus 052b:1513 Megapix V4
110tv8532 0545:808b Veo Stingray
111tv8532 0545:8333 Veo Stingray
112sunplus 0546:3155 Polaroid PDC3070
113sunplus 0546:3191 Polaroid Ion 80
114sunplus 0546:3273 Polaroid PDC2030
115ov519 054c:0154 Sonny toy4
116ov519 054c:0155 Sonny toy5
117zc3xx 055f:c005 Mustek Wcam300A
118spca500 055f:c200 Mustek Gsmart 300
119sunplus 055f:c211 Kowa Bs888e Microcamera
120spca500 055f:c220 Gsmart Mini
121sunplus 055f:c230 Mustek Digicam 330K
122sunplus 055f:c232 Mustek MDC3500
123sunplus 055f:c360 Mustek DV4000 Mpeg4
124sunplus 055f:c420 Mustek gSmart Mini 2
125sunplus 055f:c430 Mustek Gsmart LCD 2
126sunplus 055f:c440 Mustek DV 3000
127sunplus 055f:c520 Mustek gSmart Mini 3
128sunplus 055f:c530 Mustek Gsmart LCD 3
129sunplus 055f:c540 Gsmart D30
130sunplus 055f:c630 Mustek MDC4000
131sunplus 055f:c650 Mustek MDC5500Z
132zc3xx 055f:d003 Mustek WCam300A
133zc3xx 055f:d004 Mustek WCam300 AN
134conex 0572:0041 Creative Notebook cx11646
135ov519 05a9:0519 OmniVision
136ov519 05a9:0530 OmniVision
137ov519 05a9:4519 OmniVision
138ov519 05a9:8519 OmniVision
139sunplus 05da:1018 Digital Dream Enigma 1.3
140stk014 05e1:0893 Syntek DV4000
141spca561 060b:a001 Maxell Compact Pc PM3
142zc3xx 0698:2003 CTX M730V built in
143spca500 06bd:0404 Agfa CL20
144spca500 06be:0800 Optimedia
145sunplus 06d6:0031 Trust 610 LCD PowerC@m Zoom
146spca506 06e1:a190 ADS Instant VCD
147spca508 0733:0110 ViewQuest VQ110
148spca508 0130:0130 Clone Digital Webcam 11043
149spca501 0733:0401 Intel Create and Share
150spca501 0733:0402 ViewQuest M318B
151spca505 0733:0430 Intel PC Camera Pro
152sunplus 0733:1311 Digital Dream Epsilon 1.3
153sunplus 0733:1314 Mercury 2.1MEG Deluxe Classic Cam
154sunplus 0733:2211 Jenoptik jdc 21 LCD
155sunplus 0733:2221 Mercury Digital Pro 3.1p
156sunplus 0733:3261 Concord 3045 spca536a
157sunplus 0733:3281 Cyberpix S550V
158spca506 0734:043b 3DeMon USB Capture aka
159spca500 084d:0003 D-Link DSC-350
160spca500 08ca:0103 Aiptek PocketDV
161sunplus 08ca:0104 Aiptek PocketDVII 1.3
162sunplus 08ca:0106 Aiptek Pocket DV3100+
163sunplus 08ca:2008 Aiptek Mini PenCam 2 M
164sunplus 08ca:2010 Aiptek PocketCam 3M
165sunplus 08ca:2016 Aiptek PocketCam 2 Mega
166sunplus 08ca:2018 Aiptek Pencam SD 2M
167sunplus 08ca:2020 Aiptek Slim 3000F
168sunplus 08ca:2022 Aiptek Slim 3200
169sunplus 08ca:2024 Aiptek DV3500 Mpeg4
170sunplus 08ca:2028 Aiptek PocketCam4M
171sunplus 08ca:2040 Aiptek PocketDV4100M
172sunplus 08ca:2042 Aiptek PocketDV5100
173sunplus 08ca:2050 Medion MD 41437
174sunplus 08ca:2060 Aiptek PocketDV5300
175tv8532 0923:010f ICM532 cams
176mars 093a:050f Mars-Semi Pc-Camera
177pac207 093a:2460 PAC207 Qtec Webcam 100
178pac207 093a:2463 Philips spc200nc pac207
179pac207 093a:2464 Labtec Webcam 1200
180pac207 093a:2468 PAC207
181pac207 093a:2470 Genius GF112
182pac207 093a:2471 PAC207 Genius VideoCam ge111
183pac207 093a:2472 PAC207 Genius VideoCam ge110
184pac7311 093a:2600 PAC7311 Typhoon
185pac7311 093a:2601 PAC7311 Phillips SPC610NC
186pac7311 093a:2603 PAC7312
187pac7311 093a:2608 PAC7311 Trust WB-3300p
188pac7311 093a:260e PAC7311 Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
189pac7311 093a:260f PAC7311 SnakeCam
190pac7311 093a:2621 PAC731x
191zc3xx 0ac8:0302 Z-star Vimicro zc0302
192vc032x 0ac8:0321 Vimicro generic vc0321
193vc032x 0ac8:0323 Vimicro Vc0323
194vc032x 0ac8:0328 A4Tech PK-130MG
195zc3xx 0ac8:301b Z-Star zc301b
196zc3xx 0ac8:303b Vimicro 0x303b
197zc3xx 0ac8:305b Z-star Vimicro zc0305b
198zc3xx 0ac8:307b Ldlc VC302+Ov7620
199vc032x 0ac8:c001 Sony embedded vimicro
200vc032x 0ac8:c002 Sony embedded vimicro
201spca508 0af9:0010 Hama USB Sightcam 100
202spca508 0af9:0011 Hama USB Sightcam 100
203sonixb 0c45:6001 Genius VideoCAM NB
204sonixb 0c45:6005 Microdia Sweex Mini Webcam
205sonixb 0c45:6007 Sonix sn9c101 + Tas5110D
206sonixb 0c45:6009 spcaCam@120
207sonixb 0c45:600d spcaCam@120
208sonixb 0c45:6011 Microdia PC Camera (SN9C102)
209sonixb 0c45:6019 Generic Sonix OV7630
210sonixb 0c45:6024 Generic Sonix Tas5130c
211sonixb 0c45:6025 Xcam Shanga
212sonixb 0c45:6028 Sonix Btc Pc380
213sonixb 0c45:6029 spcaCam@150
214sonixb 0c45:602c Generic Sonix OV7630
215sonixb 0c45:602d LIC-200 LG
216sonixb 0c45:602e Genius VideoCam Messenger
217sonixj 0c45:6040 Speed NVC 350K
218sonixj 0c45:607c Sonix sn9c102p Hv7131R
219sonixj 0c45:60c0 Sangha Sn535
220sonixj 0c45:60ec SN9C105+MO4000
221sonixj 0c45:60fb Surfer NoName
222sonixj 0c45:60fc LG-LIC300
223sonixj 0c45:612a Avant Camera
224sonixj 0c45:612c Typhoon Rasy Cam 1.3MPix
225sonixj 0c45:6130 Sonix Pccam
226sonixj 0c45:6138 Sn9c120 Mo4000
227sonixj 0c45:613b Surfer SN-206
228sonixj 0c45:613c Sonix Pccam168
229sunplus 0d64:0303 Sunplus FashionCam DXG
230etoms 102c:6151 Qcam Sangha CIF
231etoms 102c:6251 Qcam xxxxxx VGA
232zc3xx 10fd:0128 Typhoon Webshot II USB 300k 0x0128
233spca561 10fd:7e50 FlyCam Usb 100
234zc3xx 10fd:8050 Typhoon Webshot II USB 300k
235spca501 1776:501c Arowana 300K CMOS Camera
236t613 17a1:0128 T613/TAS5130A
237vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC
238pac207 2001:f115 D-Link DSB-C120
239spca500 2899:012c Toptro Industrial
240spca508 8086:0110 Intel Easy PC Camera
241spca500 8086:0630 Intel Pocket PC Camera
242spca506 99fa:8988 Grandtec V.cap
243spca561 abcd:cdee Petcam
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 7a7803b5d497..93ea201f426c 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -38,7 +38,6 @@ config VIDEO_ALLOW_V4L1
38 bool "Enable Video For Linux API 1 (DEPRECATED)" 38 bool "Enable Video For Linux API 1 (DEPRECATED)"
39 depends on VIDEO_DEV && VIDEO_V4L2_COMMON 39 depends on VIDEO_DEV && VIDEO_V4L2_COMMON
40 default VIDEO_DEV && VIDEO_V4L2_COMMON 40 default VIDEO_DEV && VIDEO_V4L2_COMMON
41 select VIDEO_V4L1_COMPAT
42 ---help--- 41 ---help---
43 Enables drivers based on the legacy V4L1 API. 42 Enables drivers based on the legacy V4L1 API.
44 43
@@ -49,9 +48,9 @@ config VIDEO_ALLOW_V4L1
49 If you are unsure as to whether this is required, answer Y. 48 If you are unsure as to whether this is required, answer Y.
50 49
51config VIDEO_V4L1_COMPAT 50config VIDEO_V4L1_COMPAT
52 bool "Enable Video For Linux API 1 compatible Layer" 51 bool "Enable Video For Linux API 1 compatible Layer" if !VIDEO_ALLOW_V4L1
53 depends on VIDEO_DEV 52 depends on VIDEO_DEV
54 default VIDEO_DEV 53 default y
55 ---help--- 54 ---help---
56 Enables a compatibility API used by most V4L2 devices to allow 55 Enables a compatibility API used by most V4L2 devices to allow
57 its usage with legacy applications that supports only V4L1 api. 56 its usage with legacy applications that supports only V4L1 api.
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
index 266505207925..16792a68a449 100644
--- a/drivers/media/common/ir-functions.c
+++ b/drivers/media/common/ir-functions.c
@@ -66,7 +66,6 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
66 if (ir_codes) 66 if (ir_codes)
67 memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes)); 67 memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes));
68 68
69
70 dev->keycode = ir->ir_codes; 69 dev->keycode = ir->ir_codes;
71 dev->keycodesize = sizeof(IR_KEYTAB_TYPE); 70 dev->keycodesize = sizeof(IR_KEYTAB_TYPE);
72 dev->keycodemax = IR_KEYTAB_SIZE; 71 dev->keycodemax = IR_KEYTAB_SIZE;
@@ -78,6 +77,7 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
78 if (repeat) 77 if (repeat)
79 set_bit(EV_REP, dev->evbit); 78 set_bit(EV_REP, dev->evbit);
80} 79}
80EXPORT_SYMBOL_GPL(ir_input_init);
81 81
82void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir) 82void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
83{ 83{
@@ -86,6 +86,7 @@ void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
86 ir_input_key_event(dev,ir); 86 ir_input_key_event(dev,ir);
87 } 87 }
88} 88}
89EXPORT_SYMBOL_GPL(ir_input_nokey);
89 90
90void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir, 91void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
91 u32 ir_key, u32 ir_raw) 92 u32 ir_key, u32 ir_raw)
@@ -104,6 +105,7 @@ void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
104 ir_input_key_event(dev,ir); 105 ir_input_key_event(dev,ir);
105 } 106 }
106} 107}
108EXPORT_SYMBOL_GPL(ir_input_keydown);
107 109
108/* -------------------------------------------------------------------------- */ 110/* -------------------------------------------------------------------------- */
109/* extract mask bits out of data and pack them into the result */ 111/* extract mask bits out of data and pack them into the result */
@@ -122,6 +124,7 @@ u32 ir_extract_bits(u32 data, u32 mask)
122 124
123 return value; 125 return value;
124} 126}
127EXPORT_SYMBOL_GPL(ir_extract_bits);
125 128
126static int inline getbit(u32 *samples, int bit) 129static int inline getbit(u32 *samples, int bit)
127{ 130{
@@ -146,6 +149,7 @@ int ir_dump_samples(u32 *samples, int count)
146 printk("\n"); 149 printk("\n");
147 return 0; 150 return 0;
148} 151}
152EXPORT_SYMBOL_GPL(ir_dump_samples);
149 153
150/* decode raw samples, pulse distance coding used by NEC remotes */ 154/* decode raw samples, pulse distance coding used by NEC remotes */
151int ir_decode_pulsedistance(u32 *samples, int count, int low, int high) 155int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
@@ -212,6 +216,7 @@ int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
212 216
213 return value; 217 return value;
214} 218}
219EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
215 220
216/* decode raw samples, biphase coding, used by rc5 for example */ 221/* decode raw samples, biphase coding, used by rc5 for example */
217int ir_decode_biphase(u32 *samples, int count, int low, int high) 222int ir_decode_biphase(u32 *samples, int count, int low, int high)
@@ -253,6 +258,7 @@ int ir_decode_biphase(u32 *samples, int count, int low, int high)
253 } 258 }
254 return value; 259 return value;
255} 260}
261EXPORT_SYMBOL_GPL(ir_decode_biphase);
256 262
257/* RC5 decoding stuff, moved from bttv-input.c to share it with 263/* RC5 decoding stuff, moved from bttv-input.c to share it with
258 * saa7134 */ 264 * saa7134 */
@@ -353,6 +359,7 @@ void ir_rc5_timer_end(unsigned long data)
353 } 359 }
354 } 360 }
355} 361}
362EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
356 363
357void ir_rc5_timer_keyup(unsigned long data) 364void ir_rc5_timer_keyup(unsigned long data)
358{ 365{
@@ -361,21 +368,4 @@ void ir_rc5_timer_keyup(unsigned long data)
361 dprintk(1, "ir-common: key released\n"); 368 dprintk(1, "ir-common: key released\n");
362 ir_input_nokey(ir->dev, &ir->ir); 369 ir_input_nokey(ir->dev, &ir->ir);
363} 370}
364
365EXPORT_SYMBOL_GPL(ir_input_init);
366EXPORT_SYMBOL_GPL(ir_input_nokey);
367EXPORT_SYMBOL_GPL(ir_input_keydown);
368
369EXPORT_SYMBOL_GPL(ir_extract_bits);
370EXPORT_SYMBOL_GPL(ir_dump_samples);
371EXPORT_SYMBOL_GPL(ir_decode_biphase);
372EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
373
374EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
375EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup); 371EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
376
377/*
378 * Local variables:
379 * c-basic-offset: 8
380 * End:
381 */
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 89c7660b85d6..d01965e96927 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -233,7 +233,7 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
233 233
234int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt) 234int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
235{ 235{
236 u32 *cpu; 236 __le32 *cpu;
237 dma_addr_t dma_addr; 237 dma_addr_t dma_addr;
238 238
239 cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr); 239 cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr);
@@ -250,7 +250,7 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
250int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, 250int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
251 struct scatterlist *list, int sglen ) 251 struct scatterlist *list, int sglen )
252{ 252{
253 u32 *ptr, fill; 253 __le32 *ptr, fill;
254 int nr_pages = 0; 254 int nr_pages = 0;
255 int i,p; 255 int i,p;
256 256
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
index 9c905399a233..05bde9ccb770 100644
--- a/drivers/media/common/saa7146_hlp.c
+++ b/drivers/media/common/saa7146_hlp.c
@@ -338,7 +338,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
338 struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field) 338 struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field)
339{ 339{
340 struct saa7146_vv *vv = dev->vv_data; 340 struct saa7146_vv *vv = dev->vv_data;
341 u32 *clipping = vv->d_clipping.cpu_addr; 341 __le32 *clipping = vv->d_clipping.cpu_addr;
342 342
343 int width = fh->ov.win.w.width; 343 int width = fh->ov.win.w.width;
344 int height = fh->ov.win.w.height; 344 int height = fh->ov.win.w.height;
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index 35b01ec40a51..c11da4d09cd0 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -24,7 +24,7 @@ static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
24 sent through the saa7146. have a look at the specifications p. 122 ff 24 sent through the saa7146. have a look at the specifications p. 122 ff
25 to understand this. it returns the number of u32s to send, or -1 25 to understand this. it returns the number of u32s to send, or -1
26 in case of an error. */ 26 in case of an error. */
27static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op) 27static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, __le32 *op)
28{ 28{
29 int h1, h2; 29 int h1, h2;
30 int i, j, addr; 30 int i, j, addr;
@@ -47,7 +47,7 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
47 } 47 }
48 48
49 /* be careful: clear out the i2c-mem first */ 49 /* be careful: clear out the i2c-mem first */
50 memset(op,0,sizeof(u32)*mem); 50 memset(op,0,sizeof(__le32)*mem);
51 51
52 /* loop through all messages */ 52 /* loop through all messages */
53 for(i = 0; i < num; i++) { 53 for(i = 0; i < num; i++) {
@@ -57,16 +57,16 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
57 so we have to perform a translation */ 57 so we have to perform a translation */
58 addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0); 58 addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0);
59 h1 = op_count/3; h2 = op_count%3; 59 h1 = op_count/3; h2 = op_count%3;
60 op[h1] |= ( (u8)addr << ((3-h2)*8)); 60 op[h1] |= cpu_to_le32( (u8)addr << ((3-h2)*8));
61 op[h1] |= (SAA7146_I2C_START << ((3-h2)*2)); 61 op[h1] |= cpu_to_le32(SAA7146_I2C_START << ((3-h2)*2));
62 op_count++; 62 op_count++;
63 63
64 /* loop through all bytes of message i */ 64 /* loop through all bytes of message i */
65 for(j = 0; j < m[i].len; j++) { 65 for(j = 0; j < m[i].len; j++) {
66 /* insert the data bytes */ 66 /* insert the data bytes */
67 h1 = op_count/3; h2 = op_count%3; 67 h1 = op_count/3; h2 = op_count%3;
68 op[h1] |= ( (u32)((u8)m[i].buf[j]) << ((3-h2)*8)); 68 op[h1] |= cpu_to_le32( (u32)((u8)m[i].buf[j]) << ((3-h2)*8));
69 op[h1] |= ( SAA7146_I2C_CONT << ((3-h2)*2)); 69 op[h1] |= cpu_to_le32( SAA7146_I2C_CONT << ((3-h2)*2));
70 op_count++; 70 op_count++;
71 } 71 }
72 72
@@ -75,9 +75,9 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
75 /* have a look at the last byte inserted: 75 /* have a look at the last byte inserted:
76 if it was: ...CONT change it to ...STOP */ 76 if it was: ...CONT change it to ...STOP */
77 h1 = (op_count-1)/3; h2 = (op_count-1)%3; 77 h1 = (op_count-1)/3; h2 = (op_count-1)%3;
78 if ( SAA7146_I2C_CONT == (0x3 & (op[h1] >> ((3-h2)*2))) ) { 78 if ( SAA7146_I2C_CONT == (0x3 & (le32_to_cpu(op[h1]) >> ((3-h2)*2))) ) {
79 op[h1] &= ~(0x2 << ((3-h2)*2)); 79 op[h1] &= ~cpu_to_le32(0x2 << ((3-h2)*2));
80 op[h1] |= (SAA7146_I2C_STOP << ((3-h2)*2)); 80 op[h1] |= cpu_to_le32(SAA7146_I2C_STOP << ((3-h2)*2));
81 } 81 }
82 82
83 /* return the number of u32s to send */ 83 /* return the number of u32s to send */
@@ -88,7 +88,7 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
88 which bytes were read through the adapter and write them back to the corresponding 88 which bytes were read through the adapter and write them back to the corresponding
89 i2c-message. but instead, we simply write back all bytes. 89 i2c-message. but instead, we simply write back all bytes.
90 fixme: this could be improved. */ 90 fixme: this could be improved. */
91static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op) 91static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, __le32 *op)
92{ 92{
93 int i, j; 93 int i, j;
94 int op_count = 0; 94 int op_count = 0;
@@ -101,7 +101,7 @@ static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op)
101 /* loop throgh all bytes of message i */ 101 /* loop throgh all bytes of message i */
102 for(j = 0; j < m[i].len; j++) { 102 for(j = 0; j < m[i].len; j++) {
103 /* write back all bytes that could have been read */ 103 /* write back all bytes that could have been read */
104 m[i].buf[j] = (op[op_count/3] >> ((3-(op_count%3))*8)); 104 m[i].buf[j] = (le32_to_cpu(op[op_count/3]) >> ((3-(op_count%3))*8));
105 op_count++; 105 op_count++;
106 } 106 }
107 } 107 }
@@ -174,7 +174,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
174/* this functions writes out the data-byte 'dword' to the i2c-device. 174/* this functions writes out the data-byte 'dword' to the i2c-device.
175 it returns 0 if ok, -1 if the transfer failed, -2 if the transfer 175 it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
176 failed badly (e.g. address error) */ 176 failed badly (e.g. address error) */
177static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_delay) 177static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int short_delay)
178{ 178{
179 u32 status = 0, mc2 = 0; 179 u32 status = 0, mc2 = 0;
180 int trial = 0; 180 int trial = 0;
@@ -186,7 +186,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
186 if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) { 186 if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
187 187
188 saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); 188 saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
189 saa7146_write(dev, I2C_TRANSFER, *dword); 189 saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword));
190 190
191 dev->i2c_op = 1; 191 dev->i2c_op = 1;
192 SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17); 192 SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
@@ -209,7 +209,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
209 status = saa7146_read(dev, I2C_STATUS); 209 status = saa7146_read(dev, I2C_STATUS);
210 } else { 210 } else {
211 saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); 211 saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
212 saa7146_write(dev, I2C_TRANSFER, *dword); 212 saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword));
213 saa7146_write(dev, MC2, (MASK_00 | MASK_16)); 213 saa7146_write(dev, MC2, (MASK_00 | MASK_16));
214 214
215 /* do not poll for i2c-status before upload is complete */ 215 /* do not poll for i2c-status before upload is complete */
@@ -282,7 +282,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
282 } 282 }
283 283
284 /* read back data, just in case we were reading ... */ 284 /* read back data, just in case we were reading ... */
285 *dword = saa7146_read(dev, I2C_TRANSFER); 285 *dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER));
286 286
287 DEB_I2C(("after: 0x%08x\n",*dword)); 287 DEB_I2C(("after: 0x%08x\n",*dword));
288 return 0; 288 return 0;
@@ -291,7 +291,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
291static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries) 291static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
292{ 292{
293 int i = 0, count = 0; 293 int i = 0, count = 0;
294 u32* buffer = dev->d_i2c.cpu_addr; 294 __le32 *buffer = dev->d_i2c.cpu_addr;
295 int err = 0; 295 int err = 0;
296 int address_err = 0; 296 int address_err = 0;
297 int short_delay = 0; 297 int short_delay = 0;
@@ -376,7 +376,7 @@ out:
376 /* another bug in revision 0: the i2c-registers get uploaded randomly by other 376 /* another bug in revision 0: the i2c-registers get uploaded randomly by other
377 uploads, so we better clear them out before continueing */ 377 uploads, so we better clear them out before continueing */
378 if( 0 == dev->revision ) { 378 if( 0 == dev->revision ) {
379 u32 zero = 0; 379 __le32 zero = 0;
380 saa7146_i2c_reset(dev); 380 saa7146_i2c_reset(dev);
381 if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) { 381 if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
382 INFO(("revision 0 error. this should never happen.\n")); 382 INFO(("revision 0 error. this should never happen.\n"));
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 3cbc6ebbe649..a5e62750eea3 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -605,8 +605,8 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
605 struct saa7146_pgtable *pt1 = &buf->pt[0]; 605 struct saa7146_pgtable *pt1 = &buf->pt[0];
606 struct saa7146_pgtable *pt2 = &buf->pt[1]; 606 struct saa7146_pgtable *pt2 = &buf->pt[1];
607 struct saa7146_pgtable *pt3 = &buf->pt[2]; 607 struct saa7146_pgtable *pt3 = &buf->pt[2];
608 u32 *ptr1, *ptr2, *ptr3; 608 __le32 *ptr1, *ptr2, *ptr3;
609 u32 fill; 609 __le32 fill;
610 610
611 int size = buf->fmt->width*buf->fmt->height; 611 int size = buf->fmt->width*buf->fmt->height;
612 int i,p,m1,m2,m3,o1,o2; 612 int i,p,m1,m2,m3,o1,o2;
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
index 85482960d012..850d5689b14d 100644
--- a/drivers/media/common/tuners/Kconfig
+++ b/drivers/media/common/tuners/Kconfig
@@ -34,6 +34,7 @@ config MEDIA_TUNER
34menuconfig MEDIA_TUNER_CUSTOMIZE 34menuconfig MEDIA_TUNER_CUSTOMIZE
35 bool "Customize analog and hybrid tuner modules to build" 35 bool "Customize analog and hybrid tuner modules to build"
36 depends on MEDIA_TUNER 36 depends on MEDIA_TUNER
37 default n
37 help 38 help
38 This allows the user to deselect tuner drivers unnecessary 39 This allows the user to deselect tuner drivers unnecessary
39 for their hardware from the build. Use this option with care 40 for their hardware from the build. Use this option with care
diff --git a/drivers/media/common/tuners/tda18271-maps.c b/drivers/media/common/tuners/tda18271-maps.c
index 83e7561960c1..ab14ceb9e0ce 100644
--- a/drivers/media/common/tuners/tda18271-maps.c
+++ b/drivers/media/common/tuners/tda18271-maps.c
@@ -1,5 +1,5 @@
1/* 1/*
2 tda18271-tables.c - driver for the Philips / NXP TDA18271 silicon tuner 2 tda18271-maps.c - driver for the Philips / NXP TDA18271 silicon tuner
3 3
4 Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org> 4 Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
5 5
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
index 30eb07b7f9ef..4dd1d2421cc5 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -15,6 +15,7 @@
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <media/tuner.h> 16#include <media/tuner.h>
17#include <linux/mutex.h> 17#include <linux/mutex.h>
18#include <asm/unaligned.h>
18#include "tuner-i2c.h" 19#include "tuner-i2c.h"
19#include "tuner-xc2028.h" 20#include "tuner-xc2028.h"
20#include "tuner-xc2028-types.h" 21#include "tuner-xc2028-types.h"
@@ -292,10 +293,10 @@ static int load_all_firmwares(struct dvb_frontend *fe)
292 name[sizeof(name) - 1] = 0; 293 name[sizeof(name) - 1] = 0;
293 p += sizeof(name) - 1; 294 p += sizeof(name) - 1;
294 295
295 priv->firm_version = le16_to_cpu(*(__u16 *) p); 296 priv->firm_version = get_unaligned_le16(p);
296 p += 2; 297 p += 2;
297 298
298 n_array = le16_to_cpu(*(__u16 *) p); 299 n_array = get_unaligned_le16(p);
299 p += 2; 300 p += 2;
300 301
301 tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n", 302 tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
@@ -324,26 +325,26 @@ static int load_all_firmwares(struct dvb_frontend *fe)
324 } 325 }
325 326
326 /* Checks if there's enough bytes to read */ 327 /* Checks if there's enough bytes to read */
327 if (p + sizeof(type) + sizeof(id) + sizeof(size) > endp) { 328 if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
328 tuner_err("Firmware header is incomplete!\n"); 329 goto header;
329 goto corrupt;
330 }
331 330
332 type = le32_to_cpu(*(__u32 *) p); 331 type = get_unaligned_le32(p);
333 p += sizeof(type); 332 p += sizeof(type);
334 333
335 id = le64_to_cpu(*(v4l2_std_id *) p); 334 id = get_unaligned_le64(p);
336 p += sizeof(id); 335 p += sizeof(id);
337 336
338 if (type & HAS_IF) { 337 if (type & HAS_IF) {
339 int_freq = le16_to_cpu(*(__u16 *) p); 338 int_freq = get_unaligned_le16(p);
340 p += sizeof(int_freq); 339 p += sizeof(int_freq);
340 if (endp - p < sizeof(size))
341 goto header;
341 } 342 }
342 343
343 size = le32_to_cpu(*(__u32 *) p); 344 size = get_unaligned_le32(p);
344 p += sizeof(size); 345 p += sizeof(size);
345 346
346 if ((!size) || (size + p > endp)) { 347 if (!size || size > endp - p) {
347 tuner_err("Firmware type "); 348 tuner_err("Firmware type ");
348 dump_firm_type(type); 349 dump_firm_type(type);
349 printk("(%x), id %llx is corrupted " 350 printk("(%x), id %llx is corrupted "
@@ -382,6 +383,8 @@ static int load_all_firmwares(struct dvb_frontend *fe)
382 383
383 goto done; 384 goto done;
384 385
386header:
387 tuner_err("Firmware header is incomplete!\n");
385corrupt: 388corrupt:
386 rc = -EINVAL; 389 rc = -EINVAL;
387 tuner_err("Error: firmware file is corrupted!\n"); 390 tuner_err("Error: firmware file is corrupted!\n");
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index 4878d6477a8c..5f99de0ad612 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -36,6 +36,10 @@ static int debug;
36module_param(debug, int, 0644); 36module_param(debug, int, 0644);
37MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); 37MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
38 38
39static int xc5000_load_fw_on_attach;
40module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644);
41MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
42
39#define dprintk(level,fmt, arg...) if (debug >= level) \ 43#define dprintk(level,fmt, arg...) if (debug >= level) \
40 printk(KERN_INFO "%s: " fmt, "xc5000", ## arg) 44 printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
41 45
@@ -972,6 +976,9 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
972 976
973 fe->tuner_priv = priv; 977 fe->tuner_priv = priv;
974 978
979 if (xc5000_load_fw_on_attach)
980 xc5000_init(fe);
981
975 return fe; 982 return fe;
976} 983}
977EXPORT_SYMBOL(xc5000_attach); 984EXPORT_SYMBOL(xc5000_attach);
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 7b21b49f1945..8bc1445bd33b 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -21,6 +21,7 @@ source "drivers/media/dvb/dvb-usb/Kconfig"
21source "drivers/media/dvb/ttusb-budget/Kconfig" 21source "drivers/media/dvb/ttusb-budget/Kconfig"
22source "drivers/media/dvb/ttusb-dec/Kconfig" 22source "drivers/media/dvb/ttusb-dec/Kconfig"
23source "drivers/media/dvb/cinergyT2/Kconfig" 23source "drivers/media/dvb/cinergyT2/Kconfig"
24source "drivers/media/dvb/siano/Kconfig"
24 25
25comment "Supported FlexCopII (B2C2) Adapters" 26comment "Supported FlexCopII (B2C2) Adapters"
26 depends on DVB_CORE && (PCI || USB) && I2C 27 depends on DVB_CORE && (PCI || USB) && I2C
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index a7ad0841e6fc..d6ba4d195201 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -2,4 +2,4 @@
2# Makefile for the kernel multimedia device drivers. 2# Makefile for the kernel multimedia device drivers.
3# 3#
4 4
5obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ 5obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
index 375fd2892a11..d19b59299d78 100644
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ b/drivers/media/dvb/bt8xx/bt878.h
@@ -128,7 +128,7 @@ struct bt878 {
128 dma_addr_t buf_dma; 128 dma_addr_t buf_dma;
129 129
130 u32 risc_size; 130 u32 risc_size;
131 u32 *risc_cpu; 131 __le32 *risc_cpu;
132 dma_addr_t risc_dma; 132 dma_addr_t risc_dma;
133 u32 risc_pos; 133 u32 risc_pos;
134 134
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index b0d347daae47..eb91fd808c16 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -247,7 +247,7 @@ struct dmx_demux {
247 void* priv; /* Pointer to private data of the API client */ 247 void* priv; /* Pointer to private data of the API client */
248 int (*open) (struct dmx_demux* demux); 248 int (*open) (struct dmx_demux* demux);
249 int (*close) (struct dmx_demux* demux); 249 int (*close) (struct dmx_demux* demux);
250 int (*write) (struct dmx_demux* demux, const char* buf, size_t count); 250 int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
251 int (*allocate_ts_feed) (struct dmx_demux* demux, 251 int (*allocate_ts_feed) (struct dmx_demux* demux,
252 struct dmx_ts_feed** feed, 252 struct dmx_ts_feed** feed,
253 dmx_ts_cb callback); 253 dmx_ts_cb callback);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index df5bef6a2517..1cf9fcb6f514 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -96,7 +96,7 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
96 if (avail > todo) 96 if (avail > todo)
97 avail = todo; 97 avail = todo;
98 98
99 ret = dvb_ringbuffer_read(src, (u8 *)buf, avail, 1); 99 ret = dvb_ringbuffer_read_user(src, buf, avail);
100 if (ret < 0) 100 if (ret < 0)
101 break; 101 break;
102 102
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 588fbe105c27..8e5dd7b1f034 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1357,7 +1357,7 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca,
1357 1357
1358 idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen); 1358 idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
1359 while (idx != -1) { 1359 while (idx != -1) {
1360 dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0); 1360 dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
1361 if (connection_id == -1) 1361 if (connection_id == -1)
1362 connection_id = hdr[0]; 1362 connection_id = hdr[0];
1363 if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) { 1363 if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) {
@@ -1438,7 +1438,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
1438 goto exit; 1438 goto exit;
1439 } 1439 }
1440 1440
1441 dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0); 1441 dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
1442 if (connection_id == -1) 1442 if (connection_id == -1)
1443 connection_id = hdr[0]; 1443 connection_id = hdr[0];
1444 if (hdr[0] == connection_id) { 1444 if (hdr[0] == connection_id) {
@@ -1449,8 +1449,8 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
1449 fraglen -= 2; 1449 fraglen -= 2;
1450 } 1450 }
1451 1451
1452 if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2, 1452 if ((status = dvb_ringbuffer_pkt_read_user(&ca->slot_info[slot].rx_buffer, idx, 2,
1453 (u8 *)buf + pktlen, fraglen, 1)) < 0) { 1453 buf + pktlen, fraglen)) < 0) {
1454 goto exit; 1454 goto exit;
1455 } 1455 }
1456 pktlen += fraglen; 1456 pktlen += fraglen;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 934e15fffc56..e2eca0b1fe7c 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1056,16 +1056,27 @@ static int dvbdmx_close(struct dmx_demux *demux)
1056 return 0; 1056 return 0;
1057} 1057}
1058 1058
1059static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count) 1059static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t count)
1060{ 1060{
1061 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux; 1061 struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
1062 void *p;
1062 1063
1063 if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE)) 1064 if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
1064 return -EINVAL; 1065 return -EINVAL;
1065 1066
1066 if (mutex_lock_interruptible(&dvbdemux->mutex)) 1067 p = kmalloc(count, GFP_USER);
1068 if (!p)
1069 return -ENOMEM;
1070 if (copy_from_user(p, buf, count)) {
1071 kfree(p);
1072 return -EFAULT;
1073 }
1074 if (mutex_lock_interruptible(&dvbdemux->mutex)) {
1075 kfree(p);
1067 return -ERESTARTSYS; 1076 return -ERESTARTSYS;
1068 dvb_dmx_swfilter(dvbdemux, (u8 *)buf, count); 1077 }
1078 dvb_dmx_swfilter(dvbdemux, p, count);
1079 kfree(p);
1069 mutex_unlock(&dvbdemux->mutex); 1080 mutex_unlock(&dvbdemux->mutex);
1070 1081
1071 if (signal_pending(current)) 1082 if (signal_pending(current))
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index c2c033722a93..c93019ca519e 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -606,7 +606,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
606 if (priv->ule_dbit) { 606 if (priv->ule_dbit) {
607 /* Set D-bit for CRC32 verification, 607 /* Set D-bit for CRC32 verification,
608 * if it was set originally. */ 608 * if it was set originally. */
609 ulen |= 0x0080; 609 ulen |= htons(0x8000);
610 } 610 }
611 611
612 ule_crc = iov_crc32(ule_crc, iov, 3); 612 ule_crc = iov_crc32(ule_crc, iov, 3);
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index 872985b7912d..584bbd194dc8 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -107,35 +107,43 @@ void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
107 wake_up(&rbuf->queue); 107 wake_up(&rbuf->queue);
108} 108}
109 109
110 110ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len)
111
112ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, int usermem)
113{ 111{
114 size_t todo = len; 112 size_t todo = len;
115 size_t split; 113 size_t split;
116 114
117 split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; 115 split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
118 if (split > 0) { 116 if (split > 0) {
119 if (!usermem) 117 if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
120 memcpy(buf, rbuf->data+rbuf->pread, split); 118 return -EFAULT;
121 else
122 if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
123 return -EFAULT;
124 buf += split; 119 buf += split;
125 todo -= split; 120 todo -= split;
126 rbuf->pread = 0; 121 rbuf->pread = 0;
127 } 122 }
128 if (!usermem) 123 if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
129 memcpy(buf, rbuf->data+rbuf->pread, todo); 124 return -EFAULT;
130 else
131 if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
132 return -EFAULT;
133 125
134 rbuf->pread = (rbuf->pread + todo) % rbuf->size; 126 rbuf->pread = (rbuf->pread + todo) % rbuf->size;
135 127
136 return len; 128 return len;
137} 129}
138 130
131void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
132{
133 size_t todo = len;
134 size_t split;
135
136 split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
137 if (split > 0) {
138 memcpy(buf, rbuf->data+rbuf->pread, split);
139 buf += split;
140 todo -= split;
141 rbuf->pread = 0;
142 }
143 memcpy(buf, rbuf->data+rbuf->pread, todo);
144
145 rbuf->pread = (rbuf->pread + todo) % rbuf->size;
146}
139 147
140 148
141ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len) 149ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len)
@@ -171,8 +179,8 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le
171 return status; 179 return status;
172} 180}
173 181
174ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, 182ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
175 int offset, u8* buf, size_t len, int usermem) 183 int offset, u8 __user *buf, size_t len)
176{ 184{
177 size_t todo; 185 size_t todo;
178 size_t split; 186 size_t split;
@@ -187,21 +195,40 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
187 todo = len; 195 todo = len;
188 split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0; 196 split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
189 if (split > 0) { 197 if (split > 0) {
190 if (!usermem) 198 if (copy_to_user(buf, rbuf->data+idx, split))
191 memcpy(buf, rbuf->data+idx, split); 199 return -EFAULT;
192 else
193 if (copy_to_user(buf, rbuf->data+idx, split))
194 return -EFAULT;
195 buf += split; 200 buf += split;
196 todo -= split; 201 todo -= split;
197 idx = 0; 202 idx = 0;
198 } 203 }
199 if (!usermem) 204 if (copy_to_user(buf, rbuf->data+idx, todo))
200 memcpy(buf, rbuf->data+idx, todo); 205 return -EFAULT;
201 else 206
202 if (copy_to_user(buf, rbuf->data+idx, todo)) 207 return len;
203 return -EFAULT; 208}
204 209
210ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
211 int offset, u8* buf, size_t len)
212{
213 size_t todo;
214 size_t split;
215 size_t pktlen;
216
217 pktlen = rbuf->data[idx] << 8;
218 pktlen |= rbuf->data[(idx + 1) % rbuf->size];
219 if (offset > pktlen) return -EINVAL;
220 if ((offset + len) > pktlen) len = pktlen - offset;
221
222 idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
223 todo = len;
224 split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
225 if (split > 0) {
226 memcpy(buf, rbuf->data+idx, split);
227 buf += split;
228 todo -= split;
229 idx = 0;
230 }
231 memcpy(buf, rbuf->data+idx, todo);
205 return len; 232 return len;
206} 233}
207 234
@@ -266,5 +293,6 @@ EXPORT_SYMBOL(dvb_ringbuffer_empty);
266EXPORT_SYMBOL(dvb_ringbuffer_free); 293EXPORT_SYMBOL(dvb_ringbuffer_free);
267EXPORT_SYMBOL(dvb_ringbuffer_avail); 294EXPORT_SYMBOL(dvb_ringbuffer_avail);
268EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup); 295EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
296EXPORT_SYMBOL(dvb_ringbuffer_read_user);
269EXPORT_SYMBOL(dvb_ringbuffer_read); 297EXPORT_SYMBOL(dvb_ringbuffer_read);
270EXPORT_SYMBOL(dvb_ringbuffer_write); 298EXPORT_SYMBOL(dvb_ringbuffer_write);
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
index 890826262966..41f04dae69b6 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
@@ -61,7 +61,7 @@ struct dvb_ringbuffer {
61** *** read min. 1000, max. <bufsize> bytes *** 61** *** read min. 1000, max. <bufsize> bytes ***
62** avail = dvb_ringbuffer_avail(rbuf); 62** avail = dvb_ringbuffer_avail(rbuf);
63** if (avail >= 1000) 63** if (avail >= 1000)
64** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize), 0); 64** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
65** else 65** else
66** ... 66** ...
67** 67**
@@ -114,8 +114,10 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
114** <usermem> specifies whether <buf> resides in user space 114** <usermem> specifies whether <buf> resides in user space
115** returns number of bytes transferred or -EFAULT 115** returns number of bytes transferred or -EFAULT
116*/ 116*/
117extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, 117extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf,
118 size_t len, int usermem); 118 u8 __user *buf, size_t len);
119extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
120 u8 *buf, size_t len);
119 121
120 122
121/* write routines & macros */ 123/* write routines & macros */
@@ -157,8 +159,10 @@ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
157 * <usermem> Set to 1 if <buf> is in userspace. 159 * <usermem> Set to 1 if <buf> is in userspace.
158 * returns Number of bytes read, or -EFAULT. 160 * returns Number of bytes read, or -EFAULT.
159 */ 161 */
162extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
163 int offset, u8 __user *buf, size_t len);
160extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx, 164extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
161 int offset, u8* buf, size_t len, int usermem); 165 int offset, u8 *buf, size_t len);
162 166
163/** 167/**
164 * Dispose of a packet in the ring buffer. 168 * Dispose of a packet in the ring buffer.
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index f00a0eb40420..a577c0f89f67 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -76,6 +76,7 @@ config DVB_USB_DIB0700
76 select DVB_DIB3000MC 76 select DVB_DIB3000MC
77 select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE 77 select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
78 select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE 78 select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE
79 select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
79 select DVB_TUNER_DIB0070 80 select DVB_TUNER_DIB0070
80 help 81 help
81 Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The 82 Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
@@ -107,6 +108,8 @@ config DVB_USB_CXUSB
107 select DVB_MT352 if !DVB_FE_CUSTOMISE 108 select DVB_MT352 if !DVB_FE_CUSTOMISE
108 select DVB_ZL10353 if !DVB_FE_CUSTOMISE 109 select DVB_ZL10353 if !DVB_FE_CUSTOMISE
109 select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE 110 select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
111 select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
112 select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
110 help 113 help
111 Say Y here to support the Conexant USB2.0 hybrid reference design. 114 Say Y here to support the Conexant USB2.0 hybrid reference design.
112 Currently, only DVB and ATSC modes are supported, analog mode 115 Currently, only DVB and ATSC modes are supported, analog mode
@@ -120,6 +123,8 @@ config DVB_USB_M920X
120 depends on DVB_USB 123 depends on DVB_USB
121 select DVB_MT352 if !DVB_FE_CUSTOMISE 124 select DVB_MT352 if !DVB_FE_CUSTOMISE
122 select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE 125 select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
126 select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
127 select DVB_TDA1004X if !DVB_FE_CUSTOMISE
123 help 128 help
124 Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. 129 Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
125 Currently, only devices with a product id of 130 Currently, only devices with a product id of
@@ -241,3 +246,13 @@ config DVB_USB_AF9005_REMOTE
241 Say Y here to support the default remote control decoding for the 246 Say Y here to support the default remote control decoding for the
242 Afatech AF9005 based receiver. 247 Afatech AF9005 based receiver.
243 248
249config DVB_USB_ANYSEE
250 tristate "Anysee DVB-T/C USB2.0 support"
251 depends on DVB_USB
252 select DVB_PLL if !DVB_FE_CUSTOMISE
253 select DVB_MT352 if !DVB_FE_CUSTOMISE
254 select DVB_ZL10353 if !DVB_FE_CUSTOMISE
255 select DVB_TDA10023 if !DVB_FE_CUSTOMISE
256 help
257 Say Y here to support the Anysee E30, Anysee E30 Plus or
258 Anysee E30 C Plus DVB USB2.0 receiver.
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index c6511a6c0ab8..44c11e45e564 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -61,6 +61,9 @@ obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o
61dvb-usb-af9005-remote-objs = af9005-remote.o 61dvb-usb-af9005-remote-objs = af9005-remote.o
62obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o 62obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
63 63
64dvb-usb-anysee-objs = anysee.o
65obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
66
64EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ 67EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
65# due to tuner-xc3028 68# due to tuner-xc3028
66EXTRA_CFLAGS += -Idrivers/media/common/tuners 69EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
new file mode 100644
index 000000000000..adfd4fc82efd
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -0,0 +1,553 @@
1/*
2 * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver
3 *
4 * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * TODO:
21 * - add smart card reader support for Conditional Access (CA)
22 *
23 * Card reader in Anysee is nothing more than ISO 7816 card reader.
24 * There is no hardware CAM in any Anysee device sold.
25 * In my understanding it should be implemented by making own module
26 * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This
27 * module registers serial interface that can be used to communicate
28 * with any ISO 7816 smart card.
29 *
30 * Any help according to implement serial smart card reader support
31 * is highly welcome!
32 */
33
34#include "anysee.h"
35#include "tda1002x.h"
36#include "mt352.h"
37#include "mt352_priv.h"
38#include "zl10353.h"
39
40/* debug */
41static int dvb_usb_anysee_debug;
42module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
43MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
44DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
45
46struct mutex anysee_usb_mutex;
47
48static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
49 u8 *rbuf, u8 rlen)
50{
51 struct anysee_state *state = d->priv;
52 int act_len, ret;
53 u8 buf[64];
54
55 if (slen > sizeof(buf))
56 slen = sizeof(buf);
57 memcpy(&buf[0], sbuf, slen);
58 buf[60] = state->seq++;
59
60 if (mutex_lock_interruptible(&anysee_usb_mutex) < 0)
61 return -EAGAIN;
62
63 /* We need receive one message more after dvb_usb_generic_rw due
64 to weird transaction flow, which is 1 x send + 2 x receive. */
65 ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
66
67 if (!ret) {
68 /* receive 2nd answer */
69 ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
70 d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf),
71 &act_len, 2000);
72 if (ret)
73 err("%s: recv bulk message failed: %d", __func__, ret);
74 else {
75 deb_xfer("<<< ");
76 debug_dump(buf, act_len, deb_xfer);
77 }
78 }
79
80 /* read request, copy returned data to return buf */
81 if (!ret && rbuf && rlen)
82 memcpy(rbuf, buf, rlen);
83
84 mutex_unlock(&anysee_usb_mutex);
85
86 return ret;
87}
88
89static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
90{
91 u8 buf[] = {CMD_REG_READ, reg >> 8, reg & 0xff, 0x01};
92 int ret;
93 ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1);
94 deb_info("%s: reg:%04x val:%02x\n", __func__, reg, *val);
95 return ret;
96}
97
98static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val)
99{
100 u8 buf[] = {CMD_REG_WRITE, reg >> 8, reg & 0xff, 0x01, val};
101 deb_info("%s: reg:%04x val:%02x\n", __func__, reg, val);
102 return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
103}
104
105static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
106{
107 u8 buf[] = {CMD_GET_HW_INFO};
108 return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3);
109}
110
111static int anysee_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
112{
113 u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00};
114 deb_info("%s: onoff:%02x\n", __func__, onoff);
115 return anysee_ctrl_msg(adap->dev, buf, sizeof(buf), NULL, 0);
116}
117
118static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval)
119{
120 u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval};
121 deb_info("%s: state:%02x interval:%02x\n", __func__, mode, interval);
122 return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
123}
124
125static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff)
126{
127 u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff};
128 deb_info("%s: onoff:%02x\n", __func__, onoff);
129 return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
130}
131
132static int anysee_init(struct dvb_usb_device *d)
133{
134 int ret;
135 /* LED light */
136 ret = anysee_led_ctrl(d, 0x01, 0x03);
137 if (ret)
138 return ret;
139
140 /* enable IR */
141 ret = anysee_ir_ctrl(d, 1);
142 if (ret)
143 return ret;
144
145 return 0;
146}
147
148/* I2C */
149static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
150 int num)
151{
152 struct dvb_usb_device *d = i2c_get_adapdata(adap);
153 int ret, inc, i = 0;
154
155 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
156 return -EAGAIN;
157
158 while (i < num) {
159 if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
160 u8 buf[6];
161 buf[0] = CMD_I2C_READ;
162 buf[1] = msg[i].addr + 1;
163 buf[2] = msg[i].buf[0];
164 buf[3] = 0x00;
165 buf[4] = 0x00;
166 buf[5] = 0x01;
167 ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf,
168 msg[i+1].len);
169 inc = 2;
170 } else {
171 u8 buf[4+msg[i].len];
172 buf[0] = CMD_I2C_WRITE;
173 buf[1] = msg[i].addr;
174 buf[2] = msg[i].len;
175 buf[3] = 0x01;
176 memcpy(&buf[4], msg[i].buf, msg[i].len);
177 ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
178 inc = 1;
179 }
180 if (ret)
181 return ret;
182
183 i += inc;
184 }
185
186 mutex_unlock(&d->i2c_mutex);
187
188 return i;
189}
190
191static u32 anysee_i2c_func(struct i2c_adapter *adapter)
192{
193 return I2C_FUNC_I2C;
194}
195
196static struct i2c_algorithm anysee_i2c_algo = {
197 .master_xfer = anysee_master_xfer,
198 .functionality = anysee_i2c_func,
199};
200
201static int anysee_mt352_demod_init(struct dvb_frontend *fe)
202{
203 static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 };
204 static u8 reset [] = { RESET, 0x80 };
205 static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
206 static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
207 static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
208 static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
209
210 mt352_write(fe, clock_config, sizeof(clock_config));
211 udelay(200);
212 mt352_write(fe, reset, sizeof(reset));
213 mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
214
215 mt352_write(fe, agc_cfg, sizeof(agc_cfg));
216 mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
217 mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
218
219 return 0;
220}
221
222/* Callbacks for DVB USB */
223static struct tda10023_config anysee_tda10023_config = {
224 .demod_address = 0x1a,
225 .invert = 0,
226 .xtal = 16000000,
227 .pll_m = 11,
228 .pll_p = 3,
229 .pll_n = 1,
230 .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C,
231 .deltaf = 0xfeeb,
232};
233
234static struct mt352_config anysee_mt352_config = {
235 .demod_address = 0x1e,
236 .demod_init = anysee_mt352_demod_init,
237};
238
239static struct zl10353_config anysee_zl10353_config = {
240 .demod_address = 0x1e,
241 .parallel_ts = 1,
242};
243
244static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
245{
246 int ret;
247 struct anysee_state *state = adap->dev->priv;
248 u8 hw_info[3];
249 u8 io_d; /* IO port D */
250
251 /* check which hardware we have
252 We must do this call two times to get reliable values (hw bug). */
253 ret = anysee_get_hw_info(adap->dev, hw_info);
254 if (ret)
255 return ret;
256 ret = anysee_get_hw_info(adap->dev, hw_info);
257 if (ret)
258 return ret;
259
260 /* Meaning of these info bytes are guessed. */
261 info("firmware version:%d.%d.%d hardware id:%d",
262 0, hw_info[1], hw_info[2], hw_info[0]);
263
264 ret = anysee_read_reg(adap->dev, 0xb0, &io_d); /* IO port D */
265 if (ret)
266 return ret;
267 deb_info("%s: IO port D:%02x\n", __func__, io_d);
268
269 /* Select demod using trial and error method. */
270
271 /* Try to attach demodulator in following order:
272 model demod hw firmware
273 1. E30 MT352 02 0.2.1
274 2. E30 ZL10353 02 0.2.1
275 3. E30 Plus ZL10353 06 0.1.0
276 4. E30C Plus TDA10023 0a 0.1.0 rev 0.2
277 4. E30C Plus TDA10023 0f 0.1.2 rev 0.4
278 */
279
280 /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */
281 adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
282 &adap->dev->i2c_adap);
283 if (adap->fe != NULL) {
284 state->tuner = DVB_PLL_THOMSON_DTT7579;
285 return 0;
286 }
287
288 /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
289 adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
290 &adap->dev->i2c_adap);
291 if (adap->fe != NULL) {
292 state->tuner = DVB_PLL_THOMSON_DTT7579;
293 return 0;
294 }
295
296 /* connect demod on IO port D for TDA10023 & ZL10353 */
297 ret = anysee_write_reg(adap->dev, 0xb0, 0x25);
298 if (ret)
299 return ret;
300
301 /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
302 adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
303 &adap->dev->i2c_adap);
304 if (adap->fe != NULL) {
305 state->tuner = DVB_PLL_THOMSON_DTT7579;
306 return 0;
307 }
308
309 /* IO port E - E30C rev 0.4 board requires this */
310 ret = anysee_write_reg(adap->dev, 0xb1, 0xa7);
311 if (ret)
312 return ret;
313
314 /* Philips TDA10023 DVB-C demod */
315 adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
316 &adap->dev->i2c_adap, 0x48);
317 if (adap->fe != NULL) {
318 state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
319 return 0;
320 }
321
322 /* return IO port D to init value for safe */
323 ret = anysee_write_reg(adap->dev, 0xb0, io_d);
324 if (ret)
325 return ret;
326
327 err("Unkown Anysee version: %02x %02x %02x. "\
328 "Please report the <linux-dvb@linuxtv.org>.",
329 hw_info[0], hw_info[1], hw_info[2]);
330
331 return -ENODEV;
332}
333
334static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
335{
336 struct anysee_state *state = adap->dev->priv;
337 deb_info("%s: \n", __func__);
338
339 switch (state->tuner) {
340 case DVB_PLL_THOMSON_DTT7579:
341 /* Thomson dtt7579 (not sure) PLL inside of:
342 Samsung DNOS404ZH102A NIM
343 Samsung DNOS404ZH103A NIM */
344 dvb_attach(dvb_pll_attach, adap->fe, 0x61,
345 NULL, DVB_PLL_THOMSON_DTT7579);
346 break;
347 case DVB_PLL_SAMSUNG_DTOS403IH102A:
348 /* Unknown PLL inside of Samsung DTOS403IH102A tuner module */
349 dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
350 &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
351 break;
352 }
353
354 return 0;
355}
356
357static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
358{
359 u8 buf[] = {CMD_GET_IR_CODE};
360 struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
361 u8 ircode[2];
362 int i, ret;
363
364 ret = anysee_ctrl_msg(d, buf, sizeof(buf), &ircode[0], 2);
365 if (ret)
366 return ret;
367
368 *event = 0;
369 *state = REMOTE_NO_KEY_PRESSED;
370
371 for (i = 0; i < d->props.rc_key_map_size; i++) {
372 if (keymap[i].custom == ircode[0] &&
373 keymap[i].data == ircode[1]) {
374 *event = keymap[i].event;
375 *state = REMOTE_KEY_PRESSED;
376 return 0;
377 }
378 }
379 return 0;
380}
381
382static struct dvb_usb_rc_key anysee_rc_keys[] = {
383 { 0x01, 0x00, KEY_0 },
384 { 0x01, 0x01, KEY_1 },
385 { 0x01, 0x02, KEY_2 },
386 { 0x01, 0x03, KEY_3 },
387 { 0x01, 0x04, KEY_4 },
388 { 0x01, 0x05, KEY_5 },
389 { 0x01, 0x06, KEY_6 },
390 { 0x01, 0x07, KEY_7 },
391 { 0x01, 0x08, KEY_8 },
392 { 0x01, 0x09, KEY_9 },
393 { 0x01, 0x0a, KEY_POWER },
394 { 0x01, 0x0b, KEY_DOCUMENTS }, /* * */
395 { 0x01, 0x19, KEY_FAVORITES },
396 { 0x01, 0x20, KEY_SLEEP },
397 { 0x01, 0x21, KEY_MODE }, /* 4:3 / 16:9 select */
398 { 0x01, 0x22, KEY_ZOOM },
399 { 0x01, 0x47, KEY_TEXT },
400 { 0x01, 0x16, KEY_TV }, /* TV / radio select */
401 { 0x01, 0x1e, KEY_LANGUAGE }, /* Second Audio Program */
402 { 0x01, 0x1a, KEY_SUBTITLE },
403 { 0x01, 0x1b, KEY_CAMERA }, /* screenshot */
404 { 0x01, 0x42, KEY_MUTE },
405 { 0x01, 0x0e, KEY_MENU },
406 { 0x01, 0x0f, KEY_EPG },
407 { 0x01, 0x17, KEY_INFO },
408 { 0x01, 0x10, KEY_EXIT },
409 { 0x01, 0x13, KEY_VOLUMEUP },
410 { 0x01, 0x12, KEY_VOLUMEDOWN },
411 { 0x01, 0x11, KEY_CHANNELUP },
412 { 0x01, 0x14, KEY_CHANNELDOWN },
413 { 0x01, 0x15, KEY_OK },
414 { 0x01, 0x1d, KEY_RED },
415 { 0x01, 0x1f, KEY_GREEN },
416 { 0x01, 0x1c, KEY_YELLOW },
417 { 0x01, 0x44, KEY_BLUE },
418 { 0x01, 0x0c, KEY_SHUFFLE }, /* snapshot */
419 { 0x01, 0x48, KEY_STOP },
420 { 0x01, 0x50, KEY_PLAY },
421 { 0x01, 0x51, KEY_PAUSE },
422 { 0x01, 0x49, KEY_RECORD },
423 { 0x01, 0x18, KEY_PREVIOUS }, /* |<< */
424 { 0x01, 0x0d, KEY_NEXT }, /* >>| */
425 { 0x01, 0x24, KEY_PROG1 }, /* F1 */
426 { 0x01, 0x25, KEY_PROG2 }, /* F2 */
427};
428
429/* DVB USB Driver stuff */
430static struct dvb_usb_device_properties anysee_properties;
431
432static int anysee_probe(struct usb_interface *intf,
433 const struct usb_device_id *id)
434{
435 struct dvb_usb_device *d;
436 struct usb_host_interface *alt;
437 int ret;
438
439 mutex_init(&anysee_usb_mutex);
440
441 /* There is one interface with two alternate settings.
442 Alternate setting 0 is for bulk transfer.
443 Alternate setting 1 is for isochronous transfer.
444 We use bulk transfer (alternate setting 0). */
445 if (intf->num_altsetting < 1)
446 return -ENODEV;
447
448 ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d,
449 adapter_nr);
450 if (ret)
451 return ret;
452
453 alt = usb_altnum_to_altsetting(intf, 0);
454 if (alt == NULL) {
455 deb_info("%s: no alt found!\n", __func__);
456 return -ENODEV;
457 }
458
459 ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
460 alt->desc.bAlternateSetting);
461 if (ret)
462 return ret;
463
464 if (d)
465 ret = anysee_init(d);
466
467 return ret;
468}
469
470static struct usb_device_id anysee_table [] = {
471 { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) },
472 { USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE) },
473 { } /* Terminating entry */
474};
475MODULE_DEVICE_TABLE(usb, anysee_table);
476
477static struct dvb_usb_device_properties anysee_properties = {
478 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
479
480 .usb_ctrl = DEVICE_SPECIFIC,
481
482 .size_of_priv = sizeof(struct anysee_state),
483
484 .num_adapters = 1,
485 .adapter = {
486 {
487 .streaming_ctrl = anysee_streaming_ctrl,
488 .frontend_attach = anysee_frontend_attach,
489 .tuner_attach = anysee_tuner_attach,
490 .stream = {
491 .type = USB_BULK,
492 .count = 8,
493 .endpoint = 0x82,
494 .u = {
495 .bulk = {
496 .buffersize = 512,
497 }
498 }
499 },
500 }
501 },
502
503 .rc_key_map = anysee_rc_keys,
504 .rc_key_map_size = ARRAY_SIZE(anysee_rc_keys),
505 .rc_query = anysee_rc_query,
506 .rc_interval = 200, /* windows driver uses 500ms */
507
508 .i2c_algo = &anysee_i2c_algo,
509
510 .generic_bulk_ctrl_endpoint = 1,
511
512 .num_device_descs = 1,
513 .devices = {
514 {
515 .name = "Anysee DVB USB2.0",
516 .cold_ids = {NULL},
517 .warm_ids = {&anysee_table[0],
518 &anysee_table[1], NULL},
519 },
520 }
521};
522
523static struct usb_driver anysee_driver = {
524 .name = "dvb_usb_anysee",
525 .probe = anysee_probe,
526 .disconnect = dvb_usb_device_exit,
527 .id_table = anysee_table,
528};
529
530/* module stuff */
531static int __init anysee_module_init(void)
532{
533 int ret;
534
535 ret = usb_register(&anysee_driver);
536 if (ret)
537 err("%s: usb_register failed. Error number %d", __func__, ret);
538
539 return ret;
540}
541
542static void __exit anysee_module_exit(void)
543{
544 /* deregister this driver from the USB subsystem */
545 usb_deregister(&anysee_driver);
546}
547
548module_init(anysee_module_init);
549module_exit(anysee_module_exit);
550
551MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
552MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0");
553MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h
new file mode 100644
index 000000000000..7ca01ff6e13c
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/anysee.h
@@ -0,0 +1,304 @@
1/*
2 * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver
3 *
4 * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * TODO:
21 * - add smart card reader support for Conditional Access (CA)
22 *
23 * Card reader in Anysee is nothing more than ISO 7816 card reader.
24 * There is no hardware CAM in any Anysee device sold.
25 * In my understanding it should be implemented by making own module
26 * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This
27 * module registers serial interface that can be used to communicate
28 * with any ISO 7816 smart card.
29 *
30 * Any help according to implement serial smart card reader support
31 * is highly welcome!
32 */
33
34#ifndef _DVB_USB_ANYSEE_H_
35#define _DVB_USB_ANYSEE_H_
36
37#define DVB_USB_LOG_PREFIX "anysee"
38#include "dvb-usb.h"
39
40#define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args)
41#define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args)
42#define deb_rc(args...) dprintk(dvb_usb_anysee_debug, 0x04, args)
43#define deb_reg(args...) dprintk(dvb_usb_anysee_debug, 0x08, args)
44#define deb_i2c(args...) dprintk(dvb_usb_anysee_debug, 0x10, args)
45#define deb_fw(args...) dprintk(dvb_usb_anysee_debug, 0x20, args)
46
47enum cmd {
48 CMD_I2C_READ = 0x33,
49 CMD_I2C_WRITE = 0x31,
50 CMD_REG_READ = 0xb0,
51 CMD_REG_WRITE = 0xb1,
52 CMD_STREAMING_CTRL = 0x12,
53 CMD_LED_AND_IR_CTRL = 0x16,
54 CMD_GET_IR_CODE = 0x41,
55 CMD_GET_HW_INFO = 0x19,
56 CMD_SMARTCARD = 0x34,
57};
58
59struct anysee_state {
60 u8 tuner;
61 u8 seq;
62};
63
64#endif
65
66/***************************************************************************
67 * USB API description (reverse engineered)
68 ***************************************************************************
69
70Transaction flow:
71=================
72BULK[00001] >>> REQUEST PACKET 64 bytes
73BULK[00081] <<< REPLY PACKET #1 64 bytes (PREVIOUS TRANSACTION REPLY)
74BULK[00081] <<< REPLY PACKET #2 64 bytes (CURRENT TRANSACTION REPLY)
75
76General reply packet(s) are always used if not own reply defined.
77
78============================================================================
79| 00-63 | GENERAL REPLY PACKET #1 (PREVIOUS REPLY)
80============================================================================
81| 00 | reply data (if any) from previous transaction
82| | Just same reply packet as returned during previous transaction.
83| | Needed only if reply is missed in previous transaction.
84| | Just skip normally.
85----------------------------------------------------------------------------
86| 01-59 | don't care
87----------------------------------------------------------------------------
88| 60 | packet sequence number
89----------------------------------------------------------------------------
90| 61-63 | don't care
91----------------------------------------------------------------------------
92
93============================================================================
94| 00-63 | GENERAL REPLY PACKET #2 (CURRENT REPLY)
95============================================================================
96| 00 | reply data (if any)
97----------------------------------------------------------------------------
98| 01-59 | don't care
99----------------------------------------------------------------------------
100| 60 | packet sequence number
101----------------------------------------------------------------------------
102| 61-63 | don't care
103----------------------------------------------------------------------------
104
105============================================================================
106| 00-63 | I2C WRITE REQUEST PACKET
107============================================================================
108| 00 | 0x31 I2C write command
109----------------------------------------------------------------------------
110| 01 | i2c address
111----------------------------------------------------------------------------
112| 02 | data length
113| | 0x02 (for typical I2C reg / val pair)
114----------------------------------------------------------------------------
115| 03 | 0x01
116----------------------------------------------------------------------------
117| 04- | data
118----------------------------------------------------------------------------
119| -59 | don't care
120----------------------------------------------------------------------------
121| 60 | packet sequence number
122----------------------------------------------------------------------------
123| 61-63 | don't care
124----------------------------------------------------------------------------
125
126============================================================================
127| 00-63 | I2C READ REQUEST PACKET
128============================================================================
129| 00 | 0x33 I2C read command
130----------------------------------------------------------------------------
131| 01 | i2c address + 1
132----------------------------------------------------------------------------
133| 02 | register
134----------------------------------------------------------------------------
135| 03 | 0x00
136----------------------------------------------------------------------------
137| 04 | 0x00
138----------------------------------------------------------------------------
139| 05 | 0x01
140----------------------------------------------------------------------------
141| 06-59 | don't care
142----------------------------------------------------------------------------
143| 60 | packet sequence number
144----------------------------------------------------------------------------
145| 61-63 | don't care
146----------------------------------------------------------------------------
147
148============================================================================
149| 00-63 | USB CONTROLLER REGISTER WRITE REQUEST PACKET
150============================================================================
151| 00 | 0xb1 register write command
152----------------------------------------------------------------------------
153| 01-02 | register
154----------------------------------------------------------------------------
155| 03 | 0x01
156----------------------------------------------------------------------------
157| 04 | value
158----------------------------------------------------------------------------
159| 05-59 | don't care
160----------------------------------------------------------------------------
161| 60 | packet sequence number
162----------------------------------------------------------------------------
163| 61-63 | don't care
164----------------------------------------------------------------------------
165
166============================================================================
167| 00-63 | USB CONTROLLER REGISTER READ REQUEST PACKET
168============================================================================
169| 00 | 0xb0 register read command
170----------------------------------------------------------------------------
171| 01-02 | register
172----------------------------------------------------------------------------
173| 03 | 0x01
174----------------------------------------------------------------------------
175| 04-59 | don't care
176----------------------------------------------------------------------------
177| 60 | packet sequence number
178----------------------------------------------------------------------------
179| 61-63 | don't care
180----------------------------------------------------------------------------
181
182============================================================================
183| 00-63 | LED CONTROL REQUEST PACKET
184============================================================================
185| 00 | 0x16 LED and IR control command
186----------------------------------------------------------------------------
187| 01 | 0x01 (LED)
188----------------------------------------------------------------------------
189| 03 | 0x00 blink
190| | 0x01 lights continuously
191----------------------------------------------------------------------------
192| 04 | blink interval
193| | 0x00 fastest (looks like LED lights continuously)
194| | 0xff slowest
195----------------------------------------------------------------------------
196| 05-59 | don't care
197----------------------------------------------------------------------------
198| 60 | packet sequence number
199----------------------------------------------------------------------------
200| 61-63 | don't care
201----------------------------------------------------------------------------
202
203============================================================================
204| 00-63 | IR CONTROL REQUEST PACKET
205============================================================================
206| 00 | 0x16 LED and IR control command
207----------------------------------------------------------------------------
208| 01 | 0x02 (IR)
209----------------------------------------------------------------------------
210| 03 | 0x00 IR disabled
211| | 0x01 IR enabled
212----------------------------------------------------------------------------
213| 04-59 | don't care
214----------------------------------------------------------------------------
215| 60 | packet sequence number
216----------------------------------------------------------------------------
217| 61-63 | don't care
218----------------------------------------------------------------------------
219
220============================================================================
221| 00-63 | STREAMING CONTROL REQUEST PACKET
222============================================================================
223| 00 | 0x12 streaming control command
224----------------------------------------------------------------------------
225| 01 | 0x00 streaming disabled
226| | 0x01 streaming enabled
227----------------------------------------------------------------------------
228| 02 | 0x00
229----------------------------------------------------------------------------
230| 03-59 | don't care
231----------------------------------------------------------------------------
232| 60 | packet sequence number
233----------------------------------------------------------------------------
234| 61-63 | don't care
235----------------------------------------------------------------------------
236
237============================================================================
238| 00-63 | REMOTE CONTROL REQUEST PACKET
239============================================================================
240| 00 | 0x41 remote control command
241----------------------------------------------------------------------------
242| 01-59 | don't care
243----------------------------------------------------------------------------
244| 60 | packet sequence number
245----------------------------------------------------------------------------
246| 61-63 | don't care
247----------------------------------------------------------------------------
248
249============================================================================
250| 00-63 | REMOTE CONTROL REPLY PACKET
251============================================================================
252| 00 | 0x00 code not received
253| | 0x01 code received
254----------------------------------------------------------------------------
255| 01 | remote control code
256----------------------------------------------------------------------------
257| 02-59 | don't care
258----------------------------------------------------------------------------
259| 60 | packet sequence number
260----------------------------------------------------------------------------
261| 61-63 | don't care
262----------------------------------------------------------------------------
263
264============================================================================
265| 00-63 | GET HARDWARE INFO REQUEST PACKET
266============================================================================
267| 00 | 0x19 get hardware info command
268----------------------------------------------------------------------------
269| 01-59 | don't care
270----------------------------------------------------------------------------
271| 60 | packet sequence number
272----------------------------------------------------------------------------
273| 61-63 | don't care
274----------------------------------------------------------------------------
275
276============================================================================
277| 00-63 | GET HARDWARE INFO REPLY PACKET
278============================================================================
279| 00 | hardware id
280----------------------------------------------------------------------------
281| 01-02 | firmware version
282----------------------------------------------------------------------------
283| 03-59 | don't care
284----------------------------------------------------------------------------
285| 60 | packet sequence number
286----------------------------------------------------------------------------
287| 61-63 | don't care
288----------------------------------------------------------------------------
289
290============================================================================
291| 00-63 | SMART CARD READER PACKET
292============================================================================
293| 00 | 0x34 smart card reader command
294----------------------------------------------------------------------------
295| xx |
296----------------------------------------------------------------------------
297| xx-59 | don't care
298----------------------------------------------------------------------------
299| 60 | packet sequence number
300----------------------------------------------------------------------------
301| 61-63 | don't care
302----------------------------------------------------------------------------
303
304*/
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c
index 2ccb90fa60c8..eb34cc3894e0 100644
--- a/drivers/media/dvb/dvb-usb/au6610.c
+++ b/drivers/media/dvb/dvb-usb/au6610.c
@@ -1,24 +1,31 @@
1/* DVB USB compliant linux driver for Sigmatek DVB-110 DVB-T USB2.0 receiver 1/*
2 * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0.
2 * 3 *
3 * Copyright (C) 2006 Antti Palosaari <crope@iki.fi> 4 * Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
4 * 5 *
5 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify
6 * under the terms of the GNU General Public License as published by the Free 7 * it under the terms of the GNU General Public License as published by
7 * Software Foundation, version 2. 8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
8 * 10 *
9 * see Documentation/dvb/README.dvb-usb for more information 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10 */ 19 */
11 20
12#include "au6610.h" 21#include "au6610.h"
13
14#include "zl10353.h" 22#include "zl10353.h"
15#include "qt1010.h" 23#include "qt1010.h"
16 24
17/* debug */ 25/* debug */
18static int dvb_usb_au6610_debug; 26static int dvb_usb_au6610_debug;
19module_param_named(debug, dvb_usb_au6610_debug, int, 0644); 27module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
20MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); 28MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
21
22DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 29DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
23 30
24static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr, 31static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
@@ -42,9 +49,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
42 } 49 }
43 50
44 ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation, 51 ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
45 USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, usb_buf, 52 USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index,
46 sizeof(usb_buf), AU6610_USB_TIMEOUT); 53 usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT);
47
48 if (ret < 0) 54 if (ret < 0)
49 return ret; 55 return ret;
50 56
@@ -116,15 +122,6 @@ static struct i2c_algorithm au6610_i2c_algo = {
116}; 122};
117 123
118/* Callbacks for DVB USB */ 124/* Callbacks for DVB USB */
119static int au6610_identify_state(struct usb_device *udev,
120 struct dvb_usb_device_properties *props,
121 struct dvb_usb_device_description **desc,
122 int *cold)
123{
124 *cold = 0;
125 return 0;
126}
127
128static struct zl10353_config au6610_zl10353_config = { 125static struct zl10353_config au6610_zl10353_config = {
129 .demod_address = 0x0f, 126 .demod_address = 0x0f,
130 .no_tuner = 1, 127 .no_tuner = 1,
@@ -133,12 +130,12 @@ static struct zl10353_config au6610_zl10353_config = {
133 130
134static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap) 131static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
135{ 132{
136 if ((adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config, 133 adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
137 &adap->dev->i2c_adap)) != NULL) { 134 &adap->dev->i2c_adap);
138 return 0; 135 if (adap->fe == NULL)
139 } 136 return -ENODEV;
140 137
141 return -EIO; 138 return 0;
142} 139}
143 140
144static struct qt1010_config au6610_qt1010_config = { 141static struct qt1010_config au6610_qt1010_config = {
@@ -171,7 +168,7 @@ static int au6610_probe(struct usb_interface *intf,
171 alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING); 168 alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
172 169
173 if (alt == NULL) { 170 if (alt == NULL) {
174 deb_rc("no alt found!\n"); 171 deb_info("%s: no alt found!\n", __func__);
175 return -ENODEV; 172 return -ENODEV;
176 } 173 }
177 ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber, 174 ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
@@ -181,18 +178,19 @@ static int au6610_probe(struct usb_interface *intf,
181 return ret; 178 return ret;
182} 179}
183 180
184
185static struct usb_device_id au6610_table [] = { 181static struct usb_device_id au6610_table [] = {
186 { USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) }, 182 { USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) },
187 { } /* Terminating entry */ 183 { } /* Terminating entry */
188}; 184};
189MODULE_DEVICE_TABLE (usb, au6610_table); 185MODULE_DEVICE_TABLE(usb, au6610_table);
190 186
191static struct dvb_usb_device_properties au6610_properties = { 187static struct dvb_usb_device_properties au6610_properties = {
192 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 188 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
189
193 .usb_ctrl = DEVICE_SPECIFIC, 190 .usb_ctrl = DEVICE_SPECIFIC,
194 .size_of_priv = 0, 191
195 .identify_state = au6610_identify_state, 192 .size_of_priv = 0,
193
196 .num_adapters = 1, 194 .num_adapters = 1,
197 .adapter = { 195 .adapter = {
198 { 196 {
@@ -206,20 +204,22 @@ static struct dvb_usb_device_properties au6610_properties = {
206 .u = { 204 .u = {
207 .isoc = { 205 .isoc = {
208 .framesperurb = 40, 206 .framesperurb = 40,
209 .framesize = 942, /* maximum packet size */ 207 .framesize = 942,
210 .interval = 1.25, /* 125 us */ 208 .interval = 1,
211 } 209 }
212 } 210 }
213 }, 211 },
214 } 212 }
215 }, 213 },
214
216 .i2c_algo = &au6610_i2c_algo, 215 .i2c_algo = &au6610_i2c_algo,
216
217 .num_device_descs = 1, 217 .num_device_descs = 1,
218 .devices = { 218 .devices = {
219 { 219 {
220 "Sigmatek DVB-110 DVB-T USB2.0", 220 .name = "Sigmatek DVB-110 DVB-T USB2.0",
221 { &au6610_table[0], NULL }, 221 .cold_ids = {NULL},
222 { NULL }, 222 .warm_ids = {&au6610_table[0], NULL},
223 }, 223 },
224 } 224 }
225}; 225};
@@ -236,12 +236,11 @@ static int __init au6610_module_init(void)
236{ 236{
237 int ret; 237 int ret;
238 238
239 if ((ret = usb_register(&au6610_driver))) { 239 ret = usb_register(&au6610_driver);
240 if (ret)
240 err("usb_register failed. Error number %d", ret); 241 err("usb_register failed. Error number %d", ret);
241 return ret;
242 }
243 242
244 return 0; 243 return ret;
245} 244}
246 245
247static void __exit au6610_module_exit(void) 246static void __exit au6610_module_exit(void)
@@ -250,10 +249,10 @@ static void __exit au6610_module_exit(void)
250 usb_deregister(&au6610_driver); 249 usb_deregister(&au6610_driver);
251} 250}
252 251
253module_init (au6610_module_init); 252module_init(au6610_module_init);
254module_exit (au6610_module_exit); 253module_exit(au6610_module_exit);
255 254
256MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 255MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
257MODULE_DESCRIPTION("Driver Sigmatek DVB-110 DVB-T USB2.0 / AU6610"); 256MODULE_DESCRIPTION("Driver for Alcor Micro AU6610 DVB-T USB2.0");
258MODULE_VERSION("0.1"); 257MODULE_VERSION("0.1");
259MODULE_LICENSE("GPL"); 258MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/au6610.h b/drivers/media/dvb/dvb-usb/au6610.h
index 4161b054c713..7849abe2c614 100644
--- a/drivers/media/dvb/dvb-usb/au6610.h
+++ b/drivers/media/dvb/dvb-usb/au6610.h
@@ -1,10 +1,30 @@
1/*
2 * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0.
3 *
4 * Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
1#ifndef _DVB_USB_AU6610_H_ 21#ifndef _DVB_USB_AU6610_H_
2#define _DVB_USB_AU6610_H_ 22#define _DVB_USB_AU6610_H_
3 23
4#define DVB_USB_LOG_PREFIX "au6610" 24#define DVB_USB_LOG_PREFIX "au6610"
5#include "dvb-usb.h" 25#include "dvb-usb.h"
6 26
7#define deb_rc(args...) dprintk(dvb_usb_au6610_debug,0x01,args) 27#define deb_info(args...) dprintk(dvb_usb_au6610_debug, 0x01, args)
8 28
9#define AU6610_REQ_I2C_WRITE 0x14 29#define AU6610_REQ_I2C_WRITE 0x14
10#define AU6610_REQ_I2C_READ 0x13 30#define AU6610_REQ_I2C_READ 0x13
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 0286156704f2..578afce6884c 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -35,6 +35,7 @@
35#include "zl10353.h" 35#include "zl10353.h"
36#include "tuner-xc2028.h" 36#include "tuner-xc2028.h"
37#include "tuner-simple.h" 37#include "tuner-simple.h"
38#include "mxl5005s.h"
38 39
39/* debug */ 40/* debug */
40static int dvb_usb_cxusb_debug; 41static int dvb_usb_cxusb_debug;
@@ -43,9 +44,8 @@ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_ST
43 44
44DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 45DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
45 46
46#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args) 47#define deb_info(args...) dprintk(dvb_usb_cxusb_debug, 0x03, args)
47#define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \ 48#define deb_i2c(args...) dprintk(dvb_usb_cxusb_debug, 0x02, args)
48 dprintk(dvb_usb_cxusb_debug,0x01,args)
49 49
50static int cxusb_ctrl_msg(struct dvb_usb_device *d, 50static int cxusb_ctrl_msg(struct dvb_usb_device *d,
51 u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) 51 u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
@@ -202,6 +202,46 @@ static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
202 return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0); 202 return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
203} 203}
204 204
205static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff)
206{
207 int ret;
208 if (!onoff)
209 return cxusb_ctrl_msg(d, CMD_POWER_OFF, NULL, 0, NULL, 0);
210 if (d->state == DVB_USB_STATE_INIT &&
211 usb_set_interface(d->udev, 0, 0) < 0)
212 err("set interface failed");
213 do; while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
214 !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) &&
215 !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0);
216 if (!ret) {
217 /* FIXME: We don't know why, but we need to configure the
218 * lgdt3303 with the register settings below on resume */
219 int i;
220 u8 buf, bufs[] = {
221 0x0e, 0x2, 0x00, 0x7f,
222 0x0e, 0x2, 0x02, 0xfe,
223 0x0e, 0x2, 0x02, 0x01,
224 0x0e, 0x2, 0x00, 0x03,
225 0x0e, 0x2, 0x0d, 0x40,
226 0x0e, 0x2, 0x0e, 0x87,
227 0x0e, 0x2, 0x0f, 0x8e,
228 0x0e, 0x2, 0x10, 0x01,
229 0x0e, 0x2, 0x14, 0xd7,
230 0x0e, 0x2, 0x47, 0x88,
231 };
232 msleep(20);
233 for (i = 0; i < sizeof(bufs)/sizeof(u8); i += 4/sizeof(u8)) {
234 ret = cxusb_ctrl_msg(d, CMD_I2C_WRITE,
235 bufs+i, 4, &buf, 1);
236 if (ret)
237 break;
238 if (buf != 0x8)
239 return -EREMOTEIO;
240 }
241 }
242 return ret;
243}
244
205static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff) 245static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
206{ 246{
207 u8 b = 0; 247 u8 b = 0;
@@ -233,6 +273,16 @@ static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
233 return 0; 273 return 0;
234} 274}
235 275
276static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
277{
278 if (onoff)
279 cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_ON, NULL, 0, NULL, 0);
280 else
281 cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_OFF,
282 NULL, 0, NULL, 0);
283 return 0;
284}
285
236static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) 286static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
237{ 287{
238 struct dvb_usb_rc_key *keymap = d->props.rc_key_map; 288 struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
@@ -423,6 +473,12 @@ static struct lgdt330x_config cxusb_lgdt3303_config = {
423 .demod_chip = LGDT3303, 473 .demod_chip = LGDT3303,
424}; 474};
425 475
476static struct lgdt330x_config cxusb_aver_lgdt3303_config = {
477 .demod_address = 0x0e,
478 .demod_chip = LGDT3303,
479 .clock_polarity_flip = 2,
480};
481
426static struct mt352_config cxusb_dee1601_config = { 482static struct mt352_config cxusb_dee1601_config = {
427 .demod_address = 0x0f, 483 .demod_address = 0x0f,
428 .demod_init = cxusb_dee1601_demod_init, 484 .demod_init = cxusb_dee1601_demod_init,
@@ -453,6 +509,24 @@ static struct mt352_config cxusb_mt352_xc3028_config = {
453 .demod_init = cxusb_mt352_demod_init, 509 .demod_init = cxusb_mt352_demod_init,
454}; 510};
455 511
512/* FIXME: needs tweaking */
513static struct mxl5005s_config aver_a868r_tuner = {
514 .i2c_address = 0x63,
515 .if_freq = 6000000UL,
516 .xtal_freq = CRYSTAL_FREQ_16000000HZ,
517 .agc_mode = MXL_SINGLE_AGC,
518 .tracking_filter = MXL_TF_C,
519 .rssi_enable = MXL_RSSI_ENABLE,
520 .cap_select = MXL_CAP_SEL_ENABLE,
521 .div_out = MXL_DIV_OUT_4,
522 .clock_out = MXL_CLOCK_OUT_DISABLE,
523 .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
524 .top = MXL5005S_TOP_25P2,
525 .mod_mode = MXL_DIGITAL_MODE,
526 .if_mode = MXL_ZERO_IF,
527 .AgcMasterByte = 0x00,
528};
529
456/* Callbacks for DVB USB */ 530/* Callbacks for DVB USB */
457static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap) 531static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
458{ 532{
@@ -533,6 +607,13 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
533 return 0; 607 return 0;
534} 608}
535 609
610static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
611{
612 dvb_attach(mxl5005s_attach, adap->fe,
613 &adap->dev->i2c_adap, &aver_a868r_tuner);
614 return 0;
615}
616
536static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap) 617static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
537{ 618{
538 u8 b; 619 u8 b;
@@ -562,6 +643,16 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
562 return -EIO; 643 return -EIO;
563} 644}
564 645
646static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
647{
648 adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
649 &adap->dev->i2c_adap);
650 if (adap->fe != NULL)
651 return 0;
652
653 return -EIO;
654}
655
565static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap) 656static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
566{ 657{
567 /* used in both lgz201 and th7579 */ 658 /* used in both lgz201 and th7579 */
@@ -736,6 +827,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
736static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties; 827static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
737static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties; 828static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
738static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties; 829static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
830static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
739 831
740static int cxusb_probe(struct usb_interface *intf, 832static int cxusb_probe(struct usb_interface *intf,
741 const struct usb_device_id *id) 833 const struct usb_device_id *id)
@@ -756,7 +848,10 @@ static int cxusb_probe(struct usb_interface *intf,
756 THIS_MODULE, NULL, adapter_nr) || 848 THIS_MODULE, NULL, adapter_nr) ||
757 0 == dvb_usb_device_init(intf, 849 0 == dvb_usb_device_init(intf,
758 &cxusb_bluebird_nano2_needsfirmware_properties, 850 &cxusb_bluebird_nano2_needsfirmware_properties,
759 THIS_MODULE, NULL, adapter_nr)) 851 THIS_MODULE, NULL, adapter_nr) ||
852 0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties,
853 THIS_MODULE, NULL, adapter_nr) ||
854 0)
760 return 0; 855 return 0;
761 856
762 return -EINVAL; 857 return -EINVAL;
@@ -779,6 +874,7 @@ static struct usb_device_id cxusb_table [] = {
779 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) }, 874 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
780 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) }, 875 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
781 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) }, 876 { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
877 { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) },
782 {} /* Terminating entry */ 878 {} /* Terminating entry */
783}; 879};
784MODULE_DEVICE_TABLE (usb, cxusb_table); 880MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -1182,6 +1278,48 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
1182 } 1278 }
1183}; 1279};
1184 1280
1281static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
1282 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
1283
1284 .usb_ctrl = CYPRESS_FX2,
1285
1286 .size_of_priv = sizeof(struct cxusb_state),
1287
1288 .num_adapters = 1,
1289 .adapter = {
1290 {
1291 .streaming_ctrl = cxusb_aver_streaming_ctrl,
1292 .frontend_attach = cxusb_aver_lgdt3303_frontend_attach,
1293 .tuner_attach = cxusb_mxl5003s_tuner_attach,
1294 /* parameter for the MPEG2-data transfer */
1295 .stream = {
1296 .type = USB_BULK,
1297 .count = 5,
1298 .endpoint = 0x04,
1299 .u = {
1300 .bulk = {
1301 .buffersize = 8192,
1302 }
1303 }
1304 },
1305
1306 },
1307 },
1308 .power_ctrl = cxusb_aver_power_ctrl,
1309
1310 .i2c_algo = &cxusb_i2c_algo,
1311
1312 .generic_bulk_ctrl_endpoint = 0x01,
1313
1314 .num_device_descs = 1,
1315 .devices = {
1316 { "AVerMedia AVerTVHD Volar (A868R)",
1317 { NULL },
1318 { &cxusb_table[16], NULL },
1319 },
1320 }
1321};
1322
1185static struct usb_driver cxusb_driver = { 1323static struct usb_driver cxusb_driver = {
1186 .name = "dvb_usb_cxusb", 1324 .name = "dvb_usb_cxusb",
1187 .probe = cxusb_probe, 1325 .probe = cxusb_probe,
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
index 4768a2c35517..1a51eafd31b9 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.h
+++ b/drivers/media/dvb/dvb-usb/cxusb.h
@@ -20,6 +20,9 @@
20#define CMD_STREAMING_ON 0x36 20#define CMD_STREAMING_ON 0x36
21#define CMD_STREAMING_OFF 0x37 21#define CMD_STREAMING_OFF 0x37
22 22
23#define CMD_AVER_STREAM_ON 0x18
24#define CMD_AVER_STREAM_OFF 0x19
25
23#define CMD_GET_IR_CODE 0x47 26#define CMD_GET_IR_CODE 0x47
24 27
25#define CMD_ANALOG 0x50 28#define CMD_ANALOG 0x50
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
index c4d40fe01d57..3dd20bfbed32 100644
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -1117,6 +1117,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
1117 { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) }, 1117 { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_HT_EXPRESS) },
1118 { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) }, 1118 { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS) },
1119 { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) }, 1119 { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
1120 { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) },
1120 { 0 } /* Terminating entry */ 1121 { 0 } /* Terminating entry */
1121}; 1122};
1122MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); 1123MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1372,7 +1373,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
1372 } 1373 }
1373 }, 1374 },
1374 1375
1375 .num_device_descs = 2, 1376 .num_device_descs = 3,
1376 .devices = { 1377 .devices = {
1377 { "DiBcom STK7070PD reference design", 1378 { "DiBcom STK7070PD reference design",
1378 { &dib0700_usb_id_table[17], NULL }, 1379 { &dib0700_usb_id_table[17], NULL },
@@ -1381,6 +1382,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
1381 { "Pinnacle PCTV Dual DVB-T Diversity Stick", 1382 { "Pinnacle PCTV Dual DVB-T Diversity Stick",
1382 { &dib0700_usb_id_table[18], NULL }, 1383 { &dib0700_usb_id_table[18], NULL },
1383 { NULL }, 1384 { NULL },
1385 },
1386 { "Hauppauge Nova-TD Stick (52009)",
1387 { &dib0700_usb_id_table[35], NULL },
1388 { NULL },
1384 } 1389 }
1385 } 1390 }
1386 }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, 1391 }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 23428cd30756..326f7608954b 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -20,11 +20,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
20 } 20 }
21 21
22 strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name)); 22 strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
23#ifdef I2C_ADAP_CLASS_TV_DIGITAL
24 d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
25#else
26 d->i2c_adap.class = I2C_CLASS_TV_DIGITAL, 23 d->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
27#endif
28 d->i2c_adap.algo = d->props.i2c_algo; 24 d->i2c_adap.algo = d->props.i2c_algo;
29 d->i2c_adap.algo_data = NULL; 25 d->i2c_adap.algo_data = NULL;
30 d->i2c_adap.dev.parent = &d->udev->dev; 26 d->i2c_adap.dev.parent = &d->udev->dev;
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 34245d1b7dd9..e5238b31e946 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -14,6 +14,7 @@
14#define USB_VID_AFATECH 0x15a4 14#define USB_VID_AFATECH 0x15a4
15#define USB_VID_ALCOR_MICRO 0x058f 15#define USB_VID_ALCOR_MICRO 0x058f
16#define USB_VID_ALINK 0x05e3 16#define USB_VID_ALINK 0x05e3
17#define USB_VID_AMT 0x1c73
17#define USB_VID_ANCHOR 0x0547 18#define USB_VID_ANCHOR 0x0547
18#define USB_VID_ANSONIC 0x10b9 19#define USB_VID_ANSONIC 0x10b9
19#define USB_VID_ANUBIS_ELECTRONIC 0x10fd 20#define USB_VID_ANUBIS_ELECTRONIC 0x10fd
@@ -57,6 +58,7 @@
57#define USB_PID_AFATECH_AF9005 0x9020 58#define USB_PID_AFATECH_AF9005 0x9020
58#define USB_VID_ALINK_DTU 0xf170 59#define USB_VID_ALINK_DTU 0xf170
59#define USB_PID_ANSONIC_DVBT_USB 0x6000 60#define USB_PID_ANSONIC_DVBT_USB 0x6000
61#define USB_PID_ANYSEE 0x861f
60#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 62#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
61#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 63#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
62#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 64#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
@@ -132,9 +134,15 @@
132#define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070 134#define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070
133#define USB_PID_HAUPPAUGE_MYTV_T 0x7080 135#define USB_PID_HAUPPAUGE_MYTV_T 0x7080
134#define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580 136#define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580
137#define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009 0x5200
135#define USB_PID_AVERMEDIA_EXPRESS 0xb568 138#define USB_PID_AVERMEDIA_EXPRESS 0xb568
136#define USB_PID_AVERMEDIA_VOLAR 0xa807 139#define USB_PID_AVERMEDIA_VOLAR 0xa807
137#define USB_PID_AVERMEDIA_VOLAR_2 0xb808 140#define USB_PID_AVERMEDIA_VOLAR_2 0xb808
141#define USB_PID_AVERMEDIA_VOLAR_A868R 0xa868
142#define USB_PID_AVERMEDIA_MCE_USB_M038 0x1228
143#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R 0x0039
144#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC 0x1039
145#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT 0x2039
138#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006 146#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
139#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a 147#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
140#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058 148#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c
index 037f7ffb47b2..6f596ed41761 100644
--- a/drivers/media/dvb/dvb-usb/gl861.c
+++ b/drivers/media/dvb/dvb-usb/gl861.c
@@ -1,8 +1,8 @@
1/* DVB USB compliant linux driver for GL861 USB2.0 devices. 1/* DVB USB compliant linux driver for GL861 USB2.0 devices.
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify it 3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by the Free 4 * under the terms of the GNU General Public License as published by the
5 * Software Foundation, version 2. 5 * Free Software Foundation, version 2.
6 * 6 *
7 * see Documentation/dvb/README.dvb-usb for more information 7 * see Documentation/dvb/README.dvb-usb for more information
8 */ 8 */
@@ -13,9 +13,9 @@
13 13
14/* debug */ 14/* debug */
15static int dvb_usb_gl861_debug; 15static int dvb_usb_gl861_debug;
16module_param_named(debug,dvb_usb_gl861_debug, int, 0644); 16module_param_named(debug, dvb_usb_gl861_debug, int, 0644);
17MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); 17MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))."
18 18 DVB_USB_DEBUG_STATUS);
19DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 19DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
20 20
21static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, 21static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
@@ -70,7 +70,7 @@ static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
70 /* write/read request */ 70 /* write/read request */
71 if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { 71 if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
72 if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf, 72 if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
73 msg[i].len, msg[i+1].buf, msg[i+1].len) < 0) 73 msg[i].len, msg[i+1].buf, msg[i+1].len) < 0)
74 break; 74 break;
75 i++; 75 i++;
76 } else 76 } else
@@ -102,12 +102,13 @@ static struct zl10353_config gl861_zl10353_config = {
102 102
103static int gl861_frontend_attach(struct dvb_usb_adapter *adap) 103static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
104{ 104{
105 if ((adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
106 &adap->dev->i2c_adap)) != NULL) {
107 return 0;
108 }
109 105
110 return -EIO; 106 adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
107 &adap->dev->i2c_adap);
108 if (adap->fe == NULL)
109 return -EIO;
110
111 return 0;
111} 112}
112 113
113static struct qt1010_config gl861_qt1010_config = { 114static struct qt1010_config gl861_qt1010_config = {
@@ -156,7 +157,7 @@ static struct usb_device_id gl861_table [] = {
156 { USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) }, 157 { USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) },
157 { } /* Terminating entry */ 158 { } /* Terminating entry */
158}; 159};
159MODULE_DEVICE_TABLE (usb, gl861_table); 160MODULE_DEVICE_TABLE(usb, gl861_table);
160 161
161static struct dvb_usb_device_properties gl861_properties = { 162static struct dvb_usb_device_properties gl861_properties = {
162 .caps = DVB_USB_IS_AN_I2C_ADAPTER, 163 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
@@ -180,7 +181,7 @@ static struct dvb_usb_device_properties gl861_properties = {
180 } 181 }
181 } 182 }
182 }, 183 },
183 }}, 184 } },
184 .i2c_algo = &gl861_i2c_algo, 185 .i2c_algo = &gl861_i2c_algo,
185 186
186 .num_device_descs = 2, 187 .num_device_descs = 2,
@@ -210,12 +211,11 @@ static int __init gl861_module_init(void)
210{ 211{
211 int ret; 212 int ret;
212 213
213 if ((ret = usb_register(&gl861_driver))) { 214 ret = usb_register(&gl861_driver);
215 if (ret)
214 err("usb_register failed. Error number %d", ret); 216 err("usb_register failed. Error number %d", ret);
215 return ret;
216 }
217 217
218 return 0; 218 return ret;
219} 219}
220 220
221static void __exit gl861_module_exit(void) 221static void __exit gl861_module_exit(void)
@@ -224,8 +224,8 @@ static void __exit gl861_module_exit(void)
224 usb_deregister(&gl861_driver); 224 usb_deregister(&gl861_driver);
225} 225}
226 226
227module_init (gl861_module_init); 227module_init(gl861_module_init);
228module_exit (gl861_module_exit); 228module_exit(gl861_module_exit);
229 229
230MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>"); 230MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>");
231MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861"); 231MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861");
diff --git a/drivers/media/dvb/dvb-usb/gl861.h b/drivers/media/dvb/dvb-usb/gl861.h
index 72a51afd5ee3..c54855e2c233 100644
--- a/drivers/media/dvb/dvb-usb/gl861.h
+++ b/drivers/media/dvb/dvb-usb/gl861.h
@@ -4,7 +4,7 @@
4#define DVB_USB_LOG_PREFIX "gl861" 4#define DVB_USB_LOG_PREFIX "gl861"
5#include "dvb-usb.h" 5#include "dvb-usb.h"
6 6
7#define deb_rc(args...) dprintk(dvb_usb_gl861_debug,0x01,args) 7#define deb_rc(args...) dprintk(dvb_usb_gl861_debug, 0x01, args)
8 8
9#define GL861_WRITE 0x40 9#define GL861_WRITE 0x40
10#define GL861_READ 0xc0 10#define GL861_READ 0xc0
diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c
index 03900d241a76..f7b71657f0f6 100644
--- a/drivers/media/dvb/frontends/au8522.c
+++ b/drivers/media/dvb/frontends/au8522.c
@@ -26,7 +26,6 @@
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include "dvb_frontend.h" 28#include "dvb_frontend.h"
29#include "dvb-pll.h"
30#include "au8522.h" 29#include "au8522.h"
31 30
32struct au8522_state { 31struct au8522_state {
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index a054894ff481..ea058153ebfa 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -343,6 +343,52 @@ static struct dvb_pll_desc dvb_pll_opera1 = {
343 } 343 }
344}; 344};
345 345
346static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf,
347 const struct dvb_frontend_parameters *params)
348{
349 struct dvb_pll_priv *priv = fe->tuner_priv;
350 struct i2c_msg msg = {
351 .addr = priv->pll_i2c_address,
352 .flags = 0,
353 .buf = buf,
354 .len = 4
355 };
356 int result;
357
358 if (fe->ops.i2c_gate_ctrl)
359 fe->ops.i2c_gate_ctrl(fe, 1);
360
361 result = i2c_transfer(priv->i2c, &msg, 1);
362 if (result != 1)
363 printk(KERN_ERR "%s: i2c_transfer failed:%d",
364 __func__, result);
365
366 buf[2] = 0x9e;
367 buf[3] = 0x90;
368
369 return;
370}
371
372/* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
373static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
374 .name = "Samsung DTOS403IH102A",
375 .min = 44250000,
376 .max = 858000000,
377 .iffreq = 36125000,
378 .count = 8,
379 .set = samsung_dtos403ih102a_set,
380 .entries = {
381 { 135000000, 62500, 0xbe, 0x01 },
382 { 177000000, 62500, 0xf6, 0x01 },
383 { 370000000, 62500, 0xbe, 0x02 },
384 { 450000000, 62500, 0xf6, 0x02 },
385 { 466000000, 62500, 0xfe, 0x02 },
386 { 538000000, 62500, 0xbe, 0x08 },
387 { 826000000, 62500, 0xf6, 0x08 },
388 { 999999999, 62500, 0xfe, 0x08 },
389 }
390};
391
346/* ----------------------------------------------------------- */ 392/* ----------------------------------------------------------- */
347 393
348static struct dvb_pll_desc *pll_list[] = { 394static struct dvb_pll_desc *pll_list[] = {
@@ -360,6 +406,7 @@ static struct dvb_pll_desc *pll_list[] = {
360 [DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv, 406 [DVB_PLL_SAMSUNG_TBMV] = &dvb_pll_samsung_tbmv,
361 [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261, 407 [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
362 [DVB_PLL_OPERA1] = &dvb_pll_opera1, 408 [DVB_PLL_OPERA1] = &dvb_pll_opera1,
409 [DVB_PLL_SAMSUNG_DTOS403IH102A] = &dvb_pll_samsung_dtos403ih102a,
363}; 410};
364 411
365/* ----------------------------------------------------------- */ 412/* ----------------------------------------------------------- */
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index 872ca29e7cf3..05239f579ccf 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -22,6 +22,7 @@
22#define DVB_PLL_SAMSUNG_TBMV 11 22#define DVB_PLL_SAMSUNG_TBMV 11
23#define DVB_PLL_PHILIPS_SD1878_TDA8261 12 23#define DVB_PLL_PHILIPS_SD1878_TDA8261 12
24#define DVB_PLL_OPERA1 13 24#define DVB_PLL_OPERA1 13
25#define DVB_PLL_SAMSUNG_DTOS403IH102A 14
25 26
26/** 27/**
27 * Attach a dvb-pll to the supplied frontend structure. 28 * Attach a dvb-pll to the supplied frontend structure.
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index f0195c8272f4..056387b41a8f 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -226,11 +226,16 @@ static int lgdt330x_init(struct dvb_frontend* fe)
226 0x4c, 0x14 226 0x4c, 0x14
227 }; 227 };
228 228
229 static u8 flip_lgdt3303_init_data[] = { 229 static u8 flip_1_lgdt3303_init_data[] = {
230 0x4c, 0x14, 230 0x4c, 0x14,
231 0x87, 0xf3 231 0x87, 0xf3
232 }; 232 };
233 233
234 static u8 flip_2_lgdt3303_init_data[] = {
235 0x4c, 0x14,
236 0x87, 0xda
237 };
238
234 struct lgdt330x_state* state = fe->demodulator_priv; 239 struct lgdt330x_state* state = fe->demodulator_priv;
235 char *chip_name; 240 char *chip_name;
236 int err; 241 int err;
@@ -243,10 +248,19 @@ static int lgdt330x_init(struct dvb_frontend* fe)
243 break; 248 break;
244 case LGDT3303: 249 case LGDT3303:
245 chip_name = "LGDT3303"; 250 chip_name = "LGDT3303";
246 if (state->config->clock_polarity_flip) { 251 switch (state->config->clock_polarity_flip) {
247 err = i2c_write_demod_bytes(state, flip_lgdt3303_init_data, 252 case 2:
248 sizeof(flip_lgdt3303_init_data)); 253 err = i2c_write_demod_bytes(state,
249 } else { 254 flip_2_lgdt3303_init_data,
255 sizeof(flip_2_lgdt3303_init_data));
256 break;
257 case 1:
258 err = i2c_write_demod_bytes(state,
259 flip_1_lgdt3303_init_data,
260 sizeof(flip_1_lgdt3303_init_data));
261 break;
262 case 0:
263 default:
250 err = i2c_write_demod_bytes(state, lgdt3303_init_data, 264 err = i2c_write_demod_bytes(state, lgdt3303_init_data,
251 sizeof(lgdt3303_init_data)); 265 sizeof(lgdt3303_init_data));
252 } 266 }
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
index b999ec424ff7..5ddb2dca305c 100644
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ b/drivers/media/dvb/frontends/s5h1409.c
@@ -26,7 +26,6 @@
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include "dvb_frontend.h" 28#include "dvb_frontend.h"
29#include "dvb-pll.h"
30#include "s5h1409.h" 29#include "s5h1409.h"
31 30
32struct s5h1409_state { 31struct s5h1409_state {
diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
index eb5bfc99d4e9..cff360ce1ba3 100644
--- a/drivers/media/dvb/frontends/s5h1411.c
+++ b/drivers/media/dvb/frontends/s5h1411.c
@@ -26,7 +26,6 @@
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include "dvb_frontend.h" 28#include "dvb_frontend.h"
29#include "dvb-pll.h"
30#include "s5h1411.h" 29#include "s5h1411.h"
31 30
32struct s5h1411_state { 31struct s5h1411_state {
diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c
index c6ff5b82ff80..a3c34eecdee9 100644
--- a/drivers/media/dvb/frontends/tda10023.c
+++ b/drivers/media/dvb/frontends/tda10023.c
@@ -38,75 +38,29 @@
38#include "dvb_frontend.h" 38#include "dvb_frontend.h"
39#include "tda1002x.h" 39#include "tda1002x.h"
40 40
41#define REG0_INIT_VAL 0x23
41 42
42struct tda10023_state { 43struct tda10023_state {
43 struct i2c_adapter* i2c; 44 struct i2c_adapter* i2c;
44 /* configuration settings */ 45 /* configuration settings */
45 const struct tda1002x_config* config; 46 const struct tda10023_config *config;
46 struct dvb_frontend frontend; 47 struct dvb_frontend frontend;
47 48
48 u8 pwm; 49 u8 pwm;
49 u8 reg0; 50 u8 reg0;
50};
51 51
52 /* clock settings */
53 u32 xtal;
54 u8 pll_m;
55 u8 pll_p;
56 u8 pll_n;
57 u32 sysclk;
58};
52 59
53#define dprintk(x...) 60#define dprintk(x...)
54 61
55static int verbose; 62static int verbose;
56 63
57#define XTAL 28920000UL
58#define PLL_M 8UL
59#define PLL_P 4UL
60#define PLL_N 1UL
61#define SYSCLK (XTAL*PLL_M/(PLL_N*PLL_P)) // -> 57840000
62
63static u8 tda10023_inittab[]={
64 // reg mask val
65 0x2a,0xff,0x02, // PLL3, Bypass, Power Down
66 0xff,0x64,0x00, // Sleep 100ms
67 0x2a,0xff,0x03, // PLL3, Bypass, Power Down
68 0xff,0x64,0x00, // Sleep 100ms
69 0x28,0xff,PLL_M-1, // PLL1 M=8
70 0x29,0xff,((PLL_P-1)<<6)|(PLL_N-1), // PLL2
71 0x00,0xff,0x23, // GPR FSAMPLING=1
72 0x2a,0xff,0x08, // PLL3 PSACLK=1
73 0xff,0x64,0x00, // Sleep 100ms
74 0x1f,0xff,0x00, // RESET
75 0xff,0x64,0x00, // Sleep 100ms
76 0xe6,0x0c,0x04, // RSCFG_IND
77 0x10,0xc0,0x80, // DECDVBCFG1 PBER=1
78
79 0x0e,0xff,0x82, // GAIN1
80 0x03,0x08,0x08, // CLKCONF DYN=1
81 0x2e,0xbf,0x30, // AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1 PPWMTUN=0 PPWMIF=0
82 0x01,0xff,0x30, // AGCREF
83 0x1e,0x84,0x84, // CONTROL SACLK_ON=1
84 0x1b,0xff,0xc8, // ADC TWOS=1
85 0x3b,0xff,0xff, // IFMAX
86 0x3c,0xff,0x00, // IFMIN
87 0x34,0xff,0x00, // PWMREF
88 0x35,0xff,0xff, // TUNMAX
89 0x36,0xff,0x00, // TUNMIN
90 0x06,0xff,0x7f, // EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 // 0x77
91 0x1c,0x30,0x30, // EQCONF2 STEPALGO=SGNALGO=1
92 0x37,0xff,0xf6, // DELTAF_LSB
93 0x38,0xff,0xff, // DELTAF_MSB
94 0x02,0xff,0x93, // AGCCONF1 IFS=1 KAGCIF=2 KAGCTUN=3
95 0x2d,0xff,0xf6, // SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2
96 0x04,0x10,0x00, // SWRAMP=1
97 0x12,0xff,0xa1, // INTP1 POCLKP=1 FEL=1 MFS=0
98 0x2b,0x01,0xa1, // INTS1
99 0x20,0xff,0x04, // INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=?
100 0x2c,0xff,0x0d, // INTP/S TRIP=0 TRIS=0
101 0xc4,0xff,0x00,
102 0xc3,0x30,0x00,
103 0xb5,0xff,0x19, // ERAGC_THD
104 0x00,0x03,0x01, // GPR, CLBS soft reset
105 0x00,0x03,0x03, // GPR, CLBS soft reset
106 0xff,0x64,0x00, // Sleep 100ms
107 0xff,0xff,0xff
108};
109
110static u8 tda10023_readreg (struct tda10023_state* state, u8 reg) 64static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
111{ 65{
112 u8 b0 [] = { reg }; 66 u8 b0 [] = { reg };
@@ -219,30 +173,34 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
219 s16 SFIL=0; 173 s16 SFIL=0;
220 u16 NDEC = 0; 174 u16 NDEC = 0;
221 175
222 if (sr < (u32)(SYSCLK/98.40)) { 176 /* avoid floating point operations multiplying syscloc and divider
177 by 10 */
178 u32 sysclk_x_10 = state->sysclk * 10;
179
180 if (sr < (u32)(sysclk_x_10/984)) {
223 NDEC=3; 181 NDEC=3;
224 SFIL=1; 182 SFIL=1;
225 } else if (sr<(u32)(SYSCLK/64.0)) { 183 } else if (sr < (u32)(sysclk_x_10/640)) {
226 NDEC=3; 184 NDEC=3;
227 SFIL=0; 185 SFIL=0;
228 } else if (sr<(u32)(SYSCLK/49.2)) { 186 } else if (sr < (u32)(sysclk_x_10/492)) {
229 NDEC=2; 187 NDEC=2;
230 SFIL=1; 188 SFIL=1;
231 } else if (sr<(u32)(SYSCLK/32.0)) { 189 } else if (sr < (u32)(sysclk_x_10/320)) {
232 NDEC=2; 190 NDEC=2;
233 SFIL=0; 191 SFIL=0;
234 } else if (sr<(u32)(SYSCLK/24.6)) { 192 } else if (sr < (u32)(sysclk_x_10/246)) {
235 NDEC=1; 193 NDEC=1;
236 SFIL=1; 194 SFIL=1;
237 } else if (sr<(u32)(SYSCLK/16.0)) { 195 } else if (sr < (u32)(sysclk_x_10/160)) {
238 NDEC=1; 196 NDEC=1;
239 SFIL=0; 197 SFIL=0;
240 } else if (sr<(u32)(SYSCLK/12.3)) { 198 } else if (sr < (u32)(sysclk_x_10/123)) {
241 NDEC=0; 199 NDEC=0;
242 SFIL=1; 200 SFIL=1;
243 } 201 }
244 202
245 BDRI=SYSCLK*16; 203 BDRI = (state->sysclk)*16;
246 BDRI>>=NDEC; 204 BDRI>>=NDEC;
247 BDRI +=sr/2; 205 BDRI +=sr/2;
248 BDRI /=sr; 206 BDRI /=sr;
@@ -255,11 +213,12 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
255 213
256 BDRX=1<<(24+NDEC); 214 BDRX=1<<(24+NDEC);
257 BDRX*=sr; 215 BDRX*=sr;
258 do_div(BDRX,SYSCLK); // BDRX/=SYSCLK; 216 do_div(BDRX, state->sysclk); /* BDRX/=SYSCLK; */
259 217
260 BDR=(s32)BDRX; 218 BDR=(s32)BDRX;
261 } 219 }
262// printk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",sr,BDR,BDRI,NDEC); 220 dprintk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",
221 sr, BDR, BDRI, NDEC);
263 tda10023_writebit (state, 0x03, 0xc0, NDEC<<6); 222 tda10023_writebit (state, 0x03, 0xc0, NDEC<<6);
264 tda10023_writereg (state, 0x0a, BDR&255); 223 tda10023_writereg (state, 0x0a, BDR&255);
265 tda10023_writereg (state, 0x0b, (BDR>>8)&255); 224 tda10023_writereg (state, 0x0b, (BDR>>8)&255);
@@ -272,8 +231,67 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
272static int tda10023_init (struct dvb_frontend *fe) 231static int tda10023_init (struct dvb_frontend *fe)
273{ 232{
274 struct tda10023_state* state = fe->demodulator_priv; 233 struct tda10023_state* state = fe->demodulator_priv;
234 u8 tda10023_inittab[] = {
235/* reg mask val */
236/* 000 */ 0x2a, 0xff, 0x02, /* PLL3, Bypass, Power Down */
237/* 003 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
238/* 006 */ 0x2a, 0xff, 0x03, /* PLL3, Bypass, Power Down */
239/* 009 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
240 /* PLL1 */
241/* 012 */ 0x28, 0xff, (state->pll_m-1),
242 /* PLL2 */
243/* 015 */ 0x29, 0xff, ((state->pll_p-1)<<6)|(state->pll_n-1),
244 /* GPR FSAMPLING=1 */
245/* 018 */ 0x00, 0xff, REG0_INIT_VAL,
246/* 021 */ 0x2a, 0xff, 0x08, /* PLL3 PSACLK=1 */
247/* 024 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
248/* 027 */ 0x1f, 0xff, 0x00, /* RESET */
249/* 030 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
250/* 033 */ 0xe6, 0x0c, 0x04, /* RSCFG_IND */
251/* 036 */ 0x10, 0xc0, 0x80, /* DECDVBCFG1 PBER=1 */
252
253/* 039 */ 0x0e, 0xff, 0x82, /* GAIN1 */
254/* 042 */ 0x03, 0x08, 0x08, /* CLKCONF DYN=1 */
255/* 045 */ 0x2e, 0xbf, 0x30, /* AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1
256 PPWMTUN=0 PPWMIF=0 */
257/* 048 */ 0x01, 0xff, 0x30, /* AGCREF */
258/* 051 */ 0x1e, 0x84, 0x84, /* CONTROL SACLK_ON=1 */
259/* 054 */ 0x1b, 0xff, 0xc8, /* ADC TWOS=1 */
260/* 057 */ 0x3b, 0xff, 0xff, /* IFMAX */
261/* 060 */ 0x3c, 0xff, 0x00, /* IFMIN */
262/* 063 */ 0x34, 0xff, 0x00, /* PWMREF */
263/* 066 */ 0x35, 0xff, 0xff, /* TUNMAX */
264/* 069 */ 0x36, 0xff, 0x00, /* TUNMIN */
265/* 072 */ 0x06, 0xff, 0x7f, /* EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 */
266/* 075 */ 0x1c, 0x30, 0x30, /* EQCONF2 STEPALGO=SGNALGO=1 */
267/* 078 */ 0x37, 0xff, 0xf6, /* DELTAF_LSB */
268/* 081 */ 0x38, 0xff, 0xff, /* DELTAF_MSB */
269/* 084 */ 0x02, 0xff, 0x93, /* AGCCONF1 IFS=1 KAGCIF=2 KAGCTUN=3 */
270/* 087 */ 0x2d, 0xff, 0xf6, /* SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2 */
271/* 090 */ 0x04, 0x10, 0x00, /* SWRAMP=1 */
272/* 093 */ 0x12, 0xff, TDA10023_OUTPUT_MODE_PARALLEL_B, /*
273 INTP1 POCLKP=1 FEL=1 MFS=0 */
274/* 096 */ 0x2b, 0x01, 0xa1, /* INTS1 */
275/* 099 */ 0x20, 0xff, 0x04, /* INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=? */
276/* 102 */ 0x2c, 0xff, 0x0d, /* INTP/S TRIP=0 TRIS=0 */
277/* 105 */ 0xc4, 0xff, 0x00,
278/* 108 */ 0xc3, 0x30, 0x00,
279/* 111 */ 0xb5, 0xff, 0x19, /* ERAGC_THD */
280/* 114 */ 0x00, 0x03, 0x01, /* GPR, CLBS soft reset */
281/* 117 */ 0x00, 0x03, 0x03, /* GPR, CLBS soft reset */
282/* 120 */ 0xff, 0x64, 0x00, /* Sleep 100ms */
283/* 123 */ 0xff, 0xff, 0xff
284};
285 dprintk("DVB: TDA10023(%d): init chip\n", fe->dvb->num);
286
287 /* override default values if set in config */
288 if (state->config->deltaf) {
289 tda10023_inittab[80] = (state->config->deltaf & 0xff);
290 tda10023_inittab[83] = (state->config->deltaf >> 8);
291 }
275 292
276 dprintk("DVB: TDA10023(%d): init chip\n", fe->adapter->num); 293 if (state->config->output_mode)
294 tda10023_inittab[95] = state->config->output_mode;
277 295
278 tda10023_writetab(state, tda10023_inittab); 296 tda10023_writetab(state, tda10023_inittab);
279 297
@@ -460,12 +478,11 @@ static void tda10023_release(struct dvb_frontend* fe)
460 478
461static struct dvb_frontend_ops tda10023_ops; 479static struct dvb_frontend_ops tda10023_ops;
462 480
463struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config, 481struct dvb_frontend *tda10023_attach(const struct tda10023_config *config,
464 struct i2c_adapter* i2c, 482 struct i2c_adapter *i2c,
465 u8 pwm) 483 u8 pwm)
466{ 484{
467 struct tda10023_state* state = NULL; 485 struct tda10023_state* state = NULL;
468 int i;
469 486
470 /* allocate memory for the internal state */ 487 /* allocate memory for the internal state */
471 state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL); 488 state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL);
@@ -474,22 +491,40 @@ struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
474 /* setup the state */ 491 /* setup the state */
475 state->config = config; 492 state->config = config;
476 state->i2c = i2c; 493 state->i2c = i2c;
477 memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
478 state->pwm = pwm;
479 for (i=0; i < ARRAY_SIZE(tda10023_inittab);i+=3) {
480 if (tda10023_inittab[i] == 0x00) {
481 state->reg0 = tda10023_inittab[i+2];
482 break;
483 }
484 }
485 494
486 // Wakeup if in standby 495 /* wakeup if in standby */
487 tda10023_writereg (state, 0x00, 0x33); 496 tda10023_writereg (state, 0x00, 0x33);
488 /* check if the demod is there */ 497 /* check if the demod is there */
489 if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error; 498 if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
490 499
491 /* create dvb_frontend */ 500 /* create dvb_frontend */
492 memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops)); 501 memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
502 state->pwm = pwm;
503 state->reg0 = REG0_INIT_VAL;
504 if (state->config->xtal) {
505 state->xtal = state->config->xtal;
506 state->pll_m = state->config->pll_m;
507 state->pll_p = state->config->pll_p;
508 state->pll_n = state->config->pll_n;
509 } else {
510 /* set default values if not defined in config */
511 state->xtal = 28920000;
512 state->pll_m = 8;
513 state->pll_p = 4;
514 state->pll_n = 1;
515 }
516
517 /* calc sysclk */
518 state->sysclk = (state->xtal * state->pll_m / \
519 (state->pll_n * state->pll_p));
520
521 state->frontend.ops.info.symbol_rate_min = (state->sysclk/2)/64;
522 state->frontend.ops.info.symbol_rate_max = (state->sysclk/2)/4;
523
524 dprintk("DVB: TDA10023 %s: xtal:%d pll_m:%d pll_p:%d pll_n:%d\n",
525 __func__, state->xtal, state->pll_m, state->pll_p,
526 state->pll_n);
527
493 state->frontend.demodulator_priv = state; 528 state->frontend.demodulator_priv = state;
494 return &state->frontend; 529 return &state->frontend;
495 530
@@ -504,10 +539,10 @@ static struct dvb_frontend_ops tda10023_ops = {
504 .name = "Philips TDA10023 DVB-C", 539 .name = "Philips TDA10023 DVB-C",
505 .type = FE_QAM, 540 .type = FE_QAM,
506 .frequency_stepsize = 62500, 541 .frequency_stepsize = 62500,
507 .frequency_min = 47000000, 542 .frequency_min = 47000000,
508 .frequency_max = 862000000, 543 .frequency_max = 862000000,
509 .symbol_rate_min = (SYSCLK/2)/64, /* SACLK/64 == (SYSCLK/2)/64 */ 544 .symbol_rate_min = 0, /* set in tda10023_attach */
510 .symbol_rate_max = (SYSCLK/2)/4, /* SACLK/4 */ 545 .symbol_rate_max = 0, /* set in tda10023_attach */
511 .caps = 0x400 | //FE_CAN_QAM_4 546 .caps = 0x400 | //FE_CAN_QAM_4
512 FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | 547 FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
513 FE_CAN_QAM_128 | FE_CAN_QAM_256 | 548 FE_CAN_QAM_128 | FE_CAN_QAM_256 |
diff --git a/drivers/media/dvb/frontends/tda1002x.h b/drivers/media/dvb/frontends/tda1002x.h
index 1bcc0d44b90b..04d19418bf20 100644
--- a/drivers/media/dvb/frontends/tda1002x.h
+++ b/drivers/media/dvb/frontends/tda1002x.h
@@ -26,13 +26,37 @@
26 26
27#include <linux/dvb/frontend.h> 27#include <linux/dvb/frontend.h>
28 28
29struct tda1002x_config 29struct tda1002x_config {
30{
31 /* the demodulator's i2c address */ 30 /* the demodulator's i2c address */
32 u8 demod_address; 31 u8 demod_address;
33 u8 invert; 32 u8 invert;
34}; 33};
35 34
35enum tda10023_output_mode {
36 TDA10023_OUTPUT_MODE_PARALLEL_A = 0xe0,
37 TDA10023_OUTPUT_MODE_PARALLEL_B = 0xa1,
38 TDA10023_OUTPUT_MODE_PARALLEL_C = 0xa0,
39 TDA10023_OUTPUT_MODE_SERIAL, /* TODO: not implemented */
40};
41
42struct tda10023_config {
43 /* the demodulator's i2c address */
44 u8 demod_address;
45 u8 invert;
46
47 /* clock settings */
48 u32 xtal; /* defaults: 28920000 */
49 u8 pll_m; /* defaults: 8 */
50 u8 pll_p; /* defaults: 4 */
51 u8 pll_n; /* defaults: 1 */
52
53 /* MPEG2 TS output mode */
54 u8 output_mode;
55
56 /* input freq offset + baseband conversion type */
57 u16 deltaf;
58};
59
36#if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE)) 60#if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE))
37extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, 61extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
38 struct i2c_adapter* i2c, u8 pwm); 62 struct i2c_adapter* i2c, u8 pwm);
@@ -45,12 +69,15 @@ static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config*
45} 69}
46#endif // CONFIG_DVB_TDA10021 70#endif // CONFIG_DVB_TDA10021
47 71
48#if defined(CONFIG_DVB_TDA10023) || (defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE)) 72#if defined(CONFIG_DVB_TDA10023) || \
49extern struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config, 73 (defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE))
50 struct i2c_adapter* i2c, u8 pwm); 74extern struct dvb_frontend *tda10023_attach(
75 const struct tda10023_config *config,
76 struct i2c_adapter *i2c, u8 pwm);
51#else 77#else
52static inline struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config, 78static inline struct dvb_frontend *tda10023_attach(
53 struct i2c_adapter* i2c, u8 pwm) 79 const struct tda10023_config *config,
80 struct i2c_adapter *i2c, u8 pwm)
54{ 81{
55 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); 82 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
56 return NULL; 83 return NULL;
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 960ed5763ae1..1360403b88b6 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -234,7 +234,7 @@ static void pluto_reset_ts(struct pluto *pluto, int reenable)
234 234
235static void pluto_set_dma_addr(struct pluto *pluto) 235static void pluto_set_dma_addr(struct pluto *pluto)
236{ 236{
237 pluto_writereg(pluto, REG_PCAR, cpu_to_le32(pluto->dma_addr)); 237 pluto_writereg(pluto, REG_PCAR, pluto->dma_addr);
238} 238}
239 239
240static int __devinit pluto_dma_map(struct pluto *pluto) 240static int __devinit pluto_dma_map(struct pluto *pluto)
diff --git a/drivers/media/dvb/siano/Kconfig b/drivers/media/dvb/siano/Kconfig
new file mode 100644
index 000000000000..dd863f261672
--- /dev/null
+++ b/drivers/media/dvb/siano/Kconfig
@@ -0,0 +1,26 @@
1#
2# Siano Mobile Silicon Digital TV device configuration
3#
4
5config DVB_SIANO_SMS1XXX
6 tristate "Siano SMS1XXX USB dongle support"
7 depends on DVB_CORE && USB
8 ---help---
9 Choose Y here if you have a USB dongle with a SMS1XXX chipset.
10
11 To compile this driver as a module, choose M here: the
12 module will be called sms1xxx.
13
14config DVB_SIANO_SMS1XXX_SMS_IDS
15 bool "Enable support for Siano Mobile Silicon default USB IDs"
16 depends on DVB_SIANO_SMS1XXX
17 default y
18 ---help---
19 Choose Y here if you have a USB dongle with a SMS1XXX chipset
20 that uses Siano Mobile Silicon's default usb vid:pid.
21
22 Choose N here if you would prefer to use Siano's external driver.
23
24 Further documentation on this driver can be found on the WWW at
25 <http://www.siano-ms.com/>.
26
diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile
new file mode 100644
index 000000000000..ee0737af98c0
--- /dev/null
+++ b/drivers/media/dvb/siano/Makefile
@@ -0,0 +1,8 @@
1sms1xxx-objs := smscoreapi.o smsusb.o smsdvb.o sms-cards.o
2
3obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o
4
5EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
6
7EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
8
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
new file mode 100644
index 000000000000..e7a8ac0c4049
--- /dev/null
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -0,0 +1,102 @@
1/*
2 * Card-specific functions for the Siano SMS1xxx USB dongle
3 *
4 * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation;
9 *
10 * Software distributed under the License is distributed on an "AS IS"
11 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
12 *
13 * See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include "sms-cards.h"
21
22struct usb_device_id smsusb_id_table[] = {
23#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS
24 { USB_DEVICE(0x187f, 0x0010),
25 .driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
26 { USB_DEVICE(0x187f, 0x0100),
27 .driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
28 { USB_DEVICE(0x187f, 0x0200),
29 .driver_info = SMS1XXX_BOARD_SIANO_NOVA_A },
30 { USB_DEVICE(0x187f, 0x0201),
31 .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B },
32 { USB_DEVICE(0x187f, 0x0300),
33 .driver_info = SMS1XXX_BOARD_SIANO_VEGA },
34#endif
35 { USB_DEVICE(0x2040, 0x1700),
36 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT },
37 { USB_DEVICE(0x2040, 0x1800),
38 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A },
39 { USB_DEVICE(0x2040, 0x1801),
40 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
41 { USB_DEVICE(0x2040, 0x5500),
42 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
43 { USB_DEVICE(0x2040, 0x5580),
44 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
45 { USB_DEVICE(0x2040, 0x5590),
46 .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
47 { } /* Terminating entry */
48};
49MODULE_DEVICE_TABLE(usb, smsusb_id_table);
50
51static struct sms_board sms_boards[] = {
52 [SMS_BOARD_UNKNOWN] = {
53 .name = "Unknown board",
54 },
55 [SMS1XXX_BOARD_SIANO_STELLAR] = {
56 .name = "Siano Stellar Digital Receiver",
57 .type = SMS_STELLAR,
58 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
59 },
60 [SMS1XXX_BOARD_SIANO_NOVA_A] = {
61 .name = "Siano Nova A Digital Receiver",
62 .type = SMS_NOVA_A0,
63 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
64 },
65 [SMS1XXX_BOARD_SIANO_NOVA_B] = {
66 .name = "Siano Nova B Digital Receiver",
67 .type = SMS_NOVA_B0,
68 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
69 },
70 [SMS1XXX_BOARD_SIANO_VEGA] = {
71 .name = "Siano Vega Digital Receiver",
72 .type = SMS_VEGA,
73 },
74 [SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = {
75 .name = "Hauppauge Catamount",
76 .type = SMS_STELLAR,
77 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
78 },
79 [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = {
80 .name = "Hauppauge Okemo-A",
81 .type = SMS_NOVA_A0,
82 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
83 },
84 [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = {
85 .name = "Hauppauge Okemo-B",
86 .type = SMS_NOVA_B0,
87 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
88 },
89 [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
90 .name = "Hauppauge WinTV-Nova-T-MiniStick",
91 .type = SMS_NOVA_B0,
92 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",
93 },
94};
95
96struct sms_board *sms_get_board(int id)
97{
98 BUG_ON(id >= ARRAY_SIZE(sms_boards));
99
100 return &sms_boards[id];
101}
102
diff --git a/drivers/media/dvb/siano/sms-cards.h b/drivers/media/dvb/siano/sms-cards.h
new file mode 100644
index 000000000000..83b39bc203fe
--- /dev/null
+++ b/drivers/media/dvb/siano/sms-cards.h
@@ -0,0 +1,45 @@
1/*
2 * Card-specific functions for the Siano SMS1xxx USB dongle
3 *
4 * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation;
9 *
10 * Software distributed under the License is distributed on an "AS IS"
11 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
12 *
13 * See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef __SMS_CARDS_H__
21#define __SMS_CARDS_H__
22
23#include <linux/usb.h>
24#include "smscoreapi.h"
25
26#define SMS_BOARD_UNKNOWN 0
27#define SMS1XXX_BOARD_SIANO_STELLAR 1
28#define SMS1XXX_BOARD_SIANO_NOVA_A 2
29#define SMS1XXX_BOARD_SIANO_NOVA_B 3
30#define SMS1XXX_BOARD_SIANO_VEGA 4
31#define SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT 5
32#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A 6
33#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B 7
34#define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8
35
36struct sms_board {
37 enum sms_device_type_st type;
38 char *name, *fw[DEVICE_MODE_MAX];
39};
40
41struct sms_board *sms_get_board(int id);
42
43extern struct usb_device_id smsusb_id_table[];
44
45#endif /* __SMS_CARDS_H__ */
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
new file mode 100644
index 000000000000..b4b8ed795c95
--- /dev/null
+++ b/drivers/media/dvb/siano/smscoreapi.c
@@ -0,0 +1,1251 @@
1/*
2 * Siano core API module
3 *
4 * This file contains implementation for the interface to sms core component
5 *
6 * author: Anatoly Greenblat
7 *
8 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 3 as
12 * published by the Free Software Foundation;
13 *
14 * Software distributed under the License is distributed on an "AS IS"
15 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
16 *
17 * See the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/kernel.h>
25#include <linux/init.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/dma-mapping.h>
29#include <linux/delay.h>
30#include <linux/io.h>
31
32#include <linux/firmware.h>
33
34#include "smscoreapi.h"
35#include "sms-cards.h"
36
37int sms_debug;
38module_param_named(debug, sms_debug, int, 0644);
39MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
40
41struct smscore_device_notifyee_t {
42 struct list_head entry;
43 hotplug_t hotplug;
44};
45
46struct smscore_idlist_t {
47 struct list_head entry;
48 int id;
49 int data_type;
50};
51
52struct smscore_client_t {
53 struct list_head entry;
54 struct smscore_device_t *coredev;
55 void *context;
56 struct list_head idlist;
57 onresponse_t onresponse_handler;
58 onremove_t onremove_handler;
59};
60
61struct smscore_device_t {
62 struct list_head entry;
63
64 struct list_head clients;
65 struct list_head subclients;
66 spinlock_t clientslock;
67
68 struct list_head buffers;
69 spinlock_t bufferslock;
70 int num_buffers;
71
72 void *common_buffer;
73 int common_buffer_size;
74 dma_addr_t common_buffer_phys;
75
76 void *context;
77 struct device *device;
78
79 char devpath[32];
80 unsigned long device_flags;
81
82 setmode_t setmode_handler;
83 detectmode_t detectmode_handler;
84 sendrequest_t sendrequest_handler;
85 preload_t preload_handler;
86 postload_t postload_handler;
87
88 int mode, modes_supported;
89
90 struct completion version_ex_done, data_download_done, trigger_done;
91 struct completion init_device_done, reload_start_done, resume_done;
92
93 int board_id;
94};
95
96void smscore_set_board_id(struct smscore_device_t *core, int id)
97{
98 core->board_id = id;
99}
100
101int smscore_get_board_id(struct smscore_device_t *core)
102{
103 return core->board_id;
104}
105
106struct smscore_registry_entry_t {
107 struct list_head entry;
108 char devpath[32];
109 int mode;
110 enum sms_device_type_st type;
111};
112
113struct list_head g_smscore_notifyees;
114struct list_head g_smscore_devices;
115struct mutex g_smscore_deviceslock;
116
117struct list_head g_smscore_registry;
118struct mutex g_smscore_registrylock;
119
120static int default_mode = 4;
121
122module_param(default_mode, int, 0644);
123MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
124
125static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
126{
127 struct smscore_registry_entry_t *entry;
128 struct list_head *next;
129
130 kmutex_lock(&g_smscore_registrylock);
131 for (next = g_smscore_registry.next;
132 next != &g_smscore_registry;
133 next = next->next) {
134 entry = (struct smscore_registry_entry_t *) next;
135 if (!strcmp(entry->devpath, devpath)) {
136 kmutex_unlock(&g_smscore_registrylock);
137 return entry;
138 }
139 }
140 entry = (struct smscore_registry_entry_t *)
141 kmalloc(sizeof(struct smscore_registry_entry_t),
142 GFP_KERNEL);
143 if (entry) {
144 entry->mode = default_mode;
145 strcpy(entry->devpath, devpath);
146 list_add(&entry->entry, &g_smscore_registry);
147 } else
148 sms_err("failed to create smscore_registry.");
149 kmutex_unlock(&g_smscore_registrylock);
150 return entry;
151}
152
153int smscore_registry_getmode(char *devpath)
154{
155 struct smscore_registry_entry_t *entry;
156
157 entry = smscore_find_registry(devpath);
158 if (entry)
159 return entry->mode;
160 else
161 sms_err("No registry found.");
162
163 return default_mode;
164}
165
166static enum sms_device_type_st smscore_registry_gettype(char *devpath)
167{
168 struct smscore_registry_entry_t *entry;
169
170 entry = smscore_find_registry(devpath);
171 if (entry)
172 return entry->type;
173 else
174 sms_err("No registry found.");
175
176 return -1;
177}
178
179void smscore_registry_setmode(char *devpath, int mode)
180{
181 struct smscore_registry_entry_t *entry;
182
183 entry = smscore_find_registry(devpath);
184 if (entry)
185 entry->mode = mode;
186 else
187 sms_err("No registry found.");
188}
189
190static void smscore_registry_settype(char *devpath,
191 enum sms_device_type_st type)
192{
193 struct smscore_registry_entry_t *entry;
194
195 entry = smscore_find_registry(devpath);
196 if (entry)
197 entry->type = type;
198 else
199 sms_err("No registry found.");
200}
201
202
203static void list_add_locked(struct list_head *new, struct list_head *head,
204 spinlock_t *lock)
205{
206 unsigned long flags;
207
208 spin_lock_irqsave(lock, flags);
209
210 list_add(new, head);
211
212 spin_unlock_irqrestore(lock, flags);
213}
214
215/**
216 * register a client callback that called when device plugged in/unplugged
217 * NOTE: if devices exist callback is called immediately for each device
218 *
219 * @param hotplug callback
220 *
221 * @return 0 on success, <0 on error.
222 */
223int smscore_register_hotplug(hotplug_t hotplug)
224{
225 struct smscore_device_notifyee_t *notifyee;
226 struct list_head *next, *first;
227 int rc = 0;
228
229 kmutex_lock(&g_smscore_deviceslock);
230
231 notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
232 GFP_KERNEL);
233 if (notifyee) {
234 /* now notify callback about existing devices */
235 first = &g_smscore_devices;
236 for (next = first->next;
237 next != first && !rc;
238 next = next->next) {
239 struct smscore_device_t *coredev =
240 (struct smscore_device_t *) next;
241 rc = hotplug(coredev, coredev->device, 1);
242 }
243
244 if (rc >= 0) {
245 notifyee->hotplug = hotplug;
246 list_add(&notifyee->entry, &g_smscore_notifyees);
247 } else
248 kfree(notifyee);
249 } else
250 rc = -ENOMEM;
251
252 kmutex_unlock(&g_smscore_deviceslock);
253
254 return rc;
255}
256
257/**
258 * unregister a client callback that called when device plugged in/unplugged
259 *
260 * @param hotplug callback
261 *
262 */
263void smscore_unregister_hotplug(hotplug_t hotplug)
264{
265 struct list_head *next, *first;
266
267 kmutex_lock(&g_smscore_deviceslock);
268
269 first = &g_smscore_notifyees;
270
271 for (next = first->next; next != first;) {
272 struct smscore_device_notifyee_t *notifyee =
273 (struct smscore_device_notifyee_t *) next;
274 next = next->next;
275
276 if (notifyee->hotplug == hotplug) {
277 list_del(&notifyee->entry);
278 kfree(notifyee);
279 }
280 }
281
282 kmutex_unlock(&g_smscore_deviceslock);
283}
284
285static void smscore_notify_clients(struct smscore_device_t *coredev)
286{
287 struct smscore_client_t *client;
288
289 /* the client must call smscore_unregister_client from remove handler */
290 while (!list_empty(&coredev->clients)) {
291 client = (struct smscore_client_t *) coredev->clients.next;
292 client->onremove_handler(client->context);
293 }
294}
295
296static int smscore_notify_callbacks(struct smscore_device_t *coredev,
297 struct device *device, int arrival)
298{
299 struct list_head *next, *first;
300 int rc = 0;
301
302 /* note: must be called under g_deviceslock */
303
304 first = &g_smscore_notifyees;
305
306 for (next = first->next; next != first; next = next->next) {
307 rc = ((struct smscore_device_notifyee_t *) next)->
308 hotplug(coredev, device, arrival);
309 if (rc < 0)
310 break;
311 }
312
313 return rc;
314}
315
316static struct
317smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
318 dma_addr_t common_buffer_phys)
319{
320 struct smscore_buffer_t *cb =
321 kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
322 if (!cb) {
323 sms_info("kmalloc(...) failed");
324 return NULL;
325 }
326
327 cb->p = buffer;
328 cb->offset_in_common = buffer - (u8 *) common_buffer;
329 cb->phys = common_buffer_phys + cb->offset_in_common;
330
331 return cb;
332}
333
334/**
335 * creates coredev object for a device, prepares buffers,
336 * creates buffer mappings, notifies registered hotplugs about new device.
337 *
338 * @param params device pointer to struct with device specific parameters
339 * and handlers
340 * @param coredev pointer to a value that receives created coredev object
341 *
342 * @return 0 on success, <0 on error.
343 */
344int smscore_register_device(struct smsdevice_params_t *params,
345 struct smscore_device_t **coredev)
346{
347 struct smscore_device_t *dev;
348 u8 *buffer;
349
350 dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
351 if (!dev) {
352 sms_info("kzalloc(...) failed");
353 return -ENOMEM;
354 }
355
356 /* init list entry so it could be safe in smscore_unregister_device */
357 INIT_LIST_HEAD(&dev->entry);
358
359 /* init queues */
360 INIT_LIST_HEAD(&dev->clients);
361 INIT_LIST_HEAD(&dev->buffers);
362
363 /* init locks */
364 spin_lock_init(&dev->clientslock);
365 spin_lock_init(&dev->bufferslock);
366
367 /* init completion events */
368 init_completion(&dev->version_ex_done);
369 init_completion(&dev->data_download_done);
370 init_completion(&dev->trigger_done);
371 init_completion(&dev->init_device_done);
372 init_completion(&dev->reload_start_done);
373 init_completion(&dev->resume_done);
374
375 /* alloc common buffer */
376 dev->common_buffer_size = params->buffer_size * params->num_buffers;
377 dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
378 &dev->common_buffer_phys,
379 GFP_KERNEL | GFP_DMA);
380 if (!dev->common_buffer) {
381 smscore_unregister_device(dev);
382 return -ENOMEM;
383 }
384
385 /* prepare dma buffers */
386 for (buffer = dev->common_buffer;
387 dev->num_buffers < params->num_buffers;
388 dev->num_buffers++, buffer += params->buffer_size) {
389 struct smscore_buffer_t *cb =
390 smscore_createbuffer(buffer, dev->common_buffer,
391 dev->common_buffer_phys);
392 if (!cb) {
393 smscore_unregister_device(dev);
394 return -ENOMEM;
395 }
396
397 smscore_putbuffer(dev, cb);
398 }
399
400 sms_info("allocated %d buffers", dev->num_buffers);
401
402 dev->mode = DEVICE_MODE_NONE;
403 dev->context = params->context;
404 dev->device = params->device;
405 dev->setmode_handler = params->setmode_handler;
406 dev->detectmode_handler = params->detectmode_handler;
407 dev->sendrequest_handler = params->sendrequest_handler;
408 dev->preload_handler = params->preload_handler;
409 dev->postload_handler = params->postload_handler;
410
411 dev->device_flags = params->flags;
412 strcpy(dev->devpath, params->devpath);
413
414 smscore_registry_settype(dev->devpath, params->device_type);
415
416 /* add device to devices list */
417 kmutex_lock(&g_smscore_deviceslock);
418 list_add(&dev->entry, &g_smscore_devices);
419 kmutex_unlock(&g_smscore_deviceslock);
420
421 *coredev = dev;
422
423 sms_info("device %p created", dev);
424
425 return 0;
426}
427
428/**
429 * sets initial device mode and notifies client hotplugs that device is ready
430 *
431 * @param coredev pointer to a coredev object returned by
432 * smscore_register_device
433 *
434 * @return 0 on success, <0 on error.
435 */
436int smscore_start_device(struct smscore_device_t *coredev)
437{
438 int rc = smscore_set_device_mode(
439 coredev, smscore_registry_getmode(coredev->devpath));
440 if (rc < 0) {
441 sms_info("set device mode faile , rc %d", rc);
442 return rc;
443 }
444
445 kmutex_lock(&g_smscore_deviceslock);
446
447 rc = smscore_notify_callbacks(coredev, coredev->device, 1);
448
449 sms_info("device %p started, rc %d", coredev, rc);
450
451 kmutex_unlock(&g_smscore_deviceslock);
452
453 return rc;
454}
455
456static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
457 void *buffer, size_t size,
458 struct completion *completion)
459{
460 int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
461 if (rc < 0) {
462 sms_info("sendrequest returned error %d", rc);
463 return rc;
464 }
465
466 return wait_for_completion_timeout(completion,
467 msecs_to_jiffies(10000)) ?
468 0 : -ETIME;
469}
470
471static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
472 void *buffer, size_t size)
473{
474 struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
475 struct SmsMsgHdr_ST *msg;
476 u32 mem_address = firmware->StartAddress;
477 u8 *payload = firmware->Payload;
478 int rc = 0;
479
480 sms_info("loading FW to addr 0x%x size %d",
481 mem_address, firmware->Length);
482 if (coredev->preload_handler) {
483 rc = coredev->preload_handler(coredev->context);
484 if (rc < 0)
485 return rc;
486 }
487
488 /* PAGE_SIZE buffer shall be enough and dma aligned */
489 msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
490 if (!msg)
491 return -ENOMEM;
492
493 if (coredev->mode != DEVICE_MODE_NONE) {
494 sms_debug("sending reload command.");
495 SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
496 sizeof(struct SmsMsgHdr_ST));
497 rc = smscore_sendrequest_and_wait(coredev, msg,
498 msg->msgLength,
499 &coredev->reload_start_done);
500 mem_address = *(u32 *) &payload[20];
501 }
502
503 while (size && rc >= 0) {
504 struct SmsDataDownload_ST *DataMsg =
505 (struct SmsDataDownload_ST *) msg;
506 int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
507
508 SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
509 (u16)(sizeof(struct SmsMsgHdr_ST) +
510 sizeof(u32) + payload_size));
511
512 DataMsg->MemAddr = mem_address;
513 memcpy(DataMsg->Payload, payload, payload_size);
514
515 if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
516 (coredev->mode == DEVICE_MODE_NONE))
517 rc = coredev->sendrequest_handler(
518 coredev->context, DataMsg,
519 DataMsg->xMsgHeader.msgLength);
520 else
521 rc = smscore_sendrequest_and_wait(
522 coredev, DataMsg,
523 DataMsg->xMsgHeader.msgLength,
524 &coredev->data_download_done);
525
526 payload += payload_size;
527 size -= payload_size;
528 mem_address += payload_size;
529 }
530
531 if (rc >= 0) {
532 if (coredev->mode == DEVICE_MODE_NONE) {
533 struct SmsMsgData_ST *TriggerMsg =
534 (struct SmsMsgData_ST *) msg;
535
536 SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
537 sizeof(struct SmsMsgHdr_ST) +
538 sizeof(u32) * 5);
539
540 TriggerMsg->msgData[0] = firmware->StartAddress;
541 /* Entry point */
542 TriggerMsg->msgData[1] = 5; /* Priority */
543 TriggerMsg->msgData[2] = 0x200; /* Stack size */
544 TriggerMsg->msgData[3] = 0; /* Parameter */
545 TriggerMsg->msgData[4] = 4; /* Task ID */
546
547 if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
548 rc = coredev->sendrequest_handler(
549 coredev->context, TriggerMsg,
550 TriggerMsg->xMsgHeader.msgLength);
551 msleep(100);
552 } else
553 rc = smscore_sendrequest_and_wait(
554 coredev, TriggerMsg,
555 TriggerMsg->xMsgHeader.msgLength,
556 &coredev->trigger_done);
557 } else {
558 SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
559 sizeof(struct SmsMsgHdr_ST));
560
561 rc = coredev->sendrequest_handler(coredev->context,
562 msg, msg->msgLength);
563 }
564 msleep(500);
565 }
566
567 sms_debug("rc=%d, postload=%p ", rc,
568 coredev->postload_handler);
569
570 kfree(msg);
571
572 return ((rc >= 0) && coredev->postload_handler) ?
573 coredev->postload_handler(coredev->context) :
574 rc;
575}
576
577/**
578 * loads specified firmware into a buffer and calls device loadfirmware_handler
579 *
580 * @param coredev pointer to a coredev object returned by
581 * smscore_register_device
582 * @param filename null-terminated string specifies firmware file name
583 * @param loadfirmware_handler device handler that loads firmware
584 *
585 * @return 0 on success, <0 on error.
586 */
587static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
588 char *filename,
589 loadfirmware_t loadfirmware_handler)
590{
591 int rc = -ENOENT;
592 const struct firmware *fw;
593 u8 *fw_buffer;
594
595 if (loadfirmware_handler == NULL && !(coredev->device_flags &
596 SMS_DEVICE_FAMILY2))
597 return -EINVAL;
598
599 rc = request_firmware(&fw, filename, coredev->device);
600 if (rc < 0) {
601 sms_info("failed to open \"%s\"", filename);
602 return rc;
603 }
604 sms_info("read FW %s, size=%zd", filename, fw->size);
605 fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
606 GFP_KERNEL | GFP_DMA);
607 if (fw_buffer) {
608 memcpy(fw_buffer, fw->data, fw->size);
609
610 rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
611 smscore_load_firmware_family2(coredev,
612 fw_buffer,
613 fw->size) :
614 loadfirmware_handler(coredev->context,
615 fw_buffer, fw->size);
616
617 kfree(fw_buffer);
618 } else {
619 sms_info("failed to allocate firmware buffer");
620 rc = -ENOMEM;
621 }
622
623 release_firmware(fw);
624
625 return rc;
626}
627
628/**
629 * notifies all clients registered with the device, notifies hotplugs,
630 * frees all buffers and coredev object
631 *
632 * @param coredev pointer to a coredev object returned by
633 * smscore_register_device
634 *
635 * @return 0 on success, <0 on error.
636 */
637void smscore_unregister_device(struct smscore_device_t *coredev)
638{
639 struct smscore_buffer_t *cb;
640 int num_buffers = 0;
641 int retry = 0;
642
643 kmutex_lock(&g_smscore_deviceslock);
644
645 smscore_notify_clients(coredev);
646 smscore_notify_callbacks(coredev, NULL, 0);
647
648 /* at this point all buffers should be back
649 * onresponse must no longer be called */
650
651 while (1) {
652 while ((cb = smscore_getbuffer(coredev))) {
653 kfree(cb);
654 num_buffers++;
655 }
656 if (num_buffers == coredev->num_buffers)
657 break;
658 if (++retry > 10) {
659 sms_info("exiting although "
660 "not all buffers released.");
661 break;
662 }
663
664 sms_info("waiting for %d buffer(s)",
665 coredev->num_buffers - num_buffers);
666 msleep(100);
667 }
668
669 sms_info("freed %d buffers", num_buffers);
670
671 if (coredev->common_buffer)
672 dma_free_coherent(NULL, coredev->common_buffer_size,
673 coredev->common_buffer,
674 coredev->common_buffer_phys);
675
676 list_del(&coredev->entry);
677 kfree(coredev);
678
679 kmutex_unlock(&g_smscore_deviceslock);
680
681 sms_info("device %p destroyed", coredev);
682}
683
684static int smscore_detect_mode(struct smscore_device_t *coredev)
685{
686 void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
687 GFP_KERNEL | GFP_DMA);
688 struct SmsMsgHdr_ST *msg =
689 (struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
690 int rc;
691
692 if (!buffer)
693 return -ENOMEM;
694
695 SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
696 sizeof(struct SmsMsgHdr_ST));
697
698 rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
699 &coredev->version_ex_done);
700 if (rc == -ETIME) {
701 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
702
703 if (wait_for_completion_timeout(&coredev->resume_done,
704 msecs_to_jiffies(5000))) {
705 rc = smscore_sendrequest_and_wait(
706 coredev, msg, msg->msgLength,
707 &coredev->version_ex_done);
708 if (rc < 0)
709 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
710 "second try, rc %d", rc);
711 } else
712 rc = -ETIME;
713 }
714
715 kfree(buffer);
716
717 return rc;
718}
719
720static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
721 /*Stellar NOVA A0 Nova B0 VEGA*/
722 /*DVBT*/
723 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
724 /*DVBH*/
725 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
726 /*TDMB*/
727 {"none", "tdmb_nova_12mhz.inp", "none", "none"},
728 /*DABIP*/
729 {"none", "none", "none", "none"},
730 /*BDA*/
731 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
732 /*ISDBT*/
733 {"none", "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp", "none"},
734 /*ISDBTBDA*/
735 {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
736 /*CMMB*/
737 {"none", "none", "none", "cmmb_vega_12mhz.inp"}
738};
739
740static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
741 int mode, enum sms_device_type_st type)
742{
743 char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
744 return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
745}
746
747/**
748 * calls device handler to change mode of operation
749 * NOTE: stellar/usb may disconnect when changing mode
750 *
751 * @param coredev pointer to a coredev object returned by
752 * smscore_register_device
753 * @param mode requested mode of operation
754 *
755 * @return 0 on success, <0 on error.
756 */
757int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
758{
759 void *buffer;
760 int rc = 0;
761 enum sms_device_type_st type;
762
763 sms_debug("set device mode to %d", mode);
764 if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
765 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) {
766 sms_err("invalid mode specified %d", mode);
767 return -EINVAL;
768 }
769
770 smscore_registry_setmode(coredev->devpath, mode);
771
772 if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
773 rc = smscore_detect_mode(coredev);
774 if (rc < 0) {
775 sms_err("mode detect failed %d", rc);
776 return rc;
777 }
778 }
779
780 if (coredev->mode == mode) {
781 sms_info("device mode %d already set", mode);
782 return 0;
783 }
784
785 if (!(coredev->modes_supported & (1 << mode))) {
786 char *fw_filename;
787
788 type = smscore_registry_gettype(coredev->devpath);
789 fw_filename = sms_get_fw_name(coredev, mode, type);
790
791 rc = smscore_load_firmware_from_file(coredev,
792 fw_filename, NULL);
793 if (rc < 0) {
794 sms_warn("error %d loading firmware: %s, "
795 "trying again with default firmware",
796 rc, fw_filename);
797
798 /* try again with the default firmware */
799 fw_filename = smscore_fw_lkup[mode][type];
800 rc = smscore_load_firmware_from_file(coredev,
801 fw_filename, NULL);
802
803 if (rc < 0) {
804 sms_warn("error %d loading "
805 "firmware: %s", rc,
806 fw_filename);
807 return rc;
808 }
809 }
810 sms_log("firmware download success: %s", fw_filename);
811 } else
812 sms_info("mode %d supported by running "
813 "firmware", mode);
814
815 buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
816 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
817 if (buffer) {
818 struct SmsMsgData_ST *msg =
819 (struct SmsMsgData_ST *)
820 SMS_ALIGN_ADDRESS(buffer);
821
822 SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
823 sizeof(struct SmsMsgData_ST));
824 msg->msgData[0] = mode;
825
826 rc = smscore_sendrequest_and_wait(
827 coredev, msg, msg->xMsgHeader.msgLength,
828 &coredev->init_device_done);
829
830 kfree(buffer);
831 } else {
832 sms_err("Could not allocate buffer for "
833 "init device message.");
834 rc = -ENOMEM;
835 }
836 } else {
837 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
838 sms_err("invalid mode specified %d", mode);
839 return -EINVAL;
840 }
841
842 smscore_registry_setmode(coredev->devpath, mode);
843
844 if (coredev->detectmode_handler)
845 coredev->detectmode_handler(coredev->context,
846 &coredev->mode);
847
848 if (coredev->mode != mode && coredev->setmode_handler)
849 rc = coredev->setmode_handler(coredev->context, mode);
850 }
851
852 if (rc >= 0) {
853 coredev->mode = mode;
854 coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
855 }
856
857 if (rc != 0)
858 sms_err("return error code %d.", rc);
859 return rc;
860}
861
862/**
863 * calls device handler to get current mode of operation
864 *
865 * @param coredev pointer to a coredev object returned by
866 * smscore_register_device
867 *
868 * @return current mode
869 */
870int smscore_get_device_mode(struct smscore_device_t *coredev)
871{
872 return coredev->mode;
873}
874
875/**
876 * find client by response id & type within the clients list.
877 * return client handle or NULL.
878 *
879 * @param coredev pointer to a coredev object returned by
880 * smscore_register_device
881 * @param data_type client data type (SMS_DONT_CARE for all types)
882 * @param id client id (SMS_DONT_CARE for all id)
883 *
884 */
885static struct
886smscore_client_t *smscore_find_client(struct smscore_device_t *coredev,
887 int data_type, int id)
888{
889 struct smscore_client_t *client = NULL;
890 struct list_head *next, *first;
891 unsigned long flags;
892 struct list_head *firstid, *nextid;
893
894
895 spin_lock_irqsave(&coredev->clientslock, flags);
896 first = &coredev->clients;
897 for (next = first->next;
898 (next != first) && !client;
899 next = next->next) {
900 firstid = &((struct smscore_client_t *)next)->idlist;
901 for (nextid = firstid->next;
902 nextid != firstid;
903 nextid = nextid->next) {
904 if ((((struct smscore_idlist_t *)nextid)->id == id) &&
905 (((struct smscore_idlist_t *)nextid)->data_type == data_type ||
906 (((struct smscore_idlist_t *)nextid)->data_type == 0))) {
907 client = (struct smscore_client_t *) next;
908 break;
909 }
910 }
911 }
912 spin_unlock_irqrestore(&coredev->clientslock, flags);
913 return client;
914}
915
916/**
917 * find client by response id/type, call clients onresponse handler
918 * return buffer to pool on error
919 *
920 * @param coredev pointer to a coredev object returned by
921 * smscore_register_device
922 * @param cb pointer to response buffer descriptor
923 *
924 */
925void smscore_onresponse(struct smscore_device_t *coredev,
926 struct smscore_buffer_t *cb)
927{
928 struct SmsMsgHdr_ST *phdr =
929 (struct SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset);
930 struct smscore_client_t *client =
931 smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
932 int rc = -EBUSY;
933
934 static unsigned long last_sample_time; /* = 0; */
935 static int data_total; /* = 0; */
936 unsigned long time_now = jiffies_to_msecs(jiffies);
937
938 if (!last_sample_time)
939 last_sample_time = time_now;
940
941 if (time_now - last_sample_time > 10000) {
942 sms_debug("\ndata rate %d bytes/secs",
943 (int)((data_total * 1000) /
944 (time_now - last_sample_time)));
945
946 last_sample_time = time_now;
947 data_total = 0;
948 }
949
950 data_total += cb->size;
951 /* If no client registered for type & id,
952 * check for control client where type is not registered */
953 if (client)
954 rc = client->onresponse_handler(client->context, cb);
955
956 if (rc < 0) {
957 switch (phdr->msgType) {
958 case MSG_SMS_GET_VERSION_EX_RES:
959 {
960 struct SmsVersionRes_ST *ver =
961 (struct SmsVersionRes_ST *) phdr;
962 sms_debug("MSG_SMS_GET_VERSION_EX_RES "
963 "id %d prots 0x%x ver %d.%d",
964 ver->FirmwareId, ver->SupportedProtocols,
965 ver->RomVersionMajor, ver->RomVersionMinor);
966
967 coredev->mode = ver->FirmwareId == 255 ?
968 DEVICE_MODE_NONE : ver->FirmwareId;
969 coredev->modes_supported = ver->SupportedProtocols;
970
971 complete(&coredev->version_ex_done);
972 break;
973 }
974 case MSG_SMS_INIT_DEVICE_RES:
975 sms_debug("MSG_SMS_INIT_DEVICE_RES");
976 complete(&coredev->init_device_done);
977 break;
978 case MSG_SW_RELOAD_START_RES:
979 sms_debug("MSG_SW_RELOAD_START_RES");
980 complete(&coredev->reload_start_done);
981 break;
982 case MSG_SMS_DATA_DOWNLOAD_RES:
983 complete(&coredev->data_download_done);
984 break;
985 case MSG_SW_RELOAD_EXEC_RES:
986 sms_debug("MSG_SW_RELOAD_EXEC_RES");
987 break;
988 case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
989 sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
990 complete(&coredev->trigger_done);
991 break;
992 case MSG_SMS_SLEEP_RESUME_COMP_IND:
993 complete(&coredev->resume_done);
994 break;
995 default:
996 break;
997 }
998 smscore_putbuffer(coredev, cb);
999 }
1000}
1001
1002/**
1003 * return pointer to next free buffer descriptor from core pool
1004 *
1005 * @param coredev pointer to a coredev object returned by
1006 * smscore_register_device
1007 *
1008 * @return pointer to descriptor on success, NULL on error.
1009 */
1010struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
1011{
1012 struct smscore_buffer_t *cb = NULL;
1013 unsigned long flags;
1014
1015 spin_lock_irqsave(&coredev->bufferslock, flags);
1016
1017 if (!list_empty(&coredev->buffers)) {
1018 cb = (struct smscore_buffer_t *) coredev->buffers.next;
1019 list_del(&cb->entry);
1020 }
1021
1022 spin_unlock_irqrestore(&coredev->bufferslock, flags);
1023
1024 return cb;
1025}
1026
1027/**
1028 * return buffer descriptor to a pool
1029 *
1030 * @param coredev pointer to a coredev object returned by
1031 * smscore_register_device
1032 * @param cb pointer buffer descriptor
1033 *
1034 */
1035void smscore_putbuffer(struct smscore_device_t *coredev,
1036 struct smscore_buffer_t *cb)
1037{
1038 list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
1039}
1040
1041static int smscore_validate_client(struct smscore_device_t *coredev,
1042 struct smscore_client_t *client,
1043 int data_type, int id)
1044{
1045 struct smscore_idlist_t *listentry;
1046 struct smscore_client_t *registered_client;
1047
1048 if (!client) {
1049 sms_err("bad parameter.");
1050 return -EFAULT;
1051 }
1052 registered_client = smscore_find_client(coredev, data_type, id);
1053 if (registered_client == client)
1054 return 0;
1055
1056 if (registered_client) {
1057 sms_err("The msg ID already registered to another client.");
1058 return -EEXIST;
1059 }
1060 listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
1061 if (!listentry) {
1062 sms_err("Can't allocate memory for client id.");
1063 return -ENOMEM;
1064 }
1065 listentry->id = id;
1066 listentry->data_type = data_type;
1067 list_add_locked(&listentry->entry, &client->idlist,
1068 &coredev->clientslock);
1069 return 0;
1070}
1071
1072/**
1073 * creates smsclient object, check that id is taken by another client
1074 *
1075 * @param coredev pointer to a coredev object from clients hotplug
1076 * @param initial_id all messages with this id would be sent to this client
1077 * @param data_type all messages of this type would be sent to this client
1078 * @param onresponse_handler client handler that is called to
1079 * process incoming messages
1080 * @param onremove_handler client handler that is called when device is removed
1081 * @param context client-specific context
1082 * @param client pointer to a value that receives created smsclient object
1083 *
1084 * @return 0 on success, <0 on error.
1085 */
1086int smscore_register_client(struct smscore_device_t *coredev,
1087 struct smsclient_params_t *params,
1088 struct smscore_client_t **client)
1089{
1090 struct smscore_client_t *newclient;
1091 /* check that no other channel with same parameters exists */
1092 if (smscore_find_client(coredev, params->data_type,
1093 params->initial_id)) {
1094 sms_err("Client already exist.");
1095 return -EEXIST;
1096 }
1097
1098 newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
1099 if (!newclient) {
1100 sms_err("Failed to allocate memory for client.");
1101 return -ENOMEM;
1102 }
1103
1104 INIT_LIST_HEAD(&newclient->idlist);
1105 newclient->coredev = coredev;
1106 newclient->onresponse_handler = params->onresponse_handler;
1107 newclient->onremove_handler = params->onremove_handler;
1108 newclient->context = params->context;
1109 list_add_locked(&newclient->entry, &coredev->clients,
1110 &coredev->clientslock);
1111 smscore_validate_client(coredev, newclient, params->data_type,
1112 params->initial_id);
1113 *client = newclient;
1114 sms_debug("%p %d %d", params->context, params->data_type,
1115 params->initial_id);
1116
1117 return 0;
1118}
1119
1120/**
1121 * frees smsclient object and all subclients associated with it
1122 *
1123 * @param client pointer to smsclient object returned by
1124 * smscore_register_client
1125 *
1126 */
1127void smscore_unregister_client(struct smscore_client_t *client)
1128{
1129 struct smscore_device_t *coredev = client->coredev;
1130 unsigned long flags;
1131
1132 spin_lock_irqsave(&coredev->clientslock, flags);
1133
1134
1135 while (!list_empty(&client->idlist)) {
1136 struct smscore_idlist_t *identry =
1137 (struct smscore_idlist_t *) client->idlist.next;
1138 list_del(&identry->entry);
1139 kfree(identry);
1140 }
1141
1142 sms_info("%p", client->context);
1143
1144 list_del(&client->entry);
1145 kfree(client);
1146
1147 spin_unlock_irqrestore(&coredev->clientslock, flags);
1148}
1149
1150/**
1151 * verifies that source id is not taken by another client,
1152 * calls device handler to send requests to the device
1153 *
1154 * @param client pointer to smsclient object returned by
1155 * smscore_register_client
1156 * @param buffer pointer to a request buffer
1157 * @param size size (in bytes) of request buffer
1158 *
1159 * @return 0 on success, <0 on error.
1160 */
1161int smsclient_sendrequest(struct smscore_client_t *client,
1162 void *buffer, size_t size)
1163{
1164 struct smscore_device_t *coredev;
1165 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
1166 int rc;
1167
1168 if (client == NULL) {
1169 sms_err("Got NULL client");
1170 return -EINVAL;
1171 }
1172
1173 coredev = client->coredev;
1174
1175 /* check that no other channel with same id exists */
1176 if (coredev == NULL) {
1177 sms_err("Got NULL coredev");
1178 return -EINVAL;
1179 }
1180
1181 rc = smscore_validate_client(client->coredev, client, 0,
1182 phdr->msgSrcId);
1183 if (rc < 0)
1184 return rc;
1185
1186 return coredev->sendrequest_handler(coredev->context, buffer, size);
1187}
1188
1189
1190int smscore_module_init(void)
1191{
1192 int rc = 0;
1193
1194 INIT_LIST_HEAD(&g_smscore_notifyees);
1195 INIT_LIST_HEAD(&g_smscore_devices);
1196 kmutex_init(&g_smscore_deviceslock);
1197
1198 INIT_LIST_HEAD(&g_smscore_registry);
1199 kmutex_init(&g_smscore_registrylock);
1200
1201 /* USB Register */
1202 rc = smsusb_register();
1203
1204 /* DVB Register */
1205 rc = smsdvb_register();
1206
1207 sms_debug("rc %d", rc);
1208
1209 return rc;
1210}
1211
1212void smscore_module_exit(void)
1213{
1214
1215 kmutex_lock(&g_smscore_deviceslock);
1216 while (!list_empty(&g_smscore_notifyees)) {
1217 struct smscore_device_notifyee_t *notifyee =
1218 (struct smscore_device_notifyee_t *)
1219 g_smscore_notifyees.next;
1220
1221 list_del(&notifyee->entry);
1222 kfree(notifyee);
1223 }
1224 kmutex_unlock(&g_smscore_deviceslock);
1225
1226 kmutex_lock(&g_smscore_registrylock);
1227 while (!list_empty(&g_smscore_registry)) {
1228 struct smscore_registry_entry_t *entry =
1229 (struct smscore_registry_entry_t *)
1230 g_smscore_registry.next;
1231
1232 list_del(&entry->entry);
1233 kfree(entry);
1234 }
1235 kmutex_unlock(&g_smscore_registrylock);
1236
1237 /* DVB UnRegister */
1238 smsdvb_unregister();
1239
1240 /* Unregister USB */
1241 smsusb_unregister();
1242
1243 sms_debug("");
1244}
1245
1246module_init(smscore_module_init);
1247module_exit(smscore_module_exit);
1248
1249MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle");
1250MODULE_AUTHOR("Siano Mobile Silicon,,, (doronc@siano-ms.com)");
1251MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h
new file mode 100644
index 000000000000..c1f8f1dccb11
--- /dev/null
+++ b/drivers/media/dvb/siano/smscoreapi.h
@@ -0,0 +1,434 @@
1/*
2 * Driver for the Siano SMS1xxx USB dongle
3 *
4 * author: Anatoly Greenblat
5 *
6 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 3 as
10 * published by the Free Software Foundation;
11 *
12 * Software distributed under the License is distributed on an "AS IS"
13 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
14 *
15 * See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#ifndef __smscoreapi_h__
23#define __smscoreapi_h__
24
25#include <linux/version.h>
26#include <linux/device.h>
27#include <linux/list.h>
28#include <linux/mm.h>
29#include <linux/scatterlist.h>
30#include <linux/types.h>
31#include <asm/page.h>
32
33#include "dmxdev.h"
34#include "dvbdev.h"
35#include "dvb_demux.h"
36#include "dvb_frontend.h"
37
38#include <linux/mutex.h>
39
40#define kmutex_init(_p_) mutex_init(_p_)
41#define kmutex_lock(_p_) mutex_lock(_p_)
42#define kmutex_trylock(_p_) mutex_trylock(_p_)
43#define kmutex_unlock(_p_) mutex_unlock(_p_)
44
45#ifndef min
46#define min(a, b) (((a) < (b)) ? (a) : (b))
47#endif
48
49#define SMS_ALLOC_ALIGNMENT 128
50#define SMS_DMA_ALIGNMENT 16
51#define SMS_ALIGN_ADDRESS(addr) \
52 ((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
53
54#define SMS_DEVICE_FAMILY2 1
55#define SMS_ROM_NO_RESPONSE 2
56#define SMS_DEVICE_NOT_READY 0x8000000
57
58enum sms_device_type_st {
59 SMS_STELLAR = 0,
60 SMS_NOVA_A0,
61 SMS_NOVA_B0,
62 SMS_VEGA,
63 SMS_NUM_OF_DEVICE_TYPES
64};
65
66struct smscore_device_t;
67struct smscore_client_t;
68struct smscore_buffer_t;
69
70typedef int (*hotplug_t)(struct smscore_device_t *coredev,
71 struct device *device, int arrival);
72
73typedef int (*setmode_t)(void *context, int mode);
74typedef void (*detectmode_t)(void *context, int *mode);
75typedef int (*sendrequest_t)(void *context, void *buffer, size_t size);
76typedef int (*loadfirmware_t)(void *context, void *buffer, size_t size);
77typedef int (*preload_t)(void *context);
78typedef int (*postload_t)(void *context);
79
80typedef int (*onresponse_t)(void *context, struct smscore_buffer_t *cb);
81typedef void (*onremove_t)(void *context);
82
83struct smscore_buffer_t {
84 /* public members, once passed to clients can be changed freely */
85 struct list_head entry;
86 int size;
87 int offset;
88
89 /* private members, read-only for clients */
90 void *p;
91 dma_addr_t phys;
92 unsigned long offset_in_common;
93};
94
95struct smsdevice_params_t {
96 struct device *device;
97
98 int buffer_size;
99 int num_buffers;
100
101 char devpath[32];
102 unsigned long flags;
103
104 setmode_t setmode_handler;
105 detectmode_t detectmode_handler;
106 sendrequest_t sendrequest_handler;
107 preload_t preload_handler;
108 postload_t postload_handler;
109
110 void *context;
111 enum sms_device_type_st device_type;
112};
113
114struct smsclient_params_t {
115 int initial_id;
116 int data_type;
117 onresponse_t onresponse_handler;
118 onremove_t onremove_handler;
119
120 void *context;
121};
122
123/* GPIO definitions for antenna frequency domain control (SMS8021) */
124#define SMS_ANTENNA_GPIO_0 1
125#define SMS_ANTENNA_GPIO_1 0
126
127#define BW_8_MHZ 0
128#define BW_7_MHZ 1
129#define BW_6_MHZ 2
130#define BW_5_MHZ 3
131#define BW_ISDBT_1SEG 4
132#define BW_ISDBT_3SEG 5
133
134#define MSG_HDR_FLAG_SPLIT_MSG 4
135
136#define MAX_GPIO_PIN_NUMBER 31
137
138#define HIF_TASK 11
139#define SMS_HOST_LIB 150
140#define DVBT_BDA_CONTROL_MSG_ID 201
141
142#define SMS_MAX_PAYLOAD_SIZE 240
143#define SMS_TUNE_TIMEOUT 500
144
145#define MSG_SMS_GPIO_CONFIG_REQ 507
146#define MSG_SMS_GPIO_CONFIG_RES 508
147#define MSG_SMS_GPIO_SET_LEVEL_REQ 509
148#define MSG_SMS_GPIO_SET_LEVEL_RES 510
149#define MSG_SMS_GPIO_GET_LEVEL_REQ 511
150#define MSG_SMS_GPIO_GET_LEVEL_RES 512
151#define MSG_SMS_RF_TUNE_REQ 561
152#define MSG_SMS_RF_TUNE_RES 562
153#define MSG_SMS_INIT_DEVICE_REQ 578
154#define MSG_SMS_INIT_DEVICE_RES 579
155#define MSG_SMS_ADD_PID_FILTER_REQ 601
156#define MSG_SMS_ADD_PID_FILTER_RES 602
157#define MSG_SMS_REMOVE_PID_FILTER_REQ 603
158#define MSG_SMS_REMOVE_PID_FILTER_RES 604
159#define MSG_SMS_DAB_CHANNEL 607
160#define MSG_SMS_GET_PID_FILTER_LIST_REQ 608
161#define MSG_SMS_GET_PID_FILTER_LIST_RES 609
162#define MSG_SMS_GET_STATISTICS_REQ 615
163#define MSG_SMS_GET_STATISTICS_RES 616
164#define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651
165#define MSG_SMS_SET_ANTENNA_CONFIG_RES 652
166#define MSG_SMS_GET_STATISTICS_EX_REQ 653
167#define MSG_SMS_GET_STATISTICS_EX_RES 654
168#define MSG_SMS_SLEEP_RESUME_COMP_IND 655
169#define MSG_SMS_DATA_DOWNLOAD_REQ 660
170#define MSG_SMS_DATA_DOWNLOAD_RES 661
171#define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ 664
172#define MSG_SMS_SWDOWNLOAD_TRIGGER_RES 665
173#define MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ 666
174#define MSG_SMS_SWDOWNLOAD_BACKDOOR_RES 667
175#define MSG_SMS_GET_VERSION_EX_REQ 668
176#define MSG_SMS_GET_VERSION_EX_RES 669
177#define MSG_SMS_SET_CLOCK_OUTPUT_REQ 670
178#define MSG_SMS_I2C_SET_FREQ_REQ 685
179#define MSG_SMS_GENERIC_I2C_REQ 687
180#define MSG_SMS_GENERIC_I2C_RES 688
181#define MSG_SMS_DVBT_BDA_DATA 693
182#define MSG_SW_RELOAD_REQ 697
183#define MSG_SMS_DATA_MSG 699
184#define MSG_SW_RELOAD_START_REQ 702
185#define MSG_SW_RELOAD_START_RES 703
186#define MSG_SW_RELOAD_EXEC_REQ 704
187#define MSG_SW_RELOAD_EXEC_RES 705
188#define MSG_SMS_SPI_INT_LINE_SET_REQ 710
189#define MSG_SMS_ISDBT_TUNE_REQ 776
190#define MSG_SMS_ISDBT_TUNE_RES 777
191
192#define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
193 (ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
194 (ptr)->msgLength = len; (ptr)->msgFlags = 0; \
195} while (0)
196#define SMS_INIT_MSG(ptr, type, len) \
197 SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len)
198
199enum SMS_DEVICE_MODE {
200 DEVICE_MODE_NONE = -1,
201 DEVICE_MODE_DVBT = 0,
202 DEVICE_MODE_DVBH,
203 DEVICE_MODE_DAB_TDMB,
204 DEVICE_MODE_DAB_TDMB_DABIP,
205 DEVICE_MODE_DVBT_BDA,
206 DEVICE_MODE_ISDBT,
207 DEVICE_MODE_ISDBT_BDA,
208 DEVICE_MODE_CMMB,
209 DEVICE_MODE_RAW_TUNER,
210 DEVICE_MODE_MAX,
211};
212
213struct SmsMsgHdr_ST {
214 u16 msgType;
215 u8 msgSrcId;
216 u8 msgDstId;
217 u16 msgLength; /* Length of entire message, including header */
218 u16 msgFlags;
219};
220
221struct SmsMsgData_ST {
222 struct SmsMsgHdr_ST xMsgHeader;
223 u32 msgData[1];
224};
225
226struct SmsDataDownload_ST {
227 struct SmsMsgHdr_ST xMsgHeader;
228 u32 MemAddr;
229 u8 Payload[SMS_MAX_PAYLOAD_SIZE];
230};
231
232struct SmsVersionRes_ST {
233 struct SmsMsgHdr_ST xMsgHeader;
234
235 u16 ChipModel; /* e.g. 0x1102 for SMS-1102 "Nova" */
236 u8 Step; /* 0 - Step A */
237 u8 MetalFix; /* 0 - Metal 0 */
238
239 u8 FirmwareId; /* 0xFF � ROM, otherwise the
240 * value indicated by
241 * SMSHOSTLIB_DEVICE_MODES_E */
242 u8 SupportedProtocols; /* Bitwise OR combination of
243 * supported protocols */
244
245 u8 VersionMajor;
246 u8 VersionMinor;
247 u8 VersionPatch;
248 u8 VersionFieldPatch;
249
250 u8 RomVersionMajor;
251 u8 RomVersionMinor;
252 u8 RomVersionPatch;
253 u8 RomVersionFieldPatch;
254
255 u8 TextLabel[34];
256};
257
258struct SmsFirmware_ST {
259 u32 CheckSum;
260 u32 Length;
261 u32 StartAddress;
262 u8 Payload[1];
263};
264
265struct SMSHOSTLIB_STATISTICS_ST {
266 u32 Reserved; /* Reserved */
267
268 /* Common parameters */
269 u32 IsRfLocked; /* 0 - not locked, 1 - locked */
270 u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
271 u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
272
273 /* Reception quality */
274 s32 SNR; /* dB */
275 u32 BER; /* Post Viterbi BER [1E-5] */
276 u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */
277 u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A,
278 * valid only for DVB-T/H */
279 u32 MFER; /* DVB-H frame error rate in percentage,
280 * 0xFFFFFFFF indicate N/A, valid only for DVB-H */
281 s32 RSSI; /* dBm */
282 s32 InBandPwr; /* In band power in dBM */
283 s32 CarrierOffset; /* Carrier Offset in bin/1024 */
284
285 /* Transmission parameters, valid only for DVB-T/H */
286 u32 Frequency; /* Frequency in Hz */
287 u32 Bandwidth; /* Bandwidth in MHz */
288 u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4,
289 * for DVB-T/H FFT mode carriers in Kilos */
290 u32 ModemState; /* from SMS_DvbModemState_ET */
291 u32 GuardInterval; /* Guard Interval, 1 divided by value */
292 u32 CodeRate; /* Code Rate from SMS_DvbModemState_ET */
293 u32 LPCodeRate; /* Low Priority Code Rate from SMS_DvbModemState_ET */
294 u32 Hierarchy; /* Hierarchy from SMS_Hierarchy_ET */
295 u32 Constellation; /* Constellation from SMS_Constellation_ET */
296
297 /* Burst parameters, valid only for DVB-H */
298 u32 BurstSize; /* Current burst size in bytes */
299 u32 BurstDuration; /* Current burst duration in mSec */
300 u32 BurstCycleTime; /* Current burst cycle time in mSec */
301 u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec,
302 * as calculated by demodulator */
303 u32 NumOfRows; /* Number of rows in MPE table */
304 u32 NumOfPaddCols; /* Number of padding columns in MPE table */
305 u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */
306 /* Burst parameters */
307 u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
308 u32 TotalTSPackets; /* Total number of transport-stream packets */
309 u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include
310 * errors after MPE RS decoding */
311 u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include errors
312 * after MPE RS decoding */
313 u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were corrected
314 * by MPE RS decoding */
315
316 /* Common params */
317 u32 BERErrorCount; /* Number of errornous SYNC bits. */
318 u32 BERBitCount; /* Total number of SYNC bits. */
319
320 /* Interface information */
321 u32 SmsToHostTxErrors; /* Total number of transmission errors. */
322
323 /* DAB/T-DMB */
324 u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */
325
326 /* DVB-H TPS parameters */
327 u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero;
328 * if set to 0xFFFFFFFF cell_id not yet recovered */
329
330};
331
332struct SmsMsgStatisticsInfo_ST {
333 u32 RequestResult;
334
335 struct SMSHOSTLIB_STATISTICS_ST Stat;
336
337 /* Split the calc of the SNR in DAB */
338 u32 Signal; /* dB */
339 u32 Noise; /* dB */
340
341};
342
343
344struct smsdvb_client_t {
345 struct list_head entry;
346
347 struct smscore_device_t *coredev;
348 struct smscore_client_t *smsclient;
349
350 struct dvb_adapter adapter;
351 struct dvb_demux demux;
352 struct dmxdev dmxdev;
353 struct dvb_frontend frontend;
354
355 fe_status_t fe_status;
356 int fe_ber, fe_snr, fe_signal_strength;
357
358 struct completion tune_done, stat_done;
359
360 /* todo: save freq/band instead whole struct */
361 struct dvb_frontend_parameters fe_params;
362
363};
364
365extern void smscore_registry_setmode(char *devpath, int mode);
366extern int smscore_registry_getmode(char *devpath);
367
368extern int smscore_register_hotplug(hotplug_t hotplug);
369extern void smscore_unregister_hotplug(hotplug_t hotplug);
370
371extern int smscore_register_device(struct smsdevice_params_t *params,
372 struct smscore_device_t **coredev);
373extern void smscore_unregister_device(struct smscore_device_t *coredev);
374
375extern int smscore_start_device(struct smscore_device_t *coredev);
376extern int smscore_load_firmware(struct smscore_device_t *coredev,
377 char *filename,
378 loadfirmware_t loadfirmware_handler);
379
380extern int smscore_set_device_mode(struct smscore_device_t *coredev, int mode);
381extern int smscore_get_device_mode(struct smscore_device_t *coredev);
382
383extern int smscore_register_client(struct smscore_device_t *coredev,
384 struct smsclient_params_t *params,
385 struct smscore_client_t **client);
386extern void smscore_unregister_client(struct smscore_client_t *client);
387
388extern int smsclient_sendrequest(struct smscore_client_t *client,
389 void *buffer, size_t size);
390extern void smscore_onresponse(struct smscore_device_t *coredev,
391 struct smscore_buffer_t *cb);
392
393
394extern
395struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev);
396extern void smscore_putbuffer(struct smscore_device_t *coredev,
397 struct smscore_buffer_t *cb);
398
399void smscore_set_board_id(struct smscore_device_t *core, int id);
400int smscore_get_board_id(struct smscore_device_t *core);
401
402/* smsdvb.c */
403int smsdvb_register(void);
404void smsdvb_unregister(void);
405
406/* smsusb.c */
407int smsusb_register(void);
408void smsusb_unregister(void);
409
410/* ------------------------------------------------------------------------ */
411
412extern int sms_debug;
413
414#define DBG_INFO 1
415#define DBG_ADV 2
416
417#define sms_printk(kern, fmt, arg...) \
418 printk(kern "%s: " fmt "\n", __func__, ##arg)
419
420#define dprintk(kern, lvl, fmt, arg...) do {\
421 if (sms_debug & lvl) \
422 sms_printk(kern, fmt, ##arg); } while (0)
423
424#define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
425#define sms_err(fmt, arg...) \
426 sms_printk(KERN_ERR, "line: %d: " fmt, __LINE__, ##arg)
427#define sms_warn(fmt, arg...) sms_printk(KERN_WARNING, fmt, ##arg)
428#define sms_info(fmt, arg...) \
429 dprintk(KERN_INFO, DBG_INFO, fmt, ##arg)
430#define sms_debug(fmt, arg...) \
431 dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg)
432
433
434#endif /* __smscoreapi_h__ */
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
new file mode 100644
index 000000000000..6f9c18563867
--- /dev/null
+++ b/drivers/media/dvb/siano/smsdvb.c
@@ -0,0 +1,449 @@
1/*
2 * Driver for the Siano SMS1xxx USB dongle
3 *
4 * author: Anatoly Greenblat
5 *
6 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 3 as
10 * published by the Free Software Foundation;
11 *
12 * Software distributed under the License is distributed on an "AS IS"
13 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
14 *
15 * See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <linux/module.h>
23#include <linux/init.h>
24
25#include "smscoreapi.h"
26#include "sms-cards.h"
27
28DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
29
30struct list_head g_smsdvb_clients;
31struct mutex g_smsdvb_clientslock;
32
33static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
34{
35 struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
36 struct SmsMsgHdr_ST *phdr =
37 (struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset);
38
39 switch (phdr->msgType) {
40 case MSG_SMS_DVBT_BDA_DATA:
41 dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
42 cb->size - sizeof(struct SmsMsgHdr_ST));
43 break;
44
45 case MSG_SMS_RF_TUNE_RES:
46 complete(&client->tune_done);
47 break;
48
49 case MSG_SMS_GET_STATISTICS_RES:
50 {
51 struct SmsMsgStatisticsInfo_ST *p =
52 (struct SmsMsgStatisticsInfo_ST *)(phdr + 1);
53
54 if (p->Stat.IsDemodLocked) {
55 client->fe_status = FE_HAS_SIGNAL |
56 FE_HAS_CARRIER |
57 FE_HAS_VITERBI |
58 FE_HAS_SYNC |
59 FE_HAS_LOCK;
60
61 client->fe_snr = p->Stat.SNR;
62 client->fe_ber = p->Stat.BER;
63
64 if (p->Stat.InBandPwr < -95)
65 client->fe_signal_strength = 0;
66 else if (p->Stat.InBandPwr > -29)
67 client->fe_signal_strength = 100;
68 else
69 client->fe_signal_strength =
70 (p->Stat.InBandPwr + 95) * 3 / 2;
71 } else {
72 client->fe_status = 0;
73 client->fe_snr =
74 client->fe_ber =
75 client->fe_signal_strength = 0;
76 }
77
78 complete(&client->stat_done);
79 break;
80 } }
81
82 smscore_putbuffer(client->coredev, cb);
83
84 return 0;
85}
86
87static void smsdvb_unregister_client(struct smsdvb_client_t *client)
88{
89 /* must be called under clientslock */
90
91 list_del(&client->entry);
92
93 smscore_unregister_client(client->smsclient);
94 dvb_unregister_frontend(&client->frontend);
95 dvb_dmxdev_release(&client->dmxdev);
96 dvb_dmx_release(&client->demux);
97 dvb_unregister_adapter(&client->adapter);
98 kfree(client);
99}
100
101static void smsdvb_onremove(void *context)
102{
103 kmutex_lock(&g_smsdvb_clientslock);
104
105 smsdvb_unregister_client((struct smsdvb_client_t *) context);
106
107 kmutex_unlock(&g_smsdvb_clientslock);
108}
109
110static int smsdvb_start_feed(struct dvb_demux_feed *feed)
111{
112 struct smsdvb_client_t *client =
113 container_of(feed->demux, struct smsdvb_client_t, demux);
114 struct SmsMsgData_ST PidMsg;
115
116 sms_debug("add pid %d(%x)",
117 feed->pid, feed->pid);
118
119 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
120 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
121 PidMsg.xMsgHeader.msgFlags = 0;
122 PidMsg.xMsgHeader.msgType = MSG_SMS_ADD_PID_FILTER_REQ;
123 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
124 PidMsg.msgData[0] = feed->pid;
125
126 return smsclient_sendrequest(client->smsclient,
127 &PidMsg, sizeof(PidMsg));
128}
129
130static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
131{
132 struct smsdvb_client_t *client =
133 container_of(feed->demux, struct smsdvb_client_t, demux);
134 struct SmsMsgData_ST PidMsg;
135
136 sms_debug("remove pid %d(%x)",
137 feed->pid, feed->pid);
138
139 PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
140 PidMsg.xMsgHeader.msgDstId = HIF_TASK;
141 PidMsg.xMsgHeader.msgFlags = 0;
142 PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ;
143 PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
144 PidMsg.msgData[0] = feed->pid;
145
146 return smsclient_sendrequest(client->smsclient,
147 &PidMsg, sizeof(PidMsg));
148}
149
150static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
151 void *buffer, size_t size,
152 struct completion *completion)
153{
154 int rc = smsclient_sendrequest(client->smsclient, buffer, size);
155 if (rc < 0)
156 return rc;
157
158 return wait_for_completion_timeout(completion,
159 msecs_to_jiffies(2000)) ?
160 0 : -ETIME;
161}
162
163static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
164{
165 struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
166 DVBT_BDA_CONTROL_MSG_ID,
167 HIF_TASK, sizeof(struct SmsMsgHdr_ST), 0 };
168 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
169 &client->stat_done);
170}
171
172static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
173{
174 struct smsdvb_client_t *client =
175 container_of(fe, struct smsdvb_client_t, frontend);
176 int rc = smsdvb_send_statistics_request(client);
177
178 if (!rc)
179 *stat = client->fe_status;
180
181 return rc;
182}
183
184static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
185{
186 struct smsdvb_client_t *client =
187 container_of(fe, struct smsdvb_client_t, frontend);
188 int rc = smsdvb_send_statistics_request(client);
189
190 if (!rc)
191 *ber = client->fe_ber;
192
193 return rc;
194}
195
196static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
197{
198 struct smsdvb_client_t *client =
199 container_of(fe, struct smsdvb_client_t, frontend);
200 int rc = smsdvb_send_statistics_request(client);
201
202 if (!rc)
203 *strength = client->fe_signal_strength;
204
205 return rc;
206}
207
208static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
209{
210 struct smsdvb_client_t *client =
211 container_of(fe, struct smsdvb_client_t, frontend);
212 int rc = smsdvb_send_statistics_request(client);
213
214 if (!rc)
215 *snr = client->fe_snr;
216
217 return rc;
218}
219
220static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
221 struct dvb_frontend_tune_settings *tune)
222{
223 sms_debug("");
224
225 tune->min_delay_ms = 400;
226 tune->step_size = 250000;
227 tune->max_drift = 0;
228 return 0;
229}
230
231static int smsdvb_set_frontend(struct dvb_frontend *fe,
232 struct dvb_frontend_parameters *fep)
233{
234 struct smsdvb_client_t *client =
235 container_of(fe, struct smsdvb_client_t, frontend);
236
237 struct {
238 struct SmsMsgHdr_ST Msg;
239 u32 Data[3];
240 } Msg;
241
242 Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
243 Msg.Msg.msgDstId = HIF_TASK;
244 Msg.Msg.msgFlags = 0;
245 Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
246 Msg.Msg.msgLength = sizeof(Msg);
247 Msg.Data[0] = fep->frequency;
248 Msg.Data[2] = 12000000;
249
250 sms_debug("freq %d band %d",
251 fep->frequency, fep->u.ofdm.bandwidth);
252
253 switch (fep->u.ofdm.bandwidth) {
254 case BANDWIDTH_8_MHZ: Msg.Data[1] = BW_8_MHZ; break;
255 case BANDWIDTH_7_MHZ: Msg.Data[1] = BW_7_MHZ; break;
256 case BANDWIDTH_6_MHZ: Msg.Data[1] = BW_6_MHZ; break;
257 case BANDWIDTH_AUTO: return -EOPNOTSUPP;
258 default: return -EINVAL;
259 }
260
261 return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
262 &client->tune_done);
263}
264
265static int smsdvb_get_frontend(struct dvb_frontend *fe,
266 struct dvb_frontend_parameters *fep)
267{
268 struct smsdvb_client_t *client =
269 container_of(fe, struct smsdvb_client_t, frontend);
270
271 sms_debug("");
272
273 /* todo: */
274 memcpy(fep, &client->fe_params,
275 sizeof(struct dvb_frontend_parameters));
276 return 0;
277}
278
279static void smsdvb_release(struct dvb_frontend *fe)
280{
281 /* do nothing */
282}
283
284static struct dvb_frontend_ops smsdvb_fe_ops = {
285 .info = {
286 .name = "Siano Mobile Digital SMS1xxx",
287 .type = FE_OFDM,
288 .frequency_min = 44250000,
289 .frequency_max = 867250000,
290 .frequency_stepsize = 250000,
291 .caps = FE_CAN_INVERSION_AUTO |
292 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
293 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
294 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
295 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
296 FE_CAN_GUARD_INTERVAL_AUTO |
297 FE_CAN_RECOVER |
298 FE_CAN_HIERARCHY_AUTO,
299 },
300
301 .release = smsdvb_release,
302
303 .set_frontend = smsdvb_set_frontend,
304 .get_frontend = smsdvb_get_frontend,
305 .get_tune_settings = smsdvb_get_tune_settings,
306
307 .read_status = smsdvb_read_status,
308 .read_ber = smsdvb_read_ber,
309 .read_signal_strength = smsdvb_read_signal_strength,
310 .read_snr = smsdvb_read_snr,
311};
312
313static int smsdvb_hotplug(struct smscore_device_t *coredev,
314 struct device *device, int arrival)
315{
316 struct smsclient_params_t params;
317 struct smsdvb_client_t *client;
318 int rc;
319
320 /* device removal handled by onremove callback */
321 if (!arrival)
322 return 0;
323
324 if (smscore_get_device_mode(coredev) != 4) {
325 sms_err("SMS Device mode is not set for "
326 "DVB operation.");
327 return 0;
328 }
329
330 client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
331 if (!client) {
332 sms_err("kmalloc() failed");
333 return -ENOMEM;
334 }
335
336 /* register dvb adapter */
337 rc = dvb_register_adapter(&client->adapter,
338 sms_get_board(
339 smscore_get_board_id(coredev))->name,
340 THIS_MODULE, device, adapter_nr);
341 if (rc < 0) {
342 sms_err("dvb_register_adapter() failed %d", rc);
343 goto adapter_error;
344 }
345
346 /* init dvb demux */
347 client->demux.dmx.capabilities = DMX_TS_FILTERING;
348 client->demux.filternum = 32; /* todo: nova ??? */
349 client->demux.feednum = 32;
350 client->demux.start_feed = smsdvb_start_feed;
351 client->demux.stop_feed = smsdvb_stop_feed;
352
353 rc = dvb_dmx_init(&client->demux);
354 if (rc < 0) {
355 sms_err("dvb_dmx_init failed %d", rc);
356 goto dvbdmx_error;
357 }
358
359 /* init dmxdev */
360 client->dmxdev.filternum = 32;
361 client->dmxdev.demux = &client->demux.dmx;
362 client->dmxdev.capabilities = 0;
363
364 rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
365 if (rc < 0) {
366 sms_err("dvb_dmxdev_init failed %d", rc);
367 goto dmxdev_error;
368 }
369
370 /* init and register frontend */
371 memcpy(&client->frontend.ops, &smsdvb_fe_ops,
372 sizeof(struct dvb_frontend_ops));
373
374 rc = dvb_register_frontend(&client->adapter, &client->frontend);
375 if (rc < 0) {
376 sms_err("frontend registration failed %d", rc);
377 goto frontend_error;
378 }
379
380 params.initial_id = 1;
381 params.data_type = MSG_SMS_DVBT_BDA_DATA;
382 params.onresponse_handler = smsdvb_onresponse;
383 params.onremove_handler = smsdvb_onremove;
384 params.context = client;
385
386 rc = smscore_register_client(coredev, &params, &client->smsclient);
387 if (rc < 0) {
388 sms_err("smscore_register_client() failed %d", rc);
389 goto client_error;
390 }
391
392 client->coredev = coredev;
393
394 init_completion(&client->tune_done);
395 init_completion(&client->stat_done);
396
397 kmutex_lock(&g_smsdvb_clientslock);
398
399 list_add(&client->entry, &g_smsdvb_clients);
400
401 kmutex_unlock(&g_smsdvb_clientslock);
402
403 sms_info("success");
404
405 return 0;
406
407client_error:
408 dvb_unregister_frontend(&client->frontend);
409
410frontend_error:
411 dvb_dmxdev_release(&client->dmxdev);
412
413dmxdev_error:
414 dvb_dmx_release(&client->demux);
415
416dvbdmx_error:
417 dvb_unregister_adapter(&client->adapter);
418
419adapter_error:
420 kfree(client);
421 return rc;
422}
423
424int smsdvb_register(void)
425{
426 int rc;
427
428 INIT_LIST_HEAD(&g_smsdvb_clients);
429 kmutex_init(&g_smsdvb_clientslock);
430
431 rc = smscore_register_hotplug(smsdvb_hotplug);
432
433 sms_debug("");
434
435 return rc;
436}
437
438void smsdvb_unregister(void)
439{
440 smscore_unregister_hotplug(smsdvb_hotplug);
441
442 kmutex_lock(&g_smsdvb_clientslock);
443
444 while (!list_empty(&g_smsdvb_clients))
445 smsdvb_unregister_client(
446 (struct smsdvb_client_t *) g_smsdvb_clients.next);
447
448 kmutex_unlock(&g_smsdvb_clientslock);
449}
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
new file mode 100644
index 000000000000..c10b1849c6a3
--- /dev/null
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -0,0 +1,459 @@
1/*
2 * Driver for the Siano SMS1xxx USB dongle
3 *
4 * author: Anatoly Greenblat
5 *
6 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 3 as
10 * published by the Free Software Foundation;
11 *
12 * Software distributed under the License is distributed on an "AS IS"
13 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
14 *
15 * See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/usb.h>
25#include <linux/firmware.h>
26
27#include "smscoreapi.h"
28#include "sms-cards.h"
29
30#define USB1_BUFFER_SIZE 0x1000
31#define USB2_BUFFER_SIZE 0x4000
32
33#define MAX_BUFFERS 50
34#define MAX_URBS 10
35
36struct smsusb_device_t;
37
38struct smsusb_urb_t {
39 struct smscore_buffer_t *cb;
40 struct smsusb_device_t *dev;
41
42 struct urb urb;
43};
44
45struct smsusb_device_t {
46 struct usb_device *udev;
47 struct smscore_device_t *coredev;
48
49 struct smsusb_urb_t surbs[MAX_URBS];
50
51 int response_alignment;
52 int buffer_size;
53};
54
55static int smsusb_submit_urb(struct smsusb_device_t *dev,
56 struct smsusb_urb_t *surb);
57
58static void smsusb_onresponse(struct urb *urb)
59{
60 struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context;
61 struct smsusb_device_t *dev = surb->dev;
62
63 if (urb->status < 0) {
64 sms_err("error, urb status %d, %d bytes",
65 urb->status, urb->actual_length);
66 return;
67 }
68
69 if (urb->actual_length > 0) {
70 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) surb->cb->p;
71
72 if (urb->actual_length >= phdr->msgLength) {
73 surb->cb->size = phdr->msgLength;
74
75 if (dev->response_alignment &&
76 (phdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG)) {
77
78 surb->cb->offset =
79 dev->response_alignment +
80 ((phdr->msgFlags >> 8) & 3);
81
82 /* sanity check */
83 if (((int) phdr->msgLength +
84 surb->cb->offset) > urb->actual_length) {
85 sms_err("invalid response "
86 "msglen %d offset %d "
87 "size %d",
88 phdr->msgLength,
89 surb->cb->offset,
90 urb->actual_length);
91 goto exit_and_resubmit;
92 }
93
94 /* move buffer pointer and
95 * copy header to its new location */
96 memcpy((char *) phdr + surb->cb->offset,
97 phdr, sizeof(struct SmsMsgHdr_ST));
98 } else
99 surb->cb->offset = 0;
100
101 smscore_onresponse(dev->coredev, surb->cb);
102 surb->cb = NULL;
103 } else {
104 sms_err("invalid response "
105 "msglen %d actual %d",
106 phdr->msgLength, urb->actual_length);
107 }
108 }
109
110exit_and_resubmit:
111 smsusb_submit_urb(dev, surb);
112}
113
114static int smsusb_submit_urb(struct smsusb_device_t *dev,
115 struct smsusb_urb_t *surb)
116{
117 if (!surb->cb) {
118 surb->cb = smscore_getbuffer(dev->coredev);
119 if (!surb->cb) {
120 sms_err("smscore_getbuffer(...) returned NULL");
121 return -ENOMEM;
122 }
123 }
124
125 usb_fill_bulk_urb(
126 &surb->urb,
127 dev->udev,
128 usb_rcvbulkpipe(dev->udev, 0x81),
129 surb->cb->p,
130 dev->buffer_size,
131 smsusb_onresponse,
132 surb
133 );
134 surb->urb.transfer_dma = surb->cb->phys;
135 surb->urb.transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
136
137 return usb_submit_urb(&surb->urb, GFP_ATOMIC);
138}
139
140static void smsusb_stop_streaming(struct smsusb_device_t *dev)
141{
142 int i;
143
144 for (i = 0; i < MAX_URBS; i++) {
145 usb_kill_urb(&dev->surbs[i].urb);
146
147 if (dev->surbs[i].cb) {
148 smscore_putbuffer(dev->coredev, dev->surbs[i].cb);
149 dev->surbs[i].cb = NULL;
150 }
151 }
152}
153
154static int smsusb_start_streaming(struct smsusb_device_t *dev)
155{
156 int i, rc;
157
158 for (i = 0; i < MAX_URBS; i++) {
159 rc = smsusb_submit_urb(dev, &dev->surbs[i]);
160 if (rc < 0) {
161 sms_err("smsusb_submit_urb(...) failed");
162 smsusb_stop_streaming(dev);
163 break;
164 }
165 }
166
167 return rc;
168}
169
170static int smsusb_sendrequest(void *context, void *buffer, size_t size)
171{
172 struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
173 int dummy;
174
175 return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
176 buffer, size, &dummy, 1000);
177}
178
179static char *smsusb1_fw_lkup[] = {
180 "dvbt_stellar_usb.inp",
181 "dvbh_stellar_usb.inp",
182 "tdmb_stellar_usb.inp",
183 "none",
184 "dvbt_bda_stellar_usb.inp",
185};
186
187static inline char *sms_get_fw_name(int mode, int board_id)
188{
189 char **fw = sms_get_board(board_id)->fw;
190 return (fw && fw[mode]) ? fw[mode] : smsusb1_fw_lkup[mode];
191}
192
193static int smsusb1_load_firmware(struct usb_device *udev, int id, int board_id)
194{
195 const struct firmware *fw;
196 u8 *fw_buffer;
197 int rc, dummy;
198 char *fw_filename;
199
200 if (id < DEVICE_MODE_DVBT || id > DEVICE_MODE_DVBT_BDA) {
201 sms_err("invalid firmware id specified %d", id);
202 return -EINVAL;
203 }
204
205 fw_filename = sms_get_fw_name(id, board_id);
206
207 rc = request_firmware(&fw, fw_filename, &udev->dev);
208 if (rc < 0) {
209 sms_warn("failed to open \"%s\" mode %d, "
210 "trying again with default firmware", fw_filename, id);
211
212 fw_filename = smsusb1_fw_lkup[id];
213 rc = request_firmware(&fw, fw_filename, &udev->dev);
214 if (rc < 0) {
215 sms_warn("failed to open \"%s\" mode %d",
216 fw_filename, id);
217
218 return rc;
219 }
220 }
221
222 fw_buffer = kmalloc(fw->size, GFP_KERNEL);
223 if (fw_buffer) {
224 memcpy(fw_buffer, fw->data, fw->size);
225
226 rc = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 2),
227 fw_buffer, fw->size, &dummy, 1000);
228
229 sms_info("sent %zd(%d) bytes, rc %d", fw->size, dummy, rc);
230
231 kfree(fw_buffer);
232 } else {
233 sms_err("failed to allocate firmware buffer");
234 rc = -ENOMEM;
235 }
236 sms_info("read FW %s, size=%zd", fw_filename, fw->size);
237
238 release_firmware(fw);
239
240 return rc;
241}
242
243static void smsusb1_detectmode(void *context, int *mode)
244{
245 char *product_string =
246 ((struct smsusb_device_t *) context)->udev->product;
247
248 *mode = DEVICE_MODE_NONE;
249
250 if (!product_string) {
251 product_string = "none";
252 sms_err("product string not found");
253 } else if (strstr(product_string, "DVBH"))
254 *mode = 1;
255 else if (strstr(product_string, "BDA"))
256 *mode = 4;
257 else if (strstr(product_string, "DVBT"))
258 *mode = 0;
259 else if (strstr(product_string, "TDMB"))
260 *mode = 2;
261
262 sms_info("%d \"%s\"", *mode, product_string);
263}
264
265static int smsusb1_setmode(void *context, int mode)
266{
267 struct SmsMsgHdr_ST Msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK,
268 sizeof(struct SmsMsgHdr_ST), 0 };
269
270 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
271 sms_err("invalid firmware id specified %d", mode);
272 return -EINVAL;
273 }
274
275 return smsusb_sendrequest(context, &Msg, sizeof(Msg));
276}
277
278static void smsusb_term_device(struct usb_interface *intf)
279{
280 struct smsusb_device_t *dev =
281 (struct smsusb_device_t *) usb_get_intfdata(intf);
282
283 if (dev) {
284 smsusb_stop_streaming(dev);
285
286 /* unregister from smscore */
287 if (dev->coredev)
288 smscore_unregister_device(dev->coredev);
289
290 kfree(dev);
291
292 sms_info("device %p destroyed", dev);
293 }
294
295 usb_set_intfdata(intf, NULL);
296}
297
298static int smsusb_init_device(struct usb_interface *intf, int board_id)
299{
300 struct smsdevice_params_t params;
301 struct smsusb_device_t *dev;
302 int i, rc;
303
304 /* create device object */
305 dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
306 if (!dev) {
307 sms_err("kzalloc(sizeof(struct smsusb_device_t) failed");
308 return -ENOMEM;
309 }
310
311 memset(&params, 0, sizeof(params));
312 usb_set_intfdata(intf, dev);
313 dev->udev = interface_to_usbdev(intf);
314
315 params.device_type = sms_get_board(board_id)->type;
316
317 switch (params.device_type) {
318 case SMS_STELLAR:
319 dev->buffer_size = USB1_BUFFER_SIZE;
320
321 params.setmode_handler = smsusb1_setmode;
322 params.detectmode_handler = smsusb1_detectmode;
323 break;
324 default:
325 sms_err("Unspecified sms device type!");
326 /* fall-thru */
327 case SMS_NOVA_A0:
328 case SMS_NOVA_B0:
329 case SMS_VEGA:
330 dev->buffer_size = USB2_BUFFER_SIZE;
331 dev->response_alignment =
332 dev->udev->ep_in[1]->desc.wMaxPacketSize -
333 sizeof(struct SmsMsgHdr_ST);
334
335 params.flags |= SMS_DEVICE_FAMILY2;
336 break;
337 }
338
339 params.device = &dev->udev->dev;
340 params.buffer_size = dev->buffer_size;
341 params.num_buffers = MAX_BUFFERS;
342 params.sendrequest_handler = smsusb_sendrequest;
343 params.context = dev;
344 snprintf(params.devpath, sizeof(params.devpath),
345 "usb\\%d-%s", dev->udev->bus->busnum, dev->udev->devpath);
346
347 /* register in smscore */
348 rc = smscore_register_device(&params, &dev->coredev);
349 if (rc < 0) {
350 sms_err("smscore_register_device(...) failed, rc %d", rc);
351 smsusb_term_device(intf);
352 return rc;
353 }
354
355 smscore_set_board_id(dev->coredev, board_id);
356
357 /* initialize urbs */
358 for (i = 0; i < MAX_URBS; i++) {
359 dev->surbs[i].dev = dev;
360 usb_init_urb(&dev->surbs[i].urb);
361 }
362
363 sms_info("smsusb_start_streaming(...).");
364 rc = smsusb_start_streaming(dev);
365 if (rc < 0) {
366 sms_err("smsusb_start_streaming(...) failed");
367 smsusb_term_device(intf);
368 return rc;
369 }
370
371 rc = smscore_start_device(dev->coredev);
372 if (rc < 0) {
373 sms_err("smscore_start_device(...) failed");
374 smsusb_term_device(intf);
375 return rc;
376 }
377
378 sms_info("device %p created", dev);
379
380 return rc;
381}
382
383static int smsusb_probe(struct usb_interface *intf,
384 const struct usb_device_id *id)
385{
386 struct usb_device *udev = interface_to_usbdev(intf);
387 char devpath[32];
388 int i, rc;
389
390 rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
391 rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
392
393 if (intf->num_altsetting > 0) {
394 rc = usb_set_interface(
395 udev, intf->cur_altsetting->desc.bInterfaceNumber, 0);
396 if (rc < 0) {
397 sms_err("usb_set_interface failed, rc %d", rc);
398 return rc;
399 }
400 }
401
402 sms_info("smsusb_probe %d",
403 intf->cur_altsetting->desc.bInterfaceNumber);
404 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
405 sms_info("endpoint %d %02x %02x %d", i,
406 intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
407 intf->cur_altsetting->endpoint[i].desc.bmAttributes,
408 intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
409
410 if ((udev->actconfig->desc.bNumInterfaces == 2) &&
411 (intf->cur_altsetting->desc.bInterfaceNumber == 0)) {
412 sms_err("rom interface 0 is not used");
413 return -ENODEV;
414 }
415
416 if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
417 snprintf(devpath, sizeof(devpath), "usb\\%d-%s",
418 udev->bus->busnum, udev->devpath);
419 sms_info("stellar device was found.");
420 return smsusb1_load_firmware(
421 udev, smscore_registry_getmode(devpath),
422 id->driver_info);
423 }
424
425 rc = smsusb_init_device(intf, id->driver_info);
426 sms_info("rc %d", rc);
427 return rc;
428}
429
430static void smsusb_disconnect(struct usb_interface *intf)
431{
432 smsusb_term_device(intf);
433}
434
435static struct usb_driver smsusb_driver = {
436 .name = "sms1xxx",
437 .probe = smsusb_probe,
438 .disconnect = smsusb_disconnect,
439 .id_table = smsusb_id_table,
440};
441
442int smsusb_register(void)
443{
444 int rc = usb_register(&smsusb_driver);
445 if (rc)
446 sms_err("usb_register failed. Error number %d", rc);
447
448 sms_debug("");
449
450 return rc;
451}
452
453void smsusb_unregister(void)
454{
455 sms_debug("");
456 /* Regular USB Cleanup */
457 usb_deregister(&smsusb_driver);
458}
459
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index 07643e010093..87c973ac668b 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -106,6 +106,8 @@ config DVB_BUDGET_CI
106 select DVB_STV0299 if !DVB_FE_CUSTOMISE 106 select DVB_STV0299 if !DVB_FE_CUSTOMISE
107 select DVB_TDA1004X if !DVB_FE_CUSTOMISE 107 select DVB_TDA1004X if !DVB_FE_CUSTOMISE
108 select DVB_LNBP21 if !DVB_FE_CUSTOMISE 108 select DVB_LNBP21 if !DVB_FE_CUSTOMISE
109 select DVB_TDA10023 if !DVB_FE_CUSTOMISE
110 select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
109 select VIDEO_IR 111 select VIDEO_IR
110 help 112 help
111 Support for simple SAA7146 based DVB cards 113 Support for simple SAA7146 based DVB cards
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index d7483f1a9b3f..71451237294c 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -3,7 +3,11 @@
3# and the AV7110 DVB device driver 3# and the AV7110 DVB device driver
4# 4#
5 5
6dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o av7110_ca.o av7110.o av7110_ipack.o av7110_ir.o 6dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o av7110_ca.o av7110.o av7110_ipack.o
7
8ifdef CONFIG_INPUT_EVDEV
9dvb-ttpci-objs += av7110_ir.o
10endif
7 11
8obj-$(CONFIG_TTPCI_EEPROM) += ttpci-eeprom.o 12obj-$(CONFIG_TTPCI_EEPROM) += ttpci-eeprom.o
9obj-$(CONFIG_DVB_BUDGET_CORE) += budget-core.o 13obj-$(CONFIG_DVB_BUDGET_CORE) += budget-core.o
@@ -14,6 +18,7 @@ obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
14obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o 18obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
15 19
16EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ 20EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
21EXTRA_CFLAGS += -Idrivers/media/common/tuners
17 22
18hostprogs-y := fdump 23hostprogs-y := fdump
19 24
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index f05d43d8b5cf..0777e8f9544b 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -587,7 +587,7 @@ static void gpioirq(unsigned long data)
587 } 587 }
588 DVB_RINGBUFFER_SKIP(cibuf, 2); 588 DVB_RINGBUFFER_SKIP(cibuf, 2);
589 589
590 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len, 0); 590 dvb_ringbuffer_read(cibuf, av7110->debi_virt, len);
591 591
592 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2); 592 iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
593 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2); 593 iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
@@ -1198,7 +1198,6 @@ static int start_ts_capture(struct av7110 *budget)
1198 if (budget->feeding1) 1198 if (budget->feeding1)
1199 return ++budget->feeding1; 1199 return ++budget->feeding1;
1200 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH); 1200 memset(budget->grabbing, 0x00, TS_HEIGHT * TS_WIDTH);
1201 budget->tsf = 0xff;
1202 budget->ttbp = 0; 1201 budget->ttbp = 0;
1203 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */ 1202 SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
1204 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */ 1203 saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
@@ -2403,18 +2402,18 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
2403 saa7146_write(dev, MC1, MASK_29); 2402 saa7146_write(dev, MC1, MASK_29);
2404 /* RPS1 timeout disable */ 2403 /* RPS1 timeout disable */
2405 saa7146_write(dev, RPS_TOV1, 0); 2404 saa7146_write(dev, RPS_TOV1, 0);
2406 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B)); 2405 WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
2407 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); 2406 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2408 WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); 2407 WRITE_RPS1(GPIO3_MSK);
2409 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24)); 2408 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
2410#if RPS_IRQ 2409#if RPS_IRQ
2411 /* issue RPS1 interrupt to increment counter */ 2410 /* issue RPS1 interrupt to increment counter */
2412 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 2411 WRITE_RPS1(CMD_INTERRUPT);
2413#endif 2412#endif
2414 WRITE_RPS1(cpu_to_le32(CMD_STOP)); 2413 WRITE_RPS1(CMD_STOP);
2415 /* Jump to begin of RPS program as safety measure (p37) */ 2414 /* Jump to begin of RPS program as safety measure (p37) */
2416 WRITE_RPS1(cpu_to_le32(CMD_JUMP)); 2415 WRITE_RPS1(CMD_JUMP);
2417 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle)); 2416 WRITE_RPS1(dev->d_rps1.dma_handle);
2418 2417
2419#if RPS_IRQ 2418#if RPS_IRQ
2420 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53) 2419 /* set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
@@ -2472,11 +2471,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
2472 get recognized before the main driver is fully loaded */ 2471 get recognized before the main driver is fully loaded */
2473 saa7146_write(dev, GPIO_CTRL, 0x500000); 2472 saa7146_write(dev, GPIO_CTRL, 0x500000);
2474 2473
2475#ifdef I2C_ADAP_CLASS_TV_DIGITAL
2476 av7110->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
2477#else
2478 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL; 2474 av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
2479#endif
2480 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name)); 2475 strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
2481 2476
2482 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */ 2477 saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
@@ -2527,28 +2522,28 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
2527 count = 0; 2522 count = 0;
2528 2523
2529 /* Wait Source Line Counter Threshold (p36) */ 2524 /* Wait Source Line Counter Threshold (p36) */
2530 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS)); 2525 WRITE_RPS1(CMD_PAUSE | EVT_HS);
2531 /* Set GPIO3=1 (p42) */ 2526 /* Set GPIO3=1 (p42) */
2532 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); 2527 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2533 WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); 2528 WRITE_RPS1(GPIO3_MSK);
2534 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24)); 2529 WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
2535#if RPS_IRQ 2530#if RPS_IRQ
2536 /* issue RPS1 interrupt */ 2531 /* issue RPS1 interrupt */
2537 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 2532 WRITE_RPS1(CMD_INTERRUPT);
2538#endif 2533#endif
2539 /* Wait reset Source Line Counter Threshold (p36) */ 2534 /* Wait reset Source Line Counter Threshold (p36) */
2540 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS)); 2535 WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
2541 /* Set GPIO3=0 (p42) */ 2536 /* Set GPIO3=0 (p42) */
2542 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); 2537 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
2543 WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); 2538 WRITE_RPS1(GPIO3_MSK);
2544 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24)); 2539 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
2545#if RPS_IRQ 2540#if RPS_IRQ
2546 /* issue RPS1 interrupt */ 2541 /* issue RPS1 interrupt */
2547 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 2542 WRITE_RPS1(CMD_INTERRUPT);
2548#endif 2543#endif
2549 /* Jump to begin of RPS program (p37) */ 2544 /* Jump to begin of RPS program (p37) */
2550 WRITE_RPS1(cpu_to_le32(CMD_JUMP)); 2545 WRITE_RPS1(CMD_JUMP);
2551 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle)); 2546 WRITE_RPS1(dev->d_rps1.dma_handle);
2552 2547
2553 /* Fix VSYNC level */ 2548 /* Fix VSYNC level */
2554 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 2549 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index e494e04eeee8..55f23ddcb994 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -188,7 +188,6 @@ struct av7110 {
188 struct dvb_net dvb_net1; 188 struct dvb_net dvb_net1;
189 spinlock_t feedlock1; 189 spinlock_t feedlock1;
190 int feeding1; 190 int feeding1;
191 u8 tsf;
192 u32 ttbp; 191 u32 ttbp;
193 unsigned char *grabbing; 192 unsigned char *grabbing;
194 struct saa7146_pgtable pt; 193 struct saa7146_pgtable pt;
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index ec55a968f204..184647ad1c7c 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -269,7 +269,7 @@ int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen)
269 return -1; 269 return -1;
270 } 270 }
271 271
272 dvb_ringbuffer_read(buf, dest, (size_t) blen, 0); 272 dvb_ringbuffer_read(buf, dest, (size_t) blen);
273 273
274 dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n", 274 dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n",
275 (unsigned long) buf->pread, (unsigned long) buf->pwrite); 275 (unsigned long) buf->pread, (unsigned long) buf->pwrite);
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index c58e3fc509ed..261135ded481 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -208,7 +208,7 @@ static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file,
208 return -EINVAL; 208 return -EINVAL;
209 DVB_RINGBUFFER_SKIP(cibuf, 2); 209 DVB_RINGBUFFER_SKIP(cibuf, 2);
210 210
211 return dvb_ringbuffer_read(cibuf, (u8 *)buf, len, 1); 211 return dvb_ringbuffer_read_user(cibuf, buf, len);
212} 212}
213 213
214static int dvb_ca_open(struct inode *inode, struct file *file) 214static int dvb_ca_open(struct inode *inode, struct file *file)
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h
index 74d940f75da6..ca99e5c1fc8a 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/drivers/media/dvb/ttpci/av7110_hw.h
@@ -305,7 +305,6 @@ enum av7110_command_type {
305#define IRQ_STATE (DPRAM_BASE + 0x0F4) 305#define IRQ_STATE (DPRAM_BASE + 0x0F4)
306#define IRQ_STATE_EXT (DPRAM_BASE + 0x0F6) 306#define IRQ_STATE_EXT (DPRAM_BASE + 0x0F6)
307#define MSGSTATE (DPRAM_BASE + 0x0F8) 307#define MSGSTATE (DPRAM_BASE + 0x0F8)
308#define FILT_STATE (DPRAM_BASE + 0x0FA)
309#define COMMAND (DPRAM_BASE + 0x0FC) 308#define COMMAND (DPRAM_BASE + 0x0FC)
310#define COM_BUFF (DPRAM_BASE + 0x100) 309#define COM_BUFF (DPRAM_BASE + 0x100)
311#define COM_BUFF_SIZE 0x20 310#define COM_BUFF_SIZE 0x20
@@ -332,8 +331,6 @@ enum av7110_command_type {
332 331
333/* firmware status area */ 332/* firmware status area */
334#define STATUS_BASE (DPRAM_BASE + 0x1FC0) 333#define STATUS_BASE (DPRAM_BASE + 0x1FC0)
335#define STATUS_SCR (STATUS_BASE + 0x00)
336#define STATUS_MODES (STATUS_BASE + 0x04)
337#define STATUS_LOOPS (STATUS_BASE + 0x08) 334#define STATUS_LOOPS (STATUS_BASE + 0x08)
338 335
339#define STATUS_MPEG_WIDTH (STATUS_BASE + 0x0C) 336#define STATUS_MPEG_WIDTH (STATUS_BASE + 0x0C)
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index b30a5288e484..b7d1f2f18d3a 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -667,6 +667,11 @@ static struct tda1002x_config philips_cu1216_config_altaddress = {
667 .invert = 0, 667 .invert = 0,
668}; 668};
669 669
670static struct tda10023_config philips_cu1216_tda10023_config = {
671 .demod_address = 0x0c,
672 .invert = 1,
673};
674
670static int philips_tu1216_tuner_init(struct dvb_frontend *fe) 675static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
671{ 676{
672 struct budget *budget = (struct budget *) fe->dvb->priv; 677 struct budget *budget = (struct budget *) fe->dvb->priv;
@@ -1019,9 +1024,10 @@ static void frontend_init(struct budget_av *budget_av)
1019 case SUBID_DVBC_KNC1_PLUS_MK3: 1024 case SUBID_DVBC_KNC1_PLUS_MK3:
1020 budget_av->reinitialise_demod = 1; 1025 budget_av->reinitialise_demod = 1;
1021 budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240; 1026 budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
1022 fe = dvb_attach(tda10023_attach, &philips_cu1216_config, 1027 fe = dvb_attach(tda10023_attach,
1023 &budget_av->budget.i2c_adap, 1028 &philips_cu1216_tda10023_config,
1024 read_pwm(budget_av)); 1029 &budget_av->budget.i2c_adap,
1030 read_pwm(budget_av));
1025 if (fe) { 1031 if (fe) {
1026 fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params; 1032 fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
1027 } 1033 }
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 6530323d5406..060e7c785326 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -46,6 +46,8 @@
46#include "lnbp21.h" 46#include "lnbp21.h"
47#include "bsbe1.h" 47#include "bsbe1.h"
48#include "bsru6.h" 48#include "bsru6.h"
49#include "tda1002x.h"
50#include "tda827x.h"
49 51
50/* 52/*
51 * Regarding DEBIADDR_IR: 53 * Regarding DEBIADDR_IR:
@@ -225,6 +227,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
225 break; 227 break;
226 case 0x1010: 228 case 0x1010:
227 case 0x1017: 229 case 0x1017:
230 case 0x101a:
228 /* for the Technotrend 1500 bundled remote */ 231 /* for the Technotrend 1500 bundled remote */
229 ir_input_init(input_dev, &budget_ci->ir.state, 232 ir_input_init(input_dev, &budget_ci->ir.state,
230 IR_TYPE_RC5, ir_codes_tt_1500); 233 IR_TYPE_RC5, ir_codes_tt_1500);
@@ -1056,6 +1059,15 @@ static struct stv0297_config dvbc_philips_tdm1316l_config = {
1056 .stop_during_read = 1, 1059 .stop_during_read = 1,
1057}; 1060};
1058 1061
1062static struct tda10023_config tda10023_config = {
1063 .demod_address = 0xc,
1064 .invert = 0,
1065 .xtal = 16000000,
1066 .pll_m = 11,
1067 .pll_p = 3,
1068 .pll_n = 1,
1069 .deltaf = 0xa511,
1070};
1059 1071
1060 1072
1061 1073
@@ -1126,7 +1138,17 @@ static void frontend_init(struct budget_ci *budget_ci)
1126 budget_ci->budget.dvb_frontend = NULL; 1138 budget_ci->budget.dvb_frontend = NULL;
1127 } 1139 }
1128 } 1140 }
1141 break;
1129 1142
1143 case 0x101a: /* TT Budget-C-1501 (philips tda10023/philips tda8274A) */
1144 budget_ci->budget.dvb_frontend = dvb_attach(tda10023_attach, &tda10023_config, &budget_ci->budget.i2c_adap, 0x48);
1145 if (budget_ci->budget.dvb_frontend) {
1146 if (dvb_attach(tda827x_attach, budget_ci->budget.dvb_frontend, 0x61, &budget_ci->budget.i2c_adap, NULL) == NULL) {
1147 printk(KERN_ERR "%s: No tda827x found!\n", __func__);
1148 dvb_frontend_detach(budget_ci->budget.dvb_frontend);
1149 budget_ci->budget.dvb_frontend = NULL;
1150 }
1151 }
1130 break; 1152 break;
1131 } 1153 }
1132 1154
@@ -1216,6 +1238,7 @@ MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
1216MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); 1238MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT);
1217MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT); 1239MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
1218MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT); 1240MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
1241MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
1219 1242
1220static struct pci_device_id pci_tbl[] = { 1243static struct pci_device_id pci_tbl[] = {
1221 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c), 1244 MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
@@ -1224,6 +1247,7 @@ static struct pci_device_id pci_tbl[] = {
1224 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011), 1247 MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
1225 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012), 1248 MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
1226 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017), 1249 MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
1250 MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
1227 { 1251 {
1228 .vendor = 0, 1252 .vendor = 0,
1229 } 1253 }
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 18cac4b12ab2..6f4ddb643fee 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -497,11 +497,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
497 if (bi->type != BUDGET_FS_ACTIVY) 497 if (bi->type != BUDGET_FS_ACTIVY)
498 saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */ 498 saa7146_write(dev, GPIO_CTRL, 0x500000); /* GPIO 3 = 1 */
499 499
500#ifdef I2C_ADAP_CLASS_TV_DIGITAL
501 budget->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
502#else
503 budget->i2c_adap.class = I2C_CLASS_TV_DIGITAL; 500 budget->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
504#endif
505 501
506 strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name)); 502 strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name));
507 503
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 9a155396d6ac..39bd0a20f53a 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -431,22 +431,22 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
431 // in budget patch GPIO3 is connected to VSYNC_B 431 // in budget patch GPIO3 is connected to VSYNC_B
432 count = 0; 432 count = 0;
433#if 0 433#if 0
434 WRITE_RPS1(cpu_to_le32(CMD_UPLOAD | 434 WRITE_RPS1(CMD_UPLOAD |
435 MASK_10 | MASK_09 | MASK_08 | MASK_06 | MASK_05 | MASK_04 | MASK_03 | MASK_02 )); 435 MASK_10 | MASK_09 | MASK_08 | MASK_06 | MASK_05 | MASK_04 | MASK_03 | MASK_02 );
436#endif 436#endif
437 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B)); 437 WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
438 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); 438 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
439 WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); 439 WRITE_RPS1(GPIO3_MSK);
440 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24)); 440 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
441#if RPS_IRQ 441#if RPS_IRQ
442 // issue RPS1 interrupt to increment counter 442 // issue RPS1 interrupt to increment counter
443 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 443 WRITE_RPS1(CMD_INTERRUPT);
444 // at least a NOP is neede between two interrupts 444 // at least a NOP is neede between two interrupts
445 WRITE_RPS1(cpu_to_le32(CMD_NOP)); 445 WRITE_RPS1(CMD_NOP);
446 // interrupt again 446 // interrupt again
447 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 447 WRITE_RPS1(CMD_INTERRUPT);
448#endif 448#endif
449 WRITE_RPS1(cpu_to_le32(CMD_STOP)); 449 WRITE_RPS1(CMD_STOP);
450 450
451#if RPS_IRQ 451#if RPS_IRQ
452 // set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53) 452 // set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53)
@@ -558,28 +558,28 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
558 558
559 559
560 // Wait Source Line Counter Threshold (p36) 560 // Wait Source Line Counter Threshold (p36)
561 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS)); 561 WRITE_RPS1(CMD_PAUSE | EVT_HS);
562 // Set GPIO3=1 (p42) 562 // Set GPIO3=1 (p42)
563 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); 563 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
564 WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); 564 WRITE_RPS1(GPIO3_MSK);
565 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24)); 565 WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
566#if RPS_IRQ 566#if RPS_IRQ
567 // issue RPS1 interrupt 567 // issue RPS1 interrupt
568 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 568 WRITE_RPS1(CMD_INTERRUPT);
569#endif 569#endif
570 // Wait reset Source Line Counter Threshold (p36) 570 // Wait reset Source Line Counter Threshold (p36)
571 WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS)); 571 WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
572 // Set GPIO3=0 (p42) 572 // Set GPIO3=0 (p42)
573 WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); 573 WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
574 WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); 574 WRITE_RPS1(GPIO3_MSK);
575 WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24)); 575 WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
576#if RPS_IRQ 576#if RPS_IRQ
577 // issue RPS1 interrupt 577 // issue RPS1 interrupt
578 WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 578 WRITE_RPS1(CMD_INTERRUPT);
579#endif 579#endif
580 // Jump to begin of RPS program (p37) 580 // Jump to begin of RPS program (p37)
581 WRITE_RPS1(cpu_to_le32(CMD_JUMP)); 581 WRITE_RPS1(CMD_JUMP);
582 WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle)); 582 WRITE_RPS1(dev->d_rps1.dma_handle);
583 583
584 // Fix VSYNC level 584 // Fix VSYNC level
585 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 585 saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index bc2043e44ebd..e6c9cd2e3b94 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -12,6 +12,7 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/wait.h> 14#include <linux/wait.h>
15#include <linux/fs.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/usb.h> 17#include <linux/usb.h>
17#include <linux/delay.h> 18#include <linux/delay.h>
@@ -990,22 +991,9 @@ static int stc_open(struct inode *inode, struct file *file)
990} 991}
991 992
992static ssize_t stc_read(struct file *file, char *buf, size_t count, 993static ssize_t stc_read(struct file *file, char *buf, size_t count,
993 loff_t * offset) 994 loff_t *offset)
994{ 995{
995 int tc = count; 996 return simple_read_from_buffer(buf, count, offset, stc_firmware, 8192);
996
997 if ((tc + *offset) > 8192)
998 tc = 8192 - *offset;
999
1000 if (tc < 0)
1001 return 0;
1002
1003 if (copy_to_user(buf, stc_firmware + *offset, tc))
1004 return -EFAULT;
1005
1006 *offset += tc;
1007
1008 return tc;
1009} 997}
1010 998
1011static int stc_release(struct inode *inode, struct file *file) 999static int stc_release(struct inode *inode, struct file *file)
@@ -1693,11 +1681,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
1693 1681
1694 i2c_set_adapdata(&ttusb->i2c_adap, ttusb); 1682 i2c_set_adapdata(&ttusb->i2c_adap, ttusb);
1695 1683
1696#ifdef I2C_ADAP_CLASS_TV_DIGITAL
1697 ttusb->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL;
1698#else
1699 ttusb->i2c_adap.class = I2C_CLASS_TV_DIGITAL; 1684 ttusb->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
1700#endif
1701 ttusb->i2c_adap.algo = &ttusb_dec_algo; 1685 ttusb->i2c_adap.algo = &ttusb_dec_algo;
1702 ttusb->i2c_adap.algo_data = NULL; 1686 ttusb->i2c_adap.algo_data = NULL;
1703 ttusb->i2c_adap.dev.parent = &udev->dev; 1687 ttusb->i2c_adap.dev.parent = &udev->dev;
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index 77354ca6e8e9..dc93a882b385 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -24,6 +24,19 @@
24 24
25 25
26/* 26/*
27 * User Notes:
28 * - USB Audio is provided by the alsa snd_usb_audio module.
29 * For listing you have to redirect the sound, for example using:
30 * arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B -
31 * - regarding module parameters in /sys/module/radio_si470x/parameters:
32 * the contents of read-only files (0444) are not updated, even if
33 * space, band and de are changed using private video controls
34 * - increase tune_timeout, if you often get -EIO errors
35 * - hw_freq_seek returns -EAGAIN, when timed out or band limit is reached
36 */
37
38
39/*
27 * History: 40 * History:
28 * 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net> 41 * 2008-01-12 Tobias Lorenz <tobias.lorenz@gmx.net>
29 * Version 1.0.0 42 * Version 1.0.0
@@ -85,10 +98,14 @@
85 * Oliver Neukum <oliver@neukum.org> 98 * Oliver Neukum <oliver@neukum.org>
86 * Version 1.0.7 99 * Version 1.0.7
87 * - usb autosuspend support 100 * - usb autosuspend support
88 * - unplugging fixed 101 * - unplugging fixed
102 * 2008-05-07 Tobias Lorenz <tobias.lorenz@gmx.net>
103 * Version 1.0.8
104 * - hardware frequency seek support
105 * - afc indication
106 * - more safety checks, let si470x_get_freq return errno
89 * 107 *
90 * ToDo: 108 * ToDo:
91 * - add seeking support
92 * - add firmware download/update support 109 * - add firmware download/update support
93 * - RDS support: interrupt mode, instead of polling 110 * - RDS support: interrupt mode, instead of polling
94 * - add LED status output (check if that's not already done in firmware) 111 * - add LED status output (check if that's not already done in firmware)
@@ -98,10 +115,10 @@
98/* driver definitions */ 115/* driver definitions */
99#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" 116#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
100#define DRIVER_NAME "radio-si470x" 117#define DRIVER_NAME "radio-si470x"
101#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7) 118#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 8)
102#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" 119#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
103#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" 120#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
104#define DRIVER_VERSION "1.0.7" 121#define DRIVER_VERSION "1.0.8"
105 122
106 123
107/* kernel includes */ 124/* kernel includes */
@@ -175,6 +192,11 @@ static unsigned int tune_timeout = 3000;
175module_param(tune_timeout, uint, 0); 192module_param(tune_timeout, uint, 0);
176MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*"); 193MODULE_PARM_DESC(tune_timeout, "Tune timeout: *3000*");
177 194
195/* Seek timeout */
196static unsigned int seek_timeout = 5000;
197module_param(seek_timeout, uint, 0);
198MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
199
178/* RDS buffer blocks */ 200/* RDS buffer blocks */
179static unsigned int rds_buf = 100; 201static unsigned int rds_buf = 100;
180module_param(rds_buf, uint, 0); 202module_param(rds_buf, uint, 0);
@@ -425,7 +447,8 @@ struct si470x_device {
425 447
426 /* driver management */ 448 /* driver management */
427 unsigned int users; 449 unsigned int users;
428 unsigned char disconnected; 450 unsigned char disconnected;
451 struct mutex disconnect_lock;
429 452
430 /* Silabs internal registers (0..15) */ 453 /* Silabs internal registers (0..15) */
431 unsigned short registers[RADIO_REGISTER_NUM]; 454 unsigned short registers[RADIO_REGISTER_NUM];
@@ -442,12 +465,6 @@ struct si470x_device {
442 465
443 466
444/* 467/*
445 * Lock to prevent kfree of data before all users have releases the device.
446 */
447static DEFINE_MUTEX(open_close_lock);
448
449
450/*
451 * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, 468 * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
452 * 62.5 kHz otherwise. 469 * 62.5 kHz otherwise.
453 * The tuner is able to have a channel spacing of 50, 100 or 200 kHz. 470 * The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
@@ -476,11 +493,11 @@ static int si470x_get_report(struct si470x_device *radio, void *buf, int size)
476 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, 493 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
477 report[0], 2, 494 report[0], 2,
478 buf, size, usb_timeout); 495 buf, size, usb_timeout);
496
479 if (retval < 0) 497 if (retval < 0)
480 printk(KERN_WARNING DRIVER_NAME 498 printk(KERN_WARNING DRIVER_NAME
481 ": si470x_get_report: usb_control_msg returned %d\n", 499 ": si470x_get_report: usb_control_msg returned %d\n",
482 retval); 500 retval);
483
484 return retval; 501 return retval;
485} 502}
486 503
@@ -499,11 +516,11 @@ static int si470x_set_report(struct si470x_device *radio, void *buf, int size)
499 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, 516 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
500 report[0], 2, 517 report[0], 2,
501 buf, size, usb_timeout); 518 buf, size, usb_timeout);
519
502 if (retval < 0) 520 if (retval < 0)
503 printk(KERN_WARNING DRIVER_NAME 521 printk(KERN_WARNING DRIVER_NAME
504 ": si470x_set_report: usb_control_msg returned %d\n", 522 ": si470x_set_report: usb_control_msg returned %d\n",
505 retval); 523 retval);
506
507 return retval; 524 return retval;
508} 525}
509 526
@@ -521,8 +538,7 @@ static int si470x_get_register(struct si470x_device *radio, int regnr)
521 retval = si470x_get_report(radio, (void *) &buf, sizeof(buf)); 538 retval = si470x_get_report(radio, (void *) &buf, sizeof(buf));
522 539
523 if (retval >= 0) 540 if (retval >= 0)
524 radio->registers[regnr] = be16_to_cpu(get_unaligned( 541 radio->registers[regnr] = get_unaligned_be16(&buf[1]);
525 (unsigned short *) &buf[1]));
526 542
527 return (retval < 0) ? -EINVAL : 0; 543 return (retval < 0) ? -EINVAL : 0;
528} 544}
@@ -537,8 +553,7 @@ static int si470x_set_register(struct si470x_device *radio, int regnr)
537 int retval; 553 int retval;
538 554
539 buf[0] = REGISTER_REPORT(regnr); 555 buf[0] = REGISTER_REPORT(regnr);
540 put_unaligned(cpu_to_be16(radio->registers[regnr]), 556 put_unaligned_be16(radio->registers[regnr], &buf[1]);
541 (unsigned short *) &buf[1]);
542 557
543 retval = si470x_set_report(radio, (void *) &buf, sizeof(buf)); 558 retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
544 559
@@ -561,9 +576,8 @@ static int si470x_get_all_registers(struct si470x_device *radio)
561 576
562 if (retval >= 0) 577 if (retval >= 0)
563 for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++) 578 for (regnr = 0; regnr < RADIO_REGISTER_NUM; regnr++)
564 radio->registers[regnr] = be16_to_cpu(get_unaligned( 579 radio->registers[regnr] = get_unaligned_be16(
565 (unsigned short *) 580 &buf[regnr * RADIO_REGISTER_SIZE + 1]);
566 &buf[regnr * RADIO_REGISTER_SIZE + 1]));
567 581
568 return (retval < 0) ? -EINVAL : 0; 582 return (retval < 0) ? -EINVAL : 0;
569} 583}
@@ -585,7 +599,7 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
585 usb_rcvintpipe(radio->usbdev, 1), 599 usb_rcvintpipe(radio->usbdev, 1),
586 (void *) &buf, sizeof(buf), &size, usb_timeout); 600 (void *) &buf, sizeof(buf), &size, usb_timeout);
587 if (size != sizeof(buf)) 601 if (size != sizeof(buf))
588 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " 602 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
589 "return size differs: %d != %zu\n", size, sizeof(buf)); 603 "return size differs: %d != %zu\n", size, sizeof(buf));
590 if (retval < 0) 604 if (retval < 0)
591 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " 605 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
@@ -594,8 +608,8 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
594 if (retval >= 0) 608 if (retval >= 0)
595 for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) 609 for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++)
596 radio->registers[STATUSRSSI + regnr] = 610 radio->registers[STATUSRSSI + regnr] =
597 be16_to_cpu(get_unaligned((unsigned short *) 611 get_unaligned_be16(
598 &buf[regnr * RADIO_REGISTER_SIZE + 1])); 612 &buf[regnr * RADIO_REGISTER_SIZE + 1]);
599 613
600 return (retval < 0) ? -EINVAL : 0; 614 return (retval < 0) ? -EINVAL : 0;
601} 615}
@@ -615,33 +629,39 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
615 radio->registers[CHANNEL] |= CHANNEL_TUNE | chan; 629 radio->registers[CHANNEL] |= CHANNEL_TUNE | chan;
616 retval = si470x_set_register(radio, CHANNEL); 630 retval = si470x_set_register(radio, CHANNEL);
617 if (retval < 0) 631 if (retval < 0)
618 return retval; 632 goto done;
619 633
620 /* wait till seek operation has completed */ 634 /* wait till tune operation has completed */
621 timeout = jiffies + msecs_to_jiffies(tune_timeout); 635 timeout = jiffies + msecs_to_jiffies(tune_timeout);
622 do { 636 do {
623 retval = si470x_get_register(radio, STATUSRSSI); 637 retval = si470x_get_register(radio, STATUSRSSI);
624 if (retval < 0) 638 if (retval < 0)
625 return retval; 639 goto stop;
626 timed_out = time_after(jiffies, timeout); 640 timed_out = time_after(jiffies, timeout);
627 } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) && 641 } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
628 (!timed_out)); 642 (!timed_out));
643 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
644 printk(KERN_WARNING DRIVER_NAME ": tune does not complete\n");
629 if (timed_out) 645 if (timed_out)
630 printk(KERN_WARNING DRIVER_NAME 646 printk(KERN_WARNING DRIVER_NAME
631 ": seek does not finish after %u ms\n", tune_timeout); 647 ": tune timed out after %u ms\n", tune_timeout);
632 648
649stop:
633 /* stop tuning */ 650 /* stop tuning */
634 radio->registers[CHANNEL] &= ~CHANNEL_TUNE; 651 radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
635 return si470x_set_register(radio, CHANNEL); 652 retval = si470x_set_register(radio, CHANNEL);
653
654done:
655 return retval;
636} 656}
637 657
638 658
639/* 659/*
640 * si470x_get_freq - get the frequency 660 * si470x_get_freq - get the frequency
641 */ 661 */
642static unsigned int si470x_get_freq(struct si470x_device *radio) 662static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
643{ 663{
644 unsigned int spacing, band_bottom, freq; 664 unsigned int spacing, band_bottom;
645 unsigned short chan; 665 unsigned short chan;
646 int retval; 666 int retval;
647 667
@@ -667,14 +687,12 @@ static unsigned int si470x_get_freq(struct si470x_device *radio)
667 687
668 /* read channel */ 688 /* read channel */
669 retval = si470x_get_register(radio, READCHAN); 689 retval = si470x_get_register(radio, READCHAN);
670 if (retval < 0)
671 return retval;
672 chan = radio->registers[READCHAN] & READCHAN_READCHAN; 690 chan = radio->registers[READCHAN] & READCHAN_READCHAN;
673 691
674 /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */ 692 /* Frequency (MHz) = Spacing (kHz) x Channel + Bottom of Band (MHz) */
675 freq = chan * spacing + band_bottom; 693 *freq = chan * spacing + band_bottom;
676 694
677 return freq; 695 return retval;
678} 696}
679 697
680 698
@@ -714,6 +732,62 @@ static int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
714 732
715 733
716/* 734/*
735 * si470x_set_seek - set seek
736 */
737static int si470x_set_seek(struct si470x_device *radio,
738 unsigned int wrap_around, unsigned int seek_upward)
739{
740 int retval = 0;
741 unsigned long timeout;
742 bool timed_out = 0;
743
744 /* start seeking */
745 radio->registers[POWERCFG] |= POWERCFG_SEEK;
746 if (wrap_around == 1)
747 radio->registers[POWERCFG] &= ~POWERCFG_SKMODE;
748 else
749 radio->registers[POWERCFG] |= POWERCFG_SKMODE;
750 if (seek_upward == 1)
751 radio->registers[POWERCFG] |= POWERCFG_SEEKUP;
752 else
753 radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
754 retval = si470x_set_register(radio, POWERCFG);
755 if (retval < 0)
756 goto done;
757
758 /* wait till seek operation has completed */
759 timeout = jiffies + msecs_to_jiffies(seek_timeout);
760 do {
761 retval = si470x_get_register(radio, STATUSRSSI);
762 if (retval < 0)
763 goto stop;
764 timed_out = time_after(jiffies, timeout);
765 } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
766 (!timed_out));
767 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
768 printk(KERN_WARNING DRIVER_NAME ": seek does not complete\n");
769 if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
770 printk(KERN_WARNING DRIVER_NAME
771 ": seek failed / band limit reached\n");
772 if (timed_out)
773 printk(KERN_WARNING DRIVER_NAME
774 ": seek timed out after %u ms\n", seek_timeout);
775
776stop:
777 /* stop seeking */
778 radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
779 retval = si470x_set_register(radio, POWERCFG);
780
781done:
782 /* try again, if timed out */
783 if ((retval == 0) && timed_out)
784 retval = -EAGAIN;
785
786 return retval;
787}
788
789
790/*
717 * si470x_start - switch on radio 791 * si470x_start - switch on radio
718 */ 792 */
719static int si470x_start(struct si470x_device *radio) 793static int si470x_start(struct si470x_device *radio)
@@ -725,27 +799,30 @@ static int si470x_start(struct si470x_device *radio)
725 POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM; 799 POWERCFG_DMUTE | POWERCFG_ENABLE | POWERCFG_RDSM;
726 retval = si470x_set_register(radio, POWERCFG); 800 retval = si470x_set_register(radio, POWERCFG);
727 if (retval < 0) 801 if (retval < 0)
728 return retval; 802 goto done;
729 803
730 /* sysconfig 1 */ 804 /* sysconfig 1 */
731 radio->registers[SYSCONFIG1] = SYSCONFIG1_DE; 805 radio->registers[SYSCONFIG1] = SYSCONFIG1_DE;
732 retval = si470x_set_register(radio, SYSCONFIG1); 806 retval = si470x_set_register(radio, SYSCONFIG1);
733 if (retval < 0) 807 if (retval < 0)
734 return retval; 808 goto done;
735 809
736 /* sysconfig 2 */ 810 /* sysconfig 2 */
737 radio->registers[SYSCONFIG2] = 811 radio->registers[SYSCONFIG2] =
738 (0x3f << 8) | /* SEEKTH */ 812 (0x3f << 8) | /* SEEKTH */
739 (band << 6) | /* BAND */ 813 ((band << 6) & SYSCONFIG2_BAND) | /* BAND */
740 (space << 4) | /* SPACE */ 814 ((space << 4) & SYSCONFIG2_SPACE) | /* SPACE */
741 15; /* VOLUME (max) */ 815 15; /* VOLUME (max) */
742 retval = si470x_set_register(radio, SYSCONFIG2); 816 retval = si470x_set_register(radio, SYSCONFIG2);
743 if (retval < 0) 817 if (retval < 0)
744 return retval; 818 goto done;
745 819
746 /* reset last channel */ 820 /* reset last channel */
747 return si470x_set_chan(radio, 821 retval = si470x_set_chan(radio,
748 radio->registers[CHANNEL] & CHANNEL_CHAN); 822 radio->registers[CHANNEL] & CHANNEL_CHAN);
823
824done:
825 return retval;
749} 826}
750 827
751 828
@@ -760,13 +837,16 @@ static int si470x_stop(struct si470x_device *radio)
760 radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS; 837 radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
761 retval = si470x_set_register(radio, SYSCONFIG1); 838 retval = si470x_set_register(radio, SYSCONFIG1);
762 if (retval < 0) 839 if (retval < 0)
763 return retval; 840 goto done;
764 841
765 /* powercfg */ 842 /* powercfg */
766 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; 843 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
767 /* POWERCFG_ENABLE has to automatically go low */ 844 /* POWERCFG_ENABLE has to automatically go low */
768 radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE; 845 radio->registers[POWERCFG] |= POWERCFG_ENABLE | POWERCFG_DISABLE;
769 return si470x_set_register(radio, POWERCFG); 846 retval = si470x_set_register(radio, POWERCFG);
847
848done:
849 return retval;
770} 850}
771 851
772 852
@@ -843,7 +923,7 @@ static void si470x_rds(struct si470x_device *radio)
843 }; 923 };
844 924
845 /* Fill the V4L2 RDS buffer */ 925 /* Fill the V4L2 RDS buffer */
846 put_unaligned(cpu_to_le16(rds), (unsigned short *) &tmpbuf); 926 put_unaligned_le16(rds, &tmpbuf);
847 tmpbuf[2] = blocknum; /* offset name */ 927 tmpbuf[2] = blocknum; /* offset name */
848 tmpbuf[2] |= blocknum << 3; /* received offset */ 928 tmpbuf[2] |= blocknum << 3; /* received offset */
849 if (bler > max_rds_errors) 929 if (bler > max_rds_errors)
@@ -883,8 +963,9 @@ static void si470x_work(struct work_struct *work)
883 struct si470x_device *radio = container_of(work, struct si470x_device, 963 struct si470x_device *radio = container_of(work, struct si470x_device,
884 work.work); 964 work.work);
885 965
886 if (radio->disconnected) 966 /* safety checks */
887 return; 967 if (radio->disconnected)
968 return;
888 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 969 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
889 return; 970 return;
890 971
@@ -917,11 +998,15 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
917 998
918 /* block if no new data available */ 999 /* block if no new data available */
919 while (radio->wr_index == radio->rd_index) { 1000 while (radio->wr_index == radio->rd_index) {
920 if (file->f_flags & O_NONBLOCK) 1001 if (file->f_flags & O_NONBLOCK) {
921 return -EWOULDBLOCK; 1002 retval = -EWOULDBLOCK;
1003 goto done;
1004 }
922 if (wait_event_interruptible(radio->read_queue, 1005 if (wait_event_interruptible(radio->read_queue,
923 radio->wr_index != radio->rd_index) < 0) 1006 radio->wr_index != radio->rd_index) < 0) {
924 return -EINTR; 1007 retval = -EINTR;
1008 goto done;
1009 }
925 } 1010 }
926 1011
927 /* calculate block count from byte count */ 1012 /* calculate block count from byte count */
@@ -950,6 +1035,7 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
950 } 1035 }
951 mutex_unlock(&radio->lock); 1036 mutex_unlock(&radio->lock);
952 1037
1038done:
953 return retval; 1039 return retval;
954} 1040}
955 1041
@@ -961,6 +1047,7 @@ static unsigned int si470x_fops_poll(struct file *file,
961 struct poll_table_struct *pts) 1047 struct poll_table_struct *pts)
962{ 1048{
963 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1049 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1050 int retval = 0;
964 1051
965 /* switch on rds reception */ 1052 /* switch on rds reception */
966 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) { 1053 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
@@ -972,9 +1059,9 @@ static unsigned int si470x_fops_poll(struct file *file,
972 poll_wait(file, &radio->read_queue, pts); 1059 poll_wait(file, &radio->read_queue, pts);
973 1060
974 if (radio->rd_index != radio->wr_index) 1061 if (radio->rd_index != radio->wr_index)
975 return POLLIN | POLLRDNORM; 1062 retval = POLLIN | POLLRDNORM;
976 1063
977 return 0; 1064 return retval;
978} 1065}
979 1066
980 1067
@@ -991,17 +1078,18 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
991 retval = usb_autopm_get_interface(radio->intf); 1078 retval = usb_autopm_get_interface(radio->intf);
992 if (retval < 0) { 1079 if (retval < 0) {
993 radio->users--; 1080 radio->users--;
994 return -EIO; 1081 retval = -EIO;
1082 goto done;
995 } 1083 }
996 1084
997 if (radio->users == 1) { 1085 if (radio->users == 1) {
998 retval = si470x_start(radio); 1086 retval = si470x_start(radio);
999 if (retval < 0) 1087 if (retval < 0)
1000 usb_autopm_put_interface(radio->intf); 1088 usb_autopm_put_interface(radio->intf);
1001 return retval;
1002 } 1089 }
1003 1090
1004 return 0; 1091done:
1092 return retval;
1005} 1093}
1006 1094
1007 1095
@@ -1011,20 +1099,23 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
1011static int si470x_fops_release(struct inode *inode, struct file *file) 1099static int si470x_fops_release(struct inode *inode, struct file *file)
1012{ 1100{
1013 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1101 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1014 int retval = 0; 1102 int retval = 0;
1015 1103
1016 if (!radio) 1104 /* safety check */
1017 return -ENODEV; 1105 if (!radio) {
1106 retval = -ENODEV;
1107 goto done;
1108 }
1018 1109
1019 mutex_lock(&open_close_lock); 1110 mutex_lock(&radio->disconnect_lock);
1020 radio->users--; 1111 radio->users--;
1021 if (radio->users == 0) { 1112 if (radio->users == 0) {
1022 if (radio->disconnected) { 1113 if (radio->disconnected) {
1023 video_unregister_device(radio->videodev); 1114 video_unregister_device(radio->videodev);
1024 kfree(radio->buffer); 1115 kfree(radio->buffer);
1025 kfree(radio); 1116 kfree(radio);
1026 goto done; 1117 goto unlock;
1027 } 1118 }
1028 1119
1029 /* stop rds reception */ 1120 /* stop rds reception */
1030 cancel_delayed_work_sync(&radio->work); 1121 cancel_delayed_work_sync(&radio->work);
@@ -1036,9 +1127,11 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
1036 usb_autopm_put_interface(radio->intf); 1127 usb_autopm_put_interface(radio->intf);
1037 } 1128 }
1038 1129
1130unlock:
1131 mutex_unlock(&radio->disconnect_lock);
1132
1039done: 1133done:
1040 mutex_unlock(&open_close_lock); 1134 return retval;
1041 return retval;
1042} 1135}
1043 1136
1044 1137
@@ -1116,7 +1209,8 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
1116 strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); 1209 strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
1117 sprintf(capability->bus_info, "USB"); 1210 sprintf(capability->bus_info, "USB");
1118 capability->version = DRIVER_KERNEL_VERSION; 1211 capability->version = DRIVER_KERNEL_VERSION;
1119 capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; 1212 capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
1213 V4L2_CAP_TUNER | V4L2_CAP_RADIO;
1120 1214
1121 return 0; 1215 return 0;
1122} 1216}
@@ -1125,7 +1219,7 @@ static int si470x_vidioc_querycap(struct file *file, void *priv,
1125/* 1219/*
1126 * si470x_vidioc_g_input - get input 1220 * si470x_vidioc_g_input - get input
1127 */ 1221 */
1128static int si470x_vidioc_g_input(struct file *filp, void *priv, 1222static int si470x_vidioc_g_input(struct file *file, void *priv,
1129 unsigned int *i) 1223 unsigned int *i)
1130{ 1224{
1131 *i = 0; 1225 *i = 0;
@@ -1137,12 +1231,18 @@ static int si470x_vidioc_g_input(struct file *filp, void *priv,
1137/* 1231/*
1138 * si470x_vidioc_s_input - set input 1232 * si470x_vidioc_s_input - set input
1139 */ 1233 */
1140static int si470x_vidioc_s_input(struct file *filp, void *priv, unsigned int i) 1234static int si470x_vidioc_s_input(struct file *file, void *priv, unsigned int i)
1141{ 1235{
1236 int retval = 0;
1237
1238 /* safety checks */
1142 if (i != 0) 1239 if (i != 0)
1143 return -EINVAL; 1240 retval = -EINVAL;
1144 1241
1145 return 0; 1242 if (retval < 0)
1243 printk(KERN_WARNING DRIVER_NAME
1244 ": set input failed with %d\n", retval);
1245 return retval;
1146} 1246}
1147 1247
1148 1248
@@ -1155,17 +1255,22 @@ static int si470x_vidioc_queryctrl(struct file *file, void *priv,
1155 unsigned char i; 1255 unsigned char i;
1156 int retval = -EINVAL; 1256 int retval = -EINVAL;
1157 1257
1258 /* safety checks */
1259 if (!qc->id)
1260 goto done;
1261
1158 for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) { 1262 for (i = 0; i < ARRAY_SIZE(si470x_v4l2_queryctrl); i++) {
1159 if (qc->id && qc->id == si470x_v4l2_queryctrl[i].id) { 1263 if (qc->id == si470x_v4l2_queryctrl[i].id) {
1160 memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc)); 1264 memcpy(qc, &(si470x_v4l2_queryctrl[i]), sizeof(*qc));
1161 retval = 0; 1265 retval = 0;
1162 break; 1266 break;
1163 } 1267 }
1164 } 1268 }
1269
1270done:
1165 if (retval < 0) 1271 if (retval < 0)
1166 printk(KERN_WARNING DRIVER_NAME 1272 printk(KERN_WARNING DRIVER_NAME
1167 ": query control failed with %d\n", retval); 1273 ": query controls failed with %d\n", retval);
1168
1169 return retval; 1274 return retval;
1170} 1275}
1171 1276
@@ -1177,9 +1282,13 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
1177 struct v4l2_control *ctrl) 1282 struct v4l2_control *ctrl)
1178{ 1283{
1179 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1284 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1285 int retval = 0;
1180 1286
1181 if (radio->disconnected) 1287 /* safety checks */
1182 return -EIO; 1288 if (radio->disconnected) {
1289 retval = -EIO;
1290 goto done;
1291 }
1183 1292
1184 switch (ctrl->id) { 1293 switch (ctrl->id) {
1185 case V4L2_CID_AUDIO_VOLUME: 1294 case V4L2_CID_AUDIO_VOLUME:
@@ -1190,9 +1299,15 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
1190 ctrl->value = ((radio->registers[POWERCFG] & 1299 ctrl->value = ((radio->registers[POWERCFG] &
1191 POWERCFG_DMUTE) == 0) ? 1 : 0; 1300 POWERCFG_DMUTE) == 0) ? 1 : 0;
1192 break; 1301 break;
1302 default:
1303 retval = -EINVAL;
1193 } 1304 }
1194 1305
1195 return 0; 1306done:
1307 if (retval < 0)
1308 printk(KERN_WARNING DRIVER_NAME
1309 ": get control failed with %d\n", retval);
1310 return retval;
1196} 1311}
1197 1312
1198 1313
@@ -1203,10 +1318,13 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
1203 struct v4l2_control *ctrl) 1318 struct v4l2_control *ctrl)
1204{ 1319{
1205 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1320 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1206 int retval; 1321 int retval = 0;
1207 1322
1208 if (radio->disconnected) 1323 /* safety checks */
1209 return -EIO; 1324 if (radio->disconnected) {
1325 retval = -EIO;
1326 goto done;
1327 }
1210 1328
1211 switch (ctrl->id) { 1329 switch (ctrl->id) {
1212 case V4L2_CID_AUDIO_VOLUME: 1330 case V4L2_CID_AUDIO_VOLUME:
@@ -1224,10 +1342,11 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
1224 default: 1342 default:
1225 retval = -EINVAL; 1343 retval = -EINVAL;
1226 } 1344 }
1345
1346done:
1227 if (retval < 0) 1347 if (retval < 0)
1228 printk(KERN_WARNING DRIVER_NAME 1348 printk(KERN_WARNING DRIVER_NAME
1229 ": set control failed with %d\n", retval); 1349 ": set control failed with %d\n", retval);
1230
1231 return retval; 1350 return retval;
1232} 1351}
1233 1352
@@ -1238,13 +1357,22 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
1238static int si470x_vidioc_g_audio(struct file *file, void *priv, 1357static int si470x_vidioc_g_audio(struct file *file, void *priv,
1239 struct v4l2_audio *audio) 1358 struct v4l2_audio *audio)
1240{ 1359{
1241 if (audio->index > 1) 1360 int retval = 0;
1242 return -EINVAL; 1361
1362 /* safety checks */
1363 if (audio->index != 0) {
1364 retval = -EINVAL;
1365 goto done;
1366 }
1243 1367
1244 strcpy(audio->name, "Radio"); 1368 strcpy(audio->name, "Radio");
1245 audio->capability = V4L2_AUDCAP_STEREO; 1369 audio->capability = V4L2_AUDCAP_STEREO;
1246 1370
1247 return 0; 1371done:
1372 if (retval < 0)
1373 printk(KERN_WARNING DRIVER_NAME
1374 ": get audio failed with %d\n", retval);
1375 return retval;
1248} 1376}
1249 1377
1250 1378
@@ -1254,10 +1382,19 @@ static int si470x_vidioc_g_audio(struct file *file, void *priv,
1254static int si470x_vidioc_s_audio(struct file *file, void *priv, 1382static int si470x_vidioc_s_audio(struct file *file, void *priv,
1255 struct v4l2_audio *audio) 1383 struct v4l2_audio *audio)
1256{ 1384{
1257 if (audio->index != 0) 1385 int retval = 0;
1258 return -EINVAL;
1259 1386
1260 return 0; 1387 /* safety checks */
1388 if (audio->index != 0) {
1389 retval = -EINVAL;
1390 goto done;
1391 }
1392
1393done:
1394 if (retval < 0)
1395 printk(KERN_WARNING DRIVER_NAME
1396 ": set audio failed with %d\n", retval);
1397 return retval;
1261} 1398}
1262 1399
1263 1400
@@ -1268,20 +1405,23 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
1268 struct v4l2_tuner *tuner) 1405 struct v4l2_tuner *tuner)
1269{ 1406{
1270 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1407 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1271 int retval; 1408 int retval = 0;
1272 1409
1273 if (radio->disconnected) 1410 /* safety checks */
1274 return -EIO; 1411 if (radio->disconnected) {
1275 if (tuner->index > 0) 1412 retval = -EIO;
1276 return -EINVAL; 1413 goto done;
1414 }
1415 if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
1416 retval = -EINVAL;
1417 goto done;
1418 }
1277 1419
1278 /* read status rssi */
1279 retval = si470x_get_register(radio, STATUSRSSI); 1420 retval = si470x_get_register(radio, STATUSRSSI);
1280 if (retval < 0) 1421 if (retval < 0)
1281 return retval; 1422 goto done;
1282 1423
1283 strcpy(tuner->name, "FM"); 1424 strcpy(tuner->name, "FM");
1284 tuner->type = V4L2_TUNER_RADIO;
1285 switch (band) { 1425 switch (band) {
1286 /* 0: 87.5 - 108 MHz (USA, Europe, default) */ 1426 /* 0: 87.5 - 108 MHz (USA, Europe, default) */
1287 default: 1427 default:
@@ -1313,9 +1453,14 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
1313 * 0x0101; 1453 * 0x0101;
1314 1454
1315 /* automatic frequency control: -1: freq to low, 1 freq to high */ 1455 /* automatic frequency control: -1: freq to low, 1 freq to high */
1316 tuner->afc = 0; 1456 /* AFCRL does only indicate that freq. differs, not if too low/high */
1457 tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0;
1317 1458
1318 return 0; 1459done:
1460 if (retval < 0)
1461 printk(KERN_WARNING DRIVER_NAME
1462 ": get tuner failed with %d\n", retval);
1463 return retval;
1319} 1464}
1320 1465
1321 1466
@@ -1326,12 +1471,17 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
1326 struct v4l2_tuner *tuner) 1471 struct v4l2_tuner *tuner)
1327{ 1472{
1328 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1473 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1329 int retval; 1474 int retval = 0;
1330 1475
1331 if (radio->disconnected) 1476 /* safety checks */
1332 return -EIO; 1477 if (radio->disconnected) {
1333 if (tuner->index > 0) 1478 retval = -EIO;
1334 return -EINVAL; 1479 goto done;
1480 }
1481 if ((tuner->index != 0) && (tuner->type != V4L2_TUNER_RADIO)) {
1482 retval = -EINVAL;
1483 goto done;
1484 }
1335 1485
1336 if (tuner->audmode == V4L2_TUNER_MODE_MONO) 1486 if (tuner->audmode == V4L2_TUNER_MODE_MONO)
1337 radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */ 1487 radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
@@ -1339,10 +1489,11 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
1339 radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ 1489 radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
1340 1490
1341 retval = si470x_set_register(radio, POWERCFG); 1491 retval = si470x_set_register(radio, POWERCFG);
1492
1493done:
1342 if (retval < 0) 1494 if (retval < 0)
1343 printk(KERN_WARNING DRIVER_NAME 1495 printk(KERN_WARNING DRIVER_NAME
1344 ": set tuner failed with %d\n", retval); 1496 ": set tuner failed with %d\n", retval);
1345
1346 return retval; 1497 return retval;
1347} 1498}
1348 1499
@@ -1354,14 +1505,25 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
1354 struct v4l2_frequency *freq) 1505 struct v4l2_frequency *freq)
1355{ 1506{
1356 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1507 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1508 int retval = 0;
1357 1509
1358 if (radio->disconnected) 1510 /* safety checks */
1359 return -EIO; 1511 if (radio->disconnected) {
1512 retval = -EIO;
1513 goto done;
1514 }
1515 if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
1516 retval = -EINVAL;
1517 goto done;
1518 }
1360 1519
1361 freq->type = V4L2_TUNER_RADIO; 1520 retval = si470x_get_freq(radio, &freq->frequency);
1362 freq->frequency = si470x_get_freq(radio);
1363 1521
1364 return 0; 1522done:
1523 if (retval < 0)
1524 printk(KERN_WARNING DRIVER_NAME
1525 ": get frequency failed with %d\n", retval);
1526 return retval;
1365} 1527}
1366 1528
1367 1529
@@ -1372,19 +1534,55 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
1372 struct v4l2_frequency *freq) 1534 struct v4l2_frequency *freq)
1373{ 1535{
1374 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1536 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1375 int retval; 1537 int retval = 0;
1376 1538
1377 if (radio->disconnected) 1539 /* safety checks */
1378 return -EIO; 1540 if (radio->disconnected) {
1379 if (freq->type != V4L2_TUNER_RADIO) 1541 retval = -EIO;
1380 return -EINVAL; 1542 goto done;
1543 }
1544 if ((freq->tuner != 0) && (freq->type != V4L2_TUNER_RADIO)) {
1545 retval = -EINVAL;
1546 goto done;
1547 }
1381 1548
1382 retval = si470x_set_freq(radio, freq->frequency); 1549 retval = si470x_set_freq(radio, freq->frequency);
1550
1551done:
1383 if (retval < 0) 1552 if (retval < 0)
1384 printk(KERN_WARNING DRIVER_NAME 1553 printk(KERN_WARNING DRIVER_NAME
1385 ": set frequency failed with %d\n", retval); 1554 ": set frequency failed with %d\n", retval);
1555 return retval;
1556}
1386 1557
1387 return 0; 1558
1559/*
1560 * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek
1561 */
1562static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
1563 struct v4l2_hw_freq_seek *seek)
1564{
1565 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1566 int retval = 0;
1567
1568 /* safety checks */
1569 if (radio->disconnected) {
1570 retval = -EIO;
1571 goto done;
1572 }
1573 if ((seek->tuner != 0) && (seek->type != V4L2_TUNER_RADIO)) {
1574 retval = -EINVAL;
1575 goto done;
1576 }
1577
1578 retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward);
1579
1580done:
1581 if (retval < 0)
1582 printk(KERN_WARNING DRIVER_NAME
1583 ": set hardware frequency seek failed with %d\n",
1584 retval);
1585 return retval;
1388} 1586}
1389 1587
1390 1588
@@ -1408,6 +1606,7 @@ static struct video_device si470x_viddev_template = {
1408 .vidioc_s_tuner = si470x_vidioc_s_tuner, 1606 .vidioc_s_tuner = si470x_vidioc_s_tuner,
1409 .vidioc_g_frequency = si470x_vidioc_g_frequency, 1607 .vidioc_g_frequency = si470x_vidioc_g_frequency,
1410 .vidioc_s_frequency = si470x_vidioc_s_frequency, 1608 .vidioc_s_frequency = si470x_vidioc_s_frequency,
1609 .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
1411 .owner = THIS_MODULE, 1610 .owner = THIS_MODULE,
1412}; 1611};
1413 1612
@@ -1424,31 +1623,36 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
1424 const struct usb_device_id *id) 1623 const struct usb_device_id *id)
1425{ 1624{
1426 struct si470x_device *radio; 1625 struct si470x_device *radio;
1427 int retval = -ENOMEM; 1626 int retval = 0;
1428 1627
1429 /* private data allocation */ 1628 /* private data allocation and initialization */
1430 radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL); 1629 radio = kzalloc(sizeof(struct si470x_device), GFP_KERNEL);
1431 if (!radio) 1630 if (!radio) {
1631 retval = -ENOMEM;
1432 goto err_initial; 1632 goto err_initial;
1633 }
1634 radio->users = 0;
1635 radio->disconnected = 0;
1636 radio->usbdev = interface_to_usbdev(intf);
1637 radio->intf = intf;
1638 mutex_init(&radio->disconnect_lock);
1639 mutex_init(&radio->lock);
1433 1640
1434 /* video device allocation */ 1641 /* video device allocation and initialization */
1435 radio->videodev = video_device_alloc(); 1642 radio->videodev = video_device_alloc();
1436 if (!radio->videodev) 1643 if (!radio->videodev) {
1644 retval = -ENOMEM;
1437 goto err_radio; 1645 goto err_radio;
1438 1646 }
1439 /* initial configuration */
1440 memcpy(radio->videodev, &si470x_viddev_template, 1647 memcpy(radio->videodev, &si470x_viddev_template,
1441 sizeof(si470x_viddev_template)); 1648 sizeof(si470x_viddev_template));
1442 radio->users = 0;
1443 radio->usbdev = interface_to_usbdev(intf);
1444 radio->intf = intf;
1445 mutex_init(&radio->lock);
1446 video_set_drvdata(radio->videodev, radio); 1649 video_set_drvdata(radio->videodev, radio);
1447 1650
1448 /* show some infos about the specific device */ 1651 /* show some infos about the specific device */
1449 retval = -EIO; 1652 if (si470x_get_all_registers(radio) < 0) {
1450 if (si470x_get_all_registers(radio) < 0) 1653 retval = -EIO;
1451 goto err_all; 1654 goto err_all;
1655 }
1452 printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", 1656 printk(KERN_INFO DRIVER_NAME ": DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
1453 radio->registers[DEVICEID], radio->registers[CHIPID]); 1657 radio->registers[DEVICEID], radio->registers[CHIPID]);
1454 1658
@@ -1474,8 +1678,10 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
1474 /* rds buffer allocation */ 1678 /* rds buffer allocation */
1475 radio->buf_size = rds_buf * 3; 1679 radio->buf_size = rds_buf * 3;
1476 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); 1680 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
1477 if (!radio->buffer) 1681 if (!radio->buffer) {
1682 retval = -EIO;
1478 goto err_all; 1683 goto err_all;
1684 }
1479 1685
1480 /* rds buffer configuration */ 1686 /* rds buffer configuration */
1481 radio->wr_index = 0; 1687 radio->wr_index = 0;
@@ -1487,6 +1693,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
1487 1693
1488 /* register video device */ 1694 /* register video device */
1489 if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) { 1695 if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
1696 retval = -EIO;
1490 printk(KERN_WARNING DRIVER_NAME 1697 printk(KERN_WARNING DRIVER_NAME
1491 ": Could not register video device\n"); 1698 ": Could not register video device\n");
1492 goto err_all; 1699 goto err_all;
@@ -1546,16 +1753,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
1546{ 1753{
1547 struct si470x_device *radio = usb_get_intfdata(intf); 1754 struct si470x_device *radio = usb_get_intfdata(intf);
1548 1755
1549 mutex_lock(&open_close_lock); 1756 mutex_lock(&radio->disconnect_lock);
1550 radio->disconnected = 1; 1757 radio->disconnected = 1;
1551 cancel_delayed_work_sync(&radio->work); 1758 cancel_delayed_work_sync(&radio->work);
1552 usb_set_intfdata(intf, NULL); 1759 usb_set_intfdata(intf, NULL);
1553 if (radio->users == 0) { 1760 if (radio->users == 0) {
1554 video_unregister_device(radio->videodev); 1761 video_unregister_device(radio->videodev);
1555 kfree(radio->buffer); 1762 kfree(radio->buffer);
1556 kfree(radio); 1763 kfree(radio);
1557 } 1764 }
1558 mutex_unlock(&open_close_lock); 1765 mutex_unlock(&radio->disconnect_lock);
1559} 1766}
1560 1767
1561 1768
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 5ccb0aeca8cc..f606d2951fde 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -24,21 +24,21 @@ config VIDEOBUF_VMALLOC
24 select VIDEOBUF_GEN 24 select VIDEOBUF_GEN
25 tristate 25 tristate
26 26
27config VIDEOBUF_DMA_CONTIG
28 depends on HAS_DMA
29 select VIDEOBUF_GEN
30 tristate
31
27config VIDEOBUF_DVB 32config VIDEOBUF_DVB
28 tristate 33 tristate
29 select VIDEOBUF_GEN 34 select VIDEOBUF_GEN
30 select VIDEOBUF_DMA_SG
31 35
32config VIDEO_BTCX 36config VIDEO_BTCX
33 tristate 37 tristate
34 38
35config VIDEO_IR_I2C
36 tristate
37
38config VIDEO_IR 39config VIDEO_IR
39 tristate 40 tristate
40 depends on INPUT 41 depends on INPUT
41 select VIDEO_IR_I2C if I2C
42 42
43config VIDEO_TVEEPROM 43config VIDEO_TVEEPROM
44 tristate 44 tristate
@@ -84,6 +84,19 @@ config VIDEO_HELPER_CHIPS_AUTO
84 84
85 In doubt, say Y. 85 In doubt, say Y.
86 86
87config VIDEO_IR_I2C
88 tristate "I2C module for IR" if !VIDEO_HELPER_CHIPS_AUTO
89 depends on I2C && VIDEO_IR
90 default y
91 ---help---
92 Most boards have an IR chip directly connected via GPIO. However,
93 some video boards have the IR connected via I2C bus.
94
95 If your board doesn't have an I2C IR chip, you may disable this
96 option.
97
98 In doubt, say Y.
99
87# 100#
88# Encoder / Decoder module configuration 101# Encoder / Decoder module configuration
89# 102#
@@ -600,9 +613,6 @@ config VIDEO_STRADIS
600 driver for PCI. There is a product page at 613 driver for PCI. There is a product page at
601 <http://www.stradis.com/>. 614 <http://www.stradis.com/>.
602 615
603config VIDEO_ZORAN_ZR36060
604 tristate
605
606config VIDEO_ZORAN 616config VIDEO_ZORAN
607 tristate "Zoran ZR36057/36067 Video For Linux" 617 tristate "Zoran ZR36057/36067 Video For Linux"
608 depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS 618 depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && VIRT_TO_BUS
@@ -616,61 +626,64 @@ config VIDEO_ZORAN
616 To compile this driver as a module, choose M here: the 626 To compile this driver as a module, choose M here: the
617 module will be called zr36067. 627 module will be called zr36067.
618 628
629config VIDEO_ZORAN_DC30
630 tristate "Pinnacle/Miro DC30(+) support"
631 depends on VIDEO_ZORAN
632 select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
633 select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
634 help
635 Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
636 card. This also supports really old DC10 cards based on the
637 zr36050 MJPEG codec and zr36016 VFE.
638
639config VIDEO_ZORAN_ZR36060
640 tristate "Zoran ZR36060"
641 depends on VIDEO_ZORAN
642 help
643 Say Y to support Zoran boards based on 36060 chips.
644 This includes Iomega Bus, Pinnacle DC10, Linux media Labs 33
645 and 33 R10 and AverMedia 6 boards.
646
619config VIDEO_ZORAN_BUZ 647config VIDEO_ZORAN_BUZ
620 tristate "Iomega Buz support" 648 tristate "Iomega Buz support"
621 depends on VIDEO_ZORAN 649 depends on VIDEO_ZORAN_ZR36060
622 select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO 650 select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
623 select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO 651 select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
624 select VIDEO_ZORAN_ZR36060
625 help 652 help
626 Support for the Iomega Buz MJPEG capture/playback card. 653 Support for the Iomega Buz MJPEG capture/playback card.
627 654
628config VIDEO_ZORAN_DC10 655config VIDEO_ZORAN_DC10
629 tristate "Pinnacle/Miro DC10(+) support" 656 tristate "Pinnacle/Miro DC10(+) support"
630 depends on VIDEO_ZORAN 657 depends on VIDEO_ZORAN_ZR36060
631 select VIDEO_SAA7110 658 select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO
632 select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO 659 select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
633 select VIDEO_ZORAN_ZR36060
634 help 660 help
635 Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback 661 Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
636 card. 662 card.
637 663
638config VIDEO_ZORAN_DC30
639 tristate "Pinnacle/Miro DC30(+) support"
640 depends on VIDEO_ZORAN
641 select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
642 select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
643 help
644 Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
645 card. This also supports really old DC10 cards based on the
646 zr36050 MJPEG codec and zr36016 VFE.
647
648config VIDEO_ZORAN_LML33 664config VIDEO_ZORAN_LML33
649 tristate "Linux Media Labs LML33 support" 665 tristate "Linux Media Labs LML33 support"
650 depends on VIDEO_ZORAN 666 depends on VIDEO_ZORAN_ZR36060
651 select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO 667 select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
652 select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO 668 select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
653 select VIDEO_ZORAN_ZR36060
654 help 669 help
655 Support for the Linux Media Labs LML33 MJPEG capture/playback 670 Support for the Linux Media Labs LML33 MJPEG capture/playback
656 card. 671 card.
657 672
658config VIDEO_ZORAN_LML33R10 673config VIDEO_ZORAN_LML33R10
659 tristate "Linux Media Labs LML33R10 support" 674 tristate "Linux Media Labs LML33R10 support"
660 depends on VIDEO_ZORAN 675 depends on VIDEO_ZORAN_ZR36060
661 select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO 676 select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO
662 select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO 677 select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
663 select VIDEO_ZORAN_ZR36060
664 help 678 help
665 support for the Linux Media Labs LML33R10 MJPEG capture/playback 679 support for the Linux Media Labs LML33R10 MJPEG capture/playback
666 card. 680 card.
667 681
668config VIDEO_ZORAN_AVS6EYES 682config VIDEO_ZORAN_AVS6EYES
669 tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" 683 tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
670 depends on VIDEO_ZORAN && EXPERIMENTAL && VIDEO_V4L1 684 depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1
671 select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO 685 select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
672 select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO 686 select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
673 select VIDEO_ZORAN_ZR36060
674 help 687 help
675 Support for the AverMedia 6 Eyes video surveillance card. 688 Support for the AverMedia 6 Eyes video surveillance card.
676 689
@@ -801,6 +814,8 @@ config USB_VIDEO_CLASS
801 814
802 For more information see: <http://linux-uvc.berlios.de/> 815 For more information see: <http://linux-uvc.berlios.de/>
803 816
817source "drivers/media/video/gspca/Kconfig"
818
804source "drivers/media/video/pvrusb2/Kconfig" 819source "drivers/media/video/pvrusb2/Kconfig"
805 820
806source "drivers/media/video/em28xx/Kconfig" 821source "drivers/media/video/em28xx/Kconfig"
@@ -905,12 +920,21 @@ config USB_STKWEBCAM
905 To compile this driver as a module, choose M here: the 920 To compile this driver as a module, choose M here: the
906 module will be called stkwebcam. 921 module will be called stkwebcam.
907 922
923config USB_S2255
924 tristate "USB Sensoray 2255 video capture device"
925 depends on VIDEO_V4L2
926 select VIDEOBUF_VMALLOC
927 default n
928 help
929 Say Y here if you want support for the Sensoray 2255 USB device.
930 This driver can be compiled as a module, called s2255drv.
931
908endif # V4L_USB_DRIVERS 932endif # V4L_USB_DRIVERS
909 933
910config SOC_CAMERA 934config SOC_CAMERA
911 tristate "SoC camera support" 935 tristate "SoC camera support"
912 depends on VIDEO_V4L2 && HAS_DMA 936 depends on VIDEO_V4L2 && HAS_DMA
913 select VIDEOBUF_DMA_SG 937 select VIDEOBUF_GEN
914 help 938 help
915 SoC Camera is a common API to several cameras, not connecting 939 SoC Camera is a common API to several cameras, not connecting
916 over a bus like PCI or USB. For example some i2c camera connected 940 over a bus like PCI or USB. For example some i2c camera connected
@@ -945,11 +969,26 @@ config MT9V022_PCA9536_SWITCH
945 Select this if your MT9V022 camera uses a PCA9536 I2C GPIO 969 Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
946 extender to switch between 8 and 10 bit datawidth modes 970 extender to switch between 8 and 10 bit datawidth modes
947 971
972config SOC_CAMERA_PLATFORM
973 tristate "platform camera support"
974 depends on SOC_CAMERA
975 help
976 This is a generic SoC camera platform driver, useful for testing
977
948config VIDEO_PXA27x 978config VIDEO_PXA27x
949 tristate "PXA27x Quick Capture Interface driver" 979 tristate "PXA27x Quick Capture Interface driver"
950 depends on VIDEO_DEV && PXA27x 980 depends on VIDEO_DEV && PXA27x
951 select SOC_CAMERA 981 select SOC_CAMERA
982 select VIDEOBUF_DMA_SG
952 ---help--- 983 ---help---
953 This is a v4l2 driver for the PXA27x Quick Capture Interface 984 This is a v4l2 driver for the PXA27x Quick Capture Interface
954 985
986config VIDEO_SH_MOBILE_CEU
987 tristate "SuperH Mobile CEU Interface driver"
988 depends on VIDEO_DEV
989 select SOC_CAMERA
990 select VIDEOBUF_DMA_CONTIG
991 ---help---
992 This is a v4l2 driver for the SuperH Mobile CEU Interface
993
955endif # VIDEO_CAPTURE_DRIVERS 994endif # VIDEO_CAPTURE_DRIVERS
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index ecbbfaab24d5..45d5db5abb1e 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_VIDEO_TUNER) += tuner.o
88 88
89obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o 89obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
90obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o 90obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
91obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
91obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o 92obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
92obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o 93obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
93obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o 94obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
@@ -117,11 +118,13 @@ obj-$(CONFIG_USB_SN9C102) += sn9c102/
117obj-$(CONFIG_USB_ET61X251) += et61x251/ 118obj-$(CONFIG_USB_ET61X251) += et61x251/
118obj-$(CONFIG_USB_PWC) += pwc/ 119obj-$(CONFIG_USB_PWC) += pwc/
119obj-$(CONFIG_USB_ZC0301) += zc0301/ 120obj-$(CONFIG_USB_ZC0301) += zc0301/
121obj-$(CONFIG_USB_GSPCA) += gspca/
120 122
121obj-$(CONFIG_USB_IBMCAM) += usbvideo/ 123obj-$(CONFIG_USB_IBMCAM) += usbvideo/
122obj-$(CONFIG_USB_KONICAWC) += usbvideo/ 124obj-$(CONFIG_USB_KONICAWC) += usbvideo/
123obj-$(CONFIG_USB_VICAM) += usbvideo/ 125obj-$(CONFIG_USB_VICAM) += usbvideo/
124obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/ 126obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/
127obj-$(CONFIG_USB_S2255) += s2255drv.o
125 128
126obj-$(CONFIG_VIDEO_IVTV) += ivtv/ 129obj-$(CONFIG_VIDEO_IVTV) += ivtv/
127obj-$(CONFIG_VIDEO_CX18) += cx18/ 130obj-$(CONFIG_VIDEO_CX18) += cx18/
@@ -130,9 +133,11 @@ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
130obj-$(CONFIG_VIDEO_CX23885) += cx23885/ 133obj-$(CONFIG_VIDEO_CX23885) += cx23885/
131 134
132obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o 135obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
136obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
133obj-$(CONFIG_SOC_CAMERA) += soc_camera.o 137obj-$(CONFIG_SOC_CAMERA) += soc_camera.o
134obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o 138obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
135obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o 139obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
140obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
136 141
137obj-$(CONFIG_VIDEO_AU0828) += au0828/ 142obj-$(CONFIG_VIDEO_AU0828) += au0828/
138 143
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index 8bfd5c75cb3a..ddd2a7964dec 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -516,7 +516,7 @@ bt819_detect_client (struct i2c_adapter *adapter,
516 516
517 dprintk(1, 517 dprintk(1,
518 KERN_INFO 518 KERN_INFO
519 "saa7111.c: detecting bt819 client on address 0x%x\n", 519 "bt819: detecting bt819 client on address 0x%x\n",
520 address << 1); 520 address << 1);
521 521
522 /* Check if the adapter supports the needed features */ 522 /* Check if the adapter supports the needed features */
diff --git a/drivers/media/video/bt8xx/bt832.c b/drivers/media/video/bt8xx/bt832.c
index f92f06dec0d0..216fc9680e80 100644
--- a/drivers/media/video/bt8xx/bt832.c
+++ b/drivers/media/video/bt8xx/bt832.c
@@ -179,7 +179,6 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
179 179
180 v4l_info(&t->client,"chip found @ 0x%x\n", addr<<1); 180 v4l_info(&t->client,"chip found @ 0x%x\n", addr<<1);
181 181
182
183 if(! bt832_init(&t->client)) { 182 if(! bt832_init(&t->client)) {
184 bt832_detach(&t->client); 183 bt832_detach(&t->client);
185 return -1; 184 return -1;
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 0165aac533bf..0ea559a7fe59 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -2448,7 +2448,7 @@ pix_format_set_size (struct v4l2_pix_format * f,
2448 } 2448 }
2449} 2449}
2450 2450
2451static int bttv_g_fmt_cap(struct file *file, void *priv, 2451static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
2452 struct v4l2_format *f) 2452 struct v4l2_format *f)
2453{ 2453{
2454 struct bttv_fh *fh = priv; 2454 struct bttv_fh *fh = priv;
@@ -2461,7 +2461,7 @@ static int bttv_g_fmt_cap(struct file *file, void *priv,
2461 return 0; 2461 return 0;
2462} 2462}
2463 2463
2464static int bttv_g_fmt_overlay(struct file *file, void *priv, 2464static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
2465 struct v4l2_format *f) 2465 struct v4l2_format *f)
2466{ 2466{
2467 struct bttv_fh *fh = priv; 2467 struct bttv_fh *fh = priv;
@@ -2472,7 +2472,7 @@ static int bttv_g_fmt_overlay(struct file *file, void *priv,
2472 return 0; 2472 return 0;
2473} 2473}
2474 2474
2475static int bttv_try_fmt_cap(struct file *file, void *priv, 2475static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
2476 struct v4l2_format *f) 2476 struct v4l2_format *f)
2477{ 2477{
2478 const struct bttv_format *fmt; 2478 const struct bttv_format *fmt;
@@ -2532,7 +2532,7 @@ static int bttv_try_fmt_cap(struct file *file, void *priv,
2532 return 0; 2532 return 0;
2533} 2533}
2534 2534
2535static int bttv_try_fmt_overlay(struct file *file, void *priv, 2535static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
2536 struct v4l2_format *f) 2536 struct v4l2_format *f)
2537{ 2537{
2538 struct bttv_fh *fh = priv; 2538 struct bttv_fh *fh = priv;
@@ -2542,7 +2542,7 @@ static int bttv_try_fmt_overlay(struct file *file, void *priv,
2542 /* adjust_crop */ 0); 2542 /* adjust_crop */ 0);
2543} 2543}
2544 2544
2545static int bttv_s_fmt_cap(struct file *file, void *priv, 2545static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
2546 struct v4l2_format *f) 2546 struct v4l2_format *f)
2547{ 2547{
2548 int retval; 2548 int retval;
@@ -2556,7 +2556,7 @@ static int bttv_s_fmt_cap(struct file *file, void *priv,
2556 if (0 != retval) 2556 if (0 != retval)
2557 return retval; 2557 return retval;
2558 2558
2559 retval = bttv_try_fmt_cap(file, priv, f); 2559 retval = bttv_try_fmt_vid_cap(file, priv, f);
2560 if (0 != retval) 2560 if (0 != retval)
2561 return retval; 2561 return retval;
2562 2562
@@ -2591,7 +2591,7 @@ static int bttv_s_fmt_cap(struct file *file, void *priv,
2591 return 0; 2591 return 0;
2592} 2592}
2593 2593
2594static int bttv_s_fmt_overlay(struct file *file, void *priv, 2594static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
2595 struct v4l2_format *f) 2595 struct v4l2_format *f)
2596{ 2596{
2597 struct bttv_fh *fh = priv; 2597 struct bttv_fh *fh = priv;
@@ -2661,7 +2661,7 @@ static int bttv_querycap(struct file *file, void *priv,
2661 return 0; 2661 return 0;
2662} 2662}
2663 2663
2664static int bttv_enum_fmt_vbi(struct file *file, void *priv, 2664static int bttv_enum_fmt_vbi_cap(struct file *file, void *priv,
2665 struct v4l2_fmtdesc *f) 2665 struct v4l2_fmtdesc *f)
2666{ 2666{
2667 if (0 != f->index) 2667 if (0 != f->index)
@@ -2692,7 +2692,7 @@ static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
2692 return i; 2692 return i;
2693} 2693}
2694 2694
2695static int bttv_enum_fmt_cap(struct file *file, void *priv, 2695static int bttv_enum_fmt_vid_cap(struct file *file, void *priv,
2696 struct v4l2_fmtdesc *f) 2696 struct v4l2_fmtdesc *f)
2697{ 2697{
2698 int rc = bttv_enum_fmt_cap_ovr(f); 2698 int rc = bttv_enum_fmt_cap_ovr(f);
@@ -2703,7 +2703,7 @@ static int bttv_enum_fmt_cap(struct file *file, void *priv,
2703 return 0; 2703 return 0;
2704} 2704}
2705 2705
2706static int bttv_enum_fmt_overlay(struct file *file, void *priv, 2706static int bttv_enum_fmt_vid_overlay(struct file *file, void *priv,
2707 struct v4l2_fmtdesc *f) 2707 struct v4l2_fmtdesc *f)
2708{ 2708{
2709 int rc; 2709 int rc;
@@ -3362,18 +3362,18 @@ static struct video_device bttv_video_template =
3362 .fops = &bttv_fops, 3362 .fops = &bttv_fops,
3363 .minor = -1, 3363 .minor = -1,
3364 .vidioc_querycap = bttv_querycap, 3364 .vidioc_querycap = bttv_querycap,
3365 .vidioc_enum_fmt_cap = bttv_enum_fmt_cap, 3365 .vidioc_enum_fmt_vid_cap = bttv_enum_fmt_vid_cap,
3366 .vidioc_g_fmt_cap = bttv_g_fmt_cap, 3366 .vidioc_g_fmt_vid_cap = bttv_g_fmt_vid_cap,
3367 .vidioc_try_fmt_cap = bttv_try_fmt_cap, 3367 .vidioc_try_fmt_vid_cap = bttv_try_fmt_vid_cap,
3368 .vidioc_s_fmt_cap = bttv_s_fmt_cap, 3368 .vidioc_s_fmt_vid_cap = bttv_s_fmt_vid_cap,
3369 .vidioc_enum_fmt_overlay = bttv_enum_fmt_overlay, 3369 .vidioc_enum_fmt_vid_overlay = bttv_enum_fmt_vid_overlay,
3370 .vidioc_g_fmt_overlay = bttv_g_fmt_overlay, 3370 .vidioc_g_fmt_vid_overlay = bttv_g_fmt_vid_overlay,
3371 .vidioc_try_fmt_overlay = bttv_try_fmt_overlay, 3371 .vidioc_try_fmt_vid_overlay = bttv_try_fmt_vid_overlay,
3372 .vidioc_s_fmt_overlay = bttv_s_fmt_overlay, 3372 .vidioc_s_fmt_vid_overlay = bttv_s_fmt_vid_overlay,
3373 .vidioc_enum_fmt_vbi = bttv_enum_fmt_vbi, 3373 .vidioc_enum_fmt_vbi_cap = bttv_enum_fmt_vbi_cap,
3374 .vidioc_g_fmt_vbi = bttv_g_fmt_vbi, 3374 .vidioc_g_fmt_vbi_cap = bttv_g_fmt_vbi_cap,
3375 .vidioc_try_fmt_vbi = bttv_try_fmt_vbi, 3375 .vidioc_try_fmt_vbi_cap = bttv_try_fmt_vbi_cap,
3376 .vidioc_s_fmt_vbi = bttv_s_fmt_vbi, 3376 .vidioc_s_fmt_vbi_cap = bttv_s_fmt_vbi_cap,
3377 .vidioc_g_audio = bttv_g_audio, 3377 .vidioc_g_audio = bttv_g_audio,
3378 .vidioc_s_audio = bttv_s_audio, 3378 .vidioc_s_audio = bttv_s_audio,
3379 .vidioc_cropcap = bttv_cropcap, 3379 .vidioc_cropcap = bttv_cropcap,
@@ -3705,7 +3705,7 @@ static void bttv_risc_disasm(struct bttv *btv,
3705 for (i = 0; i < (risc->size >> 2); i += n) { 3705 for (i = 0; i < (risc->size >> 2); i += n) {
3706 printk("%s: 0x%lx: ", btv->c.name, 3706 printk("%s: 0x%lx: ", btv->c.name,
3707 (unsigned long)(risc->dma + (i<<2))); 3707 (unsigned long)(risc->dma + (i<<2)));
3708 n = bttv_risc_decode(risc->cpu[i]); 3708 n = bttv_risc_decode(le32_to_cpu(risc->cpu[i]));
3709 for (j = 1; j < n; j++) 3709 for (j = 1; j < n; j++)
3710 printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n", 3710 printk("%s: 0x%lx: 0x%08x [ arg #%d ]\n",
3711 btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)), 3711 btv->c.name, (unsigned long)(risc->dma + ((i+j)<<2)),
@@ -3774,8 +3774,8 @@ static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
3774 printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n", 3774 printk("bttv%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
3775 btv->c.nr, 3775 btv->c.nr,
3776 (unsigned long)btv->main.dma, 3776 (unsigned long)btv->main.dma,
3777 (unsigned long)btv->main.cpu[RISC_SLOT_O_VBI+1], 3777 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
3778 (unsigned long)btv->main.cpu[RISC_SLOT_O_FIELD+1], 3778 (unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
3779 (unsigned long)rc); 3779 (unsigned long)rc);
3780 3780
3781 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) { 3781 if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
@@ -4188,6 +4188,7 @@ static struct video_device *vdev_init(struct bttv *btv,
4188 vfd->dev = &btv->c.pci->dev; 4188 vfd->dev = &btv->c.pci->dev;
4189 vfd->release = video_device_release; 4189 vfd->release = video_device_release;
4190 vfd->type = type; 4190 vfd->type = type;
4191 vfd->debug = bttv_debug;
4191 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)", 4192 snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
4192 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", 4193 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
4193 type_name, bttv_tvcards[btv->c.type].name); 4194 type_name, bttv_tvcards[btv->c.type].name);
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c
index 4d5b8035e466..bcd2cd240a16 100644
--- a/drivers/media/video/bt8xx/bttv-i2c.c
+++ b/drivers/media/video/bt8xx/bttv-i2c.c
@@ -36,11 +36,6 @@
36#include <linux/jiffies.h> 36#include <linux/jiffies.h>
37#include <asm/io.h> 37#include <asm/io.h>
38 38
39static struct i2c_algo_bit_data bttv_i2c_algo_bit_template;
40static struct i2c_adapter bttv_i2c_adap_sw_template;
41static struct i2c_adapter bttv_i2c_adap_hw_template;
42static struct i2c_client bttv_i2c_client_template;
43
44static int attach_inform(struct i2c_client *client); 39static int attach_inform(struct i2c_client *client);
45 40
46static int i2c_debug; 41static int i2c_debug;
@@ -104,7 +99,7 @@ static int bttv_bit_getsda(void *data)
104 return state; 99 return state;
105} 100}
106 101
107static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = { 102static struct i2c_algo_bit_data __devinitdata bttv_i2c_algo_bit_template = {
108 .setsda = bttv_bit_setsda, 103 .setsda = bttv_bit_setsda,
109 .setscl = bttv_bit_setscl, 104 .setscl = bttv_bit_setscl,
110 .getsda = bttv_bit_getsda, 105 .getsda = bttv_bit_getsda,
@@ -113,14 +108,6 @@ static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
113 .timeout = 200, 108 .timeout = 200,
114}; 109};
115 110
116static struct i2c_adapter bttv_i2c_adap_sw_template = {
117 .owner = THIS_MODULE,
118 .class = I2C_CLASS_TV_ANALOG,
119 .name = "bttv",
120 .id = I2C_HW_B_BT848,
121 .client_register = attach_inform,
122};
123
124/* ----------------------------------------------------------------------- */ 111/* ----------------------------------------------------------------------- */
125/* I2C functions - hardware i2c */ 112/* I2C functions - hardware i2c */
126 113
@@ -270,20 +257,11 @@ static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int
270 return retval; 257 return retval;
271} 258}
272 259
273static struct i2c_algorithm bttv_algo = { 260static const struct i2c_algorithm bttv_algo = {
274 .master_xfer = bttv_i2c_xfer, 261 .master_xfer = bttv_i2c_xfer,
275 .functionality = functionality, 262 .functionality = functionality,
276}; 263};
277 264
278static struct i2c_adapter bttv_i2c_adap_hw_template = {
279 .owner = THIS_MODULE,
280 .class = I2C_CLASS_TV_ANALOG,
281 .name = "bt878",
282 .id = I2C_HW_B_BT848 /* FIXME */,
283 .algo = &bttv_algo,
284 .client_register = attach_inform,
285};
286
287/* ----------------------------------------------------------------------- */ 265/* ----------------------------------------------------------------------- */
288/* I2C functions - common stuff */ 266/* I2C functions - common stuff */
289 267
@@ -332,10 +310,6 @@ void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
332 i2c_clients_command(&btv->c.i2c_adap, cmd, arg); 310 i2c_clients_command(&btv->c.i2c_adap, cmd, arg);
333} 311}
334 312
335static struct i2c_client bttv_i2c_client_template = {
336 .name = "bttv internal",
337};
338
339 313
340/* read I2C */ 314/* read I2C */
341int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) 315int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
@@ -417,29 +391,34 @@ static void do_i2c_scan(char *name, struct i2c_client *c)
417/* init + register i2c algo-bit adapter */ 391/* init + register i2c algo-bit adapter */
418int __devinit init_bttv_i2c(struct bttv *btv) 392int __devinit init_bttv_i2c(struct bttv *btv)
419{ 393{
420 memcpy(&btv->i2c_client, &bttv_i2c_client_template, 394 strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
421 sizeof(bttv_i2c_client_template));
422 395
423 if (i2c_hw) 396 if (i2c_hw)
424 btv->use_i2c_hw = 1; 397 btv->use_i2c_hw = 1;
425 if (btv->use_i2c_hw) { 398 if (btv->use_i2c_hw) {
426 /* bt878 */ 399 /* bt878 */
427 memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_hw_template, 400 strlcpy(btv->c.i2c_adap.name, "bt878",
428 sizeof(bttv_i2c_adap_hw_template)); 401 sizeof(btv->c.i2c_adap.name));
402 btv->c.i2c_adap.id = I2C_HW_B_BT848; /* FIXME */
403 btv->c.i2c_adap.algo = &bttv_algo;
429 } else { 404 } else {
430 /* bt848 */ 405 /* bt848 */
431 /* Prevents usage of invalid delay values */ 406 /* Prevents usage of invalid delay values */
432 if (i2c_udelay<5) 407 if (i2c_udelay<5)
433 i2c_udelay=5; 408 i2c_udelay=5;
434 bttv_i2c_algo_bit_template.udelay=i2c_udelay;
435 409
436 memcpy(&btv->c.i2c_adap, &bttv_i2c_adap_sw_template, 410 strlcpy(btv->c.i2c_adap.name, "bttv",
437 sizeof(bttv_i2c_adap_sw_template)); 411 sizeof(btv->c.i2c_adap.name));
412 btv->c.i2c_adap.id = I2C_HW_B_BT848;
438 memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template, 413 memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template,
439 sizeof(bttv_i2c_algo_bit_template)); 414 sizeof(bttv_i2c_algo_bit_template));
415 btv->i2c_algo.udelay = i2c_udelay;
440 btv->i2c_algo.data = btv; 416 btv->i2c_algo.data = btv;
441 btv->c.i2c_adap.algo_data = &btv->i2c_algo; 417 btv->c.i2c_adap.algo_data = &btv->i2c_algo;
442 } 418 }
419 btv->c.i2c_adap.owner = THIS_MODULE;
420 btv->c.i2c_adap.class = I2C_CLASS_TV_ANALOG;
421 btv->c.i2c_adap.client_register = attach_inform;
443 422
444 btv->c.i2c_adap.dev.parent = &btv->c.pci->dev; 423 btv->c.i2c_adap.dev.parent = &btv->c.pci->dev;
445 snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name), 424 snprintf(btv->c.i2c_adap.name, sizeof(btv->c.i2c_adap.name),
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index bfdbc469e30f..68f28e5fa040 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -303,7 +303,7 @@ static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
303 return 0; 303 return 0;
304} 304}
305 305
306int bttv_try_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt) 306int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
307{ 307{
308 struct bttv_fh *fh = f; 308 struct bttv_fh *fh = f;
309 struct bttv *btv = fh->btv; 309 struct bttv *btv = fh->btv;
@@ -321,7 +321,7 @@ int bttv_try_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
321} 321}
322 322
323 323
324int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt) 324int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
325{ 325{
326 struct bttv_fh *fh = f; 326 struct bttv_fh *fh = f;
327 struct bttv *btv = fh->btv; 327 struct bttv *btv = fh->btv;
@@ -369,7 +369,7 @@ int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
369} 369}
370 370
371 371
372int bttv_g_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt) 372int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
373{ 373{
374 struct bttv_fh *fh = f; 374 struct bttv_fh *fh = f;
375 const struct bttv_tvnorm *tvnorm; 375 const struct bttv_tvnorm *tvnorm;
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
index f2393202904b..6d93d16c96e4 100644
--- a/drivers/media/video/bt8xx/bttv.h
+++ b/drivers/media/video/bt8xx/bttv.h
@@ -299,7 +299,6 @@ extern int bttv_write_gpio(unsigned int card,
299/* ---------------------------------------------------------- */ 299/* ---------------------------------------------------------- */
300/* sysfs/driver-moded based gpio access interface */ 300/* sysfs/driver-moded based gpio access interface */
301 301
302
303struct bttv_sub_device { 302struct bttv_sub_device {
304 struct device dev; 303 struct device dev;
305 struct bttv_core *core; 304 struct bttv_core *core;
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index 27da7b423275..08ef54a22c9e 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -39,7 +39,6 @@
39#include <linux/scatterlist.h> 39#include <linux/scatterlist.h>
40#include <asm/io.h> 40#include <asm/io.h>
41#include <media/v4l2-common.h> 41#include <media/v4l2-common.h>
42
43#include <linux/device.h> 42#include <linux/device.h>
44#include <media/videobuf-dma-sg.h> 43#include <media/videobuf-dma-sg.h>
45#include <media/tveeprom.h> 44#include <media/tveeprom.h>
@@ -254,21 +253,19 @@ int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
254/* ---------------------------------------------------------- */ 253/* ---------------------------------------------------------- */
255/* bttv-vbi.c */ 254/* bttv-vbi.c */
256 255
257int bttv_try_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f); 256int bttv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
258int bttv_g_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f); 257int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
259int bttv_s_fmt_vbi(struct file *file, void *fh, struct v4l2_format *f); 258int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
260 259
261extern struct videobuf_queue_ops bttv_vbi_qops; 260extern struct videobuf_queue_ops bttv_vbi_qops;
262 261
263/* ---------------------------------------------------------- */ 262/* ---------------------------------------------------------- */
264/* bttv-gpio.c */ 263/* bttv-gpio.c */
265 264
266
267extern struct bus_type bttv_sub_bus_type; 265extern struct bus_type bttv_sub_bus_type;
268int bttv_sub_add_device(struct bttv_core *core, char *name); 266int bttv_sub_add_device(struct bttv_core *core, char *name);
269int bttv_sub_del_devices(struct bttv_core *core); 267int bttv_sub_del_devices(struct bttv_core *core);
270 268
271
272/* ---------------------------------------------------------- */ 269/* ---------------------------------------------------------- */
273/* bttv-driver.c */ 270/* bttv-driver.c */
274 271
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c
index 5195b1f3378a..d99453faaab7 100644
--- a/drivers/media/video/cafe_ccic.c
+++ b/drivers/media/video/cafe_ccic.c
@@ -1593,7 +1593,7 @@ static struct v4l2_pix_format cafe_def_pix_format = {
1593 .sizeimage = VGA_WIDTH*VGA_HEIGHT*2, 1593 .sizeimage = VGA_WIDTH*VGA_HEIGHT*2,
1594}; 1594};
1595 1595
1596static int cafe_vidioc_enum_fmt_cap(struct file *filp, 1596static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp,
1597 void *priv, struct v4l2_fmtdesc *fmt) 1597 void *priv, struct v4l2_fmtdesc *fmt)
1598{ 1598{
1599 struct cafe_camera *cam = priv; 1599 struct cafe_camera *cam = priv;
@@ -1608,7 +1608,7 @@ static int cafe_vidioc_enum_fmt_cap(struct file *filp,
1608} 1608}
1609 1609
1610 1610
1611static int cafe_vidioc_try_fmt_cap (struct file *filp, void *priv, 1611static int cafe_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
1612 struct v4l2_format *fmt) 1612 struct v4l2_format *fmt)
1613{ 1613{
1614 struct cafe_camera *cam = priv; 1614 struct cafe_camera *cam = priv;
@@ -1620,7 +1620,7 @@ static int cafe_vidioc_try_fmt_cap (struct file *filp, void *priv,
1620 return ret; 1620 return ret;
1621} 1621}
1622 1622
1623static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv, 1623static int cafe_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
1624 struct v4l2_format *fmt) 1624 struct v4l2_format *fmt)
1625{ 1625{
1626 struct cafe_camera *cam = priv; 1626 struct cafe_camera *cam = priv;
@@ -1635,7 +1635,7 @@ static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv,
1635 /* 1635 /*
1636 * See if the formatting works in principle. 1636 * See if the formatting works in principle.
1637 */ 1637 */
1638 ret = cafe_vidioc_try_fmt_cap(filp, priv, fmt); 1638 ret = cafe_vidioc_try_fmt_vid_cap(filp, priv, fmt);
1639 if (ret) 1639 if (ret)
1640 return ret; 1640 return ret;
1641 /* 1641 /*
@@ -1670,7 +1670,7 @@ static int cafe_vidioc_s_fmt_cap(struct file *filp, void *priv,
1670 * The V4l2 spec wants us to be smarter, and actually get this from 1670 * The V4l2 spec wants us to be smarter, and actually get this from
1671 * the camera (and not mess with it at open time). Someday. 1671 * the camera (and not mess with it at open time). Someday.
1672 */ 1672 */
1673static int cafe_vidioc_g_fmt_cap(struct file *filp, void *priv, 1673static int cafe_vidioc_g_fmt_vid_cap(struct file *filp, void *priv,
1674 struct v4l2_format *f) 1674 struct v4l2_format *f)
1675{ 1675{
1676 struct cafe_camera *cam = priv; 1676 struct cafe_camera *cam = priv;
@@ -1780,10 +1780,10 @@ static struct video_device cafe_v4l_template = {
1780 .release = cafe_v4l_dev_release, 1780 .release = cafe_v4l_dev_release,
1781 1781
1782 .vidioc_querycap = cafe_vidioc_querycap, 1782 .vidioc_querycap = cafe_vidioc_querycap,
1783 .vidioc_enum_fmt_cap = cafe_vidioc_enum_fmt_cap, 1783 .vidioc_enum_fmt_vid_cap = cafe_vidioc_enum_fmt_vid_cap,
1784 .vidioc_try_fmt_cap = cafe_vidioc_try_fmt_cap, 1784 .vidioc_try_fmt_vid_cap = cafe_vidioc_try_fmt_vid_cap,
1785 .vidioc_s_fmt_cap = cafe_vidioc_s_fmt_cap, 1785 .vidioc_s_fmt_vid_cap = cafe_vidioc_s_fmt_vid_cap,
1786 .vidioc_g_fmt_cap = cafe_vidioc_g_fmt_cap, 1786 .vidioc_g_fmt_vid_cap = cafe_vidioc_g_fmt_vid_cap,
1787 .vidioc_enum_input = cafe_vidioc_enum_input, 1787 .vidioc_enum_input = cafe_vidioc_enum_input,
1788 .vidioc_g_input = cafe_vidioc_g_input, 1788 .vidioc_g_input = cafe_vidioc_g_input,
1789 .vidioc_s_input = cafe_vidioc_s_input, 1789 .vidioc_s_input = cafe_vidioc_s_input,
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index cefd1381e8de..54de0cd482e9 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -884,6 +884,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
884 case VIDIOC_G_INPUT32: 884 case VIDIOC_G_INPUT32:
885 case VIDIOC_S_INPUT32: 885 case VIDIOC_S_INPUT32:
886 case VIDIOC_TRY_FMT32: 886 case VIDIOC_TRY_FMT32:
887 case VIDIOC_S_HW_FREQ_SEEK:
887 ret = do_video_ioctl(file, cmd, arg); 888 ret = do_video_ioctl(file, cmd, arg);
888 break; 889 break;
889 890
diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c
index 03411503457e..1c3fa3a7470a 100644
--- a/drivers/media/video/cs5345.c
+++ b/drivers/media/video/cs5345.c
@@ -173,4 +173,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
173 .probe = cs5345_probe, 173 .probe = cs5345_probe,
174 .id_table = cs5345_id, 174 .id_table = cs5345_id,
175}; 175};
176
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c
index d965af860ab2..645b339152d3 100644
--- a/drivers/media/video/cs53l32a.c
+++ b/drivers/media/video/cs53l32a.c
@@ -43,7 +43,6 @@ MODULE_PARM_DESC(debug, "Debugging messages\n\t\t\t0=Off (default), 1=On");
43 43
44static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END }; 44static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
45 45
46
47I2C_CLIENT_INSMOD; 46I2C_CLIENT_INSMOD;
48 47
49/* ----------------------------------------------------------------------- */ 48/* ----------------------------------------------------------------------- */
@@ -189,4 +188,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
189 .probe = cs53l32a_probe, 188 .probe = cs53l32a_probe,
190 .id_table = cs53l32a_id, 189 .id_table = cs53l32a_id,
191}; 190};
192
diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c
index 1adc404d955e..6d5b94fc7087 100644
--- a/drivers/media/video/cx18/cx18-audio.c
+++ b/drivers/media/video/cx18/cx18-audio.c
@@ -26,13 +26,17 @@
26#include "cx18-cards.h" 26#include "cx18-cards.h"
27#include "cx18-audio.h" 27#include "cx18-audio.h"
28 28
29#define CX18_AUDIO_ENABLE 0xc72014
30
29/* Selects the audio input and output according to the current 31/* Selects the audio input and output according to the current
30 settings. */ 32 settings. */
31int cx18_audio_set_io(struct cx18 *cx) 33int cx18_audio_set_io(struct cx18 *cx)
32{ 34{
33 struct v4l2_routing route; 35 struct v4l2_routing route;
34 u32 audio_input; 36 u32 audio_input;
37 u32 val;
35 int mux_input; 38 int mux_input;
39 int err;
36 40
37 /* Determine which input to use */ 41 /* Determine which input to use */
38 if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { 42 if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
@@ -51,8 +55,17 @@ int cx18_audio_set_io(struct cx18 *cx)
51 cx18_i2c_hw(cx, cx->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route); 55 cx18_i2c_hw(cx, cx->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route);
52 56
53 route.input = audio_input; 57 route.input = audio_input;
54 return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, 58 err = cx18_i2c_hw(cx, cx->card->hw_audio_ctrl,
55 VIDIOC_INT_S_AUDIO_ROUTING, &route); 59 VIDIOC_INT_S_AUDIO_ROUTING, &route);
60 if (err)
61 return err;
62
63 val = read_reg(CX18_AUDIO_ENABLE) & ~0x30;
64 val |= (audio_input > CX18_AV_AUDIO_SERIAL2) ? 0x20 :
65 (audio_input << 4);
66 write_reg(val | 0xb00, CX18_AUDIO_ENABLE);
67 cx18_vapi(cx, CX18_APU_RESETAI, 1, 0);
68 return 0;
56} 69}
57 70
58void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route) 71void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route)
diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
index 2dc3a5dd170e..c40a286de1b9 100644
--- a/drivers/media/video/cx18/cx18-av-audio.c
+++ b/drivers/media/video/cx18/cx18-av-audio.c
@@ -34,7 +34,7 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
34 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */ 34 /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
35 cx18_av_write(cx, 0x127, 0x50); 35 cx18_av_write(cx, 0x127, 0x50);
36 36
37 if (state->aud_input != CX18_AV_AUDIO_SERIAL) { 37 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
38 switch (freq) { 38 switch (freq) {
39 case 32000: 39 case 32000:
40 /* VID_PLL and AUX_PLL */ 40 /* VID_PLL and AUX_PLL */
@@ -148,7 +148,7 @@ void cx18_av_audio_set_path(struct cx18 *cx)
148 /* Mute everything to prevent the PFFT! */ 148 /* Mute everything to prevent the PFFT! */
149 cx18_av_write(cx, 0x8d3, 0x1f); 149 cx18_av_write(cx, 0x8d3, 0x1f);
150 150
151 if (state->aud_input == CX18_AV_AUDIO_SERIAL) { 151 if (state->aud_input <= CX18_AV_AUDIO_SERIAL2) {
152 /* Set Path1 to Serial Audio Input */ 152 /* Set Path1 to Serial Audio Input */
153 cx18_av_write4(cx, 0x8d0, 0x01011012); 153 cx18_av_write4(cx, 0x8d0, 0x01011012);
154 154
@@ -165,7 +165,7 @@ void cx18_av_audio_set_path(struct cx18 *cx)
165 /* deassert soft reset */ 165 /* deassert soft reset */
166 cx18_av_and_or(cx, 0x810, ~0x1, 0x00); 166 cx18_av_and_or(cx, 0x810, ~0x1, 0x00);
167 167
168 if (state->aud_input != CX18_AV_AUDIO_SERIAL) { 168 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
169 /* When the microcontroller detects the 169 /* When the microcontroller detects the
170 * audio format, it will unmute the lines */ 170 * audio format, it will unmute the lines */
171 cx18_av_and_or(cx, 0x803, ~0x10, 0x10); 171 cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
@@ -271,7 +271,7 @@ static void set_mute(struct cx18 *cx, int mute)
271{ 271{
272 struct cx18_av_state *state = &cx->av_state; 272 struct cx18_av_state *state = &cx->av_state;
273 273
274 if (state->aud_input != CX18_AV_AUDIO_SERIAL) { 274 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
275 /* Must turn off microcontroller in order to mute sound. 275 /* Must turn off microcontroller in order to mute sound.
276 * Not sure if this is the best method, but it does work. 276 * Not sure if this is the best method, but it does work.
277 * If the microcontroller is running, then it will undo any 277 * If the microcontroller is running, then it will undo any
@@ -298,14 +298,14 @@ int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
298 298
299 switch (cmd) { 299 switch (cmd) {
300 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 300 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
301 if (state->aud_input != CX18_AV_AUDIO_SERIAL) { 301 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
302 cx18_av_and_or(cx, 0x803, ~0x10, 0); 302 cx18_av_and_or(cx, 0x803, ~0x10, 0);
303 cx18_av_write(cx, 0x8d3, 0x1f); 303 cx18_av_write(cx, 0x8d3, 0x1f);
304 } 304 }
305 cx18_av_and_or(cx, 0x810, ~0x1, 1); 305 cx18_av_and_or(cx, 0x810, ~0x1, 1);
306 retval = set_audclk_freq(cx, *(u32 *)arg); 306 retval = set_audclk_freq(cx, *(u32 *)arg);
307 cx18_av_and_or(cx, 0x810, ~0x1, 0); 307 cx18_av_and_or(cx, 0x810, ~0x1, 0);
308 if (state->aud_input != CX18_AV_AUDIO_SERIAL) 308 if (state->aud_input > CX18_AV_AUDIO_SERIAL2)
309 cx18_av_and_or(cx, 0x803, ~0x10, 0x10); 309 cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
310 return retval; 310 return retval;
311 311
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index faca43eb940f..3b0a2c450605 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -69,58 +69,6 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
69 or_value); 69 or_value);
70} 70}
71 71
72int cx18_av_write_no_acfg(struct cx18 *cx, u16 addr, u8 value, int no_acfg_mask)
73{
74 int retval;
75 u32 saved_reg[8] = {0};
76
77 if (no_acfg_mask & CXADEC_NO_ACFG_AFE) {
78 saved_reg[0] = cx18_av_read4(cx, CXADEC_CHIP_CTRL);
79 saved_reg[1] = cx18_av_read4(cx, CXADEC_AFE_CTRL);
80 }
81
82 if (no_acfg_mask & CXADEC_NO_ACFG_PLL) {
83 saved_reg[2] = cx18_av_read4(cx, CXADEC_PLL_CTRL1);
84 saved_reg[3] = cx18_av_read4(cx, CXADEC_VID_PLL_FRAC);
85 }
86
87 if (no_acfg_mask & CXADEC_NO_ACFG_VID) {
88 saved_reg[4] = cx18_av_read4(cx, CXADEC_HORIZ_TIM_CTRL);
89 saved_reg[5] = cx18_av_read4(cx, CXADEC_VERT_TIM_CTRL);
90 saved_reg[6] = cx18_av_read4(cx, CXADEC_SRC_COMB_CFG);
91 saved_reg[7] = cx18_av_read4(cx, CXADEC_CHROMA_VBIOFF_CFG);
92 }
93
94 retval = cx18_av_write(cx, addr, value);
95
96 if (no_acfg_mask & CXADEC_NO_ACFG_AFE) {
97 cx18_av_write4(cx, CXADEC_CHIP_CTRL, saved_reg[0]);
98 cx18_av_write4(cx, CXADEC_AFE_CTRL, saved_reg[1]);
99 }
100
101 if (no_acfg_mask & CXADEC_NO_ACFG_PLL) {
102 cx18_av_write4(cx, CXADEC_PLL_CTRL1, saved_reg[2]);
103 cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, saved_reg[3]);
104 }
105
106 if (no_acfg_mask & CXADEC_NO_ACFG_VID) {
107 cx18_av_write4(cx, CXADEC_HORIZ_TIM_CTRL, saved_reg[4]);
108 cx18_av_write4(cx, CXADEC_VERT_TIM_CTRL, saved_reg[5]);
109 cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, saved_reg[6]);
110 cx18_av_write4(cx, CXADEC_CHROMA_VBIOFF_CFG, saved_reg[7]);
111 }
112
113 return retval;
114}
115
116int cx18_av_and_or_no_acfg(struct cx18 *cx, u16 addr, unsigned and_mask,
117 u8 or_value, int no_acfg_mask)
118{
119 return cx18_av_write_no_acfg(cx, addr,
120 (cx18_av_read(cx, addr) & and_mask) |
121 or_value, no_acfg_mask);
122}
123
124/* ----------------------------------------------------------------------- */ 72/* ----------------------------------------------------------------------- */
125 73
126static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, 74static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
@@ -132,6 +80,7 @@ static void log_video_status(struct cx18 *cx);
132 80
133static void cx18_av_initialize(struct cx18 *cx) 81static void cx18_av_initialize(struct cx18 *cx)
134{ 82{
83 struct cx18_av_state *state = &cx->av_state;
135 u32 v; 84 u32 v;
136 85
137 cx18_av_loadfw(cx); 86 cx18_av_loadfw(cx);
@@ -211,6 +160,149 @@ static void cx18_av_initialize(struct cx18 *cx)
211/* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x6628021F); */ 160/* CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x6628021F); */
212/* } */ 161/* } */
213 cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F); 162 cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F);
163 state->default_volume = 228 - cx18_av_read(cx, 0x8d4);
164 state->default_volume = ((state->default_volume / 2) + 23) << 9;
165}
166
167/* ----------------------------------------------------------------------- */
168
169void cx18_av_std_setup(struct cx18 *cx)
170{
171 struct cx18_av_state *state = &cx->av_state;
172 v4l2_std_id std = state->std;
173 int hblank, hactive, burst, vblank, vactive, sc;
174 int vblank656, src_decimation;
175 int luma_lpf, uv_lpf, comb;
176 u32 pll_int, pll_frac, pll_post;
177
178 /* datasheet startup, step 8d */
179 if (std & ~V4L2_STD_NTSC)
180 cx18_av_write(cx, 0x49f, 0x11);
181 else
182 cx18_av_write(cx, 0x49f, 0x14);
183
184 if (std & V4L2_STD_625_50) {
185 hblank = 132;
186 hactive = 720;
187 burst = 93;
188 vblank = 36;
189 vactive = 580;
190 vblank656 = 40;
191 src_decimation = 0x21f;
192
193 luma_lpf = 2;
194 if (std & V4L2_STD_PAL) {
195 uv_lpf = 1;
196 comb = 0x20;
197 sc = 688739;
198 } else if (std == V4L2_STD_PAL_Nc) {
199 uv_lpf = 1;
200 comb = 0x20;
201 sc = 556453;
202 } else { /* SECAM */
203 uv_lpf = 0;
204 comb = 0;
205 sc = 672351;
206 }
207 } else {
208 hactive = 720;
209 hblank = 122;
210 vactive = 487;
211 luma_lpf = 1;
212 uv_lpf = 1;
213 vblank = 26;
214 vblank656 = 26;
215
216 src_decimation = 0x21f;
217 if (std == V4L2_STD_PAL_60) {
218 burst = 0x5b;
219 luma_lpf = 2;
220 comb = 0x20;
221 sc = 688739;
222 } else if (std == V4L2_STD_PAL_M) {
223 burst = 0x61;
224 comb = 0x20;
225 sc = 555452;
226 } else {
227 burst = 0x5b;
228 comb = 0x66;
229 sc = 556063;
230 }
231 }
232
233 /* DEBUG: Displays configured PLL frequency */
234 pll_int = cx18_av_read(cx, 0x108);
235 pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
236 pll_post = cx18_av_read(cx, 0x109);
237 CX18_DEBUG_INFO("PLL regs = int: %u, frac: %u, post: %u\n",
238 pll_int, pll_frac, pll_post);
239
240 if (pll_post) {
241 int fin, fsc;
242 int pll = 28636363L * ((((u64)pll_int) << 25) + pll_frac);
243
244 pll >>= 25;
245 pll /= pll_post;
246 CX18_DEBUG_INFO("PLL = %d.%06d MHz\n",
247 pll / 1000000, pll % 1000000);
248 CX18_DEBUG_INFO("PLL/8 = %d.%06d MHz\n",
249 pll / 8000000, (pll / 8) % 1000000);
250
251 fin = ((u64)src_decimation * pll) >> 12;
252 CX18_DEBUG_INFO("ADC Sampling freq = %d.%06d MHz\n",
253 fin / 1000000, fin % 1000000);
254
255 fsc = (((u64)sc) * pll) >> 24L;
256 CX18_DEBUG_INFO("Chroma sub-carrier freq = %d.%06d MHz\n",
257 fsc / 1000000, fsc % 1000000);
258
259 CX18_DEBUG_INFO("hblank %i, hactive %i, "
260 "vblank %i , vactive %i, vblank656 %i, src_dec %i,"
261 "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
262 " sc 0x%06x\n",
263 hblank, hactive, vblank, vactive, vblank656,
264 src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
265 }
266
267 /* Sets horizontal blanking delay and active lines */
268 cx18_av_write(cx, 0x470, hblank);
269 cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
270 (hactive << 4)));
271 cx18_av_write(cx, 0x472, hactive >> 4);
272
273 /* Sets burst gate delay */
274 cx18_av_write(cx, 0x473, burst);
275
276 /* Sets vertical blanking delay and active duration */
277 cx18_av_write(cx, 0x474, vblank);
278 cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
279 (vactive << 4)));
280 cx18_av_write(cx, 0x476, vactive >> 4);
281 cx18_av_write(cx, 0x477, vblank656);
282
283 /* Sets src decimation rate */
284 cx18_av_write(cx, 0x478, 0xff & src_decimation);
285 cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
286
287 /* Sets Luma and UV Low pass filters */
288 cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
289
290 /* Enables comb filters */
291 cx18_av_write(cx, 0x47b, comb);
292
293 /* Sets SC Step*/
294 cx18_av_write(cx, 0x47c, sc);
295 cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
296 cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
297
298 /* Sets VBI parameters */
299 if (std & V4L2_STD_625_50) {
300 cx18_av_write(cx, 0x47f, 0x01);
301 state->vbi_line_offset = 5;
302 } else {
303 cx18_av_write(cx, 0x47f, 0x00);
304 state->vbi_line_offset = 8;
305 }
214} 306}
215 307
216/* ----------------------------------------------------------------------- */ 308/* ----------------------------------------------------------------------- */
@@ -221,16 +313,9 @@ static void input_change(struct cx18 *cx)
221 v4l2_std_id std = state->std; 313 v4l2_std_id std = state->std;
222 314
223 /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */ 315 /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
224 if (std & V4L2_STD_SECAM) 316 cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
225 cx18_av_write_no_acfg(cx, 0x402, 0, CXADEC_NO_ACFG_ALL); 317 cx18_av_and_or(cx, 0x401, ~0x60, 0);
226 else { 318 cx18_av_and_or(cx, 0x401, ~0x60, 0x60);
227 cx18_av_write_no_acfg(cx, 0x402, 0x04, CXADEC_NO_ACFG_ALL);
228 cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
229 }
230 cx18_av_and_or_no_acfg(cx, 0x401, ~0x60, 0,
231 CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID);
232 cx18_av_and_or_no_acfg(cx, 0x401, ~0x60, 0x60,
233 CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID);
234 319
235 if (std & V4L2_STD_525_60) { 320 if (std & V4L2_STD_525_60) {
236 if (std == V4L2_STD_NTSC_M_JP) { 321 if (std == V4L2_STD_NTSC_M_JP) {
@@ -300,7 +385,8 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
300 } 385 }
301 386
302 switch (aud_input) { 387 switch (aud_input) {
303 case CX18_AV_AUDIO_SERIAL: 388 case CX18_AV_AUDIO_SERIAL1:
389 case CX18_AV_AUDIO_SERIAL2:
304 /* do nothing, use serial audio input */ 390 /* do nothing, use serial audio input */
305 break; 391 break;
306 case CX18_AV_AUDIO4: reg &= ~0x30; break; 392 case CX18_AV_AUDIO4: reg &= ~0x30; break;
@@ -316,8 +402,7 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
316 402
317 cx18_av_write(cx, 0x103, reg); 403 cx18_av_write(cx, 0x103, reg);
318 /* Set INPUT_MODE to Composite (0) or S-Video (1) */ 404 /* Set INPUT_MODE to Composite (0) or S-Video (1) */
319 cx18_av_and_or_no_acfg(cx, 0x401, ~0x6, is_composite ? 0 : 0x02, 405 cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02);
320 CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID);
321 /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ 406 /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
322 cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); 407 cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
323 /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */ 408 /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
@@ -373,13 +458,13 @@ static int set_v4lstd(struct cx18 *cx)
373 This happens for example with the Yuan MPC622. */ 458 This happens for example with the Yuan MPC622. */
374 if (fmt >= 4 && fmt < 8) { 459 if (fmt >= 4 && fmt < 8) {
375 /* Set format to NTSC-M */ 460 /* Set format to NTSC-M */
376 cx18_av_and_or_no_acfg(cx, 0x400, ~0xf, 1, CXADEC_NO_ACFG_AFE); 461 cx18_av_and_or(cx, 0x400, ~0xf, 1);
377 /* Turn off LCOMB */ 462 /* Turn off LCOMB */
378 cx18_av_and_or(cx, 0x47b, ~6, 0); 463 cx18_av_and_or(cx, 0x47b, ~6, 0);
379 } 464 }
380 cx18_av_and_or_no_acfg(cx, 0x400, ~0xf, fmt, CXADEC_NO_ACFG_AFE); 465 cx18_av_and_or(cx, 0x400, ~0x2f, fmt | 0x20);
381 cx18_av_and_or_no_acfg(cx, 0x403, ~0x3, pal_m, CXADEC_NO_ACFG_ALL); 466 cx18_av_and_or(cx, 0x403, ~0x3, pal_m);
382 cx18_av_vbi_setup(cx); 467 cx18_av_std_setup(cx);
383 input_change(cx); 468 input_change(cx);
384 return 0; 469 return 0;
385} 470}
@@ -618,6 +703,8 @@ int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg)
618 703
619 switch (qc->id) { 704 switch (qc->id) {
620 case V4L2_CID_AUDIO_VOLUME: 705 case V4L2_CID_AUDIO_VOLUME:
706 return v4l2_ctrl_query_fill(qc, 0, 65535,
707 65535 / 100, state->default_volume);
621 case V4L2_CID_AUDIO_MUTE: 708 case V4L2_CID_AUDIO_MUTE:
622 case V4L2_CID_AUDIO_BALANCE: 709 case V4L2_CID_AUDIO_BALANCE:
623 case V4L2_CID_AUDIO_BASS: 710 case V4L2_CID_AUDIO_BASS:
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h
index c172823ce1d8..eb61fa1e0965 100644
--- a/drivers/media/video/cx18/cx18-av-core.h
+++ b/drivers/media/video/cx18/cx18-av-core.h
@@ -62,7 +62,8 @@ enum cx18_av_video_input {
62 62
63enum cx18_av_audio_input { 63enum cx18_av_audio_input {
64 /* Audio inputs: serial or In4-In8 */ 64 /* Audio inputs: serial or In4-In8 */
65 CX18_AV_AUDIO_SERIAL, 65 CX18_AV_AUDIO_SERIAL1,
66 CX18_AV_AUDIO_SERIAL2,
66 CX18_AV_AUDIO4 = 4, 67 CX18_AV_AUDIO4 = 4,
67 CX18_AV_AUDIO5, 68 CX18_AV_AUDIO5,
68 CX18_AV_AUDIO6, 69 CX18_AV_AUDIO6,
@@ -78,6 +79,7 @@ struct cx18_av_state {
78 u32 audclk_freq; 79 u32 audclk_freq;
79 int audmode; 80 int audmode;
80 int vbi_line_offset; 81 int vbi_line_offset;
82 int default_volume;
81 u32 id; 83 u32 id;
82 u32 rev; 84 u32 rev;
83 int is_initialized; 85 int is_initialized;
@@ -295,25 +297,16 @@ struct cx18_av_state {
295#define CXADEC_SELECT_AUDIO_STANDARD_FM 0xF9 /* FM radio */ 297#define CXADEC_SELECT_AUDIO_STANDARD_FM 0xF9 /* FM radio */
296#define CXADEC_SELECT_AUDIO_STANDARD_AUTO 0xFF /* Auto detect */ 298#define CXADEC_SELECT_AUDIO_STANDARD_AUTO 0xFF /* Auto detect */
297 299
298/* Flags on what to preserve on write to 0x400-0x403 with cx18_av_.*_no_acfg()*/
299#define CXADEC_NO_ACFG_AFE 0x01 /* Preserve 0x100-0x107 */
300#define CXADEC_NO_ACFG_PLL 0x02 /* Preserve 0x108-0x10f */
301#define CXADEC_NO_ACFG_VID 0x04 /* Preserve 0x470-0x47f */
302#define CXADEC_NO_ACFG_ALL 0x07
303
304/* ----------------------------------------------------------------------- */ 300/* ----------------------------------------------------------------------- */
305/* cx18_av-core.c */ 301/* cx18_av-core.c */
306int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); 302int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
307int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); 303int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
308int cx18_av_write_no_acfg(struct cx18 *cx, u16 addr, u8 value,
309 int no_acfg_mask);
310u8 cx18_av_read(struct cx18 *cx, u16 addr); 304u8 cx18_av_read(struct cx18 *cx, u16 addr);
311u32 cx18_av_read4(struct cx18 *cx, u16 addr); 305u32 cx18_av_read4(struct cx18 *cx, u16 addr);
312int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); 306int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
313int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); 307int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
314int cx18_av_and_or_no_acfg(struct cx18 *cx, u16 addr, unsigned mask, u8 value,
315 int no_acfg_mask);
316int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); 308int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg);
309void cx18_av_std_setup(struct cx18 *cx);
317 310
318/* ----------------------------------------------------------------------- */ 311/* ----------------------------------------------------------------------- */
319/* cx18_av-firmware.c */ 312/* cx18_av-firmware.c */
@@ -326,7 +319,6 @@ void cx18_av_audio_set_path(struct cx18 *cx);
326 319
327/* ----------------------------------------------------------------------- */ 320/* ----------------------------------------------------------------------- */
328/* cx18_av-vbi.c */ 321/* cx18_av-vbi.c */
329void cx18_av_vbi_setup(struct cx18 *cx);
330int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg); 322int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg);
331 323
332#endif 324#endif
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
index a1a6af6c1c8f..834b9248242e 100644
--- a/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/drivers/media/video/cx18/cx18-av-firmware.c
@@ -22,6 +22,7 @@
22#include "cx18-driver.h" 22#include "cx18-driver.h"
23#include <linux/firmware.h> 23#include <linux/firmware.h>
24 24
25#define CX18_AUDIO_ENABLE 0xc72014
25#define FWFILE "v4l-cx23418-dig.fw" 26#define FWFILE "v4l-cx23418-dig.fw"
26 27
27int cx18_av_loadfw(struct cx18 *cx) 28int cx18_av_loadfw(struct cx18 *cx)
@@ -31,40 +32,58 @@ int cx18_av_loadfw(struct cx18 *cx)
31 u32 v; 32 u32 v;
32 const u8 *ptr; 33 const u8 *ptr;
33 int i; 34 int i;
35 int retries = 0;
34 36
35 if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) { 37 if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
36 CX18_ERR("unable to open firmware %s\n", FWFILE); 38 CX18_ERR("unable to open firmware %s\n", FWFILE);
37 return -EINVAL; 39 return -EINVAL;
38 } 40 }
39 41
40 cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000); 42 /* The firmware load often has byte errors, so allow for several
41 cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6); /* Byte 0 */ 43 retries, both at byte level and at the firmware load level. */
42 44 while (retries < 5) {
43 /* Reset the Mako core (Register is undocumented.) */ 45 cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
44 cx18_av_write4(cx, 0x8100, 0x00010000); 46 cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6);
45 47
46 /* Put the 8051 in reset and enable firmware upload */ 48 /* Reset the Mako core (Register is undocumented.) */
47 cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000); 49 cx18_av_write4(cx, 0x8100, 0x00010000);
48 50
49 ptr = fw->data; 51 /* Put the 8051 in reset and enable firmware upload */
50 size = fw->size; 52 cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
51 53
52 for (i = 0; i < size; i++) { 54 ptr = fw->data;
53 u32 dl_control = 0x0F000000 | ((u32)ptr[i] << 16); 55 size = fw->size;
54 u32 value = 0; 56
55 int retries; 57 for (i = 0; i < size; i++) {
56 58 u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
57 for (retries = 0; retries < 5; retries++) { 59 u32 value = 0;
58 cx18_av_write4(cx, CXADEC_DL_CTL, dl_control); 60 int retries;
59 value = cx18_av_read4(cx, CXADEC_DL_CTL); 61
60 if ((value & 0x3F00) == (dl_control & 0x3F00)) 62 for (retries = 0; retries < 5; retries++) {
63 cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
64 udelay(10);
65 value = cx18_av_read4(cx, CXADEC_DL_CTL);
66 if (value == dl_control)
67 break;
68 /* Check if we can correct the byte by changing
69 the address. We can only write the lower
70 address byte of the address. */
71 if ((value & 0x3F00) != (dl_control & 0x3F00)) {
72 retries = 5;
73 break;
74 }
75 }
76 if (retries >= 5)
61 break; 77 break;
62 } 78 }
63 if (retries >= 5) { 79 if (i == size)
64 CX18_ERR("unable to load firmware %s\n", FWFILE); 80 break;
65 release_firmware(fw); 81 retries++;
66 return -EIO; 82 }
67 } 83 if (retries >= 5) {
84 CX18_ERR("unable to load firmware %s\n", FWFILE);
85 release_firmware(fw);
86 return -EIO;
68 } 87 }
69 88
70 cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size); 89 cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size);
@@ -100,7 +119,6 @@ int cx18_av_loadfw(struct cx18 *cx)
100 have a name in the spec. */ 119 have a name in the spec. */
101 cx18_av_write4(cx, 0x09CC, 1); 120 cx18_av_write4(cx, 0x09CC, 1);
102 121
103#define CX18_AUDIO_ENABLE 0xc72014
104 v = read_reg(CX18_AUDIO_ENABLE); 122 v = read_reg(CX18_AUDIO_ENABLE);
105 /* If bit 11 is 1 */ 123 /* If bit 11 is 1 */
106 if (v & 0x800) 124 if (v & 0x800)
diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c
index d09f1daf4ebf..02fdf57bb678 100644
--- a/drivers/media/video/cx18/cx18-av-vbi.c
+++ b/drivers/media/video/cx18/cx18-av-vbi.c
@@ -83,150 +83,6 @@ static int decode_vps(u8 *dst, u8 *p)
83 return err & 0xf0; 83 return err & 0xf0;
84} 84}
85 85
86void cx18_av_vbi_setup(struct cx18 *cx)
87{
88 struct cx18_av_state *state = &cx->av_state;
89 v4l2_std_id std = state->std;
90 int hblank, hactive, burst, vblank, vactive, sc;
91 int vblank656, src_decimation;
92 int luma_lpf, uv_lpf, comb;
93 u32 pll_int, pll_frac, pll_post;
94
95 /* datasheet startup, step 8d */
96 if (std & ~V4L2_STD_NTSC)
97 cx18_av_write(cx, 0x49f, 0x11);
98 else
99 cx18_av_write(cx, 0x49f, 0x14);
100
101 if (std & V4L2_STD_625_50) {
102 hblank = 0x084;
103 hactive = 0x2d0;
104 burst = 0x5d;
105 vblank = 0x024;
106 vactive = 0x244;
107 vblank656 = 0x28;
108 src_decimation = 0x21f;
109
110 luma_lpf = 2;
111 if (std & V4L2_STD_SECAM) {
112 uv_lpf = 0;
113 comb = 0;
114 sc = 0x0a425f;
115 } else if (std == V4L2_STD_PAL_Nc) {
116 uv_lpf = 1;
117 comb = 0x20;
118 sc = 556453;
119 } else {
120 uv_lpf = 1;
121 comb = 0x20;
122 sc = 0x0a8263;
123 }
124 } else {
125 hactive = 720;
126 hblank = 122;
127 vactive = 487;
128 luma_lpf = 1;
129 uv_lpf = 1;
130
131 src_decimation = 0x21f;
132 if (std == V4L2_STD_PAL_60) {
133 vblank = 26;
134 vblank656 = 26;
135 burst = 0x5b;
136 luma_lpf = 2;
137 comb = 0x20;
138 sc = 0x0a8263;
139 } else if (std == V4L2_STD_PAL_M) {
140 vblank = 20;
141 vblank656 = 24;
142 burst = 0x61;
143 comb = 0x20;
144
145 sc = 555452;
146 } else {
147 vblank = 26;
148 vblank656 = 26;
149 burst = 0x5b;
150 comb = 0x66;
151 sc = 556063;
152 }
153 }
154
155 /* DEBUG: Displays configured PLL frequency */
156 pll_int = cx18_av_read(cx, 0x108);
157 pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
158 pll_post = cx18_av_read(cx, 0x109);
159 CX18_DEBUG_INFO("PLL regs = int: %u, frac: %u, post: %u\n",
160 pll_int, pll_frac, pll_post);
161
162 if (pll_post) {
163 int fin, fsc;
164 int pll = 28636363L * ((((u64)pll_int) << 25) + pll_frac);
165
166 pll >>= 25;
167 pll /= pll_post;
168 CX18_DEBUG_INFO("PLL = %d.%06d MHz\n",
169 pll / 1000000, pll % 1000000);
170 CX18_DEBUG_INFO("PLL/8 = %d.%06d MHz\n",
171 pll / 8000000, (pll / 8) % 1000000);
172
173 fin = ((u64)src_decimation * pll) >> 12;
174 CX18_DEBUG_INFO("ADC Sampling freq = %d.%06d MHz\n",
175 fin / 1000000, fin % 1000000);
176
177 fsc = (((u64)sc) * pll) >> 24L;
178 CX18_DEBUG_INFO("Chroma sub-carrier freq = %d.%06d MHz\n",
179 fsc / 1000000, fsc % 1000000);
180
181 CX18_DEBUG_INFO("hblank %i, hactive %i, "
182 "vblank %i , vactive %i, vblank656 %i, src_dec %i,"
183 "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
184 " sc 0x%06x\n",
185 hblank, hactive, vblank, vactive, vblank656,
186 src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
187 }
188
189 /* Sets horizontal blanking delay and active lines */
190 cx18_av_write(cx, 0x470, hblank);
191 cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
192 (hactive << 4)));
193 cx18_av_write(cx, 0x472, hactive >> 4);
194
195 /* Sets burst gate delay */
196 cx18_av_write(cx, 0x473, burst);
197
198 /* Sets vertical blanking delay and active duration */
199 cx18_av_write(cx, 0x474, vblank);
200 cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
201 (vactive << 4)));
202 cx18_av_write(cx, 0x476, vactive >> 4);
203 cx18_av_write(cx, 0x477, vblank656);
204
205 /* Sets src decimation rate */
206 cx18_av_write(cx, 0x478, 0xff & src_decimation);
207 cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
208
209 /* Sets Luma and UV Low pass filters */
210 cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
211
212 /* Enables comb filters */
213 cx18_av_write(cx, 0x47b, comb);
214
215 /* Sets SC Step*/
216 cx18_av_write(cx, 0x47c, sc);
217 cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
218 cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
219
220 /* Sets VBI parameters */
221 if (std & V4L2_STD_625_50) {
222 cx18_av_write(cx, 0x47f, 0x01);
223 state->vbi_line_offset = 5;
224 } else {
225 cx18_av_write(cx, 0x47f, 0x00);
226 state->vbi_line_offset = 8;
227 }
228}
229
230int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) 86int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
231{ 87{
232 struct cx18_av_state *state = &cx->av_state; 88 struct cx18_av_state *state = &cx->av_state;
@@ -292,8 +148,8 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
292 /* raw VBI */ 148 /* raw VBI */
293 memset(svbi, 0, sizeof(*svbi)); 149 memset(svbi, 0, sizeof(*svbi));
294 150
295 /* Setup VBI */ 151 /* Setup standard */
296 cx18_av_vbi_setup(cx); 152 cx18_av_std_setup(cx);
297 153
298 /* VBI Offset */ 154 /* VBI Offset */
299 cx18_av_write(cx, 0x47f, vbi_offset); 155 cx18_av_write(cx, 0x47f, vbi_offset);
@@ -304,8 +160,8 @@ int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
304 for (x = 0; x <= 23; x++) 160 for (x = 0; x <= 23; x++)
305 lcr[x] = 0x00; 161 lcr[x] = 0x00;
306 162
307 /* Setup VBI */ 163 /* Setup standard */
308 cx18_av_vbi_setup(cx); 164 cx18_av_std_setup(cx);
309 165
310 /* Sliced VBI */ 166 /* Sliced VBI */
311 cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */ 167 cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
index c26e0ef5b075..8fe5f38c4d7c 100644
--- a/drivers/media/video/cx18/cx18-cards.c
+++ b/drivers/media/video/cx18/cx18-cards.c
@@ -27,6 +27,8 @@
27#include "cx18-i2c.h" 27#include "cx18-i2c.h"
28#include <media/cs5345.h> 28#include <media/cs5345.h>
29 29
30#define V4L2_STD_PAL_SECAM (V4L2_STD_PAL|V4L2_STD_SECAM)
31
30/********************** card configuration *******************************/ 32/********************** card configuration *******************************/
31 33
32/* usual i2c tuner addresses to probe */ 34/* usual i2c tuner addresses to probe */
@@ -65,12 +67,12 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
65 { CX18_CARD_INPUT_AUD_TUNER, 67 { CX18_CARD_INPUT_AUD_TUNER,
66 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, 68 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
67 { CX18_CARD_INPUT_LINE_IN1, 69 { CX18_CARD_INPUT_LINE_IN1,
68 CX18_AV_AUDIO_SERIAL, CS5345_IN_2 }, 70 CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
69 { CX18_CARD_INPUT_LINE_IN2, 71 { CX18_CARD_INPUT_LINE_IN2,
70 CX18_AV_AUDIO_SERIAL, CS5345_IN_3 }, 72 CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
71 }, 73 },
72 .radio_input = { CX18_CARD_INPUT_AUD_TUNER, 74 .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
73 CX18_AV_AUDIO_SERIAL, CS5345_IN_4 }, 75 CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
74 .ddr = { 76 .ddr = {
75 /* ESMT M13S128324A-5B memory */ 77 /* ESMT M13S128324A-5B memory */
76 .chip_config = 0x003, 78 .chip_config = 0x003,
@@ -86,6 +88,7 @@ static const struct cx18_card cx18_card_hvr1600_esmt = {
86 .active_lo_mask = 0x3001, 88 .active_lo_mask = 0x3001,
87 .msecs_asserted = 10, 89 .msecs_asserted = 10,
88 .msecs_recovery = 40, 90 .msecs_recovery = 40,
91 .ir_reset_mask = 0x0001,
89 }, 92 },
90 .i2c = &cx18_i2c_std, 93 .i2c = &cx18_i2c_std,
91}; 94};
@@ -110,12 +113,12 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
110 { CX18_CARD_INPUT_AUD_TUNER, 113 { CX18_CARD_INPUT_AUD_TUNER,
111 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, 114 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
112 { CX18_CARD_INPUT_LINE_IN1, 115 { CX18_CARD_INPUT_LINE_IN1,
113 CX18_AV_AUDIO_SERIAL, CS5345_IN_2 }, 116 CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
114 { CX18_CARD_INPUT_LINE_IN2, 117 { CX18_CARD_INPUT_LINE_IN2,
115 CX18_AV_AUDIO_SERIAL, CS5345_IN_3 }, 118 CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
116 }, 119 },
117 .radio_input = { CX18_CARD_INPUT_AUD_TUNER, 120 .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
118 CX18_AV_AUDIO_SERIAL, CS5345_IN_4 }, 121 CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
119 .ddr = { 122 .ddr = {
120 /* Samsung K4D263238G-VC33 memory */ 123 /* Samsung K4D263238G-VC33 memory */
121 .chip_config = 0x003, 124 .chip_config = 0x003,
@@ -131,6 +134,7 @@ static const struct cx18_card cx18_card_hvr1600_samsung = {
131 .active_lo_mask = 0x3001, 134 .active_lo_mask = 0x3001,
132 .msecs_asserted = 10, 135 .msecs_asserted = 10,
133 .msecs_recovery = 40, 136 .msecs_recovery = 40,
137 .ir_reset_mask = 0x0001,
134 }, 138 },
135 .i2c = &cx18_i2c_std, 139 .i2c = &cx18_i2c_std,
136}; 140};
@@ -161,10 +165,10 @@ static const struct cx18_card cx18_card_h900 = {
161 { CX18_CARD_INPUT_AUD_TUNER, 165 { CX18_CARD_INPUT_AUD_TUNER,
162 CX18_AV_AUDIO8, 0 }, 166 CX18_AV_AUDIO8, 0 },
163 { CX18_CARD_INPUT_LINE_IN1, 167 { CX18_CARD_INPUT_LINE_IN1,
164 CX18_AV_AUDIO_SERIAL, 0 }, 168 CX18_AV_AUDIO_SERIAL1, 0 },
165 }, 169 },
166 .radio_input = { CX18_CARD_INPUT_AUD_TUNER, 170 .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
167 CX18_AV_AUDIO_SERIAL, 0 }, 171 CX18_AV_AUDIO_SERIAL1, 0 },
168 .tuners = { 172 .tuners = {
169 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, 173 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
170 }, 174 },
@@ -194,7 +198,7 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = {
194static const struct cx18_card cx18_card_mpc718 = { 198static const struct cx18_card cx18_card_mpc718 = {
195 .type = CX18_CARD_YUAN_MPC718, 199 .type = CX18_CARD_YUAN_MPC718,
196 .name = "Yuan MPC718", 200 .name = "Yuan MPC718",
197 .comment = "Some Composite and S-Video inputs are currently working.\n", 201 .comment = "Analog video capture works; some audio line in may not.\n",
198 .v4l2_capabilities = CX18_CAP_ENCODER, 202 .v4l2_capabilities = CX18_CAP_ENCODER,
199 .hw_audio_ctrl = CX18_HW_CX23418, 203 .hw_audio_ctrl = CX18_HW_CX23418,
200 .hw_all = CX18_HW_TUNER, 204 .hw_all = CX18_HW_TUNER,
@@ -209,11 +213,11 @@ static const struct cx18_card cx18_card_mpc718 = {
209 { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 }, 213 { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 },
210 }, 214 },
211 .audio_inputs = { 215 .audio_inputs = {
212 { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, 216 { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 },
213 { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL, 0 }, 217 { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 0 },
214 { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL, 0 }, 218 { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL1, 0 },
215 }, 219 },
216 .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL, 0 }, 220 .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 0 },
217 .tuners = { 221 .tuners = {
218 /* XC3028 tuner */ 222 /* XC3028 tuner */
219 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, 223 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
@@ -227,16 +231,73 @@ static const struct cx18_card cx18_card_mpc718 = {
227 .tune_lane = 0, 231 .tune_lane = 0,
228 .initial_emrs = 2, 232 .initial_emrs = 2,
229 }, 233 },
230 .xceive_pin = 15, 234 .xceive_pin = 0,
231 .pci_list = cx18_pci_mpc718, 235 .pci_list = cx18_pci_mpc718,
232 .i2c = &cx18_i2c_std, 236 .i2c = &cx18_i2c_std,
233}; 237};
234 238
239/* ------------------------------------------------------------------------- */
240
241/* Conexant Raptor PAL/SECAM: note that this card is analog only! */
242
243static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = {
244 { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_CONEXANT, 0x0009 },
245 { 0, 0, 0 }
246};
247
248static const struct cx18_card cx18_card_cnxt_raptor_pal = {
249 .type = CX18_CARD_CNXT_RAPTOR_PAL,
250 .name = "Conexant Raptor PAL/SECAM",
251 .comment = "VBI is not yet supported\n",
252 .v4l2_capabilities = CX18_CAP_ENCODER,
253 .hw_audio_ctrl = CX18_HW_CX23418,
254 .hw_muxer = CX18_HW_GPIO,
255 .hw_all = CX18_HW_TUNER | CX18_HW_GPIO,
256 .video_inputs = {
257 { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 },
258 { CX18_CARD_INPUT_SVIDEO1, 1,
259 CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
260 { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
261 { CX18_CARD_INPUT_SVIDEO2, 2,
262 CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
263 { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
264 },
265 .audio_inputs = {
266 { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 },
267 { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL1, 1 },
268 { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL2, 1 },
269 },
270 .tuners = {
271 { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
272 },
273 .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 2 },
274 .ddr = {
275 /* MT 46V16M16 memory */
276 .chip_config = 0x50306,
277 .refresh = 0x753,
278 .timing1 = 0x33220953,
279 .timing2 = 0x09,
280 .tune_lane = 0,
281 .initial_emrs = 0,
282 },
283 .gpio_init.initial_value = 0x1002,
284 .gpio_init.direction = 0xf002,
285 .gpio_audio_input = { .mask = 0xf002,
286 .tuner = 0x1002, /* LED D1 Tuner AF */
287 .linein = 0x2000, /* LED D2 Line In 1 */
288 .radio = 0x4002 }, /* LED D3 Tuner AF */
289 .pci_list = cx18_pci_cnxt_raptor_pal,
290 .i2c = &cx18_i2c_std,
291};
292
293/* ------------------------------------------------------------------------- */
294
235static const struct cx18_card *cx18_card_list[] = { 295static const struct cx18_card *cx18_card_list[] = {
236 &cx18_card_hvr1600_esmt, 296 &cx18_card_hvr1600_esmt,
237 &cx18_card_hvr1600_samsung, 297 &cx18_card_hvr1600_samsung,
238 &cx18_card_h900, 298 &cx18_card_h900,
239 &cx18_card_mpc718, 299 &cx18_card_mpc718,
300 &cx18_card_cnxt_raptor_pal,
240}; 301};
241 302
242const struct cx18_card *cx18_get_card(u16 index) 303const struct cx18_card *cx18_get_card(u16 index)
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
index dc2dd945d4c3..32155f6e6fe4 100644
--- a/drivers/media/video/cx18/cx18-cards.h
+++ b/drivers/media/video/cx18/cx18-cards.h
@@ -83,6 +83,14 @@ struct cx18_gpio_i2c_slave_reset {
83 u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */ 83 u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */
84 int msecs_asserted; /* time period reset must remain asserted */ 84 int msecs_asserted; /* time period reset must remain asserted */
85 int msecs_recovery; /* time after deassert for chips to be ready */ 85 int msecs_recovery; /* time after deassert for chips to be ready */
86 u32 ir_reset_mask; /* GPIO to reset the Zilog Z8F0811 IR contoller */
87};
88
89struct cx18_gpio_audio_input { /* select tuner/line in input */
90 u32 mask; /* leave to 0 if not supported */
91 u32 tuner;
92 u32 linein;
93 u32 radio;
86}; 94};
87 95
88struct cx18_card_tuner { 96struct cx18_card_tuner {
@@ -123,6 +131,7 @@ struct cx18_card {
123 u8 xceive_pin; /* XCeive tuner GPIO reset pin */ 131 u8 xceive_pin; /* XCeive tuner GPIO reset pin */
124 struct cx18_gpio_init gpio_init; 132 struct cx18_gpio_init gpio_init;
125 struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset; 133 struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset;
134 struct cx18_gpio_audio_input gpio_audio_input;
126 135
127 struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS]; 136 struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
128 struct cx18_card_tuner_i2c *i2c; 137 struct cx18_card_tuner_i2c *i2c;
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
index 87cf41021665..f46c7e5ed747 100644
--- a/drivers/media/video/cx18/cx18-controls.c
+++ b/drivers/media/video/cx18/cx18-controls.c
@@ -51,12 +51,11 @@ static const u32 *ctrl_classes[] = {
51 NULL 51 NULL
52}; 52};
53 53
54static int cx18_queryctrl(struct cx18 *cx, struct v4l2_queryctrl *qctrl) 54int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl)
55{ 55{
56 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
56 const char *name; 57 const char *name;
57 58
58 CX18_DEBUG_IOCTL("VIDIOC_QUERYCTRL(%08x)\n", qctrl->id);
59
60 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); 59 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
61 if (qctrl->id == 0) 60 if (qctrl->id == 0)
62 return -EINVAL; 61 return -EINVAL;
@@ -91,21 +90,35 @@ static int cx18_queryctrl(struct cx18 *cx, struct v4l2_queryctrl *qctrl)
91 return 0; 90 return 0;
92} 91}
93 92
94static int cx18_querymenu(struct cx18 *cx, struct v4l2_querymenu *qmenu) 93int cx18_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qmenu)
95{ 94{
95 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
96 struct v4l2_queryctrl qctrl; 96 struct v4l2_queryctrl qctrl;
97 97
98 qctrl.id = qmenu->id; 98 qctrl.id = qmenu->id;
99 cx18_queryctrl(cx, &qctrl); 99 cx18_queryctrl(file, fh, &qctrl);
100 return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id)); 100 return v4l2_ctrl_query_menu(qmenu, &qctrl,
101 cx2341x_ctrl_get_menu(&cx->params, qmenu->id));
101} 102}
102 103
103static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl) 104static int cx18_try_ctrl(struct file *file, void *fh,
105 struct v4l2_ext_control *vctrl)
104{ 106{
105 s32 v = vctrl->value; 107 struct v4l2_queryctrl qctrl;
106 108 const char **menu_items = NULL;
107 CX18_DEBUG_IOCTL("VIDIOC_S_CTRL(%08x, %x)\n", vctrl->id, v); 109 int err;
110
111 qctrl.id = vctrl->id;
112 err = cx18_queryctrl(file, fh, &qctrl);
113 if (err)
114 return err;
115 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
116 menu_items = v4l2_ctrl_get_menu(qctrl.id);
117 return v4l2_ctrl_check(vctrl, &qctrl, menu_items);
118}
108 119
120static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
121{
109 switch (vctrl->id) { 122 switch (vctrl->id) {
110 /* Standard V4L2 controls */ 123 /* Standard V4L2 controls */
111 case V4L2_CID_BRIGHTNESS: 124 case V4L2_CID_BRIGHTNESS:
@@ -123,7 +136,7 @@ static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
123 return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl); 136 return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl);
124 137
125 default: 138 default:
126 CX18_DEBUG_IOCTL("invalid control %x\n", vctrl->id); 139 CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
127 return -EINVAL; 140 return -EINVAL;
128 } 141 }
129 return 0; 142 return 0;
@@ -131,8 +144,6 @@ static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
131 144
132static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl) 145static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
133{ 146{
134 CX18_DEBUG_IOCTL("VIDIOC_G_CTRL(%08x)\n", vctrl->id);
135
136 switch (vctrl->id) { 147 switch (vctrl->id) {
137 /* Standard V4L2 controls */ 148 /* Standard V4L2 controls */
138 case V4L2_CID_BRIGHTNESS: 149 case V4L2_CID_BRIGHTNESS:
@@ -149,7 +160,7 @@ static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
149 case V4L2_CID_AUDIO_LOUDNESS: 160 case V4L2_CID_AUDIO_LOUDNESS:
150 return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl); 161 return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl);
151 default: 162 default:
152 CX18_DEBUG_IOCTL("invalid control %x\n", vctrl->id); 163 CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
153 return -EINVAL; 164 return -EINVAL;
154 } 165 }
155 return 0; 166 return 0;
@@ -194,113 +205,110 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt
194 return 0; 205 return 0;
195} 206}
196 207
197int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg) 208int cx18_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
198{ 209{
210 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
199 struct v4l2_control ctrl; 211 struct v4l2_control ctrl;
200 212
201 switch (cmd) { 213 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
202 case VIDIOC_QUERYMENU: 214 int i;
203 CX18_DEBUG_IOCTL("VIDIOC_QUERYMENU\n"); 215 int err = 0;
204 return cx18_querymenu(cx, arg); 216
205 217 for (i = 0; i < c->count; i++) {
206 case VIDIOC_QUERYCTRL: 218 ctrl.id = c->controls[i].id;
207 return cx18_queryctrl(cx, arg); 219 ctrl.value = c->controls[i].value;
208 220 err = cx18_g_ctrl(cx, &ctrl);
209 case VIDIOC_S_CTRL: 221 c->controls[i].value = ctrl.value;
210 return cx18_s_ctrl(cx, arg); 222 if (err) {
211 223 c->error_idx = i;
212 case VIDIOC_G_CTRL: 224 break;
213 return cx18_g_ctrl(cx, arg);
214
215 case VIDIOC_S_EXT_CTRLS:
216 {
217 struct v4l2_ext_controls *c = arg;
218
219 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
220 int i;
221 int err = 0;
222
223 for (i = 0; i < c->count; i++) {
224 ctrl.id = c->controls[i].id;
225 ctrl.value = c->controls[i].value;
226 err = cx18_s_ctrl(cx, &ctrl);
227 c->controls[i].value = ctrl.value;
228 if (err) {
229 c->error_idx = i;
230 break;
231 }
232 } 225 }
233 return err;
234 } 226 }
235 CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); 227 return err;
236 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { 228 }
237 struct cx2341x_mpeg_params p = cx->params; 229 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
238 int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), arg, cmd); 230 return cx2341x_ext_ctrls(&cx->params, 0, c, VIDIOC_G_EXT_CTRLS);
231 return -EINVAL;
232}
239 233
240 if (err) 234int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
241 return err; 235{
236 struct cx18_open_id *id = fh;
237 struct cx18 *cx = id->cx;
238 int ret;
239 struct v4l2_control ctrl;
242 240
243 if (p.video_encoding != cx->params.video_encoding) { 241 ret = v4l2_prio_check(&cx->prio, &id->prio);
244 int is_mpeg1 = p.video_encoding == 242 if (ret)
245 V4L2_MPEG_VIDEO_ENCODING_MPEG_1; 243 return ret;
246 struct v4l2_format fmt;
247 244
248 /* fix videodecoder resolution */ 245 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
249 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 246 int i;
250 fmt.fmt.pix.width = cx->params.width / (is_mpeg1 ? 2 : 1); 247 int err = 0;
251 fmt.fmt.pix.height = cx->params.height; 248
252 cx18_av_cmd(cx, VIDIOC_S_FMT, &fmt); 249 for (i = 0; i < c->count; i++) {
250 ctrl.id = c->controls[i].id;
251 ctrl.value = c->controls[i].value;
252 err = cx18_s_ctrl(cx, &ctrl);
253 c->controls[i].value = ctrl.value;
254 if (err) {
255 c->error_idx = i;
256 break;
253 } 257 }
254 err = cx2341x_update(cx, cx18_api_func, &cx->params, &p);
255 if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt)
256 err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt);
257 cx->params = p;
258 cx->dualwatch_stereo_mode = p.audio_properties & 0x0300;
259 cx18_audio_set_audio_clock_freq(cx, p.audio_properties & 0x03);
260 return err;
261 } 258 }
262 return -EINVAL; 259 return err;
263 } 260 }
261 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
262 struct cx2341x_mpeg_params p = cx->params;
263 int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing),
264 c, VIDIOC_S_EXT_CTRLS);
264 265
265 case VIDIOC_G_EXT_CTRLS: 266 if (err)
266 {
267 struct v4l2_ext_controls *c = arg;
268
269 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
270 int i;
271 int err = 0;
272
273 for (i = 0; i < c->count; i++) {
274 ctrl.id = c->controls[i].id;
275 ctrl.value = c->controls[i].value;
276 err = cx18_g_ctrl(cx, &ctrl);
277 c->controls[i].value = ctrl.value;
278 if (err) {
279 c->error_idx = i;
280 break;
281 }
282 }
283 return err; 267 return err;
268
269 if (p.video_encoding != cx->params.video_encoding) {
270 int is_mpeg1 = p.video_encoding ==
271 V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
272 struct v4l2_format fmt;
273
274 /* fix videodecoder resolution */
275 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
276 fmt.fmt.pix.width = cx->params.width
277 / (is_mpeg1 ? 2 : 1);
278 fmt.fmt.pix.height = cx->params.height;
279 cx18_av_cmd(cx, VIDIOC_S_FMT, &fmt);
284 } 280 }
285 CX18_DEBUG_IOCTL("VIDIOC_G_EXT_CTRLS\n"); 281 err = cx2341x_update(cx, cx18_api_func, &cx->params, &p);
286 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) 282 if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt)
287 return cx2341x_ext_ctrls(&cx->params, 0, arg, cmd); 283 err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt);
288 return -EINVAL; 284 cx->params = p;
285 cx->dualwatch_stereo_mode = p.audio_properties & 0x0300;
286 cx18_audio_set_audio_clock_freq(cx, p.audio_properties & 0x03);
287 return err;
289 } 288 }
289 return -EINVAL;
290}
290 291
291 case VIDIOC_TRY_EXT_CTRLS: 292int cx18_try_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
292 { 293{
293 struct v4l2_ext_controls *c = arg; 294 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
294 295
295 CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); 296 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
296 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) 297 int i;
297 return cx2341x_ext_ctrls(&cx->params, 298 int err = 0;
298 atomic_read(&cx->ana_capturing), arg, cmd);
299 return -EINVAL;
300 }
301 299
302 default: 300 for (i = 0; i < c->count; i++) {
303 return -EINVAL; 301 err = cx18_try_ctrl(file, fh, &c->controls[i]);
302 if (err) {
303 c->error_idx = i;
304 break;
305 }
306 }
307 return err;
304 } 308 }
305 return 0; 309 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
310 return cx2341x_ext_ctrls(&cx->params,
311 atomic_read(&cx->ana_capturing),
312 c, VIDIOC_TRY_EXT_CTRLS);
313 return -EINVAL;
306} 314}
diff --git a/drivers/media/video/cx18/cx18-controls.h b/drivers/media/video/cx18/cx18-controls.h
index 6e985cf422a0..e46323700b81 100644
--- a/drivers/media/video/cx18/cx18-controls.h
+++ b/drivers/media/video/cx18/cx18-controls.h
@@ -21,4 +21,9 @@
21 * 02111-1307 USA 21 * 02111-1307 USA
22 */ 22 */
23 23
24int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg); 24int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *a);
25int cx18_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
26int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
27int cx18_try_ext_ctrls(struct file *file, void *fh,
28 struct v4l2_ext_controls *a);
29int cx18_querymenu(struct file *file, void *fh, struct v4l2_querymenu *a);
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 2b810bb2a4c7..22434aadde31 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -120,6 +120,7 @@ MODULE_PARM_DESC(cardtype,
120 "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n" 120 "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n"
121 "\t\t\t 3 = Compro VideoMate H900\n" 121 "\t\t\t 3 = Compro VideoMate H900\n"
122 "\t\t\t 4 = Yuan MPC718\n" 122 "\t\t\t 4 = Yuan MPC718\n"
123 "\t\t\t 5 = Conexant Raptor PAL/SECAM\n"
123 "\t\t\t 0 = Autodetect (default)\n" 124 "\t\t\t 0 = Autodetect (default)\n"
124 "\t\t\t-1 = Ignore this card\n\t\t"); 125 "\t\t\t-1 = Ignore this card\n\t\t");
125MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60"); 126MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
@@ -420,6 +421,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
420 mutex_init(&cx->serialize_lock); 421 mutex_init(&cx->serialize_lock);
421 mutex_init(&cx->i2c_bus_lock[0]); 422 mutex_init(&cx->i2c_bus_lock[0]);
422 mutex_init(&cx->i2c_bus_lock[1]); 423 mutex_init(&cx->i2c_bus_lock[1]);
424 mutex_init(&cx->gpio_lock);
423 425
424 spin_lock_init(&cx->lock); 426 spin_lock_init(&cx->lock);
425 spin_lock_init(&cx->dma_reg_lock); 427 spin_lock_init(&cx->dma_reg_lock);
@@ -435,7 +437,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
435 (cx->params.video_temporal_filter_mode << 1) | 437 (cx->params.video_temporal_filter_mode << 1) |
436 (cx->params.video_median_filter_type << 2); 438 (cx->params.video_median_filter_type << 2);
437 cx->params.port = CX2341X_PORT_MEMORY; 439 cx->params.port = CX2341X_PORT_MEMORY;
438 cx->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI; 440 cx->params.capabilities = CX2341X_CAP_HAS_TS;
439 init_waitqueue_head(&cx->cap_w); 441 init_waitqueue_head(&cx->cap_w);
440 init_waitqueue_head(&cx->mb_apu_waitq); 442 init_waitqueue_head(&cx->mb_apu_waitq);
441 init_waitqueue_head(&cx->mb_cpu_waitq); 443 init_waitqueue_head(&cx->mb_cpu_waitq);
@@ -614,7 +616,7 @@ static int __devinit cx18_probe(struct pci_dev *dev,
614 cx18_cards[cx18_cards_active] = cx; 616 cx18_cards[cx18_cards_active] = cx;
615 cx->dev = dev; 617 cx->dev = dev;
616 cx->num = cx18_cards_active++; 618 cx->num = cx18_cards_active++;
617 snprintf(cx->name, sizeof(cx->name) - 1, "cx18-%d", cx->num); 619 snprintf(cx->name, sizeof(cx->name), "cx18-%d", cx->num);
618 CX18_INFO("Initializing card #%d\n", cx->num); 620 CX18_INFO("Initializing card #%d\n", cx->num);
619 621
620 spin_unlock(&cx18_cards_lock); 622 spin_unlock(&cx18_cards_lock);
@@ -721,6 +723,12 @@ static int __devinit cx18_probe(struct pci_dev *dev,
721 /* if no tuner was found, then pick the first tuner in the card list */ 723 /* if no tuner was found, then pick the first tuner in the card list */
722 if (cx->options.tuner == -1 && cx->card->tuners[0].std) { 724 if (cx->options.tuner == -1 && cx->card->tuners[0].std) {
723 cx->std = cx->card->tuners[0].std; 725 cx->std = cx->card->tuners[0].std;
726 if (cx->std & V4L2_STD_PAL)
727 cx->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
728 else if (cx->std & V4L2_STD_NTSC)
729 cx->std = V4L2_STD_NTSC_M;
730 else if (cx->std & V4L2_STD_SECAM)
731 cx->std = V4L2_STD_SECAM_L;
724 cx->options.tuner = cx->card->tuners[0].tuner; 732 cx->options.tuner = cx->card->tuners[0].tuner;
725 } 733 }
726 if (cx->options.radio == -1) 734 if (cx->options.radio == -1)
@@ -818,6 +826,9 @@ int cx18_init_on_first_open(struct cx18 *cx)
818 int video_input; 826 int video_input;
819 int fw_retry_count = 3; 827 int fw_retry_count = 3;
820 struct v4l2_frequency vf; 828 struct v4l2_frequency vf;
829 struct cx18_open_id fh;
830
831 fh.cx = cx;
821 832
822 if (test_bit(CX18_F_I_FAILED, &cx->i_flags)) 833 if (test_bit(CX18_F_I_FAILED, &cx->i_flags))
823 return -ENXIO; 834 return -ENXIO;
@@ -869,13 +880,13 @@ int cx18_init_on_first_open(struct cx18 *cx)
869 880
870 video_input = cx->active_input; 881 video_input = cx->active_input;
871 cx->active_input++; /* Force update of input */ 882 cx->active_input++; /* Force update of input */
872 cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_INPUT, &video_input); 883 cx18_s_input(NULL, &fh, video_input);
873 884
874 /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code 885 /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
875 in one place. */ 886 in one place. */
876 cx->std++; /* Force full standard initialization */ 887 cx->std++; /* Force full standard initialization */
877 cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_STD, &cx->tuner_std); 888 cx18_s_std(NULL, &fh, &cx->tuner_std);
878 cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_FREQUENCY, &vf); 889 cx18_s_frequency(NULL, &fh, &vf);
879 return 0; 890 return 0;
880} 891}
881 892
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index de14ab59a206..45e31b04730e 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -75,7 +75,8 @@
75#define CX18_CARD_HVR_1600_SAMSUNG 1 /* Hauppauge HVR 1600 (Samsung memory) */ 75#define CX18_CARD_HVR_1600_SAMSUNG 1 /* Hauppauge HVR 1600 (Samsung memory) */
76#define CX18_CARD_COMPRO_H900 2 /* Compro VideoMate H900 */ 76#define CX18_CARD_COMPRO_H900 2 /* Compro VideoMate H900 */
77#define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */ 77#define CX18_CARD_YUAN_MPC718 3 /* Yuan MPC718 */
78#define CX18_CARD_LAST 3 78#define CX18_CARD_CNXT_RAPTOR_PAL 4 /* Conexant Raptor PAL */
79#define CX18_CARD_LAST 4
79 80
80#define CX18_ENC_STREAM_TYPE_MPG 0 81#define CX18_ENC_STREAM_TYPE_MPG 0
81#define CX18_ENC_STREAM_TYPE_TS 1 82#define CX18_ENC_STREAM_TYPE_TS 1
@@ -94,6 +95,7 @@
94#define CX18_PCI_ID_HAUPPAUGE 0x0070 95#define CX18_PCI_ID_HAUPPAUGE 0x0070
95#define CX18_PCI_ID_COMPRO 0x185b 96#define CX18_PCI_ID_COMPRO 0x185b
96#define CX18_PCI_ID_YUAN 0x12ab 97#define CX18_PCI_ID_YUAN 0x12ab
98#define CX18_PCI_ID_CONEXANT 0x14f1
97 99
98/* ======================================================================== */ 100/* ======================================================================== */
99/* ========================== START USER SETTABLE DMA VARIABLES =========== */ 101/* ========================== START USER SETTABLE DMA VARIABLES =========== */
@@ -228,9 +230,7 @@ struct cx18_dvb {
228 struct dvb_net dvbnet; 230 struct dvb_net dvbnet;
229 int enabled; 231 int enabled;
230 int feeding; 232 int feeding;
231
232 struct mutex feedlock; 233 struct mutex feedlock;
233
234}; 234};
235 235
236struct cx18; /* forward reference */ 236struct cx18; /* forward reference */
@@ -427,6 +427,7 @@ struct cx18 {
427 /* gpio */ 427 /* gpio */
428 u32 gpio_dir; 428 u32 gpio_dir;
429 u32 gpio_val; 429 u32 gpio_val;
430 struct mutex gpio_lock;
430 431
431 /* v4l2 and User settings */ 432 /* v4l2 and User settings */
432 433
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
index 2694ce350631..2d630d9f7496 100644
--- a/drivers/media/video/cx18/cx18-firmware.c
+++ b/drivers/media/video/cx18/cx18-firmware.c
@@ -41,9 +41,6 @@
41 41
42#define CX18_REG_BUS_TIMEOUT_EN 0xc72024 42#define CX18_REG_BUS_TIMEOUT_EN 0xc72024
43 43
44#define CX18_AUDIO_ENABLE 0xc72014
45#define CX18_REG_BUS_TIMEOUT_EN 0xc72024
46
47#define CX18_FAST_CLOCK_PLL_INT 0xc78000 44#define CX18_FAST_CLOCK_PLL_INT 0xc78000
48#define CX18_FAST_CLOCK_PLL_FRAC 0xc78004 45#define CX18_FAST_CLOCK_PLL_FRAC 0xc78004
49#define CX18_FAST_CLOCK_PLL_POST 0xc78008 46#define CX18_FAST_CLOCK_PLL_POST 0xc78008
@@ -90,7 +87,7 @@
90#define CX18_DSP0_INTERRUPT_MASK 0xd0004C 87#define CX18_DSP0_INTERRUPT_MASK 0xd0004C
91 88
92/* Encoder/decoder firmware sizes */ 89/* Encoder/decoder firmware sizes */
93#define CX18_FW_CPU_SIZE (174716) 90#define CX18_FW_CPU_SIZE (158332)
94#define CX18_FW_APU_SIZE (141200) 91#define CX18_FW_APU_SIZE (141200)
95 92
96#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */ 93#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
@@ -345,6 +342,11 @@ int cx18_firmware_init(struct cx18 *cx)
345 int sz = load_apu_fw_direct("v4l-cx23418-apu.fw", 342 int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
346 cx->enc_mem, cx, CX18_FW_APU_SIZE); 343 cx->enc_mem, cx, CX18_FW_APU_SIZE);
347 344
345 write_enc(0xE51FF004, 0);
346 write_enc(0xa00000, 4); /* todo: not hardcoded */
347 write_reg(0x00010000, CX18_PROC_SOFT_RESET); /* Start APU */
348 cx18_msleep_timeout(500, 0);
349
348 sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw", 350 sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
349 cx->enc_mem, cx, CX18_FW_CPU_SIZE); 351 cx->enc_mem, cx, CX18_FW_CPU_SIZE);
350 352
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
index b302833f6f9d..3d495dba4983 100644
--- a/drivers/media/video/cx18/cx18-gpio.c
+++ b/drivers/media/video/cx18/cx18-gpio.c
@@ -69,6 +69,7 @@ void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
69 /* Assuming that the masks are a subset of the bits in gpio_dir */ 69 /* Assuming that the masks are a subset of the bits in gpio_dir */
70 70
71 /* Assert */ 71 /* Assert */
72 mutex_lock(&cx->gpio_lock);
72 cx->gpio_val = 73 cx->gpio_val =
73 (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask); 74 (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask);
74 gpio_write(cx); 75 gpio_write(cx);
@@ -79,10 +80,53 @@ void cx18_reset_i2c_slaves_gpio(struct cx18 *cx)
79 (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask); 80 (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask);
80 gpio_write(cx); 81 gpio_write(cx);
81 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery)); 82 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
83 mutex_unlock(&cx->gpio_lock);
82} 84}
83 85
86void cx18_reset_ir_gpio(void *data)
87{
88 struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
89 const struct cx18_gpio_i2c_slave_reset *p;
90
91 p = &cx->card->gpio_i2c_slave_reset;
92
93 if (p->ir_reset_mask == 0)
94 return;
95
96 CX18_DEBUG_INFO("Resetting IR microcontroller\n");
97
98 /*
99 Assert timing for the Z8F0811 on HVR-1600 boards:
100 1. Assert RESET for min of 4 clock cycles at 18.432 MHz to initiate
101 2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock cycles
102 (6,601,085 nanoseconds ~= 7 milliseconds)
103 3. DBG pin must be high before chip exits reset for normal operation.
104 DBG is open drain and hopefully pulled high since we don't
105 normally drive it (GPIO 1?) for the HVR-1600
106 4. Z8F0811 won't exit reset until RESET is deasserted
107 */
108 mutex_lock(&cx->gpio_lock);
109 cx->gpio_val = cx->gpio_val & ~p->ir_reset_mask;
110 gpio_write(cx);
111 mutex_unlock(&cx->gpio_lock);
112 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted));
113
114 /*
115 Zilog comes out of reset, loads reset vector address and executes
116 from there. Required recovery delay unknown.
117 */
118 mutex_lock(&cx->gpio_lock);
119 cx->gpio_val = cx->gpio_val | p->ir_reset_mask;
120 gpio_write(cx);
121 mutex_unlock(&cx->gpio_lock);
122 schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
123}
124EXPORT_SYMBOL(cx18_reset_ir_gpio);
125/* This symbol is exported for use by an infrared module for the IR-blaster */
126
84void cx18_gpio_init(struct cx18 *cx) 127void cx18_gpio_init(struct cx18 *cx)
85{ 128{
129 mutex_lock(&cx->gpio_lock);
86 cx->gpio_dir = cx->card->gpio_init.direction; 130 cx->gpio_dir = cx->card->gpio_init.direction;
87 cx->gpio_val = cx->card->gpio_init.initial_value; 131 cx->gpio_val = cx->card->gpio_init.initial_value;
88 132
@@ -91,14 +135,17 @@ void cx18_gpio_init(struct cx18 *cx)
91 cx->gpio_val |= 1 << cx->card->xceive_pin; 135 cx->gpio_val |= 1 << cx->card->xceive_pin;
92 } 136 }
93 137
94 if (cx->gpio_dir == 0) 138 if (cx->gpio_dir == 0) {
139 mutex_unlock(&cx->gpio_lock);
95 return; 140 return;
141 }
96 142
97 CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", 143 CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
98 read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2), 144 read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2),
99 read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2)); 145 read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2));
100 146
101 gpio_write(cx); 147 gpio_write(cx);
148 mutex_unlock(&cx->gpio_lock);
102} 149}
103 150
104/* Xceive tuner reset function */ 151/* Xceive tuner reset function */
@@ -112,13 +159,52 @@ int cx18_reset_tuner_gpio(void *dev, int cmd, int value)
112 return 0; 159 return 0;
113 CX18_DEBUG_INFO("Resetting tuner\n"); 160 CX18_DEBUG_INFO("Resetting tuner\n");
114 161
162 mutex_lock(&cx->gpio_lock);
115 cx->gpio_val &= ~(1 << cx->card->xceive_pin); 163 cx->gpio_val &= ~(1 << cx->card->xceive_pin);
116
117 gpio_write(cx); 164 gpio_write(cx);
165 mutex_unlock(&cx->gpio_lock);
118 schedule_timeout_interruptible(msecs_to_jiffies(1)); 166 schedule_timeout_interruptible(msecs_to_jiffies(1));
119 167
168 mutex_lock(&cx->gpio_lock);
120 cx->gpio_val |= 1 << cx->card->xceive_pin; 169 cx->gpio_val |= 1 << cx->card->xceive_pin;
121 gpio_write(cx); 170 gpio_write(cx);
171 mutex_unlock(&cx->gpio_lock);
122 schedule_timeout_interruptible(msecs_to_jiffies(1)); 172 schedule_timeout_interruptible(msecs_to_jiffies(1));
123 return 0; 173 return 0;
124} 174}
175
176int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg)
177{
178 struct v4l2_routing *route = arg;
179 u32 mask, data;
180
181 switch (command) {
182 case VIDIOC_INT_S_AUDIO_ROUTING:
183 if (route->input > 2)
184 return -EINVAL;
185 mask = cx->card->gpio_audio_input.mask;
186 switch (route->input) {
187 case 0:
188 data = cx->card->gpio_audio_input.tuner;
189 break;
190 case 1:
191 data = cx->card->gpio_audio_input.linein;
192 break;
193 case 2:
194 default:
195 data = cx->card->gpio_audio_input.radio;
196 break;
197 }
198 break;
199
200 default:
201 return -EINVAL;
202 }
203 if (mask) {
204 mutex_lock(&cx->gpio_lock);
205 cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
206 gpio_write(cx);
207 mutex_unlock(&cx->gpio_lock);
208 }
209 return 0;
210}
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h
index 525c328f748a..22cd7ddf8554 100644
--- a/drivers/media/video/cx18/cx18-gpio.h
+++ b/drivers/media/video/cx18/cx18-gpio.h
@@ -22,4 +22,6 @@
22 22
23void cx18_gpio_init(struct cx18 *cx); 23void cx18_gpio_init(struct cx18 *cx);
24void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); 24void cx18_reset_i2c_slaves_gpio(struct cx18 *cx);
25void cx18_reset_ir_gpio(void *data);
25int cx18_reset_tuner_gpio(void *dev, int cmd, int value); 26int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
27int cx18_gpio(struct cx18 *cx, unsigned int command, void *arg);
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index 680bc4e35b79..6023ba3bd3a6 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -39,10 +39,6 @@
39#define GETSCL_BIT 0x0004 39#define GETSCL_BIT 0x0004
40#define GETSDL_BIT 0x0008 40#define GETSDL_BIT 0x0008
41 41
42#ifndef I2C_ADAP_CLASS_TV_ANALOG
43#define I2C_ADAP_CLASS_TV_ANALOG I2C_CLASS_TV_ANALOG
44#endif
45
46#define CX18_CS5345_I2C_ADDR 0x4c 42#define CX18_CS5345_I2C_ADDR 0x4c
47 43
48/* This array should match the CX18_HW_ defines */ 44/* This array should match the CX18_HW_ defines */
@@ -311,8 +307,12 @@ int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg)
311{ 307{
312 int addr; 308 int addr;
313 309
314 if (hw == CX18_HW_GPIO || hw == 0) 310 if (hw == 0)
315 return 0; 311 return 0;
312
313 if (hw == CX18_HW_GPIO)
314 return cx18_gpio(cx, cmd, arg);
315
316 if (hw == CX18_HW_CX23418) 316 if (hw == CX18_HW_CX23418)
317 return cx18_av_cmd(cx, cmd, arg); 317 return cx18_av_cmd(cx, cmd, arg);
318 318
@@ -350,6 +350,8 @@ void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg)
350 cx18_av_cmd(cx, cmd, arg); 350 cx18_av_cmd(cx, cmd, arg);
351 i2c_clients_command(&cx->i2c_adap[0], cmd, arg); 351 i2c_clients_command(&cx->i2c_adap[0], cmd, arg);
352 i2c_clients_command(&cx->i2c_adap[1], cmd, arg); 352 i2c_clients_command(&cx->i2c_adap[1], cmd, arg);
353 if (cx->hw_flags & CX18_HW_GPIO)
354 cx18_gpio(cx, cmd, arg);
353} 355}
354 356
355/* init + register i2c algo-bit adapter */ 357/* init + register i2c algo-bit adapter */
@@ -358,6 +360,18 @@ int init_cx18_i2c(struct cx18 *cx)
358 int i; 360 int i;
359 CX18_DEBUG_I2C("i2c init\n"); 361 CX18_DEBUG_I2C("i2c init\n");
360 362
363 /* Sanity checks for the I2C hardware arrays. They must be the
364 * same size and GPIO/CX23418 must be the last entries.
365 */
366 if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) ||
367 ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) ||
368 CX18_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 2)) ||
369 CX18_HW_CX23418 != (1 << (ARRAY_SIZE(hw_addrs) - 1)) ||
370 hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) {
371 CX18_ERR("Mismatched I2C hardware arrays\n");
372 return -ENODEV;
373 }
374
361 for (i = 0; i < 2; i++) { 375 for (i = 0; i < 2; i++) {
362 memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template, 376 memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
363 sizeof(struct i2c_adapter)); 377 sizeof(struct i2c_adapter));
@@ -391,6 +405,7 @@ int init_cx18_i2c(struct cx18 *cx)
391 write_reg_sync(0x00c000c0, 0xc7001c); 405 write_reg_sync(0x00c000c0, 0xc7001c);
392 mdelay(10); 406 mdelay(10);
393 write_reg_sync(0x00c00000, 0xc7001c); 407 write_reg_sync(0x00c00000, 0xc7001c);
408 mdelay(10);
394 409
395 write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */ 410 write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */
396 write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */ 411 write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index 4151f1e5493f..0d74e59e503e 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -100,19 +100,6 @@ void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
100 } 100 }
101} 101}
102 102
103static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
104{
105 int f, l;
106 u16 set = 0;
107
108 for (f = 0; f < 2; f++) {
109 for (l = 0; l < 24; l++) {
110 fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
111 set |= fmt->service_lines[f][l];
112 }
113 }
114 return set != 0;
115}
116 103
117u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt) 104u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
118{ 105{
@@ -126,35 +113,167 @@ u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
126 return set; 113 return set;
127} 114}
128 115
129static const struct { 116static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
130 v4l2_std_id std; 117 struct v4l2_format *fmt)
131 char *name; 118{
132} enum_stds[] = { 119 struct cx18_open_id *id = fh;
133 { V4L2_STD_PAL_BG | V4L2_STD_PAL_H, "PAL-BGH" }, 120 struct cx18 *cx = id->cx;
134 { V4L2_STD_PAL_DK, "PAL-DK" }, 121 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
135 { V4L2_STD_PAL_I, "PAL-I" }, 122
136 { V4L2_STD_PAL_M, "PAL-M" }, 123 pixfmt->width = cx->params.width;
137 { V4L2_STD_PAL_N, "PAL-N" }, 124 pixfmt->height = cx->params.height;
138 { V4L2_STD_PAL_Nc, "PAL-Nc" }, 125 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
139 { V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H, "SECAM-BGH" }, 126 pixfmt->field = V4L2_FIELD_INTERLACED;
140 { V4L2_STD_SECAM_DK, "SECAM-DK" }, 127 pixfmt->priv = 0;
141 { V4L2_STD_SECAM_L, "SECAM-L" }, 128 if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
142 { V4L2_STD_SECAM_LC, "SECAM-L'" }, 129 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
143 { V4L2_STD_NTSC_M, "NTSC-M" }, 130 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
144 { V4L2_STD_NTSC_M_JP, "NTSC-J" }, 131 pixfmt->sizeimage =
145 { V4L2_STD_NTSC_M_KR, "NTSC-K" }, 132 pixfmt->height * pixfmt->width +
146}; 133 pixfmt->height * (pixfmt->width / 2);
147 134 pixfmt->bytesperline = 720;
148static const struct v4l2_standard cx18_std_60hz = { 135 } else {
149 .frameperiod = {.numerator = 1001, .denominator = 30000}, 136 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
150 .framelines = 525, 137 pixfmt->sizeimage = 128 * 1024;
151}; 138 pixfmt->bytesperline = 0;
152 139 }
153static const struct v4l2_standard cx18_std_50hz = { 140 return 0;
154 .frameperiod = { .numerator = 1, .denominator = 25 }, 141}
155 .framelines = 625, 142
156}; 143static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
144 struct v4l2_format *fmt)
145{
146 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
147 struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
148
149 vbifmt->sampling_rate = 27000000;
150 vbifmt->offset = 248;
151 vbifmt->samples_per_line = cx->vbi.raw_decoder_line_size - 4;
152 vbifmt->sample_format = V4L2_PIX_FMT_GREY;
153 vbifmt->start[0] = cx->vbi.start[0];
154 vbifmt->start[1] = cx->vbi.start[1];
155 vbifmt->count[0] = vbifmt->count[1] = cx->vbi.count;
156 vbifmt->flags = 0;
157 vbifmt->reserved[0] = 0;
158 vbifmt->reserved[1] = 0;
159 return 0;
160}
161
162static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
163 struct v4l2_format *fmt)
164{
165 return -EINVAL;
166}
167
168static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
169 struct v4l2_format *fmt)
170{
171 struct cx18_open_id *id = fh;
172 struct cx18 *cx = id->cx;
173
174 int w = fmt->fmt.pix.width;
175 int h = fmt->fmt.pix.height;
176
177 w = min(w, 720);
178 w = max(w, 1);
179 h = min(h, cx->is_50hz ? 576 : 480);
180 h = max(h, 2);
181 cx18_g_fmt_vid_cap(file, fh, fmt);
182 fmt->fmt.pix.width = w;
183 fmt->fmt.pix.height = h;
184 return 0;
185}
186
187static int cx18_try_fmt_vbi_cap(struct file *file, void *fh,
188 struct v4l2_format *fmt)
189{
190 return cx18_g_fmt_vbi_cap(file, fh, fmt);
191}
192
193static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh,
194 struct v4l2_format *fmt)
195{
196 return -EINVAL;
197}
198
199static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
200 struct v4l2_format *fmt)
201{
202 struct cx18_open_id *id = fh;
203 struct cx18 *cx = id->cx;
204 int ret;
205 int w = fmt->fmt.pix.width;
206 int h = fmt->fmt.pix.height;
207
208 ret = v4l2_prio_check(&cx->prio, &id->prio);
209 if (ret)
210 return ret;
211
212 ret = cx18_try_fmt_vid_cap(file, fh, fmt);
213 if (ret)
214 return ret;
215
216 if (cx->params.width == w && cx->params.height == h)
217 return 0;
218
219 if (atomic_read(&cx->ana_capturing) > 0)
220 return -EBUSY;
221
222 cx->params.width = w;
223 cx->params.height = h;
224 cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
225 return cx18_g_fmt_vid_cap(file, fh, fmt);
226}
227
228static int cx18_s_fmt_vbi_cap(struct file *file, void *fh,
229 struct v4l2_format *fmt)
230{
231 struct cx18_open_id *id = fh;
232 struct cx18 *cx = id->cx;
233 int ret;
234
235 ret = v4l2_prio_check(&cx->prio, &id->prio);
236 if (ret)
237 return ret;
238
239 if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
240 cx->vbi.sliced_in->service_set &&
241 atomic_read(&cx->ana_capturing) > 0)
242 return -EBUSY;
243
244 cx->vbi.sliced_in->service_set = 0;
245 cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in);
246 return cx18_g_fmt_vbi_cap(file, fh, fmt);
247}
248
249static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh,
250 struct v4l2_format *fmt)
251{
252 return -EINVAL;
253}
157 254
255static int cx18_g_chip_ident(struct file *file, void *fh,
256 struct v4l2_chip_ident *chip)
257{
258 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
259
260 chip->ident = V4L2_IDENT_NONE;
261 chip->revision = 0;
262 if (chip->match_type == V4L2_CHIP_MATCH_HOST) {
263 if (v4l2_chip_match_host(chip->match_type, chip->match_chip))
264 chip->ident = V4L2_IDENT_CX23418;
265 return 0;
266 }
267 if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
268 return cx18_i2c_id(cx, chip->match_chip, VIDIOC_G_CHIP_IDENT,
269 chip);
270 if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
271 return cx18_call_i2c_client(cx, chip->match_chip,
272 VIDIOC_G_CHIP_IDENT, chip);
273 return -EINVAL;
274}
275
276#ifdef CONFIG_VIDEO_ADV_DEBUG
158static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg) 277static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
159{ 278{
160 struct v4l2_register *regs = arg; 279 struct v4l2_register *regs = arg;
@@ -174,665 +293,478 @@ static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
174 return 0; 293 return 0;
175} 294}
176 295
177static int cx18_get_fmt(struct cx18 *cx, int streamtype, struct v4l2_format *fmt) 296static int cx18_g_register(struct file *file, void *fh,
178{ 297 struct v4l2_register *reg)
179 switch (fmt->type) { 298{
180 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 299 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
181 fmt->fmt.pix.width = cx->params.width; 300
182 fmt->fmt.pix.height = cx->params.height; 301 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
183 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 302 return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
184 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; 303 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
185 if (streamtype == CX18_ENC_STREAM_TYPE_YUV) { 304 return cx18_i2c_id(cx, reg->match_chip, VIDIOC_DBG_G_REGISTER,
186 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; 305 reg);
187 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ 306 return cx18_call_i2c_client(cx, reg->match_chip, VIDIOC_DBG_G_REGISTER,
188 fmt->fmt.pix.sizeimage = 307 reg);
189 fmt->fmt.pix.height * fmt->fmt.pix.width + 308}
190 fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
191 } else {
192 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
193 fmt->fmt.pix.sizeimage = 128 * 1024;
194 }
195 break;
196
197 case V4L2_BUF_TYPE_VBI_CAPTURE:
198 fmt->fmt.vbi.sampling_rate = 27000000;
199 fmt->fmt.vbi.offset = 248;
200 fmt->fmt.vbi.samples_per_line = cx->vbi.raw_decoder_line_size - 4;
201 fmt->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
202 fmt->fmt.vbi.start[0] = cx->vbi.start[0];
203 fmt->fmt.vbi.start[1] = cx->vbi.start[1];
204 fmt->fmt.vbi.count[0] = fmt->fmt.vbi.count[1] = cx->vbi.count;
205 break;
206 309
207 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 310static int cx18_s_register(struct file *file, void *fh,
208 { 311 struct v4l2_register *reg)
209 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; 312{
313 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
314
315 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
316 return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
317 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
318 return cx18_i2c_id(cx, reg->match_chip, VIDIOC_DBG_S_REGISTER,
319 reg);
320 return cx18_call_i2c_client(cx, reg->match_chip, VIDIOC_DBG_S_REGISTER,
321 reg);
322}
323#endif
210 324
211 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; 325static int cx18_g_priority(struct file *file, void *fh, enum v4l2_priority *p)
212 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); 326{
213 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); 327 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
214 328
215 cx18_av_cmd(cx, VIDIOC_G_FMT, fmt); 329 *p = v4l2_prio_max(&cx->prio);
216 vbifmt->service_set = cx18_get_service_set(vbifmt);
217 break;
218 }
219 default:
220 return -EINVAL;
221 }
222 return 0; 330 return 0;
223} 331}
224 332
225static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype, 333static int cx18_s_priority(struct file *file, void *fh, enum v4l2_priority prio)
226 struct v4l2_format *fmt, int set_fmt)
227{ 334{
228 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; 335 struct cx18_open_id *id = fh;
229 u16 set; 336 struct cx18 *cx = id->cx;
230 337
231 /* set window size */ 338 return v4l2_prio_change(&cx->prio, &id->prio, prio);
232 if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 339}
233 int w = fmt->fmt.pix.width;
234 int h = fmt->fmt.pix.height;
235 340
236 if (w > 720) 341static int cx18_querycap(struct file *file, void *fh,
237 w = 720; 342 struct v4l2_capability *vcap)
238 else if (w < 1) 343{
239 w = 1; 344 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
240 if (h > (cx->is_50hz ? 576 : 480))
241 h = (cx->is_50hz ? 576 : 480);
242 else if (h < 2)
243 h = 2;
244 cx18_get_fmt(cx, streamtype, fmt);
245 fmt->fmt.pix.width = w;
246 fmt->fmt.pix.height = h;
247 345
248 if (!set_fmt || (cx->params.width == w && cx->params.height == h)) 346 strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
249 return 0; 347 strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
250 if (atomic_read(&cx->ana_capturing) > 0) 348 strlcpy(vcap->bus_info, pci_name(cx->dev), sizeof(vcap->bus_info));
251 return -EBUSY; 349 vcap->version = CX18_DRIVER_VERSION; /* version */
252 350 vcap->capabilities = cx->v4l2_cap; /* capabilities */
253 cx->params.width = w; 351 return 0;
254 cx->params.height = h; 352}
255 if (w != 720 || h != (cx->is_50hz ? 576 : 480))
256 cx->params.video_temporal_filter = 0;
257 else
258 cx->params.video_temporal_filter = 8;
259 cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
260 return cx18_get_fmt(cx, streamtype, fmt);
261 }
262 353
263 /* set raw VBI format */ 354static int cx18_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
264 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 355{
265 if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI && 356 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
266 cx->vbi.sliced_in->service_set &&
267 atomic_read(&cx->ana_capturing) > 0)
268 return -EBUSY;
269 if (set_fmt) {
270 cx->vbi.sliced_in->service_set = 0;
271 cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in);
272 }
273 return cx18_get_fmt(cx, streamtype, fmt);
274 }
275 357
276 /* any else but sliced VBI capture is an error */ 358 return cx18_get_audio_input(cx, vin->index, vin);
277 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) 359}
278 return -EINVAL;
279 360
280 /* TODO: implement sliced VBI, for now silently return 0 */ 361static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
281 return 0; 362{
363 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
282 364
283 /* set sliced VBI capture format */ 365 vin->index = cx->audio_input;
284 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; 366 return cx18_get_audio_input(cx, vin->index, vin);
285 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); 367}
286 368
287 if (vbifmt->service_set) 369static int cx18_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
288 cx18_expand_service_set(vbifmt, cx->is_50hz); 370{
289 set = check_service_set(vbifmt, cx->is_50hz); 371 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
290 vbifmt->service_set = cx18_get_service_set(vbifmt);
291 372
292 if (!set_fmt) 373 if (vout->index >= cx->nof_audio_inputs)
293 return 0;
294 if (set == 0)
295 return -EINVAL; 374 return -EINVAL;
296 if (atomic_read(&cx->ana_capturing) > 0 && cx->vbi.sliced_in->service_set == 0) 375 cx->audio_input = vout->index;
297 return -EBUSY; 376 cx18_audio_set_io(cx);
298 cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
299 memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
300 return 0; 377 return 0;
301} 378}
302 379
303static int cx18_debug_ioctls(struct file *filp, unsigned int cmd, void *arg) 380static int cx18_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
304{ 381{
305 struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data; 382 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
306 struct cx18 *cx = id->cx;
307 struct v4l2_register *reg = arg;
308 383
309 switch (cmd) { 384 /* set it to defaults from our table */
310 /* ioctls to allow direct access to the encoder registers for testing */ 385 return cx18_get_input(cx, vin->index, vin);
311 case VIDIOC_DBG_G_REGISTER: 386}
312 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
313 return cx18_cxc(cx, cmd, arg);
314 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
315 return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
316 return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
317
318 case VIDIOC_DBG_S_REGISTER:
319 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
320 return cx18_cxc(cx, cmd, arg);
321 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
322 return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
323 return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
324
325 case VIDIOC_G_CHIP_IDENT: {
326 struct v4l2_chip_ident *chip = arg;
327
328 chip->ident = V4L2_IDENT_NONE;
329 chip->revision = 0;
330 if (reg->match_type == V4L2_CHIP_MATCH_HOST) {
331 if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) {
332 struct v4l2_chip_ident *chip = arg;
333
334 chip->ident = V4L2_IDENT_CX23418;
335 }
336 return 0;
337 }
338 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
339 return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
340 if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
341 return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
342 return -EINVAL;
343 }
344
345 case VIDIOC_INT_S_AUDIO_ROUTING: {
346 struct v4l2_routing *route = arg;
347 387
348 cx18_audio_set_route(cx, route); 388static int cx18_cropcap(struct file *file, void *fh,
349 break; 389 struct v4l2_cropcap *cropcap)
350 } 390{
391 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
351 392
352 default: 393 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
353 return -EINVAL; 394 return -EINVAL;
354 } 395 cropcap->bounds.top = cropcap->bounds.left = 0;
396 cropcap->bounds.width = 720;
397 cropcap->bounds.height = cx->is_50hz ? 576 : 480;
398 cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10;
399 cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11;
400 cropcap->defrect = cropcap->bounds;
355 return 0; 401 return 0;
356} 402}
357 403
358int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg) 404static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
359{ 405{
360 struct cx18_open_id *id = NULL; 406 struct cx18_open_id *id = fh;
361 407 struct cx18 *cx = id->cx;
362 if (filp) 408 int ret;
363 id = (struct cx18_open_id *)filp->private_data;
364
365 switch (cmd) {
366 case VIDIOC_G_PRIORITY:
367 {
368 enum v4l2_priority *p = arg;
369 409
370 *p = v4l2_prio_max(&cx->prio); 410 ret = v4l2_prio_check(&cx->prio, &id->prio);
371 break; 411 if (ret)
372 } 412 return ret;
373 413
374 case VIDIOC_S_PRIORITY: 414 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
375 { 415 return -EINVAL;
376 enum v4l2_priority *prio = arg; 416 return cx18_av_cmd(cx, VIDIOC_S_CROP, crop);
417}
377 418
378 return v4l2_prio_change(&cx->prio, &id->prio, *prio); 419static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
379 } 420{
421 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
380 422
381 case VIDIOC_QUERYCAP:{ 423 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
382 struct v4l2_capability *vcap = arg; 424 return -EINVAL;
425 return cx18_av_cmd(cx, VIDIOC_G_CROP, crop);
426}
383 427
384 memset(vcap, 0, sizeof(*vcap)); 428static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
385 strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); 429 struct v4l2_fmtdesc *fmt)
386 strlcpy(vcap->card, cx->card_name, sizeof(vcap->card)); 430{
387 strlcpy(vcap->bus_info, pci_name(cx->dev), sizeof(vcap->bus_info)); 431 static struct v4l2_fmtdesc formats[] = {
388 vcap->version = CX18_DRIVER_VERSION; /* version */ 432 { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
389 vcap->capabilities = cx->v4l2_cap; /* capabilities */ 433 "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 }
434 },
435 { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
436 "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 }
437 }
438 };
390 439
391 /* reserved.. must set to 0! */ 440 if (fmt->index > 1)
392 vcap->reserved[0] = vcap->reserved[1] = 441 return -EINVAL;
393 vcap->reserved[2] = vcap->reserved[3] = 0; 442 *fmt = formats[fmt->index];
394 break; 443 return 0;
395 } 444}
396 445
397 case VIDIOC_ENUMAUDIO:{ 446static int cx18_g_input(struct file *file, void *fh, unsigned int *i)
398 struct v4l2_audio *vin = arg; 447{
448 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
399 449
400 return cx18_get_audio_input(cx, vin->index, vin); 450 *i = cx->active_input;
401 } 451 return 0;
452}
402 453
403 case VIDIOC_G_AUDIO:{ 454int cx18_s_input(struct file *file, void *fh, unsigned int inp)
404 struct v4l2_audio *vin = arg; 455{
456 struct cx18_open_id *id = fh;
457 struct cx18 *cx = id->cx;
458 int ret;
405 459
406 vin->index = cx->audio_input; 460 ret = v4l2_prio_check(&cx->prio, &id->prio);
407 return cx18_get_audio_input(cx, vin->index, vin); 461 if (ret)
408 } 462 return ret;
409 463
410 case VIDIOC_S_AUDIO:{ 464 if (inp < 0 || inp >= cx->nof_inputs)
411 struct v4l2_audio *vout = arg; 465 return -EINVAL;
412 466
413 if (vout->index >= cx->nof_audio_inputs) 467 if (inp == cx->active_input) {
414 return -EINVAL; 468 CX18_DEBUG_INFO("Input unchanged\n");
415 cx->audio_input = vout->index; 469 return 0;
416 cx18_audio_set_io(cx);
417 break;
418 } 470 }
419 471
420 case VIDIOC_ENUMINPUT:{ 472 CX18_DEBUG_INFO("Changing input from %d to %d\n",
421 struct v4l2_input *vin = arg; 473 cx->active_input, inp);
422
423 /* set it to defaults from our table */
424 return cx18_get_input(cx, vin->index, vin);
425 }
426 474
427 case VIDIOC_TRY_FMT: 475 cx->active_input = inp;
428 case VIDIOC_S_FMT: { 476 /* Set the audio input to whatever is appropriate for the input type. */
429 struct v4l2_format *fmt = arg; 477 cx->audio_input = cx->card->video_inputs[inp].audio_index;
430 478
431 return cx18_try_or_set_fmt(cx, id->type, fmt, cmd == VIDIOC_S_FMT); 479 /* prevent others from messing with the streams until
432 } 480 we're finished changing inputs. */
481 cx18_mute(cx);
482 cx18_video_set_io(cx);
483 cx18_audio_set_io(cx);
484 cx18_unmute(cx);
485 return 0;
486}
433 487
434 case VIDIOC_G_FMT: { 488static int cx18_g_frequency(struct file *file, void *fh,
435 struct v4l2_format *fmt = arg; 489 struct v4l2_frequency *vf)
436 int type = fmt->type; 490{
491 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
437 492
438 memset(fmt, 0, sizeof(*fmt)); 493 if (vf->tuner != 0)
439 fmt->type = type; 494 return -EINVAL;
440 return cx18_get_fmt(cx, id->type, fmt);
441 }
442 495
443 case VIDIOC_CROPCAP: { 496 cx18_call_i2c_clients(cx, VIDIOC_G_FREQUENCY, vf);
444 struct v4l2_cropcap *cropcap = arg; 497 return 0;
445 498}
446 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
447 return -EINVAL;
448 cropcap->bounds.top = cropcap->bounds.left = 0;
449 cropcap->bounds.width = 720;
450 cropcap->bounds.height = cx->is_50hz ? 576 : 480;
451 cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10;
452 cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11;
453 cropcap->defrect = cropcap->bounds;
454 return 0;
455 }
456 499
457 case VIDIOC_S_CROP: { 500int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
458 struct v4l2_crop *crop = arg; 501{
502 struct cx18_open_id *id = fh;
503 struct cx18 *cx = id->cx;
504 int ret;
459 505
460 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 506 ret = v4l2_prio_check(&cx->prio, &id->prio);
461 return -EINVAL; 507 if (ret)
462 return cx18_av_cmd(cx, VIDIOC_S_CROP, arg); 508 return ret;
463 }
464 509
465 case VIDIOC_G_CROP: { 510 if (vf->tuner != 0)
466 struct v4l2_crop *crop = arg; 511 return -EINVAL;
467 512
468 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 513 cx18_mute(cx);
469 return -EINVAL; 514 CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
470 return cx18_av_cmd(cx, VIDIOC_G_CROP, arg); 515 cx18_call_i2c_clients(cx, VIDIOC_S_FREQUENCY, vf);
471 } 516 cx18_unmute(cx);
517 return 0;
518}
472 519
473 case VIDIOC_ENUM_FMT: { 520static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std)
474 static struct v4l2_fmtdesc formats[] = { 521{
475 { 0, 0, 0, 522 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
476 "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12,
477 { 0, 0, 0, 0 }
478 },
479 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
480 "MPEG", V4L2_PIX_FMT_MPEG,
481 { 0, 0, 0, 0 }
482 }
483 };
484 struct v4l2_fmtdesc *fmt = arg;
485 enum v4l2_buf_type type = fmt->type;
486
487 switch (type) {
488 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
489 break;
490 default:
491 return -EINVAL;
492 }
493 if (fmt->index > 1)
494 return -EINVAL;
495 *fmt = formats[fmt->index];
496 fmt->type = type;
497 return 0;
498 }
499 523
500 case VIDIOC_G_INPUT:{ 524 *std = cx->std;
501 *(int *)arg = cx->active_input; 525 return 0;
502 break; 526}
503 }
504 527
505 case VIDIOC_S_INPUT:{ 528int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
506 int inp = *(int *)arg; 529{
530 struct cx18_open_id *id = fh;
531 struct cx18 *cx = id->cx;
532 int ret;
507 533
508 if (inp < 0 || inp >= cx->nof_inputs) 534 ret = v4l2_prio_check(&cx->prio, &id->prio);
509 return -EINVAL; 535 if (ret)
536 return ret;
510 537
511 if (inp == cx->active_input) { 538 if ((*std & V4L2_STD_ALL) == 0)
512 CX18_DEBUG_INFO("Input unchanged\n"); 539 return -EINVAL;
513 break;
514 }
515 CX18_DEBUG_INFO("Changing input from %d to %d\n",
516 cx->active_input, inp);
517 540
518 cx->active_input = inp; 541 if (*std == cx->std)
519 /* Set the audio input to whatever is appropriate for the 542 return 0;
520 input type. */
521 cx->audio_input = cx->card->video_inputs[inp].audio_index;
522 543
523 /* prevent others from messing with the streams until 544 if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
524 we're finished changing inputs. */ 545 atomic_read(&cx->ana_capturing) > 0) {
525 cx18_mute(cx); 546 /* Switching standard would turn off the radio or mess
526 cx18_video_set_io(cx); 547 with already running streams, prevent that by
527 cx18_audio_set_io(cx); 548 returning EBUSY. */
528 cx18_unmute(cx); 549 return -EBUSY;
529 break;
530 } 550 }
531 551
532 case VIDIOC_G_FREQUENCY:{ 552 cx->std = *std;
533 struct v4l2_frequency *vf = arg; 553 cx->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
554 cx->params.is_50hz = cx->is_50hz = !cx->is_60hz;
555 cx->params.width = 720;
556 cx->params.height = cx->is_50hz ? 576 : 480;
557 cx->vbi.count = cx->is_50hz ? 18 : 12;
558 cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
559 cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
560 cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284;
561 CX18_DEBUG_INFO("Switching standard to %llx.\n",
562 (unsigned long long) cx->std);
563
564 /* Tuner */
565 cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
566 return 0;
567}
534 568
535 if (vf->tuner != 0) 569static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
536 return -EINVAL; 570{
537 cx18_call_i2c_clients(cx, cmd, arg); 571 struct cx18_open_id *id = fh;
538 break; 572 struct cx18 *cx = id->cx;
539 } 573 int ret;
540 574
541 case VIDIOC_S_FREQUENCY:{ 575 ret = v4l2_prio_check(&cx->prio, &id->prio);
542 struct v4l2_frequency vf = *(struct v4l2_frequency *)arg; 576 if (ret)
577 return ret;
543 578
544 if (vf.tuner != 0) 579 if (vt->index != 0)
545 return -EINVAL; 580 return -EINVAL;
546 581
547 cx18_mute(cx); 582 /* Setting tuner can only set audio mode */
548 CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency); 583 cx18_call_i2c_clients(cx, VIDIOC_S_TUNER, vt);
549 cx18_call_i2c_clients(cx, cmd, &vf);
550 cx18_unmute(cx);
551 break;
552 }
553 584
554 case VIDIOC_ENUMSTD:{ 585 return 0;
555 struct v4l2_standard *vs = arg; 586}
556 int idx = vs->index;
557 587
558 if (idx < 0 || idx >= ARRAY_SIZE(enum_stds)) 588static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
559 return -EINVAL; 589{
590 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
560 591
561 *vs = (enum_stds[idx].std & V4L2_STD_525_60) ? 592 if (vt->index != 0)
562 cx18_std_60hz : cx18_std_50hz; 593 return -EINVAL;
563 vs->index = idx;
564 vs->id = enum_stds[idx].std;
565 strlcpy(vs->name, enum_stds[idx].name, sizeof(vs->name));
566 break;
567 }
568 594
569 case VIDIOC_G_STD:{ 595 cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, vt);
570 *(v4l2_std_id *) arg = cx->std; 596
571 break; 597 if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
598 strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
599 vt->type = V4L2_TUNER_RADIO;
600 } else {
601 strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name));
602 vt->type = V4L2_TUNER_ANALOG_TV;
572 } 603 }
573 604
574 case VIDIOC_S_STD: { 605 return 0;
575 v4l2_std_id std = *(v4l2_std_id *) arg; 606}
576 607
577 if ((std & V4L2_STD_ALL) == 0) 608static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
578 return -EINVAL; 609 struct v4l2_sliced_vbi_cap *cap)
610{
611 return -EINVAL;
612}
579 613
580 if (std == cx->std) 614static int cx18_g_enc_index(struct file *file, void *fh,
581 break; 615 struct v4l2_enc_idx *idx)
616{
617 return -EINVAL;
618}
582 619
583 if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) || 620static int cx18_encoder_cmd(struct file *file, void *fh,
584 atomic_read(&cx->ana_capturing) > 0) { 621 struct v4l2_encoder_cmd *enc)
585 /* Switching standard would turn off the radio or mess 622{
586 with already running streams, prevent that by 623 struct cx18_open_id *id = fh;
587 returning EBUSY. */ 624 struct cx18 *cx = id->cx;
588 return -EBUSY;
589 }
590 625
591 cx->std = std; 626 switch (enc->cmd) {
592 cx->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0; 627 case V4L2_ENC_CMD_START:
593 cx->params.is_50hz = cx->is_50hz = !cx->is_60hz; 628 CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
594 cx->params.width = 720; 629 enc->flags = 0;
595 cx->params.height = cx->is_50hz ? 576 : 480; 630 return cx18_start_capture(id);
596 cx->vbi.count = cx->is_50hz ? 18 : 12; 631
597 cx->vbi.start[0] = cx->is_50hz ? 6 : 10; 632 case V4L2_ENC_CMD_STOP:
598 cx->vbi.start[1] = cx->is_50hz ? 318 : 273; 633 CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
599 cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284; 634 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
600 CX18_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)cx->std); 635 cx18_stop_capture(id,
601 636 enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
602 /* Tuner */
603 cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
604 break; 637 break;
605 }
606
607 case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */
608 struct v4l2_tuner *vt = arg;
609 638
610 if (vt->index != 0) 639 case V4L2_ENC_CMD_PAUSE:
611 return -EINVAL; 640 CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
612 641 enc->flags = 0;
613 cx18_call_i2c_clients(cx, VIDIOC_S_TUNER, vt); 642 if (!atomic_read(&cx->ana_capturing))
643 return -EPERM;
644 if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
645 return 0;
646 cx18_mute(cx);
647 cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx));
614 break; 648 break;
615 }
616
617 case VIDIOC_G_TUNER: {
618 struct v4l2_tuner *vt = arg;
619
620 if (vt->index != 0)
621 return -EINVAL;
622
623 memset(vt, 0, sizeof(*vt));
624 cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, vt);
625 649
626 if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { 650 case V4L2_ENC_CMD_RESUME:
627 strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name)); 651 CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
628 vt->type = V4L2_TUNER_RADIO; 652 enc->flags = 0;
629 } else { 653 if (!atomic_read(&cx->ana_capturing))
630 strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name)); 654 return -EPERM;
631 vt->type = V4L2_TUNER_ANALOG_TV; 655 if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
632 } 656 return 0;
657 cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx));
658 cx18_unmute(cx);
633 break; 659 break;
634 }
635 660
636 case VIDIOC_G_SLICED_VBI_CAP: { 661 default:
637 struct v4l2_sliced_vbi_cap *cap = arg; 662 CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
638 int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
639 int f, l;
640 enum v4l2_buf_type type = cap->type;
641
642 memset(cap, 0, sizeof(*cap));
643 cap->type = type;
644 if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
645 for (f = 0; f < 2; f++) {
646 for (l = 0; l < 24; l++) {
647 if (valid_service_line(f, l, cx->is_50hz))
648 cap->service_lines[f][l] = set;
649 }
650 }
651 return 0;
652 }
653 return -EINVAL; 663 return -EINVAL;
654 } 664 }
665 return 0;
666}
655 667
656 case VIDIOC_ENCODER_CMD: 668static int cx18_try_encoder_cmd(struct file *file, void *fh,
657 case VIDIOC_TRY_ENCODER_CMD: { 669 struct v4l2_encoder_cmd *enc)
658 struct v4l2_encoder_cmd *enc = arg; 670{
659 int try = cmd == VIDIOC_TRY_ENCODER_CMD; 671 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
660
661 memset(&enc->raw, 0, sizeof(enc->raw));
662 switch (enc->cmd) {
663 case V4L2_ENC_CMD_START:
664 enc->flags = 0;
665 if (try)
666 return 0;
667 return cx18_start_capture(id);
668
669 case V4L2_ENC_CMD_STOP:
670 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
671 if (try)
672 return 0;
673 cx18_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
674 return 0;
675 672
676 case V4L2_ENC_CMD_PAUSE: 673 switch (enc->cmd) {
677 enc->flags = 0; 674 case V4L2_ENC_CMD_START:
678 if (try) 675 CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
679 return 0; 676 enc->flags = 0;
680 if (!atomic_read(&cx->ana_capturing))
681 return -EPERM;
682 if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
683 return 0;
684 cx18_mute(cx);
685 cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx));
686 break;
687
688 case V4L2_ENC_CMD_RESUME:
689 enc->flags = 0;
690 if (try)
691 return 0;
692 if (!atomic_read(&cx->ana_capturing))
693 return -EPERM;
694 if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
695 return 0;
696 cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx));
697 cx18_unmute(cx);
698 break;
699 default:
700 return -EINVAL;
701 }
702 break; 677 break;
703 }
704 678
705 case VIDIOC_LOG_STATUS: 679 case V4L2_ENC_CMD_STOP:
706 { 680 CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
707 struct v4l2_input vidin; 681 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
708 struct v4l2_audio audin; 682 break;
709 int i;
710 683
711 CX18_INFO("================= START STATUS CARD #%d =================\n", cx->num); 684 case V4L2_ENC_CMD_PAUSE:
712 if (cx->hw_flags & CX18_HW_TVEEPROM) { 685 CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
713 struct tveeprom tv; 686 enc->flags = 0;
687 break;
714 688
715 cx18_read_eeprom(cx, &tv); 689 case V4L2_ENC_CMD_RESUME:
716 } 690 CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
717 cx18_call_i2c_clients(cx, VIDIOC_LOG_STATUS, NULL); 691 enc->flags = 0;
718 cx18_get_input(cx, cx->active_input, &vidin);
719 cx18_get_audio_input(cx, cx->audio_input, &audin);
720 CX18_INFO("Video Input: %s\n", vidin.name);
721 CX18_INFO("Audio Input: %s\n", audin.name);
722 CX18_INFO("Tuner: %s\n",
723 test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?
724 "Radio" : "TV");
725 cx2341x_log_status(&cx->params, cx->name);
726 CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
727 for (i = 0; i < CX18_MAX_STREAMS; i++) {
728 struct cx18_stream *s = &cx->streams[i];
729
730 if (s->v4l2dev == NULL || s->buffers == 0)
731 continue;
732 CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
733 s->name, s->s_flags,
734 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
735 (s->buffers * s->buf_size) / 1024, s->buffers);
736 }
737 CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
738 (long long)cx->mpg_data_received,
739 (long long)cx->vbi_data_inserted);
740 CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num);
741 break; 692 break;
742 }
743 693
744 default: 694 default:
695 CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
745 return -EINVAL; 696 return -EINVAL;
746 } 697 }
747 return 0; 698 return 0;
748} 699}
749 700
750static int cx18_v4l2_do_ioctl(struct inode *inode, struct file *filp, 701static int cx18_log_status(struct file *file, void *fh)
751 unsigned int cmd, void *arg)
752{ 702{
753 struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data; 703 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
754 struct cx18 *cx = id->cx; 704 struct v4l2_input vidin;
755 int ret; 705 struct v4l2_audio audin;
706 int i;
707
708 CX18_INFO("================= START STATUS CARD #%d =================\n", cx->num);
709 if (cx->hw_flags & CX18_HW_TVEEPROM) {
710 struct tveeprom tv;
711
712 cx18_read_eeprom(cx, &tv);
713 }
714 cx18_call_i2c_clients(cx, VIDIOC_LOG_STATUS, NULL);
715 cx18_get_input(cx, cx->active_input, &vidin);
716 cx18_get_audio_input(cx, cx->audio_input, &audin);
717 CX18_INFO("Video Input: %s\n", vidin.name);
718 CX18_INFO("Audio Input: %s\n", audin.name);
719 mutex_lock(&cx->gpio_lock);
720 CX18_INFO("GPIO: direction 0x%08x, value 0x%08x\n",
721 cx->gpio_dir, cx->gpio_val);
722 mutex_unlock(&cx->gpio_lock);
723 CX18_INFO("Tuner: %s\n",
724 test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ? "Radio" : "TV");
725 cx2341x_log_status(&cx->params, cx->name);
726 CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
727 for (i = 0; i < CX18_MAX_STREAMS; i++) {
728 struct cx18_stream *s = &cx->streams[i];
729
730 if (s->v4l2dev == NULL || s->buffers == 0)
731 continue;
732 CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
733 s->name, s->s_flags,
734 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
735 (s->buffers * s->buf_size) / 1024, s->buffers);
736 }
737 CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
738 (long long)cx->mpg_data_received,
739 (long long)cx->vbi_data_inserted);
740 CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num);
741 return 0;
742}
743
744static int cx18_default(struct file *file, void *fh, int cmd, void *arg)
745{
746 struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
756 747
757 /* check priority */
758 switch (cmd) { 748 switch (cmd) {
759 case VIDIOC_S_CTRL: 749 case VIDIOC_INT_S_AUDIO_ROUTING: {
760 case VIDIOC_S_STD: 750 struct v4l2_routing *route = arg;
761 case VIDIOC_S_INPUT: 751
762 case VIDIOC_S_TUNER: 752 CX18_DEBUG_IOCTL("VIDIOC_INT_S_AUDIO_ROUTING(%d, %d)\n",
763 case VIDIOC_S_FREQUENCY: 753 route->input, route->output);
764 case VIDIOC_S_FMT: 754 cx18_audio_set_route(cx, route);
765 case VIDIOC_S_CROP: 755 break;
766 case VIDIOC_S_EXT_CTRLS:
767 ret = v4l2_prio_check(&cx->prio, &id->prio);
768 if (ret)
769 return ret;
770 } 756 }
771 757
772 switch (cmd) { 758 case VIDIOC_INT_RESET: {
773 case VIDIOC_DBG_G_REGISTER: 759 u32 val = *(u32 *)arg;
774 case VIDIOC_DBG_S_REGISTER: 760
775 case VIDIOC_G_CHIP_IDENT: 761 if ((val == 0) || (val & 0x01))
776 case VIDIOC_INT_S_AUDIO_ROUTING: 762 cx18_reset_ir_gpio(&cx->i2c_algo_cb_data[0]);
777 case VIDIOC_INT_RESET: 763 break;
778 if (cx18_debug & CX18_DBGFLG_IOCTL) { 764 }
779 printk(KERN_INFO "cx18%d ioctl: ", cx->num);
780 v4l_printk_ioctl(cmd);
781 }
782 return cx18_debug_ioctls(filp, cmd, arg);
783
784 case VIDIOC_G_PRIORITY:
785 case VIDIOC_S_PRIORITY:
786 case VIDIOC_QUERYCAP:
787 case VIDIOC_ENUMINPUT:
788 case VIDIOC_G_INPUT:
789 case VIDIOC_S_INPUT:
790 case VIDIOC_G_FMT:
791 case VIDIOC_S_FMT:
792 case VIDIOC_TRY_FMT:
793 case VIDIOC_ENUM_FMT:
794 case VIDIOC_CROPCAP:
795 case VIDIOC_G_CROP:
796 case VIDIOC_S_CROP:
797 case VIDIOC_G_FREQUENCY:
798 case VIDIOC_S_FREQUENCY:
799 case VIDIOC_ENUMSTD:
800 case VIDIOC_G_STD:
801 case VIDIOC_S_STD:
802 case VIDIOC_S_TUNER:
803 case VIDIOC_G_TUNER:
804 case VIDIOC_ENUMAUDIO:
805 case VIDIOC_S_AUDIO:
806 case VIDIOC_G_AUDIO:
807 case VIDIOC_G_SLICED_VBI_CAP:
808 case VIDIOC_LOG_STATUS:
809 case VIDIOC_G_ENC_INDEX:
810 case VIDIOC_ENCODER_CMD:
811 case VIDIOC_TRY_ENCODER_CMD:
812 if (cx18_debug & CX18_DBGFLG_IOCTL) {
813 printk(KERN_INFO "cx18%d ioctl: ", cx->num);
814 v4l_printk_ioctl(cmd);
815 }
816 return cx18_v4l2_ioctls(cx, filp, cmd, arg);
817
818 case VIDIOC_QUERYMENU:
819 case VIDIOC_QUERYCTRL:
820 case VIDIOC_S_CTRL:
821 case VIDIOC_G_CTRL:
822 case VIDIOC_S_EXT_CTRLS:
823 case VIDIOC_G_EXT_CTRLS:
824 case VIDIOC_TRY_EXT_CTRLS:
825 if (cx18_debug & CX18_DBGFLG_IOCTL) {
826 printk(KERN_INFO "cx18%d ioctl: ", cx->num);
827 v4l_printk_ioctl(cmd);
828 }
829 return cx18_control_ioctls(cx, cmd, arg);
830 765
831 case 0x00005401: /* Handle isatty() calls */
832 return -EINVAL;
833 default: 766 default:
834 return v4l_compat_translate_ioctl(inode, filp, cmd, arg, 767 return -EINVAL;
835 cx18_v4l2_do_ioctl);
836 } 768 }
837 return 0; 769 return 0;
838} 770}
@@ -840,12 +772,65 @@ static int cx18_v4l2_do_ioctl(struct inode *inode, struct file *filp,
840int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 772int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
841 unsigned long arg) 773 unsigned long arg)
842{ 774{
775 struct video_device *vfd = video_devdata(filp);
843 struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data; 776 struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
844 struct cx18 *cx = id->cx; 777 struct cx18 *cx = id->cx;
845 int res; 778 int res;
846 779
847 mutex_lock(&cx->serialize_lock); 780 mutex_lock(&cx->serialize_lock);
848 res = video_usercopy(inode, filp, cmd, arg, cx18_v4l2_do_ioctl); 781
782 if (cx18_debug & CX18_DBGFLG_IOCTL)
783 vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
784 res = video_ioctl2(inode, filp, cmd, arg);
785 vfd->debug = 0;
849 mutex_unlock(&cx->serialize_lock); 786 mutex_unlock(&cx->serialize_lock);
850 return res; 787 return res;
851} 788}
789
790void cx18_set_funcs(struct video_device *vdev)
791{
792 vdev->vidioc_querycap = cx18_querycap;
793 vdev->vidioc_g_priority = cx18_g_priority;
794 vdev->vidioc_s_priority = cx18_s_priority;
795 vdev->vidioc_s_audio = cx18_s_audio;
796 vdev->vidioc_g_audio = cx18_g_audio;
797 vdev->vidioc_enumaudio = cx18_enumaudio;
798 vdev->vidioc_enum_input = cx18_enum_input;
799 vdev->vidioc_cropcap = cx18_cropcap;
800 vdev->vidioc_s_crop = cx18_s_crop;
801 vdev->vidioc_g_crop = cx18_g_crop;
802 vdev->vidioc_g_input = cx18_g_input;
803 vdev->vidioc_s_input = cx18_s_input;
804 vdev->vidioc_g_frequency = cx18_g_frequency;
805 vdev->vidioc_s_frequency = cx18_s_frequency;
806 vdev->vidioc_s_tuner = cx18_s_tuner;
807 vdev->vidioc_g_tuner = cx18_g_tuner;
808 vdev->vidioc_g_enc_index = cx18_g_enc_index;
809 vdev->vidioc_g_std = cx18_g_std;
810 vdev->vidioc_s_std = cx18_s_std;
811 vdev->vidioc_log_status = cx18_log_status;
812 vdev->vidioc_enum_fmt_vid_cap = cx18_enum_fmt_vid_cap;
813 vdev->vidioc_encoder_cmd = cx18_encoder_cmd;
814 vdev->vidioc_try_encoder_cmd = cx18_try_encoder_cmd;
815 vdev->vidioc_g_fmt_vid_cap = cx18_g_fmt_vid_cap;
816 vdev->vidioc_g_fmt_vbi_cap = cx18_g_fmt_vbi_cap;
817 vdev->vidioc_g_fmt_sliced_vbi_cap = cx18_g_fmt_sliced_vbi_cap;
818 vdev->vidioc_s_fmt_vid_cap = cx18_s_fmt_vid_cap;
819 vdev->vidioc_s_fmt_vbi_cap = cx18_s_fmt_vbi_cap;
820 vdev->vidioc_s_fmt_sliced_vbi_cap = cx18_s_fmt_sliced_vbi_cap;
821 vdev->vidioc_try_fmt_vid_cap = cx18_try_fmt_vid_cap;
822 vdev->vidioc_try_fmt_vbi_cap = cx18_try_fmt_vbi_cap;
823 vdev->vidioc_try_fmt_sliced_vbi_cap = cx18_try_fmt_sliced_vbi_cap;
824 vdev->vidioc_g_sliced_vbi_cap = cx18_g_sliced_vbi_cap;
825 vdev->vidioc_g_chip_ident = cx18_g_chip_ident;
826#ifdef CONFIG_VIDEO_ADV_DEBUG
827 vdev->vidioc_g_register = cx18_g_register;
828 vdev->vidioc_s_register = cx18_s_register;
829#endif
830 vdev->vidioc_default = cx18_default;
831 vdev->vidioc_queryctrl = cx18_queryctrl;
832 vdev->vidioc_querymenu = cx18_querymenu;
833 vdev->vidioc_g_ext_ctrls = cx18_g_ext_ctrls;
834 vdev->vidioc_s_ext_ctrls = cx18_s_ext_ctrls;
835 vdev->vidioc_try_ext_ctrls = cx18_try_ext_ctrls;
836}
diff --git a/drivers/media/video/cx18/cx18-ioctl.h b/drivers/media/video/cx18/cx18-ioctl.h
index 9f4c7eb2897f..2222f679d86d 100644
--- a/drivers/media/video/cx18/cx18-ioctl.h
+++ b/drivers/media/video/cx18/cx18-ioctl.h
@@ -24,7 +24,9 @@
24u16 cx18_service2vbi(int type); 24u16 cx18_service2vbi(int type);
25void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal); 25void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
26u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt); 26u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt);
27void cx18_set_funcs(struct video_device *vdev);
28int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std);
29int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
30int cx18_s_input(struct file *file, void *fh, unsigned int inp);
27int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 31int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
28 unsigned long arg); 32 unsigned long arg);
29int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd,
30 void *arg);
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index 2a5ccef9185b..93177514e846 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -81,6 +81,7 @@ static const struct cx18_api_info api_info[] = {
81 API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0), 81 API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS, 0),
82 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), 82 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0),
83 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), 83 API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST),
84 API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST),
84 API_ENTRY(0, 0, 0), 85 API_ENTRY(0, 0, 0),
85}; 86};
86 87
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 1b921a336092..1728b1d832a9 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -39,6 +39,7 @@ static struct file_operations cx18_v4l2_enc_fops = {
39 .owner = THIS_MODULE, 39 .owner = THIS_MODULE,
40 .read = cx18_v4l2_read, 40 .read = cx18_v4l2_read,
41 .open = cx18_v4l2_open, 41 .open = cx18_v4l2_open,
42 /* FIXME change to video_ioctl2 if serialization lock can be removed */
42 .ioctl = cx18_v4l2_ioctl, 43 .ioctl = cx18_v4l2_ioctl,
43 .compat_ioctl = v4l_compat_ioctl32, 44 .compat_ioctl = v4l_compat_ioctl32,
44 .release = cx18_v4l2_close, 45 .release = cx18_v4l2_close,
@@ -189,14 +190,15 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
189 s->v4l2dev->type = 190 s->v4l2dev->type =
190 VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT | 191 VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT |
191 VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER; 192 VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER;
192 snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18%d %s", 193 snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d",
193 cx->num, s->name); 194 cx->num);
194 195
195 s->v4l2dev->minor = minor; 196 s->v4l2dev->minor = minor;
196 s->v4l2dev->dev = &cx->dev->dev; 197 s->v4l2dev->dev = &cx->dev->dev;
197 s->v4l2dev->fops = cx18_stream_info[type].fops; 198 s->v4l2dev->fops = cx18_stream_info[type].fops;
198 s->v4l2dev->release = video_device_release; 199 s->v4l2dev->release = video_device_release;
199 200 s->v4l2dev->tvnorms = V4L2_STD_ALL;
201 cx18_set_funcs(s->v4l2dev);
200 return 0; 202 return 0;
201} 203}
202 204
@@ -309,8 +311,10 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
309 311
310 /* Teardown all streams */ 312 /* Teardown all streams */
311 for (type = 0; type < CX18_MAX_STREAMS; type++) { 313 for (type = 0; type < CX18_MAX_STREAMS; type++) {
312 if (cx->streams[type].dvb.enabled) 314 if (cx->streams[type].dvb.enabled) {
313 cx18_dvb_unregister(&cx->streams[type]); 315 cx18_dvb_unregister(&cx->streams[type]);
316 cx->streams[type].dvb.enabled = false;
317 }
314 318
315 vdev = cx->streams[type].v4l2dev; 319 vdev = cx->streams[type].v4l2dev;
316 320
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h
index 33f78da9dba8..e7ed053059a8 100644
--- a/drivers/media/video/cx18/cx23418.h
+++ b/drivers/media/video/cx18/cx23418.h
@@ -52,6 +52,11 @@
52#define EPU_CMD_MASK_DEBUG (EPU_CMD_MASK | 0x000000) 52#define EPU_CMD_MASK_DEBUG (EPU_CMD_MASK | 0x000000)
53#define EPU_CMD_MASK_DE (EPU_CMD_MASK | 0x040000) 53#define EPU_CMD_MASK_DE (EPU_CMD_MASK | 0x040000)
54 54
55#define APU_CMD_MASK 0x10000000
56#define APU_CMD_MASK_ACK (APU_CMD_MASK | 0x80000000)
57
58#define CX18_APU_RESETAI (APU_CMD_MASK | 0x05)
59
55/* Description: This command indicates that a Memory Descriptor List has been 60/* Description: This command indicates that a Memory Descriptor List has been
56 filled with the requested channel type 61 filled with the requested channel type
57 IN[0] - Task handle. Handle of the task 62 IN[0] - Task handle. Handle of the task
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
index c592899a2317..22847a0444f5 100644
--- a/drivers/media/video/cx2341x.c
+++ b/drivers/media/video/cx2341x.c
@@ -77,10 +77,65 @@ const u32 cx2341x_mpeg_ctrls[] = {
77}; 77};
78EXPORT_SYMBOL(cx2341x_mpeg_ctrls); 78EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
79 79
80static const struct cx2341x_mpeg_params default_params = {
81 /* misc */
82 .capabilities = 0,
83 .port = CX2341X_PORT_MEMORY,
84 .width = 720,
85 .height = 480,
86 .is_50hz = 0,
87
88 /* stream */
89 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
90 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
91 .stream_insert_nav_packets = 0,
92
93 /* audio */
94 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
95 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
96 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
97 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
98 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
99 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
100 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
101 .audio_mute = 0,
102
103 /* video */
104 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
105 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
106 .video_b_frames = 2,
107 .video_gop_size = 12,
108 .video_gop_closure = 1,
109 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
110 .video_bitrate = 6000000,
111 .video_bitrate_peak = 8000000,
112 .video_temporal_decimation = 0,
113 .video_mute = 0,
114 .video_mute_yuv = 0x008080, /* YCbCr value for black */
115
116 /* encoding filters */
117 .video_spatial_filter_mode =
118 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
119 .video_spatial_filter = 0,
120 .video_luma_spatial_filter_type =
121 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
122 .video_chroma_spatial_filter_type =
123 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
124 .video_temporal_filter_mode =
125 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
126 .video_temporal_filter = 8,
127 .video_median_filter_type =
128 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
129 .video_luma_median_filter_top = 255,
130 .video_luma_median_filter_bottom = 0,
131 .video_chroma_median_filter_top = 255,
132 .video_chroma_median_filter_bottom = 0,
133};
134
80 135
81/* Map the control ID to the correct field in the cx2341x_mpeg_params 136/* Map the control ID to the correct field in the cx2341x_mpeg_params
82 struct. Return -EINVAL if the ID is unknown, else return 0. */ 137 struct. Return -EINVAL if the ID is unknown, else return 0. */
83static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params, 138static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
84 struct v4l2_ext_control *ctrl) 139 struct v4l2_ext_control *ctrl)
85{ 140{
86 switch (ctrl->id) { 141 switch (ctrl->id) {
@@ -420,7 +475,7 @@ static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
420 return 0; 475 return 0;
421} 476}
422 477
423int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, 478int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
424 struct v4l2_queryctrl *qctrl) 479 struct v4l2_queryctrl *qctrl)
425{ 480{
426 int err; 481 int err;
@@ -430,13 +485,13 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
430 return v4l2_ctrl_query_fill(qctrl, 485 return v4l2_ctrl_query_fill(qctrl,
431 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 486 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
432 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, 487 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
433 V4L2_MPEG_AUDIO_ENCODING_LAYER_2); 488 default_params.audio_encoding);
434 489
435 case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 490 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
436 return v4l2_ctrl_query_fill(qctrl, 491 return v4l2_ctrl_query_fill(qctrl,
437 V4L2_MPEG_AUDIO_L2_BITRATE_192K, 492 V4L2_MPEG_AUDIO_L2_BITRATE_192K,
438 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, 493 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
439 V4L2_MPEG_AUDIO_L2_BITRATE_224K); 494 default_params.audio_l2_bitrate);
440 495
441 case V4L2_CID_MPEG_AUDIO_L1_BITRATE: 496 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
442 case V4L2_CID_MPEG_AUDIO_L3_BITRATE: 497 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
@@ -479,17 +534,22 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
479 return cx2341x_ctrl_query_fill(qctrl, 534 return cx2341x_ctrl_query_fill(qctrl,
480 V4L2_MPEG_STREAM_VBI_FMT_NONE, 535 V4L2_MPEG_STREAM_VBI_FMT_NONE,
481 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1, 536 V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
482 V4L2_MPEG_STREAM_VBI_FMT_NONE); 537 default_params.stream_vbi_fmt);
538
539 case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
540 return v4l2_ctrl_query_fill(qctrl, 1, 34, 1,
541 params->is_50hz ? 12 : 15);
483 542
484 /* CX23415/6 specific */ 543 /* CX23415/6 specific */
485 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: 544 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
486 return cx2341x_ctrl_query_fill(qctrl, 545 return cx2341x_ctrl_query_fill(qctrl,
487 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, 546 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
488 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1, 547 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
489 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL); 548 default_params.video_spatial_filter_mode);
490 549
491 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: 550 case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
492 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0); 551 cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
552 default_params.video_spatial_filter);
493 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 553 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
494 if (params->video_spatial_filter_mode == 554 if (params->video_spatial_filter_mode ==
495 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) 555 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
@@ -501,7 +561,7 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
501 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF, 561 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
502 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 562 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
503 1, 563 1,
504 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF); 564 default_params.video_luma_spatial_filter_type);
505 if (params->video_spatial_filter_mode == 565 if (params->video_spatial_filter_mode ==
506 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) 566 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
507 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 567 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
@@ -512,7 +572,7 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
512 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF, 572 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
513 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 573 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
514 1, 574 1,
515 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF); 575 default_params.video_chroma_spatial_filter_type);
516 if (params->video_spatial_filter_mode == 576 if (params->video_spatial_filter_mode ==
517 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) 577 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
518 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; 578 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
@@ -522,10 +582,11 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
522 return cx2341x_ctrl_query_fill(qctrl, 582 return cx2341x_ctrl_query_fill(qctrl,
523 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, 583 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
524 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1, 584 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
525 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL); 585 default_params.video_temporal_filter_mode);
526 586
527 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: 587 case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
528 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0); 588 cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
589 default_params.video_temporal_filter);
529 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 590 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
530 if (params->video_temporal_filter_mode == 591 if (params->video_temporal_filter_mode ==
531 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO) 592 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
@@ -536,10 +597,11 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
536 return cx2341x_ctrl_query_fill(qctrl, 597 return cx2341x_ctrl_query_fill(qctrl,
537 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, 598 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
538 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1, 599 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
539 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF); 600 default_params.video_median_filter_type);
540 601
541 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: 602 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
542 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255); 603 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
604 default_params.video_luma_median_filter_top);
543 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 605 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
544 if (params->video_median_filter_type == 606 if (params->video_median_filter_type ==
545 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 607 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
@@ -547,7 +609,8 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
547 return 0; 609 return 0;
548 610
549 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: 611 case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
550 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0); 612 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
613 default_params.video_luma_median_filter_bottom);
551 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 614 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
552 if (params->video_median_filter_type == 615 if (params->video_median_filter_type ==
553 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 616 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
@@ -555,7 +618,8 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
555 return 0; 618 return 0;
556 619
557 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: 620 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
558 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255); 621 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
622 default_params.video_chroma_median_filter_top);
559 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 623 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
560 if (params->video_median_filter_type == 624 if (params->video_median_filter_type ==
561 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 625 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
@@ -563,7 +627,8 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
563 return 0; 627 return 0;
564 628
565 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: 629 case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
566 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0); 630 cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
631 default_params.video_chroma_median_filter_bottom);
567 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; 632 qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
568 if (params->video_median_filter_type == 633 if (params->video_median_filter_type ==
569 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) 634 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
@@ -571,7 +636,8 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
571 return 0; 636 return 0;
572 637
573 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS: 638 case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
574 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1, 0); 639 return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
640 default_params.stream_insert_nav_packets);
575 641
576 default: 642 default:
577 return v4l2_ctrl_query_fill_std(qctrl); 643 return v4l2_ctrl_query_fill_std(qctrl);
@@ -580,9 +646,9 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
580} 646}
581EXPORT_SYMBOL(cx2341x_ctrl_query); 647EXPORT_SYMBOL(cx2341x_ctrl_query);
582 648
583const char **cx2341x_ctrl_get_menu(u32 id) 649const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
584{ 650{
585 static const char *mpeg_stream_type[] = { 651 static const char *mpeg_stream_type_without_ts[] = {
586 "MPEG-2 Program Stream", 652 "MPEG-2 Program Stream",
587 "", 653 "",
588 "MPEG-1 System Stream", 654 "MPEG-1 System Stream",
@@ -592,6 +658,16 @@ const char **cx2341x_ctrl_get_menu(u32 id)
592 NULL 658 NULL
593 }; 659 };
594 660
661 static const char *mpeg_stream_type_with_ts[] = {
662 "MPEG-2 Program Stream",
663 "MPEG-2 Transport Stream",
664 "MPEG-1 System Stream",
665 "MPEG-2 DVD-compatible Stream",
666 "MPEG-1 VCD-compatible Stream",
667 "MPEG-2 SVCD-compatible Stream",
668 NULL
669 };
670
595 static const char *cx2341x_video_spatial_filter_mode_menu[] = { 671 static const char *cx2341x_video_spatial_filter_mode_menu[] = {
596 "Manual", 672 "Manual",
597 "Auto", 673 "Auto",
@@ -630,7 +706,8 @@ const char **cx2341x_ctrl_get_menu(u32 id)
630 706
631 switch (id) { 707 switch (id) {
632 case V4L2_CID_MPEG_STREAM_TYPE: 708 case V4L2_CID_MPEG_STREAM_TYPE:
633 return mpeg_stream_type; 709 return (p->capabilities & CX2341X_CAP_HAS_TS) ?
710 mpeg_stream_type_with_ts : mpeg_stream_type_without_ts;
634 case V4L2_CID_MPEG_AUDIO_L1_BITRATE: 711 case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
635 case V4L2_CID_MPEG_AUDIO_L3_BITRATE: 712 case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
636 return NULL; 713 return NULL;
@@ -690,7 +767,7 @@ int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
690 if (err) 767 if (err)
691 break; 768 break;
692 if (qctrl.type == V4L2_CTRL_TYPE_MENU) 769 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
693 menu_items = cx2341x_ctrl_get_menu(qctrl.id); 770 menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
694 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items); 771 err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
695 if (err) 772 if (err)
696 break; 773 break;
@@ -714,61 +791,6 @@ EXPORT_SYMBOL(cx2341x_ext_ctrls);
714 791
715void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p) 792void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
716{ 793{
717 static struct cx2341x_mpeg_params default_params = {
718 /* misc */
719 .capabilities = 0,
720 .port = CX2341X_PORT_MEMORY,
721 .width = 720,
722 .height = 480,
723 .is_50hz = 0,
724
725 /* stream */
726 .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
727 .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
728 .stream_insert_nav_packets = 0,
729
730 /* audio */
731 .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
732 .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
733 .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
734 .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
735 .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
736 .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
737 .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
738 .audio_mute = 0,
739
740 /* video */
741 .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
742 .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
743 .video_b_frames = 2,
744 .video_gop_size = 12,
745 .video_gop_closure = 1,
746 .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
747 .video_bitrate = 6000000,
748 .video_bitrate_peak = 8000000,
749 .video_temporal_decimation = 0,
750 .video_mute = 0,
751 .video_mute_yuv = 0x008080, /* YCbCr value for black */
752
753 /* encoding filters */
754 .video_spatial_filter_mode =
755 V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
756 .video_spatial_filter = 0,
757 .video_luma_spatial_filter_type =
758 V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
759 .video_chroma_spatial_filter_type =
760 V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
761 .video_temporal_filter_mode =
762 V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
763 .video_temporal_filter = 8,
764 .video_median_filter_type =
765 V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
766 .video_luma_median_filter_top = 255,
767 .video_luma_median_filter_bottom = 0,
768 .video_chroma_median_filter_top = 255,
769 .video_chroma_median_filter_bottom = 0,
770 };
771
772 *p = default_params; 794 *p = default_params;
773 cx2341x_calc_audio_properties(p); 795 cx2341x_calc_audio_properties(p);
774} 796}
@@ -933,9 +955,9 @@ int cx2341x_update(void *priv, cx2341x_mbox_func func,
933} 955}
934EXPORT_SYMBOL(cx2341x_update); 956EXPORT_SYMBOL(cx2341x_update);
935 957
936static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id) 958static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
937{ 959{
938 const char **menu = cx2341x_ctrl_get_menu(id); 960 const char **menu = cx2341x_ctrl_get_menu(p, id);
939 struct v4l2_ext_control ctrl; 961 struct v4l2_ext_control ctrl;
940 962
941 if (menu == NULL) 963 if (menu == NULL)
@@ -952,7 +974,7 @@ invalid:
952 return "<invalid>"; 974 return "<invalid>";
953} 975}
954 976
955void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix) 977void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
956{ 978{
957 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; 979 int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
958 int temporal = p->video_temporal_filter; 980 int temporal = p->video_temporal_filter;
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
index 7bf14c9a15c7..5cfb46bbdaa9 100644
--- a/drivers/media/video/cx23885/Kconfig
+++ b/drivers/media/video/cx23885/Kconfig
@@ -9,11 +9,13 @@ config VIDEO_CX23885
9 select VIDEO_TVEEPROM 9 select VIDEO_TVEEPROM
10 select VIDEO_IR 10 select VIDEO_IR
11 select VIDEOBUF_DVB 11 select VIDEOBUF_DVB
12 select VIDEOBUF_DMA_SG
12 select VIDEO_CX25840 13 select VIDEO_CX25840
13 select VIDEO_CX2341X 14 select VIDEO_CX2341X
14 select DVB_DIB7000P if !DVB_FE_CUSTOMISE 15 select DVB_DIB7000P if !DVB_FE_CUSTOMISE
15 select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE 16 select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE
16 select DVB_S5H1409 if !DVB_FE_CUSTOMISE 17 select DVB_S5H1409 if !DVB_FE_CUSTOMISE
18 select DVB_S5H1411 if !DVB_FE_CUSTOMISE
17 select DVB_LGDT330X if !DVB_FE_CUSTOMISE 19 select DVB_LGDT330X if !DVB_FE_CUSTOMISE
18 select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE 20 select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE
19 select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE 21 select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
index acdd3b6b3e7c..e7ef093265af 100644
--- a/drivers/media/video/cx23885/cx23885-417.c
+++ b/drivers/media/video/cx23885/cx23885-417.c
@@ -1173,379 +1173,404 @@ static int cx23885_querymenu(struct cx23885_dev *dev,
1173 qctrl.id = qmenu->id; 1173 qctrl.id = qmenu->id;
1174 cx23885_queryctrl(dev, &qctrl); 1174 cx23885_queryctrl(dev, &qctrl);
1175 return v4l2_ctrl_query_menu(qmenu, &qctrl, 1175 return v4l2_ctrl_query_menu(qmenu, &qctrl,
1176 cx2341x_ctrl_get_menu(qmenu->id)); 1176 cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));
1177} 1177}
1178 1178
1179int cx23885_do_ioctl(struct inode *inode, struct file *file, int radio, 1179static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
1180 struct cx23885_dev *dev, unsigned int cmd, void *arg,
1181 v4l2_kioctl driver_ioctl)
1182{ 1180{
1183 int err; 1181 struct cx23885_fh *fh = file->private_data;
1182 struct cx23885_dev *dev = fh->dev;
1183 unsigned int i;
1184 1184
1185 switch (cmd) { 1185 for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)
1186 /* ---------- tv norms ---------- */ 1186 if (*id & cx23885_tvnorms[i].id)
1187 case VIDIOC_ENUMSTD: 1187 break;
1188 { 1188 if (i == ARRAY_SIZE(cx23885_tvnorms))
1189 struct v4l2_standard *e = arg; 1189 return -EINVAL;
1190 unsigned int i; 1190 dev->encodernorm = cx23885_tvnorms[i];
1191 1191 return 0;
1192 i = e->index; 1192}
1193 if (i >= ARRAY_SIZE(cx23885_tvnorms))
1194 return -EINVAL;
1195 err = v4l2_video_std_construct(e,
1196 cx23885_tvnorms[e->index].id,
1197 cx23885_tvnorms[e->index].name);
1198 e->index = i;
1199 if (err < 0)
1200 return err;
1201 return 0;
1202 }
1203 case VIDIOC_G_STD:
1204 {
1205 v4l2_std_id *id = arg;
1206 1193
1207 *id = dev->encodernorm.id; 1194static int vidioc_enum_input(struct file *file, void *priv,
1208 return 0; 1195 struct v4l2_input *i)
1209 } 1196{
1210 case VIDIOC_S_STD: 1197 struct cx23885_fh *fh = file->private_data;
1211 { 1198 struct cx23885_dev *dev = fh->dev;
1212 v4l2_std_id *id = arg; 1199 struct cx23885_input *input;
1213 unsigned int i; 1200 unsigned int n;
1214 1201
1215 for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++) 1202 n = i->index;
1216 if (*id & cx23885_tvnorms[i].id)
1217 break;
1218 if (i == ARRAY_SIZE(cx23885_tvnorms))
1219 return -EINVAL;
1220 dev->encodernorm = cx23885_tvnorms[i];
1221 1203
1222 return 0; 1204 if (n >= 4)
1223 } 1205 return -EINVAL;
1224 1206
1225 /* ------ input switching ---------- */ 1207 input = &cx23885_boards[dev->board].input[n];
1226 case VIDIOC_ENUMINPUT:
1227 {
1228 struct cx23885_input *input;
1229 struct v4l2_input *i = arg;
1230 unsigned int n;
1231
1232 n = i->index;
1233 if (n >= 4)
1234 return -EINVAL;
1235 input = &cx23885_boards[dev->board].input[n];
1236 if (input->type == 0)
1237 return -EINVAL;
1238 memset(i, 0, sizeof(*i));
1239 i->index = n;
1240 /* FIXME
1241 * strcpy(i->name, input->name); */
1242 strcpy(i->name, "unset");
1243 if (input->type == CX23885_VMUX_TELEVISION ||
1244 input->type == CX23885_VMUX_CABLE)
1245 i->type = V4L2_INPUT_TYPE_TUNER;
1246 else
1247 i->type = V4L2_INPUT_TYPE_CAMERA;
1248 1208
1249 for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++) 1209 if (input->type == 0)
1250 i->std |= cx23885_tvnorms[n].id; 1210 return -EINVAL;
1251 return 0;
1252 }
1253 case VIDIOC_G_INPUT:
1254 {
1255 unsigned int *i = arg;
1256 1211
1257 *i = dev->input; 1212 memset(i, 0, sizeof(*i));
1258 return 0; 1213 i->index = n;
1259 }
1260 case VIDIOC_S_INPUT:
1261 {
1262 unsigned int *i = arg;
1263 1214
1264 if (*i >= 4) 1215 /* FIXME
1265 return -EINVAL; 1216 * strcpy(i->name, input->name); */
1217 strcpy(i->name, "unset");
1266 1218
1267 return 0; 1219 if (input->type == CX23885_VMUX_TELEVISION ||
1268 } 1220 input->type == CX23885_VMUX_CABLE)
1221 i->type = V4L2_INPUT_TYPE_TUNER;
1222 else
1223 i->type = V4L2_INPUT_TYPE_CAMERA;
1269 1224
1270 /* --- tuner ioctls ------------------------------------------ */ 1225 for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++)
1271 case VIDIOC_G_TUNER: 1226 i->std |= cx23885_tvnorms[n].id;
1272 { 1227 return 0;
1273 struct v4l2_tuner *t = arg; 1228}
1274 1229
1275 if (UNSET == dev->tuner_type) 1230static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1276 return -EINVAL; 1231{
1277 if (0 != t->index) 1232 struct cx23885_fh *fh = file->private_data;
1278 return -EINVAL; 1233 struct cx23885_dev *dev = fh->dev;
1279 memset(t, 0, sizeof(*t));
1280 strcpy(t->name, "Television");
1281 cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t);
1282 cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
1283 1234
1284 dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type); 1235 *i = dev->input;
1236 return 0;
1237}
1285 1238
1286 return 0; 1239static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1287 } 1240{
1288 case VIDIOC_S_TUNER: 1241 if (i >= 4)
1289 { 1242 return -EINVAL;
1290 struct v4l2_tuner *t = arg;
1291 1243
1292 if (UNSET == dev->tuner_type) 1244 return 0;
1293 return -EINVAL; 1245}
1294 1246
1295 /* Update the A/V core */ 1247static int vidioc_g_tuner(struct file *file, void *priv,
1296 cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t); 1248 struct v4l2_tuner *t)
1249{
1250 struct cx23885_fh *fh = file->private_data;
1251 struct cx23885_dev *dev = fh->dev;
1297 1252
1298 return 0; 1253 if (UNSET == dev->tuner_type)
1299 } 1254 return -EINVAL;
1300 case VIDIOC_G_FREQUENCY: 1255 if (0 != t->index)
1301 { 1256 return -EINVAL;
1302 struct v4l2_frequency *f = arg; 1257 memset(t, 0, sizeof(*t));
1258 strcpy(t->name, "Television");
1259 cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_G_TUNER, t);
1260 cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_TUNER, t);
1303 1261
1304 memset(f, 0, sizeof(*f)); 1262 dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
1305 if (UNSET == dev->tuner_type)
1306 return -EINVAL;
1307 f->type = V4L2_TUNER_ANALOG_TV;
1308 f->frequency = dev->freq;
1309 1263
1310 /* Assumption that tuner is always on bus 1 */ 1264 return 0;
1311 cx23885_call_i2c_clients(&dev->i2c_bus[1], 1265}
1312 VIDIOC_G_FREQUENCY, f);
1313 1266
1314 return 0; 1267static int vidioc_s_tuner(struct file *file, void *priv,
1315 } 1268 struct v4l2_tuner *t)
1316 case VIDIOC_S_FREQUENCY: 1269{
1317 { 1270 struct cx23885_fh *fh = file->private_data;
1318 struct v4l2_frequency *f = arg; 1271 struct cx23885_dev *dev = fh->dev;
1319 1272
1320 dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n", 1273 if (UNSET == dev->tuner_type)
1321 dev->tuner_type); 1274 return -EINVAL;
1322 dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n", 1275
1323 f->tuner, f->type); 1276 /* Update the A/V core */
1324 if (UNSET == dev->tuner_type) 1277 cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_TUNER, t);
1325 return -EINVAL; 1278
1326 if (f->tuner != 0) 1279 return 0;
1327 return -EINVAL; 1280}
1328 if (f->type != V4L2_TUNER_ANALOG_TV) 1281
1329 return -EINVAL; 1282static int vidioc_g_frequency(struct file *file, void *priv,
1330 dev->freq = f->frequency; 1283 struct v4l2_frequency *f)
1331 1284{
1332 /* Assumption that tuner is always on bus 1 */ 1285 struct cx23885_fh *fh = file->private_data;
1333 cx23885_call_i2c_clients(&dev->i2c_bus[1], 1286 struct cx23885_dev *dev = fh->dev;
1334 VIDIOC_S_FREQUENCY, f); 1287
1335 return 0; 1288 memset(f, 0, sizeof(*f));
1336 } 1289 if (UNSET == dev->tuner_type)
1337 case VIDIOC_S_CTRL: 1290 return -EINVAL;
1338 { 1291 f->type = V4L2_TUNER_ANALOG_TV;
1339 /* Update the A/V core */ 1292 f->frequency = dev->freq;
1340 cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, arg); 1293
1341 return 0; 1294 /* Assumption that tuner is always on bus 1 */
1342 } 1295 cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_G_FREQUENCY, f);
1343 default: 1296
1344 /* Convert V4L ioctl to V4L2 and call mpeg_do_ioctl 1297 return 0;
1345 * (driver_ioctl) */ 1298}
1346 return v4l_compat_translate_ioctl(inode, file, cmd, arg, 1299
1347 driver_ioctl); 1300static int vidioc_s_frequency(struct file *file, void *priv,
1348 } 1301 struct v4l2_frequency *f)
1302{
1303 struct cx23885_fh *fh = file->private_data;
1304 struct cx23885_dev *dev = fh->dev;
1305
1306 cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
1307 CX23885_END_NOW, CX23885_MPEG_CAPTURE,
1308 CX23885_RAW_BITS_NONE);
1309
1310 dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n",
1311 dev->tuner_type);
1312 dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n",
1313 f->tuner, f->type);
1314 if (UNSET == dev->tuner_type)
1315 return -EINVAL;
1316 if (f->tuner != 0)
1317 return -EINVAL;
1318 if (f->type != V4L2_TUNER_ANALOG_TV)
1319 return -EINVAL;
1320 dev->freq = f->frequency;
1321
1322 /* Assumption that tuner is always on bus 1 */
1323 cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, f);
1324
1325 cx23885_initialize_codec(dev);
1349 1326
1350 return 0; 1327 return 0;
1351} 1328}
1352 1329
1353static int mpeg_do_ioctl(struct inode *inode, struct file *file, 1330static int vidioc_s_ctrl(struct file *file, void *priv,
1354 unsigned int cmd, void *arg) 1331 struct v4l2_control *ctl)
1332{
1333 struct cx23885_fh *fh = file->private_data;
1334 struct cx23885_dev *dev = fh->dev;
1335
1336 /* Update the A/V core */
1337 cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_S_CTRL, ctl);
1338 return 0;
1339}
1340
1341static int vidioc_querycap(struct file *file, void *priv,
1342 struct v4l2_capability *cap)
1355{ 1343{
1356 struct cx23885_fh *fh = file->private_data; 1344 struct cx23885_fh *fh = file->private_data;
1357 struct cx23885_dev *dev = fh->dev; 1345 struct cx23885_dev *dev = fh->dev;
1358 struct cx23885_tsport *tsport = &dev->ts1; 1346 struct cx23885_tsport *tsport = &dev->ts1;
1359 1347
1360 if (v4l_debug > 1) 1348 memset(cap, 0, sizeof(*cap));
1361 v4l_print_ioctl(dev->name, cmd); 1349 strcpy(cap->driver, dev->name);
1350 strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
1351 sizeof(cap->card));
1352 sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
1353 cap->version = CX23885_VERSION_CODE;
1354 cap->capabilities =
1355 V4L2_CAP_VIDEO_CAPTURE |
1356 V4L2_CAP_READWRITE |
1357 V4L2_CAP_STREAMING |
1358 0;
1359 if (UNSET != dev->tuner_type)
1360 cap->capabilities |= V4L2_CAP_TUNER;
1362 1361
1363 switch (cmd) { 1362 return 0;
1363}
1364 1364
1365 /* --- capabilities ------------------------------------------ */ 1365static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1366 case VIDIOC_QUERYCAP: 1366 struct v4l2_fmtdesc *f)
1367 { 1367{
1368 struct v4l2_capability *cap = arg; 1368 int index;
1369
1370 memset(cap, 0, sizeof(*cap));
1371 strcpy(cap->driver, dev->name);
1372 strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
1373 sizeof(cap->card));
1374 sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
1375 cap->version = CX23885_VERSION_CODE;
1376 cap->capabilities =
1377 V4L2_CAP_VIDEO_CAPTURE |
1378 V4L2_CAP_READWRITE |
1379 V4L2_CAP_STREAMING |
1380 0;
1381 if (UNSET != dev->tuner_type)
1382 cap->capabilities |= V4L2_CAP_TUNER;
1383
1384 return 0;
1385 }
1386 1369
1387 /* --- capture ioctls ---------------------------------------- */ 1370 index = f->index;
1388 case VIDIOC_ENUM_FMT: 1371 if (index != 0)
1389 { 1372 return -EINVAL;
1390 struct v4l2_fmtdesc *f = arg;
1391 int index;
1392
1393 index = f->index;
1394 if (index != 0)
1395 return -EINVAL;
1396
1397 memset(f, 0, sizeof(*f));
1398 f->index = index;
1399 strlcpy(f->description, "MPEG", sizeof(f->description));
1400 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1401 f->pixelformat = V4L2_PIX_FMT_MPEG;
1402 return 0;
1403 }
1404 case VIDIOC_G_FMT:
1405 {
1406 struct v4l2_format *f = arg;
1407
1408 memset(f, 0, sizeof(*f));
1409 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1410 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
1411 f->fmt.pix.bytesperline = 0;
1412 f->fmt.pix.sizeimage =
1413 dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
1414 f->fmt.pix.colorspace = 0;
1415 f->fmt.pix.width = dev->ts1.width;
1416 f->fmt.pix.height = dev->ts1.height;
1417 f->fmt.pix.field = fh->mpegq.field;
1418 dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
1419 dev->ts1.width, dev->ts1.height, fh->mpegq.field);
1420 return 0;
1421 }
1422 case VIDIOC_TRY_FMT:
1423 {
1424 struct v4l2_format *f = arg;
1425
1426 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1427 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
1428 f->fmt.pix.bytesperline = 0;
1429 f->fmt.pix.sizeimage =
1430 dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
1431 f->fmt.pix.sizeimage =
1432 f->fmt.pix.colorspace = 0;
1433 dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
1434 dev->ts1.width, dev->ts1.height, fh->mpegq.field);
1435 return 0;
1436 }
1437 case VIDIOC_S_FMT:
1438 {
1439 struct v4l2_format *f = arg;
1440
1441 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1442 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
1443 f->fmt.pix.bytesperline = 0;
1444 f->fmt.pix.sizeimage =
1445 dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
1446 f->fmt.pix.colorspace = 0;
1447 dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
1448 f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
1449 return 0;
1450 }
1451 1373
1452 /* --- streaming capture ------------------------------------- */ 1374 memset(f, 0, sizeof(*f));
1453 case VIDIOC_REQBUFS: 1375 f->index = index;
1454 return videobuf_reqbufs(&fh->mpegq, arg); 1376 strlcpy(f->description, "MPEG", sizeof(f->description));
1377 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1378 f->pixelformat = V4L2_PIX_FMT_MPEG;
1455 1379
1456 case VIDIOC_QUERYBUF: 1380 return 0;
1457 return videobuf_querybuf(&fh->mpegq, arg); 1381}
1458 1382
1459 case VIDIOC_QBUF: 1383static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1460 return videobuf_qbuf(&fh->mpegq, arg); 1384 struct v4l2_format *f)
1385{
1386 struct cx23885_fh *fh = file->private_data;
1387 struct cx23885_dev *dev = fh->dev;
1461 1388
1462 case VIDIOC_DQBUF: 1389 memset(f, 0, sizeof(*f));
1463 return videobuf_dqbuf(&fh->mpegq, arg, 1390 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1464 file->f_flags & O_NONBLOCK); 1391 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
1392 f->fmt.pix.bytesperline = 0;
1393 f->fmt.pix.sizeimage =
1394 dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
1395 f->fmt.pix.colorspace = 0;
1396 f->fmt.pix.width = dev->ts1.width;
1397 f->fmt.pix.height = dev->ts1.height;
1398 f->fmt.pix.field = fh->mpegq.field;
1399 dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
1400 dev->ts1.width, dev->ts1.height, fh->mpegq.field);
1401 return 0;
1402}
1465 1403
1466 case VIDIOC_STREAMON: 1404static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1467 return videobuf_streamon(&fh->mpegq); 1405 struct v4l2_format *f)
1406{
1407 struct cx23885_fh *fh = file->private_data;
1408 struct cx23885_dev *dev = fh->dev;
1468 1409
1469 case VIDIOC_STREAMOFF: 1410 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1470 return videobuf_streamoff(&fh->mpegq); 1411 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
1412 f->fmt.pix.bytesperline = 0;
1413 f->fmt.pix.sizeimage =
1414 dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
1415 f->fmt.pix.sizeimage =
1416 f->fmt.pix.colorspace = 0;
1417 dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
1418 dev->ts1.width, dev->ts1.height, fh->mpegq.field);
1419 return 0;
1420}
1471 1421
1472 case VIDIOC_G_EXT_CTRLS: 1422static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1473 { 1423 struct v4l2_format *f)
1474 struct v4l2_ext_controls *f = arg; 1424{
1425 struct cx23885_fh *fh = file->private_data;
1426 struct cx23885_dev *dev = fh->dev;
1475 1427
1476 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) 1428 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1477 return -EINVAL; 1429 f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
1478 return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, cmd); 1430 f->fmt.pix.bytesperline = 0;
1479 } 1431 f->fmt.pix.sizeimage =
1480 case VIDIOC_S_EXT_CTRLS: 1432 dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
1481 case VIDIOC_TRY_EXT_CTRLS: 1433 f->fmt.pix.colorspace = 0;
1482 { 1434 dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
1483 struct v4l2_ext_controls *f = arg; 1435 f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
1484 struct cx2341x_mpeg_params p; 1436 return 0;
1485 int err; 1437}
1486
1487 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
1488 return -EINVAL;
1489 p = dev->mpeg_params;
1490 err = cx2341x_ext_ctrls(&p, 0, f, cmd);
1491 if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
1492 err = cx2341x_update(dev, cx23885_mbox_func,
1493 &dev->mpeg_params, &p);
1494 dev->mpeg_params = p;
1495 }
1496 return err;
1497 }
1498 case VIDIOC_S_FREQUENCY:
1499 {
1500 cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
1501 CX23885_END_NOW, CX23885_MPEG_CAPTURE,
1502 CX23885_RAW_BITS_NONE);
1503 cx23885_do_ioctl(inode, file, 0, dev, cmd, arg,
1504 mpeg_do_ioctl);
1505 cx23885_initialize_codec(dev);
1506
1507 return 0;
1508 }
1509 case VIDIOC_LOG_STATUS:
1510 {
1511 char name[32 + 2];
1512
1513 snprintf(name, sizeof(name), "%s/2", dev->name);
1514 printk(KERN_INFO
1515 "%s/2: ============ START LOG STATUS ============\n",
1516 dev->name);
1517 cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS,
1518 NULL);
1519 cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS,
1520 NULL);
1521 cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS,
1522 NULL);
1523 cx2341x_log_status(&dev->mpeg_params, name);
1524 printk(KERN_INFO
1525 "%s/2: ============= END LOG STATUS =============\n",
1526 dev->name);
1527 return 0;
1528 }
1529 case VIDIOC_QUERYMENU:
1530 return cx23885_querymenu(dev, arg);
1531 case VIDIOC_QUERYCTRL:
1532 {
1533 struct v4l2_queryctrl *c = arg;
1534 1438
1535 return cx23885_queryctrl(dev, c); 1439static int vidioc_reqbufs(struct file *file, void *priv,
1536 } 1440 struct v4l2_requestbuffers *p)
1441{
1442 struct cx23885_fh *fh = file->private_data;
1537 1443
1538 default: 1444 return videobuf_reqbufs(&fh->mpegq, p);
1539 return cx23885_do_ioctl(inode, file, 0, dev, cmd, arg, 1445}
1540 mpeg_do_ioctl); 1446
1447static int vidioc_querybuf(struct file *file, void *priv,
1448 struct v4l2_buffer *p)
1449{
1450 struct cx23885_fh *fh = file->private_data;
1451
1452 return videobuf_querybuf(&fh->mpegq, p);
1453}
1454
1455static int vidioc_qbuf(struct file *file, void *priv,
1456 struct v4l2_buffer *p)
1457{
1458 struct cx23885_fh *fh = file->private_data;
1459
1460 return videobuf_qbuf(&fh->mpegq, p);
1461}
1462
1463static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
1464{
1465 struct cx23885_fh *fh = priv;
1466
1467 return videobuf_dqbuf(&fh->mpegq, b, file->f_flags & O_NONBLOCK);
1468}
1469
1470
1471static int vidioc_streamon(struct file *file, void *priv,
1472 enum v4l2_buf_type i)
1473{
1474 struct cx23885_fh *fh = file->private_data;
1475
1476 return videobuf_streamon(&fh->mpegq);
1477}
1478
1479static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
1480{
1481 struct cx23885_fh *fh = file->private_data;
1482
1483 return videobuf_streamoff(&fh->mpegq);
1484}
1485
1486static int vidioc_g_ext_ctrls(struct file *file, void *priv,
1487 struct v4l2_ext_controls *f)
1488{
1489 struct cx23885_fh *fh = priv;
1490 struct cx23885_dev *dev = fh->dev;
1491
1492 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
1493 return -EINVAL;
1494 return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);
1495}
1496
1497static int vidioc_s_ext_ctrls(struct file *file, void *priv,
1498 struct v4l2_ext_controls *f)
1499{
1500 struct cx23885_fh *fh = priv;
1501 struct cx23885_dev *dev = fh->dev;
1502 struct cx2341x_mpeg_params p;
1503 int err;
1504
1505 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
1506 return -EINVAL;
1507
1508 p = dev->mpeg_params;
1509 err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS);
1510
1511 if (err == 0) {
1512 err = cx2341x_update(dev, cx23885_mbox_func,
1513 &dev->mpeg_params, &p);
1514 dev->mpeg_params = p;
1541 } 1515 }
1516 return err;
1517}
1518
1519static int vidioc_try_ext_ctrls(struct file *file, void *priv,
1520 struct v4l2_ext_controls *f)
1521{
1522 struct cx23885_fh *fh = priv;
1523 struct cx23885_dev *dev = fh->dev;
1524 struct cx2341x_mpeg_params p;
1525 int err;
1526
1527 if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
1528 return -EINVAL;
1529
1530 p = dev->mpeg_params;
1531 err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
1532 return err;
1533}
1534
1535static int vidioc_log_status(struct file *file, void *priv)
1536{
1537 struct cx23885_fh *fh = priv;
1538 struct cx23885_dev *dev = fh->dev;
1539 char name[32 + 2];
1540
1541 snprintf(name, sizeof(name), "%s/2", dev->name);
1542 printk(KERN_INFO
1543 "%s/2: ============ START LOG STATUS ============\n",
1544 dev->name);
1545 cx23885_call_i2c_clients(&dev->i2c_bus[0], VIDIOC_LOG_STATUS,
1546 NULL);
1547 cx23885_call_i2c_clients(&dev->i2c_bus[1], VIDIOC_LOG_STATUS,
1548 NULL);
1549 cx23885_call_i2c_clients(&dev->i2c_bus[2], VIDIOC_LOG_STATUS,
1550 NULL);
1551 cx2341x_log_status(&dev->mpeg_params, name);
1552 printk(KERN_INFO
1553 "%s/2: ============= END LOG STATUS =============\n",
1554 dev->name);
1542 return 0; 1555 return 0;
1543} 1556}
1544 1557
1545static int mpeg_ioctl(struct inode *inode, struct file *file, 1558static int vidioc_querymenu(struct file *file, void *priv,
1546 unsigned int cmd, unsigned long arg) 1559 struct v4l2_querymenu *a)
1560{
1561 struct cx23885_fh *fh = priv;
1562 struct cx23885_dev *dev = fh->dev;
1563
1564 return cx23885_querymenu(dev, a);
1565}
1566
1567static int vidioc_queryctrl(struct file *file, void *priv,
1568 struct v4l2_queryctrl *c)
1547{ 1569{
1548 return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl); 1570 struct cx23885_fh *fh = priv;
1571 struct cx23885_dev *dev = fh->dev;
1572
1573 return cx23885_queryctrl(dev, c);
1549} 1574}
1550 1575
1551static int mpeg_open(struct inode *inode, struct file *file) 1576static int mpeg_open(struct inode *inode, struct file *file)
@@ -1670,7 +1695,7 @@ static struct file_operations mpeg_fops = {
1670 .read = mpeg_read, 1695 .read = mpeg_read,
1671 .poll = mpeg_poll, 1696 .poll = mpeg_poll,
1672 .mmap = mpeg_mmap, 1697 .mmap = mpeg_mmap,
1673 .ioctl = mpeg_ioctl, 1698 .ioctl = video_ioctl2,
1674 .llseek = no_llseek, 1699 .llseek = no_llseek,
1675}; 1700};
1676 1701
@@ -1682,6 +1707,32 @@ static struct video_device cx23885_mpeg_template = {
1682 VID_TYPE_MPEG_ENCODER, 1707 VID_TYPE_MPEG_ENCODER,
1683 .fops = &mpeg_fops, 1708 .fops = &mpeg_fops,
1684 .minor = -1, 1709 .minor = -1,
1710 .vidioc_s_std = vidioc_s_std,
1711 .vidioc_enum_input = vidioc_enum_input,
1712 .vidioc_g_input = vidioc_g_input,
1713 .vidioc_s_input = vidioc_s_input,
1714 .vidioc_g_tuner = vidioc_g_tuner,
1715 .vidioc_s_tuner = vidioc_s_tuner,
1716 .vidioc_g_frequency = vidioc_g_frequency,
1717 .vidioc_s_frequency = vidioc_s_frequency,
1718 .vidioc_s_ctrl = vidioc_s_ctrl,
1719 .vidioc_querycap = vidioc_querycap,
1720 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1721 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1722 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1723 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1724 .vidioc_reqbufs = vidioc_reqbufs,
1725 .vidioc_querybuf = vidioc_querybuf,
1726 .vidioc_qbuf = vidioc_qbuf,
1727 .vidioc_dqbuf = vidioc_dqbuf,
1728 .vidioc_streamon = vidioc_streamon,
1729 .vidioc_streamoff = vidioc_streamoff,
1730 .vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
1731 .vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
1732 .vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
1733 .vidioc_log_status = vidioc_log_status,
1734 .vidioc_querymenu = vidioc_querymenu,
1735 .vidioc_queryctrl = vidioc_queryctrl,
1685}; 1736};
1686 1737
1687void cx23885_417_unregister(struct cx23885_dev *dev) 1738void cx23885_417_unregister(struct cx23885_dev *dev)
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
index 20e05f230546..fd7112c11d35 100644
--- a/drivers/media/video/cx23885/cx23885-cards.c
+++ b/drivers/media/video/cx23885/cx23885-cards.c
@@ -143,6 +143,10 @@ struct cx23885_board cx23885_boards[] = {
143 .name = "Hauppauge WinTV-HVR1400", 143 .name = "Hauppauge WinTV-HVR1400",
144 .portc = CX23885_MPEG_DVB, 144 .portc = CX23885_MPEG_DVB,
145 }, 145 },
146 [CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP] = {
147 .name = "DViCO FusionHDTV7 Dual Express",
148 .portc = CX23885_MPEG_DVB,
149 },
146}; 150};
147const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); 151const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
148 152
@@ -210,6 +214,10 @@ struct cx23885_subid cx23885_subids[] = {
210 .subvendor = 0x0070, 214 .subvendor = 0x0070,
211 .subdevice = 0x8010, 215 .subdevice = 0x8010,
212 .card = CX23885_BOARD_HAUPPAUGE_HVR1400, 216 .card = CX23885_BOARD_HAUPPAUGE_HVR1400,
217 },{
218 .subvendor = 0x18ac,
219 .subdevice = 0xd618,
220 .card = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP,
213 }, 221 },
214}; 222};
215const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); 223const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -477,6 +485,11 @@ void cx23885_card_setup(struct cx23885_dev *dev)
477 } 485 }
478 486
479 switch (dev->board) { 487 switch (dev->board) {
488 case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
489 ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
490 ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
491 ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
492 /* break omitted intentionally */
480 case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP: 493 case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
481 ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ 494 ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
482 ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ 495 ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
index c4cc2f3b8876..d17343ea0d33 100644
--- a/drivers/media/video/cx23885/cx23885-core.c
+++ b/drivers/media/video/cx23885/cx23885-core.c
@@ -291,9 +291,9 @@ int cx23885_sram_channel_setup(struct cx23885_dev *dev,
291 lines = 6; 291 lines = 6;
292 BUG_ON(lines < 2); 292 BUG_ON(lines < 2);
293 293
294 cx_write(8 + 0, cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC) ); 294 cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
295 cx_write(8 + 4, cpu_to_le32(8) ); 295 cx_write(8 + 4, 8);
296 cx_write(8 + 8, cpu_to_le32(0) ); 296 cx_write(8 + 8, 0);
297 297
298 /* write CDT */ 298 /* write CDT */
299 for (i = 0; i < lines; i++) { 299 for (i = 0; i < lines; i++) {
@@ -408,11 +408,11 @@ static void cx23885_risc_disasm(struct cx23885_tsport *port,
408 dev->name, risc->cpu, (unsigned long)risc->dma); 408 dev->name, risc->cpu, (unsigned long)risc->dma);
409 for (i = 0; i < (risc->size >> 2); i += n) { 409 for (i = 0; i < (risc->size >> 2); i += n) {
410 printk("%s: %04d: ", dev->name, i); 410 printk("%s: %04d: ", dev->name, i);
411 n = cx23885_risc_decode(risc->cpu[i]); 411 n = cx23885_risc_decode(le32_to_cpu(risc->cpu[i]));
412 for (j = 1; j < n; j++) 412 for (j = 1; j < n; j++)
413 printk("%s: %04d: 0x%08x [ arg #%d ]\n", 413 printk("%s: %04d: 0x%08x [ arg #%d ]\n",
414 dev->name, i + j, risc->cpu[i + j], j); 414 dev->name, i + j, risc->cpu[i + j], j);
415 if (risc->cpu[i] == RISC_JUMP) 415 if (risc->cpu[i] == cpu_to_le32(RISC_JUMP))
416 break; 416 break;
417 } 417 }
418} 418}
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
index 022aa391937a..0a2e6558cd66 100644
--- a/drivers/media/video/cx23885/cx23885-dvb.c
+++ b/drivers/media/video/cx23885/cx23885-dvb.c
@@ -31,6 +31,7 @@
31#include <media/v4l2-common.h> 31#include <media/v4l2-common.h>
32 32
33#include "s5h1409.h" 33#include "s5h1409.h"
34#include "s5h1411.h"
34#include "mt2131.h" 35#include "mt2131.h"
35#include "tda8290.h" 36#include "tda8290.h"
36#include "tda18271.h" 37#include "tda18271.h"
@@ -164,12 +165,38 @@ static struct s5h1409_config hauppauge_hvr1500q_config = {
164 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, 165 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
165}; 166};
166 167
168static struct s5h1409_config dvico_s5h1409_config = {
169 .demod_address = 0x32 >> 1,
170 .output_mode = S5H1409_SERIAL_OUTPUT,
171 .gpio = S5H1409_GPIO_ON,
172 .qam_if = 44000,
173 .inversion = S5H1409_INVERSION_OFF,
174 .status_mode = S5H1409_DEMODLOCKING,
175 .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
176};
177
178static struct s5h1411_config dvico_s5h1411_config = {
179 .output_mode = S5H1411_SERIAL_OUTPUT,
180 .gpio = S5H1411_GPIO_ON,
181 .qam_if = S5H1411_IF_44000,
182 .vsb_if = S5H1411_IF_44000,
183 .inversion = S5H1411_INVERSION_OFF,
184 .status_mode = S5H1411_DEMODLOCKING,
185 .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
186};
187
167static struct xc5000_config hauppauge_hvr1500q_tunerconfig = { 188static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
168 .i2c_address = 0x61, 189 .i2c_address = 0x61,
169 .if_khz = 5380, 190 .if_khz = 5380,
170 .tuner_callback = cx23885_tuner_callback 191 .tuner_callback = cx23885_tuner_callback
171}; 192};
172 193
194static struct xc5000_config dvico_xc5000_tunerconfig = {
195 .i2c_address = 0x64,
196 .if_khz = 5380,
197 .tuner_callback = cx23885_tuner_callback
198};
199
173static struct tda829x_config tda829x_no_probe = { 200static struct tda829x_config tda829x_no_probe = {
174 .probe_tuner = TDA829X_DONT_PROBE, 201 .probe_tuner = TDA829X_DONT_PROBE,
175}; 202};
@@ -453,6 +480,21 @@ static int dvb_register(struct cx23885_tsport *port)
453 fe->ops.tuner_ops.set_config(fe, &ctl); 480 fe->ops.tuner_ops.set_config(fe, &ctl);
454 } 481 }
455 break; 482 break;
483 case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
484 i2c_bus = &dev->i2c_bus[port->nr - 1];
485
486 port->dvb.frontend = dvb_attach(s5h1409_attach,
487 &dvico_s5h1409_config,
488 &i2c_bus->i2c_adap);
489 if (port->dvb.frontend == NULL)
490 port->dvb.frontend = dvb_attach(s5h1411_attach,
491 &dvico_s5h1411_config,
492 &i2c_bus->i2c_adap);
493 if (port->dvb.frontend != NULL)
494 dvb_attach(xc5000_attach, port->dvb.frontend,
495 &i2c_bus->i2c_adap,
496 &dvico_xc5000_tunerconfig, i2c_bus);
497 break;
456 default: 498 default:
457 printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", 499 printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
458 dev->name); 500 dev->name);
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
index 84652210a28c..043fc4e5c586 100644
--- a/drivers/media/video/cx23885/cx23885-video.c
+++ b/drivers/media/video/cx23885/cx23885-video.c
@@ -915,7 +915,7 @@ static void init_controls(struct cx23885_dev *dev)
915/* ------------------------------------------------------------------ */ 915/* ------------------------------------------------------------------ */
916/* VIDEO IOCTLS */ 916/* VIDEO IOCTLS */
917 917
918static int vidioc_g_fmt_cap(struct file *file, void *priv, 918static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
919 struct v4l2_format *f) 919 struct v4l2_format *f)
920{ 920{
921 struct cx23885_fh *fh = priv; 921 struct cx23885_fh *fh = priv;
@@ -932,7 +932,7 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
932 return 0; 932 return 0;
933} 933}
934 934
935static int vidioc_try_fmt_cap(struct file *file, void *priv, 935static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
936 struct v4l2_format *f) 936 struct v4l2_format *f)
937{ 937{
938 struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; 938 struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
@@ -983,7 +983,7 @@ static int vidioc_try_fmt_cap(struct file *file, void *priv,
983 return 0; 983 return 0;
984} 984}
985 985
986static int vidioc_s_fmt_cap(struct file *file, void *priv, 986static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
987 struct v4l2_format *f) 987 struct v4l2_format *f)
988{ 988{
989 struct cx23885_fh *fh = priv; 989 struct cx23885_fh *fh = priv;
@@ -991,7 +991,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
991 int err; 991 int err;
992 992
993 dprintk(2, "%s()\n", __func__); 993 dprintk(2, "%s()\n", __func__);
994 err = vidioc_try_fmt_cap(file, priv, f); 994 err = vidioc_try_fmt_vid_cap(file, priv, f);
995 995
996 if (0 != err) 996 if (0 != err)
997 return err; 997 return err;
@@ -1025,7 +1025,7 @@ static int vidioc_querycap(struct file *file, void *priv,
1025 return 0; 1025 return 0;
1026} 1026}
1027 1027
1028static int vidioc_enum_fmt_cap(struct file *file, void *priv, 1028static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1029 struct v4l2_fmtdesc *f) 1029 struct v4l2_fmtdesc *f)
1030{ 1030{
1031 if (unlikely(f->index >= ARRAY_SIZE(formats))) 1031 if (unlikely(f->index >= ARRAY_SIZE(formats)))
@@ -1440,13 +1440,13 @@ static struct video_device cx23885_video_template = {
1440 .fops = &video_fops, 1440 .fops = &video_fops,
1441 .minor = -1, 1441 .minor = -1,
1442 .vidioc_querycap = vidioc_querycap, 1442 .vidioc_querycap = vidioc_querycap,
1443 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, 1443 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1444 .vidioc_g_fmt_cap = vidioc_g_fmt_cap, 1444 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1445 .vidioc_try_fmt_cap = vidioc_try_fmt_cap, 1445 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1446 .vidioc_s_fmt_cap = vidioc_s_fmt_cap, 1446 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1447 .vidioc_g_fmt_vbi = cx23885_vbi_fmt, 1447 .vidioc_g_fmt_vbi_cap = cx23885_vbi_fmt,
1448 .vidioc_try_fmt_vbi = cx23885_vbi_fmt, 1448 .vidioc_try_fmt_vbi_cap = cx23885_vbi_fmt,
1449 .vidioc_s_fmt_vbi = cx23885_vbi_fmt, 1449 .vidioc_s_fmt_vbi_cap = cx23885_vbi_fmt,
1450 .vidioc_reqbufs = vidioc_reqbufs, 1450 .vidioc_reqbufs = vidioc_reqbufs,
1451 .vidioc_querybuf = vidioc_querybuf, 1451 .vidioc_querybuf = vidioc_querybuf,
1452 .vidioc_qbuf = vidioc_qbuf, 1452 .vidioc_qbuf = vidioc_qbuf,
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
index 32af87f25e7b..00dfdc89d641 100644
--- a/drivers/media/video/cx23885/cx23885.h
+++ b/drivers/media/video/cx23885/cx23885.h
@@ -63,6 +63,7 @@
63#define CX23885_BOARD_HAUPPAUGE_HVR1200 7 63#define CX23885_BOARD_HAUPPAUGE_HVR1200 7
64#define CX23885_BOARD_HAUPPAUGE_HVR1700 8 64#define CX23885_BOARD_HAUPPAUGE_HVR1700 8
65#define CX23885_BOARD_HAUPPAUGE_HVR1400 9 65#define CX23885_BOARD_HAUPPAUGE_HVR1400 9
66#define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10
66 67
67/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ 68/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
68#define CX23885_NORMS (\ 69#define CX23885_NORMS (\
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 1da6f134888d..e7bf4f4c1319 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -50,7 +50,6 @@ MODULE_LICENSE("GPL");
50 50
51static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; 51static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
52 52
53
54int cx25840_debug; 53int cx25840_debug;
55 54
56module_param_named(debug,cx25840_debug, int, 0644); 55module_param_named(debug,cx25840_debug, int, 0644);
@@ -238,7 +237,7 @@ static void cx25840_initialize(struct i2c_client *client)
238 cx25840_write(client, 0x8d3, 0x1f); 237 cx25840_write(client, 0x8d3, 0x1f);
239 cx25840_write(client, 0x8e3, 0x03); 238 cx25840_write(client, 0x8e3, 0x03);
240 239
241 cx25840_vbi_setup(client); 240 cx25840_std_setup(client);
242 241
243 /* trial and error says these are needed to get audio */ 242 /* trial and error says these are needed to get audio */
244 cx25840_write(client, 0x914, 0xa0); 243 cx25840_write(client, 0x914, 0xa0);
@@ -338,7 +337,7 @@ static void cx23885_initialize(struct i2c_client *client)
338 finish_wait(&state->fw_wait, &wait); 337 finish_wait(&state->fw_wait, &wait);
339 destroy_workqueue(q); 338 destroy_workqueue(q);
340 339
341 cx25840_vbi_setup(client); 340 cx25840_std_setup(client);
342 341
343 /* (re)set input */ 342 /* (re)set input */
344 set_input(client, state->vid_input, state->aud_input); 343 set_input(client, state->vid_input, state->aud_input);
@@ -349,6 +348,153 @@ static void cx23885_initialize(struct i2c_client *client)
349 348
350/* ----------------------------------------------------------------------- */ 349/* ----------------------------------------------------------------------- */
351 350
351void cx25840_std_setup(struct i2c_client *client)
352{
353 struct cx25840_state *state = i2c_get_clientdata(client);
354 v4l2_std_id std = state->std;
355 int hblank, hactive, burst, vblank, vactive, sc;
356 int vblank656, src_decimation;
357 int luma_lpf, uv_lpf, comb;
358 u32 pll_int, pll_frac, pll_post;
359
360 /* datasheet startup, step 8d */
361 if (std & ~V4L2_STD_NTSC)
362 cx25840_write(client, 0x49f, 0x11);
363 else
364 cx25840_write(client, 0x49f, 0x14);
365
366 if (std & V4L2_STD_625_50) {
367 hblank = 132;
368 hactive = 720;
369 burst = 93;
370 vblank = 36;
371 vactive = 580;
372 vblank656 = 40;
373 src_decimation = 0x21f;
374 luma_lpf = 2;
375
376 if (std & V4L2_STD_SECAM) {
377 uv_lpf = 0;
378 comb = 0;
379 sc = 0x0a425f;
380 } else if (std == V4L2_STD_PAL_Nc) {
381 uv_lpf = 1;
382 comb = 0x20;
383 sc = 556453;
384 } else {
385 uv_lpf = 1;
386 comb = 0x20;
387 sc = 688739;
388 }
389 } else {
390 hactive = 720;
391 hblank = 122;
392 vactive = 487;
393 luma_lpf = 1;
394 uv_lpf = 1;
395
396 src_decimation = 0x21f;
397 if (std == V4L2_STD_PAL_60) {
398 vblank = 26;
399 vblank656 = 26;
400 burst = 0x5b;
401 luma_lpf = 2;
402 comb = 0x20;
403 sc = 688739;
404 } else if (std == V4L2_STD_PAL_M) {
405 vblank = 20;
406 vblank656 = 24;
407 burst = 0x61;
408 comb = 0x20;
409 sc = 555452;
410 } else {
411 vblank = 26;
412 vblank656 = 26;
413 burst = 0x5b;
414 comb = 0x66;
415 sc = 556063;
416 }
417 }
418
419 /* DEBUG: Displays configured PLL frequency */
420 pll_int = cx25840_read(client, 0x108);
421 pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff;
422 pll_post = cx25840_read(client, 0x109);
423 v4l_dbg(1, cx25840_debug, client,
424 "PLL regs = int: %u, frac: %u, post: %u\n",
425 pll_int, pll_frac, pll_post);
426
427 if (pll_post) {
428 int fin, fsc;
429 int pll = (28636363L * ((((u64)pll_int) << 25L) + pll_frac)) >> 25L;
430
431 pll /= pll_post;
432 v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n",
433 pll / 1000000, pll % 1000000);
434 v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n",
435 pll / 8000000, (pll / 8) % 1000000);
436
437 fin = ((u64)src_decimation * pll) >> 12;
438 v4l_dbg(1, cx25840_debug, client,
439 "ADC Sampling freq = %d.%06d MHz\n",
440 fin / 1000000, fin % 1000000);
441
442 fsc = (((u64)sc) * pll) >> 24L;
443 v4l_dbg(1, cx25840_debug, client,
444 "Chroma sub-carrier freq = %d.%06d MHz\n",
445 fsc / 1000000, fsc % 1000000);
446
447 v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
448 "vblank %i, vactive %i, vblank656 %i, src_dec %i, "
449 "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, "
450 "sc 0x%06x\n",
451 hblank, hactive, vblank, vactive, vblank656,
452 src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
453 }
454
455 /* Sets horizontal blanking delay and active lines */
456 cx25840_write(client, 0x470, hblank);
457 cx25840_write(client, 0x471,
458 0xff & (((hblank >> 8) & 0x3) | (hactive << 4)));
459 cx25840_write(client, 0x472, hactive >> 4);
460
461 /* Sets burst gate delay */
462 cx25840_write(client, 0x473, burst);
463
464 /* Sets vertical blanking delay and active duration */
465 cx25840_write(client, 0x474, vblank);
466 cx25840_write(client, 0x475,
467 0xff & (((vblank >> 8) & 0x3) | (vactive << 4)));
468 cx25840_write(client, 0x476, vactive >> 4);
469 cx25840_write(client, 0x477, vblank656);
470
471 /* Sets src decimation rate */
472 cx25840_write(client, 0x478, 0xff & src_decimation);
473 cx25840_write(client, 0x479, 0xff & (src_decimation >> 8));
474
475 /* Sets Luma and UV Low pass filters */
476 cx25840_write(client, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
477
478 /* Enables comb filters */
479 cx25840_write(client, 0x47b, comb);
480
481 /* Sets SC Step*/
482 cx25840_write(client, 0x47c, sc);
483 cx25840_write(client, 0x47d, 0xff & sc >> 8);
484 cx25840_write(client, 0x47e, 0xff & sc >> 16);
485
486 /* Sets VBI parameters */
487 if (std & V4L2_STD_625_50) {
488 cx25840_write(client, 0x47f, 0x01);
489 state->vbi_line_offset = 5;
490 } else {
491 cx25840_write(client, 0x47f, 0x00);
492 state->vbi_line_offset = 8;
493 }
494}
495
496/* ----------------------------------------------------------------------- */
497
352static void input_change(struct i2c_client *client) 498static void input_change(struct i2c_client *client)
353{ 499{
354 struct cx25840_state *state = i2c_get_clientdata(client); 500 struct cx25840_state *state = i2c_get_clientdata(client);
@@ -566,7 +712,7 @@ static int set_v4lstd(struct i2c_client *client)
566 } 712 }
567 cx25840_and_or(client, 0x400, ~0xf, fmt); 713 cx25840_and_or(client, 0x400, ~0xf, fmt);
568 cx25840_and_or(client, 0x403, ~0x3, pal_m); 714 cx25840_and_or(client, 0x403, ~0x3, pal_m);
569 cx25840_vbi_setup(client); 715 cx25840_std_setup(client);
570 if (!state->is_cx25836) 716 if (!state->is_cx25836)
571 input_change(client); 717 input_change(client);
572 return 0; 718 return 0;
@@ -1058,6 +1204,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
1058 1204
1059 switch (qc->id) { 1205 switch (qc->id) {
1060 case V4L2_CID_AUDIO_VOLUME: 1206 case V4L2_CID_AUDIO_VOLUME:
1207 return v4l2_ctrl_query_fill(qc, 0, 65535,
1208 65535 / 100, state->default_volume);
1061 case V4L2_CID_AUDIO_MUTE: 1209 case V4L2_CID_AUDIO_MUTE:
1062 case V4L2_CID_AUDIO_BALANCE: 1210 case V4L2_CID_AUDIO_BALANCE:
1063 case V4L2_CID_AUDIO_BASS: 1211 case V4L2_CID_AUDIO_BASS:
@@ -1265,6 +1413,8 @@ static int cx25840_probe(struct i2c_client *client,
1265 state->pvr150_workaround = 0; 1413 state->pvr150_workaround = 0;
1266 state->audmode = V4L2_TUNER_MODE_LANG1; 1414 state->audmode = V4L2_TUNER_MODE_LANG1;
1267 state->unmute_volume = -1; 1415 state->unmute_volume = -1;
1416 state->default_volume = 228 - cx25840_read(client, 0x8d4);
1417 state->default_volume = ((state->default_volume / 2) + 23) << 9;
1268 state->vbi_line_offset = 8; 1418 state->vbi_line_offset = 8;
1269 state->id = id; 1419 state->id = id;
1270 state->rev = device_id; 1420 state->rev = device_id;
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h
index 8bf797f48b09..72916ba975a8 100644
--- a/drivers/media/video/cx25840/cx25840-core.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -44,6 +44,7 @@ struct cx25840_state {
44 u32 audclk_freq; 44 u32 audclk_freq;
45 int audmode; 45 int audmode;
46 int unmute_volume; /* -1 if not muted */ 46 int unmute_volume; /* -1 if not muted */
47 int default_volume;
47 int vbi_line_offset; 48 int vbi_line_offset;
48 u32 id; 49 u32 id;
49 u32 rev; 50 u32 rev;
@@ -61,6 +62,7 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
61u8 cx25840_read(struct i2c_client *client, u16 addr); 62u8 cx25840_read(struct i2c_client *client, u16 addr);
62u32 cx25840_read4(struct i2c_client *client, u16 addr); 63u32 cx25840_read4(struct i2c_client *client, u16 addr);
63int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value); 64int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
65void cx25840_std_setup(struct i2c_client *client);
64 66
65/* ----------------------------------------------------------------------- */ 67/* ----------------------------------------------------------------------- */
66/* cx25850-firmware.c */ 68/* cx25850-firmware.c */
@@ -73,7 +75,6 @@ void cx25840_audio_set_path(struct i2c_client *client);
73 75
74/* ----------------------------------------------------------------------- */ 76/* ----------------------------------------------------------------------- */
75/* cx25850-vbi.c */ 77/* cx25850-vbi.c */
76void cx25840_vbi_setup(struct i2c_client *client);
77int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg); 78int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg);
78 79
79#endif 80#endif
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index c754b9d13369..69f2bbdbb929 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -82,150 +82,6 @@ static int decode_vps(u8 * dst, u8 * p)
82 return err & 0xf0; 82 return err & 0xf0;
83} 83}
84 84
85void cx25840_vbi_setup(struct i2c_client *client)
86{
87 struct cx25840_state *state = i2c_get_clientdata(client);
88 v4l2_std_id std = state->std;
89 int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
90 int luma_lpf,uv_lpf, comb;
91 u32 pll_int,pll_frac,pll_post;
92
93 /* datasheet startup, step 8d */
94 if (std & ~V4L2_STD_NTSC) {
95 cx25840_write(client, 0x49f, 0x11);
96 } else {
97 cx25840_write(client, 0x49f, 0x14);
98 }
99
100 if (std & V4L2_STD_625_50) {
101 hblank=0x084;
102 hactive=0x2d0;
103 burst=0x5d;
104 vblank=0x024;
105 vactive=0x244;
106 vblank656=0x28;
107 src_decimation=0x21f;
108
109 luma_lpf=2;
110 if (std & V4L2_STD_SECAM) {
111 uv_lpf=0;
112 comb=0;
113 sc=0x0a425f;
114 } else if (std == V4L2_STD_PAL_Nc) {
115 uv_lpf=1;
116 comb=0x20;
117 sc=556453;
118 } else {
119 uv_lpf=1;
120 comb=0x20;
121 sc=0x0a8263;
122 }
123 } else {
124 hactive=720;
125 hblank=122;
126 vactive=487;
127 luma_lpf=1;
128 uv_lpf=1;
129
130 src_decimation=0x21f;
131 if (std == V4L2_STD_PAL_60) {
132 vblank=26;
133 vblank656=26;
134 burst=0x5b;
135 luma_lpf=2;
136 comb=0x20;
137 sc=0x0a8263;
138 } else if (std == V4L2_STD_PAL_M) {
139 vblank=20;
140 vblank656=24;
141 burst=0x61;
142 comb=0x20;
143
144 sc=555452;
145 } else {
146 vblank=26;
147 vblank656=26;
148 burst=0x5b;
149 comb=0x66;
150 sc=556063;
151 }
152 }
153
154 /* DEBUG: Displays configured PLL frequency */
155 pll_int=cx25840_read(client, 0x108);
156 pll_frac=cx25840_read4(client, 0x10c)&0x1ffffff;
157 pll_post=cx25840_read(client, 0x109);
158 v4l_dbg(1, cx25840_debug, client,
159 "PLL regs = int: %u, frac: %u, post: %u\n",
160 pll_int,pll_frac,pll_post);
161
162 if (pll_post) {
163 int fin, fsc;
164 int pll= (28636363L*((((u64)pll_int)<<25L)+pll_frac)) >>25L;
165
166 pll/=pll_post;
167 v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n",
168 pll/1000000, pll%1000000);
169 v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n",
170 pll/8000000, (pll/8)%1000000);
171
172 fin=((u64)src_decimation*pll)>>12;
173 v4l_dbg(1, cx25840_debug, client, "ADC Sampling freq = "
174 "%d.%06d MHz\n",
175 fin/1000000,fin%1000000);
176
177 fsc= (((u64)sc)*pll) >> 24L;
178 v4l_dbg(1, cx25840_debug, client, "Chroma sub-carrier freq = "
179 "%d.%06d MHz\n",
180 fsc/1000000,fsc%1000000);
181
182 v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
183 "vblank %i, vactive %i, vblank656 %i, src_dec %i, "
184 "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
185 " sc 0x%06x\n",
186 hblank, hactive, vblank, vactive, vblank656,
187 src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
188 }
189
190 /* Sets horizontal blanking delay and active lines */
191 cx25840_write(client, 0x470, hblank);
192 cx25840_write(client, 0x471, 0xff&(((hblank>>8)&0x3)|(hactive <<4)));
193 cx25840_write(client, 0x472, hactive>>4);
194
195 /* Sets burst gate delay */
196 cx25840_write(client, 0x473, burst);
197
198 /* Sets vertical blanking delay and active duration */
199 cx25840_write(client, 0x474, vblank);
200 cx25840_write(client, 0x475, 0xff&(((vblank>>8)&0x3)|(vactive <<4)));
201 cx25840_write(client, 0x476, vactive>>4);
202 cx25840_write(client, 0x477, vblank656);
203
204 /* Sets src decimation rate */
205 cx25840_write(client, 0x478, 0xff&src_decimation);
206 cx25840_write(client, 0x479, 0xff&(src_decimation>>8));
207
208 /* Sets Luma and UV Low pass filters */
209 cx25840_write(client, 0x47a, luma_lpf<<6|((uv_lpf<<4)&0x30));
210
211 /* Enables comb filters */
212 cx25840_write(client, 0x47b, comb);
213
214 /* Sets SC Step*/
215 cx25840_write(client, 0x47c, sc);
216 cx25840_write(client, 0x47d, 0xff&sc>>8);
217 cx25840_write(client, 0x47e, 0xff&sc>>16);
218
219 /* Sets VBI parameters */
220 if (std & V4L2_STD_625_50) {
221 cx25840_write(client, 0x47f, 0x01);
222 state->vbi_line_offset = 5;
223 } else {
224 cx25840_write(client, 0x47f, 0x00);
225 state->vbi_line_offset = 8;
226 }
227}
228
229int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) 85int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
230{ 86{
231 struct cx25840_state *state = i2c_get_clientdata(client); 87 struct cx25840_state *state = i2c_get_clientdata(client);
@@ -292,8 +148,8 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
292 /* raw VBI */ 148 /* raw VBI */
293 memset(svbi, 0, sizeof(*svbi)); 149 memset(svbi, 0, sizeof(*svbi));
294 150
295 /* Setup VBI */ 151 /* Setup standard */
296 cx25840_vbi_setup(client); 152 cx25840_std_setup(client);
297 153
298 /* VBI Offset */ 154 /* VBI Offset */
299 cx25840_write(client, 0x47f, vbi_offset); 155 cx25840_write(client, 0x47f, vbi_offset);
@@ -304,8 +160,8 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
304 for (x = 0; x <= 23; x++) 160 for (x = 0; x <= 23; x++)
305 lcr[x] = 0x00; 161 lcr[x] = 0x00;
306 162
307 /* Setup VBI */ 163 /* Setup standard */
308 cx25840_vbi_setup(client); 164 cx25840_std_setup(client);
309 165
310 /* Sliced VBI */ 166 /* Sliced VBI */
311 cx25840_write(client, 0x404, 0x32); /* Ancillary data */ 167 cx25840_write(client, 0x404, 0x32); /* Ancillary data */
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 80c8883e54b5..06f171ab6149 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -82,7 +82,6 @@ typedef struct cx88_audio_dev snd_cx88_card_t;
82 82
83 83
84 84
85
86/**************************************************************************** 85/****************************************************************************
87 Module global static vars 86 Module global static vars
88 ****************************************************************************/ 87 ****************************************************************************/
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 6c0c94c5ef91..bfdca5847764 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -715,7 +715,8 @@ static int vidioc_querymenu (struct file *file, void *priv,
715 715
716 qctrl.id = qmenu->id; 716 qctrl.id = qmenu->id;
717 blackbird_queryctrl(dev, &qctrl); 717 blackbird_queryctrl(dev, &qctrl);
718 return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id)); 718 return v4l2_ctrl_query_menu(qmenu, &qctrl,
719 cx2341x_ctrl_get_menu(&dev->params, qmenu->id));
719} 720}
720 721
721static int vidioc_querycap (struct file *file, void *priv, 722static int vidioc_querycap (struct file *file, void *priv,
@@ -737,7 +738,7 @@ static int vidioc_querycap (struct file *file, void *priv,
737 return 0; 738 return 0;
738} 739}
739 740
740static int vidioc_enum_fmt_cap (struct file *file, void *priv, 741static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
741 struct v4l2_fmtdesc *f) 742 struct v4l2_fmtdesc *f)
742{ 743{
743 if (f->index != 0) 744 if (f->index != 0)
@@ -749,7 +750,7 @@ static int vidioc_enum_fmt_cap (struct file *file, void *priv,
749 return 0; 750 return 0;
750} 751}
751 752
752static int vidioc_g_fmt_cap (struct file *file, void *priv, 753static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
753 struct v4l2_format *f) 754 struct v4l2_format *f)
754{ 755{
755 struct cx8802_fh *fh = priv; 756 struct cx8802_fh *fh = priv;
@@ -768,7 +769,7 @@ static int vidioc_g_fmt_cap (struct file *file, void *priv,
768 return 0; 769 return 0;
769} 770}
770 771
771static int vidioc_try_fmt_cap (struct file *file, void *priv, 772static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
772 struct v4l2_format *f) 773 struct v4l2_format *f)
773{ 774{
774 struct cx8802_fh *fh = priv; 775 struct cx8802_fh *fh = priv;
@@ -784,7 +785,7 @@ static int vidioc_try_fmt_cap (struct file *file, void *priv,
784 return 0; 785 return 0;
785} 786}
786 787
787static int vidioc_s_fmt_cap (struct file *file, void *priv, 788static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
788 struct v4l2_format *f) 789 struct v4l2_format *f)
789{ 790{
790 struct cx8802_fh *fh = priv; 791 struct cx8802_fh *fh = priv;
@@ -1181,10 +1182,10 @@ static struct video_device cx8802_mpeg_template =
1181 .minor = -1, 1182 .minor = -1,
1182 .vidioc_querymenu = vidioc_querymenu, 1183 .vidioc_querymenu = vidioc_querymenu,
1183 .vidioc_querycap = vidioc_querycap, 1184 .vidioc_querycap = vidioc_querycap,
1184 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, 1185 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1185 .vidioc_g_fmt_cap = vidioc_g_fmt_cap, 1186 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1186 .vidioc_try_fmt_cap = vidioc_try_fmt_cap, 1187 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1187 .vidioc_s_fmt_cap = vidioc_s_fmt_cap, 1188 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1188 .vidioc_reqbufs = vidioc_reqbufs, 1189 .vidioc_reqbufs = vidioc_reqbufs,
1189 .vidioc_querybuf = vidioc_querybuf, 1190 .vidioc_querybuf = vidioc_querybuf,
1190 .vidioc_qbuf = vidioc_qbuf, 1191 .vidioc_qbuf = vidioc_qbuf,
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index cb6a096069c7..d7406a994f09 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -103,7 +103,6 @@ static int attach_inform(struct i2c_client *client)
103 103
104 dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", 104 dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
105 client->driver->driver.name, client->addr, client->name); 105 client->driver->driver.name, client->addr, client->name);
106
107 return 0; 106 return 0;
108} 107}
109 108
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index eea23f95edb7..0fed5cd2ccea 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1045,7 +1045,7 @@ static void init_controls(struct cx88_core *core)
1045/* ------------------------------------------------------------------ */ 1045/* ------------------------------------------------------------------ */
1046/* VIDEO IOCTLS */ 1046/* VIDEO IOCTLS */
1047 1047
1048static int vidioc_g_fmt_cap (struct file *file, void *priv, 1048static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
1049 struct v4l2_format *f) 1049 struct v4l2_format *f)
1050{ 1050{
1051 struct cx8800_fh *fh = priv; 1051 struct cx8800_fh *fh = priv;
@@ -1061,7 +1061,7 @@ static int vidioc_g_fmt_cap (struct file *file, void *priv,
1061 return 0; 1061 return 0;
1062} 1062}
1063 1063
1064static int vidioc_try_fmt_cap (struct file *file, void *priv, 1064static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
1065 struct v4l2_format *f) 1065 struct v4l2_format *f)
1066{ 1066{
1067 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; 1067 struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
@@ -1112,11 +1112,11 @@ static int vidioc_try_fmt_cap (struct file *file, void *priv,
1112 return 0; 1112 return 0;
1113} 1113}
1114 1114
1115static int vidioc_s_fmt_cap (struct file *file, void *priv, 1115static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1116 struct v4l2_format *f) 1116 struct v4l2_format *f)
1117{ 1117{
1118 struct cx8800_fh *fh = priv; 1118 struct cx8800_fh *fh = priv;
1119 int err = vidioc_try_fmt_cap (file,priv,f); 1119 int err = vidioc_try_fmt_vid_cap (file,priv,f);
1120 1120
1121 if (0 != err) 1121 if (0 != err)
1122 return err; 1122 return err;
@@ -1147,7 +1147,7 @@ static int vidioc_querycap (struct file *file, void *priv,
1147 return 0; 1147 return 0;
1148} 1148}
1149 1149
1150static int vidioc_enum_fmt_cap (struct file *file, void *priv, 1150static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
1151 struct v4l2_fmtdesc *f) 1151 struct v4l2_fmtdesc *f)
1152{ 1152{
1153 if (unlikely(f->index >= ARRAY_SIZE(formats))) 1153 if (unlikely(f->index >= ARRAY_SIZE(formats)))
@@ -1690,13 +1690,13 @@ static struct video_device cx8800_video_template =
1690 .fops = &video_fops, 1690 .fops = &video_fops,
1691 .minor = -1, 1691 .minor = -1,
1692 .vidioc_querycap = vidioc_querycap, 1692 .vidioc_querycap = vidioc_querycap,
1693 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, 1693 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1694 .vidioc_g_fmt_cap = vidioc_g_fmt_cap, 1694 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1695 .vidioc_try_fmt_cap = vidioc_try_fmt_cap, 1695 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1696 .vidioc_s_fmt_cap = vidioc_s_fmt_cap, 1696 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1697 .vidioc_g_fmt_vbi = cx8800_vbi_fmt, 1697 .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt,
1698 .vidioc_try_fmt_vbi = cx8800_vbi_fmt, 1698 .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt,
1699 .vidioc_s_fmt_vbi = cx8800_vbi_fmt, 1699 .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt,
1700 .vidioc_reqbufs = vidioc_reqbufs, 1700 .vidioc_reqbufs = vidioc_reqbufs,
1701 .vidioc_querybuf = vidioc_querybuf, 1701 .vidioc_querybuf = vidioc_querybuf,
1702 .vidioc_qbuf = vidioc_qbuf, 1702 .vidioc_qbuf = vidioc_qbuf,
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
index 6ce5af488471..20800425c51e 100644
--- a/drivers/media/video/cx88/cx88-vp3054-i2c.c
+++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c
@@ -30,7 +30,6 @@
30#include "cx88.h" 30#include "cx88.h"
31#include "cx88-vp3054-i2c.h" 31#include "cx88-vp3054-i2c.h"
32 32
33
34MODULE_DESCRIPTION("driver for cx2388x VP3054 design"); 33MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
35MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); 34MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
36MODULE_LICENSE("GPL"); 35MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 8cbda43727c3..05f0d5a15058 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -173,6 +173,27 @@ struct em28xx_board em28xx_boards[] = {
173 .amux = 1, 173 .amux = 1,
174 } }, 174 } },
175 }, 175 },
176 [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2] = {
177 .name = "Hauppauge WinTV HVR 900 (R2)",
178 .vchannels = 3,
179 .tda9887_conf = TDA9887_PRESENT,
180 .tuner_type = TUNER_XC2028,
181 .mts_firmware = 1,
182 .decoder = EM28XX_TVP5150,
183 .input = { {
184 .type = EM28XX_VMUX_TELEVISION,
185 .vmux = TVP5150_COMPOSITE0,
186 .amux = 0,
187 }, {
188 .type = EM28XX_VMUX_COMPOSITE1,
189 .vmux = TVP5150_COMPOSITE1,
190 .amux = 1,
191 }, {
192 .type = EM28XX_VMUX_SVIDEO,
193 .vmux = TVP5150_SVIDEO,
194 .amux = 1,
195 } },
196 },
176 [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950] = { 197 [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950] = {
177 .name = "Hauppauge WinTV HVR 950", 198 .name = "Hauppauge WinTV HVR 950",
178 .vchannels = 3, 199 .vchannels = 3,
@@ -196,6 +217,29 @@ struct em28xx_board em28xx_boards[] = {
196 .amux = 1, 217 .amux = 1,
197 } }, 218 } },
198 }, 219 },
220 [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = {
221 .name = "Pinnacle PCTV HD Pro Stick",
222 .vchannels = 3,
223 .tda9887_conf = TDA9887_PRESENT,
224 .tuner_type = TUNER_XC2028,
225 .mts_firmware = 1,
226 .has_12mhz_i2s = 1,
227 .has_dvb = 1,
228 .decoder = EM28XX_TVP5150,
229 .input = { {
230 .type = EM28XX_VMUX_TELEVISION,
231 .vmux = TVP5150_COMPOSITE0,
232 .amux = 0,
233 }, {
234 .type = EM28XX_VMUX_COMPOSITE1,
235 .vmux = TVP5150_COMPOSITE1,
236 .amux = 1,
237 }, {
238 .type = EM28XX_VMUX_SVIDEO,
239 .vmux = TVP5150_SVIDEO,
240 .amux = 1,
241 } },
242 },
199 [EM2880_BOARD_TERRATEC_HYBRID_XS] = { 243 [EM2880_BOARD_TERRATEC_HYBRID_XS] = {
200 .name = "Terratec Hybrid XS", 244 .name = "Terratec Hybrid XS",
201 .vchannels = 3, 245 .vchannels = 3,
@@ -382,6 +426,19 @@ struct em28xx_board em28xx_boards[] = {
382 .amux = EM28XX_AMUX_LINE_IN, 426 .amux = EM28XX_AMUX_LINE_IN,
383 } }, 427 } },
384 }, 428 },
429 [EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA] = {
430 .name = "PointNix Intra-Oral Camera",
431 .has_snapshot_button = 1,
432 .vchannels = 1,
433 .tda9887_conf = TDA9887_PRESENT,
434 .tuner_type = TUNER_ABSENT,
435 .decoder = EM28XX_SAA7113,
436 .input = { {
437 .type = EM28XX_VMUX_SVIDEO,
438 .vmux = SAA7115_SVIDEO3,
439 .amux = 0,
440 } },
441 },
385}; 442};
386const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); 443const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
387 444
@@ -417,10 +474,12 @@ struct usb_device_id em28xx_id_table [] = {
417 .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, 474 .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
418 { USB_DEVICE(0x2304, 0x021a), 475 { USB_DEVICE(0x2304, 0x021a),
419 .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, 476 .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
477 { USB_DEVICE(0x2304, 0x0227),
478 .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO },
420 { USB_DEVICE(0x2040, 0x6500), 479 { USB_DEVICE(0x2040, 0x6500),
421 .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, 480 .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
422 { USB_DEVICE(0x2040, 0x6502), 481 { USB_DEVICE(0x2040, 0x6502),
423 .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, 482 .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 },
424 { USB_DEVICE(0x2040, 0x6513), /* HCW HVR-980 */ 483 { USB_DEVICE(0x2040, 0x6513), /* HCW HVR-980 */
425 .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, 484 .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
426 { USB_DEVICE(0x2040, 0x6517), /* HP HVR-950 */ 485 { USB_DEVICE(0x2040, 0x6517), /* HP HVR-950 */
@@ -476,6 +535,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash [] = {
476static struct em28xx_hash_table em28xx_i2c_hash[] = { 535static struct em28xx_hash_table em28xx_i2c_hash[] = {
477 {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC}, 536 {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC},
478 {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, 537 {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
538 {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT},
479}; 539};
480 540
481int em28xx_tuner_callback(void *ptr, int command, int arg) 541int em28xx_tuner_callback(void *ptr, int command, int arg)
@@ -508,6 +568,7 @@ static void em28xx_set_model(struct em28xx *dev)
508 dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; 568 dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
509 dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; 569 dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
510 dev->has_dvb = em28xx_boards[dev->model].has_dvb; 570 dev->has_dvb = em28xx_boards[dev->model].has_dvb;
571 dev->has_snapshot_button = em28xx_boards[dev->model].has_snapshot_button;
511} 572}
512 573
513/* Since em28xx_pre_card_setup() requires a proper dev->model, 574/* Since em28xx_pre_card_setup() requires a proper dev->model,
@@ -542,8 +603,10 @@ void em28xx_pre_card_setup(struct em28xx *dev)
542 switch (dev->model) { 603 switch (dev->model) {
543 case EM2880_BOARD_TERRATEC_PRODIGY_XS: 604 case EM2880_BOARD_TERRATEC_PRODIGY_XS:
544 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: 605 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
606 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
545 case EM2880_BOARD_TERRATEC_HYBRID_XS: 607 case EM2880_BOARD_TERRATEC_HYBRID_XS:
546 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: 608 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
609 case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
547 em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); 610 em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1);
548 em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); 611 em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
549 msleep(50); 612 msleep(50);
@@ -576,7 +639,12 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
576 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: 639 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
577 ctl->demod = XC3028_FE_ZARLINK456; 640 ctl->demod = XC3028_FE_ZARLINK456;
578 break; 641 break;
642 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
643 /* djh - Not sure which demod we need here */
644 ctl->demod = XC3028_FE_DEFAULT;
645 break;
579 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: 646 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
647 case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
580 /* FIXME: Better to specify the needed IF */ 648 /* FIXME: Better to specify the needed IF */
581 ctl->demod = XC3028_FE_DEFAULT; 649 ctl->demod = XC3028_FE_DEFAULT;
582 break; 650 break;
@@ -754,6 +822,7 @@ void em28xx_card_setup(struct em28xx *dev)
754 switch (dev->model) { 822 switch (dev->model) {
755 case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2: 823 case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
756 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: 824 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
825 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
757 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: 826 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
758 { 827 {
759 struct tveeprom tv; 828 struct tveeprom tv;
@@ -787,6 +856,9 @@ void em28xx_card_setup(struct em28xx *dev)
787 em28xx_set_model(dev); 856 em28xx_set_model(dev);
788 } 857 }
789 858
859 if (dev->has_snapshot_button)
860 em28xx_register_snapshot_button(dev);
861
790 /* Allow override tuner type by a module parameter */ 862 /* Allow override tuner type by a module parameter */
791 if (tuner >= 0) 863 if (tuner >= 0)
792 dev->tuner_type = tuner; 864 dev->tuner_type = tuner;
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index 0b2333ee07f8..cc61cfb23a4a 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -5,6 +5,7 @@
5 5
6 (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com> 6 (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
7 - Fixes for the driver to properly work with HVR-950 7 - Fixes for the driver to properly work with HVR-950
8 - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick
8 9
9 (c) 2008 Aidan Thornton <makosoft@googlemail.com> 10 (c) 2008 Aidan Thornton <makosoft@googlemail.com>
10 11
@@ -26,6 +27,9 @@
26 27
27#include "lgdt330x.h" 28#include "lgdt330x.h"
28#include "zl10353.h" 29#include "zl10353.h"
30#ifdef EM28XX_DRX397XD_SUPPORT
31#include "drx397xD.h"
32#endif
29 33
30MODULE_DESCRIPTION("driver for em28xx based DVB cards"); 34MODULE_DESCRIPTION("driver for em28xx based DVB cards");
31MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 35MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -227,6 +231,13 @@ static struct zl10353_config em28xx_zl10353_with_xc3028 = {
227 .if2 = 45600, 231 .if2 = 45600,
228}; 232};
229 233
234#ifdef EM28XX_DRX397XD_SUPPORT
235/* [TODO] djh - not sure yet what the device config needs to contain */
236static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
237 .demod_address = (0xe0 >> 1),
238};
239#endif
240
230/* ------------------------------------------------------------------ */ 241/* ------------------------------------------------------------------ */
231 242
232static int attach_xc3028(u8 addr, struct em28xx *dev) 243static int attach_xc3028(u8 addr, struct em28xx *dev)
@@ -399,6 +410,7 @@ static int dvb_init(struct em28xx *dev)
399 /* init frontend */ 410 /* init frontend */
400 switch (dev->model) { 411 switch (dev->model) {
401 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: 412 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
413 case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
402 dvb->frontend = dvb_attach(lgdt330x_attach, 414 dvb->frontend = dvb_attach(lgdt330x_attach,
403 &em2880_lgdt3303_dev, 415 &em2880_lgdt3303_dev,
404 &dev->i2c_adap); 416 &dev->i2c_adap);
@@ -416,6 +428,19 @@ static int dvb_init(struct em28xx *dev)
416 goto out_free; 428 goto out_free;
417 } 429 }
418 break; 430 break;
431 case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
432#ifdef EM28XX_DRX397XD_SUPPORT
433 /* We don't have the config structure properly populated, so
434 this is commented out for now */
435 dvb->frontend = dvb_attach(drx397xD_attach,
436 &em28xx_drx397xD_with_xc3028,
437 &dev->i2c_adap);
438 if (attach_xc3028(0x61, dev) < 0) {
439 result = -EINVAL;
440 goto out_free;
441 }
442 break;
443#endif
419 default: 444 default:
420 printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card" 445 printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
421 " isn't supported yet\n", 446 " isn't supported yet\n",
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 6a78fd294cab..97853384c943 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -432,7 +432,6 @@ static u32 functionality(struct i2c_adapter *adap)
432 return I2C_FUNC_SMBUS_EMUL; 432 return I2C_FUNC_SMBUS_EMUL;
433} 433}
434 434
435
436/* 435/*
437 * attach_inform() 436 * attach_inform()
438 * gets called when a device attaches to the i2c bus 437 * gets called when a device attaches to the i2c bus
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index bb5807159b8d..eab3d9511af3 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -30,6 +30,10 @@
30 30
31#include "em28xx.h" 31#include "em28xx.h"
32 32
33#define EM28XX_SNAPSHOT_KEY KEY_CAMERA
34#define EM28XX_SBUTTON_QUERY_INTERVAL 500
35#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20
36
33static unsigned int ir_debug; 37static unsigned int ir_debug;
34module_param(ir_debug, int, 0644); 38module_param(ir_debug, int, 0644);
35MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); 39MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
@@ -124,6 +128,89 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
124 return 1; 128 return 1;
125} 129}
126 130
131static void em28xx_query_sbutton(struct work_struct *work)
132{
133 /* Poll the register and see if the button is depressed */
134 struct em28xx *dev =
135 container_of(work, struct em28xx, sbutton_query_work.work);
136 int ret;
137
138 ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP);
139
140 if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) {
141 u8 cleared;
142 /* Button is depressed, clear the register */
143 cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT;
144 em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1);
145
146 /* Not emulate the keypress */
147 input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
148 1);
149 /* Now unpress the key */
150 input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
151 0);
152 }
153
154 /* Schedule next poll */
155 schedule_delayed_work(&dev->sbutton_query_work,
156 msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
157}
158
159void em28xx_register_snapshot_button(struct em28xx *dev)
160{
161 struct input_dev *input_dev;
162 int err;
163
164 em28xx_info("Registering snapshot button...\n");
165 input_dev = input_allocate_device();
166 if (!input_dev) {
167 em28xx_errdev("input_allocate_device failed\n");
168 return;
169 }
170
171 usb_make_path(dev->udev, dev->snapshot_button_path,
172 sizeof(dev->snapshot_button_path));
173 strlcat(dev->snapshot_button_path, "/sbutton",
174 sizeof(dev->snapshot_button_path));
175 INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton);
176
177 input_dev->name = "em28xx snapshot button";
178 input_dev->phys = dev->snapshot_button_path;
179 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
180 set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit);
181 input_dev->keycodesize = 0;
182 input_dev->keycodemax = 0;
183 input_dev->id.bustype = BUS_USB;
184 input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
185 input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
186 input_dev->id.version = 1;
187 input_dev->dev.parent = &dev->udev->dev;
188
189 err = input_register_device(input_dev);
190 if (err) {
191 em28xx_errdev("input_register_device failed\n");
192 input_free_device(input_dev);
193 return;
194 }
195
196 dev->sbutton_input_dev = input_dev;
197 schedule_delayed_work(&dev->sbutton_query_work,
198 msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
199 return;
200
201}
202
203void em28xx_deregister_snapshot_button(struct em28xx *dev)
204{
205 if (dev->sbutton_input_dev != NULL) {
206 em28xx_info("Deregistering snapshot button\n");
207 cancel_rearming_delayed_work(&dev->sbutton_query_work);
208 input_unregister_device(dev->sbutton_input_dev);
209 dev->sbutton_input_dev = NULL;
210 }
211 return;
212}
213
127/* ---------------------------------------------------------------------- 214/* ----------------------------------------------------------------------
128 * Local variables: 215 * Local variables:
129 * c-basic-offset: 8 216 * c-basic-offset: 8
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 285bc62bbe46..2d9f14d2a00b 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -683,7 +683,7 @@ static void get_scale(struct em28xx *dev,
683 IOCTL vidioc handling 683 IOCTL vidioc handling
684 ------------------------------------------------------------------*/ 684 ------------------------------------------------------------------*/
685 685
686static int vidioc_g_fmt_cap(struct file *file, void *priv, 686static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
687 struct v4l2_format *f) 687 struct v4l2_format *f)
688{ 688{
689 struct em28xx_fh *fh = priv; 689 struct em28xx_fh *fh = priv;
@@ -706,7 +706,7 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
706 return 0; 706 return 0;
707} 707}
708 708
709static int vidioc_try_fmt_cap(struct file *file, void *priv, 709static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
710 struct v4l2_format *f) 710 struct v4l2_format *f)
711{ 711{
712 struct em28xx_fh *fh = priv; 712 struct em28xx_fh *fh = priv;
@@ -766,7 +766,7 @@ static int vidioc_try_fmt_cap(struct file *file, void *priv,
766 return 0; 766 return 0;
767} 767}
768 768
769static int vidioc_s_fmt_cap(struct file *file, void *priv, 769static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
770 struct v4l2_format *f) 770 struct v4l2_format *f)
771{ 771{
772 struct em28xx_fh *fh = priv; 772 struct em28xx_fh *fh = priv;
@@ -777,7 +777,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
777 if (rc < 0) 777 if (rc < 0)
778 return rc; 778 return rc;
779 779
780 vidioc_try_fmt_cap(file, priv, f); 780 vidioc_try_fmt_vid_cap(file, priv, f);
781 781
782 mutex_lock(&dev->lock); 782 mutex_lock(&dev->lock);
783 783
@@ -826,7 +826,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
826 /* Adjusts width/height, if needed */ 826 /* Adjusts width/height, if needed */
827 f.fmt.pix.width = dev->width; 827 f.fmt.pix.width = dev->width;
828 f.fmt.pix.height = dev->height; 828 f.fmt.pix.height = dev->height;
829 vidioc_try_fmt_cap(file, priv, &f); 829 vidioc_try_fmt_vid_cap(file, priv, &f);
830 830
831 mutex_lock(&dev->lock); 831 mutex_lock(&dev->lock);
832 832
@@ -1277,7 +1277,7 @@ static int vidioc_querycap(struct file *file, void *priv,
1277 return 0; 1277 return 0;
1278} 1278}
1279 1279
1280static int vidioc_enum_fmt_cap(struct file *file, void *priv, 1280static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
1281 struct v4l2_fmtdesc *fmtd) 1281 struct v4l2_fmtdesc *fmtd)
1282{ 1282{
1283 if (fmtd->index != 0) 1283 if (fmtd->index != 0)
@@ -1292,7 +1292,7 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv,
1292} 1292}
1293 1293
1294/* Sliced VBI ioctls */ 1294/* Sliced VBI ioctls */
1295static int vidioc_g_fmt_vbi_capture(struct file *file, void *priv, 1295static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
1296 struct v4l2_format *f) 1296 struct v4l2_format *f)
1297{ 1297{
1298 struct em28xx_fh *fh = priv; 1298 struct em28xx_fh *fh = priv;
@@ -1316,7 +1316,7 @@ static int vidioc_g_fmt_vbi_capture(struct file *file, void *priv,
1316 return rc; 1316 return rc;
1317} 1317}
1318 1318
1319static int vidioc_try_set_vbi_capture(struct file *file, void *priv, 1319static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
1320 struct v4l2_format *f) 1320 struct v4l2_format *f)
1321{ 1321{
1322 struct em28xx_fh *fh = priv; 1322 struct em28xx_fh *fh = priv;
@@ -1590,6 +1590,8 @@ static void em28xx_release_resources(struct em28xx *dev)
1590 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, 1590 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
1591 dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); 1591 dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
1592 list_del(&dev->devlist); 1592 list_del(&dev->devlist);
1593 if (dev->sbutton_input_dev)
1594 em28xx_deregister_snapshot_button(dev);
1593 if (dev->radio_dev) { 1595 if (dev->radio_dev) {
1594 if (-1 != dev->radio_dev->minor) 1596 if (-1 != dev->radio_dev->minor)
1595 video_unregister_device(dev->radio_dev); 1597 video_unregister_device(dev->radio_dev);
@@ -1776,17 +1778,17 @@ static const struct video_device em28xx_video_template = {
1776 1778
1777 .minor = -1, 1779 .minor = -1,
1778 .vidioc_querycap = vidioc_querycap, 1780 .vidioc_querycap = vidioc_querycap,
1779 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, 1781 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1780 .vidioc_g_fmt_cap = vidioc_g_fmt_cap, 1782 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1781 .vidioc_try_fmt_cap = vidioc_try_fmt_cap, 1783 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1782 .vidioc_s_fmt_cap = vidioc_s_fmt_cap, 1784 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1783 .vidioc_g_audio = vidioc_g_audio, 1785 .vidioc_g_audio = vidioc_g_audio,
1784 .vidioc_s_audio = vidioc_s_audio, 1786 .vidioc_s_audio = vidioc_s_audio,
1785 .vidioc_cropcap = vidioc_cropcap, 1787 .vidioc_cropcap = vidioc_cropcap,
1786 1788
1787 .vidioc_g_fmt_vbi_capture = vidioc_g_fmt_vbi_capture, 1789 .vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap,
1788 .vidioc_try_fmt_vbi_capture = vidioc_try_set_vbi_capture, 1790 .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
1789 .vidioc_s_fmt_vbi_capture = vidioc_try_set_vbi_capture, 1791 .vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
1790 1792
1791 .vidioc_reqbufs = vidioc_reqbufs, 1793 .vidioc_reqbufs = vidioc_reqbufs,
1792 .vidioc_querybuf = vidioc_querybuf, 1794 .vidioc_querybuf = vidioc_querybuf,
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 002f170b211a..89842c5d64a1 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -55,6 +55,9 @@
55#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14 55#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14
56#define EM2800_BOARD_VGEAR_POCKETTV 15 56#define EM2800_BOARD_VGEAR_POCKETTV 15
57#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16 57#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16
58#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO 17
59#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 18
60#define EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA 19
58 61
59/* Limits minimum and default number of buffers */ 62/* Limits minimum and default number of buffers */
60#define EM28XX_MIN_BUF 4 63#define EM28XX_MIN_BUF 4
@@ -247,6 +250,7 @@ struct em28xx_board {
247 unsigned int has_12mhz_i2s:1; 250 unsigned int has_12mhz_i2s:1;
248 unsigned int max_range_640_480:1; 251 unsigned int max_range_640_480:1;
249 unsigned int has_dvb:1; 252 unsigned int has_dvb:1;
253 unsigned int has_snapshot_button:1;
250 254
251 enum em28xx_decoder decoder; 255 enum em28xx_decoder decoder;
252 256
@@ -326,6 +330,7 @@ struct em28xx {
326 unsigned int has_12mhz_i2s:1; 330 unsigned int has_12mhz_i2s:1;
327 unsigned int max_range_640_480:1; 331 unsigned int max_range_640_480:1;
328 unsigned int has_dvb:1; 332 unsigned int has_dvb:1;
333 unsigned int has_snapshot_button:1;
329 334
330 /* Some older em28xx chips needs a waiting time after writing */ 335 /* Some older em28xx chips needs a waiting time after writing */
331 unsigned int wait_after_write; 336 unsigned int wait_after_write;
@@ -416,6 +421,11 @@ struct em28xx {
416 /* Caches GPO and GPIO registers */ 421 /* Caches GPO and GPIO registers */
417 unsigned char reg_gpo, reg_gpio; 422 unsigned char reg_gpo, reg_gpio;
418 423
424 /* Snapshot button */
425 char snapshot_button_path[30]; /* path of the input dev */
426 struct input_dev *sbutton_input_dev;
427 struct delayed_work sbutton_query_work;
428
419 struct em28xx_dvb *dvb; 429 struct em28xx_dvb *dvb;
420}; 430};
421 431
@@ -481,6 +491,8 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
481int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); 491int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
482int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, 492int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
483 u32 *ir_raw); 493 u32 *ir_raw);
494void em28xx_register_snapshot_button(struct em28xx *dev);
495void em28xx_deregister_snapshot_button(struct em28xx *dev);
484 496
485/* printk macros */ 497/* printk macros */
486 498
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
new file mode 100644
index 000000000000..42b90742b40b
--- /dev/null
+++ b/drivers/media/video/gspca/Kconfig
@@ -0,0 +1,13 @@
1config USB_GSPCA
2 tristate "USB GSPCA driver"
3 depends on VIDEO_V4L2
4 ---help---
5 Say Y here if you want support for various USB webcams.
6
7 See <file:Documentation/video4linux/gspca.txt> for more info.
8
9 This driver uses the Video For Linux API. You must say Y or M to
10 "Video For Linux" to use this driver.
11
12 To compile this driver as modules, choose M here: the
13 modules will be called gspca_xxxx.
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
new file mode 100644
index 000000000000..e68a8965297a
--- /dev/null
+++ b/drivers/media/video/gspca/Makefile
@@ -0,0 +1,29 @@
1obj-$(CONFIG_USB_GSPCA) += gspca_main.o \
2 gspca_conex.o gspca_etoms.o gspca_mars.o \
3 gspca_ov519.o gspca_pac207.o gspca_pac7311.o \
4 gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \
5 gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \
6 gspca_sunplus.o gspca_stk014.o gspca_t613.o gspca_tv8532.o \
7 gspca_vc032x.o gspca_zc3xx.o
8
9gspca_main-objs := gspca.o
10gspca_conex-objs := conex.o
11gspca_etoms-objs := etoms.o
12gspca_mars-objs := mars.o
13gspca_ov519-objs := ov519.o
14gspca_pac207-objs := pac207.o
15gspca_pac7311-objs := pac7311.o
16gspca_sonixb-objs := sonixb.o
17gspca_sonixj-objs := sonixj.o
18gspca_spca500-objs := spca500.o
19gspca_spca501-objs := spca501.o
20gspca_spca505-objs := spca505.o
21gspca_spca506-objs := spca506.o
22gspca_spca508-objs := spca508.o
23gspca_spca561-objs := spca561.o
24gspca_stk014-objs := stk014.o
25gspca_sunplus-objs := sunplus.o
26gspca_t613-objs := t613.o
27gspca_tv8532-objs := tv8532.o
28gspca_vc032x-objs := vc032x.o
29gspca_zc3xx-objs := zc3xx.o
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
new file mode 100644
index 000000000000..013d593b0c67
--- /dev/null
+++ b/drivers/media/video/gspca/conex.c
@@ -0,0 +1,1051 @@
1/*
2 * Connexant Cx11646 library
3 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "conex"
23
24#include "gspca.h"
25#define CONEX_CAM 1 /* special JPEG header */
26#include "jpeg.h"
27
28#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
29static const char version[] = "2.1.7";
30
31MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
32MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
33MODULE_LICENSE("GPL");
34
35/* specific webcam descriptor */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
39 unsigned char brightness;
40 unsigned char contrast;
41 unsigned char colors;
42
43 unsigned char qindex;
44};
45
46/* V4L2 controls supported by the driver */
47static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
48static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
49static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
50static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
51static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
52static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
53
54static struct ctrl sd_ctrls[] = {
55 {
56 {
57 .id = V4L2_CID_BRIGHTNESS,
58 .type = V4L2_CTRL_TYPE_INTEGER,
59 .name = "Brightness",
60 .minimum = 0,
61 .maximum = 255,
62 .step = 1,
63#define BRIGHTNESS_DEF 0xd4
64 .default_value = BRIGHTNESS_DEF,
65 },
66 .set = sd_setbrightness,
67 .get = sd_getbrightness,
68 },
69 {
70 {
71 .id = V4L2_CID_CONTRAST,
72 .type = V4L2_CTRL_TYPE_INTEGER,
73 .name = "Contrast",
74 .minimum = 0x0a,
75 .maximum = 0x1f,
76 .step = 1,
77#define CONTRAST_DEF 0x0c
78 .default_value = CONTRAST_DEF,
79 },
80 .set = sd_setcontrast,
81 .get = sd_getcontrast,
82 },
83 {
84 {
85 .id = V4L2_CID_SATURATION,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "Color",
88 .minimum = 0,
89 .maximum = 7,
90 .step = 1,
91#define COLOR_DEF 3
92 .default_value = COLOR_DEF,
93 },
94 .set = sd_setcolors,
95 .get = sd_getcolors,
96 },
97};
98
99static struct v4l2_pix_format vga_mode[] = {
100 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
101 .bytesperline = 176,
102 .sizeimage = 176 * 144 * 3 / 8 + 590,
103 .colorspace = V4L2_COLORSPACE_JPEG,
104 .priv = 3},
105 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
106 .bytesperline = 320,
107 .sizeimage = 320 * 240 * 3 / 8 + 590,
108 .colorspace = V4L2_COLORSPACE_JPEG,
109 .priv = 2},
110 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
111 .bytesperline = 352,
112 .sizeimage = 352 * 288 * 3 / 8 + 590,
113 .colorspace = V4L2_COLORSPACE_JPEG,
114 .priv = 1},
115 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
116 .bytesperline = 640,
117 .sizeimage = 640 * 480 * 3 / 8 + 590,
118 .colorspace = V4L2_COLORSPACE_JPEG,
119 .priv = 0},
120};
121
122/* the read bytes are found in gspca_dev->usb_buf */
123static void reg_r(struct gspca_dev *gspca_dev,
124 __u16 index,
125 __u16 len)
126{
127 struct usb_device *dev = gspca_dev->dev;
128
129#ifdef CONFIG_VIDEO_ADV_DEBUG
130 if (len > sizeof gspca_dev->usb_buf) {
131 err("reg_r: buffer overflow");
132 return;
133 }
134#endif
135 usb_control_msg(dev,
136 usb_rcvctrlpipe(dev, 0),
137 0,
138 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
139 0,
140 index, gspca_dev->usb_buf, len,
141 500);
142 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
143 index, gspca_dev->usb_buf[0]);
144}
145
146/* the bytes to write are in gspca_dev->usb_buf */
147static void reg_w_val(struct gspca_dev *gspca_dev,
148 __u16 index,
149 __u8 val)
150{
151 struct usb_device *dev = gspca_dev->dev;
152
153 gspca_dev->usb_buf[0] = val;
154 usb_control_msg(dev,
155 usb_sndctrlpipe(dev, 0),
156 0,
157 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
158 0,
159 index, gspca_dev->usb_buf, 1, 500);
160}
161
162static void reg_w(struct gspca_dev *gspca_dev,
163 __u16 index,
164 const __u8 *buffer,
165 __u16 len)
166{
167 struct usb_device *dev = gspca_dev->dev;
168
169#ifdef CONFIG_VIDEO_ADV_DEBUG
170 if (len > sizeof gspca_dev->usb_buf) {
171 err("reg_w: buffer overflow");
172 return;
173 }
174 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
175#endif
176 memcpy(gspca_dev->usb_buf, buffer, len);
177 usb_control_msg(dev,
178 usb_sndctrlpipe(dev, 0),
179 0,
180 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
181 0,
182 index, gspca_dev->usb_buf, len, 500);
183}
184
185static const __u8 cx_sensor_init[][4] = {
186 {0x88, 0x11, 0x01, 0x01},
187 {0x88, 0x12, 0x70, 0x01},
188 {0x88, 0x0f, 0x00, 0x01},
189 {0x88, 0x05, 0x01, 0x01},
190 {}
191};
192
193static const __u8 cx11646_fw1[][3] = {
194 {0x00, 0x02, 0x00},
195 {0x01, 0x43, 0x00},
196 {0x02, 0xA7, 0x00},
197 {0x03, 0x8B, 0x01},
198 {0x04, 0xE9, 0x02},
199 {0x05, 0x08, 0x04},
200 {0x06, 0x08, 0x05},
201 {0x07, 0x07, 0x06},
202 {0x08, 0xE7, 0x06},
203 {0x09, 0xC6, 0x07},
204 {0x0A, 0x86, 0x08},
205 {0x0B, 0x46, 0x09},
206 {0x0C, 0x05, 0x0A},
207 {0x0D, 0xA5, 0x0A},
208 {0x0E, 0x45, 0x0B},
209 {0x0F, 0xE5, 0x0B},
210 {0x10, 0x85, 0x0C},
211 {0x11, 0x25, 0x0D},
212 {0x12, 0xC4, 0x0D},
213 {0x13, 0x45, 0x0E},
214 {0x14, 0xE4, 0x0E},
215 {0x15, 0x64, 0x0F},
216 {0x16, 0xE4, 0x0F},
217 {0x17, 0x64, 0x10},
218 {0x18, 0xE4, 0x10},
219 {0x19, 0x64, 0x11},
220 {0x1A, 0xE4, 0x11},
221 {0x1B, 0x64, 0x12},
222 {0x1C, 0xE3, 0x12},
223 {0x1D, 0x44, 0x13},
224 {0x1E, 0xC3, 0x13},
225 {0x1F, 0x24, 0x14},
226 {0x20, 0xA3, 0x14},
227 {0x21, 0x04, 0x15},
228 {0x22, 0x83, 0x15},
229 {0x23, 0xE3, 0x15},
230 {0x24, 0x43, 0x16},
231 {0x25, 0xA4, 0x16},
232 {0x26, 0x23, 0x17},
233 {0x27, 0x83, 0x17},
234 {0x28, 0xE3, 0x17},
235 {0x29, 0x43, 0x18},
236 {0x2A, 0xA3, 0x18},
237 {0x2B, 0x03, 0x19},
238 {0x2C, 0x63, 0x19},
239 {0x2D, 0xC3, 0x19},
240 {0x2E, 0x22, 0x1A},
241 {0x2F, 0x63, 0x1A},
242 {0x30, 0xC3, 0x1A},
243 {0x31, 0x23, 0x1B},
244 {0x32, 0x83, 0x1B},
245 {0x33, 0xE2, 0x1B},
246 {0x34, 0x23, 0x1C},
247 {0x35, 0x83, 0x1C},
248 {0x36, 0xE2, 0x1C},
249 {0x37, 0x23, 0x1D},
250 {0x38, 0x83, 0x1D},
251 {0x39, 0xE2, 0x1D},
252 {0x3A, 0x23, 0x1E},
253 {0x3B, 0x82, 0x1E},
254 {0x3C, 0xC3, 0x1E},
255 {0x3D, 0x22, 0x1F},
256 {0x3E, 0x63, 0x1F},
257 {0x3F, 0xC1, 0x1F},
258 {}
259};
260static void cx11646_fw(struct gspca_dev*gspca_dev)
261{
262 int i = 0;
263
264 reg_w_val(gspca_dev, 0x006a, 0x02);
265 while (cx11646_fw1[i][1]) {
266 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
267 i++;
268 }
269 reg_w_val(gspca_dev, 0x006a, 0x00);
270}
271
272static const __u8 cxsensor[] = {
273 0x88, 0x12, 0x70, 0x01,
274 0x88, 0x0d, 0x02, 0x01,
275 0x88, 0x0f, 0x00, 0x01,
276 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
277 0x88, 0x02, 0x10, 0x01,
278 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
279 0x88, 0x0B, 0x00, 0x01,
280 0x88, 0x0A, 0x0A, 0x01,
281 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
282 0x88, 0x05, 0x01, 0x01,
283 0xA1, 0x18, 0x00, 0x01,
284 0x00
285};
286
287static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
288static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
289static const __u8 reg10[] = { 0xb1, 0xb1 };
290static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
291static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
292 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
293static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
294 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
295static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
296static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
297
298static void cx_sensor(struct gspca_dev*gspca_dev)
299{
300 int i = 0;
301 int length;
302 const __u8 *ptsensor = cxsensor;
303
304 reg_w(gspca_dev, 0x0020, reg20, 8);
305 reg_w(gspca_dev, 0x0028, reg28, 8);
306 reg_w(gspca_dev, 0x0010, reg10, 8);
307 reg_w_val(gspca_dev, 0x0092, 0x03);
308
309 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
310 case 0:
311 reg_w(gspca_dev, 0x0071, reg71a, 4);
312 break;
313 case 1:
314 reg_w(gspca_dev, 0x0071, reg71b, 4);
315 break;
316 default:
317/* case 2: */
318 reg_w(gspca_dev, 0x0071, reg71c, 4);
319 break;
320 case 3:
321 reg_w(gspca_dev, 0x0071, reg71d, 4);
322 break;
323 }
324 reg_w(gspca_dev, 0x007b, reg7b, 6);
325 reg_w_val(gspca_dev, 0x00f8, 0x00);
326 reg_w(gspca_dev, 0x0010, reg10, 8);
327 reg_w_val(gspca_dev, 0x0098, 0x41);
328 for (i = 0; i < 11; i++) {
329 if (i == 3 || i == 5 || i == 8)
330 length = 8;
331 else
332 length = 4;
333 reg_w(gspca_dev, 0x00e5, ptsensor, length);
334 if (length == 4)
335 reg_r(gspca_dev, 0x00e8, 1);
336 else
337 reg_r(gspca_dev, 0x00e8, length);
338 ptsensor += length;
339 }
340 reg_r(gspca_dev, 0x00e7, 8);
341}
342
343static const __u8 cx_inits_176[] = {
344 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
345 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
346 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
347 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
348 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
349 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
350 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
351};
352static const __u8 cx_inits_320[] = {
353 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
354 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
355 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
356 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
357 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
358 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
359 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
360};
361static const __u8 cx_inits_352[] = {
362 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
363 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
364 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
365 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
366 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
367 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
368 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
369};
370static const __u8 cx_inits_640[] = {
371 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
372 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
373 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
374 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
375 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
376 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
377 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
378};
379
380static void cx11646_initsize(struct gspca_dev *gspca_dev)
381{
382 const __u8 *cxinit;
383 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
384 static const __u8 reg17[] =
385 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
386
387 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
388 case 0:
389 cxinit = cx_inits_640;
390 break;
391 case 1:
392 cxinit = cx_inits_352;
393 break;
394 default:
395/* case 2: */
396 cxinit = cx_inits_320;
397 break;
398 case 3:
399 cxinit = cx_inits_176;
400 break;
401 }
402 reg_w_val(gspca_dev, 0x009a, 0x01);
403 reg_w_val(gspca_dev, 0x0010, 0x10);
404 reg_w(gspca_dev, 0x0012, reg12, 5);
405 reg_w(gspca_dev, 0x0017, reg17, 8);
406 reg_w_val(gspca_dev, 0x00c0, 0x00);
407 reg_w_val(gspca_dev, 0x00c1, 0x04);
408 reg_w_val(gspca_dev, 0x00c2, 0x04);
409
410 reg_w(gspca_dev, 0x0061, cxinit, 8);
411 cxinit += 8;
412 reg_w(gspca_dev, 0x00ca, cxinit, 8);
413 cxinit += 8;
414 reg_w(gspca_dev, 0x00d2, cxinit, 8);
415 cxinit += 8;
416 reg_w(gspca_dev, 0x00da, cxinit, 6);
417 cxinit += 8;
418 reg_w(gspca_dev, 0x0041, cxinit, 8);
419 cxinit += 8;
420 reg_w(gspca_dev, 0x0049, cxinit, 8);
421 cxinit += 8;
422 reg_w(gspca_dev, 0x0051, cxinit, 2);
423
424 reg_r(gspca_dev, 0x0010, 1);
425}
426
427static const __u8 cx_jpeg_init[][8] = {
428 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
429 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
430 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
431 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
432 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
433 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
434 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
435 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
436 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
437 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
438 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
439 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
440 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
441 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
442 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
443 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
444 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
445 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
446 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
447 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
448 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
449 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
450 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
451 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
452 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
453 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
454 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
455 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
456 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
457 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
458 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
459 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
460 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
461 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
462 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
463 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
464 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
465 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
466 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
467 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
468 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
469 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
470 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
471 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
472 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
473 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
474 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
475 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
476 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
477 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
478 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
479 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
480 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
481 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
482 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
483 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
484 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
485 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
486 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
487 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
488 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
489 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
490 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
491 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
492 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
493 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
494 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
495 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
496 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
497 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
498 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
499 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
500 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
501 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
502 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
503 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
504 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
505 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
506 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
507};
508
509
510static const __u8 cxjpeg_640[][8] = {
511 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
512 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
513 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
514 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
515 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
516 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
517 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
518 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
519 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
520 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
521 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
522 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
523 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
524 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
525 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
526 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
527 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
528 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
529 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
530 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
531 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
532 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
533 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
534 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
535 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
536 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
537 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
538};
539static const __u8 cxjpeg_352[][8] = {
540 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
541 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
542 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
543 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
544 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
545 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
546 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
547 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
548 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
549 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
550 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
551 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
552 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
553 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
554 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
555 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
556 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
557 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
558 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
559 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
560 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
561 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
562 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
563 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
564 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
565 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
566 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
567};
568static const __u8 cxjpeg_320[][8] = {
569 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
570 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
571 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
572 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
573 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
574 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
575 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
576 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
577 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
578 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
579 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
580 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
581 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
582 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
583 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
584 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
585 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
586 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
587 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
588 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
589 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
590 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
591 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
592 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
593 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
594 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
595 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
596};
597static const __u8 cxjpeg_176[][8] = {
598 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
599 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
600 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
601 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
602 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
603 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
604 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
605 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
606 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
607 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
608 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
609 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
610 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
611 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
612 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
613 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
614 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
615 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
616 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
617 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
618 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
619 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
620 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
621 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
622 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
623 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
624 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
625};
626/* 640 take with the zcx30x part */
627static const __u8 cxjpeg_qtable[][8] = {
628 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
629 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
630 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
631 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
632 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
633 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
634 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
635 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
636 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
637 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
638 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
639 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
640 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
641 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
642 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
643 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
644 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
645 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
646};
647
648
649static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
650{
651 int i;
652 int length;
653
654 reg_w_val(gspca_dev, 0x00c0, 0x01);
655 reg_w_val(gspca_dev, 0x00c3, 0x00);
656 reg_w_val(gspca_dev, 0x00c0, 0x00);
657 reg_r(gspca_dev, 0x0001, 1);
658 length = 8;
659 for (i = 0; i < 79; i++) {
660 if (i == 78)
661 length = 6;
662 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
663 }
664 reg_r(gspca_dev, 0x0002, 1);
665 reg_w_val(gspca_dev, 0x0055, 0x14);
666}
667
668static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
669static const __u8 regE5_8[] =
670 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
671static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
672static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
673static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
674static const __u8 reg51[] = { 0x77, 0x03 };
675#define reg70 0x03
676
677static void cx11646_jpeg(struct gspca_dev*gspca_dev)
678{
679 int i;
680 int length;
681 __u8 Reg55;
682 int retry;
683
684 reg_w_val(gspca_dev, 0x00c0, 0x01);
685 reg_w_val(gspca_dev, 0x00c3, 0x00);
686 reg_w_val(gspca_dev, 0x00c0, 0x00);
687 reg_r(gspca_dev, 0x0001, 1);
688 length = 8;
689 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
690 case 0:
691 for (i = 0; i < 27; i++) {
692 if (i == 26)
693 length = 2;
694 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
695 }
696 Reg55 = 0x28;
697 break;
698 case 1:
699 for (i = 0; i < 27; i++) {
700 if (i == 26)
701 length = 2;
702 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
703 }
704 Reg55 = 0x16;
705 break;
706 default:
707/* case 2: */
708 for (i = 0; i < 27; i++) {
709 if (i == 26)
710 length = 2;
711 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
712 }
713 Reg55 = 0x14;
714 break;
715 case 3:
716 for (i = 0; i < 27; i++) {
717 if (i == 26)
718 length = 2;
719 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
720 }
721 Reg55 = 0x0B;
722 break;
723 }
724
725 reg_r(gspca_dev, 0x0002, 1);
726 reg_w_val(gspca_dev, 0x0055, Reg55);
727 reg_r(gspca_dev, 0x0002, 1);
728 reg_w(gspca_dev, 0x0010, reg10, 2);
729 reg_w_val(gspca_dev, 0x0054, 0x02);
730 reg_w_val(gspca_dev, 0x0054, 0x01);
731 reg_w_val(gspca_dev, 0x0000, 0x94);
732 reg_w_val(gspca_dev, 0x0053, 0xc0);
733 reg_w_val(gspca_dev, 0x00fc, 0xe1);
734 reg_w_val(gspca_dev, 0x0000, 0x00);
735 /* wait for completion */
736 retry = 50;
737 while (retry--) {
738 reg_r(gspca_dev, 0x0002, 1);
739 /* 0x07 until 0x00 */
740 if (gspca_dev->usb_buf[0] == 0x00)
741 break;
742 reg_w_val(gspca_dev, 0x0053, 0x00);
743 }
744 if (retry == 0)
745 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
746 /* send the qtable now */
747 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
748 length = 8;
749 for (i = 0; i < 18; i++) {
750 if (i == 17)
751 length = 2;
752 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
753
754 }
755 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
756 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
757 reg_w_val(gspca_dev, 0x0054, 0x02);
758 reg_w_val(gspca_dev, 0x0054, 0x01);
759 reg_w_val(gspca_dev, 0x0000, 0x94);
760 reg_w_val(gspca_dev, 0x0053, 0xc0);
761
762 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
763 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
764 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
765 reg_w(gspca_dev, 0x0012, reg12, 5);
766 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
767 reg_r(gspca_dev, 0x00e8, 8);
768 reg_w(gspca_dev, 0x00e5, regE5a, 4);
769 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
770 reg_w_val(gspca_dev, 0x009a, 0x01);
771 reg_w(gspca_dev, 0x00e5, regE5b, 4);
772 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
773 reg_w(gspca_dev, 0x00e5, regE5c, 4);
774 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
775
776 reg_w(gspca_dev, 0x0051, reg51, 2);
777 reg_w(gspca_dev, 0x0010, reg10, 2);
778 reg_w_val(gspca_dev, 0x0070, reg70);
779}
780
781static void cx11646_init1(struct gspca_dev *gspca_dev)
782{
783 int i = 0;
784
785 reg_w_val(gspca_dev, 0x0010, 0x00);
786 reg_w_val(gspca_dev, 0x0053, 0x00);
787 reg_w_val(gspca_dev, 0x0052, 0x00);
788 reg_w_val(gspca_dev, 0x009b, 0x2f);
789 reg_w_val(gspca_dev, 0x009c, 0x10);
790 reg_r(gspca_dev, 0x0098, 1);
791 reg_w_val(gspca_dev, 0x0098, 0x40);
792 reg_r(gspca_dev, 0x0099, 1);
793 reg_w_val(gspca_dev, 0x0099, 0x07);
794 reg_w_val(gspca_dev, 0x0039, 0x40);
795 reg_w_val(gspca_dev, 0x003c, 0xff);
796 reg_w_val(gspca_dev, 0x003f, 0x1f);
797 reg_w_val(gspca_dev, 0x003d, 0x40);
798/* reg_w_val(gspca_dev, 0x003d, 0x60); */
799 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
800
801 while (cx_sensor_init[i][0]) {
802 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
803 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
804 if (i == 1) {
805 reg_w_val(gspca_dev, 0x00ed, 0x01);
806 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
807 }
808 i++;
809 }
810 reg_w_val(gspca_dev, 0x00c3, 0x00);
811}
812
813/* this function is called at probe time */
814static int sd_config(struct gspca_dev *gspca_dev,
815 const struct usb_device_id *id)
816{
817 struct sd *sd = (struct sd *) gspca_dev;
818 struct cam *cam;
819
820 cam = &gspca_dev->cam;
821 cam->dev_name = (char *) id->driver_info;
822 cam->epaddr = 0x01;
823 cam->cam_mode = vga_mode;
824 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
825
826 sd->qindex = 0; /* set the quantization */
827 sd->brightness = BRIGHTNESS_DEF;
828 sd->contrast = CONTRAST_DEF;
829 sd->colors = COLOR_DEF;
830 return 0;
831}
832
833/* this function is called at open time */
834static int sd_open(struct gspca_dev *gspca_dev)
835{
836 cx11646_init1(gspca_dev);
837 cx11646_initsize(gspca_dev);
838 cx11646_fw(gspca_dev);
839 cx_sensor(gspca_dev);
840 cx11646_jpegInit(gspca_dev);
841 return 0;
842}
843
844static void sd_start(struct gspca_dev *gspca_dev)
845{
846 cx11646_initsize(gspca_dev);
847 cx11646_fw(gspca_dev);
848 cx_sensor(gspca_dev);
849 cx11646_jpeg(gspca_dev);
850}
851
852static void sd_stopN(struct gspca_dev *gspca_dev)
853{
854}
855
856static void sd_stop0(struct gspca_dev *gspca_dev)
857{
858 int retry = 50;
859
860 reg_w_val(gspca_dev, 0x0000, 0x00);
861 reg_r(gspca_dev, 0x0002, 1);
862 reg_w_val(gspca_dev, 0x0053, 0x00);
863
864 while (retry--) {
865/* reg_r(gspca_dev, 0x0002, 1);*/
866 reg_r(gspca_dev, 0x0053, 1);
867 if (gspca_dev->usb_buf[0] == 0)
868 break;
869 }
870 reg_w_val(gspca_dev, 0x0000, 0x00);
871 reg_r(gspca_dev, 0x0002, 1);
872
873 reg_w_val(gspca_dev, 0x0010, 0x00);
874 reg_r(gspca_dev, 0x0033, 1);
875 reg_w_val(gspca_dev, 0x00fc, 0xe0);
876}
877
878static void sd_close(struct gspca_dev *gspca_dev)
879{
880}
881
882static void sd_pkt_scan(struct gspca_dev *gspca_dev,
883 struct gspca_frame *frame, /* target */
884 __u8 *data, /* isoc packet */
885 int len) /* iso packet length */
886{
887 if (data[0] == 0xff && data[1] == 0xd8) {
888
889 /* start of frame */
890 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
891 data, 0);
892
893 /* put the JPEG header in the new frame */
894 jpeg_put_header(gspca_dev, frame,
895 ((struct sd *) gspca_dev)->qindex,
896 0x22);
897 data += 2;
898 len -= 2;
899 }
900 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
901}
902
903static void setbrightness(struct gspca_dev*gspca_dev)
904{
905 struct sd *sd = (struct sd *) gspca_dev;
906 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
907 __u8 reg51c[2];
908 __u8 bright;
909 __u8 colors;
910
911 bright = sd->brightness;
912 regE5cbx[2] = bright;
913 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
914 reg_r(gspca_dev, 0x00e8, 8);
915 reg_w(gspca_dev, 0x00e5, regE5c, 4);
916 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
917
918 colors = sd->colors;
919 reg51c[0] = 0x77;
920 reg51c[1] = colors;
921 reg_w(gspca_dev, 0x0051, reg51c, 2);
922 reg_w(gspca_dev, 0x0010, reg10, 2);
923 reg_w_val(gspca_dev, 0x0070, reg70);
924}
925
926static void setcontrast(struct gspca_dev*gspca_dev)
927{
928 struct sd *sd = (struct sd *) gspca_dev;
929 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
930/* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
931 __u8 reg51c[2];
932
933 regE5acx[2] = sd->contrast;
934 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
935 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
936 reg51c[0] = 0x77;
937 reg51c[1] = sd->colors;
938 reg_w(gspca_dev, 0x0051, reg51c, 2);
939 reg_w(gspca_dev, 0x0010, reg10, 2);
940 reg_w_val(gspca_dev, 0x0070, reg70);
941}
942
943static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
944{
945 struct sd *sd = (struct sd *) gspca_dev;
946
947 sd->brightness = val;
948 if (gspca_dev->streaming)
949 setbrightness(gspca_dev);
950 return 0;
951}
952
953static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
954{
955 struct sd *sd = (struct sd *) gspca_dev;
956
957 *val = sd->brightness;
958 return 0;
959}
960
961static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
962{
963 struct sd *sd = (struct sd *) gspca_dev;
964
965 sd->contrast = val;
966 if (gspca_dev->streaming)
967 setcontrast(gspca_dev);
968 return 0;
969}
970
971static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
972{
973 struct sd *sd = (struct sd *) gspca_dev;
974
975 *val = sd->contrast;
976 return 0;
977}
978
979static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
980{
981 struct sd *sd = (struct sd *) gspca_dev;
982
983 sd->colors = val;
984 if (gspca_dev->streaming) {
985 setbrightness(gspca_dev);
986 setcontrast(gspca_dev);
987 }
988 return 0;
989}
990
991static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
992{
993 struct sd *sd = (struct sd *) gspca_dev;
994
995 *val = sd->colors;
996 return 0;
997}
998
999/* sub-driver description */
1000static struct sd_desc sd_desc = {
1001 .name = MODULE_NAME,
1002 .ctrls = sd_ctrls,
1003 .nctrls = ARRAY_SIZE(sd_ctrls),
1004 .config = sd_config,
1005 .open = sd_open,
1006 .start = sd_start,
1007 .stopN = sd_stopN,
1008 .stop0 = sd_stop0,
1009 .close = sd_close,
1010 .pkt_scan = sd_pkt_scan,
1011};
1012
1013/* -- module initialisation -- */
1014#define DVNM(name) .driver_info = (kernel_ulong_t) name
1015static __devinitdata struct usb_device_id device_table[] = {
1016 {USB_DEVICE(0x0572, 0x0041), DVNM("Creative Notebook cx11646")},
1017 {}
1018};
1019MODULE_DEVICE_TABLE(usb, device_table);
1020
1021/* -- device connect -- */
1022static int sd_probe(struct usb_interface *intf,
1023 const struct usb_device_id *id)
1024{
1025 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1026 THIS_MODULE);
1027}
1028
1029static struct usb_driver sd_driver = {
1030 .name = MODULE_NAME,
1031 .id_table = device_table,
1032 .probe = sd_probe,
1033 .disconnect = gspca_disconnect,
1034};
1035
1036/* -- module insert / remove -- */
1037static int __init sd_mod_init(void)
1038{
1039 if (usb_register(&sd_driver) < 0)
1040 return -1;
1041 PDEBUG(D_PROBE, "v%s registered", version);
1042 return 0;
1043}
1044static void __exit sd_mod_exit(void)
1045{
1046 usb_deregister(&sd_driver);
1047 PDEBUG(D_PROBE, "deregistered");
1048}
1049
1050module_init(sd_mod_init);
1051module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
new file mode 100644
index 000000000000..8ab4ea7201a9
--- /dev/null
+++ b/drivers/media/video/gspca/etoms.c
@@ -0,0 +1,956 @@
1/*
2 * Etoms Et61x151 GPL Linux driver by Michel Xhaard (09/09/2004)
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define MODULE_NAME "etoms"
22
23#include "gspca.h"
24
25#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
26static const char version[] = "2.1.7";
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("Etoms USB Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* specific webcam descriptor */
33struct sd {
34 struct gspca_dev gspca_dev; /* !! must be the first item */
35
36 unsigned char brightness;
37 unsigned char contrast;
38 unsigned char colors;
39 unsigned char autogain;
40
41 char sensor;
42#define SENSOR_PAS106 0
43#define SENSOR_TAS5130CXX 1
44 signed char ag_cnt;
45#define AG_CNT_START 13
46};
47
48/* V4L2 controls supported by the driver */
49static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
50static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
51static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
52static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
53static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
54static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
55static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
56static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
57
58static struct ctrl sd_ctrls[] = {
59 {
60 {
61 .id = V4L2_CID_BRIGHTNESS,
62 .type = V4L2_CTRL_TYPE_INTEGER,
63 .name = "Brightness",
64 .minimum = 1,
65 .maximum = 127,
66 .step = 1,
67#define BRIGHTNESS_DEF 63
68 .default_value = BRIGHTNESS_DEF,
69 },
70 .set = sd_setbrightness,
71 .get = sd_getbrightness,
72 },
73 {
74 {
75 .id = V4L2_CID_CONTRAST,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Contrast",
78 .minimum = 0,
79 .maximum = 255,
80 .step = 1,
81#define CONTRAST_DEF 127
82 .default_value = CONTRAST_DEF,
83 },
84 .set = sd_setcontrast,
85 .get = sd_getcontrast,
86 },
87 {
88 {
89 .id = V4L2_CID_SATURATION,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Color",
92 .minimum = 0,
93 .maximum = 15,
94 .step = 1,
95#define COLOR_DEF 7
96 .default_value = COLOR_DEF,
97 },
98 .set = sd_setcolors,
99 .get = sd_getcolors,
100 },
101 {
102 {
103 .id = V4L2_CID_AUTOGAIN,
104 .type = V4L2_CTRL_TYPE_BOOLEAN,
105 .name = "Auto Gain",
106 .minimum = 0,
107 .maximum = 1,
108 .step = 1,
109#define AUTOGAIN_DEF 1
110 .default_value = AUTOGAIN_DEF,
111 },
112 .set = sd_setautogain,
113 .get = sd_getautogain,
114 },
115};
116
117static struct v4l2_pix_format vga_mode[] = {
118 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
119 .bytesperline = 320,
120 .sizeimage = 320 * 240,
121 .colorspace = V4L2_COLORSPACE_SRGB,
122 .priv = 1},
123/* {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
124 .bytesperline = 640,
125 .sizeimage = 640 * 480,
126 .colorspace = V4L2_COLORSPACE_SRGB,
127 .priv = 0}, */
128};
129
130static struct v4l2_pix_format sif_mode[] = {
131 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
132 .bytesperline = 176,
133 .sizeimage = 176 * 144,
134 .colorspace = V4L2_COLORSPACE_SRGB,
135 .priv = 1},
136 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
137 .bytesperline = 352,
138 .sizeimage = 352 * 288,
139 .colorspace = V4L2_COLORSPACE_SRGB,
140 .priv = 0},
141};
142
143#define ETOMS_ALT_SIZE_1000 12
144
145#define ET_GPIO_DIR_CTRL 0x04 /* Control IO bit[0..5] (0 in 1 out) */
146#define ET_GPIO_OUT 0x05 /* Only IO data */
147#define ET_GPIO_IN 0x06 /* Read Only IO data */
148#define ET_RESET_ALL 0x03
149#define ET_ClCK 0x01
150#define ET_CTRL 0x02 /* enable i2c OutClck Powerdown mode */
151
152#define ET_COMP 0x12 /* Compression register */
153#define ET_MAXQt 0x13
154#define ET_MINQt 0x14
155#define ET_COMP_VAL0 0x02
156#define ET_COMP_VAL1 0x03
157
158#define ET_REG1d 0x1d
159#define ET_REG1e 0x1e
160#define ET_REG1f 0x1f
161#define ET_REG20 0x20
162#define ET_REG21 0x21
163#define ET_REG22 0x22
164#define ET_REG23 0x23
165#define ET_REG24 0x24
166#define ET_REG25 0x25
167/* base registers for luma calculation */
168#define ET_LUMA_CENTER 0x39
169
170#define ET_G_RED 0x4d
171#define ET_G_GREEN1 0x4e
172#define ET_G_BLUE 0x4f
173#define ET_G_GREEN2 0x50
174#define ET_G_GR_H 0x51
175#define ET_G_GB_H 0x52
176
177#define ET_O_RED 0x34
178#define ET_O_GREEN1 0x35
179#define ET_O_BLUE 0x36
180#define ET_O_GREEN2 0x37
181
182#define ET_SYNCHRO 0x68
183#define ET_STARTX 0x69
184#define ET_STARTY 0x6a
185#define ET_WIDTH_LOW 0x6b
186#define ET_HEIGTH_LOW 0x6c
187#define ET_W_H_HEIGTH 0x6d
188
189#define ET_REG6e 0x6e /* OBW */
190#define ET_REG6f 0x6f /* OBW */
191#define ET_REG70 0x70 /* OBW_AWB */
192#define ET_REG71 0x71 /* OBW_AWB */
193#define ET_REG72 0x72 /* OBW_AWB */
194#define ET_REG73 0x73 /* Clkdelay ns */
195#define ET_REG74 0x74 /* test pattern */
196#define ET_REG75 0x75 /* test pattern */
197
198#define ET_I2C_CLK 0x8c
199#define ET_PXL_CLK 0x60
200
201#define ET_I2C_BASE 0x89
202#define ET_I2C_COUNT 0x8a
203#define ET_I2C_PREFETCH 0x8b
204#define ET_I2C_REG 0x88
205#define ET_I2C_DATA7 0x87
206#define ET_I2C_DATA6 0x86
207#define ET_I2C_DATA5 0x85
208#define ET_I2C_DATA4 0x84
209#define ET_I2C_DATA3 0x83
210#define ET_I2C_DATA2 0x82
211#define ET_I2C_DATA1 0x81
212#define ET_I2C_DATA0 0x80
213
214#define PAS106_REG2 0x02 /* pxlClk = systemClk/(reg2) */
215#define PAS106_REG3 0x03 /* line/frame H [11..4] */
216#define PAS106_REG4 0x04 /* line/frame L [3..0] */
217#define PAS106_REG5 0x05 /* exposure time line offset(default 5) */
218#define PAS106_REG6 0x06 /* exposure time pixel offset(default 6) */
219#define PAS106_REG7 0x07 /* signbit Dac (default 0) */
220#define PAS106_REG9 0x09
221#define PAS106_REG0e 0x0e /* global gain [4..0](default 0x0e) */
222#define PAS106_REG13 0x13 /* end i2c write */
223
224static const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
225
226static const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d };
227
228static const __u8 I2c3[] = { 0x12, 0x05 };
229
230static const __u8 I2c4[] = { 0x41, 0x08 };
231
232/* read 'len' bytes to gspca_dev->usb_buf */
233static void reg_r(struct gspca_dev *gspca_dev,
234 __u16 index,
235 __u16 len)
236{
237 struct usb_device *dev = gspca_dev->dev;
238
239#ifdef CONFIG_VIDEO_ADV_DEBUG
240 if (len > sizeof gspca_dev->usb_buf) {
241 err("reg_r: buffer overflow");
242 return;
243 }
244#endif
245 usb_control_msg(dev,
246 usb_rcvctrlpipe(dev, 0),
247 0,
248 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
249 0,
250 index, gspca_dev->usb_buf, len, 500);
251 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
252 index, gspca_dev->usb_buf[0]);
253}
254
255static void reg_w_val(struct gspca_dev *gspca_dev,
256 __u16 index,
257 __u8 val)
258{
259 struct usb_device *dev = gspca_dev->dev;
260
261 gspca_dev->usb_buf[0] = val;
262 usb_control_msg(dev,
263 usb_sndctrlpipe(dev, 0),
264 0,
265 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
266 0,
267 index, gspca_dev->usb_buf, 1, 500);
268}
269
270static void reg_w(struct gspca_dev *gspca_dev,
271 __u16 index,
272 const __u8 *buffer,
273 __u16 len)
274{
275 struct usb_device *dev = gspca_dev->dev;
276
277#ifdef CONFIG_VIDEO_ADV_DEBUG
278 if (len > sizeof gspca_dev->usb_buf) {
279 err("reg_w: buffer overflow");
280 return;
281 }
282 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
283#endif
284 memcpy(gspca_dev->usb_buf, buffer, len);
285 usb_control_msg(dev,
286 usb_sndctrlpipe(dev, 0),
287 0,
288 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
289 0, index, gspca_dev->usb_buf, len, 500);
290}
291
292static int i2c_w(struct gspca_dev *gspca_dev,
293 __u8 reg,
294 const __u8 *buffer,
295 int len, __u8 mode)
296{
297 /* buffer should be [D0..D7] */
298 __u8 ptchcount;
299
300 /* set the base address */
301 reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
302 /* sensor base for the pas106 */
303 /* set count and prefetch */
304 ptchcount = ((len & 0x07) << 4) | (mode & 0x03);
305 reg_w_val(gspca_dev, ET_I2C_COUNT, ptchcount);
306 /* set the register base */
307 reg_w_val(gspca_dev, ET_I2C_REG, reg);
308 while (--len >= 0)
309 reg_w_val(gspca_dev, ET_I2C_DATA0 + len, buffer[len]);
310 return 0;
311}
312
313static int i2c_r(struct gspca_dev *gspca_dev,
314 __u8 reg)
315{
316 /* set the base address */
317 reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
318 /* sensor base for the pas106 */
319 /* set count and prefetch (cnd: 4 bits - mode: 4 bits) */
320 reg_w_val(gspca_dev, ET_I2C_COUNT, 0x11);
321 reg_w_val(gspca_dev, ET_I2C_REG, reg); /* set the register base */
322 reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x02); /* prefetch */
323 reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x00);
324 reg_r(gspca_dev, ET_I2C_DATA0, 1); /* read one byte */
325 return 0;
326}
327
328static int Et_WaitStatus(struct gspca_dev *gspca_dev)
329{
330 int retry = 10;
331
332 while (retry--) {
333 reg_r(gspca_dev, ET_ClCK, 1);
334 if (gspca_dev->usb_buf[0] != 0)
335 return 1;
336 }
337 return 0;
338}
339
340static int et_video(struct gspca_dev *gspca_dev,
341 int on)
342{
343 int ret;
344
345 reg_w_val(gspca_dev, ET_GPIO_OUT,
346 on ? 0x10 /* startvideo - set Bit5 */
347 : 0); /* stopvideo */
348 ret = Et_WaitStatus(gspca_dev);
349 if (ret != 0)
350 PDEBUG(D_ERR, "timeout video on/off");
351 return ret;
352}
353
354static void Et_init2(struct gspca_dev *gspca_dev)
355{
356 __u8 value;
357 static const __u8 FormLine[] = { 0x84, 0x03, 0x14, 0xf4, 0x01, 0x05 };
358
359 PDEBUG(D_STREAM, "Open Init2 ET");
360 reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 0x2f);
361 reg_w_val(gspca_dev, ET_GPIO_OUT, 0x10);
362 reg_r(gspca_dev, ET_GPIO_IN, 1);
363 reg_w_val(gspca_dev, ET_ClCK, 0x14); /* 0x14 // 0x16 enabled pattern */
364 reg_w_val(gspca_dev, ET_CTRL, 0x1b);
365
366 /* compression et subsampling */
367 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
368 value = ET_COMP_VAL1; /* 320 */
369 else
370 value = ET_COMP_VAL0; /* 640 */
371 reg_w_val(gspca_dev, ET_COMP, value);
372 reg_w_val(gspca_dev, ET_MAXQt, 0x1f);
373 reg_w_val(gspca_dev, ET_MINQt, 0x04);
374 /* undocumented registers */
375 reg_w_val(gspca_dev, ET_REG1d, 0xff);
376 reg_w_val(gspca_dev, ET_REG1e, 0xff);
377 reg_w_val(gspca_dev, ET_REG1f, 0xff);
378 reg_w_val(gspca_dev, ET_REG20, 0x35);
379 reg_w_val(gspca_dev, ET_REG21, 0x01);
380 reg_w_val(gspca_dev, ET_REG22, 0x00);
381 reg_w_val(gspca_dev, ET_REG23, 0xff);
382 reg_w_val(gspca_dev, ET_REG24, 0xff);
383 reg_w_val(gspca_dev, ET_REG25, 0x0f);
384 /* colors setting */
385 reg_w_val(gspca_dev, 0x30, 0x11); /* 0x30 */
386 reg_w_val(gspca_dev, 0x31, 0x40);
387 reg_w_val(gspca_dev, 0x32, 0x00);
388 reg_w_val(gspca_dev, ET_O_RED, 0x00); /* 0x34 */
389 reg_w_val(gspca_dev, ET_O_GREEN1, 0x00);
390 reg_w_val(gspca_dev, ET_O_BLUE, 0x00);
391 reg_w_val(gspca_dev, ET_O_GREEN2, 0x00);
392 /*************/
393 reg_w_val(gspca_dev, ET_G_RED, 0x80); /* 0x4d */
394 reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
395 reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
396 reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
397 reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
398 reg_w_val(gspca_dev, ET_G_GB_H, 0x00); /* 0x52 */
399 /* Window control registers */
400 reg_w_val(gspca_dev, 0x61, 0x80); /* use cmc_out */
401 reg_w_val(gspca_dev, 0x62, 0x02);
402 reg_w_val(gspca_dev, 0x63, 0x03);
403 reg_w_val(gspca_dev, 0x64, 0x14);
404 reg_w_val(gspca_dev, 0x65, 0x0e);
405 reg_w_val(gspca_dev, 0x66, 0x02);
406 reg_w_val(gspca_dev, 0x67, 0x02);
407
408 /**************************************/
409 reg_w_val(gspca_dev, ET_SYNCHRO, 0x8f); /* 0x68 */
410 reg_w_val(gspca_dev, ET_STARTX, 0x69); /* 0x6a //0x69 */
411 reg_w_val(gspca_dev, ET_STARTY, 0x0d); /* 0x0d //0x0c */
412 reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x80);
413 reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0xe0);
414 reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x60); /* 6d */
415 reg_w_val(gspca_dev, ET_REG6e, 0x86);
416 reg_w_val(gspca_dev, ET_REG6f, 0x01);
417 reg_w_val(gspca_dev, ET_REG70, 0x26);
418 reg_w_val(gspca_dev, ET_REG71, 0x7a);
419 reg_w_val(gspca_dev, ET_REG72, 0x01);
420 /* Clock Pattern registers ***************** */
421 reg_w_val(gspca_dev, ET_REG73, 0x00);
422 reg_w_val(gspca_dev, ET_REG74, 0x18); /* 0x28 */
423 reg_w_val(gspca_dev, ET_REG75, 0x0f); /* 0x01 */
424 /**********************************************/
425 reg_w_val(gspca_dev, 0x8a, 0x20);
426 reg_w_val(gspca_dev, 0x8d, 0x0f);
427 reg_w_val(gspca_dev, 0x8e, 0x08);
428 /**************************************/
429 reg_w_val(gspca_dev, 0x03, 0x08);
430 reg_w_val(gspca_dev, ET_PXL_CLK, 0x03);
431 reg_w_val(gspca_dev, 0x81, 0xff);
432 reg_w_val(gspca_dev, 0x80, 0x00);
433 reg_w_val(gspca_dev, 0x81, 0xff);
434 reg_w_val(gspca_dev, 0x80, 0x20);
435 reg_w_val(gspca_dev, 0x03, 0x01);
436 reg_w_val(gspca_dev, 0x03, 0x00);
437 reg_w_val(gspca_dev, 0x03, 0x08);
438 /********************************************/
439
440/* reg_r(gspca_dev, ET_I2C_BASE, 1);
441 always 0x40 as the pas106 ??? */
442 /* set the sensor */
443 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
444 value = 0x04; /* 320 */
445 else /* 640 */
446 value = 0x1e; /* 0x17 * setting PixelClock
447 * 0x03 mean 24/(3+1) = 6 Mhz
448 * 0x05 -> 24/(5+1) = 4 Mhz
449 * 0x0b -> 24/(11+1) = 2 Mhz
450 * 0x17 -> 24/(23+1) = 1 Mhz
451 */
452 reg_w_val(gspca_dev, ET_PXL_CLK, value);
453 /* now set by fifo the FormatLine setting */
454 reg_w(gspca_dev, 0x62, FormLine, 6);
455
456 /* set exposure times [ 0..0x78] 0->longvalue 0x78->shortvalue */
457 reg_w_val(gspca_dev, 0x81, 0x47); /* 0x47; */
458 reg_w_val(gspca_dev, 0x80, 0x40); /* 0x40; */
459 /* Pedro change */
460 /* Brightness change Brith+ decrease value */
461 /* Brigth- increase value */
462 /* original value = 0x70; */
463 reg_w_val(gspca_dev, 0x81, 0x30); /* 0x20; - set brightness */
464 reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */
465}
466
467static void setcolors(struct gspca_dev *gspca_dev)
468{
469 struct sd *sd = (struct sd *) gspca_dev;
470 __u8 I2cc[] = { 0x05, 0x02, 0x02, 0x05, 0x0d };
471 __u8 i2cflags = 0x01;
472 /* __u8 green = 0; */
473 __u8 colors = sd->colors;
474
475 I2cc[3] = colors; /* red */
476 I2cc[0] = 15 - colors; /* blue */
477 /* green = 15 - ((((7*I2cc[0]) >> 2 ) + I2cc[3]) >> 1); */
478 /* I2cc[1] = I2cc[2] = green; */
479 if (sd->sensor == SENSOR_PAS106) {
480 i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
481 i2c_w(gspca_dev, PAS106_REG9, I2cc, sizeof I2cc, 1);
482 }
483/* PDEBUG(D_CONF , "Etoms red %d blue %d green %d",
484 I2cc[3], I2cc[0], green); */
485}
486
487static void getcolors(struct gspca_dev *gspca_dev)
488{
489 struct sd *sd = (struct sd *) gspca_dev;
490
491 if (sd->sensor == SENSOR_PAS106) {
492/* i2c_r(gspca_dev, PAS106_REG9); * blue */
493 i2c_r(gspca_dev, PAS106_REG9 + 3); /* red */
494 sd->colors = gspca_dev->usb_buf[0] & 0x0f;
495 }
496}
497
498static void Et_init1(struct gspca_dev *gspca_dev)
499{
500 __u8 value;
501/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0x22, 0xac, 0x00, 0x01, 0x00}; */
502 __u8 I2c0[] = { 0x0a, 0x12, 0x05, 0x6d, 0xcd, 0x00, 0x01, 0x00 };
503 /* try 1/120 0x6d 0xcd 0x40 */
504/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0xfe, 0xfe, 0xc0, 0x01, 0x00};
505 * 1/60000 hmm ?? */
506
507 PDEBUG(D_STREAM, "Open Init1 ET");
508 reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 7);
509 reg_r(gspca_dev, ET_GPIO_IN, 1);
510 reg_w_val(gspca_dev, ET_RESET_ALL, 1);
511 reg_w_val(gspca_dev, ET_RESET_ALL, 0);
512 reg_w_val(gspca_dev, ET_ClCK, 0x10);
513 reg_w_val(gspca_dev, ET_CTRL, 0x19);
514 /* compression et subsampling */
515 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
516 value = ET_COMP_VAL1;
517 else
518 value = ET_COMP_VAL0;
519 PDEBUG(D_STREAM, "Open mode %d Compression %d",
520 gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv,
521 value);
522 reg_w_val(gspca_dev, ET_COMP, value);
523 reg_w_val(gspca_dev, ET_MAXQt, 0x1d);
524 reg_w_val(gspca_dev, ET_MINQt, 0x02);
525 /* undocumented registers */
526 reg_w_val(gspca_dev, ET_REG1d, 0xff);
527 reg_w_val(gspca_dev, ET_REG1e, 0xff);
528 reg_w_val(gspca_dev, ET_REG1f, 0xff);
529 reg_w_val(gspca_dev, ET_REG20, 0x35);
530 reg_w_val(gspca_dev, ET_REG21, 0x01);
531 reg_w_val(gspca_dev, ET_REG22, 0x00);
532 reg_w_val(gspca_dev, ET_REG23, 0xf7);
533 reg_w_val(gspca_dev, ET_REG24, 0xff);
534 reg_w_val(gspca_dev, ET_REG25, 0x07);
535 /* colors setting */
536 reg_w_val(gspca_dev, ET_G_RED, 0x80);
537 reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
538 reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
539 reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
540 reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
541 reg_w_val(gspca_dev, ET_G_GB_H, 0x00);
542 /* Window control registers */
543 reg_w_val(gspca_dev, ET_SYNCHRO, 0xf0);
544 reg_w_val(gspca_dev, ET_STARTX, 0x56); /* 0x56 */
545 reg_w_val(gspca_dev, ET_STARTY, 0x05); /* 0x04 */
546 reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x60);
547 reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0x20);
548 reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x50);
549 reg_w_val(gspca_dev, ET_REG6e, 0x86);
550 reg_w_val(gspca_dev, ET_REG6f, 0x01);
551 reg_w_val(gspca_dev, ET_REG70, 0x86);
552 reg_w_val(gspca_dev, ET_REG71, 0x14);
553 reg_w_val(gspca_dev, ET_REG72, 0x00);
554 /* Clock Pattern registers */
555 reg_w_val(gspca_dev, ET_REG73, 0x00);
556 reg_w_val(gspca_dev, ET_REG74, 0x00);
557 reg_w_val(gspca_dev, ET_REG75, 0x0a);
558 reg_w_val(gspca_dev, ET_I2C_CLK, 0x04);
559 reg_w_val(gspca_dev, ET_PXL_CLK, 0x01);
560 /* set the sensor */
561 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
562 I2c0[0] = 0x06;
563 i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
564 i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
565 value = 0x06;
566 i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
567 i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
568 /* value = 0x1f; */
569 value = 0x04;
570 i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
571 } else {
572 I2c0[0] = 0x0a;
573
574 i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
575 i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
576 value = 0x0a;
577 i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
578 i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
579 value = 0x04;
580 /* value = 0x10; */
581 i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
582 /* bit 2 enable bit 1:2 select 0 1 2 3
583 value = 0x07; * curve 0 *
584 i2c_w(gspca_dev, PAS106_REG0f, &value, 1, 1);
585 */
586 }
587
588/* value = 0x01; */
589/* value = 0x22; */
590/* i2c_w(gspca_dev, PAS106_REG5, &value, 1, 1); */
591 /* magnetude and sign bit for DAC */
592 i2c_w(gspca_dev, PAS106_REG7, I2c4, sizeof I2c4, 1);
593 /* now set by fifo the whole colors setting */
594 reg_w(gspca_dev, ET_G_RED, GainRGBG, 6);
595 getcolors(gspca_dev);
596 setcolors(gspca_dev);
597}
598
599/* this function is called at probe time */
600static int sd_config(struct gspca_dev *gspca_dev,
601 const struct usb_device_id *id)
602{
603 struct sd *sd = (struct sd *) gspca_dev;
604 struct cam *cam;
605 __u16 vendor;
606 __u16 product;
607
608 vendor = id->idVendor;
609 product = id->idProduct;
610/* switch (vendor) { */
611/* case 0x102c: * Etoms */
612 switch (product) {
613 case 0x6151:
614 sd->sensor = SENSOR_PAS106; /* Etoms61x151 */
615 break;
616 case 0x6251:
617 sd->sensor = SENSOR_TAS5130CXX; /* Etoms61x251 */
618 break;
619/* } */
620/* break; */
621 }
622 cam = &gspca_dev->cam;
623 cam->dev_name = (char *) id->driver_info;
624 cam->epaddr = 1;
625 if (sd->sensor == SENSOR_PAS106) {
626 cam->cam_mode = sif_mode;
627 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
628 } else {
629 cam->cam_mode = vga_mode;
630 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
631 }
632 sd->brightness = BRIGHTNESS_DEF;
633 sd->contrast = CONTRAST_DEF;
634 sd->colors = COLOR_DEF;
635 sd->autogain = AUTOGAIN_DEF;
636 return 0;
637}
638
639/* this function is called at open time */
640static int sd_open(struct gspca_dev *gspca_dev)
641{
642 struct sd *sd = (struct sd *) gspca_dev;
643
644 if (sd->sensor == SENSOR_PAS106)
645 Et_init1(gspca_dev);
646 else
647 Et_init2(gspca_dev);
648 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
649 et_video(gspca_dev, 0); /* video off */
650 return 0;
651}
652
653/* -- start the camera -- */
654static void sd_start(struct gspca_dev *gspca_dev)
655{
656 struct sd *sd = (struct sd *) gspca_dev;
657
658 if (sd->sensor == SENSOR_PAS106)
659 Et_init1(gspca_dev);
660 else
661 Et_init2(gspca_dev);
662
663 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
664 et_video(gspca_dev, 1); /* video on */
665}
666
667static void sd_stopN(struct gspca_dev *gspca_dev)
668{
669 et_video(gspca_dev, 0); /* video off */
670}
671
672static void sd_stop0(struct gspca_dev *gspca_dev)
673{
674}
675
676static void sd_close(struct gspca_dev *gspca_dev)
677{
678}
679
680static void setbrightness(struct gspca_dev *gspca_dev)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683 int i;
684 __u8 brightness = sd->brightness;
685
686 for (i = 0; i < 4; i++)
687 reg_w_val(gspca_dev, ET_O_RED + i, brightness);
688}
689
690static void getbrightness(struct gspca_dev *gspca_dev)
691{
692 struct sd *sd = (struct sd *) gspca_dev;
693 int i;
694 int brightness = 0;
695
696 for (i = 0; i < 4; i++) {
697 reg_r(gspca_dev, ET_O_RED + i, 1);
698 brightness += gspca_dev->usb_buf[0];
699 }
700 sd->brightness = brightness >> 3;
701}
702
703static void setcontrast(struct gspca_dev *gspca_dev)
704{
705 struct sd *sd = (struct sd *) gspca_dev;
706 __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
707 __u8 contrast = sd->contrast;
708
709 memset(RGBG, contrast, sizeof(RGBG) - 2);
710 reg_w(gspca_dev, ET_G_RED, RGBG, 6);
711}
712
713static void getcontrast(struct gspca_dev *gspca_dev)
714{
715 struct sd *sd = (struct sd *) gspca_dev;
716 int i;
717 int contrast = 0;
718
719 for (i = 0; i < 4; i++) {
720 reg_r(gspca_dev, ET_G_RED + i, 1);
721 contrast += gspca_dev->usb_buf[0];
722 }
723 sd->contrast = contrast >> 2;
724}
725
726static __u8 Et_getgainG(struct gspca_dev *gspca_dev)
727{
728 struct sd *sd = (struct sd *) gspca_dev;
729
730 if (sd->sensor == SENSOR_PAS106) {
731 i2c_r(gspca_dev, PAS106_REG0e);
732 PDEBUG(D_CONF, "Etoms gain G %d", gspca_dev->usb_buf[0]);
733 return gspca_dev->usb_buf[0];
734 }
735 return 0x1f;
736}
737
738static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain)
739{
740 struct sd *sd = (struct sd *) gspca_dev;
741
742 if (sd->sensor == SENSOR_PAS106) {
743 __u8 i2cflags = 0x01;
744
745 i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
746 i2c_w(gspca_dev, PAS106_REG0e, &gain, 1, 1);
747 }
748}
749
750#define BLIMIT(bright) \
751 (__u8)((bright > 0x1f)?0x1f:((bright < 4)?3:bright))
752#define LIMIT(color) \
753 (unsigned char)((color > 0xff)?0xff:((color < 0)?0:color))
754
755static void setautogain(struct gspca_dev *gspca_dev)
756{
757 __u8 luma = 0;
758 __u8 luma_mean = 128;
759 __u8 luma_delta = 20;
760 __u8 spring = 4;
761 int Gbright = 0;
762 __u8 r, g, b;
763
764 Gbright = Et_getgainG(gspca_dev);
765 reg_r(gspca_dev, ET_LUMA_CENTER, 4);
766 g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1;
767 r = gspca_dev->usb_buf[1];
768 b = gspca_dev->usb_buf[2];
769 r = ((r << 8) - (r << 4) - (r << 3)) >> 10;
770 b = ((b << 7) >> 10);
771 g = ((g << 9) + (g << 7) + (g << 5)) >> 10;
772 luma = LIMIT(r + g + b);
773 PDEBUG(D_FRAM, "Etoms luma G %d", luma);
774 if (luma < luma_mean - luma_delta || luma > luma_mean + luma_delta) {
775 Gbright += (luma_mean - luma) >> spring;
776 Gbright = BLIMIT(Gbright);
777 PDEBUG(D_FRAM, "Etoms Gbright %d", Gbright);
778 Et_setgainG(gspca_dev, (__u8) Gbright);
779 }
780}
781
782#undef BLIMIT
783#undef LIMIT
784
785static void sd_pkt_scan(struct gspca_dev *gspca_dev,
786 struct gspca_frame *frame, /* target */
787 __u8 *data, /* isoc packet */
788 int len) /* iso packet length */
789{
790 struct sd *sd;
791 int seqframe;
792
793 seqframe = data[0] & 0x3f;
794 len = (int) (((data[0] & 0xc0) << 2) | data[1]);
795 if (seqframe == 0x3f) {
796 PDEBUG(D_FRAM,
797 "header packet found datalength %d !!", len);
798 PDEBUG(D_FRAM, "G %d R %d G %d B %d",
799 data[2], data[3], data[4], data[5]);
800 data += 30;
801 /* don't change datalength as the chips provided it */
802 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
803 data, 0);
804 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
805 sd = (struct sd *) gspca_dev;
806 if (sd->ag_cnt >= 0) {
807 if (--sd->ag_cnt < 0) {
808 sd->ag_cnt = AG_CNT_START;
809 setautogain(gspca_dev);
810 }
811 }
812 return;
813 }
814 if (len) {
815 data += 8;
816 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
817 } else { /* Drop Packet */
818 gspca_dev->last_packet_type = DISCARD_PACKET;
819 }
820}
821
822static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
823{
824 struct sd *sd = (struct sd *) gspca_dev;
825
826 sd->brightness = val;
827 if (gspca_dev->streaming)
828 setbrightness(gspca_dev);
829 return 0;
830}
831
832static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
833{
834 struct sd *sd = (struct sd *) gspca_dev;
835
836 getbrightness(gspca_dev);
837 *val = sd->brightness;
838 return 0;
839}
840
841static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
842{
843 struct sd *sd = (struct sd *) gspca_dev;
844
845 sd->contrast = val;
846 if (gspca_dev->streaming)
847 setcontrast(gspca_dev);
848 return 0;
849}
850
851static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
852{
853 struct sd *sd = (struct sd *) gspca_dev;
854
855 getcontrast(gspca_dev);
856 *val = sd->contrast;
857 return 0;
858}
859
860static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
861{
862 struct sd *sd = (struct sd *) gspca_dev;
863
864 sd->colors = val;
865 if (gspca_dev->streaming)
866 setcolors(gspca_dev);
867 return 0;
868}
869
870static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
871{
872 struct sd *sd = (struct sd *) gspca_dev;
873
874 getcolors(gspca_dev);
875 *val = sd->colors;
876 return 0;
877}
878
879static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
880{
881 struct sd *sd = (struct sd *) gspca_dev;
882
883 sd->autogain = val;
884 if (val)
885 sd->ag_cnt = AG_CNT_START;
886 else
887 sd->ag_cnt = -1;
888 return 0;
889}
890
891static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
892{
893 struct sd *sd = (struct sd *) gspca_dev;
894
895 *val = sd->autogain;
896 return 0;
897}
898
899/* sub-driver description */
900static struct sd_desc sd_desc = {
901 .name = MODULE_NAME,
902 .ctrls = sd_ctrls,
903 .nctrls = ARRAY_SIZE(sd_ctrls),
904 .config = sd_config,
905 .open = sd_open,
906 .start = sd_start,
907 .stopN = sd_stopN,
908 .stop0 = sd_stop0,
909 .close = sd_close,
910 .pkt_scan = sd_pkt_scan,
911};
912
913/* -- module initialisation -- */
914#define DVNM(name) .driver_info = (kernel_ulong_t) name
915static __devinitdata struct usb_device_id device_table[] = {
916#ifndef CONFIG_USB_ET61X251
917 {USB_DEVICE(0x102c, 0x6151), DVNM("Qcam Sangha CIF")},
918#endif
919 {USB_DEVICE(0x102c, 0x6251), DVNM("Qcam xxxxxx VGA")},
920 {}
921};
922
923MODULE_DEVICE_TABLE(usb, device_table);
924
925/* -- device connect -- */
926static int sd_probe(struct usb_interface *intf,
927 const struct usb_device_id *id)
928{
929 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
930 THIS_MODULE);
931}
932
933static struct usb_driver sd_driver = {
934 .name = MODULE_NAME,
935 .id_table = device_table,
936 .probe = sd_probe,
937 .disconnect = gspca_disconnect,
938};
939
940/* -- module insert / remove -- */
941static int __init sd_mod_init(void)
942{
943 if (usb_register(&sd_driver) < 0)
944 return -1;
945 PDEBUG(D_PROBE, "v%s registered", version);
946 return 0;
947}
948
949static void __exit sd_mod_exit(void)
950{
951 usb_deregister(&sd_driver);
952 PDEBUG(D_PROBE, "deregistered");
953}
954
955module_init(sd_mod_init);
956module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
new file mode 100644
index 000000000000..16e367cec760
--- /dev/null
+++ b/drivers/media/video/gspca/gspca.c
@@ -0,0 +1,1905 @@
1/*
2 * Main USB camera driver
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#define MODULE_NAME "gspca"
22
23#include <linux/init.h>
24#include <linux/fs.h>
25#include <linux/vmalloc.h>
26#include <linux/sched.h>
27#include <linux/slab.h>
28#include <linux/mm.h>
29#include <linux/string.h>
30#include <linux/pagemap.h>
31#include <linux/io.h>
32#include <asm/page.h>
33#include <linux/uaccess.h>
34#include <linux/jiffies.h>
35
36#include "gspca.h"
37
38/* global values */
39#define DEF_NURBS 2 /* default number of URBs */
40
41MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
42MODULE_DESCRIPTION("GSPCA USB Camera Driver");
43MODULE_LICENSE("GPL");
44
45#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
46static const char version[] = "2.1.7";
47
48static int video_nr = -1;
49
50#ifdef CONFIG_VIDEO_ADV_DEBUG
51int gspca_debug = D_ERR | D_PROBE;
52EXPORT_SYMBOL(gspca_debug);
53
54static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
55{
56 if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
57 PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
58 txt,
59 pixfmt & 0xff,
60 (pixfmt >> 8) & 0xff,
61 (pixfmt >> 16) & 0xff,
62 pixfmt >> 24,
63 w, h);
64 } else {
65 PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
66 txt,
67 pixfmt,
68 w, h);
69 }
70}
71#else
72#define PDEBUG_MODE(txt, pixfmt, w, h)
73#endif
74
75/* specific memory types - !! should different from V4L2_MEMORY_xxx */
76#define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */
77#define GSPCA_MEMORY_READ 7
78
79#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
80
81/*
82 * VMA operations.
83 */
84static void gspca_vm_open(struct vm_area_struct *vma)
85{
86 struct gspca_frame *frame = vma->vm_private_data;
87
88 frame->vma_use_count++;
89 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED;
90}
91
92static void gspca_vm_close(struct vm_area_struct *vma)
93{
94 struct gspca_frame *frame = vma->vm_private_data;
95
96 if (--frame->vma_use_count <= 0)
97 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED;
98}
99
100static struct vm_operations_struct gspca_vm_ops = {
101 .open = gspca_vm_open,
102 .close = gspca_vm_close,
103};
104
105/*
106 * fill a video frame from an URB and resubmit
107 */
108static void fill_frame(struct gspca_dev *gspca_dev,
109 struct urb *urb)
110{
111 struct gspca_frame *frame;
112 __u8 *data; /* address of data in the iso message */
113 int i, j, len, st;
114 cam_pkt_op pkt_scan;
115
116 if (urb->status != 0) {
117 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
118 return; /* disconnection ? */
119 }
120 pkt_scan = gspca_dev->sd_desc->pkt_scan;
121 for (i = 0; i < urb->number_of_packets; i++) {
122
123 /* check the availability of the frame buffer */
124 j = gspca_dev->fr_i;
125 j = gspca_dev->fr_queue[j];
126 frame = &gspca_dev->frame[j];
127 if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
128 != V4L2_BUF_FLAG_QUEUED) {
129 gspca_dev->last_packet_type = DISCARD_PACKET;
130 break;
131 }
132
133 /* check the packet status and length */
134 len = urb->iso_frame_desc[i].actual_length;
135 if (len == 0)
136 continue;
137 st = urb->iso_frame_desc[i].status;
138 if (st) {
139 PDEBUG(D_ERR,
140 "ISOC data error: [%d] len=%d, status=%d",
141 i, len, st);
142 gspca_dev->last_packet_type = DISCARD_PACKET;
143 continue;
144 }
145
146 /* let the packet be analyzed by the subdriver */
147 PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
148 i, urb->iso_frame_desc[i].offset, len);
149 data = (__u8 *) urb->transfer_buffer
150 + urb->iso_frame_desc[i].offset;
151 pkt_scan(gspca_dev, frame, data, len);
152 }
153
154 /* resubmit the URB */
155 urb->status = 0;
156 st = usb_submit_urb(urb, GFP_ATOMIC);
157 if (st < 0)
158 PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st);
159}
160
161/*
162 * ISOC message interrupt from the USB device
163 *
164 * Analyse each packet and call the subdriver for copy to the frame buffer.
165 */
166static void isoc_irq(struct urb *urb
167)
168{
169 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
170
171 PDEBUG(D_PACK, "isoc irq");
172 if (!gspca_dev->streaming)
173 return;
174 fill_frame(gspca_dev, urb);
175}
176
177/*
178 * add data to the current frame
179 *
180 * This function is called by the subdrivers at interrupt level.
181 *
182 * To build a frame, these ones must add
183 * - one FIRST_PACKET
184 * - 0 or many INTER_PACKETs
185 * - one LAST_PACKET
186 * DISCARD_PACKET invalidates the whole frame.
187 * On LAST_PACKET, a new frame is returned.
188 */
189struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
190 int packet_type,
191 struct gspca_frame *frame,
192 const __u8 *data,
193 int len)
194{
195 int i, j;
196
197 PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);
198
199 /* when start of a new frame, if the current frame buffer
200 * is not queued, discard the whole frame */
201 if (packet_type == FIRST_PACKET) {
202 if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
203 != V4L2_BUF_FLAG_QUEUED) {
204 gspca_dev->last_packet_type = DISCARD_PACKET;
205 return frame;
206 }
207 frame->data_end = frame->data;
208 jiffies_to_timeval(get_jiffies_64(),
209 &frame->v4l2_buf.timestamp);
210 frame->v4l2_buf.sequence = ++gspca_dev->sequence;
211 } else if (gspca_dev->last_packet_type == DISCARD_PACKET) {
212 return frame;
213 }
214
215 /* append the packet to the frame buffer */
216 if (len > 0) {
217 if (frame->data_end - frame->data + len
218 > frame->v4l2_buf.length) {
219 PDEBUG(D_ERR|D_PACK, "frame overflow %zd > %d",
220 frame->data_end - frame->data + len,
221 frame->v4l2_buf.length);
222 packet_type = DISCARD_PACKET;
223 } else {
224 memcpy(frame->data_end, data, len);
225 frame->data_end += len;
226 }
227 }
228 gspca_dev->last_packet_type = packet_type;
229
230 /* if last packet, wake the application and advance in the queue */
231 if (packet_type == LAST_PACKET) {
232 frame->v4l2_buf.bytesused = frame->data_end - frame->data;
233 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
234 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
235 atomic_inc(&gspca_dev->nevent);
236 wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
237 i = (gspca_dev->fr_i + 1) % gspca_dev->nframes;
238 gspca_dev->fr_i = i;
239 PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d",
240 frame->v4l2_buf.bytesused,
241 gspca_dev->fr_q,
242 i,
243 gspca_dev->fr_o);
244 j = gspca_dev->fr_queue[i];
245 frame = &gspca_dev->frame[j];
246 }
247 return frame;
248}
249EXPORT_SYMBOL(gspca_frame_add);
250
251static int gspca_is_compressed(__u32 format)
252{
253 switch (format) {
254 case V4L2_PIX_FMT_MJPEG:
255 case V4L2_PIX_FMT_JPEG:
256 case V4L2_PIX_FMT_SPCA561:
257 case V4L2_PIX_FMT_PAC207:
258 return 1;
259 }
260 return 0;
261}
262
263static void *rvmalloc(unsigned long size)
264{
265 void *mem;
266 unsigned long adr;
267
268/* size = PAGE_ALIGN(size); (already done) */
269 mem = vmalloc_32(size);
270 if (mem != NULL) {
271 adr = (unsigned long) mem;
272 while ((long) size > 0) {
273 SetPageReserved(vmalloc_to_page((void *) adr));
274 adr += PAGE_SIZE;
275 size -= PAGE_SIZE;
276 }
277 }
278 return mem;
279}
280
281static void rvfree(void *mem, long size)
282{
283 unsigned long adr;
284
285 adr = (unsigned long) mem;
286 while (size > 0) {
287 ClearPageReserved(vmalloc_to_page((void *) adr));
288 adr += PAGE_SIZE;
289 size -= PAGE_SIZE;
290 }
291 vfree(mem);
292}
293
294static int frame_alloc(struct gspca_dev *gspca_dev,
295 unsigned int count)
296{
297 struct gspca_frame *frame;
298 unsigned int frsz;
299 int i;
300
301 i = gspca_dev->curr_mode;
302 frsz = gspca_dev->cam.cam_mode[i].sizeimage;
303 PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
304 frsz = PAGE_ALIGN(frsz);
305 gspca_dev->frsz = frsz;
306 if (count > GSPCA_MAX_FRAMES)
307 count = GSPCA_MAX_FRAMES;
308 gspca_dev->frbuf = rvmalloc(frsz * count);
309 if (!gspca_dev->frbuf) {
310 err("frame alloc failed");
311 return -ENOMEM;
312 }
313 gspca_dev->nframes = count;
314 for (i = 0; i < count; i++) {
315 frame = &gspca_dev->frame[i];
316 frame->v4l2_buf.index = i;
317 frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
318 frame->v4l2_buf.flags = 0;
319 frame->v4l2_buf.field = V4L2_FIELD_NONE;
320 frame->v4l2_buf.length = frsz;
321 frame->v4l2_buf.memory = gspca_dev->memory;
322 frame->v4l2_buf.sequence = 0;
323 frame->data = frame->data_end =
324 gspca_dev->frbuf + i * frsz;
325 frame->v4l2_buf.m.offset = i * frsz;
326 }
327 gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
328 gspca_dev->last_packet_type = DISCARD_PACKET;
329 gspca_dev->sequence = 0;
330 atomic_set(&gspca_dev->nevent, 0);
331 return 0;
332}
333
334static void frame_free(struct gspca_dev *gspca_dev)
335{
336 int i;
337
338 PDEBUG(D_STREAM, "frame free");
339 if (gspca_dev->frbuf != NULL) {
340 rvfree(gspca_dev->frbuf,
341 gspca_dev->nframes * gspca_dev->frsz);
342 gspca_dev->frbuf = NULL;
343 for (i = 0; i < gspca_dev->nframes; i++)
344 gspca_dev->frame[i].data = NULL;
345 }
346 gspca_dev->nframes = 0;
347}
348
349static void destroy_urbs(struct gspca_dev *gspca_dev)
350{
351 struct urb *urb;
352 unsigned int i;
353
354 PDEBUG(D_STREAM, "kill transfer");
355 for (i = 0; i < MAX_NURBS; ++i) {
356 urb = gspca_dev->urb[i];
357 if (urb == NULL)
358 break;
359
360 gspca_dev->urb[i] = NULL;
361 usb_kill_urb(urb);
362 if (urb->transfer_buffer != NULL)
363 usb_buffer_free(gspca_dev->dev,
364 urb->transfer_buffer_length,
365 urb->transfer_buffer,
366 urb->transfer_dma);
367 usb_free_urb(urb);
368 }
369}
370
371/*
372 * search an input isochronous endpoint in an alternate setting
373 */
374static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
375 __u8 epaddr)
376{
377 struct usb_host_endpoint *ep;
378 int i, attr;
379
380 epaddr |= USB_DIR_IN;
381 for (i = 0; i < alt->desc.bNumEndpoints; i++) {
382 ep = &alt->endpoint[i];
383 if (ep->desc.bEndpointAddress == epaddr) {
384 attr = ep->desc.bmAttributes
385 & USB_ENDPOINT_XFERTYPE_MASK;
386 if (attr == USB_ENDPOINT_XFER_ISOC)
387 return ep;
388 break;
389 }
390 }
391 return NULL;
392}
393
394/*
395 * search an input isochronous endpoint
396 *
397 * The endpoint is defined by the subdriver.
398 * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
399 * This routine may be called many times when the bandwidth is too small
400 * (the bandwidth is checked on urb submit).
401 */
402struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
403{
404 struct usb_interface *intf;
405 struct usb_host_endpoint *ep;
406 int i, ret;
407
408 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
409 ep = NULL;
410 i = gspca_dev->alt; /* previous alt setting */
411 while (--i > 0) { /* alt 0 is unusable */
412 ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr);
413 if (ep)
414 break;
415 }
416 if (ep == NULL) {
417 err("no ISOC endpoint found");
418 return NULL;
419 }
420 PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x",
421 i, ep->desc.bEndpointAddress);
422 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
423 if (ret < 0) {
424 err("set interface err %d", ret);
425 return NULL;
426 }
427 gspca_dev->alt = i; /* memorize the current alt setting */
428 return ep;
429}
430
431/*
432 * create the isochronous URBs
433 */
434static int create_urbs(struct gspca_dev *gspca_dev,
435 struct usb_host_endpoint *ep)
436{
437 struct urb *urb;
438 int n, nurbs, i, psize, npkt, bsize;
439
440 /* calculate the packet size and the number of packets */
441 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
442
443 /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
444 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
445 npkt = ISO_MAX_SIZE / psize;
446 if (npkt > ISO_MAX_PKT)
447 npkt = ISO_MAX_PKT;
448 bsize = psize * npkt;
449 PDEBUG(D_STREAM,
450 "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
451 nurbs = DEF_NURBS;
452 gspca_dev->nurbs = nurbs;
453 for (n = 0; n < nurbs; n++) {
454 urb = usb_alloc_urb(npkt, GFP_KERNEL);
455 if (!urb) {
456 err("usb_alloc_urb failed");
457 return -ENOMEM;
458 }
459 urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
460 bsize,
461 GFP_KERNEL,
462 &urb->transfer_dma);
463
464 if (urb->transfer_buffer == NULL) {
465 usb_free_urb(urb);
466 destroy_urbs(gspca_dev);
467 err("usb_buffer_urb failed");
468 return -ENOMEM;
469 }
470 gspca_dev->urb[n] = urb;
471 urb->dev = gspca_dev->dev;
472 urb->context = gspca_dev;
473 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
474 ep->desc.bEndpointAddress);
475 urb->transfer_flags = URB_ISO_ASAP
476 | URB_NO_TRANSFER_DMA_MAP;
477 urb->interval = ep->desc.bInterval;
478 urb->complete = isoc_irq;
479 urb->number_of_packets = npkt;
480 urb->transfer_buffer_length = bsize;
481 for (i = 0; i < npkt; i++) {
482 urb->iso_frame_desc[i].length = psize;
483 urb->iso_frame_desc[i].offset = psize * i;
484 }
485 }
486 return 0;
487}
488
489/*
490 * start the USB transfer
491 */
492static int gspca_init_transfer(struct gspca_dev *gspca_dev)
493{
494 struct usb_host_endpoint *ep;
495 int n, ret;
496
497 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
498 return -ERESTARTSYS;
499
500 /* set the higher alternate setting and
501 * loop until urb submit succeeds */
502 gspca_dev->alt = gspca_dev->nbalt;
503 for (;;) {
504 PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
505 ep = get_isoc_ep(gspca_dev);
506 if (ep == NULL) {
507 ret = -EIO;
508 goto out;
509 }
510 ret = create_urbs(gspca_dev, ep);
511 if (ret < 0)
512 goto out;
513
514 /* start the cam */
515 gspca_dev->sd_desc->start(gspca_dev);
516 gspca_dev->streaming = 1;
517 atomic_set(&gspca_dev->nevent, 0);
518
519 /* submit the URBs */
520 for (n = 0; n < gspca_dev->nurbs; n++) {
521 ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL);
522 if (ret < 0) {
523 PDEBUG(D_ERR|D_STREAM,
524 "usb_submit_urb [%d] err %d", n, ret);
525 gspca_dev->streaming = 0;
526 destroy_urbs(gspca_dev);
527 if (ret == -ENOSPC)
528 break; /* try the previous alt */
529 goto out;
530 }
531 }
532 if (ret >= 0)
533 break;
534 }
535out:
536 mutex_unlock(&gspca_dev->usb_lock);
537 return ret;
538}
539
540static int gspca_set_alt0(struct gspca_dev *gspca_dev)
541{
542 int ret;
543
544 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
545 if (ret < 0)
546 PDEBUG(D_ERR|D_STREAM, "set interface 0 err %d", ret);
547 return ret;
548}
549
550/* Note both the queue and the usb lock should be hold when calling this */
551static void gspca_stream_off(struct gspca_dev *gspca_dev)
552{
553 gspca_dev->streaming = 0;
554 atomic_set(&gspca_dev->nevent, 0);
555 if (gspca_dev->present) {
556 gspca_dev->sd_desc->stopN(gspca_dev);
557 destroy_urbs(gspca_dev);
558 gspca_set_alt0(gspca_dev);
559 gspca_dev->sd_desc->stop0(gspca_dev);
560 PDEBUG(D_STREAM, "stream off OK");
561 }
562}
563
564static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
565{
566 int i;
567
568 i = gspca_dev->cam.nmodes - 1; /* take the highest mode */
569 gspca_dev->curr_mode = i;
570 gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
571 gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
572 gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat;
573}
574
575static int wxh_to_mode(struct gspca_dev *gspca_dev,
576 int width, int height)
577{
578 int i;
579
580 for (i = gspca_dev->cam.nmodes; --i > 0; ) {
581 if (width >= gspca_dev->cam.cam_mode[i].width
582 && height >= gspca_dev->cam.cam_mode[i].height)
583 break;
584 }
585 return i;
586}
587
588/*
589 * search a mode with the right pixel format
590 */
591static int gspca_get_mode(struct gspca_dev *gspca_dev,
592 int mode,
593 int pixfmt)
594{
595 int modeU, modeD;
596
597 modeU = modeD = mode;
598 while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) {
599 if (--modeD >= 0) {
600 if (gspca_dev->cam.cam_mode[modeD].pixelformat
601 == pixfmt)
602 return modeD;
603 }
604 if (++modeU < gspca_dev->cam.nmodes) {
605 if (gspca_dev->cam.cam_mode[modeU].pixelformat
606 == pixfmt)
607 return modeU;
608 }
609 }
610 return -EINVAL;
611}
612
613static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
614 struct v4l2_fmtdesc *fmtdesc)
615{
616 struct gspca_dev *gspca_dev = priv;
617 int i, j, index;
618 __u32 fmt_tb[8];
619
620 /* give an index to each format */
621 index = 0;
622 j = 0;
623 for (i = gspca_dev->cam.nmodes; --i >= 0; ) {
624 fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixelformat;
625 j = 0;
626 for (;;) {
627 if (fmt_tb[j] == fmt_tb[index])
628 break;
629 j++;
630 }
631 if (j == index) {
632 if (fmtdesc->index == index)
633 break; /* new format */
634 index++;
635 if (index >= sizeof fmt_tb / sizeof fmt_tb[0])
636 return -EINVAL;
637 }
638 }
639 if (i < 0)
640 return -EINVAL; /* no more format */
641
642 fmtdesc->pixelformat = fmt_tb[index];
643 if (gspca_is_compressed(fmt_tb[index]))
644 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
645 fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
646 fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
647 fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
648 fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
649 fmtdesc->description[3] = fmtdesc->pixelformat >> 24;
650 fmtdesc->description[4] = '\0';
651 return 0;
652}
653
654static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
655 struct v4l2_format *fmt)
656{
657 struct gspca_dev *gspca_dev = priv;
658 int mode;
659
660 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
661 return -EINVAL;
662 mode = gspca_dev->curr_mode;
663 memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode],
664 sizeof fmt->fmt.pix);
665 return 0;
666}
667
668static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
669 struct v4l2_format *fmt)
670{
671 int w, h, mode, mode2;
672
673 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
674 return -EINVAL;
675 w = fmt->fmt.pix.width;
676 h = fmt->fmt.pix.height;
677
678#ifdef CONFIG_VIDEO_ADV_DEBUG
679 if (gspca_debug & D_CONF)
680 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
681#endif
682 /* search the closest mode for width and height */
683 mode = wxh_to_mode(gspca_dev, w, h);
684
685 /* OK if right palette */
686 if (gspca_dev->cam.cam_mode[mode].pixelformat
687 != fmt->fmt.pix.pixelformat) {
688
689 /* else, search the closest mode with the same pixel format */
690 mode2 = gspca_get_mode(gspca_dev, mode,
691 fmt->fmt.pix.pixelformat);
692 if (mode2 >= 0)
693 mode = mode2;
694/* else
695 ; * no chance, return this mode */
696 }
697 memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode],
698 sizeof fmt->fmt.pix);
699 return mode; /* used when s_fmt */
700}
701
702static int vidioc_try_fmt_vid_cap(struct file *file,
703 void *priv,
704 struct v4l2_format *fmt)
705{
706 struct gspca_dev *gspca_dev = priv;
707 int ret;
708
709 ret = try_fmt_vid_cap(gspca_dev, fmt);
710 if (ret < 0)
711 return ret;
712 return 0;
713}
714
715static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
716 struct v4l2_format *fmt)
717{
718 struct gspca_dev *gspca_dev = priv;
719 int ret;
720
721 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
722 return -ERESTARTSYS;
723
724 ret = try_fmt_vid_cap(gspca_dev, fmt);
725 if (ret < 0)
726 goto out;
727
728 if (gspca_dev->nframes != 0
729 && fmt->fmt.pix.sizeimage > gspca_dev->frsz) {
730 ret = -EINVAL;
731 goto out;
732 }
733
734 if (ret == gspca_dev->curr_mode) {
735 ret = 0;
736 goto out; /* same mode */
737 }
738
739 if (gspca_dev->streaming) {
740 ret = -EBUSY;
741 goto out;
742 }
743 gspca_dev->width = fmt->fmt.pix.width;
744 gspca_dev->height = fmt->fmt.pix.height;
745 gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
746 gspca_dev->curr_mode = ret;
747
748 ret = 0;
749out:
750 mutex_unlock(&gspca_dev->queue_lock);
751 return ret;
752}
753
754static int dev_open(struct inode *inode, struct file *file)
755{
756 struct gspca_dev *gspca_dev;
757 int ret;
758
759 PDEBUG(D_STREAM, "%s open", current->comm);
760 gspca_dev = (struct gspca_dev *) video_devdata(file);
761 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
762 return -ERESTARTSYS;
763 if (!gspca_dev->present) {
764 ret = -ENODEV;
765 goto out;
766 }
767
768 /* if not done yet, initialize the sensor */
769 if (gspca_dev->users == 0) {
770 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
771 ret = -ERESTARTSYS;
772 goto out;
773 }
774 ret = gspca_dev->sd_desc->open(gspca_dev);
775 mutex_unlock(&gspca_dev->usb_lock);
776 if (ret != 0) {
777 PDEBUG(D_ERR|D_CONF, "init device failed %d", ret);
778 goto out;
779 }
780 } else if (gspca_dev->users > 4) { /* (arbitrary value) */
781 ret = -EBUSY;
782 goto out;
783 }
784 gspca_dev->users++;
785 file->private_data = gspca_dev;
786#ifdef CONFIG_VIDEO_ADV_DEBUG
787 /* activate the v4l2 debug */
788 if (gspca_debug & D_V4L2)
789 gspca_dev->vdev.debug |= 3;
790 else
791 gspca_dev->vdev.debug &= ~3;
792#endif
793out:
794 mutex_unlock(&gspca_dev->queue_lock);
795 if (ret != 0)
796 PDEBUG(D_ERR|D_STREAM, "open failed err %d", ret);
797 else
798 PDEBUG(D_STREAM, "open done");
799 return ret;
800}
801
802static int dev_close(struct inode *inode, struct file *file)
803{
804 struct gspca_dev *gspca_dev = file->private_data;
805
806 PDEBUG(D_STREAM, "%s close", current->comm);
807 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
808 return -ERESTARTSYS;
809 gspca_dev->users--;
810
811 /* if the file did the capture, free the streaming resources */
812 if (gspca_dev->capt_file == file) {
813 mutex_lock(&gspca_dev->usb_lock);
814 if (gspca_dev->streaming)
815 gspca_stream_off(gspca_dev);
816 gspca_dev->sd_desc->close(gspca_dev);
817 mutex_unlock(&gspca_dev->usb_lock);
818 frame_free(gspca_dev);
819 gspca_dev->capt_file = NULL;
820 gspca_dev->memory = GSPCA_MEMORY_NO;
821 }
822 file->private_data = NULL;
823 mutex_unlock(&gspca_dev->queue_lock);
824 PDEBUG(D_STREAM, "close done");
825 return 0;
826}
827
828static int vidioc_querycap(struct file *file, void *priv,
829 struct v4l2_capability *cap)
830{
831 struct gspca_dev *gspca_dev = priv;
832
833 memset(cap, 0, sizeof *cap);
834 strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
835 strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card);
836 strncpy(cap->bus_info, gspca_dev->dev->bus->bus_name,
837 sizeof cap->bus_info);
838 cap->version = DRIVER_VERSION_NUMBER;
839 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
840 | V4L2_CAP_STREAMING
841 | V4L2_CAP_READWRITE;
842 return 0;
843}
844
845/* the use of V4L2_CTRL_FLAG_NEXT_CTRL asks for the controls to be sorted */
846static int vidioc_queryctrl(struct file *file, void *priv,
847 struct v4l2_queryctrl *q_ctrl)
848{
849 struct gspca_dev *gspca_dev = priv;
850 int i;
851 u32 id;
852
853 id = q_ctrl->id;
854 if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
855 id &= V4L2_CTRL_ID_MASK;
856 id++;
857 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
858 if (id >= gspca_dev->sd_desc->ctrls[i].qctrl.id) {
859 memcpy(q_ctrl,
860 &gspca_dev->sd_desc->ctrls[i].qctrl,
861 sizeof *q_ctrl);
862 return 0;
863 }
864 }
865 return -EINVAL;
866 }
867 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
868 if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
869 memcpy(q_ctrl,
870 &gspca_dev->sd_desc->ctrls[i].qctrl,
871 sizeof *q_ctrl);
872 return 0;
873 }
874 }
875 if (id >= V4L2_CID_BASE
876 && id <= V4L2_CID_LASTP1) {
877 q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
878 return 0;
879 }
880 return -EINVAL;
881}
882
883static int vidioc_s_ctrl(struct file *file, void *priv,
884 struct v4l2_control *ctrl)
885{
886 struct gspca_dev *gspca_dev = priv;
887 const struct ctrl *ctrls;
888 int i, ret;
889
890 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
891 i < gspca_dev->sd_desc->nctrls;
892 i++, ctrls++) {
893 if (ctrl->id != ctrls->qctrl.id)
894 continue;
895 if (ctrl->value < ctrls->qctrl.minimum
896 && ctrl->value > ctrls->qctrl.maximum)
897 return -ERANGE;
898 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
899 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
900 return -ERESTARTSYS;
901 ret = ctrls->set(gspca_dev, ctrl->value);
902 mutex_unlock(&gspca_dev->usb_lock);
903 return ret;
904 }
905 return -EINVAL;
906}
907
908static int vidioc_g_ctrl(struct file *file, void *priv,
909 struct v4l2_control *ctrl)
910{
911 struct gspca_dev *gspca_dev = priv;
912
913 const struct ctrl *ctrls;
914 int i, ret;
915
916 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
917 i < gspca_dev->sd_desc->nctrls;
918 i++, ctrls++) {
919 if (ctrl->id != ctrls->qctrl.id)
920 continue;
921 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
922 return -ERESTARTSYS;
923 ret = ctrls->get(gspca_dev, &ctrl->value);
924 mutex_unlock(&gspca_dev->usb_lock);
925 return ret;
926 }
927 return -EINVAL;
928}
929
930static int vidioc_querymenu(struct file *file, void *priv,
931 struct v4l2_querymenu *qmenu)
932{
933 struct gspca_dev *gspca_dev = priv;
934
935 if (!gspca_dev->sd_desc->querymenu)
936 return -EINVAL;
937 return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
938}
939
940static int vidioc_enum_input(struct file *file, void *priv,
941 struct v4l2_input *input)
942{
943 struct gspca_dev *gspca_dev = priv;
944
945 if (input->index != 0)
946 return -EINVAL;
947 memset(input, 0, sizeof *input);
948 input->type = V4L2_INPUT_TYPE_CAMERA;
949 strncpy(input->name, gspca_dev->sd_desc->name,
950 sizeof input->name);
951 return 0;
952}
953
954static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
955{
956 *i = 0;
957 return 0;
958}
959
960static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
961{
962 if (i > 0)
963 return -EINVAL;
964 return (0);
965}
966
967static int vidioc_reqbufs(struct file *file, void *priv,
968 struct v4l2_requestbuffers *rb)
969{
970 struct gspca_dev *gspca_dev = priv;
971 int i, ret = 0;
972
973 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
974 return -EINVAL;
975 switch (rb->memory) {
976 case GSPCA_MEMORY_READ: /* (internal call) */
977 case V4L2_MEMORY_MMAP:
978 case V4L2_MEMORY_USERPTR:
979 break;
980 default:
981 return -EINVAL;
982 }
983 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
984 return -ERESTARTSYS;
985
986 if (gspca_dev->memory != GSPCA_MEMORY_NO
987 && gspca_dev->memory != rb->memory) {
988 ret = -EBUSY;
989 goto out;
990 }
991
992 /* only one file may do the capture */
993 if (gspca_dev->capt_file != NULL
994 && gspca_dev->capt_file != file) {
995 ret = -EBUSY;
996 goto out;
997 }
998
999 /* if allocated, the buffers must not be mapped */
1000 for (i = 0; i < gspca_dev->nframes; i++) {
1001 if (gspca_dev->frame[i].vma_use_count) {
1002 ret = -EBUSY;
1003 goto out;
1004 }
1005 }
1006
1007 /* stop streaming */
1008 if (gspca_dev->streaming) {
1009 mutex_lock(&gspca_dev->usb_lock);
1010 gspca_stream_off(gspca_dev);
1011 mutex_unlock(&gspca_dev->usb_lock);
1012 }
1013
1014 /* free the previous allocated buffers, if any */
1015 if (gspca_dev->nframes != 0) {
1016 frame_free(gspca_dev);
1017 gspca_dev->capt_file = NULL;
1018 }
1019 if (rb->count == 0) /* unrequest */
1020 goto out;
1021 gspca_dev->memory = rb->memory;
1022 ret = frame_alloc(gspca_dev, rb->count);
1023 if (ret == 0) {
1024 rb->count = gspca_dev->nframes;
1025 gspca_dev->capt_file = file;
1026 }
1027out:
1028 mutex_unlock(&gspca_dev->queue_lock);
1029 PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
1030 return ret;
1031}
1032
1033static int vidioc_querybuf(struct file *file, void *priv,
1034 struct v4l2_buffer *v4l2_buf)
1035{
1036 struct gspca_dev *gspca_dev = priv;
1037 struct gspca_frame *frame;
1038
1039 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1040 || v4l2_buf->index < 0
1041 || v4l2_buf->index >= gspca_dev->nframes)
1042 return -EINVAL;
1043
1044 frame = &gspca_dev->frame[v4l2_buf->index];
1045 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1046 return 0;
1047}
1048
1049static int vidioc_streamon(struct file *file, void *priv,
1050 enum v4l2_buf_type buf_type)
1051{
1052 struct gspca_dev *gspca_dev = priv;
1053 int ret;
1054
1055 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1056 return -EINVAL;
1057 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1058 return -ERESTARTSYS;
1059 if (!gspca_dev->present) {
1060 ret = -ENODEV;
1061 goto out;
1062 }
1063 if (gspca_dev->nframes == 0) {
1064 ret = -EINVAL;
1065 goto out;
1066 }
1067 if (!gspca_dev->streaming) {
1068 ret = gspca_init_transfer(gspca_dev);
1069 if (ret < 0)
1070 goto out;
1071 }
1072#ifdef CONFIG_VIDEO_ADV_DEBUG
1073 if (gspca_debug & D_STREAM) {
1074 PDEBUG_MODE("stream on OK",
1075 gspca_dev->pixfmt,
1076 gspca_dev->width,
1077 gspca_dev->height);
1078 }
1079#endif
1080 ret = 0;
1081out:
1082 mutex_unlock(&gspca_dev->queue_lock);
1083 return ret;
1084}
1085
1086static int vidioc_streamoff(struct file *file, void *priv,
1087 enum v4l2_buf_type buf_type)
1088{
1089 struct gspca_dev *gspca_dev = priv;
1090 int i, ret;
1091
1092 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1093 return -EINVAL;
1094 if (!gspca_dev->streaming)
1095 return 0;
1096 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1097 return -ERESTARTSYS;
1098
1099 /* stop streaming */
1100 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
1101 ret = -ERESTARTSYS;
1102 goto out;
1103 }
1104 gspca_stream_off(gspca_dev);
1105 mutex_unlock(&gspca_dev->usb_lock);
1106
1107 /* empty the application queues */
1108 for (i = 0; i < gspca_dev->nframes; i++)
1109 gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS;
1110 gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
1111 gspca_dev->last_packet_type = DISCARD_PACKET;
1112 gspca_dev->sequence = 0;
1113 atomic_set(&gspca_dev->nevent, 0);
1114 ret = 0;
1115out:
1116 mutex_unlock(&gspca_dev->queue_lock);
1117 return ret;
1118}
1119
1120static int vidioc_g_jpegcomp(struct file *file, void *priv,
1121 struct v4l2_jpegcompression *jpegcomp)
1122{
1123 struct gspca_dev *gspca_dev = priv;
1124 int ret;
1125
1126 if (!gspca_dev->sd_desc->get_jcomp)
1127 return -EINVAL;
1128 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1129 return -ERESTARTSYS;
1130 ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
1131 mutex_unlock(&gspca_dev->usb_lock);
1132 return ret;
1133}
1134
1135static int vidioc_s_jpegcomp(struct file *file, void *priv,
1136 struct v4l2_jpegcompression *jpegcomp)
1137{
1138 struct gspca_dev *gspca_dev = priv;
1139 int ret;
1140
1141 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1142 return -ERESTARTSYS;
1143 if (!gspca_dev->sd_desc->set_jcomp)
1144 return -EINVAL;
1145 ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
1146 mutex_unlock(&gspca_dev->usb_lock);
1147 return ret;
1148}
1149
1150static int vidioc_g_parm(struct file *filp, void *priv,
1151 struct v4l2_streamparm *parm)
1152{
1153 struct gspca_dev *gspca_dev = priv;
1154
1155 memset(parm, 0, sizeof *parm);
1156 parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1157 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1158 return 0;
1159}
1160
1161static int vidioc_s_parm(struct file *filp, void *priv,
1162 struct v4l2_streamparm *parm)
1163{
1164 struct gspca_dev *gspca_dev = priv;
1165 int n;
1166
1167 n = parm->parm.capture.readbuffers;
1168 if (n == 0 || n > GSPCA_MAX_FRAMES)
1169 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1170 else
1171 gspca_dev->nbufread = n;
1172 return 0;
1173}
1174
1175static int vidioc_s_std(struct file *filp, void *priv,
1176 v4l2_std_id *parm)
1177{
1178 return 0;
1179}
1180
1181#ifdef CONFIG_VIDEO_V4L1_COMPAT
1182static int vidiocgmbuf(struct file *file, void *priv,
1183 struct video_mbuf *mbuf)
1184{
1185 struct gspca_dev *gspca_dev = file->private_data;
1186 int i;
1187
1188 PDEBUG(D_STREAM, "cgmbuf");
1189 if (gspca_dev->nframes == 0) {
1190 int ret;
1191
1192 {
1193 struct v4l2_format fmt;
1194
1195 memset(&fmt, 0, sizeof fmt);
1196 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1197 i = gspca_dev->cam.nmodes - 1; /* highest mode */
1198 fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width;
1199 fmt.fmt.pix.height = gspca_dev->cam.cam_mode[i].height;
1200 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
1201 ret = vidioc_s_fmt_vid_cap(file, priv, &fmt);
1202 if (ret != 0)
1203 return ret;
1204 }
1205 {
1206 struct v4l2_requestbuffers rb;
1207
1208 memset(&rb, 0, sizeof rb);
1209 rb.count = 4;
1210 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1211 rb.memory = V4L2_MEMORY_MMAP;
1212 ret = vidioc_reqbufs(file, priv, &rb);
1213 if (ret != 0)
1214 return ret;
1215 }
1216 }
1217 mbuf->frames = gspca_dev->nframes;
1218 mbuf->size = gspca_dev->frsz * gspca_dev->nframes;
1219 for (i = 0; i < mbuf->frames; i++)
1220 mbuf->offsets[i] = gspca_dev->frame[i].v4l2_buf.m.offset;
1221 return 0;
1222}
1223#endif
1224
1225static int dev_mmap(struct file *file, struct vm_area_struct *vma)
1226{
1227 struct gspca_dev *gspca_dev = file->private_data;
1228 struct gspca_frame *frame;
1229 struct page *page;
1230 unsigned long addr, start, size;
1231 int i, ret;
1232
1233 start = vma->vm_start;
1234 size = vma->vm_end - vma->vm_start;
1235 PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);
1236
1237 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1238 return -ERESTARTSYS;
1239 if (!gspca_dev->present) {
1240 ret = -ENODEV;
1241 goto out;
1242 }
1243 if (gspca_dev->capt_file != file) {
1244 ret = -EINVAL;
1245 goto out;
1246 }
1247
1248 frame = NULL;
1249 for (i = 0; i < gspca_dev->nframes; ++i) {
1250 if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) {
1251 PDEBUG(D_STREAM, "mmap bad memory type");
1252 break;
1253 }
1254 if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT)
1255 == vma->vm_pgoff) {
1256 frame = &gspca_dev->frame[i];
1257 break;
1258 }
1259 }
1260 if (frame == NULL) {
1261 PDEBUG(D_STREAM, "mmap no frame buffer found");
1262 ret = -EINVAL;
1263 goto out;
1264 }
1265#ifdef CONFIG_VIDEO_V4L1_COMPAT
1266 /* v4l1 maps all the buffers */
1267 if (i != 0
1268 || size != frame->v4l2_buf.length * gspca_dev->nframes)
1269#endif
1270 if (size != frame->v4l2_buf.length) {
1271 PDEBUG(D_STREAM, "mmap bad size");
1272 ret = -EINVAL;
1273 goto out;
1274 }
1275
1276 /*
1277 * - VM_IO marks the area as being a mmaped region for I/O to a
1278 * device. It also prevents the region from being core dumped.
1279 */
1280 vma->vm_flags |= VM_IO;
1281
1282 addr = (unsigned long) frame->data;
1283 while (size > 0) {
1284 page = vmalloc_to_page((void *) addr);
1285 ret = vm_insert_page(vma, start, page);
1286 if (ret < 0)
1287 goto out;
1288 start += PAGE_SIZE;
1289 addr += PAGE_SIZE;
1290 size -= PAGE_SIZE;
1291 }
1292
1293 vma->vm_ops = &gspca_vm_ops;
1294 vma->vm_private_data = frame;
1295 gspca_vm_open(vma);
1296 ret = 0;
1297out:
1298 mutex_unlock(&gspca_dev->queue_lock);
1299 return ret;
1300}
1301
1302/*
1303 * wait for a video frame
1304 *
1305 * If a frame is ready, its index is returned.
1306 */
1307static int frame_wait(struct gspca_dev *gspca_dev,
1308 int nonblock_ing)
1309{
1310 struct gspca_frame *frame;
1311 int i, j, ret;
1312
1313 /* check if a frame is ready */
1314 i = gspca_dev->fr_o;
1315 j = gspca_dev->fr_queue[i];
1316 frame = &gspca_dev->frame[j];
1317 if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) {
1318 atomic_dec(&gspca_dev->nevent);
1319 goto ok;
1320 }
1321 if (nonblock_ing) /* no frame yet */
1322 return -EAGAIN;
1323
1324 /* wait till a frame is ready */
1325 for (;;) {
1326 ret = wait_event_interruptible_timeout(gspca_dev->wq,
1327 atomic_read(&gspca_dev->nevent) > 0,
1328 msecs_to_jiffies(3000));
1329 if (ret <= 0) {
1330 if (ret < 0)
1331 return ret; /* interrupt */
1332 return -EIO; /* timeout */
1333 }
1334 atomic_dec(&gspca_dev->nevent);
1335 if (!gspca_dev->streaming || !gspca_dev->present)
1336 return -EIO;
1337 i = gspca_dev->fr_o;
1338 j = gspca_dev->fr_queue[i];
1339 frame = &gspca_dev->frame[j];
1340 if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1341 break;
1342 }
1343ok:
1344 gspca_dev->fr_o = (i + 1) % gspca_dev->nframes;
1345 PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d",
1346 gspca_dev->fr_q,
1347 gspca_dev->fr_i,
1348 gspca_dev->fr_o);
1349
1350 if (gspca_dev->sd_desc->dq_callback) {
1351 mutex_lock(&gspca_dev->usb_lock);
1352 gspca_dev->sd_desc->dq_callback(gspca_dev);
1353 mutex_unlock(&gspca_dev->usb_lock);
1354 }
1355 return j;
1356}
1357
1358/*
1359 * dequeue a video buffer
1360 *
1361 * If nonblock_ing is false, block until a buffer is available.
1362 */
1363static int vidioc_dqbuf(struct file *file, void *priv,
1364 struct v4l2_buffer *v4l2_buf)
1365{
1366 struct gspca_dev *gspca_dev = priv;
1367 struct gspca_frame *frame;
1368 int i, ret;
1369
1370 PDEBUG(D_FRAM, "dqbuf");
1371 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1372 return -EINVAL;
1373 if (v4l2_buf->memory != gspca_dev->memory)
1374 return -EINVAL;
1375
1376 /* if not streaming, be sure the application will not loop forever */
1377 if (!(file->f_flags & O_NONBLOCK)
1378 && !gspca_dev->streaming && gspca_dev->users == 1)
1379 return -EINVAL;
1380
1381 /* only the capturing file may dequeue */
1382 if (gspca_dev->capt_file != file)
1383 return -EINVAL;
1384
1385 /* only one dequeue / read at a time */
1386 if (mutex_lock_interruptible(&gspca_dev->read_lock))
1387 return -ERESTARTSYS;
1388
1389 ret = frame_wait(gspca_dev, file->f_flags & O_NONBLOCK);
1390 if (ret < 0)
1391 goto out;
1392 i = ret; /* frame index */
1393 frame = &gspca_dev->frame[i];
1394 if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
1395 if (copy_to_user((__u8 *) frame->v4l2_buf.m.userptr,
1396 frame->data,
1397 frame->v4l2_buf.bytesused)) {
1398 PDEBUG(D_ERR|D_STREAM,
1399 "dqbuf cp to user failed");
1400 ret = -EFAULT;
1401 goto out;
1402 }
1403 }
1404 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
1405 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1406 PDEBUG(D_FRAM, "dqbuf %d", i);
1407 ret = 0;
1408out:
1409 mutex_unlock(&gspca_dev->read_lock);
1410 return ret;
1411}
1412
1413/*
1414 * queue a video buffer
1415 *
1416 * Attempting to queue a buffer that has already been
1417 * queued will return -EINVAL.
1418 */
1419static int vidioc_qbuf(struct file *file, void *priv,
1420 struct v4l2_buffer *v4l2_buf)
1421{
1422 struct gspca_dev *gspca_dev = priv;
1423 struct gspca_frame *frame;
1424 int i, index, ret;
1425
1426 PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
1427 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1428 return -EINVAL;
1429
1430 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1431 return -ERESTARTSYS;
1432
1433 index = v4l2_buf->index;
1434 if ((unsigned) index >= gspca_dev->nframes) {
1435 PDEBUG(D_FRAM,
1436 "qbuf idx %d >= %d", index, gspca_dev->nframes);
1437 ret = -EINVAL;
1438 goto out;
1439 }
1440 if (v4l2_buf->memory != gspca_dev->memory) {
1441 PDEBUG(D_FRAM, "qbuf bad memory type");
1442 ret = -EINVAL;
1443 goto out;
1444 }
1445
1446 frame = &gspca_dev->frame[index];
1447 if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
1448 PDEBUG(D_FRAM, "qbuf bad state");
1449 ret = -EINVAL;
1450 goto out;
1451 }
1452
1453 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
1454/* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */
1455
1456 if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
1457 frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
1458 frame->v4l2_buf.length = v4l2_buf->length;
1459 }
1460
1461 /* put the buffer in the 'queued' queue */
1462 i = gspca_dev->fr_q;
1463 gspca_dev->fr_queue[i] = index;
1464 gspca_dev->fr_q = (i + 1) % gspca_dev->nframes;
1465 PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d",
1466 gspca_dev->fr_q,
1467 gspca_dev->fr_i,
1468 gspca_dev->fr_o);
1469
1470 v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
1471 v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE;
1472 ret = 0;
1473out:
1474 mutex_unlock(&gspca_dev->queue_lock);
1475 return ret;
1476}
1477
1478/*
1479 * allocate the resources for read()
1480 */
1481static int read_alloc(struct gspca_dev *gspca_dev,
1482 struct file *file)
1483{
1484 struct v4l2_buffer v4l2_buf;
1485 int i, ret;
1486
1487 PDEBUG(D_STREAM, "read alloc");
1488 if (gspca_dev->nframes == 0) {
1489 struct v4l2_requestbuffers rb;
1490
1491 memset(&rb, 0, sizeof rb);
1492 rb.count = gspca_dev->nbufread;
1493 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1494 rb.memory = GSPCA_MEMORY_READ;
1495 ret = vidioc_reqbufs(file, gspca_dev, &rb);
1496 if (ret != 0) {
1497 PDEBUG(D_STREAM, "read reqbuf err %d", ret);
1498 return ret;
1499 }
1500 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1501 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1502 v4l2_buf.memory = GSPCA_MEMORY_READ;
1503 for (i = 0; i < gspca_dev->nbufread; i++) {
1504 v4l2_buf.index = i;
1505 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1506 if (ret != 0) {
1507 PDEBUG(D_STREAM, "read qbuf err: %d", ret);
1508 return ret;
1509 }
1510 }
1511 gspca_dev->memory = GSPCA_MEMORY_READ;
1512 }
1513
1514 /* start streaming */
1515 ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE);
1516 if (ret != 0)
1517 PDEBUG(D_STREAM, "read streamon err %d", ret);
1518 return ret;
1519}
1520
1521static unsigned int dev_poll(struct file *file, poll_table *wait)
1522{
1523 struct gspca_dev *gspca_dev = file->private_data;
1524 int i, ret;
1525
1526 PDEBUG(D_FRAM, "poll");
1527
1528 poll_wait(file, &gspca_dev->wq, wait);
1529 if (!gspca_dev->present)
1530 return POLLERR;
1531
1532 /* if reqbufs is not done, the user would use read() */
1533 if (gspca_dev->nframes == 0) {
1534 if (gspca_dev->memory != GSPCA_MEMORY_NO)
1535 return POLLERR; /* not the 1st time */
1536 ret = read_alloc(gspca_dev, file);
1537 if (ret != 0)
1538 return POLLERR;
1539 }
1540
1541 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
1542 return POLLERR;
1543 if (!gspca_dev->present) {
1544 ret = POLLERR;
1545 goto out;
1546 }
1547
1548 /* check the next incoming buffer */
1549 i = gspca_dev->fr_o;
1550 i = gspca_dev->fr_queue[i];
1551 if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1552 ret = POLLIN | POLLRDNORM; /* something to read */
1553 else
1554 ret = 0;
1555out:
1556 mutex_unlock(&gspca_dev->queue_lock);
1557 return ret;
1558}
1559
1560static ssize_t dev_read(struct file *file, char __user *data,
1561 size_t count, loff_t *ppos)
1562{
1563 struct gspca_dev *gspca_dev = file->private_data;
1564 struct gspca_frame *frame;
1565 struct v4l2_buffer v4l2_buf;
1566 struct timeval timestamp;
1567 int n, ret, ret2;
1568
1569 PDEBUG(D_FRAM, "read (%zd)", count);
1570 if (!gspca_dev->present)
1571 return -ENODEV;
1572 switch (gspca_dev->memory) {
1573 case GSPCA_MEMORY_NO: /* first time */
1574 ret = read_alloc(gspca_dev, file);
1575 if (ret != 0)
1576 return ret;
1577 break;
1578 case GSPCA_MEMORY_READ:
1579 if (gspca_dev->capt_file == file)
1580 break;
1581 /* fall thru */
1582 default:
1583 return -EINVAL;
1584 }
1585
1586 /* get a frame */
1587 jiffies_to_timeval(get_jiffies_64(), &timestamp);
1588 timestamp.tv_sec--;
1589 n = 2;
1590 for (;;) {
1591 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1592 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1593 v4l2_buf.memory = GSPCA_MEMORY_READ;
1594 ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf);
1595 if (ret != 0) {
1596 PDEBUG(D_STREAM, "read dqbuf err %d", ret);
1597 return ret;
1598 }
1599
1600 /* if the process slept for more than 1 second,
1601 * get anewer frame */
1602 frame = &gspca_dev->frame[v4l2_buf.index];
1603 if (--n < 0)
1604 break; /* avoid infinite loop */
1605 if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
1606 break;
1607 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1608 if (ret != 0) {
1609 PDEBUG(D_STREAM, "read qbuf err %d", ret);
1610 return ret;
1611 }
1612 }
1613
1614 /* copy the frame */
1615 if (count > frame->v4l2_buf.bytesused)
1616 count = frame->v4l2_buf.bytesused;
1617 ret = copy_to_user(data, frame->data, count);
1618 if (ret != 0) {
1619 PDEBUG(D_ERR|D_STREAM,
1620 "read cp to user lack %d / %zd", ret, count);
1621 ret = -EFAULT;
1622 goto out;
1623 }
1624 ret = count;
1625out:
1626 /* in each case, requeue the buffer */
1627 ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1628 if (ret2 != 0)
1629 return ret2;
1630 return ret;
1631}
1632
1633static void dev_release(struct video_device *vfd)
1634{
1635 /* nothing */
1636}
1637
1638static struct file_operations dev_fops = {
1639 .owner = THIS_MODULE,
1640 .open = dev_open,
1641 .release = dev_close,
1642 .read = dev_read,
1643 .mmap = dev_mmap,
1644 .ioctl = video_ioctl2,
1645#ifdef CONFIG_COMPAT
1646 .compat_ioctl = v4l_compat_ioctl32,
1647#endif
1648 .llseek = no_llseek,
1649 .poll = dev_poll,
1650};
1651
1652static struct video_device gspca_template = {
1653 .name = "gspca main driver",
1654 .type = VID_TYPE_CAPTURE,
1655 .fops = &dev_fops,
1656 .release = dev_release, /* mandatory */
1657 .minor = -1,
1658 .vidioc_querycap = vidioc_querycap,
1659 .vidioc_dqbuf = vidioc_dqbuf,
1660 .vidioc_qbuf = vidioc_qbuf,
1661 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1662 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1663 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1664 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1665 .vidioc_streamon = vidioc_streamon,
1666 .vidioc_queryctrl = vidioc_queryctrl,
1667 .vidioc_g_ctrl = vidioc_g_ctrl,
1668 .vidioc_s_ctrl = vidioc_s_ctrl,
1669 .vidioc_querymenu = vidioc_querymenu,
1670 .vidioc_enum_input = vidioc_enum_input,
1671 .vidioc_g_input = vidioc_g_input,
1672 .vidioc_s_input = vidioc_s_input,
1673 .vidioc_reqbufs = vidioc_reqbufs,
1674 .vidioc_querybuf = vidioc_querybuf,
1675 .vidioc_streamoff = vidioc_streamoff,
1676 .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
1677 .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
1678 .vidioc_g_parm = vidioc_g_parm,
1679 .vidioc_s_parm = vidioc_s_parm,
1680 .vidioc_s_std = vidioc_s_std,
1681#ifdef CONFIG_VIDEO_V4L1_COMPAT
1682 .vidiocgmbuf = vidiocgmbuf,
1683#endif
1684};
1685
1686/*
1687 * probe and create a new gspca device
1688 *
1689 * This function must be called by the sub-driver when it is
1690 * called for probing a new device.
1691 */
1692int gspca_dev_probe(struct usb_interface *intf,
1693 const struct usb_device_id *id,
1694 const struct sd_desc *sd_desc,
1695 int dev_size,
1696 struct module *module)
1697{
1698 struct usb_interface_descriptor *interface;
1699 struct gspca_dev *gspca_dev;
1700 struct usb_device *dev = interface_to_usbdev(intf);
1701 int ret;
1702
1703 PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
1704
1705 /* we don't handle multi-config cameras */
1706 if (dev->descriptor.bNumConfigurations != 1)
1707 return -ENODEV;
1708 interface = &intf->cur_altsetting->desc;
1709 if (interface->bInterfaceNumber > 0)
1710 return -ENODEV;
1711
1712 /* create the device */
1713 if (dev_size < sizeof *gspca_dev)
1714 dev_size = sizeof *gspca_dev;
1715 gspca_dev = kzalloc(dev_size, GFP_KERNEL);
1716 if (gspca_dev == NULL) {
1717 err("couldn't kzalloc gspca struct");
1718 return -EIO;
1719 }
1720 gspca_dev->dev = dev;
1721 gspca_dev->iface = interface->bInterfaceNumber;
1722 gspca_dev->nbalt = intf->num_altsetting;
1723 gspca_dev->sd_desc = sd_desc;
1724/* gspca_dev->users = 0; (done by kzalloc) */
1725 gspca_dev->nbufread = 2;
1726
1727 /* configure the subdriver */
1728 ret = gspca_dev->sd_desc->config(gspca_dev, id);
1729 if (ret < 0)
1730 goto out;
1731 ret = gspca_set_alt0(gspca_dev);
1732 if (ret < 0)
1733 goto out;
1734 gspca_set_default_mode(gspca_dev);
1735
1736 mutex_init(&gspca_dev->usb_lock);
1737 mutex_init(&gspca_dev->read_lock);
1738 mutex_init(&gspca_dev->queue_lock);
1739 init_waitqueue_head(&gspca_dev->wq);
1740
1741 /* init video stuff */
1742 memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
1743 gspca_dev->vdev.dev = &dev->dev;
1744 memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops);
1745 gspca_dev->vdev.fops = &gspca_dev->fops;
1746 gspca_dev->fops.owner = module; /* module protection */
1747 ret = video_register_device(&gspca_dev->vdev,
1748 VFL_TYPE_GRABBER,
1749 video_nr);
1750 if (ret < 0) {
1751 err("video_register_device err %d", ret);
1752 goto out;
1753 }
1754
1755 gspca_dev->present = 1;
1756 usb_set_intfdata(intf, gspca_dev);
1757 PDEBUG(D_PROBE, "probe ok");
1758 return 0;
1759out:
1760 kfree(gspca_dev);
1761 return ret;
1762}
1763EXPORT_SYMBOL(gspca_dev_probe);
1764
1765/*
1766 * USB disconnection
1767 *
1768 * This function must be called by the sub-driver
1769 * when the device disconnects, after the specific resources are freed.
1770 */
1771void gspca_disconnect(struct usb_interface *intf)
1772{
1773 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
1774
1775 if (!gspca_dev)
1776 return;
1777 gspca_dev->present = 0;
1778 mutex_lock(&gspca_dev->queue_lock);
1779 mutex_lock(&gspca_dev->usb_lock);
1780 gspca_dev->streaming = 0;
1781 destroy_urbs(gspca_dev);
1782 mutex_unlock(&gspca_dev->usb_lock);
1783 mutex_unlock(&gspca_dev->queue_lock);
1784 while (gspca_dev->users != 0) { /* wait until fully closed */
1785 atomic_inc(&gspca_dev->nevent);
1786 wake_up_interruptible(&gspca_dev->wq); /* wake processes */
1787 schedule();
1788 }
1789/* We don't want people trying to open up the device */
1790 video_unregister_device(&gspca_dev->vdev);
1791/* Free the memory */
1792 kfree(gspca_dev);
1793 PDEBUG(D_PROBE, "disconnect complete");
1794}
1795EXPORT_SYMBOL(gspca_disconnect);
1796
1797/* -- cam driver utility functions -- */
1798
1799/* auto gain and exposure algorithm based on the knee algorithm described here:
1800 http://ytse.tricolour.net/docs/LowLightOptimization.html
1801
1802 Returns 0 if no changes were made, 1 if the gain and or exposure settings
1803 where changed. */
1804int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
1805 int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee)
1806{
1807 int i, steps, gain, orig_gain, exposure, orig_exposure, autogain;
1808 const struct ctrl *gain_ctrl = NULL;
1809 const struct ctrl *exposure_ctrl = NULL;
1810 const struct ctrl *autogain_ctrl = NULL;
1811 int retval = 0;
1812
1813 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
1814 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
1815 gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
1816 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
1817 exposure_ctrl = &gspca_dev->sd_desc->ctrls[i];
1818 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_AUTOGAIN)
1819 autogain_ctrl = &gspca_dev->sd_desc->ctrls[i];
1820 }
1821 if (!gain_ctrl || !exposure_ctrl || !autogain_ctrl) {
1822 PDEBUG(D_ERR, "Error: gspca_auto_gain_n_exposure called "
1823 "on cam without (auto)gain/exposure");
1824 return 0;
1825 }
1826
1827 if (gain_ctrl->get(gspca_dev, &gain) ||
1828 exposure_ctrl->get(gspca_dev, &exposure) ||
1829 autogain_ctrl->get(gspca_dev, &autogain) || !autogain)
1830 return 0;
1831
1832 orig_gain = gain;
1833 orig_exposure = exposure;
1834
1835 /* If we are of a multiple of deadzone, do multiple steps to reach the
1836 desired lumination fast (with the risc of a slight overshoot) */
1837 steps = abs(desired_avg_lum - avg_lum) / deadzone;
1838
1839 PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d\n",
1840 avg_lum, desired_avg_lum, steps);
1841
1842 for (i = 0; i < steps; i++) {
1843 if (avg_lum > desired_avg_lum) {
1844 if (gain > gain_knee)
1845 gain--;
1846 else if (exposure > exposure_knee)
1847 exposure--;
1848 else if (gain > gain_ctrl->qctrl.default_value)
1849 gain--;
1850 else if (exposure > exposure_ctrl->qctrl.minimum)
1851 exposure--;
1852 else if (gain > gain_ctrl->qctrl.minimum)
1853 gain--;
1854 else
1855 break;
1856 } else {
1857 if (gain < gain_ctrl->qctrl.default_value)
1858 gain++;
1859 else if (exposure < exposure_knee)
1860 exposure++;
1861 else if (gain < gain_knee)
1862 gain++;
1863 else if (exposure < exposure_ctrl->qctrl.maximum)
1864 exposure++;
1865 else if (gain < gain_ctrl->qctrl.maximum)
1866 gain++;
1867 else
1868 break;
1869 }
1870 }
1871
1872 if (gain != orig_gain) {
1873 gain_ctrl->set(gspca_dev, gain);
1874 retval = 1;
1875 }
1876 if (exposure != orig_exposure) {
1877 exposure_ctrl->set(gspca_dev, exposure);
1878 retval = 1;
1879 }
1880
1881 return retval;
1882}
1883EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
1884
1885/* -- module insert / remove -- */
1886static int __init gspca_init(void)
1887{
1888 info("main v%s registered", version);
1889 return 0;
1890}
1891static void __exit gspca_exit(void)
1892{
1893 info("main deregistered");
1894}
1895
1896module_init(gspca_init);
1897module_exit(gspca_exit);
1898
1899#ifdef CONFIG_VIDEO_ADV_DEBUG
1900module_param_named(debug, gspca_debug, int, 0644);
1901MODULE_PARM_DESC(debug,
1902 "Debug (bit) 0x01:error 0x02:probe 0x04:config"
1903 " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout"
1904 " 0x0100: v4l2");
1905#endif
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
new file mode 100644
index 000000000000..3fd2c4eee204
--- /dev/null
+++ b/drivers/media/video/gspca/gspca.h
@@ -0,0 +1,176 @@
1#ifndef GSPCAV2_H
2#define GSPCAV2_H
3
4#include <linux/module.h>
5#include <linux/version.h>
6#include <linux/kernel.h>
7#include <linux/usb.h>
8#include <linux/videodev2.h>
9#include <media/v4l2-common.h>
10#include <linux/mutex.h>
11
12#ifdef CONFIG_VIDEO_ADV_DEBUG
13/* GSPCA our debug messages */
14extern int gspca_debug;
15#define PDEBUG(level, fmt, args...) \
16 do {\
17 if (gspca_debug & (level)) \
18 printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
19 } while (0)
20#define D_ERR 0x01
21#define D_PROBE 0x02
22#define D_CONF 0x04
23#define D_STREAM 0x08
24#define D_FRAM 0x10
25#define D_PACK 0x20
26#define D_USBI 0x40
27#define D_USBO 0x80
28#define D_V4L2 0x0100
29#else
30#define PDEBUG(level, fmt, args...)
31#endif
32#undef err
33#define err(fmt, args...) \
34 do {\
35 printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args); \
36 } while (0)
37#undef info
38#define info(fmt, args...) \
39 do {\
40 printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
41 } while (0)
42#undef warn
43#define warn(fmt, args...) \
44 do {\
45 printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args); \
46 } while (0)
47
48#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
49/* ISOC transfers */
50#define MAX_NURBS 16 /* max number of URBs */
51#define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */
52#define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */
53
54/* device information - set at probe time */
55struct cam {
56 char *dev_name;
57 struct v4l2_pix_format *cam_mode; /* size nmodes */
58 char nmodes;
59 __u8 epaddr;
60};
61
62struct gspca_dev;
63struct gspca_frame;
64
65/* subdriver operations */
66typedef int (*cam_op) (struct gspca_dev *);
67typedef void (*cam_v_op) (struct gspca_dev *);
68typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
69typedef int (*cam_jpg_op) (struct gspca_dev *,
70 struct v4l2_jpegcompression *);
71typedef int (*cam_qmnu_op) (struct gspca_dev *,
72 struct v4l2_querymenu *);
73typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
74 struct gspca_frame *frame,
75 __u8 *data,
76 int len);
77
78struct ctrl {
79 struct v4l2_queryctrl qctrl;
80 int (*set)(struct gspca_dev *, __s32);
81 int (*get)(struct gspca_dev *, __s32 *);
82};
83
84/* subdriver description */
85struct sd_desc {
86/* information */
87 const char *name; /* sub-driver name */
88/* controls */
89 const struct ctrl *ctrls;
90 int nctrls;
91/* operations */
92 cam_cf_op config; /* called on probe */
93 cam_op open; /* called on open */
94 cam_v_op start; /* called on stream on */
95 cam_v_op stopN; /* called on stream off - main alt */
96 cam_v_op stop0; /* called on stream off - alt 0 */
97 cam_v_op close; /* called on close */
98 cam_pkt_op pkt_scan;
99/* optional operations */
100 cam_v_op dq_callback; /* called when a frame has been dequeued */
101 cam_jpg_op get_jcomp;
102 cam_jpg_op set_jcomp;
103 cam_qmnu_op querymenu;
104};
105
106/* packet types when moving from iso buf to frame buf */
107#define DISCARD_PACKET 0
108#define FIRST_PACKET 1
109#define INTER_PACKET 2
110#define LAST_PACKET 3
111
112struct gspca_frame {
113 __u8 *data; /* frame buffer */
114 __u8 *data_end; /* end of frame while filling */
115 int vma_use_count;
116 struct v4l2_buffer v4l2_buf;
117};
118
119struct gspca_dev {
120 struct video_device vdev; /* !! must be the first item */
121 struct file_operations fops;
122 struct usb_device *dev;
123 struct file *capt_file; /* file doing video capture */
124
125 struct cam cam; /* device information */
126 const struct sd_desc *sd_desc; /* subdriver description */
127
128 __u8 usb_buf[8]; /* buffer for USB exchanges */
129 struct urb *urb[MAX_NURBS];
130
131 __u8 *frbuf; /* buffer for nframes */
132 struct gspca_frame frame[GSPCA_MAX_FRAMES];
133 __u32 frsz; /* frame size */
134 char nframes; /* number of frames */
135 char fr_i; /* frame being filled */
136 char fr_q; /* next frame to queue */
137 char fr_o; /* next frame to dequeue */
138 signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */
139 char last_packet_type;
140
141 __u8 iface; /* USB interface number */
142 __u8 alt; /* USB alternate setting */
143 __u8 curr_mode; /* current camera mode */
144 __u32 pixfmt; /* current mode parameters */
145 __u16 width;
146 __u16 height;
147
148 atomic_t nevent; /* number of frames done */
149 wait_queue_head_t wq; /* wait queue */
150 struct mutex usb_lock; /* usb exchange protection */
151 struct mutex read_lock; /* read protection */
152 struct mutex queue_lock; /* ISOC queue protection */
153 __u32 sequence; /* frame sequence number */
154 char streaming;
155 char users; /* number of opens */
156 char present; /* device connected */
157 char nbufread; /* number of buffers for read() */
158 char nurbs; /* number of allocated URBs */
159 char memory; /* memory type (V4L2_MEMORY_xxx) */
160 __u8 nbalt; /* number of USB alternate settings */
161};
162
163int gspca_dev_probe(struct usb_interface *intf,
164 const struct usb_device_id *id,
165 const struct sd_desc *sd_desc,
166 int dev_size,
167 struct module *module);
168void gspca_disconnect(struct usb_interface *intf);
169struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
170 int packet_type,
171 struct gspca_frame *frame,
172 const __u8 *data,
173 int len);
174int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
175 int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
176#endif /* GSPCAV2_H */
diff --git a/drivers/media/video/gspca/jpeg.h b/drivers/media/video/gspca/jpeg.h
new file mode 100644
index 000000000000..d823b47bd4e6
--- /dev/null
+++ b/drivers/media/video/gspca/jpeg.h
@@ -0,0 +1,301 @@
1#ifndef JPEG_H
2#define JPEG_H 1
3/*
4 * Insert a JPEG header at start of frame
5 *
6 * This module is used by the gspca subdrivers.
7 * A special case is done for Conexant webcams.
8 *
9 * Copyright (C) Jean-Francois Moine (http://moinejf.free.fr)
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27/* start of jpeg frame + quantization table */
28static const unsigned char quant[][0x88] = {
29/* index 0 - Q40*/
30 {
31 0xff, 0xd8, /* jpeg */
32 0xff, 0xdb, 0x00, 0x84, /* DQT */
330, /* quantization table part 1 */
34 20, 14, 15, 18, 15, 13, 20, 18, 16, 18, 23, 21, 20, 24, 30, 50,
35 33, 30, 28, 28, 30, 61, 44, 46, 36, 50, 73, 64, 76, 75, 71, 64,
36 70, 69, 80, 90, 115, 98, 80, 85, 109, 86, 69, 70, 100, 136, 101,
37 109,
38 119, 123, 129, 130, 129, 78, 96, 141, 151, 140, 125, 150, 115,
39 126, 129, 124,
401, /* quantization table part 2 */
41 21, 23, 23, 30, 26, 30, 59, 33, 33, 59, 124, 83, 70, 83, 124, 124,
42 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
43 124, 124, 124,
44 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
45 124, 124, 124,
46 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
47 124, 124, 124},
48/* index 1 - Q50 */
49 {
50 0xff, 0xd8,
51 0xff, 0xdb, 0x00, 0x84, /* DQT */
520,
53 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40,
54 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51,
55 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81, 87,
56 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92, 101,
57 103, 99,
581,
59 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99,
60 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
61 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
62 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99},
63/* index 2 Q60 */
64 {
65 0xff, 0xd8,
66 0xff, 0xdb, 0x00, 0x84, /* DQT */
670,
68 13, 9, 10, 11, 10, 8, 13, 11, 10, 11, 14, 14, 13, 15, 19, 32,
69 21, 19, 18, 18, 19, 39, 28, 30, 23, 32, 46, 41, 49, 48, 46, 41,
70 45, 44, 51, 58, 74, 62, 51, 54, 70, 55, 44, 45, 64, 87, 65, 70,
71 76, 78, 82, 83, 82, 50, 62, 90, 97, 90, 80, 96, 74, 81, 82, 79,
721,
73 14, 14, 14, 19, 17, 19, 38, 21, 21, 38, 79, 53, 45, 53, 79, 79,
74 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
75 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
76 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79},
77/* index 3 - Q70 */
78 {
79 0xff, 0xd8,
80 0xff, 0xdb, 0x00, 0x84, /* DQT */
810,
82 10, 7, 7, 8, 7, 6, 10, 8, 8, 8, 11, 10, 10, 11, 14, 24,
83 16, 14, 13, 13, 14, 29, 21, 22, 17, 24, 35, 31, 37, 36, 34, 31,
84 34, 33, 38, 43, 55, 47, 38, 41, 52, 41, 33, 34, 48, 65, 49, 52,
85 57, 59, 62, 62, 62, 37, 46, 68, 73, 67, 60, 72, 55, 61, 62, 59,
861,
87 10, 11, 11, 14, 13, 14, 28, 16, 16, 28, 59, 40, 34, 40, 59, 59,
88 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
89 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
90 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59},
91/* index 4 - Q80 */
92 {
93 0xff, 0xd8,
94 0xff, 0xdb, 0x00, 0x84, /* DQT */
950,
96 6, 4, 5, 6, 5, 4, 6, 6, 5, 6, 7, 7, 6, 8, 10, 16,
97 10, 10, 9, 9, 10, 20, 14, 15, 12, 16, 23, 20, 24, 24, 23, 20,
98 22, 22, 26, 29, 37, 31, 26, 27, 35, 28, 22, 22, 32, 44, 32, 35,
99 38, 39, 41, 42, 41, 25, 31, 45, 48, 45, 40, 48, 37, 40, 41, 40,
1001,
101 7, 7, 7, 10, 8, 10, 19, 10, 10, 19, 40, 26, 22, 26, 40, 40,
102 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
103 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
104 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40},
105/* index 5 - Q85 */
106 {
107 0xff, 0xd8,
108 0xff, 0xdb, 0x00, 0x84, /* DQT */
1090,
110 5, 3, 4, 4, 4, 3, 5, 4, 4, 4, 5, 5, 5, 6, 7, 12,
111 8, 7, 7, 7, 7, 15, 11, 11, 9, 12, 17, 15, 18, 18, 17, 15,
112 17, 17, 19, 22, 28, 23, 19, 20, 26, 21, 17, 17, 24, 33, 24, 26,
113 29, 29, 31, 31, 31, 19, 23, 34, 36, 34, 30, 36, 28, 30, 31, 30,
1141,
115 5, 5, 5, 7, 6, 7, 14, 8, 8, 14, 30, 20, 17, 20, 30, 30,
116 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
117 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
118 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},
119/* index 6 - 86 */
120{
121 0xff, 0xd8,
122 0xff, 0xdb, 0x00, 0x84, /* DQT */
1230,
124 0x04, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x04,
125 0x04, 0x04, 0x05, 0x05, 0x04, 0x05, 0x07, 0x0B,
126 0x07, 0x07, 0x06, 0x06, 0x07, 0x0E, 0x0A, 0x0A,
127 0x08, 0x0B, 0x10, 0x0E, 0x11, 0x11, 0x10, 0x0E,
128 0x10, 0x0F, 0x12, 0x14, 0x1A, 0x16, 0x12, 0x13,
129 0x18, 0x13, 0x0F, 0x10, 0x16, 0x1F, 0x17, 0x18,
130 0x1B, 0x1B, 0x1D, 0x1D, 0x1D, 0x11, 0x16, 0x20,
131 0x22, 0x1F, 0x1C, 0x22, 0x1A, 0x1C, 0x1D, 0x1C,
1321,
133 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0D, 0x07,
134 0x07, 0x0D, 0x1C, 0x12, 0x10, 0x12, 0x1C, 0x1C,
135 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
136 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
137 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
138 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
139 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
140 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
141 },
142/* index 7 - 88 */
143{
144 0xff, 0xd8,
145 0xff, 0xdb, 0x00, 0x84, /* DQT */
1460,
147 0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x04, 0x03,
148 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x06, 0x0A,
149 0x06, 0x06, 0x05, 0x05, 0x06, 0x0C, 0x08, 0x09,
150 0x07, 0x0A, 0x0E, 0x0C, 0x0F, 0x0E, 0x0E, 0x0C,
151 0x0D, 0x0D, 0x0F, 0x11, 0x16, 0x13, 0x0F, 0x10,
152 0x15, 0x11, 0x0D, 0x0D, 0x13, 0x1A, 0x13, 0x15,
153 0x17, 0x18, 0x19, 0x19, 0x19, 0x0F, 0x12, 0x1B,
154 0x1D, 0x1B, 0x18, 0x1D, 0x16, 0x18, 0x19, 0x18,
1551,
156 0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0B, 0x06,
157 0x06, 0x0B, 0x18, 0x10, 0x0D, 0x10, 0x18, 0x18,
158 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
159 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
160 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
161 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
162 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
163 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
164},
165/* index 8 - ?? */
166{
167 0xff, 0xd8,
168 0xff, 0xdb, 0x00, 0x84, /* DQT */
1690,
170 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
171 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x05,
172 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x04, 0x05,
173 0x04, 0x05, 0x07, 0x06, 0x08, 0x08, 0x07, 0x06,
174 0x07, 0x07, 0x08, 0x09, 0x0C, 0x0A, 0x08, 0x09,
175 0x0B, 0x09, 0x07, 0x07, 0x0A, 0x0E, 0x0A, 0x0B,
176 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x08, 0x0A, 0x0E,
177 0x0F, 0x0E, 0x0D, 0x0F, 0x0C, 0x0D, 0x0D, 0x0C,
1781,
179 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x06, 0x03,
180 0x03, 0x06, 0x0C, 0x08, 0x07, 0x08, 0x0C, 0x0C,
181 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
182 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
183 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
184 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
185 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
186 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C
187}
188};
189
190/* huffman table + start of SOF0 */
191static unsigned char huffman[] = {
192 0xff, 0xc4, 0x01, 0xa2,
193 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01,
194 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
196 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03,
197 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
198 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
199 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
200 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03,
201 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00,
202 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
203 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
204 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81,
205 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15,
206 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82,
207 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
208 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36,
209 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
210 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56,
211 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66,
212 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
213 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86,
214 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95,
215 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
216 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3,
217 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
218 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
219 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
220 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
221 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
222 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
223 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
224 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
225 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06,
226 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22,
227 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
228 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62,
229 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
230 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28,
231 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
232 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
233 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
234 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
235 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
236 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
237 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
238 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
239 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
240 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
241 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
242 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
243 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2,
244 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
245#ifdef CONEX_CAM
246/* the Conexant frames start with SOF0 */
247#else
248 0xff, 0xc0, 0x00, 0x11, /* SOF0 (start of frame 0 */
249 0x08, /* data precision */
250#endif
251};
252
253#ifndef CONEX_CAM
254/* variable part:
255 * 0x01, 0xe0, height
256 * 0x02, 0x80, width
257 * 0x03, component number
258 * 0x01,
259 * 0x21, samples Y
260 */
261
262/* end of header */
263static unsigned char eoh[] = {
264 0x00, /* quant Y */
265 0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */
266 0x03, 0x11, 0x01,
267
268 0xff, 0xda, 0x00, 0x0c, /* SOS (start of scan) */
269 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
270};
271#endif
272
273/* -- output the JPEG header -- */
274static void jpeg_put_header(struct gspca_dev *gspca_dev,
275 struct gspca_frame *frame,
276 int qindex,
277 int samplesY)
278{
279#ifndef CONEX_CAM
280 unsigned char tmpbuf[8];
281#endif
282
283 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
284 (unsigned char *) quant[qindex], sizeof quant[0]);
285 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
286 (unsigned char *) huffman, sizeof huffman);
287#ifndef CONEX_CAM
288 tmpbuf[0] = gspca_dev->height >> 8;
289 tmpbuf[1] = gspca_dev->height & 0xff;
290 tmpbuf[2] = gspca_dev->width >> 8;
291 tmpbuf[3] = gspca_dev->width & 0xff;
292 tmpbuf[4] = 0x03; /* component number */
293 tmpbuf[5] = 0x01; /* first component */
294 tmpbuf[6] = samplesY;
295 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
296 tmpbuf, 7);
297 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
298 eoh, sizeof eoh);
299#endif
300}
301#endif
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
new file mode 100644
index 000000000000..88c2b02f380a
--- /dev/null
+++ b/drivers/media/video/gspca/mars.c
@@ -0,0 +1,464 @@
1/*
2 * Mars-Semi MR97311A library
3 * Copyright (C) 2005 <bradlch@hotmail.com>
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "mars"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 char qindex;
39};
40
41/* V4L2 controls supported by the driver */
42static struct ctrl sd_ctrls[] = {
43};
44
45static struct v4l2_pix_format vga_mode[] = {
46 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
47 .bytesperline = 320,
48 .sizeimage = 320 * 240 * 3 / 8 + 589,
49 .colorspace = V4L2_COLORSPACE_JPEG,
50 .priv = 2},
51 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
52 .bytesperline = 640,
53 .sizeimage = 640 * 480 * 3 / 8 + 590,
54 .colorspace = V4L2_COLORSPACE_JPEG,
55 .priv = 1},
56};
57
58/* MI Register table //elvis */
59enum {
60 REG_HW_MI_0,
61 REG_HW_MI_1,
62 REG_HW_MI_2,
63 REG_HW_MI_3,
64 REG_HW_MI_4,
65 REG_HW_MI_5,
66 REG_HW_MI_6,
67 REG_HW_MI_7,
68 REG_HW_MI_9 = 0x09,
69 REG_HW_MI_B = 0x0B,
70 REG_HW_MI_C,
71 REG_HW_MI_D,
72 REG_HW_MI_1E = 0x1E,
73 REG_HW_MI_20 = 0x20,
74 REG_HW_MI_2B = 0x2B,
75 REG_HW_MI_2C,
76 REG_HW_MI_2D,
77 REG_HW_MI_2E,
78 REG_HW_MI_35 = 0x35,
79 REG_HW_MI_5F = 0x5f,
80 REG_HW_MI_60,
81 REG_HW_MI_61,
82 REG_HW_MI_62,
83 REG_HW_MI_63,
84 REG_HW_MI_64,
85 REG_HW_MI_F1 = 0xf1,
86 ATTR_TOTAL_MI_REG = 0xf2
87};
88
89/* the bytes to write are in gspca_dev->usb_buf */
90static int reg_w(struct gspca_dev *gspca_dev,
91 __u16 index, int len)
92{
93 int rc;
94
95 rc = usb_control_msg(gspca_dev->dev,
96 usb_sndbulkpipe(gspca_dev->dev, 4),
97 0x12,
98 0xc8, /* ?? */
99 0, /* value */
100 index, gspca_dev->usb_buf, len, 500);
101 if (rc < 0)
102 PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc);
103 return rc;
104}
105
106static int reg_w_buf(struct gspca_dev *gspca_dev,
107 __u16 index, __u8 *buf, int len)
108{
109 int rc;
110
111 rc = usb_control_msg(gspca_dev->dev,
112 usb_sndbulkpipe(gspca_dev->dev, 4),
113 0x12,
114 0xc8, /* ?? */
115 0, /* value */
116 index, buf, len, 500);
117 if (rc < 0)
118 PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc);
119 return rc;
120}
121
122static void bulk_w(struct gspca_dev *gspca_dev,
123 __u16 *pch,
124 __u16 Address)
125{
126 gspca_dev->usb_buf[0] = 0x1f;
127 gspca_dev->usb_buf[1] = 0; /* control byte */
128 gspca_dev->usb_buf[2] = Address;
129 gspca_dev->usb_buf[3] = *pch >> 8; /* high byte */
130 gspca_dev->usb_buf[4] = *pch; /* low byte */
131
132 reg_w(gspca_dev, Address, 5);
133}
134
135/* this function is called at probe time */
136static int sd_config(struct gspca_dev *gspca_dev,
137 const struct usb_device_id *id)
138{
139 struct sd *sd = (struct sd *) gspca_dev;
140 struct cam *cam;
141
142 cam = &gspca_dev->cam;
143 cam->dev_name = (char *) id->driver_info;
144 cam->epaddr = 0x01;
145 cam->cam_mode = vga_mode;
146 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
147 sd->qindex = 1; /* set the quantization table */
148 return 0;
149}
150
151/* this function is called at open time */
152static int sd_open(struct gspca_dev *gspca_dev)
153{
154 return 0;
155}
156
157static void sd_start(struct gspca_dev *gspca_dev)
158{
159 int err_code;
160 __u8 *data;
161 __u16 *MI_buf;
162 int h_size, v_size;
163 int intpipe;
164
165 PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface);
166 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8) < 0) {
167 PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error");
168 return;
169 }
170
171 data = gspca_dev->usb_buf;
172 data[0] = 0x01; /* address */
173 data[1] = 0x01;
174
175 err_code = reg_w(gspca_dev, data[0], 2);
176 if (err_code < 0)
177 return;
178
179 /*
180 Initialize the MR97113 chip register
181 */
182 data = kmalloc(16, GFP_KERNEL);
183 data[0] = 0x00; /* address */
184 data[1] = 0x0c | 0x01; /* reg 0 */
185 data[2] = 0x01; /* reg 1 */
186 h_size = gspca_dev->width;
187 v_size = gspca_dev->height;
188 data[3] = h_size / 8; /* h_size , reg 2 */
189 data[4] = v_size / 8; /* v_size , reg 3 */
190 data[5] = 0x30; /* reg 4, MI, PAS5101 :
191 * 0x30 for 24mhz , 0x28 for 12mhz */
192 data[6] = 4; /* reg 5, H start */
193 data[7] = 0xc0; /* reg 6, gamma 1.5 */
194 data[8] = 3; /* reg 7, V start */
195/* if (h_size == 320 ) */
196/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */
197/* else */
198 data[9] = 0x52; /* reg 8, 24MHz, no scale down */
199 data[10] = 0x5d; /* reg 9, I2C device address
200 * [for PAS5101 (0x40)] [for MI (0x5d)] */
201
202 err_code = reg_w_buf(gspca_dev, data[0], data, 11);
203 kfree(data);
204 if (err_code < 0)
205 return;
206
207 data = gspca_dev->usb_buf;
208 data[0] = 0x23; /* address */
209 data[1] = 0x09; /* reg 35, append frame header */
210
211 err_code = reg_w(gspca_dev, data[0], 2);
212 if (err_code < 0)
213 return;
214
215 data[0] = 0x3c; /* address */
216/* if (gspca_dev->width == 1280) */
217/* data[1] = 200; * reg 60, pc-cam frame size
218 * (unit: 4KB) 800KB */
219/* else */
220 data[1] = 50; /* 50 reg 60, pc-cam frame size
221 * (unit: 4KB) 200KB */
222 err_code = reg_w(gspca_dev, data[0], 2);
223 if (err_code < 0)
224 return;
225
226 if (0) { /* fixed dark-gain */
227 data[1] = 0; /* reg 94, Y Gain (1.75) */
228 data[2] = 0; /* reg 95, UV Gain (1.75) */
229 data[3] = 0x3f; /* reg 96, Y Gain/UV Gain/disable
230 * auto dark-gain */
231 data[4] = 0; /* reg 97, set fixed dark level */
232 data[5] = 0; /* reg 98, don't care */
233 } else { /* auto dark-gain */
234 data[1] = 0; /* reg 94, Y Gain (auto) */
235 data[2] = 0; /* reg 95, UV Gain (1.75) */
236 data[3] = 0x78; /* reg 96, Y Gain/UV Gain/disable
237 * auto dark-gain */
238 switch (gspca_dev->width) {
239/* case 1280: */
240/* data[4] = 154;
241 * reg 97, %3 shadow point (unit: 256 pixel) */
242/* data[5] = 51;
243 * reg 98, %1 highlight point
244 * (uint: 256 pixel) */
245/* break; */
246 default:
247/* case 640: */
248 data[4] = 36; /* reg 97, %3 shadow point
249 * (unit: 256 pixel) */
250 data[5] = 12; /* reg 98, %1 highlight point
251 * (uint: 256 pixel) */
252 break;
253 case 320:
254 data[4] = 9; /* reg 97, %3 shadow point
255 * (unit: 256 pixel) */
256 data[5] = 3; /* reg 98, %1 highlight point
257 * (uint: 256 pixel) */
258 break;
259 }
260 }
261 /* auto dark-gain */
262 data[0] = 0x5e; /* address */
263
264 err_code = reg_w(gspca_dev, data[0], 6);
265 if (err_code < 0)
266 return;
267
268 data[0] = 0x67;
269 data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */
270 err_code = reg_w(gspca_dev, data[0], 2);
271 if (err_code < 0)
272 return;
273
274 /*
275 * initialize the value of MI sensor...
276 */
277 MI_buf = kzalloc(ATTR_TOTAL_MI_REG * sizeof *MI_buf, GFP_KERNEL);
278 MI_buf[REG_HW_MI_1] = 0x000a;
279 MI_buf[REG_HW_MI_2] = 0x000c;
280 MI_buf[REG_HW_MI_3] = 0x0405;
281 MI_buf[REG_HW_MI_4] = 0x0507;
282 /* mi_Attr_Reg_[REG_HW_MI_5] = 0x01ff;//13 */
283 MI_buf[REG_HW_MI_5] = 0x0013; /* 13 */
284 MI_buf[REG_HW_MI_6] = 0x001f; /* vertical blanking */
285 /* mi_Attr_Reg_[REG_HW_MI_6] = 0x0400; // vertical blanking */
286 MI_buf[REG_HW_MI_7] = 0x0002;
287 /* mi_Attr_Reg_[REG_HW_MI_9] = 0x015f; */
288 /* mi_Attr_Reg_[REG_HW_MI_9] = 0x030f; */
289 MI_buf[REG_HW_MI_9] = 0x0374;
290 MI_buf[REG_HW_MI_B] = 0x0000;
291 MI_buf[REG_HW_MI_C] = 0x0000;
292 MI_buf[REG_HW_MI_D] = 0x0000;
293 MI_buf[REG_HW_MI_1E] = 0x8000;
294/* mi_Attr_Reg_[REG_HW_MI_20] = 0x1104; */
295 MI_buf[REG_HW_MI_20] = 0x1104; /* 0x111c; */
296 MI_buf[REG_HW_MI_2B] = 0x0008;
297/* mi_Attr_Reg_[REG_HW_MI_2C] = 0x000f; */
298 MI_buf[REG_HW_MI_2C] = 0x001f; /* lita suggest */
299 MI_buf[REG_HW_MI_2D] = 0x0008;
300 MI_buf[REG_HW_MI_2E] = 0x0008;
301 MI_buf[REG_HW_MI_35] = 0x0051;
302 MI_buf[REG_HW_MI_5F] = 0x0904; /* fail to write */
303 MI_buf[REG_HW_MI_60] = 0x0000;
304 MI_buf[REG_HW_MI_61] = 0x0000;
305 MI_buf[REG_HW_MI_62] = 0x0498;
306 MI_buf[REG_HW_MI_63] = 0x0000;
307 MI_buf[REG_HW_MI_64] = 0x0000;
308 MI_buf[REG_HW_MI_F1] = 0x0001;
309 /* changing while setting up the different value of dx/dy */
310
311 if (gspca_dev->width != 1280) {
312 MI_buf[0x01] = 0x010a;
313 MI_buf[0x02] = 0x014c;
314 MI_buf[0x03] = 0x01e5;
315 MI_buf[0x04] = 0x0287;
316 }
317 MI_buf[0x20] = 0x1104;
318
319 bulk_w(gspca_dev, MI_buf + 1, 1);
320 bulk_w(gspca_dev, MI_buf + 2, 2);
321 bulk_w(gspca_dev, MI_buf + 3, 3);
322 bulk_w(gspca_dev, MI_buf + 4, 4);
323 bulk_w(gspca_dev, MI_buf + 5, 5);
324 bulk_w(gspca_dev, MI_buf + 6, 6);
325 bulk_w(gspca_dev, MI_buf + 7, 7);
326 bulk_w(gspca_dev, MI_buf + 9, 9);
327 bulk_w(gspca_dev, MI_buf + 0x0b, 0x0b);
328 bulk_w(gspca_dev, MI_buf + 0x0c, 0x0c);
329 bulk_w(gspca_dev, MI_buf + 0x0d, 0x0d);
330 bulk_w(gspca_dev, MI_buf + 0x1e, 0x1e);
331 bulk_w(gspca_dev, MI_buf + 0x20, 0x20);
332 bulk_w(gspca_dev, MI_buf + 0x2b, 0x2b);
333 bulk_w(gspca_dev, MI_buf + 0x2c, 0x2c);
334 bulk_w(gspca_dev, MI_buf + 0x2d, 0x2d);
335 bulk_w(gspca_dev, MI_buf + 0x2e, 0x2e);
336 bulk_w(gspca_dev, MI_buf + 0x35, 0x35);
337 bulk_w(gspca_dev, MI_buf + 0x5f, 0x5f);
338 bulk_w(gspca_dev, MI_buf + 0x60, 0x60);
339 bulk_w(gspca_dev, MI_buf + 0x61, 0x61);
340 bulk_w(gspca_dev, MI_buf + 0x62, 0x62);
341 bulk_w(gspca_dev, MI_buf + 0x63, 0x63);
342 bulk_w(gspca_dev, MI_buf + 0x64, 0x64);
343 bulk_w(gspca_dev, MI_buf + 0xf1, 0xf1);
344 kfree(MI_buf);
345
346 intpipe = usb_sndintpipe(gspca_dev->dev, 0);
347 err_code = usb_clear_halt(gspca_dev->dev, intpipe);
348
349 data[0] = 0x00;
350 data[1] = 0x4d; /* ISOC transfering enable... */
351 reg_w(gspca_dev, data[0], 2);
352}
353
354static void sd_stopN(struct gspca_dev *gspca_dev)
355{
356 int result;
357
358 gspca_dev->usb_buf[0] = 1;
359 gspca_dev->usb_buf[1] = 0;
360 result = reg_w(gspca_dev, gspca_dev->usb_buf[0], 2);
361 if (result < 0)
362 PDEBUG(D_ERR, "Camera Stop failed");
363}
364
365static void sd_stop0(struct gspca_dev *gspca_dev)
366{
367}
368
369static void sd_close(struct gspca_dev *gspca_dev)
370{
371}
372
373static void sd_pkt_scan(struct gspca_dev *gspca_dev,
374 struct gspca_frame *frame, /* target */
375 __u8 *data, /* isoc packet */
376 int len) /* iso packet length */
377{
378 struct sd *sd = (struct sd *) gspca_dev;
379 int p;
380
381 if (len < 6) {
382/* gspca_dev->last_packet_type = DISCARD_PACKET; */
383 return;
384 }
385 for (p = 0; p < len - 6; p++) {
386 if (data[0 + p] == 0xff
387 && data[1 + p] == 0xff
388 && data[2 + p] == 0x00
389 && data[3 + p] == 0xff
390 && data[4 + p] == 0x96) {
391 if (data[5 + p] == 0x64
392 || data[5 + p] == 0x65
393 || data[5 + p] == 0x66
394 || data[5 + p] == 0x67) {
395 PDEBUG(D_PACK, "sof offset: %d leng: %d",
396 p, len);
397 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
398 frame, data, 0);
399
400 /* put the JPEG header */
401 jpeg_put_header(gspca_dev, frame,
402 sd->qindex, 0x21);
403 data += 16;
404 len -= 16;
405 break;
406 }
407 }
408 }
409 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
410}
411
412/* sub-driver description */
413static const struct sd_desc sd_desc = {
414 .name = MODULE_NAME,
415 .ctrls = sd_ctrls,
416 .nctrls = ARRAY_SIZE(sd_ctrls),
417 .config = sd_config,
418 .open = sd_open,
419 .start = sd_start,
420 .stopN = sd_stopN,
421 .stop0 = sd_stop0,
422 .close = sd_close,
423 .pkt_scan = sd_pkt_scan,
424};
425
426/* -- module initialisation -- */
427#define DVNM(name) .driver_info = (kernel_ulong_t) name
428static const __devinitdata struct usb_device_id device_table[] = {
429 {USB_DEVICE(0x093a, 0x050f), DVNM("Mars-Semi Pc-Camera")},
430 {}
431};
432MODULE_DEVICE_TABLE(usb, device_table);
433
434/* -- device connect -- */
435static int sd_probe(struct usb_interface *intf,
436 const struct usb_device_id *id)
437{
438 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
439 THIS_MODULE);
440}
441
442static struct usb_driver sd_driver = {
443 .name = MODULE_NAME,
444 .id_table = device_table,
445 .probe = sd_probe,
446 .disconnect = gspca_disconnect,
447};
448
449/* -- module insert / remove -- */
450static int __init sd_mod_init(void)
451{
452 if (usb_register(&sd_driver) < 0)
453 return -1;
454 PDEBUG(D_PROBE, "v%s registered", version);
455 return 0;
456}
457static void __exit sd_mod_exit(void)
458{
459 usb_deregister(&sd_driver);
460 PDEBUG(D_PROBE, "deregistered");
461}
462
463module_init(sd_mod_init);
464module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
new file mode 100644
index 000000000000..08d99c3b78e2
--- /dev/null
+++ b/drivers/media/video/gspca/ov519.c
@@ -0,0 +1,2186 @@
1/**
2 * OV519 driver
3 *
4 * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
5 *
6 * (This module is adapted from the ov51x-jpeg package)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23#define MODULE_NAME "ov519"
24
25#include "gspca.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
31MODULE_DESCRIPTION("OV519 USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* global parameters */
35static int frame_rate;
36
37/* Number of times to retry a failed I2C transaction. Increase this if you
38 * are getting "Failed to read sensor ID..." */
39static int i2c_detect_tries = 10;
40
41/* ov519 device descriptor */
42struct sd {
43 struct gspca_dev gspca_dev; /* !! must be the first item */
44
45 /* Determined by sensor type */
46 short maxwidth;
47 short maxheight;
48
49 unsigned char primary_i2c_slave; /* I2C write id of sensor */
50
51 unsigned char brightness;
52 unsigned char contrast;
53 unsigned char colors;
54
55 char compress; /* Should the next frame be compressed? */
56 char compress_inited; /* Are compression params uploaded? */
57 char stopped; /* Streaming is temporarily paused */
58
59 char frame_rate; /* current Framerate (OV519 only) */
60 char clockdiv; /* clockdiv override for OV519 only */
61
62 char sensor; /* Type of image sensor chip (SEN_*) */
63#define SEN_UNKNOWN 0
64#define SEN_OV6620 1
65#define SEN_OV6630 2
66#define SEN_OV7610 3
67#define SEN_OV7620 4
68#define SEN_OV7630 5
69#define SEN_OV7640 6
70#define SEN_OV7670 7
71#define SEN_OV76BE 8
72#define SEN_OV8610 9
73
74};
75
76/* V4L2 controls supported by the driver */
77static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
81static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
83
84static struct ctrl sd_ctrls[] = {
85#define SD_BRIGHTNESS 0
86 {
87 {
88 .id = V4L2_CID_BRIGHTNESS,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Brightness",
91 .minimum = 0,
92 .maximum = 255,
93 .step = 1,
94 .default_value = 127,
95 },
96 .set = sd_setbrightness,
97 .get = sd_getbrightness,
98 },
99#define SD_CONTRAST 1
100 {
101 {
102 .id = V4L2_CID_CONTRAST,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Contrast",
105 .minimum = 0,
106 .maximum = 255,
107 .step = 1,
108 .default_value = 127,
109 },
110 .set = sd_setcontrast,
111 .get = sd_getcontrast,
112 },
113#define SD_COLOR 2
114 {
115 {
116 .id = V4L2_CID_SATURATION,
117 .type = V4L2_CTRL_TYPE_INTEGER,
118 .name = "Saturation",
119 .minimum = 0,
120 .maximum = 255,
121 .step = 1,
122 .default_value = 127,
123 },
124 .set = sd_setcolors,
125 .get = sd_getcolors,
126 },
127};
128
129static struct v4l2_pix_format vga_mode[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 320,
132 .sizeimage = 320 * 240 * 3 / 8 + 589,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 1},
135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 640,
137 .sizeimage = 640 * 480 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 0},
140};
141static struct v4l2_pix_format sif_mode[] = {
142 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
143 .bytesperline = 176,
144 .sizeimage = 176 * 144 * 3 / 8 + 589,
145 .colorspace = V4L2_COLORSPACE_JPEG,
146 .priv = 1},
147 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
148 .bytesperline = 352,
149 .sizeimage = 352 * 288 * 3 / 8 + 589,
150 .colorspace = V4L2_COLORSPACE_JPEG,
151 .priv = 0},
152};
153
154/* OV519 Camera interface register numbers */
155#define OV519_CAM_H_SIZE 0x10
156#define OV519_CAM_V_SIZE 0x11
157#define OV519_CAM_X_OFFSETL 0x12
158#define OV519_CAM_X_OFFSETH 0x13
159#define OV519_CAM_Y_OFFSETL 0x14
160#define OV519_CAM_Y_OFFSETH 0x15
161#define OV519_CAM_DIVIDER 0x16
162#define OV519_CAM_DFR 0x20
163#define OV519_CAM_FORMAT 0x25
164
165/* OV519 System Controller register numbers */
166#define OV519_SYS_RESET1 0x51
167#define OV519_SYS_EN_CLK1 0x54
168
169#define OV519_GPIO_DATA_OUT0 0x71
170#define OV519_GPIO_IO_CTRL0 0x72
171
172#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */
173
174/* I2C registers */
175#define R51x_I2C_W_SID 0x41
176#define R51x_I2C_SADDR_3 0x42
177#define R51x_I2C_SADDR_2 0x43
178#define R51x_I2C_R_SID 0x44
179#define R51x_I2C_DATA 0x45
180#define R518_I2C_CTL 0x47 /* OV518(+) only */
181
182/* I2C ADDRESSES */
183#define OV7xx0_SID 0x42
184#define OV8xx0_SID 0xa0
185#define OV6xx0_SID 0xc0
186
187/* OV7610 registers */
188#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
189#define OV7610_REG_SAT 0x03 /* saturation */
190#define OV8610_REG_HUE 0x04 /* 04 reserved */
191#define OV7610_REG_CNT 0x05 /* Y contrast */
192#define OV7610_REG_BRT 0x06 /* Y brightness */
193#define OV7610_REG_COM_C 0x14 /* misc common regs */
194#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */
195#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */
196#define OV7610_REG_COM_I 0x29 /* misc settings */
197
198/* OV7670 registers */
199#define OV7670_REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */
200#define OV7670_REG_BLUE 0x01 /* blue gain */
201#define OV7670_REG_RED 0x02 /* red gain */
202#define OV7670_REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */
203#define OV7670_REG_COM1 0x04 /* Control 1 */
204#define OV7670_REG_AECHH 0x07 /* AEC MS 5 bits */
205#define OV7670_REG_COM3 0x0c /* Control 3 */
206#define OV7670_REG_COM4 0x0d /* Control 4 */
207#define OV7670_REG_COM5 0x0e /* All "reserved" */
208#define OV7670_REG_COM6 0x0f /* Control 6 */
209#define OV7670_REG_AECH 0x10 /* More bits of AEC value */
210#define OV7670_REG_CLKRC 0x11 /* Clock control */
211#define OV7670_REG_COM7 0x12 /* Control 7 */
212#define OV7670_COM7_FMT_VGA 0x00
213#define OV7670_COM7_YUV 0x00 /* YUV */
214#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */
215#define OV7670_COM7_FMT_MASK 0x38
216#define OV7670_COM7_RESET 0x80 /* Register reset */
217#define OV7670_REG_COM8 0x13 /* Control 8 */
218#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */
219#define OV7670_COM8_AWB 0x02 /* White balance enable */
220#define OV7670_COM8_AGC 0x04 /* Auto gain enable */
221#define OV7670_COM8_BFILT 0x20 /* Band filter enable */
222#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */
223#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */
224#define OV7670_REG_COM9 0x14 /* Control 9 - gain ceiling */
225#define OV7670_REG_COM10 0x15 /* Control 10 */
226#define OV7670_REG_HSTART 0x17 /* Horiz start high bits */
227#define OV7670_REG_HSTOP 0x18 /* Horiz stop high bits */
228#define OV7670_REG_VSTART 0x19 /* Vert start high bits */
229#define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */
230#define OV7670_REG_MVFP 0x1e /* Mirror / vflip */
231#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */
232#define OV7670_REG_AEW 0x24 /* AGC upper limit */
233#define OV7670_REG_AEB 0x25 /* AGC lower limit */
234#define OV7670_REG_VPT 0x26 /* AGC/AEC fast mode op region */
235#define OV7670_REG_HREF 0x32 /* HREF pieces */
236#define OV7670_REG_TSLB 0x3a /* lots of stuff */
237#define OV7670_REG_COM11 0x3b /* Control 11 */
238#define OV7670_COM11_EXP 0x02
239#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */
240#define OV7670_REG_COM12 0x3c /* Control 12 */
241#define OV7670_REG_COM13 0x3d /* Control 13 */
242#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */
243#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */
244#define OV7670_REG_COM14 0x3e /* Control 14 */
245#define OV7670_REG_EDGE 0x3f /* Edge enhancement factor */
246#define OV7670_REG_COM15 0x40 /* Control 15 */
247#define OV7670_COM15_R00FF 0xc0 /* 00 to FF */
248#define OV7670_REG_COM16 0x41 /* Control 16 */
249#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */
250#define OV7670_REG_BRIGHT 0x55 /* Brightness */
251#define OV7670_REG_CONTRAS 0x56 /* Contrast control */
252#define OV7670_REG_GFIX 0x69 /* Fix gain control */
253#define OV7670_REG_RGB444 0x8c /* RGB 444 control */
254#define OV7670_REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */
255#define OV7670_REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */
256#define OV7670_REG_BD50MAX 0xa5 /* 50hz banding step limit */
257#define OV7670_REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */
258#define OV7670_REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */
259#define OV7670_REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */
260#define OV7670_REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */
261#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */
262#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */
263
264struct ovsensor_window {
265 short x;
266 short y;
267 short width;
268 short height;
269/* int format; */
270 short quarter; /* Scale width and height down 2x */
271 short clockdiv; /* Clock divisor setting */
272};
273
274static unsigned char ov7670_abs_to_sm(unsigned char v)
275{
276 if (v > 127)
277 return v & 0x7f;
278 return (128 - v) | 0x80;
279}
280
281/* Write a OV519 register */
282static int reg_w(struct sd *sd, __u16 index, __u8 value)
283{
284 int ret;
285
286 sd->gspca_dev.usb_buf[0] = value;
287 ret = usb_control_msg(sd->gspca_dev.dev,
288 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
289 1, /* REQ_IO (ov518/519) */
290 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
291 0, index,
292 sd->gspca_dev.usb_buf, 1, 500);
293 if (ret < 0)
294 PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value);
295 return ret;
296}
297
298/* Read from a OV519 register */
299/* returns: negative is error, pos or zero is data */
300static int reg_r(struct sd *sd, __u16 index)
301{
302 int ret;
303
304 ret = usb_control_msg(sd->gspca_dev.dev,
305 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
306 1, /* REQ_IO */
307 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
308 0, index, sd->gspca_dev.usb_buf, 1, 500);
309
310 if (ret >= 0)
311 ret = sd->gspca_dev.usb_buf[0];
312 else
313 PDEBUG(D_ERR, "Read reg [0x%02x] failed", index);
314 return ret;
315}
316
317/* Read 8 values from a OV519 register */
318static int reg_r8(struct sd *sd,
319 __u16 index)
320{
321 int ret;
322
323 ret = usb_control_msg(sd->gspca_dev.dev,
324 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
325 1, /* REQ_IO */
326 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
327 0, index, sd->gspca_dev.usb_buf, 8, 500);
328
329 if (ret >= 0)
330 ret = sd->gspca_dev.usb_buf[0];
331 else
332 PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index);
333 return ret;
334}
335
336/*
337 * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
338 * the same position as 1's in "mask" are cleared and set to "value". Bits
339 * that are in the same position as 0's in "mask" are preserved, regardless
340 * of their respective state in "value".
341 */
342static int reg_w_mask(struct sd *sd,
343 __u16 index,
344 __u8 value,
345 __u8 mask)
346{
347 int ret;
348 __u8 oldval;
349
350 if (mask != 0xff) {
351 value &= mask; /* Enforce mask on value */
352 ret = reg_r(sd, index);
353 if (ret < 0)
354 return ret;
355
356 oldval = ret & ~mask; /* Clear the masked bits */
357 value |= oldval; /* Set the desired bits */
358 }
359 return reg_w(sd, index, value);
360}
361
362/*
363 * The OV518 I2C I/O procedure is different, hence, this function.
364 * This is normally only called from i2c_w(). Note that this function
365 * always succeeds regardless of whether the sensor is present and working.
366 */
367static int i2c_w(struct sd *sd,
368 __u8 reg,
369 __u8 value)
370{
371 int rc;
372
373 PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
374
375 /* Select camera register */
376 rc = reg_w(sd, R51x_I2C_SADDR_3, reg);
377 if (rc < 0)
378 return rc;
379
380 /* Write "value" to I2C data port of OV511 */
381 rc = reg_w(sd, R51x_I2C_DATA, value);
382 if (rc < 0)
383 return rc;
384
385 /* Initiate 3-byte write cycle */
386 rc = reg_w(sd, R518_I2C_CTL, 0x01);
387
388 /* wait for write complete */
389 msleep(4);
390 if (rc < 0)
391 return rc;
392 return reg_r8(sd, R518_I2C_CTL);
393}
394
395/*
396 * returns: negative is error, pos or zero is data
397 *
398 * The OV518 I2C I/O procedure is different, hence, this function.
399 * This is normally only called from i2c_r(). Note that this function
400 * always succeeds regardless of whether the sensor is present and working.
401 */
402static int i2c_r(struct sd *sd, __u8 reg)
403{
404 int rc, value;
405
406 /* Select camera register */
407 rc = reg_w(sd, R51x_I2C_SADDR_2, reg);
408 if (rc < 0)
409 return rc;
410
411 /* Initiate 2-byte write cycle */
412 rc = reg_w(sd, R518_I2C_CTL, 0x03);
413 if (rc < 0)
414 return rc;
415
416 /* Initiate 2-byte read cycle */
417 rc = reg_w(sd, R518_I2C_CTL, 0x05);
418 if (rc < 0)
419 return rc;
420 value = reg_r(sd, R51x_I2C_DATA);
421 PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
422 return value;
423}
424
425/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
426 * the same position as 1's in "mask" are cleared and set to "value". Bits
427 * that are in the same position as 0's in "mask" are preserved, regardless
428 * of their respective state in "value".
429 */
430static int i2c_w_mask(struct sd *sd,
431 __u8 reg,
432 __u8 value,
433 __u8 mask)
434{
435 int rc;
436 __u8 oldval;
437
438 value &= mask; /* Enforce mask on value */
439 rc = i2c_r(sd, reg);
440 if (rc < 0)
441 return rc;
442 oldval = rc & ~mask; /* Clear the masked bits */
443 value |= oldval; /* Set the desired bits */
444 return i2c_w(sd, reg, value);
445}
446
447/* Temporarily stops OV511 from functioning. Must do this before changing
448 * registers while the camera is streaming */
449static inline int ov51x_stop(struct sd *sd)
450{
451 PDEBUG(D_STREAM, "stopping");
452 sd->stopped = 1;
453 return reg_w(sd, OV519_SYS_RESET1, 0x0f);
454}
455
456/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
457 * actually stopped (for performance). */
458static inline int ov51x_restart(struct sd *sd)
459{
460 PDEBUG(D_STREAM, "restarting");
461 if (!sd->stopped)
462 return 0;
463 sd->stopped = 0;
464
465 /* Reinitialize the stream */
466 return reg_w(sd, OV519_SYS_RESET1, 0x00);
467}
468
469/* This does an initial reset of an OmniVision sensor and ensures that I2C
470 * is synchronized. Returns <0 on failure.
471 */
472static int init_ov_sensor(struct sd *sd)
473{
474 int i, success;
475
476 /* Reset the sensor */
477 if (i2c_w(sd, 0x12, 0x80) < 0)
478 return -EIO;
479
480 /* Wait for it to initialize */
481 msleep(150);
482
483 for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
484 if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f &&
485 i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) {
486 success = 1;
487 continue;
488 }
489
490 /* Reset the sensor */
491 if (i2c_w(sd, 0x12, 0x80) < 0)
492 return -EIO;
493 /* Wait for it to initialize */
494 msleep(150);
495 /* Dummy read to sync I2C */
496 if (i2c_r(sd, 0x00) < 0)
497 return -EIO;
498 }
499 if (!success)
500 return -EIO;
501 PDEBUG(D_PROBE, "I2C synced in %d attempt(s)", i);
502 return 0;
503}
504
505/* Switch on standard JPEG compression. Returns 0 for success. */
506static int ov519_init_compression(struct sd *sd)
507{
508 if (!sd->compress_inited) {
509 if (reg_w_mask(sd, OV519_SYS_EN_CLK1, 1 << 2, 1 << 2) < 0) {
510 PDEBUG(D_ERR, "Error switching to compressed mode");
511 return -EIO;
512 }
513 sd->compress_inited = 1;
514 }
515 return 0;
516}
517
518/* Set the read and write slave IDs. The "slave" argument is the write slave,
519 * and the read slave will be set to (slave + 1).
520 * This should not be called from outside the i2c I/O functions.
521 * Sets I2C read and write slave IDs. Returns <0 for error
522 */
523static int ov51x_set_slave_ids(struct sd *sd,
524 __u8 slave)
525{
526 int rc;
527
528 rc = reg_w(sd, R51x_I2C_W_SID, slave);
529 if (rc < 0)
530 return rc;
531 return reg_w(sd, R51x_I2C_R_SID, slave + 1);
532}
533
534struct ov_regvals {
535 __u8 reg;
536 __u8 val;
537};
538struct ov_i2c_regvals {
539 __u8 reg;
540 __u8 val;
541};
542
543static int write_regvals(struct sd *sd,
544 const struct ov_regvals *regvals,
545 int n)
546{
547 int rc;
548
549 while (--n >= 0) {
550 rc = reg_w(sd, regvals->reg, regvals->val);
551 if (rc < 0)
552 return rc;
553 regvals++;
554 }
555 return 0;
556}
557
558static int write_i2c_regvals(struct sd *sd,
559 const struct ov_i2c_regvals *regvals,
560 int n)
561{
562 int rc;
563
564 while (--n >= 0) {
565 rc = i2c_w(sd, regvals->reg, regvals->val);
566 if (rc < 0)
567 return rc;
568 regvals++;
569 }
570 return 0;
571}
572
573/****************************************************************************
574 *
575 * OV511 and sensor configuration
576 *
577 ***************************************************************************/
578
579/* This initializes the OV8110, OV8610 sensor. The OV8110 uses
580 * the same register settings as the OV8610, since they are very similar.
581 */
582static int ov8xx0_configure(struct sd *sd)
583{
584 int rc;
585 static const struct ov_i2c_regvals norm_8610[] = {
586 { 0x12, 0x80 },
587 { 0x00, 0x00 },
588 { 0x01, 0x80 },
589 { 0x02, 0x80 },
590 { 0x03, 0xc0 },
591 { 0x04, 0x30 },
592 { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
593 { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
594 { 0x0a, 0x86 },
595 { 0x0b, 0xb0 },
596 { 0x0c, 0x20 },
597 { 0x0d, 0x20 },
598 { 0x11, 0x01 },
599 { 0x12, 0x25 },
600 { 0x13, 0x01 },
601 { 0x14, 0x04 },
602 { 0x15, 0x01 }, /* Lin and Win think different about UV order */
603 { 0x16, 0x03 },
604 { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
605 { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
606 { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
607 { 0x1a, 0xf5 },
608 { 0x1b, 0x00 },
609 { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
610 { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
611 { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
612 { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
613 { 0x26, 0xa2 },
614 { 0x27, 0xea },
615 { 0x28, 0x00 },
616 { 0x29, 0x00 },
617 { 0x2a, 0x80 },
618 { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
619 { 0x2c, 0xac },
620 { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
621 { 0x2e, 0x80 },
622 { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
623 { 0x4c, 0x00 },
624 { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
625 { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
626 { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
627 { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
628 { 0x63, 0xff },
629 { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
630 * maybe thats wrong */
631 { 0x65, 0x00 },
632 { 0x66, 0x55 },
633 { 0x67, 0xb0 },
634 { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
635 { 0x69, 0x02 },
636 { 0x6a, 0x22 },
637 { 0x6b, 0x00 },
638 { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
639 deleting bit7 colors the first images red */
640 { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
641 { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
642 { 0x6f, 0x01 },
643 { 0x70, 0x8b },
644 { 0x71, 0x00 },
645 { 0x72, 0x14 },
646 { 0x73, 0x54 },
647 { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
648 { 0x75, 0x0e },
649 { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
650 { 0x77, 0xff },
651 { 0x78, 0x80 },
652 { 0x79, 0x80 },
653 { 0x7a, 0x80 },
654 { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
655 { 0x7c, 0x00 },
656 { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
657 { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
658 { 0x7f, 0xfb },
659 { 0x80, 0x28 },
660 { 0x81, 0x00 },
661 { 0x82, 0x23 },
662 { 0x83, 0x0b },
663 { 0x84, 0x00 },
664 { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
665 { 0x86, 0xc9 },
666 { 0x87, 0x00 },
667 { 0x88, 0x00 },
668 { 0x89, 0x01 },
669 { 0x12, 0x20 },
670 { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
671 };
672
673 PDEBUG(D_PROBE, "starting ov8xx0 configuration");
674
675 if (init_ov_sensor(sd) < 0)
676 PDEBUG(D_ERR|D_PROBE, "Failed to read sensor ID");
677 else
678 PDEBUG(D_PROBE, "OV86x0 initialized");
679
680 /* Detect sensor (sub)type */
681 rc = i2c_r(sd, OV7610_REG_COM_I);
682 if (rc < 0) {
683 PDEBUG(D_ERR, "Error detecting sensor type");
684 return -1;
685 }
686 if ((rc & 3) == 1) {
687 PDEBUG(D_PROBE, "Sensor is an OV8610");
688 sd->sensor = SEN_OV8610;
689 } else {
690 PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
691 return -1;
692 }
693 PDEBUG(D_PROBE, "Writing 8610 registers");
694 if (write_i2c_regvals(sd,
695 norm_8610,
696 sizeof norm_8610 / sizeof norm_8610[0]))
697 return -1;
698
699 /* Set sensor-specific vars */
700 sd->maxwidth = 640;
701 sd->maxheight = 480;
702 return 0;
703}
704
705/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
706 * the same register settings as the OV7610, since they are very similar.
707 */
708static int ov7xx0_configure(struct sd *sd)
709{
710 int rc, high, low;
711
712 /* Lawrence Glaister <lg@jfm.bc.ca> reports:
713 *
714 * Register 0x0f in the 7610 has the following effects:
715 *
716 * 0x85 (AEC method 1): Best overall, good contrast range
717 * 0x45 (AEC method 2): Very overexposed
718 * 0xa5 (spec sheet default): Ok, but the black level is
719 * shifted resulting in loss of contrast
720 * 0x05 (old driver setting): very overexposed, too much
721 * contrast
722 */
723 static const struct ov_i2c_regvals norm_7610[] = {
724 { 0x10, 0xff },
725 { 0x16, 0x06 },
726 { 0x28, 0x24 },
727 { 0x2b, 0xac },
728 { 0x12, 0x00 },
729 { 0x38, 0x81 },
730 { 0x28, 0x24 }, /* 0c */
731 { 0x0f, 0x85 }, /* lg's setting */
732 { 0x15, 0x01 },
733 { 0x20, 0x1c },
734 { 0x23, 0x2a },
735 { 0x24, 0x10 },
736 { 0x25, 0x8a },
737 { 0x26, 0xa2 },
738 { 0x27, 0xc2 },
739 { 0x2a, 0x04 },
740 { 0x2c, 0xfe },
741 { 0x2d, 0x93 },
742 { 0x30, 0x71 },
743 { 0x31, 0x60 },
744 { 0x32, 0x26 },
745 { 0x33, 0x20 },
746 { 0x34, 0x48 },
747 { 0x12, 0x24 },
748 { 0x11, 0x01 },
749 { 0x0c, 0x24 },
750 { 0x0d, 0x24 },
751 };
752
753 static const struct ov_i2c_regvals norm_7620[] = {
754 { 0x00, 0x00 }, /* gain */
755 { 0x01, 0x80 }, /* blue gain */
756 { 0x02, 0x80 }, /* red gain */
757 { 0x03, 0xc0 }, /* OV7670_REG_VREF */
758 { 0x06, 0x60 },
759 { 0x07, 0x00 },
760 { 0x0c, 0x24 },
761 { 0x0c, 0x24 },
762 { 0x0d, 0x24 },
763 { 0x11, 0x01 },
764 { 0x12, 0x24 },
765 { 0x13, 0x01 },
766 { 0x14, 0x84 },
767 { 0x15, 0x01 },
768 { 0x16, 0x03 },
769 { 0x17, 0x2f },
770 { 0x18, 0xcf },
771 { 0x19, 0x06 },
772 { 0x1a, 0xf5 },
773 { 0x1b, 0x00 },
774 { 0x20, 0x18 },
775 { 0x21, 0x80 },
776 { 0x22, 0x80 },
777 { 0x23, 0x00 },
778 { 0x26, 0xa2 },
779 { 0x27, 0xea },
780 { 0x28, 0x20 },
781 { 0x29, 0x00 },
782 { 0x2a, 0x10 },
783 { 0x2b, 0x00 },
784 { 0x2c, 0x88 },
785 { 0x2d, 0x91 },
786 { 0x2e, 0x80 },
787 { 0x2f, 0x44 },
788 { 0x60, 0x27 },
789 { 0x61, 0x02 },
790 { 0x62, 0x5f },
791 { 0x63, 0xd5 },
792 { 0x64, 0x57 },
793 { 0x65, 0x83 },
794 { 0x66, 0x55 },
795 { 0x67, 0x92 },
796 { 0x68, 0xcf },
797 { 0x69, 0x76 },
798 { 0x6a, 0x22 },
799 { 0x6b, 0x00 },
800 { 0x6c, 0x02 },
801 { 0x6d, 0x44 },
802 { 0x6e, 0x80 },
803 { 0x6f, 0x1d },
804 { 0x70, 0x8b },
805 { 0x71, 0x00 },
806 { 0x72, 0x14 },
807 { 0x73, 0x54 },
808 { 0x74, 0x00 },
809 { 0x75, 0x8e },
810 { 0x76, 0x00 },
811 { 0x77, 0xff },
812 { 0x78, 0x80 },
813 { 0x79, 0x80 },
814 { 0x7a, 0x80 },
815 { 0x7b, 0xe2 },
816 { 0x7c, 0x00 },
817 };
818
819 /* 7640 and 7648. The defaults should be OK for most registers. */
820 static const struct ov_i2c_regvals norm_7640[] = {
821 { 0x12, 0x80 },
822 { 0x12, 0x14 },
823 };
824
825 /* 7670. Defaults taken from OmniVision provided data,
826 * as provided by Jonathan Corbet of OLPC */
827 static const struct ov_i2c_regvals norm_7670[] = {
828 { OV7670_REG_COM7, OV7670_COM7_RESET },
829 { OV7670_REG_TSLB, 0x04 }, /* OV */
830 { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
831 { OV7670_REG_CLKRC, 0x1 },
832 /*
833 * Set the hardware window. These values from OV don't entirely
834 * make sense - hstop is less than hstart. But they work...
835 */
836 { OV7670_REG_HSTART, 0x13 }, { OV7670_REG_HSTOP, 0x01 },
837 { OV7670_REG_HREF, 0xb6 }, { OV7670_REG_VSTART, 0x02 },
838 { OV7670_REG_VSTOP, 0x7a }, { OV7670_REG_VREF, 0x0a },
839
840 { OV7670_REG_COM3, 0 }, { OV7670_REG_COM14, 0 },
841 /* Mystery scaling numbers */
842 { 0x70, 0x3a }, { 0x71, 0x35 },
843 { 0x72, 0x11 }, { 0x73, 0xf0 },
844 { 0xa2, 0x02 },
845/* jfm */
846/* { OV7670_REG_COM10, 0x0 }, */
847
848 /* Gamma curve values */
849 { 0x7a, 0x20 },
850/* jfm:win 7b=1c */
851 { 0x7b, 0x10 },
852/* jfm:win 7c=28 */
853 { 0x7c, 0x1e },
854/* jfm:win 7d=3c */
855 { 0x7d, 0x35 },
856 { 0x7e, 0x5a }, { 0x7f, 0x69 },
857 { 0x80, 0x76 }, { 0x81, 0x80 },
858 { 0x82, 0x88 }, { 0x83, 0x8f },
859 { 0x84, 0x96 }, { 0x85, 0xa3 },
860 { 0x86, 0xaf }, { 0x87, 0xc4 },
861 { 0x88, 0xd7 }, { 0x89, 0xe8 },
862
863 /* AGC and AEC parameters. Note we start by disabling those features,
864 then turn them only after tweaking the values. */
865 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
866 | OV7670_COM8_AECSTEP
867 | OV7670_COM8_BFILT },
868 { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 },
869 { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
870/* jfm:win 14=38 */
871 { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
872 { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 },
873 { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 },
874 { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 },
875 { OV7670_REG_HAECC2, 0x68 },
876/* jfm:win a1=0b */
877 { 0xa1, 0x03 }, /* magic */
878 { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 },
879 { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 },
880 { OV7670_REG_HAECC7, 0x94 },
881 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
882 | OV7670_COM8_AECSTEP
883 | OV7670_COM8_BFILT
884 | OV7670_COM8_AGC
885 | OV7670_COM8_AEC },
886
887 /* Almost all of these are magic "reserved" values. */
888 { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b },
889 { 0x16, 0x02 },
890/* jfm */
891/* { OV7670_REG_MVFP, 0x07|OV7670_MVFP_MIRROR }, */
892 { OV7670_REG_MVFP, 0x07 },
893 { 0x21, 0x02 }, { 0x22, 0x91 },
894 { 0x29, 0x07 }, { 0x33, 0x0b },
895 { 0x35, 0x0b }, { 0x37, 0x1d },
896 { 0x38, 0x71 }, { 0x39, 0x2a },
897 { OV7670_REG_COM12, 0x78 }, { 0x4d, 0x40 },
898 { 0x4e, 0x20 }, { OV7670_REG_GFIX, 0 },
899 { 0x6b, 0x4a }, { 0x74, 0x10 },
900 { 0x8d, 0x4f }, { 0x8e, 0 },
901 { 0x8f, 0 }, { 0x90, 0 },
902 { 0x91, 0 }, { 0x96, 0 },
903 { 0x9a, 0 }, { 0xb0, 0x84 },
904 { 0xb1, 0x0c }, { 0xb2, 0x0e },
905 { 0xb3, 0x82 }, { 0xb8, 0x0a },
906
907 /* More reserved magic, some of which tweaks white balance */
908 { 0x43, 0x0a }, { 0x44, 0xf0 },
909 { 0x45, 0x34 }, { 0x46, 0x58 },
910 { 0x47, 0x28 }, { 0x48, 0x3a },
911 { 0x59, 0x88 }, { 0x5a, 0x88 },
912 { 0x5b, 0x44 }, { 0x5c, 0x67 },
913 { 0x5d, 0x49 }, { 0x5e, 0x0e },
914 { 0x6c, 0x0a }, { 0x6d, 0x55 },
915 { 0x6e, 0x11 }, { 0x6f, 0x9f },
916 /* "9e for advance AWB" */
917 { 0x6a, 0x40 }, { OV7670_REG_BLUE, 0x40 },
918 { OV7670_REG_RED, 0x60 },
919 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
920 | OV7670_COM8_AECSTEP
921 | OV7670_COM8_BFILT
922 | OV7670_COM8_AGC
923 | OV7670_COM8_AEC
924 | OV7670_COM8_AWB },
925
926 /* Matrix coefficients */
927 { 0x4f, 0x80 }, { 0x50, 0x80 },
928 { 0x51, 0 }, { 0x52, 0x22 },
929 { 0x53, 0x5e }, { 0x54, 0x80 },
930 { 0x58, 0x9e },
931
932 { OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
933 { OV7670_REG_EDGE, 0 },
934 { 0x75, 0x05 }, { 0x76, 0xe1 },
935 { 0x4c, 0 }, { 0x77, 0x01 },
936 { OV7670_REG_COM13, 0xc3 }, { 0x4b, 0x09 },
937 { 0xc9, 0x60 }, { OV7670_REG_COM16, 0x38 },
938 { 0x56, 0x40 },
939
940 { 0x34, 0x11 },
941 { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
942 { 0xa4, 0x88 }, { 0x96, 0 },
943 { 0x97, 0x30 }, { 0x98, 0x20 },
944 { 0x99, 0x30 }, { 0x9a, 0x84 },
945 { 0x9b, 0x29 }, { 0x9c, 0x03 },
946 { 0x9d, 0x4c }, { 0x9e, 0x3f },
947 { 0x78, 0x04 },
948
949 /* Extra-weird stuff. Some sort of multiplexor register */
950 { 0x79, 0x01 }, { 0xc8, 0xf0 },
951 { 0x79, 0x0f }, { 0xc8, 0x00 },
952 { 0x79, 0x10 }, { 0xc8, 0x7e },
953 { 0x79, 0x0a }, { 0xc8, 0x80 },
954 { 0x79, 0x0b }, { 0xc8, 0x01 },
955 { 0x79, 0x0c }, { 0xc8, 0x0f },
956 { 0x79, 0x0d }, { 0xc8, 0x20 },
957 { 0x79, 0x09 }, { 0xc8, 0x80 },
958 { 0x79, 0x02 }, { 0xc8, 0xc0 },
959 { 0x79, 0x03 }, { 0xc8, 0x40 },
960 { 0x79, 0x05 }, { 0xc8, 0x30 },
961 { 0x79, 0x26 },
962
963 /* Format YUV422 */
964 { OV7670_REG_COM7, OV7670_COM7_YUV }, /* Selects YUV mode */
965 { OV7670_REG_RGB444, 0 }, /* No RGB444 please */
966 { OV7670_REG_COM1, 0 },
967 { OV7670_REG_COM15, OV7670_COM15_R00FF },
968 { OV7670_REG_COM9, 0x18 },
969 /* 4x gain ceiling; 0x8 is reserved bit */
970 { 0x4f, 0x80 }, /* "matrix coefficient 1" */
971 { 0x50, 0x80 }, /* "matrix coefficient 2" */
972 { 0x52, 0x22 }, /* "matrix coefficient 4" */
973 { 0x53, 0x5e }, /* "matrix coefficient 5" */
974 { 0x54, 0x80 }, /* "matrix coefficient 6" */
975 { OV7670_REG_COM13, OV7670_COM13_GAMMA|OV7670_COM13_UVSAT },
976};
977
978 PDEBUG(D_PROBE, "starting OV7xx0 configuration");
979
980/* jfm:already done? */
981 if (init_ov_sensor(sd) < 0)
982 PDEBUG(D_ERR, "Failed to read sensor ID");
983 else
984 PDEBUG(D_PROBE, "OV7xx0 initialized");
985
986 /* Detect sensor (sub)type */
987 rc = i2c_r(sd, OV7610_REG_COM_I);
988
989 /* add OV7670 here
990 * it appears to be wrongly detected as a 7610 by default */
991 if (rc < 0) {
992 PDEBUG(D_ERR, "Error detecting sensor type");
993 return -1;
994 }
995 if ((rc & 3) == 3) {
996 /* quick hack to make OV7670s work */
997 high = i2c_r(sd, 0x0a);
998 low = i2c_r(sd, 0x0b);
999 /* info("%x, %x", high, low); */
1000 if (high == 0x76 && low == 0x73) {
1001 PDEBUG(D_PROBE, "Sensor is an OV7670");
1002 sd->sensor = SEN_OV7670;
1003 } else {
1004 PDEBUG(D_PROBE, "Sensor is an OV7610");
1005 sd->sensor = SEN_OV7610;
1006 }
1007 } else if ((rc & 3) == 1) {
1008 /* I don't know what's different about the 76BE yet. */
1009 if (i2c_r(sd, 0x15) & 1)
1010 PDEBUG(D_PROBE, "Sensor is an OV7620AE");
1011 else
1012 PDEBUG(D_PROBE, "Sensor is an OV76BE");
1013
1014 /* OV511+ will return all zero isoc data unless we
1015 * configure the sensor as a 7620. Someone needs to
1016 * find the exact reg. setting that causes this. */
1017 sd->sensor = SEN_OV76BE;
1018 } else if ((rc & 3) == 0) {
1019 /* try to read product id registers */
1020 high = i2c_r(sd, 0x0a);
1021 if (high < 0) {
1022 PDEBUG(D_ERR, "Error detecting camera chip PID");
1023 return high;
1024 }
1025 low = i2c_r(sd, 0x0b);
1026 if (low < 0) {
1027 PDEBUG(D_ERR, "Error detecting camera chip VER");
1028 return low;
1029 }
1030 if (high == 0x76) {
1031 if (low == 0x30) {
1032 PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635");
1033 sd->sensor = SEN_OV7630;
1034 } else if (low == 0x40) {
1035 PDEBUG(D_PROBE, "Sensor is an OV7645");
1036 sd->sensor = SEN_OV7640; /* FIXME */
1037 } else if (low == 0x45) {
1038 PDEBUG(D_PROBE, "Sensor is an OV7645B");
1039 sd->sensor = SEN_OV7640; /* FIXME */
1040 } else if (low == 0x48) {
1041 PDEBUG(D_PROBE, "Sensor is an OV7648");
1042 sd->sensor = SEN_OV7640; /* FIXME */
1043 } else {
1044 PDEBUG(D_PROBE, "Unknown sensor: 0x76%X", low);
1045 return -1;
1046 }
1047 } else {
1048 PDEBUG(D_PROBE, "Sensor is an OV7620");
1049 sd->sensor = SEN_OV7620;
1050 }
1051 } else {
1052 PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
1053 return -1;
1054 }
1055
1056 if (sd->sensor == SEN_OV7620) {
1057 PDEBUG(D_PROBE, "Writing 7620 registers");
1058 if (write_i2c_regvals(sd, norm_7620,
1059 sizeof norm_7620 / sizeof norm_7620[0]))
1060 return -1;
1061 } else if (sd->sensor == SEN_OV7630) {
1062 PDEBUG(D_ERR, "7630 is not supported by this driver version");
1063 return -1;
1064 } else if (sd->sensor == SEN_OV7640) {
1065 PDEBUG(D_PROBE, "Writing 7640 registers");
1066 if (write_i2c_regvals(sd, norm_7640,
1067 sizeof norm_7640 / sizeof norm_7640[0]))
1068 return -1;
1069 } else if (sd->sensor == SEN_OV7670) {
1070 PDEBUG(D_PROBE, "Writing 7670 registers");
1071 if (write_i2c_regvals(sd, norm_7670,
1072 sizeof norm_7670 / sizeof norm_7670[0]))
1073 return -1;
1074 } else {
1075 PDEBUG(D_PROBE, "Writing 7610 registers");
1076 if (write_i2c_regvals(sd, norm_7610,
1077 sizeof norm_7610 / sizeof norm_7610[0]))
1078 return -1;
1079 }
1080
1081 /* Set sensor-specific vars */
1082 sd->maxwidth = 640;
1083 sd->maxheight = 480;
1084 return 0;
1085}
1086
1087/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
1088static int ov6xx0_configure(struct sd *sd)
1089{
1090 int rc;
1091 static const struct ov_i2c_regvals norm_6x20[] = {
1092 { 0x12, 0x80 }, /* reset */
1093 { 0x11, 0x01 },
1094 { 0x03, 0x60 },
1095 { 0x05, 0x7f }, /* For when autoadjust is off */
1096 { 0x07, 0xa8 },
1097 /* The ratio of 0x0c and 0x0d controls the white point */
1098 { 0x0c, 0x24 },
1099 { 0x0d, 0x24 },
1100 { 0x0f, 0x15 }, /* COMS */
1101 { 0x10, 0x75 }, /* AEC Exposure time */
1102 { 0x12, 0x24 }, /* Enable AGC */
1103 { 0x14, 0x04 },
1104 /* 0x16: 0x06 helps frame stability with moving objects */
1105 { 0x16, 0x06 },
1106/* { 0x20, 0x30 }, * Aperture correction enable */
1107 { 0x26, 0xb2 }, /* BLC enable */
1108 /* 0x28: 0x05 Selects RGB format if RGB on */
1109 { 0x28, 0x05 },
1110 { 0x2a, 0x04 }, /* Disable framerate adjust */
1111/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */
1112 { 0x2d, 0x99 },
1113 { 0x33, 0xa0 }, /* Color Processing Parameter */
1114 { 0x34, 0xd2 }, /* Max A/D range */
1115 { 0x38, 0x8b },
1116 { 0x39, 0x40 },
1117
1118 { 0x3c, 0x39 }, /* Enable AEC mode changing */
1119 { 0x3c, 0x3c }, /* Change AEC mode */
1120 { 0x3c, 0x24 }, /* Disable AEC mode changing */
1121
1122 { 0x3d, 0x80 },
1123 /* These next two registers (0x4a, 0x4b) are undocumented.
1124 * They control the color balance */
1125 { 0x4a, 0x80 },
1126 { 0x4b, 0x80 },
1127 { 0x4d, 0xd2 }, /* This reduces noise a bit */
1128 { 0x4e, 0xc1 },
1129 { 0x4f, 0x04 },
1130/* Do 50-53 have any effect? */
1131/* Toggle 0x12[2] off and on here? */
1132 };
1133
1134 static const struct ov_i2c_regvals norm_6x30[] = {
1135 { 0x12, 0x80 }, /* Reset */
1136 { 0x00, 0x1f }, /* Gain */
1137 { 0x01, 0x99 }, /* Blue gain */
1138 { 0x02, 0x7c }, /* Red gain */
1139 { 0x03, 0xc0 }, /* Saturation */
1140 { 0x05, 0x0a }, /* Contrast */
1141 { 0x06, 0x95 }, /* Brightness */
1142 { 0x07, 0x2d }, /* Sharpness */
1143 { 0x0c, 0x20 },
1144 { 0x0d, 0x20 },
1145 { 0x0e, 0x20 },
1146 { 0x0f, 0x05 },
1147 { 0x10, 0x9a },
1148 { 0x11, 0x00 }, /* Pixel clock = fastest */
1149 { 0x12, 0x24 }, /* Enable AGC and AWB */
1150 { 0x13, 0x21 },
1151 { 0x14, 0x80 },
1152 { 0x15, 0x01 },
1153 { 0x16, 0x03 },
1154 { 0x17, 0x38 },
1155 { 0x18, 0xea },
1156 { 0x19, 0x04 },
1157 { 0x1a, 0x93 },
1158 { 0x1b, 0x00 },
1159 { 0x1e, 0xc4 },
1160 { 0x1f, 0x04 },
1161 { 0x20, 0x20 },
1162 { 0x21, 0x10 },
1163 { 0x22, 0x88 },
1164 { 0x23, 0xc0 }, /* Crystal circuit power level */
1165 { 0x25, 0x9a }, /* Increase AEC black ratio */
1166 { 0x26, 0xb2 }, /* BLC enable */
1167 { 0x27, 0xa2 },
1168 { 0x28, 0x00 },
1169 { 0x29, 0x00 },
1170 { 0x2a, 0x84 }, /* 60 Hz power */
1171 { 0x2b, 0xa8 }, /* 60 Hz power */
1172 { 0x2c, 0xa0 },
1173 { 0x2d, 0x95 }, /* Enable auto-brightness */
1174 { 0x2e, 0x88 },
1175 { 0x33, 0x26 },
1176 { 0x34, 0x03 },
1177 { 0x36, 0x8f },
1178 { 0x37, 0x80 },
1179 { 0x38, 0x83 },
1180 { 0x39, 0x80 },
1181 { 0x3a, 0x0f },
1182 { 0x3b, 0x3c },
1183 { 0x3c, 0x1a },
1184 { 0x3d, 0x80 },
1185 { 0x3e, 0x80 },
1186 { 0x3f, 0x0e },
1187 { 0x40, 0x00 }, /* White bal */
1188 { 0x41, 0x00 }, /* White bal */
1189 { 0x42, 0x80 },
1190 { 0x43, 0x3f }, /* White bal */
1191 { 0x44, 0x80 },
1192 { 0x45, 0x20 },
1193 { 0x46, 0x20 },
1194 { 0x47, 0x80 },
1195 { 0x48, 0x7f },
1196 { 0x49, 0x00 },
1197 { 0x4a, 0x00 },
1198 { 0x4b, 0x80 },
1199 { 0x4c, 0xd0 },
1200 { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
1201 { 0x4e, 0x40 },
1202 { 0x4f, 0x07 }, /* UV avg., col. killer: max */
1203 { 0x50, 0xff },
1204 { 0x54, 0x23 }, /* Max AGC gain: 18dB */
1205 { 0x55, 0xff },
1206 { 0x56, 0x12 },
1207 { 0x57, 0x81 },
1208 { 0x58, 0x75 },
1209 { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
1210 { 0x5a, 0x2c },
1211 { 0x5b, 0x0f }, /* AWB chrominance levels */
1212 { 0x5c, 0x10 },
1213 { 0x3d, 0x80 },
1214 { 0x27, 0xa6 },
1215 { 0x12, 0x20 }, /* Toggle AWB */
1216 { 0x12, 0x24 },
1217 };
1218
1219 PDEBUG(D_PROBE, "starting sensor configuration");
1220
1221 if (init_ov_sensor(sd) < 0) {
1222 PDEBUG(D_ERR, "Failed to read sensor ID.");
1223 return -1;
1224 }
1225 PDEBUG(D_PROBE, "OV6xx0 sensor detected");
1226
1227 /* Detect sensor (sub)type */
1228 rc = i2c_r(sd, OV7610_REG_COM_I);
1229 if (rc < 0) {
1230 PDEBUG(D_ERR, "Error detecting sensor type");
1231 return -1;
1232 }
1233
1234 /* Ugh. The first two bits are the version bits, but
1235 * the entire register value must be used. I guess OVT
1236 * underestimated how many variants they would make. */
1237 if (rc == 0x00) {
1238 sd->sensor = SEN_OV6630;
1239 PDEBUG(D_ERR,
1240 "WARNING: Sensor is an OV66308. Your camera may have");
1241 PDEBUG(D_ERR, "been misdetected in previous driver versions.");
1242 } else if (rc == 0x01) {
1243 sd->sensor = SEN_OV6620;
1244 PDEBUG(D_PROBE, "Sensor is an OV6620");
1245 } else if (rc == 0x02) {
1246 sd->sensor = SEN_OV6630;
1247 PDEBUG(D_PROBE, "Sensor is an OV66308AE");
1248 } else if (rc == 0x03) {
1249 sd->sensor = SEN_OV6630;
1250 PDEBUG(D_PROBE, "Sensor is an OV66308AF");
1251 } else if (rc == 0x90) {
1252 sd->sensor = SEN_OV6630;
1253 PDEBUG(D_ERR,
1254 "WARNING: Sensor is an OV66307. Your camera may have");
1255 PDEBUG(D_ERR, "been misdetected in previous driver versions.");
1256 } else {
1257 PDEBUG(D_ERR, "FATAL: Unknown sensor version: 0x%02x", rc);
1258 return -1;
1259 }
1260
1261 /* Set sensor-specific vars */
1262 sd->maxwidth = 352;
1263 sd->maxheight = 288;
1264
1265 if (sd->sensor == SEN_OV6620) {
1266 PDEBUG(D_PROBE, "Writing 6x20 registers");
1267 if (write_i2c_regvals(sd, norm_6x20,
1268 sizeof norm_6x20 / sizeof norm_6x20[0]))
1269 return -1;
1270 } else {
1271 PDEBUG(D_PROBE, "Writing 6x30 registers");
1272 if (write_i2c_regvals(sd, norm_6x30,
1273 sizeof norm_6x30 / sizeof norm_6x30[0]))
1274 return -1;
1275 }
1276 return 0;
1277}
1278
1279/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
1280static void ov51x_led_control(struct sd *sd, int on)
1281{
1282 PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off");
1283
1284/* if (sd->bridge == BRG_OV511PLUS) */
1285/* reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); */
1286/* else if (sd->bridge == BRG_OV519) */
1287 reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
1288/* else if (sd->bclass == BCL_OV518) */
1289/* reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); */
1290}
1291
1292/* this function is called at probe time */
1293static int sd_config(struct gspca_dev *gspca_dev,
1294 const struct usb_device_id *id)
1295{
1296 struct sd *sd = (struct sd *) gspca_dev;
1297 struct cam *cam;
1298
1299/* (from ov519_configure) */
1300 static const struct ov_regvals init_519[] = {
1301 { 0x5a, 0x6d }, /* EnableSystem */
1302/* jfm trace usbsnoop3-1.txt */
1303/* jfm 53 = fb */
1304 { 0x53, 0x9b },
1305 { 0x54, 0xff }, /* set bit2 to enable jpeg */
1306 { 0x5d, 0x03 },
1307 { 0x49, 0x01 },
1308 { 0x48, 0x00 },
1309 /* Set LED pin to output mode. Bit 4 must be cleared or sensor
1310 * detection will fail. This deserves further investigation. */
1311 { OV519_GPIO_IO_CTRL0, 0xee },
1312 { 0x51, 0x0f }, /* SetUsbInit */
1313 { 0x51, 0x00 },
1314 { 0x22, 0x00 },
1315 /* windows reads 0x55 at this point*/
1316 };
1317
1318 if (write_regvals(sd, init_519, ARRAY_SIZE(init_519)))
1319 goto error;
1320/* jfm: not seen in windows trace */
1321 if (ov519_init_compression(sd))
1322 goto error;
1323 ov51x_led_control(sd, 0); /* turn LED off */
1324
1325 /* Test for 76xx */
1326 sd->primary_i2c_slave = OV7xx0_SID;
1327 if (ov51x_set_slave_ids(sd, OV7xx0_SID) < 0)
1328 goto error;
1329
1330 /* The OV519 must be more aggressive about sensor detection since
1331 * I2C write will never fail if the sensor is not present. We have
1332 * to try to initialize the sensor to detect its presence */
1333 if (init_ov_sensor(sd) < 0) {
1334 /* Test for 6xx0 */
1335 sd->primary_i2c_slave = OV6xx0_SID;
1336 if (ov51x_set_slave_ids(sd, OV6xx0_SID) < 0)
1337 goto error;
1338
1339 if (init_ov_sensor(sd) < 0) {
1340 /* Test for 8xx0 */
1341 sd->primary_i2c_slave = OV8xx0_SID;
1342 if (ov51x_set_slave_ids(sd, OV8xx0_SID) < 0)
1343 goto error;
1344
1345 if (init_ov_sensor(sd) < 0) {
1346 PDEBUG(D_ERR,
1347 "Can't determine sensor slave IDs");
1348 goto error;
1349 } else {
1350 if (ov8xx0_configure(sd) < 0) {
1351 PDEBUG(D_ERR,
1352 "Failed to configure OV8xx0 sensor");
1353 goto error;
1354 }
1355 }
1356 } else {
1357 if (ov6xx0_configure(sd) < 0) {
1358 PDEBUG(D_ERR, "Failed to configure OV6xx0");
1359 goto error;
1360 }
1361 }
1362 } else {
1363 if (ov7xx0_configure(sd) < 0) {
1364 PDEBUG(D_ERR, "Failed to configure OV7xx0");
1365 goto error;
1366 }
1367 }
1368
1369 cam = &gspca_dev->cam;
1370 cam->epaddr = OV511_ENDPOINT_ADDRESS;
1371 if (sd->maxwidth == 640) {
1372 cam->cam_mode = vga_mode;
1373 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1374 } else {
1375 cam->cam_mode = sif_mode;
1376 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
1377 }
1378 cam->dev_name = (char *) id->driver_info;
1379 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1380 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1381 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1382 return 0;
1383error:
1384 PDEBUG(D_ERR, "OV519 Config failed");
1385 return -EBUSY;
1386}
1387
1388/* this function is called at open time */
1389static int sd_open(struct gspca_dev *gspca_dev)
1390{
1391 return 0;
1392}
1393
1394/* Sets up the OV519 with the given image parameters
1395 *
1396 * OV519 needs a completely different approach, until we can figure out what
1397 * the individual registers do.
1398 *
1399 * Do not put any sensor-specific code in here (including I2C I/O functions)
1400 */
1401static int ov519_mode_init_regs(struct sd *sd,
1402 int width, int height)
1403{
1404 static const struct ov_regvals mode_init_519_ov7670[] = {
1405 { 0x5d, 0x03 }, /* Turn off suspend mode */
1406 { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
1407 { 0x54, 0x0f }, /* bit2 (jpeg enable) */
1408 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
1409 { 0xa3, 0x18 },
1410 { 0xa4, 0x04 },
1411 { 0xa5, 0x28 },
1412 { 0x37, 0x00 }, /* SetUsbInit */
1413 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
1414 /* Enable both fields, YUV Input, disable defect comp (why?) */
1415 { 0x20, 0x0c },
1416 { 0x21, 0x38 },
1417 { 0x22, 0x1d },
1418 { 0x17, 0x50 }, /* undocumented */
1419 { 0x37, 0x00 }, /* undocumented */
1420 { 0x40, 0xff }, /* I2C timeout counter */
1421 { 0x46, 0x00 }, /* I2C clock prescaler */
1422 { 0x59, 0x04 }, /* new from windrv 090403 */
1423 { 0xff, 0x00 }, /* undocumented */
1424 /* windows reads 0x55 at this point, why? */
1425 };
1426
1427 static const struct ov_regvals mode_init_519[] = {
1428 { 0x5d, 0x03 }, /* Turn off suspend mode */
1429 { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
1430 { 0x54, 0x0f }, /* bit2 (jpeg enable) */
1431 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
1432 { 0xa3, 0x18 },
1433 { 0xa4, 0x04 },
1434 { 0xa5, 0x28 },
1435 { 0x37, 0x00 }, /* SetUsbInit */
1436 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
1437 /* Enable both fields, YUV Input, disable defect comp (why?) */
1438 { 0x22, 0x1d },
1439 { 0x17, 0x50 }, /* undocumented */
1440 { 0x37, 0x00 }, /* undocumented */
1441 { 0x40, 0xff }, /* I2C timeout counter */
1442 { 0x46, 0x00 }, /* I2C clock prescaler */
1443 { 0x59, 0x04 }, /* new from windrv 090403 */
1444 { 0xff, 0x00 }, /* undocumented */
1445 /* windows reads 0x55 at this point, why? */
1446 };
1447
1448/* int hi_res; */
1449
1450 PDEBUG(D_CONF, "mode init %dx%d", width, height);
1451
1452/* if (width >= 800 && height >= 600)
1453 hi_res = 1;
1454 else
1455 hi_res = 0; */
1456
1457/* if (ov51x_stop(sd) < 0)
1458 return -EIO; */
1459
1460 /******** Set the mode ********/
1461 if (sd->sensor != SEN_OV7670) {
1462 if (write_regvals(sd, mode_init_519,
1463 ARRAY_SIZE(mode_init_519)))
1464 return -EIO;
1465 } else {
1466 if (write_regvals(sd, mode_init_519_ov7670,
1467 ARRAY_SIZE(mode_init_519_ov7670)))
1468 return -EIO;
1469 }
1470
1471 if (sd->sensor == SEN_OV7640) {
1472 /* Select 8-bit input mode */
1473 reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10);
1474 }
1475
1476 reg_w(sd, OV519_CAM_H_SIZE, width >> 4);
1477 reg_w(sd, OV519_CAM_V_SIZE, height >> 3);
1478 reg_w(sd, OV519_CAM_X_OFFSETL, 0x00);
1479 reg_w(sd, OV519_CAM_X_OFFSETH, 0x00);
1480 reg_w(sd, OV519_CAM_Y_OFFSETL, 0x00);
1481 reg_w(sd, OV519_CAM_Y_OFFSETH, 0x00);
1482 reg_w(sd, OV519_CAM_DIVIDER, 0x00);
1483 reg_w(sd, OV519_CAM_FORMAT, 0x03); /* YUV422 */
1484 reg_w(sd, 0x26, 0x00); /* Undocumented */
1485
1486 /******** Set the framerate ********/
1487 if (frame_rate > 0)
1488 sd->frame_rate = frame_rate;
1489
1490/* FIXME: These are only valid at the max resolution. */
1491 sd->clockdiv = 0;
1492 if (sd->sensor == SEN_OV7640) {
1493 switch (sd->frame_rate) {
1494/*jfm: default was 30 fps */
1495 case 30:
1496 reg_w(sd, 0xa4, 0x0c);
1497 reg_w(sd, 0x23, 0xff);
1498 break;
1499 case 25:
1500 reg_w(sd, 0xa4, 0x0c);
1501 reg_w(sd, 0x23, 0x1f);
1502 break;
1503 case 20:
1504 reg_w(sd, 0xa4, 0x0c);
1505 reg_w(sd, 0x23, 0x1b);
1506 break;
1507 default:
1508/* case 15: */
1509 reg_w(sd, 0xa4, 0x04);
1510 reg_w(sd, 0x23, 0xff);
1511 sd->clockdiv = 1;
1512 break;
1513 case 10:
1514 reg_w(sd, 0xa4, 0x04);
1515 reg_w(sd, 0x23, 0x1f);
1516 sd->clockdiv = 1;
1517 break;
1518 case 5:
1519 reg_w(sd, 0xa4, 0x04);
1520 reg_w(sd, 0x23, 0x1b);
1521 sd->clockdiv = 1;
1522 break;
1523 }
1524 } else if (sd->sensor == SEN_OV8610) {
1525 switch (sd->frame_rate) {
1526 default: /* 15 fps */
1527/* case 15: */
1528 reg_w(sd, 0xa4, 0x06);
1529 reg_w(sd, 0x23, 0xff);
1530 break;
1531 case 10:
1532 reg_w(sd, 0xa4, 0x06);
1533 reg_w(sd, 0x23, 0x1f);
1534 break;
1535 case 5:
1536 reg_w(sd, 0xa4, 0x06);
1537 reg_w(sd, 0x23, 0x1b);
1538 break;
1539 }
1540 sd->clockdiv = 0;
1541 } else if (sd->sensor == SEN_OV7670) { /* guesses, based on 7640 */
1542 PDEBUG(D_STREAM, "Setting framerate to %d fps",
1543 (sd->frame_rate == 0) ? 15 : sd->frame_rate);
1544 switch (sd->frame_rate) {
1545 case 30:
1546 reg_w(sd, 0xa4, 0x10);
1547 reg_w(sd, 0x23, 0xff);
1548 break;
1549 case 20:
1550 reg_w(sd, 0xa4, 0x10);
1551 reg_w(sd, 0x23, 0x1b);
1552 break;
1553 default: /* 15 fps */
1554/* case 15: */
1555 reg_w(sd, 0xa4, 0x10);
1556 reg_w(sd, 0x23, 0xff);
1557 sd->clockdiv = 1;
1558 break;
1559 }
1560 }
1561
1562/* if (ov51x_restart(sd) < 0)
1563 return -EIO; */
1564
1565 /* Reset it just for good measure */
1566/* if (ov51x_reset(sd, OV511_RESET_NOREGS) < 0)
1567 return -EIO; */
1568 return 0;
1569}
1570
1571static int mode_init_ov_sensor_regs(struct sd *sd,
1572 struct ovsensor_window *win)
1573{
1574 int qvga = win->quarter;
1575
1576 /******** Mode (VGA/QVGA) and sensor specific regs ********/
1577 switch (sd->sensor) {
1578 case SEN_OV8610:
1579 /* For OV8610 qvga means qsvga */
1580 i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
1581 break;
1582 case SEN_OV7610:
1583 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1584 break;
1585 case SEN_OV7620:
1586/* i2c_w(sd, 0x2b, 0x00); */
1587 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1588 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
1589 i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
1590 i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
1591 i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
1592 i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
1593 i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
1594 break;
1595 case SEN_OV76BE:
1596/* i2c_w(sd, 0x2b, 0x00); */
1597 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1598 break;
1599 case SEN_OV7640:
1600/* i2c_w(sd, 0x2b, 0x00); */
1601 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1602 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
1603/* i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */
1604/* i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); */
1605/* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */
1606/* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */
1607/* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */
1608 break;
1609 case SEN_OV7670:
1610 /* set COM7_FMT_VGA or COM7_FMT_QVGA
1611 * do we need to set anything else?
1612 * HSTART etc are set in set_ov_sensor_window itself */
1613 i2c_w_mask(sd, OV7670_REG_COM7,
1614 qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA,
1615 OV7670_COM7_FMT_MASK);
1616 break;
1617 case SEN_OV6620:
1618 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1619 break;
1620 case SEN_OV6630:
1621 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1622 break;
1623 default:
1624 return -EINVAL;
1625 }
1626
1627 /******** Palette-specific regs ********/
1628/* Need to do work here for the OV7670 */
1629
1630 if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
1631 /* not valid on the OV6620/OV7620/6630? */
1632 i2c_w_mask(sd, 0x0e, 0x00, 0x40);
1633 }
1634
1635 /* The OV518 needs special treatment. Although both the OV518
1636 * and the OV6630 support a 16-bit video bus, only the 8 bit Y
1637 * bus is actually used. The UV bus is tied to ground.
1638 * Therefore, the OV6630 needs to be in 8-bit multiplexed
1639 * output mode */
1640
1641 /* OV7640 is 8-bit only */
1642
1643 if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640)
1644 i2c_w_mask(sd, 0x13, 0x00, 0x20);
1645/* } */
1646
1647 /******** Clock programming ********/
1648 /* The OV6620 needs special handling. This prevents the
1649 * severe banding that normally occurs */
1650 if (sd->sensor == SEN_OV6620) {
1651
1652 /* Clock down */
1653 i2c_w(sd, 0x2a, 0x04);
1654 i2c_w(sd, 0x11, win->clockdiv);
1655 i2c_w(sd, 0x2a, 0x84);
1656 /* This next setting is critical. It seems to improve
1657 * the gain or the contrast. The "reserved" bits seem
1658 * to have some effect in this case. */
1659 i2c_w(sd, 0x2d, 0x85);
1660 } else if (win->clockdiv >= 0) {
1661 i2c_w(sd, 0x11, win->clockdiv);
1662 }
1663
1664 /******** Special Features ********/
1665/* no evidence this is possible with OV7670, either */
1666 /* Test Pattern */
1667 if (sd->sensor != SEN_OV7640 && sd->sensor != SEN_OV7670)
1668 i2c_w_mask(sd, 0x12, 0x00, 0x02);
1669
1670 /* Enable auto white balance */
1671 if (sd->sensor == SEN_OV7670)
1672 i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB,
1673 OV7670_COM8_AWB);
1674 else
1675 i2c_w_mask(sd, 0x12, 0x04, 0x04);
1676
1677 /* This will go away as soon as ov51x_mode_init_sensor_regs() */
1678 /* is fully tested. */
1679 /* 7620/6620/6630? don't have register 0x35, so play it safe */
1680 if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
1681 if (win->width == 640 /*&& win->height == 480*/)
1682 i2c_w(sd, 0x35, 0x9e);
1683 else
1684 i2c_w(sd, 0x35, 0x1e);
1685 }
1686 return 0;
1687}
1688
1689static int set_ov_sensor_window(struct sd *sd,
1690 struct ovsensor_window *win)
1691{
1692 int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
1693 int ret, hstart, hstop, vstop, vstart;
1694 __u8 v;
1695
1696 /* The different sensor ICs handle setting up of window differently.
1697 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
1698 switch (sd->sensor) {
1699 case SEN_OV8610:
1700 hwsbase = 0x1e;
1701 hwebase = 0x1e;
1702 vwsbase = 0x02;
1703 vwebase = 0x02;
1704 break;
1705 case SEN_OV7610:
1706 case SEN_OV76BE:
1707 hwsbase = 0x38;
1708 hwebase = 0x3a;
1709 vwsbase = vwebase = 0x05;
1710 break;
1711 case SEN_OV6620:
1712 case SEN_OV6630:
1713 hwsbase = 0x38;
1714 hwebase = 0x3a;
1715 vwsbase = 0x05;
1716 vwebase = 0x06;
1717 break;
1718 case SEN_OV7620:
1719 hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */
1720 hwebase = 0x2f;
1721 vwsbase = vwebase = 0x05;
1722 break;
1723 case SEN_OV7640:
1724 hwsbase = 0x1a;
1725 hwebase = 0x1a;
1726 vwsbase = vwebase = 0x03;
1727 break;
1728 case SEN_OV7670:
1729 /*handling of OV7670 hardware sensor start and stop values
1730 * is very odd, compared to the other OV sensors */
1731 vwsbase = vwebase = hwebase = hwsbase = 0x00;
1732 break;
1733 default:
1734 return -EINVAL;
1735 }
1736
1737 switch (sd->sensor) {
1738 case SEN_OV6620:
1739 case SEN_OV6630:
1740 if (win->quarter) { /* QCIF */
1741 hwscale = 0;
1742 vwscale = 0;
1743 } else { /* CIF */
1744 hwscale = 1;
1745 vwscale = 1; /* The datasheet says 0;
1746 * it's wrong */
1747 }
1748 break;
1749 case SEN_OV8610:
1750 if (win->quarter) { /* QSVGA */
1751 hwscale = 1;
1752 vwscale = 1;
1753 } else { /* SVGA */
1754 hwscale = 2;
1755 vwscale = 2;
1756 }
1757 break;
1758 default: /* SEN_OV7xx0 */
1759 if (win->quarter) { /* QVGA */
1760 hwscale = 1;
1761 vwscale = 0;
1762 } else { /* VGA */
1763 hwscale = 2;
1764 vwscale = 1;
1765 }
1766 }
1767
1768 ret = mode_init_ov_sensor_regs(sd, win);
1769 if (ret < 0)
1770 return ret;
1771
1772 if (sd->sensor == SEN_OV8610) {
1773 i2c_w_mask(sd, 0x2d, 0x05, 0x40);
1774 /* old 0x95, new 0x05 from windrv 090403 */
1775 /* bits 5-7: reserved */
1776 i2c_w_mask(sd, 0x28, 0x20, 0x20);
1777 /* bit 5: progressive mode on */
1778 }
1779
1780 /* The below is wrong for OV7670s because their window registers
1781 * only store the high bits in 0x17 to 0x1a */
1782
1783 /* SRH Use sd->max values instead of requested win values */
1784 /* SCS Since we're sticking with only the max hardware widths
1785 * for a given mode */
1786 /* I can hard code this for OV7670s */
1787 /* Yes, these numbers do look odd, but they're tested and work! */
1788 if (sd->sensor == SEN_OV7670) {
1789 if (win->quarter) { /* QVGA from ov7670.c by
1790 * Jonathan Corbet */
1791 hstart = 164;
1792 hstop = 20;
1793 vstart = 14;
1794 vstop = 494;
1795 } else { /* VGA */
1796 hstart = 158;
1797 hstop = 14;
1798 vstart = 10;
1799 vstop = 490;
1800 }
1801 /* OV7670 hardware window registers are split across
1802 * multiple locations */
1803 i2c_w(sd, OV7670_REG_HSTART, (hstart >> 3) & 0xff);
1804 i2c_w(sd, OV7670_REG_HSTOP, (hstop >> 3) & 0xff);
1805 v = i2c_r(sd, OV7670_REG_HREF);
1806 v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07);
1807 msleep(10); /* need to sleep between read and write to
1808 * same reg! */
1809 i2c_w(sd, OV7670_REG_HREF, v);
1810
1811 i2c_w(sd, OV7670_REG_VSTART, (vstart >> 2) & 0xff);
1812 i2c_w(sd, OV7670_REG_VSTOP, (vstop >> 2) & 0xff);
1813 v = i2c_r(sd, OV7670_REG_VREF);
1814 v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03);
1815 msleep(10); /* need to sleep between read and write to
1816 * same reg! */
1817 i2c_w(sd, OV7670_REG_VREF, v);
1818
1819 } else {
1820 i2c_w(sd, 0x17, hwsbase + (win->x >> hwscale));
1821 i2c_w(sd, 0x18, hwebase + ((win->x + win->width) >> hwscale));
1822 i2c_w(sd, 0x19, vwsbase + (win->y >> vwscale));
1823 i2c_w(sd, 0x1a, vwebase + ((win->y + win->height) >> vwscale));
1824 }
1825 return 0;
1826}
1827
1828static int ov_sensor_mode_setup(struct sd *sd,
1829 int width, int height)
1830{
1831 struct ovsensor_window win;
1832
1833/* win.format = mode; */
1834
1835 /* Unless subcapture is enabled,
1836 * center the image window and downsample
1837 * if possible to increase the field of view */
1838 /* NOTE: OV518(+) and OV519 does downsampling on its own */
1839 win.width = width;
1840 win.height = height;
1841 if (width == sd->maxwidth)
1842 win.quarter = 0;
1843 else
1844 win.quarter = 1;
1845
1846 /* Center it */
1847 win.x = (win.width - width) / 2;
1848 win.y = (win.height - height) / 2;
1849
1850 /* Clock is determined by OV519 frame rate code */
1851 win.clockdiv = sd->clockdiv;
1852
1853 PDEBUG(D_CONF, "Setting clock divider to %d", win.clockdiv);
1854 return set_ov_sensor_window(sd, &win);
1855}
1856
1857/* -- start the camera -- */
1858static void sd_start(struct gspca_dev *gspca_dev)
1859{
1860 struct sd *sd = (struct sd *) gspca_dev;
1861 int ret;
1862
1863
1864 ret = ov519_mode_init_regs(sd, gspca_dev->width, gspca_dev->height);
1865 if (ret < 0)
1866 goto out;
1867 ret = ov_sensor_mode_setup(sd, gspca_dev->width, gspca_dev->height);
1868 if (ret < 0)
1869 goto out;
1870
1871 ret = ov51x_restart((struct sd *) gspca_dev);
1872 if (ret < 0)
1873 goto out;
1874 PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
1875 ov51x_led_control(sd, 1);
1876 return;
1877out:
1878 PDEBUG(D_ERR, "camera start error:%d", ret);
1879}
1880
1881static void sd_stopN(struct gspca_dev *gspca_dev)
1882{
1883 ov51x_stop((struct sd *) gspca_dev);
1884 ov51x_led_control((struct sd *) gspca_dev, 0);
1885}
1886
1887static void sd_stop0(struct gspca_dev *gspca_dev)
1888{
1889}
1890
1891static void sd_close(struct gspca_dev *gspca_dev)
1892{
1893}
1894
1895static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1896 struct gspca_frame *frame, /* target */
1897 __u8 *data, /* isoc packet */
1898 int len) /* iso packet length */
1899{
1900 /* Header of ov519 is 16 bytes:
1901 * Byte Value Description
1902 * 0 0xff magic
1903 * 1 0xff magic
1904 * 2 0xff magic
1905 * 3 0xXX 0x50 = SOF, 0x51 = EOF
1906 * 9 0xXX 0x01 initial frame without data,
1907 * 0x00 standard frame with image
1908 * 14 Lo in EOF: length of image data / 8
1909 * 15 Hi
1910 */
1911
1912 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
1913 switch (data[3]) {
1914 case 0x50: /* start of frame */
1915#define HDRSZ 16
1916 data += HDRSZ;
1917 len -= HDRSZ;
1918#undef HDRSZ
1919 if (data[0] == 0xff || data[1] == 0xd8)
1920 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1921 data, len);
1922 else
1923 gspca_dev->last_packet_type = DISCARD_PACKET;
1924 return;
1925 case 0x51: /* end of frame */
1926 if (data[9] != 0)
1927 gspca_dev->last_packet_type = DISCARD_PACKET;
1928 gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1929 data, 0);
1930 return;
1931 }
1932 }
1933
1934 /* intermediate packet */
1935 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1936 data, len);
1937}
1938
1939/* -- management routines -- */
1940
1941static void setbrightness(struct gspca_dev *gspca_dev)
1942{
1943 struct sd *sd = (struct sd *) gspca_dev;
1944 int val;
1945/* int was_streaming; */
1946
1947 val = sd->brightness;
1948 PDEBUG(D_CONF, "brightness:%d", val);
1949/* was_streaming = gspca_dev->streaming;
1950 * if (was_streaming)
1951 * ov51x_stop(sd); */
1952 switch (sd->sensor) {
1953 case SEN_OV8610:
1954 case SEN_OV7610:
1955 case SEN_OV76BE:
1956 case SEN_OV6620:
1957 case SEN_OV6630:
1958 case SEN_OV7640:
1959 i2c_w(sd, OV7610_REG_BRT, val);
1960 break;
1961 case SEN_OV7620:
1962 /* 7620 doesn't like manual changes when in auto mode */
1963/*fixme
1964 * if (!sd->auto_brt) */
1965 i2c_w(sd, OV7610_REG_BRT, val);
1966 break;
1967 case SEN_OV7670:
1968/*jfm - from windblows
1969 * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */
1970 i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val));
1971 break;
1972 }
1973/* if (was_streaming)
1974 * ov51x_restart(sd); */
1975}
1976
1977static void setcontrast(struct gspca_dev *gspca_dev)
1978{
1979 struct sd *sd = (struct sd *) gspca_dev;
1980 int val;
1981/* int was_streaming; */
1982
1983 val = sd->contrast;
1984 PDEBUG(D_CONF, "contrast:%d", val);
1985/* was_streaming = gspca_dev->streaming;
1986 if (was_streaming)
1987 ov51x_stop(sd); */
1988 switch (sd->sensor) {
1989 case SEN_OV7610:
1990 case SEN_OV6620:
1991 i2c_w(sd, OV7610_REG_CNT, val);
1992 break;
1993 case SEN_OV6630:
1994 i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
1995 case SEN_OV8610: {
1996 static const __u8 ctab[] = {
1997 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
1998 };
1999
2000 /* Use Y gamma control instead. Bit 0 enables it. */
2001 i2c_w(sd, 0x64, ctab[val >> 5]);
2002 break;
2003 }
2004 case SEN_OV7620: {
2005 static const __u8 ctab[] = {
2006 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
2007 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
2008 };
2009
2010 /* Use Y gamma control instead. Bit 0 enables it. */
2011 i2c_w(sd, 0x64, ctab[val >> 4]);
2012 break;
2013 }
2014 case SEN_OV7640:
2015 /* Use gain control instead. */
2016 i2c_w(sd, OV7610_REG_GAIN, val >> 2);
2017 break;
2018 case SEN_OV7670:
2019 /* check that this isn't just the same as ov7610 */
2020 i2c_w(sd, OV7670_REG_CONTRAS, val >> 1);
2021 break;
2022 }
2023/* if (was_streaming)
2024 ov51x_restart(sd); */
2025}
2026
2027static void setcolors(struct gspca_dev *gspca_dev)
2028{
2029 struct sd *sd = (struct sd *) gspca_dev;
2030 int val;
2031/* int was_streaming; */
2032
2033 val = sd->colors;
2034 PDEBUG(D_CONF, "saturation:%d", val);
2035/* was_streaming = gspca_dev->streaming;
2036 if (was_streaming)
2037 ov51x_stop(sd); */
2038 switch (sd->sensor) {
2039 case SEN_OV8610:
2040 case SEN_OV7610:
2041 case SEN_OV76BE:
2042 case SEN_OV6620:
2043 case SEN_OV6630:
2044 i2c_w(sd, OV7610_REG_SAT, val);
2045 break;
2046 case SEN_OV7620:
2047 /* Use UV gamma control instead. Bits 0 & 7 are reserved. */
2048/* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e);
2049 if (rc < 0)
2050 goto out; */
2051 i2c_w(sd, OV7610_REG_SAT, val);
2052 break;
2053 case SEN_OV7640:
2054 i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
2055 break;
2056 case SEN_OV7670:
2057 /* supported later once I work out how to do it
2058 * transparently fail now! */
2059 /* set REG_COM13 values for UV sat auto mode */
2060 break;
2061 }
2062/* if (was_streaming)
2063 ov51x_restart(sd); */
2064}
2065
2066static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
2067{
2068 struct sd *sd = (struct sd *) gspca_dev;
2069
2070 sd->brightness = val;
2071 setbrightness(gspca_dev);
2072 return 0;
2073}
2074
2075static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
2076{
2077 struct sd *sd = (struct sd *) gspca_dev;
2078
2079 *val = sd->brightness;
2080 return 0;
2081}
2082
2083static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
2084{
2085 struct sd *sd = (struct sd *) gspca_dev;
2086
2087 sd->contrast = val;
2088 setcontrast(gspca_dev);
2089 return 0;
2090}
2091
2092static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
2093{
2094 struct sd *sd = (struct sd *) gspca_dev;
2095
2096 *val = sd->contrast;
2097 return 0;
2098}
2099
2100static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
2101{
2102 struct sd *sd = (struct sd *) gspca_dev;
2103
2104 sd->colors = val;
2105 setcolors(gspca_dev);
2106 return 0;
2107}
2108
2109static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
2110{
2111 struct sd *sd = (struct sd *) gspca_dev;
2112
2113 *val = sd->colors;
2114 return 0;
2115}
2116
2117/* sub-driver description */
2118static const struct sd_desc sd_desc = {
2119 .name = MODULE_NAME,
2120 .ctrls = sd_ctrls,
2121 .nctrls = ARRAY_SIZE(sd_ctrls),
2122 .config = sd_config,
2123 .open = sd_open,
2124 .start = sd_start,
2125 .stopN = sd_stopN,
2126 .stop0 = sd_stop0,
2127 .close = sd_close,
2128 .pkt_scan = sd_pkt_scan,
2129};
2130
2131/* -- module initialisation -- */
2132#define DVNM(name) .driver_info = (kernel_ulong_t) name
2133static const __devinitdata struct usb_device_id device_table[] = {
2134 {USB_DEVICE(0x041e, 0x4052), DVNM("Creative Live! VISTA IM")},
2135 {USB_DEVICE(0x041e, 0x405f), DVNM("Creative Live! VISTA VF0330")},
2136 {USB_DEVICE(0x041e, 0x4060), DVNM("Creative Live! VISTA VF0350")},
2137 {USB_DEVICE(0x041e, 0x4061), DVNM("Creative Live! VISTA VF0400")},
2138 {USB_DEVICE(0x041e, 0x4064), DVNM("Creative Live! VISTA VF0420")},
2139 {USB_DEVICE(0x041e, 0x4068), DVNM("Creative Live! VISTA VF0470")},
2140 {USB_DEVICE(0x045e, 0x028c), DVNM("Microsoft xbox cam")},
2141 {USB_DEVICE(0x054c, 0x0154), DVNM("Sonny toy4")},
2142 {USB_DEVICE(0x054c, 0x0155), DVNM("Sonny toy5")},
2143 {USB_DEVICE(0x05a9, 0x0519), DVNM("OmniVision")},
2144 {USB_DEVICE(0x05a9, 0x0530), DVNM("OmniVision")},
2145 {USB_DEVICE(0x05a9, 0x4519), DVNM("OmniVision")},
2146 {USB_DEVICE(0x05a9, 0x8519), DVNM("OmniVision")},
2147 {}
2148};
2149#undef DVNAME
2150MODULE_DEVICE_TABLE(usb, device_table);
2151
2152/* -- device connect -- */
2153static int sd_probe(struct usb_interface *intf,
2154 const struct usb_device_id *id)
2155{
2156 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2157 THIS_MODULE);
2158}
2159
2160static struct usb_driver sd_driver = {
2161 .name = MODULE_NAME,
2162 .id_table = device_table,
2163 .probe = sd_probe,
2164 .disconnect = gspca_disconnect,
2165};
2166
2167/* -- module insert / remove -- */
2168static int __init sd_mod_init(void)
2169{
2170 if (usb_register(&sd_driver) < 0)
2171 return -1;
2172 PDEBUG(D_PROBE, "v%s registered", version);
2173 return 0;
2174}
2175static void __exit sd_mod_exit(void)
2176{
2177 usb_deregister(&sd_driver);
2178 PDEBUG(D_PROBE, "deregistered");
2179}
2180
2181module_init(sd_mod_init);
2182module_exit(sd_mod_exit);
2183
2184module_param(frame_rate, int, 0644);
2185MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");
2186
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
new file mode 100644
index 000000000000..fa7abc411090
--- /dev/null
+++ b/drivers/media/video/gspca/pac207.c
@@ -0,0 +1,622 @@
1/*
2 * Pixart PAC207BCA library
3 *
4 * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
5 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
6 * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
7 *
8 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25
26#define MODULE_NAME "pac207"
27
28#include "gspca.h"
29
30#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
31static const char version[] = "2.1.7";
32
33MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
34MODULE_DESCRIPTION("Pixart PAC207");
35MODULE_LICENSE("GPL");
36
37#define PAC207_CTRL_TIMEOUT 100 /* ms */
38
39#define PAC207_BRIGHTNESS_MIN 0
40#define PAC207_BRIGHTNESS_MAX 255
41#define PAC207_BRIGHTNESS_DEFAULT 4 /* power on default: 4 */
42
43/* An exposure value of 4 also works (3 does not) but then we need to lower
44 the compression balance setting when in 352x288 mode, otherwise the usb
45 bandwidth is not enough and packets get dropped resulting in corrupt
46 frames. The problem with this is that when the compression balance gets
47 lowered below 0x80, the pac207 starts using a different compression
48 algorithm for some lines, these lines get prefixed with a 0x2dd2 prefix
49 and currently we do not know how to decompress these lines, so for now
50 we use a minimum exposure value of 5 */
51#define PAC207_EXPOSURE_MIN 5
52#define PAC207_EXPOSURE_MAX 26
53#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 ?? */
54#define PAC207_EXPOSURE_KNEE 11 /* 4 = 30 fps, 11 = 8, 15 = 6 */
55
56#define PAC207_GAIN_MIN 0
57#define PAC207_GAIN_MAX 31
58#define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */
59#define PAC207_GAIN_KNEE 20
60
61#define PAC207_AUTOGAIN_DEADZONE 30
62/* We calculating the autogain at the end of the transfer of a frame, at this
63 moment a frame with the old settings is being transmitted, and a frame is
64 being captured with the old settings. So if we adjust the autogain we must
65 ignore atleast the 2 next frames for the new settings to come into effect
66 before doing any other adjustments */
67#define PAC207_AUTOGAIN_IGNORE_FRAMES 3
68
69/* specific webcam descriptor */
70struct sd {
71 struct gspca_dev gspca_dev; /* !! must be the first item */
72
73 u8 mode;
74
75 u8 brightness;
76 u8 exposure;
77 u8 autogain;
78 u8 gain;
79
80 u8 sof_read;
81 u8 header_read;
82 u8 autogain_ignore_frames;
83
84 atomic_t avg_lum;
85};
86
87/* V4L2 controls supported by the driver */
88static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
90static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
91static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
92static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
93static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
94static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
95static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
96
97static struct ctrl sd_ctrls[] = {
98#define SD_BRIGHTNESS 0
99 {
100 {
101 .id = V4L2_CID_BRIGHTNESS,
102 .type = V4L2_CTRL_TYPE_INTEGER,
103 .name = "Brightness",
104 .minimum = PAC207_BRIGHTNESS_MIN,
105 .maximum = PAC207_BRIGHTNESS_MAX,
106 .step = 1,
107 .default_value = PAC207_BRIGHTNESS_DEFAULT,
108 .flags = 0,
109 },
110 .set = sd_setbrightness,
111 .get = sd_getbrightness,
112 },
113#define SD_EXPOSURE 1
114 {
115 {
116 .id = V4L2_CID_EXPOSURE,
117 .type = V4L2_CTRL_TYPE_INTEGER,
118 .name = "exposure",
119 .minimum = PAC207_EXPOSURE_MIN,
120 .maximum = PAC207_EXPOSURE_MAX,
121 .step = 1,
122 .default_value = PAC207_EXPOSURE_DEFAULT,
123 .flags = 0,
124 },
125 .set = sd_setexposure,
126 .get = sd_getexposure,
127 },
128#define SD_AUTOGAIN 2
129 {
130 {
131 .id = V4L2_CID_AUTOGAIN,
132 .type = V4L2_CTRL_TYPE_BOOLEAN,
133 .name = "Auto Gain",
134 .minimum = 0,
135 .maximum = 1,
136 .step = 1,
137 .default_value = 1,
138 .flags = 0,
139 },
140 .set = sd_setautogain,
141 .get = sd_getautogain,
142 },
143#define SD_GAIN 3
144 {
145 {
146 .id = V4L2_CID_GAIN,
147 .type = V4L2_CTRL_TYPE_INTEGER,
148 .name = "gain",
149 .minimum = PAC207_GAIN_MIN,
150 .maximum = PAC207_GAIN_MAX,
151 .step = 1,
152 .default_value = PAC207_GAIN_DEFAULT,
153 .flags = 0,
154 },
155 .set = sd_setgain,
156 .get = sd_getgain,
157 },
158};
159
160static struct v4l2_pix_format sif_mode[] = {
161 {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
162 .bytesperline = 176,
163 .sizeimage = (176 + 2) * 144,
164 /* uncompressed, add 2 bytes / line for line header */
165 .colorspace = V4L2_COLORSPACE_SRGB,
166 .priv = 1},
167 {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
168 .bytesperline = 352,
169 /* compressed, but only when needed (not compressed
170 when the framerate is low) */
171 .sizeimage = (352 + 2) * 288,
172 .colorspace = V4L2_COLORSPACE_SRGB,
173 .priv = 0},
174};
175
176static const __u8 pac207_sensor_init[][8] = {
177 {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0},
178 {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
179 {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
180 {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02},
181 {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00},
182};
183
184 /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
185static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
186
187static const unsigned char pac207_sof_marker[5] =
188 { 0xff, 0xff, 0x00, 0xff, 0x96 };
189
190static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
191 const u8 *buffer, u16 length)
192{
193 struct usb_device *udev = gspca_dev->dev;
194 int err;
195
196 memcpy(gspca_dev->usb_buf, buffer, length);
197
198 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
199 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
200 0x00, index,
201 gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
202 if (err < 0)
203 PDEBUG(D_ERR,
204 "Failed to write registers to index 0x%04X, error %d)",
205 index, err);
206
207 return err;
208}
209
210
211int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
212{
213 struct usb_device *udev = gspca_dev->dev;
214 int err;
215
216 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
217 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
218 value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
219 if (err)
220 PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
221 " value 0x%02X, error %d)", index, value, err);
222
223 return err;
224}
225
226
227int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
228{
229 struct usb_device *udev = gspca_dev->dev;
230 int res;
231
232 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
233 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
234 0x00, index,
235 gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
236 if (res < 0) {
237 PDEBUG(D_ERR,
238 "Failed to read a register (index 0x%04X, error %d)",
239 index, res);
240 return res;
241 }
242
243 return gspca_dev->usb_buf[0];
244}
245
246/* this function is called at probe time */
247static int sd_config(struct gspca_dev *gspca_dev,
248 const struct usb_device_id *id)
249{
250 struct sd *sd = (struct sd *) gspca_dev;
251 struct cam *cam;
252 u8 idreg[2];
253
254 idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
255 idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
256 idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4);
257 idreg[1] = idreg[1] & 0x0f;
258 PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
259 idreg[0], idreg[1]);
260
261 if (idreg[0] != 0x27) {
262 PDEBUG(D_PROBE, "Error invalid sensor ID!");
263 return -ENODEV;
264 }
265
266 pac207_write_reg(gspca_dev, 0x41, 0x00);
267 /* Bit_0=Image Format,
268 * Bit_1=LED,
269 * Bit_2=Compression test mode enable */
270 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
271 pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
272
273 PDEBUG(D_PROBE,
274 "Pixart PAC207BCA Image Processor and Control Chip detected"
275 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
276
277 cam = &gspca_dev->cam;
278 cam->dev_name = (char *) id->driver_info;
279 cam->epaddr = 0x05;
280 cam->cam_mode = sif_mode;
281 cam->nmodes = ARRAY_SIZE(sif_mode);
282 sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
283 sd->exposure = PAC207_EXPOSURE_DEFAULT;
284 sd->gain = PAC207_GAIN_DEFAULT;
285
286 return 0;
287}
288
289/* this function is called at open time */
290static int sd_open(struct gspca_dev *gspca_dev)
291{
292 struct sd *sd = (struct sd *) gspca_dev;
293
294 sd->autogain = 1;
295 return 0;
296}
297
298/* -- start the camera -- */
299static void sd_start(struct gspca_dev *gspca_dev)
300{
301 struct sd *sd = (struct sd *) gspca_dev;
302 __u8 mode;
303
304 pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
305 pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
306 pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
307 pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
308 pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
309 pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
310 pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
311
312 /* Compression Balance */
313 if (gspca_dev->width == 176)
314 pac207_write_reg(gspca_dev, 0x4a, 0xff);
315 else
316 pac207_write_reg(gspca_dev, 0x4a, 0x88);
317 pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
318 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
319
320 /* PGA global gain (Bit 4-0) */
321 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
322 pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
323
324 mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
325 if (gspca_dev->width == 176) { /* 176x144 */
326 mode |= 0x01;
327 PDEBUG(D_STREAM, "pac207_start mode 176x144");
328 } else { /* 352x288 */
329 PDEBUG(D_STREAM, "pac207_start mode 352x288");
330 }
331 pac207_write_reg(gspca_dev, 0x41, mode);
332
333 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
334 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
335 msleep(10);
336 pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
337
338 sd->sof_read = 0;
339 sd->autogain_ignore_frames = 0;
340 atomic_set(&sd->avg_lum, -1);
341}
342
343static void sd_stopN(struct gspca_dev *gspca_dev)
344{
345 pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
346 pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
347 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
348}
349
350static void sd_stop0(struct gspca_dev *gspca_dev)
351{
352}
353
354/* this function is called at close time */
355static void sd_close(struct gspca_dev *gspca_dev)
356{
357}
358
359static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
360{
361 struct sd *sd = (struct sd *) gspca_dev;
362 int avg_lum = atomic_read(&sd->avg_lum);
363
364 if (avg_lum == -1)
365 return;
366
367 if (sd->autogain_ignore_frames > 0)
368 sd->autogain_ignore_frames--;
369 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
370 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
371 PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
372 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
373}
374
375static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
376 unsigned char *m, int len)
377{
378 struct sd *sd = (struct sd *) gspca_dev;
379 int i;
380
381 /* Search for the SOF marker (fixed part) in the header */
382 for (i = 0; i < len; i++) {
383 if (m[i] == pac207_sof_marker[sd->sof_read]) {
384 sd->sof_read++;
385 if (sd->sof_read == sizeof(pac207_sof_marker)) {
386 PDEBUG(D_STREAM,
387 "SOF found, bytes to analyze: %u."
388 " Frame starts at byte #%u",
389 len, i + 1);
390 sd->sof_read = 0;
391 return m + i + 1;
392 }
393 } else {
394 sd->sof_read = 0;
395 }
396 }
397
398 return NULL;
399}
400
401static void sd_pkt_scan(struct gspca_dev *gspca_dev,
402 struct gspca_frame *frame,
403 __u8 *data,
404 int len)
405{
406 struct sd *sd = (struct sd *) gspca_dev;
407 unsigned char *sof;
408
409 sof = pac207_find_sof(gspca_dev, data, len);
410 if (sof) {
411 int n;
412
413 /* finish decoding current frame */
414 n = sof - data;
415 if (n > sizeof pac207_sof_marker)
416 n -= sizeof pac207_sof_marker;
417 else
418 n = 0;
419 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
420 data, n);
421 sd->header_read = 0;
422 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
423 len -= sof - data;
424 data = sof;
425 }
426 if (sd->header_read < 11) {
427 int needed;
428
429 /* get average lumination from frame header (byte 5) */
430 if (sd->header_read < 5) {
431 needed = 5 - sd->header_read;
432 if (len >= needed)
433 atomic_set(&sd->avg_lum, data[needed - 1]);
434 }
435 /* skip the rest of the header */
436 needed = 11 - sd->header_read;
437 if (len <= needed) {
438 sd->header_read += len;
439 return;
440 }
441 data += needed;
442 len -= needed;
443 sd->header_read = 11;
444 }
445
446 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
447}
448
449static void setbrightness(struct gspca_dev *gspca_dev)
450{
451 struct sd *sd = (struct sd *) gspca_dev;
452
453 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
454 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
455 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
456}
457
458static void setexposure(struct gspca_dev *gspca_dev)
459{
460 struct sd *sd = (struct sd *) gspca_dev;
461
462 pac207_write_reg(gspca_dev, 0x02, sd->exposure);
463 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
464 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
465}
466
467static void setgain(struct gspca_dev *gspca_dev)
468{
469 struct sd *sd = (struct sd *) gspca_dev;
470
471 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
472 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
473 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
474}
475
476static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
477{
478 struct sd *sd = (struct sd *) gspca_dev;
479
480 sd->brightness = val;
481 if (gspca_dev->streaming)
482 setbrightness(gspca_dev);
483 return 0;
484}
485
486static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
487{
488 struct sd *sd = (struct sd *) gspca_dev;
489
490 *val = sd->brightness;
491 return 0;
492}
493
494static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
495{
496 struct sd *sd = (struct sd *) gspca_dev;
497
498 sd->exposure = val;
499 if (gspca_dev->streaming)
500 setexposure(gspca_dev);
501 return 0;
502}
503
504static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
505{
506 struct sd *sd = (struct sd *) gspca_dev;
507
508 *val = sd->exposure;
509 return 0;
510}
511
512static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
513{
514 struct sd *sd = (struct sd *) gspca_dev;
515
516 sd->gain = val;
517 if (gspca_dev->streaming)
518 setgain(gspca_dev);
519 return 0;
520}
521
522static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
523{
524 struct sd *sd = (struct sd *) gspca_dev;
525
526 *val = sd->gain;
527 return 0;
528}
529
530static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
531{
532 struct sd *sd = (struct sd *) gspca_dev;
533
534 sd->autogain = val;
535 /* when switching to autogain set defaults to make sure
536 we are on a valid point of the autogain gain /
537 exposure knee graph, and give this change time to
538 take effect before doing autogain. */
539 if (sd->autogain) {
540 sd->exposure = PAC207_EXPOSURE_DEFAULT;
541 sd->gain = PAC207_GAIN_DEFAULT;
542 if (gspca_dev->streaming) {
543 sd->autogain_ignore_frames =
544 PAC207_AUTOGAIN_IGNORE_FRAMES;
545 setexposure(gspca_dev);
546 setgain(gspca_dev);
547 }
548 }
549
550 return 0;
551}
552
553static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
554{
555 struct sd *sd = (struct sd *) gspca_dev;
556
557 *val = sd->autogain;
558 return 0;
559}
560
561/* sub-driver description */
562static const struct sd_desc sd_desc = {
563 .name = MODULE_NAME,
564 .ctrls = sd_ctrls,
565 .nctrls = ARRAY_SIZE(sd_ctrls),
566 .config = sd_config,
567 .open = sd_open,
568 .start = sd_start,
569 .stopN = sd_stopN,
570 .stop0 = sd_stop0,
571 .close = sd_close,
572 .dq_callback = pac207_do_auto_gain,
573 .pkt_scan = sd_pkt_scan,
574};
575
576/* -- module initialisation -- */
577#define DVNM(name) .driver_info = (kernel_ulong_t) name
578static const __devinitdata struct usb_device_id device_table[] = {
579 {USB_DEVICE(0x041e, 0x4028), DVNM("Creative Webcam Vista Plus")},
580 {USB_DEVICE(0x093a, 0x2460), DVNM("Q-Tec Webcam 100")},
581 {USB_DEVICE(0x093a, 0x2463), DVNM("Philips spc200nc pac207")},
582 {USB_DEVICE(0x093a, 0x2464), DVNM("Labtec Webcam 1200")},
583 {USB_DEVICE(0x093a, 0x2468), DVNM("PAC207")},
584 {USB_DEVICE(0x093a, 0x2470), DVNM("Genius GF112")},
585 {USB_DEVICE(0x093a, 0x2471), DVNM("Genius VideoCam GE111")},
586 {USB_DEVICE(0x093a, 0x2472), DVNM("Genius VideoCam GE110")},
587 {USB_DEVICE(0x2001, 0xf115), DVNM("D-Link DSB-C120")},
588 {}
589};
590MODULE_DEVICE_TABLE(usb, device_table);
591
592/* -- device connect -- */
593static int sd_probe(struct usb_interface *intf,
594 const struct usb_device_id *id)
595{
596 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
597 THIS_MODULE);
598}
599
600static struct usb_driver sd_driver = {
601 .name = MODULE_NAME,
602 .id_table = device_table,
603 .probe = sd_probe,
604 .disconnect = gspca_disconnect,
605};
606
607/* -- module insert / remove -- */
608static int __init sd_mod_init(void)
609{
610 if (usb_register(&sd_driver) < 0)
611 return -1;
612 PDEBUG(D_PROBE, "v%s registered", version);
613 return 0;
614}
615static void __exit sd_mod_exit(void)
616{
617 usb_deregister(&sd_driver);
618 PDEBUG(D_PROBE, "deregistered");
619}
620
621module_init(sd_mod_init);
622module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
new file mode 100644
index 000000000000..5c052e31be4a
--- /dev/null
+++ b/drivers/media/video/gspca/pac7311.c
@@ -0,0 +1,760 @@
1/*
2 * Pixart PAC7311 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "pac7311"
23
24#include "gspca.h"
25
26#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
27static const char version[] = "2.1.7";
28
29MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
30MODULE_DESCRIPTION("Pixart PAC7311");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
37 int avg_lum;
38
39 unsigned char brightness;
40 unsigned char contrast;
41 unsigned char colors;
42 unsigned char autogain;
43
44 char ffseq;
45 signed char ag_cnt;
46#define AG_CNT_START 13
47};
48
49/* V4L2 controls supported by the driver */
50static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
52static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
54static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
55static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
56static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
57static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
58
59static struct ctrl sd_ctrls[] = {
60 {
61 {
62 .id = V4L2_CID_BRIGHTNESS,
63 .type = V4L2_CTRL_TYPE_INTEGER,
64 .name = "Brightness",
65 .minimum = 0,
66#define BRIGHTNESS_MAX 0x20
67 .maximum = BRIGHTNESS_MAX,
68 .step = 1,
69#define BRIGHTNESS_DEF 0x10
70 .default_value = BRIGHTNESS_DEF,
71 },
72 .set = sd_setbrightness,
73 .get = sd_getbrightness,
74 },
75 {
76 {
77 .id = V4L2_CID_CONTRAST,
78 .type = V4L2_CTRL_TYPE_INTEGER,
79 .name = "Contrast",
80 .minimum = 0,
81 .maximum = 255,
82 .step = 1,
83#define CONTRAST_DEF 127
84 .default_value = CONTRAST_DEF,
85 },
86 .set = sd_setcontrast,
87 .get = sd_getcontrast,
88 },
89 {
90 {
91 .id = V4L2_CID_SATURATION,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "Color",
94 .minimum = 0,
95 .maximum = 255,
96 .step = 1,
97#define COLOR_DEF 127
98 .default_value = COLOR_DEF,
99 },
100 .set = sd_setcolors,
101 .get = sd_getcolors,
102 },
103 {
104 {
105 .id = V4L2_CID_AUTOGAIN,
106 .type = V4L2_CTRL_TYPE_BOOLEAN,
107 .name = "Auto Gain",
108 .minimum = 0,
109 .maximum = 1,
110 .step = 1,
111#define AUTOGAIN_DEF 1
112 .default_value = AUTOGAIN_DEF,
113 },
114 .set = sd_setautogain,
115 .get = sd_getautogain,
116 },
117};
118
119static struct v4l2_pix_format vga_mode[] = {
120 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
121 .bytesperline = 160,
122 .sizeimage = 160 * 120 * 3 / 8 + 590,
123 .colorspace = V4L2_COLORSPACE_JPEG,
124 .priv = 2},
125 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
126 .bytesperline = 320,
127 .sizeimage = 320 * 240 * 3 / 8 + 590,
128 .colorspace = V4L2_COLORSPACE_JPEG,
129 .priv = 1},
130 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 640,
132 .sizeimage = 640 * 480 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 0},
135};
136
137#define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */
138
139static const __u8 pac7311_jpeg_header[] = {
140 0xff, 0xd8,
141 0xff, 0xe0, 0x00, 0x03, 0x20,
142 0xff, 0xc0, 0x00, 0x11, 0x08,
143 0x01, 0xe0, /* 12: height */
144 0x02, 0x80, /* 14: width */
145 0x03, /* 16 */
146 0x01, 0x21, 0x00,
147 0x02, 0x11, 0x01,
148 0x03, 0x11, 0x01,
149 0xff, 0xdb, 0x00, 0x84,
150 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
151 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
152 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
153 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
154 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
155 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
156 0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
157 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
158 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
159 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
160 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
161 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
162 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
163 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
164 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
166 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
167 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
168 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
169 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
170 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
171 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
172 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
173 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
174 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
175 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
176 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
177 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
178 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
179 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
180 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
181 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
182 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
183 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
184 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
185 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
187 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
188 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
189 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
190 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
191 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
192 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
193 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
194 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
195 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
196 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
197 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
198 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
199 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
200 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
201 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
202 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
203 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
204 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
205 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
206 0x11, 0x00, 0x3f, 0x00
207};
208
209static void reg_w_buf(struct gspca_dev *gspca_dev,
210 __u16 index,
211 const char *buffer, __u16 len)
212{
213 memcpy(gspca_dev->usb_buf, buffer, len);
214 usb_control_msg(gspca_dev->dev,
215 usb_sndctrlpipe(gspca_dev->dev, 0),
216 1, /* request */
217 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
218 0, /* value */
219 index, gspca_dev->usb_buf, len,
220 500);
221}
222
223static __u8 reg_r(struct gspca_dev *gspca_dev,
224 __u16 index)
225{
226 usb_control_msg(gspca_dev->dev,
227 usb_rcvctrlpipe(gspca_dev->dev, 0),
228 0, /* request */
229 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
230 0, /* value */
231 index, gspca_dev->usb_buf, 1,
232 500);
233 return gspca_dev->usb_buf[0];
234}
235
236static void reg_w(struct gspca_dev *gspca_dev,
237 __u16 index,
238 __u8 value)
239{
240 gspca_dev->usb_buf[0] = value;
241 usb_control_msg(gspca_dev->dev,
242 usb_sndctrlpipe(gspca_dev->dev, 0),
243 0, /* request */
244 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
245 value, index, gspca_dev->usb_buf, 1,
246 500);
247}
248
249/* this function is called at probe time */
250static int sd_config(struct gspca_dev *gspca_dev,
251 const struct usb_device_id *id)
252{
253 struct sd *sd = (struct sd *) gspca_dev;
254 struct cam *cam;
255
256 PDEBUG(D_CONF, "Find Sensor PAC7311");
257 reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
258 reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
259 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
260 reg_w(gspca_dev, 0xff, 0x04);
261 reg_w(gspca_dev, 0x27, 0x80);
262 reg_w(gspca_dev, 0x28, 0xca);
263 reg_w(gspca_dev, 0x29, 0x53);
264 reg_w(gspca_dev, 0x2a, 0x0e);
265 reg_w(gspca_dev, 0xff, 0x01);
266 reg_w(gspca_dev, 0x3e, 0x20);
267
268 cam = &gspca_dev->cam;
269 cam->dev_name = (char *) id->driver_info;
270 cam->epaddr = 0x05;
271 cam->cam_mode = vga_mode;
272 cam->nmodes = ARRAY_SIZE(vga_mode);
273
274 sd->brightness = BRIGHTNESS_DEF;
275 sd->contrast = CONTRAST_DEF;
276 sd->colors = COLOR_DEF;
277 sd->autogain = AUTOGAIN_DEF;
278 return 0;
279}
280
281static void setbrightness(struct gspca_dev *gspca_dev)
282{
283 struct sd *sd = (struct sd *) gspca_dev;
284 int brightness;
285
286/*jfm: inverted?*/
287 brightness = BRIGHTNESS_MAX - sd->brightness;
288 reg_w(gspca_dev, 0xff, 0x04);
289/* reg_w(gspca_dev, 0x0e, 0x00); */
290 reg_w(gspca_dev, 0x0f, brightness);
291 /* load registers to sensor (Bit 0, auto clear) */
292 reg_w(gspca_dev, 0x11, 0x01);
293 PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
294}
295
296static void setcontrast(struct gspca_dev *gspca_dev)
297{
298 struct sd *sd = (struct sd *) gspca_dev;
299
300 reg_w(gspca_dev, 0xff, 0x01);
301 reg_w(gspca_dev, 0x80, sd->contrast);
302 /* load registers to sensor (Bit 0, auto clear) */
303 reg_w(gspca_dev, 0x11, 0x01);
304 PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
305}
306
307static void setcolors(struct gspca_dev *gspca_dev)
308{
309 struct sd *sd = (struct sd *) gspca_dev;
310
311 reg_w(gspca_dev, 0xff, 0x01);
312 reg_w(gspca_dev, 0x10, sd->colors);
313 /* load registers to sensor (Bit 0, auto clear) */
314 reg_w(gspca_dev, 0x11, 0x01);
315 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
316}
317
318/* this function is called at open time */
319static int sd_open(struct gspca_dev *gspca_dev)
320{
321 reg_w(gspca_dev, 0x78, 0x00); /* Turn on LED */
322 return 0;
323}
324
325static void sd_start(struct gspca_dev *gspca_dev)
326{
327 struct sd *sd = (struct sd *) gspca_dev;
328
329 reg_w(gspca_dev, 0xff, 0x01);
330 reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
331 reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
332 reg_w_buf(gspca_dev, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
333 reg_w_buf(gspca_dev, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
334 reg_w_buf(gspca_dev, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
335 reg_w_buf(gspca_dev, 0x002a, "\x00\x00\x00", 3);
336 reg_w_buf(gspca_dev, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
337 reg_w_buf(gspca_dev, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
338 reg_w_buf(gspca_dev, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
339 reg_w_buf(gspca_dev, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
340 reg_w_buf(gspca_dev, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
341 reg_w_buf(gspca_dev, 0x0066, "\xd0\xff", 2);
342 reg_w_buf(gspca_dev, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
343 reg_w_buf(gspca_dev, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
344 reg_w_buf(gspca_dev, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
345 reg_w_buf(gspca_dev, 0x008f, "\x18\x20", 2);
346 reg_w_buf(gspca_dev, 0x0096, "\x01\x08\x04", 3);
347 reg_w_buf(gspca_dev, 0x00a0, "\x44\x44\x44\x04", 4);
348 reg_w_buf(gspca_dev, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
349 reg_w_buf(gspca_dev, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
350
351 reg_w(gspca_dev, 0xff, 0x04);
352 reg_w(gspca_dev, 0x02, 0x04);
353 reg_w(gspca_dev, 0x03, 0x54);
354 reg_w(gspca_dev, 0x04, 0x07);
355 reg_w(gspca_dev, 0x05, 0x2b);
356 reg_w(gspca_dev, 0x06, 0x09);
357 reg_w(gspca_dev, 0x07, 0x0f);
358 reg_w(gspca_dev, 0x08, 0x09);
359 reg_w(gspca_dev, 0x09, 0x00);
360 reg_w(gspca_dev, 0x0c, 0x07);
361 reg_w(gspca_dev, 0x0d, 0x00);
362 reg_w(gspca_dev, 0x0e, 0x00);
363 reg_w(gspca_dev, 0x0f, 0x62);
364 reg_w(gspca_dev, 0x10, 0x08);
365 reg_w(gspca_dev, 0x12, 0x07);
366 reg_w(gspca_dev, 0x13, 0x00);
367 reg_w(gspca_dev, 0x14, 0x00);
368 reg_w(gspca_dev, 0x15, 0x00);
369 reg_w(gspca_dev, 0x16, 0x00);
370 reg_w(gspca_dev, 0x17, 0x00);
371 reg_w(gspca_dev, 0x18, 0x00);
372 reg_w(gspca_dev, 0x19, 0x00);
373 reg_w(gspca_dev, 0x1a, 0x00);
374 reg_w(gspca_dev, 0x1b, 0x03);
375 reg_w(gspca_dev, 0x1c, 0xa0);
376 reg_w(gspca_dev, 0x1d, 0x01);
377 reg_w(gspca_dev, 0x1e, 0xf4);
378 reg_w(gspca_dev, 0x21, 0x00);
379 reg_w(gspca_dev, 0x22, 0x08);
380 reg_w(gspca_dev, 0x24, 0x03);
381 reg_w(gspca_dev, 0x26, 0x00);
382 reg_w(gspca_dev, 0x27, 0x01);
383 reg_w(gspca_dev, 0x28, 0xca);
384 reg_w(gspca_dev, 0x29, 0x10);
385 reg_w(gspca_dev, 0x2a, 0x06);
386 reg_w(gspca_dev, 0x2b, 0x78);
387 reg_w(gspca_dev, 0x2c, 0x00);
388 reg_w(gspca_dev, 0x2d, 0x00);
389 reg_w(gspca_dev, 0x2e, 0x00);
390 reg_w(gspca_dev, 0x2f, 0x00);
391 reg_w(gspca_dev, 0x30, 0x23);
392 reg_w(gspca_dev, 0x31, 0x28);
393 reg_w(gspca_dev, 0x32, 0x04);
394 reg_w(gspca_dev, 0x33, 0x11);
395 reg_w(gspca_dev, 0x34, 0x00);
396 reg_w(gspca_dev, 0x35, 0x00);
397 reg_w(gspca_dev, 0x11, 0x01);
398 setcontrast(gspca_dev);
399 setbrightness(gspca_dev);
400 setcolors(gspca_dev);
401
402 /* set correct resolution */
403 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
404 case 2: /* 160x120 */
405 reg_w(gspca_dev, 0xff, 0x04);
406 reg_w(gspca_dev, 0x02, 0x03);
407 reg_w(gspca_dev, 0xff, 0x01);
408 reg_w(gspca_dev, 0x08, 0x09);
409 reg_w(gspca_dev, 0x17, 0x20);
410 reg_w(gspca_dev, 0x1b, 0x00);
411/* reg_w(gspca_dev, 0x80, 0x69); */
412 reg_w(gspca_dev, 0x87, 0x10);
413 break;
414 case 1: /* 320x240 */
415 reg_w(gspca_dev, 0xff, 0x04);
416 reg_w(gspca_dev, 0x02, 0x03);
417 reg_w(gspca_dev, 0xff, 0x01);
418 reg_w(gspca_dev, 0x08, 0x09);
419 reg_w(gspca_dev, 0x17, 0x30);
420/* reg_w(gspca_dev, 0x80, 0x3f); */
421 reg_w(gspca_dev, 0x87, 0x11);
422 break;
423 case 0: /* 640x480 */
424 reg_w(gspca_dev, 0xff, 0x04);
425 reg_w(gspca_dev, 0x02, 0x03);
426 reg_w(gspca_dev, 0xff, 0x01);
427 reg_w(gspca_dev, 0x08, 0x08);
428 reg_w(gspca_dev, 0x17, 0x00);
429/* reg_w(gspca_dev, 0x80, 0x1c); */
430 reg_w(gspca_dev, 0x87, 0x12);
431 break;
432 }
433
434 /* start stream */
435 reg_w(gspca_dev, 0xff, 0x01);
436 reg_w(gspca_dev, 0x78, 0x04);
437 reg_w(gspca_dev, 0x78, 0x05);
438
439 if (sd->autogain) {
440 sd->ag_cnt = AG_CNT_START;
441 sd->avg_lum = 0;
442 } else {
443 sd->ag_cnt = -1;
444 }
445}
446
447static void sd_stopN(struct gspca_dev *gspca_dev)
448{
449 reg_w(gspca_dev, 0xff, 0x04);
450 reg_w(gspca_dev, 0x27, 0x80);
451 reg_w(gspca_dev, 0x28, 0xca);
452 reg_w(gspca_dev, 0x29, 0x53);
453 reg_w(gspca_dev, 0x2a, 0x0e);
454 reg_w(gspca_dev, 0xff, 0x01);
455 reg_w(gspca_dev, 0x3e, 0x20);
456 reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
457 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
458 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
459}
460
461static void sd_stop0(struct gspca_dev *gspca_dev)
462{
463}
464
465/* this function is called at close time */
466static void sd_close(struct gspca_dev *gspca_dev)
467{
468 reg_w(gspca_dev, 0xff, 0x04);
469 reg_w(gspca_dev, 0x27, 0x80);
470 reg_w(gspca_dev, 0x28, 0xca);
471 reg_w(gspca_dev, 0x29, 0x53);
472 reg_w(gspca_dev, 0x2a, 0x0e);
473 reg_w(gspca_dev, 0xff, 0x01);
474 reg_w(gspca_dev, 0x3e, 0x20);
475 reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
476 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
477 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
478}
479
480static void setautogain(struct gspca_dev *gspca_dev, int luma)
481{
482 int luma_mean = 128;
483 int luma_delta = 20;
484 __u8 spring = 5;
485 int Gbright;
486
487 Gbright = reg_r(gspca_dev, 0x02);
488 PDEBUG(D_FRAM, "luma mean %d", luma);
489 if (luma < luma_mean - luma_delta ||
490 luma > luma_mean + luma_delta) {
491 Gbright += (luma_mean - luma) >> spring;
492 if (Gbright > 0x1a)
493 Gbright = 0x1a;
494 else if (Gbright < 4)
495 Gbright = 4;
496 PDEBUG(D_FRAM, "gbright %d", Gbright);
497 reg_w(gspca_dev, 0xff, 0x04);
498 reg_w(gspca_dev, 0x0f, Gbright);
499 /* load registers to sensor (Bit 0, auto clear) */
500 reg_w(gspca_dev, 0x11, 0x01);
501 }
502}
503
504static void sd_pkt_scan(struct gspca_dev *gspca_dev,
505 struct gspca_frame *frame, /* target */
506 __u8 *data, /* isoc packet */
507 int len) /* iso packet length */
508{
509 struct sd *sd = (struct sd *) gspca_dev;
510 unsigned char tmpbuf[4];
511 int i, p, ffseq;
512
513/* if (len < 5) { */
514 if (len < 6) {
515/* gspca_dev->last_packet_type = DISCARD_PACKET; */
516 return;
517 }
518
519 ffseq = sd->ffseq;
520
521 for (p = 0; p < len - 6; p++) {
522 if ((data[0 + p] == 0xff)
523 && (data[1 + p] == 0xff)
524 && (data[2 + p] == 0x00)
525 && (data[3 + p] == 0xff)
526 && (data[4 + p] == 0x96)) {
527
528 /* start of frame */
529 if (sd->ag_cnt >= 0 && p > 28) {
530 sd->avg_lum += data[p - 23];
531 if (--sd->ag_cnt < 0) {
532 sd->ag_cnt = AG_CNT_START;
533 setautogain(gspca_dev,
534 sd->avg_lum / AG_CNT_START);
535 sd->avg_lum = 0;
536 }
537 }
538
539 /* copy the end of data to the current frame */
540 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
541 data, p);
542
543 /* put the JPEG header in the new frame */
544 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
545 (unsigned char *) pac7311_jpeg_header,
546 12);
547 tmpbuf[0] = gspca_dev->height >> 8;
548 tmpbuf[1] = gspca_dev->height & 0xff;
549 tmpbuf[2] = gspca_dev->width >> 8;
550 tmpbuf[3] = gspca_dev->width & 0xff;
551 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
552 tmpbuf, 4);
553 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
554 (unsigned char *) &pac7311_jpeg_header[16],
555 PAC7311_JPEG_HEADER_SIZE - 16);
556
557 data += p + 7;
558 len -= p + 7;
559 ffseq = 0;
560 break;
561 }
562 }
563
564 /* remove the 'ff ff ff xx' sequences */
565 switch (ffseq) {
566 case 3:
567 data += 1;
568 len -= 1;
569 break;
570 case 2:
571 if (data[0] == 0xff) {
572 data += 2;
573 len -= 2;
574 frame->data_end -= 2;
575 }
576 break;
577 case 1:
578 if (data[0] == 0xff
579 && data[1] == 0xff) {
580 data += 3;
581 len -= 3;
582 frame->data_end -= 1;
583 }
584 break;
585 }
586 for (i = 0; i < len - 4; i++) {
587 if (data[i] == 0xff
588 && data[i + 1] == 0xff
589 && data[i + 2] == 0xff) {
590 memmove(&data[i], &data[i + 4], len - i - 4);
591 len -= 4;
592 }
593 }
594 ffseq = 0;
595 if (data[len - 4] == 0xff) {
596 if (data[len - 3] == 0xff
597 && data[len - 2] == 0xff) {
598 len -= 4;
599 }
600 } else if (data[len - 3] == 0xff) {
601 if (data[len - 2] == 0xff
602 && data[len - 1] == 0xff)
603 ffseq = 3;
604 } else if (data[len - 2] == 0xff) {
605 if (data[len - 1] == 0xff)
606 ffseq = 2;
607 } else if (data[len - 1] == 0xff)
608 ffseq = 1;
609 sd->ffseq = ffseq;
610 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
611}
612
613static void getbrightness(struct gspca_dev *gspca_dev)
614{
615/* sd->brightness = reg_r(gspca_dev, 0x08);
616 return sd->brightness; */
617/* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
618}
619
620
621
622static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
623{
624 struct sd *sd = (struct sd *) gspca_dev;
625
626 sd->brightness = val;
627 if (gspca_dev->streaming)
628 setbrightness(gspca_dev);
629 return 0;
630}
631
632static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
633{
634 struct sd *sd = (struct sd *) gspca_dev;
635
636 getbrightness(gspca_dev);
637 *val = sd->brightness;
638 return 0;
639}
640
641static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
642{
643 struct sd *sd = (struct sd *) gspca_dev;
644
645 sd->contrast = val;
646 if (gspca_dev->streaming)
647 setcontrast(gspca_dev);
648 return 0;
649}
650
651static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
652{
653 struct sd *sd = (struct sd *) gspca_dev;
654
655/* getcontrast(gspca_dev); */
656 *val = sd->contrast;
657 return 0;
658}
659
660static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
661{
662 struct sd *sd = (struct sd *) gspca_dev;
663
664 sd->colors = val;
665 if (gspca_dev->streaming)
666 setcolors(gspca_dev);
667 return 0;
668}
669
670static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
671{
672 struct sd *sd = (struct sd *) gspca_dev;
673
674/* getcolors(gspca_dev); */
675 *val = sd->colors;
676 return 0;
677}
678
679static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
680{
681 struct sd *sd = (struct sd *) gspca_dev;
682
683 sd->autogain = val;
684 if (val) {
685 sd->ag_cnt = AG_CNT_START;
686 sd->avg_lum = 0;
687 } else {
688 sd->ag_cnt = -1;
689 }
690 return 0;
691}
692
693static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
694{
695 struct sd *sd = (struct sd *) gspca_dev;
696
697 *val = sd->autogain;
698 return 0;
699}
700
701/* sub-driver description */
702static struct sd_desc sd_desc = {
703 .name = MODULE_NAME,
704 .ctrls = sd_ctrls,
705 .nctrls = ARRAY_SIZE(sd_ctrls),
706 .config = sd_config,
707 .open = sd_open,
708 .start = sd_start,
709 .stopN = sd_stopN,
710 .stop0 = sd_stop0,
711 .close = sd_close,
712 .pkt_scan = sd_pkt_scan,
713};
714
715/* -- module initialisation -- */
716#define DVNM(name) .driver_info = (kernel_ulong_t) name
717static __devinitdata struct usb_device_id device_table[] = {
718 {USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
719 {USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
720 {USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
721 {USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
722 {USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera")},
723 /* and also ', Trust WB-3350p, SIGMA cam 2350' */
724 {USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
725 {USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
726 {}
727};
728MODULE_DEVICE_TABLE(usb, device_table);
729
730/* -- device connect -- */
731static int sd_probe(struct usb_interface *intf,
732 const struct usb_device_id *id)
733{
734 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
735 THIS_MODULE);
736}
737
738static struct usb_driver sd_driver = {
739 .name = MODULE_NAME,
740 .id_table = device_table,
741 .probe = sd_probe,
742 .disconnect = gspca_disconnect,
743};
744
745/* -- module insert / remove -- */
746static int __init sd_mod_init(void)
747{
748 if (usb_register(&sd_driver) < 0)
749 return -1;
750 PDEBUG(D_PROBE, "v%s registered", version);
751 return 0;
752}
753static void __exit sd_mod_exit(void)
754{
755 usb_deregister(&sd_driver);
756 PDEBUG(D_PROBE, "deregistered");
757}
758
759module_init(sd_mod_init);
760module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
new file mode 100644
index 000000000000..dbeebe8625c5
--- /dev/null
+++ b/drivers/media/video/gspca/sonixb.c
@@ -0,0 +1,1477 @@
1/*
2 * sonix sn9c102 (bayer) library
3 * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
4 * Add Pas106 Stefano Mozzi (C) 2004
5 *
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#define MODULE_NAME "sonixb"
24
25#include "gspca.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 8)
28static const char version[] = "2.1.8";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 struct sd_desc sd_desc; /* our nctrls differ dependend upon the
39 sensor, so we use a per cam copy */
40 atomic_t avg_lum;
41
42 unsigned char gain;
43 unsigned char exposure;
44 unsigned char brightness;
45 unsigned char autogain;
46 unsigned char autogain_ignore_frames;
47 unsigned char freq; /* light freq filter setting */
48 unsigned char saturation;
49 unsigned char hue;
50 unsigned char contrast;
51
52 unsigned char fr_h_sz; /* size of frame header */
53 char sensor; /* Type of image sensor chip */
54#define SENSOR_HV7131R 0
55#define SENSOR_OV6650 1
56#define SENSOR_OV7630 2
57#define SENSOR_OV7630_3 3
58#define SENSOR_PAS106 4
59#define SENSOR_PAS202 5
60#define SENSOR_TAS5110 6
61#define SENSOR_TAS5130CXX 7
62 char sensor_has_gain;
63 __u8 sensor_addr;
64};
65
66#define COMP2 0x8f
67#define COMP 0xc7 /* 0x87 //0x07 */
68#define COMP1 0xc9 /* 0x89 //0x09 */
69
70#define MCK_INIT 0x63
71#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
72
73#define SYS_CLK 0x04
74
75/* We calculate the autogain at the end of the transfer of a frame, at this
76 moment a frame with the old settings is being transmitted, and a frame is
77 being captured with the old settings. So if we adjust the autogain we must
78 ignore atleast the 2 next frames for the new settings to come into effect
79 before doing any other adjustments */
80#define AUTOGAIN_IGNORE_FRAMES 3
81#define AUTOGAIN_DEADZONE 1000
82#define DESIRED_AVG_LUM 7000
83
84/* V4L2 controls supported by the driver */
85static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
87static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
89static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
90static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
91static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
92static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
93static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
94static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
95static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val);
96static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val);
97static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
98static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
99static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
100static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
101
102static struct ctrl sd_ctrls[] = {
103 {
104 {
105 .id = V4L2_CID_BRIGHTNESS,
106 .type = V4L2_CTRL_TYPE_INTEGER,
107 .name = "Brightness",
108 .minimum = 0,
109 .maximum = 255,
110 .step = 1,
111#define BRIGHTNESS_DEF 127
112 .default_value = BRIGHTNESS_DEF,
113 },
114 .set = sd_setbrightness,
115 .get = sd_getbrightness,
116 },
117 {
118 {
119 .id = V4L2_CID_GAIN,
120 .type = V4L2_CTRL_TYPE_INTEGER,
121 .name = "Gain",
122 .minimum = 0,
123 .maximum = 255,
124 .step = 1,
125#define GAIN_DEF 127
126#define GAIN_KNEE 200
127 .default_value = GAIN_DEF,
128 },
129 .set = sd_setgain,
130 .get = sd_getgain,
131 },
132 {
133 {
134 .id = V4L2_CID_EXPOSURE,
135 .type = V4L2_CTRL_TYPE_INTEGER,
136 .name = "Exposure",
137#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
138#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
139 .minimum = 0,
140 .maximum = 255,
141 .step = 1,
142 .default_value = EXPOSURE_DEF,
143 .flags = 0,
144 },
145 .set = sd_setexposure,
146 .get = sd_getexposure,
147 },
148 {
149 {
150 .id = V4L2_CID_AUTOGAIN,
151 .type = V4L2_CTRL_TYPE_BOOLEAN,
152 .name = "Automatic Gain (and Exposure)",
153 .minimum = 0,
154 .maximum = 1,
155 .step = 1,
156#define AUTOGAIN_DEF 1
157 .default_value = AUTOGAIN_DEF,
158 .flags = 0,
159 },
160 .set = sd_setautogain,
161 .get = sd_getautogain,
162 },
163 {
164 {
165 .id = V4L2_CID_POWER_LINE_FREQUENCY,
166 .type = V4L2_CTRL_TYPE_MENU,
167 .name = "Light frequency filter",
168 .minimum = 0,
169 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
170 .step = 1,
171#define FREQ_DEF 1
172 .default_value = FREQ_DEF,
173 },
174 .set = sd_setfreq,
175 .get = sd_getfreq,
176 },
177 {
178 {
179 .id = V4L2_CID_SATURATION,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .name = "Saturation",
182 .minimum = 0,
183 .maximum = 255,
184 .step = 1,
185#define SATURATION_DEF 127
186 .default_value = SATURATION_DEF,
187 },
188 .set = sd_setsaturation,
189 .get = sd_getsaturation,
190 },
191 {
192 {
193 .id = V4L2_CID_HUE,
194 .type = V4L2_CTRL_TYPE_INTEGER,
195 .name = "Hue",
196 .minimum = 0,
197 .maximum = 255,
198 .step = 1,
199#define HUE_DEF 127
200 .default_value = HUE_DEF,
201 },
202 .set = sd_sethue,
203 .get = sd_gethue,
204 },
205 {
206 {
207 .id = V4L2_CID_CONTRAST,
208 .type = V4L2_CTRL_TYPE_INTEGER,
209 .name = "Contrast",
210 .minimum = 0,
211 .maximum = 255,
212 .step = 1,
213#define CONTRAST_DEF 127
214 .default_value = CONTRAST_DEF,
215 },
216 .set = sd_setcontrast,
217 .get = sd_getcontrast,
218 },
219};
220
221static struct v4l2_pix_format vga_mode[] = {
222 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
223 .bytesperline = 160,
224 .sizeimage = 160 * 120,
225 .colorspace = V4L2_COLORSPACE_SRGB,
226 .priv = 2},
227 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
228 .bytesperline = 320,
229 .sizeimage = 320 * 240,
230 .colorspace = V4L2_COLORSPACE_SRGB,
231 .priv = 1},
232 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
233 .bytesperline = 640,
234 .sizeimage = 640 * 480,
235 .colorspace = V4L2_COLORSPACE_SRGB,
236 .priv = 0},
237};
238static struct v4l2_pix_format sif_mode[] = {
239 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
240 .bytesperline = 176,
241 .sizeimage = 176 * 144,
242 .colorspace = V4L2_COLORSPACE_SRGB,
243 .priv = 1},
244 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
245 .bytesperline = 352,
246 .sizeimage = 352 * 288,
247 .colorspace = V4L2_COLORSPACE_SRGB,
248 .priv = 0},
249};
250
251static const __u8 probe_ov7630[] = {0x08, 0x44};
252
253static const __u8 initHv7131[] = {
254 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
255 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
257 0x28, 0x1e, 0x60, 0x8a, 0x20,
258 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
259};
260static const __u8 hv7131_sensor_init[][8] = {
261 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
262 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
263 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
264 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
265 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
266};
267static const __u8 initOv6650[] = {
268 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
269 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
271 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
272};
273static const __u8 ov6650_sensor_init[][8] =
274{
275 /* Bright, contrast, etc are set througth SCBB interface.
276 * AVCAP on win2 do not send any data on this controls. */
277 /* Anyway, some registers appears to alter bright and constrat */
278
279 /* Reset sensor */
280 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
281 /* Set clock register 0x11 low nibble is clock divider */
282 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
283 /* Next some unknown stuff */
284 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
285/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
286 * THIS SET GREEN SCREEN
287 * (pixels could be innverted in decode kind of "brg",
288 * but blue wont be there. Avoid this data ... */
289 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
290 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
291 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
292 /* Enable rgb brightness control */
293 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
294 /* HDG: Note windows uses the line below, which sets both register 0x60
295 and 0x61 I believe these registers of the ov6650 are identical as
296 those of the ov7630, because if this is true the windows settings
297 add a bit additional red gain and a lot additional blue gain, which
298 matches my findings that the windows settings make blue much too
299 blue and red a little too red.
300 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
301 /* Some more unknown stuff */
302 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
303 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
304};
305
306static const __u8 initOv7630[] = {
307 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
308 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
309 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
310 0x28, 0x1e, /* H & V sizes r15 .. r16 */
311 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
312 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
313};
314static const __u8 initOv7630_3[] = {
315 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
316 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
317 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
318 0x28, 0x1e, /* H & V sizes r15 .. r16 */
319 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
320 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
321 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
322 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
323};
324static const __u8 ov7630_sensor_init_com[][8] = {
325 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
326 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
327/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
328 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
329 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
330 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
331 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
332 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
333 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
334 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
335 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
336 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
337/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
338 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
339 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
340 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
341 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
342 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
343 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
344};
345static const __u8 ov7630_sensor_init[][8] = {
346 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
347 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
348 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
349 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
350 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
351};
352static const __u8 ov7630_sensor_init_3[][8] = {
353 {0xa0, 0x21, 0x2a, 0xa0, 0x00, 0x00, 0x00, 0x10},
354 {0xa0, 0x21, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x10},
355};
356
357static const __u8 initPas106[] = {
358 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
359 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
361 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
362 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
363};
364/* compression 0x86 mckinit1 0x2b */
365static const __u8 pas106_data[][2] = {
366 {0x02, 0x04}, /* Pixel Clock Divider 6 */
367 {0x03, 0x13}, /* Frame Time MSB */
368/* {0x03, 0x12}, * Frame Time MSB */
369 {0x04, 0x06}, /* Frame Time LSB */
370/* {0x04, 0x05}, * Frame Time LSB */
371 {0x05, 0x65}, /* Shutter Time Line Offset */
372/* {0x05, 0x6d}, * Shutter Time Line Offset */
373/* {0x06, 0xb1}, * Shutter Time Pixel Offset */
374 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
375 {0x07, 0xc1}, /* Black Level Subtract Sign */
376/* {0x07, 0x00}, * Black Level Subtract Sign */
377 {0x08, 0x06}, /* Black Level Subtract Level */
378 {0x08, 0x06}, /* Black Level Subtract Level */
379/* {0x08, 0x01}, * Black Level Subtract Level */
380 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
381 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
382 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
383 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
384 {0x0d, 0x00}, /* Color GainH Pixel */
385 {0x0e, 0x0e}, /* Global Gain */
386 {0x0f, 0x00}, /* Contrast */
387 {0x10, 0x06}, /* H&V synchro polarity */
388 {0x11, 0x06}, /* ?default */
389 {0x12, 0x06}, /* DAC scale */
390 {0x14, 0x02}, /* ?default */
391 {0x13, 0x01}, /* Validate Settings */
392};
393static const __u8 initPas202[] = {
394 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
395 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
397 0x28, 0x1e, 0x28, 0x89, 0x30,
398 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
399};
400static const __u8 pas202_sensor_init[][8] = {
401 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
402 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
403 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
404 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
405 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
406 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
407 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
408 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
409 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
410 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
411 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
412 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
413
414 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
415 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
416 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
417 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
418 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
419 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
420 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
421 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
422};
423
424static const __u8 initTas5110[] = {
425 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
426 0x00, 0x00,
427 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
428 0x16, 0x12, 0x60, 0x86, 0x2b,
429 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
430};
431static const __u8 tas5110_sensor_init[][8] = {
432 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
433 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
434 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
435};
436
437static const __u8 initTas5130[] = {
438 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
439 0x00, 0x00,
440 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
441 0x28, 0x1e, 0x60, COMP, MCK_INIT,
442 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
443};
444static const __u8 tas5130_sensor_init[][8] = {
445/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
446 * shutter 0x47 short exposure? */
447 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
448 /* shutter 0x01 long exposure */
449 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
450};
451
452/* get one byte in gspca_dev->usb_buf */
453static void reg_r(struct gspca_dev *gspca_dev,
454 __u16 value)
455{
456 usb_control_msg(gspca_dev->dev,
457 usb_rcvctrlpipe(gspca_dev->dev, 0),
458 0, /* request */
459 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
460 value,
461 0, /* index */
462 gspca_dev->usb_buf, 1,
463 500);
464}
465
466static void reg_w(struct gspca_dev *gspca_dev,
467 __u16 value,
468 const __u8 *buffer,
469 int len)
470{
471#ifdef CONFIG_VIDEO_ADV_DEBUG
472 if (len > sizeof gspca_dev->usb_buf) {
473 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
474 return;
475 }
476#endif
477 memcpy(gspca_dev->usb_buf, buffer, len);
478 usb_control_msg(gspca_dev->dev,
479 usb_sndctrlpipe(gspca_dev->dev, 0),
480 0x08, /* request */
481 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
482 value,
483 0, /* index */
484 gspca_dev->usb_buf, len,
485 500);
486}
487
488static void reg_w_big(struct gspca_dev *gspca_dev,
489 __u16 value,
490 const __u8 *buffer,
491 int len)
492{
493 __u8 *tmpbuf;
494
495 tmpbuf = kmalloc(len, GFP_KERNEL);
496 memcpy(tmpbuf, buffer, len);
497 usb_control_msg(gspca_dev->dev,
498 usb_sndctrlpipe(gspca_dev->dev, 0),
499 0x08, /* request */
500 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
501 value,
502 0, /* index */
503 tmpbuf, len,
504 500);
505 kfree(tmpbuf);
506}
507
508static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
509{
510 int retry = 60;
511
512 /* is i2c ready */
513 reg_w(gspca_dev, 0x08, buffer, 8);
514 while (retry--) {
515 msleep(10);
516 reg_r(gspca_dev, 0x08);
517 if (gspca_dev->usb_buf[0] & 0x04) {
518 if (gspca_dev->usb_buf[0] & 0x08)
519 return -1;
520 return 0;
521 }
522 }
523 return -1;
524}
525
526static void i2c_w_vector(struct gspca_dev *gspca_dev,
527 const __u8 buffer[][8], int len)
528{
529 for (;;) {
530 reg_w(gspca_dev, 0x08, *buffer, 8);
531 len -= 8;
532 if (len <= 0)
533 break;
534 buffer++;
535 }
536}
537
538static void setbrightness(struct gspca_dev *gspca_dev)
539{
540 struct sd *sd = (struct sd *) gspca_dev;
541 __u8 value;
542
543 switch (sd->sensor) {
544 case SENSOR_OV6650:
545 case SENSOR_OV7630_3:
546 case SENSOR_OV7630: {
547 __u8 i2cOV[] =
548 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
549
550 /* change reg 0x06 */
551 i2cOV[1] = sd->sensor_addr;
552 i2cOV[3] = sd->brightness;
553 if (i2c_w(gspca_dev, i2cOV) < 0)
554 goto err;
555 break;
556 }
557 case SENSOR_PAS106: {
558 __u8 i2c1[] =
559 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
560
561 i2c1[3] = sd->brightness >> 3;
562 i2c1[2] = 0x0e;
563 if (i2c_w(gspca_dev, i2c1) < 0)
564 goto err;
565 i2c1[3] = 0x01;
566 i2c1[2] = 0x13;
567 if (i2c_w(gspca_dev, i2c1) < 0)
568 goto err;
569 break;
570 }
571 case SENSOR_PAS202: {
572 /* __u8 i2cpexpo1[] =
573 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
574 __u8 i2cpexpo[] =
575 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
576 __u8 i2cp202[] =
577 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
578 static __u8 i2cpdoit[] =
579 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
580
581 /* change reg 0x10 */
582 i2cpexpo[4] = 0xff - sd->brightness;
583/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
584 goto err; */
585/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
586 goto err; */
587 if (i2c_w(gspca_dev, i2cpexpo) < 0)
588 goto err;
589 if (i2c_w(gspca_dev, i2cpdoit) < 0)
590 goto err;
591 i2cp202[3] = sd->brightness >> 3;
592 if (i2c_w(gspca_dev, i2cp202) < 0)
593 goto err;
594 if (i2c_w(gspca_dev, i2cpdoit) < 0)
595 goto err;
596 break;
597 }
598 case SENSOR_TAS5130CXX: {
599 __u8 i2c[] =
600 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
601
602 value = 0xff - sd->brightness;
603 i2c[4] = value;
604 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
605 if (i2c_w(gspca_dev, i2c) < 0)
606 goto err;
607 break;
608 }
609 case SENSOR_TAS5110:
610 /* FIXME figure out howto control brightness on TAS5110 */
611 break;
612 }
613 return;
614err:
615 PDEBUG(D_ERR, "i2c error brightness");
616}
617
618static void setsensorgain(struct gspca_dev *gspca_dev)
619{
620 struct sd *sd = (struct sd *) gspca_dev;
621 unsigned char gain = sd->gain;
622
623 switch (sd->sensor) {
624
625 case SENSOR_TAS5110: {
626 __u8 i2c[] =
627 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
628
629 i2c[4] = 255 - gain;
630 if (i2c_w(gspca_dev, i2c) < 0)
631 goto err;
632 break;
633 }
634
635 case SENSOR_OV6650:
636 gain >>= 1;
637 /* fall thru */
638 case SENSOR_OV7630_3: {
639 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
640
641 i2c[1] = sd->sensor_addr;
642 i2c[3] = gain >> 2;
643 if (i2c_w(gspca_dev, i2c) < 0)
644 goto err;
645 break;
646 }
647 }
648 return;
649err:
650 PDEBUG(D_ERR, "i2c error gain");
651}
652
653static void setgain(struct gspca_dev *gspca_dev)
654{
655 struct sd *sd = (struct sd *) gspca_dev;
656 __u8 gain;
657 __u8 rgb_value;
658
659 gain = sd->gain >> 4;
660
661 /* red and blue gain */
662 rgb_value = gain << 4 | gain;
663 reg_w(gspca_dev, 0x10, &rgb_value, 1);
664 /* green gain */
665 rgb_value = gain;
666 reg_w(gspca_dev, 0x11, &rgb_value, 1);
667
668 if (sd->sensor_has_gain)
669 setsensorgain(gspca_dev);
670}
671
672static void setexposure(struct gspca_dev *gspca_dev)
673{
674 struct sd *sd = (struct sd *) gspca_dev;
675
676 switch (sd->sensor) {
677 case SENSOR_TAS5110: {
678 __u8 reg;
679
680 /* register 19's high nibble contains the sn9c10x clock divider
681 The high nibble configures the no fps according to the
682 formula: 60 / high_nibble. With a maximum of 30 fps */
683 reg = 120 * sd->exposure / 1000;
684 if (reg < 2)
685 reg = 2;
686 else if (reg > 15)
687 reg = 15;
688 reg = (reg << 4) | 0x0b;
689 reg_w(gspca_dev, 0x19, &reg, 1);
690 break;
691 }
692 case SENSOR_OV6650:
693 case SENSOR_OV7630_3: {
694 /* The ov6650 / ov7630 have 2 registers which both influence
695 exposure, register 11, whose low nibble sets the nr off fps
696 according to: fps = 30 / (low_nibble + 1)
697
698 The fps configures the maximum exposure setting, but it is
699 possible to use less exposure then what the fps maximum
700 allows by setting register 10. register 10 configures the
701 actual exposure as quotient of the full exposure, with 0
702 being no exposure at all (not very usefull) and reg10_max
703 being max exposure possible at that framerate.
704
705 The code maps our 0 - 510 ms exposure ctrl to these 2
706 registers, trying to keep fps as high as possible.
707 */
708 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
709 int reg10, reg11;
710 /* ov6645 datasheet says reg10_max is 9a, but that uses
711 tline * 2 * reg10 as formula for calculating texpo, the
712 ov6650 probably uses the same formula as the 7730 which uses
713 tline * 4 * reg10, which explains why the reg10max we've
714 found experimentally for the ov6650 is exactly half that of
715 the ov6645. The ov7630 datasheet says the max is 0x41. */
716 const int reg10_max = (sd->sensor == SENSOR_OV6650)
717 ? 0x4d : 0x41;
718
719 reg11 = (60 * sd->exposure + 999) / 1000;
720 if (reg11 < 1)
721 reg11 = 1;
722 else if (reg11 > 16)
723 reg11 = 16;
724
725 /* frame exposure time in ms = 1000 * reg11 / 30 ->
726 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
727 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
728
729 /* Don't allow this to get below 10 when using autogain, the
730 steps become very large (relatively) when below 10 causing
731 the image to oscilate from much too dark, to much too bright
732 and back again. */
733 if (sd->autogain && reg10 < 10)
734 reg10 = 10;
735 else if (reg10 > reg10_max)
736 reg10 = reg10_max;
737
738 /* Write reg 10 and reg11 low nibble */
739 i2c[1] = sd->sensor_addr;
740 i2c[3] = reg10;
741 i2c[4] |= reg11 - 1;
742 if (sd->sensor == SENSOR_OV7630_3) {
743 __u8 reg76 = reg10 & 0x03;
744 __u8 i2c_reg76[] = {0xa0, 0x21, 0x76, 0x00,
745 0x00, 0x00, 0x00, 0x10};
746 reg10 >>= 2;
747 i2c_reg76[3] = reg76;
748 if (i2c_w(gspca_dev, i2c_reg76) < 0)
749 PDEBUG(D_ERR, "i2c error exposure");
750 }
751 if (i2c_w(gspca_dev, i2c) < 0)
752 PDEBUG(D_ERR, "i2c error exposure");
753 break;
754 }
755 }
756}
757
758static void setfreq(struct gspca_dev *gspca_dev)
759{
760 struct sd *sd = (struct sd *) gspca_dev;
761
762 switch (sd->sensor) {
763 case SENSOR_OV6650:
764 case SENSOR_OV7630_3: {
765 /* Framerate adjust register for artificial light 50 hz flicker
766 compensation, identical to ov6630 0x2b register, see ov6630
767 datasheet.
768 0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
769 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
770 switch (sd->freq) {
771 default:
772/* case 0: * no filter*/
773/* case 2: * 60 hz */
774 i2c[3] = 0;
775 break;
776 case 1: /* 50 hz */
777 i2c[3] = (sd->sensor == SENSOR_OV6650)
778 ? 0x4f : 0x8a;
779 break;
780 }
781 i2c[1] = sd->sensor_addr;
782 if (i2c_w(gspca_dev, i2c) < 0)
783 PDEBUG(D_ERR, "i2c error setfreq");
784 break;
785 }
786 }
787}
788
789static void setsaturation(struct gspca_dev *gspca_dev)
790{
791 struct sd *sd = (struct sd *) gspca_dev;
792
793 switch (sd->sensor) {
794/* case SENSOR_OV6650: */
795 case SENSOR_OV7630_3:
796 case SENSOR_OV7630: {
797 __u8 i2c[] = {0xa0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10};
798 i2c[1] = sd->sensor_addr;
799 i2c[3] = sd->saturation & 0xf0;
800 if (i2c_w(gspca_dev, i2c) < 0)
801 PDEBUG(D_ERR, "i2c error setsaturation");
802 else
803 PDEBUG(D_CONF, "saturation set to: %d",
804 (int)sd->saturation);
805 break;
806 }
807 }
808}
809
810static void sethue(struct gspca_dev *gspca_dev)
811{
812 struct sd *sd = (struct sd *) gspca_dev;
813
814 switch (sd->sensor) {
815/* case SENSOR_OV6650: */
816 case SENSOR_OV7630_3:
817 case SENSOR_OV7630: {
818 __u8 i2c[] = {0xa0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10};
819 i2c[1] = sd->sensor_addr;
820 i2c[3] = 0x20 | (sd->hue >> 3);
821 if (i2c_w(gspca_dev, i2c) < 0)
822 PDEBUG(D_ERR, "i2c error setsaturation");
823 else
824 PDEBUG(D_CONF, "hue set to: %d", (int)sd->hue);
825 break;
826 }
827 }
828}
829
830static void setcontrast(struct gspca_dev *gspca_dev)
831{
832 struct sd *sd = (struct sd *) gspca_dev;
833
834 switch (sd->sensor) {
835/* case SENSOR_OV6650: */
836 case SENSOR_OV7630_3:
837 case SENSOR_OV7630: {
838 __u8 i2c[] = {0xa0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10};
839 i2c[1] = sd->sensor_addr;
840 i2c[3] = 0x20 | (sd->contrast >> 3);
841 if (i2c_w(gspca_dev, i2c) < 0)
842 PDEBUG(D_ERR, "i2c error setcontrast");
843 else
844 PDEBUG(D_CONF, "contrast set to: %d",
845 (int)sd->contrast);
846 break;
847 }
848 }
849}
850
851
852static void do_autogain(struct gspca_dev *gspca_dev)
853{
854 struct sd *sd = (struct sd *) gspca_dev;
855 int avg_lum = atomic_read(&sd->avg_lum);
856
857 if (avg_lum == -1)
858 return;
859
860 if (sd->autogain_ignore_frames > 0)
861 sd->autogain_ignore_frames--;
862 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
863 sd->brightness * DESIRED_AVG_LUM / 127,
864 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
865 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
866 (int)sd->gain, (int)sd->exposure);
867 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
868 }
869}
870
871/* this function is called at probe time */
872static int sd_config(struct gspca_dev *gspca_dev,
873 const struct usb_device_id *id)
874{
875 struct sd *sd = (struct sd *) gspca_dev;
876 struct cam *cam;
877 __u16 product;
878 int sif = 0;
879
880 /* nctrls depends upon the sensor, so we use a per cam copy */
881 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
882 gspca_dev->sd_desc = &sd->sd_desc;
883
884 sd->fr_h_sz = 12; /* default size of the frame header */
885 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
886 sd->autogain = AUTOGAIN_DEF; /* default is autogain active */
887
888 product = id->idProduct;
889/* switch (id->idVendor) { */
890/* case 0x0c45: * Sonix */
891 switch (product) {
892 case 0x6001: /* SN9C102 */
893 case 0x6005: /* SN9C101 */
894 case 0x6007: /* SN9C101 */
895 sd->sensor = SENSOR_TAS5110;
896 sd->sensor_has_gain = 1;
897 sd->sd_desc.nctrls = 4;
898 sd->sd_desc.dq_callback = do_autogain;
899 sif = 1;
900 break;
901 case 0x6009: /* SN9C101 */
902 case 0x600d: /* SN9C101 */
903 case 0x6029: /* SN9C101 */
904 sd->sensor = SENSOR_PAS106;
905 sif = 1;
906 break;
907 case 0x6011: /* SN9C101 - SN9C101G */
908 sd->sensor = SENSOR_OV6650;
909 sd->sensor_has_gain = 1;
910 sd->sensor_addr = 0x60;
911 sd->sd_desc.nctrls = 5;
912 sd->sd_desc.dq_callback = do_autogain;
913 sif = 1;
914 break;
915 case 0x6019: /* SN9C101 */
916 case 0x602c: /* SN9C102 */
917 case 0x602e: /* SN9C102 */
918 sd->sensor = SENSOR_OV7630;
919 sd->sensor_addr = 0x21;
920 break;
921 case 0x60b0: /* SN9C103 */
922 sd->sensor = SENSOR_OV7630_3;
923 sd->sensor_addr = 0x21;
924 sd->fr_h_sz = 18; /* size of frame header */
925 sd->sensor_has_gain = 1;
926 sd->sd_desc.nctrls = 8;
927 sd->sd_desc.dq_callback = do_autogain;
928 sd->autogain = 0;
929 break;
930 case 0x6024: /* SN9C102 */
931 case 0x6025: /* SN9C102 */
932 sd->sensor = SENSOR_TAS5130CXX;
933 break;
934 case 0x6028: /* SN9C102 */
935 sd->sensor = SENSOR_PAS202;
936 break;
937 case 0x602d: /* SN9C102 */
938 sd->sensor = SENSOR_HV7131R;
939 break;
940 case 0x60af: /* SN9C103 */
941 sd->sensor = SENSOR_PAS202;
942 sd->fr_h_sz = 18; /* size of frame header (?) */
943 break;
944 }
945/* break; */
946/* } */
947
948 cam = &gspca_dev->cam;
949 cam->dev_name = (char *) id->driver_info;
950 cam->epaddr = 0x01;
951 if (!sif) {
952 cam->cam_mode = vga_mode;
953 cam->nmodes = ARRAY_SIZE(vga_mode);
954 if (sd->sensor == SENSOR_OV7630_3) {
955 /* We only have 320x240 & 640x480 */
956 cam->cam_mode++;
957 cam->nmodes--;
958 }
959 } else {
960 cam->cam_mode = sif_mode;
961 cam->nmodes = ARRAY_SIZE(sif_mode);
962 }
963 sd->brightness = BRIGHTNESS_DEF;
964 sd->gain = GAIN_DEF;
965 sd->exposure = EXPOSURE_DEF;
966 sd->freq = FREQ_DEF;
967 sd->contrast = CONTRAST_DEF;
968 sd->saturation = SATURATION_DEF;
969 sd->hue = HUE_DEF;
970 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
971 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
972 return 0;
973}
974
975/* this function is called at open time */
976static int sd_open(struct gspca_dev *gspca_dev)
977{
978 reg_r(gspca_dev, 0x00);
979 if (gspca_dev->usb_buf[0] != 0x10)
980 return -ENODEV;
981 return 0;
982}
983
984static void pas106_i2cinit(struct gspca_dev *gspca_dev)
985{
986 int i;
987 const __u8 *data;
988 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
989
990 i = ARRAY_SIZE(pas106_data);
991 data = pas106_data[0];
992 while (--i >= 0) {
993 memcpy(&i2c1[2], data, 2);
994 /* copy 2 bytes from the template */
995 if (i2c_w(gspca_dev, i2c1) < 0)
996 PDEBUG(D_ERR, "i2c error pas106");
997 data += 2;
998 }
999}
1000
1001/* -- start the camera -- */
1002static void sd_start(struct gspca_dev *gspca_dev)
1003{
1004 struct sd *sd = (struct sd *) gspca_dev;
1005 int mode, l;
1006 const __u8 *sn9c10x;
1007 __u8 reg01, reg17;
1008 __u8 reg17_19[3];
1009
1010 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1011 switch (sd->sensor) {
1012 case SENSOR_HV7131R:
1013 sn9c10x = initHv7131;
1014 reg17_19[0] = 0x60;
1015 reg17_19[1] = (mode << 4) | 0x8a;
1016 reg17_19[2] = 0x20;
1017 break;
1018 case SENSOR_OV6650:
1019 sn9c10x = initOv6650;
1020 reg17_19[0] = 0x68;
1021 reg17_19[1] = (mode << 4) | 0x8b;
1022 reg17_19[2] = 0x20;
1023 break;
1024 case SENSOR_OV7630:
1025 sn9c10x = initOv7630;
1026 reg17_19[0] = 0x68;
1027 reg17_19[1] = (mode << 4) | COMP2;
1028 reg17_19[2] = MCK_INIT1;
1029 break;
1030 case SENSOR_OV7630_3:
1031 sn9c10x = initOv7630_3;
1032 reg17_19[0] = 0x68;
1033 reg17_19[1] = (mode << 4) | COMP2;
1034 reg17_19[2] = MCK_INIT1;
1035 break;
1036 case SENSOR_PAS106:
1037 sn9c10x = initPas106;
1038 reg17_19[0] = 0x24; /* 0x28 */
1039 reg17_19[1] = (mode << 4) | COMP1;
1040 reg17_19[2] = MCK_INIT1;
1041 break;
1042 case SENSOR_PAS202:
1043 sn9c10x = initPas202;
1044 reg17_19[0] = mode ? 0x24 : 0x20;
1045 reg17_19[1] = (mode << 4) | 0x89;
1046 reg17_19[2] = 0x20;
1047 break;
1048 case SENSOR_TAS5110:
1049 sn9c10x = initTas5110;
1050 reg17_19[0] = 0x60;
1051 reg17_19[1] = (mode << 4) | 0x86;
1052 reg17_19[2] = 0x2b; /* 0xf3; */
1053 break;
1054 default:
1055/* case SENSOR_TAS5130CXX: */
1056 sn9c10x = initTas5130;
1057 reg17_19[0] = 0x60;
1058 reg17_19[1] = (mode << 4) | COMP;
1059 reg17_19[2] = mode ? 0x23 : 0x43;
1060 break;
1061 }
1062 switch (sd->sensor) {
1063 case SENSOR_OV7630:
1064 reg01 = 0x06;
1065 reg17 = 0x29;
1066 l = sizeof initOv7630;
1067 break;
1068 case SENSOR_OV7630_3:
1069 reg01 = 0x44;
1070 reg17 = 0x68;
1071 l = sizeof initOv7630_3;
1072 break;
1073 default:
1074 reg01 = sn9c10x[0];
1075 reg17 = sn9c10x[0x17 - 1];
1076 l = 0x1f;
1077 break;
1078 }
1079
1080 /* reg 0x01 bit 2 video transfert on */
1081 reg_w(gspca_dev, 0x01, &reg01, 1);
1082 /* reg 0x17 SensorClk enable inv Clk 0x60 */
1083 reg_w(gspca_dev, 0x17, &reg17, 1);
1084/*fixme: for ov7630 102
1085 reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
1086 /* Set the registers from the template */
1087 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
1088 switch (sd->sensor) {
1089 case SENSOR_HV7131R:
1090 i2c_w_vector(gspca_dev, hv7131_sensor_init,
1091 sizeof hv7131_sensor_init);
1092 break;
1093 case SENSOR_OV6650:
1094 i2c_w_vector(gspca_dev, ov6650_sensor_init,
1095 sizeof ov6650_sensor_init);
1096 break;
1097 case SENSOR_OV7630:
1098 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
1099 sizeof ov7630_sensor_init_com);
1100 msleep(200);
1101 i2c_w_vector(gspca_dev, ov7630_sensor_init,
1102 sizeof ov7630_sensor_init);
1103 break;
1104 case SENSOR_OV7630_3:
1105 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
1106 sizeof ov7630_sensor_init_com);
1107 msleep(200);
1108 i2c_w(gspca_dev, ov7630_sensor_init_3[mode]);
1109 break;
1110 case SENSOR_PAS106:
1111 pas106_i2cinit(gspca_dev);
1112 break;
1113 case SENSOR_PAS202:
1114 i2c_w_vector(gspca_dev, pas202_sensor_init,
1115 sizeof pas202_sensor_init);
1116 break;
1117 case SENSOR_TAS5110:
1118 i2c_w_vector(gspca_dev, tas5110_sensor_init,
1119 sizeof tas5110_sensor_init);
1120 break;
1121 default:
1122/* case SENSOR_TAS5130CXX: */
1123 i2c_w_vector(gspca_dev, tas5130_sensor_init,
1124 sizeof tas5130_sensor_init);
1125 break;
1126 }
1127 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
1128 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
1129 /* compression register */
1130 reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
1131 /* H_start */
1132 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
1133 /* V_START */
1134 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
1135 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1136 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
1137 reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
1138 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
1139 reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
1140 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
1141 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
1142 /* Enable video transfert */
1143 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
1144 /* Compression */
1145 reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
1146 msleep(20);
1147
1148 setgain(gspca_dev);
1149 setbrightness(gspca_dev);
1150 setexposure(gspca_dev);
1151 setfreq(gspca_dev);
1152 setsaturation(gspca_dev);
1153 sethue(gspca_dev);
1154 setcontrast(gspca_dev);
1155
1156 sd->autogain_ignore_frames = 0;
1157 atomic_set(&sd->avg_lum, -1);
1158}
1159
1160static void sd_stopN(struct gspca_dev *gspca_dev)
1161{
1162 __u8 ByteSend;
1163
1164 ByteSend = 0x09; /* 0X00 */
1165 reg_w(gspca_dev, 0x01, &ByteSend, 1);
1166}
1167
1168static void sd_stop0(struct gspca_dev *gspca_dev)
1169{
1170}
1171
1172static void sd_close(struct gspca_dev *gspca_dev)
1173{
1174}
1175
1176static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1177 struct gspca_frame *frame, /* target */
1178 unsigned char *data, /* isoc packet */
1179 int len) /* iso packet length */
1180{
1181 int i;
1182 struct sd *sd = (struct sd *) gspca_dev;
1183
1184 /* frames start with:
1185 * ff ff 00 c4 c4 96 synchro
1186 * 00 (unknown)
1187 * xx (frame sequence / size / compression)
1188 * (xx) (idem - extra byte for sn9c103)
1189 * ll mm brightness sum inside auto exposure
1190 * ll mm brightness sum outside auto exposure
1191 * (xx xx xx xx xx) audio values for snc103
1192 */
1193 if (len > 6 && len < 24) {
1194 for (i = 0; i < len - 6; i++) {
1195 if (data[0 + i] == 0xff
1196 && data[1 + i] == 0xff
1197 && data[2 + i] == 0x00
1198 && data[3 + i] == 0xc4
1199 && data[4 + i] == 0xc4
1200 && data[5 + i] == 0x96) { /* start of frame */
1201 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
1202 frame, data, 0);
1203 if (len - i < sd->fr_h_sz) {
1204 atomic_set(&sd->avg_lum, -1);
1205 PDEBUG(D_STREAM, "packet too short to"
1206 " get avg brightness");
1207 } else if (sd->fr_h_sz == 12) {
1208 atomic_set(&sd->avg_lum,
1209 data[i + 8] +
1210 (data[i + 9] << 8));
1211 } else {
1212 atomic_set(&sd->avg_lum,
1213 data[i + 9] +
1214 (data[i + 10] << 8));
1215 }
1216 data += i + sd->fr_h_sz;
1217 len -= i + sd->fr_h_sz;
1218 gspca_frame_add(gspca_dev, FIRST_PACKET,
1219 frame, data, len);
1220 return;
1221 }
1222 }
1223 }
1224 gspca_frame_add(gspca_dev, INTER_PACKET,
1225 frame, data, len);
1226}
1227
1228static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1229{
1230 struct sd *sd = (struct sd *) gspca_dev;
1231
1232 sd->brightness = val;
1233 if (gspca_dev->streaming)
1234 setbrightness(gspca_dev);
1235 return 0;
1236}
1237
1238static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1239{
1240 struct sd *sd = (struct sd *) gspca_dev;
1241
1242 *val = sd->brightness;
1243 return 0;
1244}
1245
1246static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1247{
1248 struct sd *sd = (struct sd *) gspca_dev;
1249
1250 sd->gain = val;
1251 if (gspca_dev->streaming)
1252 setgain(gspca_dev);
1253 return 0;
1254}
1255
1256static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1257{
1258 struct sd *sd = (struct sd *) gspca_dev;
1259
1260 *val = sd->gain;
1261 return 0;
1262}
1263
1264static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1265{
1266 struct sd *sd = (struct sd *) gspca_dev;
1267
1268 sd->exposure = val;
1269 if (gspca_dev->streaming)
1270 setexposure(gspca_dev);
1271 return 0;
1272}
1273
1274static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1275{
1276 struct sd *sd = (struct sd *) gspca_dev;
1277
1278 *val = sd->exposure;
1279 return 0;
1280}
1281
1282static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1283{
1284 struct sd *sd = (struct sd *) gspca_dev;
1285
1286 sd->autogain = val;
1287 /* when switching to autogain set defaults to make sure
1288 we are on a valid point of the autogain gain /
1289 exposure knee graph, and give this change time to
1290 take effect before doing autogain. */
1291 if (sd->autogain) {
1292 sd->exposure = EXPOSURE_DEF;
1293 sd->gain = GAIN_DEF;
1294 if (gspca_dev->streaming) {
1295 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1296 setexposure(gspca_dev);
1297 setgain(gspca_dev);
1298 }
1299 }
1300
1301 return 0;
1302}
1303
1304static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1305{
1306 struct sd *sd = (struct sd *) gspca_dev;
1307
1308 *val = sd->autogain;
1309 return 0;
1310}
1311
1312static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1313{
1314 struct sd *sd = (struct sd *) gspca_dev;
1315
1316 sd->freq = val;
1317 if (gspca_dev->streaming)
1318 setfreq(gspca_dev);
1319 return 0;
1320}
1321
1322static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1323{
1324 struct sd *sd = (struct sd *) gspca_dev;
1325
1326 *val = sd->freq;
1327 return 0;
1328}
1329
1330static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val)
1331{
1332 struct sd *sd = (struct sd *) gspca_dev;
1333
1334 sd->saturation = val;
1335 if (gspca_dev->streaming)
1336 setsaturation(gspca_dev);
1337 return 0;
1338}
1339
1340static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val)
1341{
1342 struct sd *sd = (struct sd *) gspca_dev;
1343
1344 *val = sd->saturation;
1345 return 0;
1346}
1347
1348static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
1349{
1350 struct sd *sd = (struct sd *) gspca_dev;
1351
1352 sd->hue = val;
1353 if (gspca_dev->streaming)
1354 sethue(gspca_dev);
1355 return 0;
1356}
1357
1358static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
1359{
1360 struct sd *sd = (struct sd *) gspca_dev;
1361
1362 *val = sd->hue;
1363 return 0;
1364}
1365
1366static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1367{
1368 struct sd *sd = (struct sd *) gspca_dev;
1369
1370 sd->contrast = val;
1371 if (gspca_dev->streaming)
1372 setcontrast(gspca_dev);
1373 return 0;
1374}
1375
1376static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1377{
1378 struct sd *sd = (struct sd *) gspca_dev;
1379
1380 *val = sd->contrast;
1381 return 0;
1382}
1383
1384static int sd_querymenu(struct gspca_dev *gspca_dev,
1385 struct v4l2_querymenu *menu)
1386{
1387 switch (menu->id) {
1388 case V4L2_CID_POWER_LINE_FREQUENCY:
1389 switch (menu->index) {
1390 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1391 strcpy((char *) menu->name, "NoFliker");
1392 return 0;
1393 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1394 strcpy((char *) menu->name, "50 Hz");
1395 return 0;
1396 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1397 strcpy((char *) menu->name, "60 Hz");
1398 return 0;
1399 }
1400 break;
1401 }
1402 return -EINVAL;
1403}
1404
1405/* sub-driver description */
1406static const struct sd_desc sd_desc = {
1407 .name = MODULE_NAME,
1408 .ctrls = sd_ctrls,
1409 .nctrls = ARRAY_SIZE(sd_ctrls),
1410 .config = sd_config,
1411 .open = sd_open,
1412 .start = sd_start,
1413 .stopN = sd_stopN,
1414 .stop0 = sd_stop0,
1415 .close = sd_close,
1416 .pkt_scan = sd_pkt_scan,
1417 .querymenu = sd_querymenu,
1418};
1419
1420/* -- module initialisation -- */
1421#define DVNM(name) .driver_info = (kernel_ulong_t) name
1422static __devinitdata struct usb_device_id device_table[] = {
1423#ifndef CONFIG_USB_SN9C102
1424 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1425 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1426 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1427 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1428 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1429#endif
1430 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1431#ifndef CONFIG_USB_SN9C102
1432 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1433 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1434 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1435 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1436 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1437 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1438 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1439 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1440 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1441 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1442#endif
1443 {}
1444};
1445MODULE_DEVICE_TABLE(usb, device_table);
1446
1447/* -- device connect -- */
1448static int sd_probe(struct usb_interface *intf,
1449 const struct usb_device_id *id)
1450{
1451 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1452 THIS_MODULE);
1453}
1454
1455static struct usb_driver sd_driver = {
1456 .name = MODULE_NAME,
1457 .id_table = device_table,
1458 .probe = sd_probe,
1459 .disconnect = gspca_disconnect,
1460};
1461
1462/* -- module insert / remove -- */
1463static int __init sd_mod_init(void)
1464{
1465 if (usb_register(&sd_driver) < 0)
1466 return -1;
1467 PDEBUG(D_PROBE, "v%s registered", version);
1468 return 0;
1469}
1470static void __exit sd_mod_exit(void)
1471{
1472 usb_deregister(&sd_driver);
1473 PDEBUG(D_PROBE, "deregistered");
1474}
1475
1476module_init(sd_mod_init);
1477module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
new file mode 100644
index 000000000000..3e68b9926956
--- /dev/null
+++ b/drivers/media/video/gspca/sonixj.c
@@ -0,0 +1,1671 @@
1/*
2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "sonixj"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 int avg_lum;
39 unsigned int exposure;
40
41 unsigned short brightness;
42 unsigned char contrast;
43 unsigned char colors;
44 unsigned char autogain;
45
46 signed char ag_cnt;
47#define AG_CNT_START 13
48
49 char qindex;
50 unsigned char bridge;
51#define BRIDGE_SN9C102P 0
52#define BRIDGE_SN9C105 1
53#define BRIDGE_SN9C110 2
54#define BRIDGE_SN9C120 3
55#define BRIDGE_SN9C325 4
56 char sensor; /* Type of image sensor chip */
57#define SENSOR_HV7131R 0
58#define SENSOR_MI0360 1
59#define SENSOR_MO4000 2
60#define SENSOR_OV7648 3
61#define SENSOR_OV7660 4
62 unsigned char i2c_base;
63};
64
65/* V4L2 controls supported by the driver */
66static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
72static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
74
75static struct ctrl sd_ctrls[] = {
76 {
77 {
78 .id = V4L2_CID_BRIGHTNESS,
79 .type = V4L2_CTRL_TYPE_INTEGER,
80 .name = "Brightness",
81 .minimum = 0,
82 .maximum = 0xffff,
83 .step = 1,
84#define BRIGHTNESS_DEF 0x7fff
85 .default_value = BRIGHTNESS_DEF,
86 },
87 .set = sd_setbrightness,
88 .get = sd_getbrightness,
89 },
90 {
91 {
92 .id = V4L2_CID_CONTRAST,
93 .type = V4L2_CTRL_TYPE_INTEGER,
94 .name = "Contrast",
95 .minimum = 0,
96 .maximum = 127,
97 .step = 1,
98#define CONTRAST_DEF 63
99 .default_value = CONTRAST_DEF,
100 },
101 .set = sd_setcontrast,
102 .get = sd_getcontrast,
103 },
104 {
105 {
106 .id = V4L2_CID_SATURATION,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "Color",
109 .minimum = 0,
110 .maximum = 255,
111 .step = 1,
112#define COLOR_DEF 127
113 .default_value = COLOR_DEF,
114 },
115 .set = sd_setcolors,
116 .get = sd_getcolors,
117 },
118 {
119 {
120 .id = V4L2_CID_AUTOGAIN,
121 .type = V4L2_CTRL_TYPE_BOOLEAN,
122 .name = "Auto Gain",
123 .minimum = 0,
124 .maximum = 1,
125 .step = 1,
126#define AUTOGAIN_DEF 1
127 .default_value = AUTOGAIN_DEF,
128 },
129 .set = sd_setautogain,
130 .get = sd_getautogain,
131 },
132};
133
134static struct v4l2_pix_format vga_mode[] = {
135 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 160,
137 .sizeimage = 160 * 120 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 2},
140 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
141 .bytesperline = 320,
142 .sizeimage = 320 * 240 * 3 / 8 + 590,
143 .colorspace = V4L2_COLORSPACE_JPEG,
144 .priv = 1},
145 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
146 .bytesperline = 640,
147 .sizeimage = 640 * 480 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
149 .priv = 0},
150};
151
152/*Data from sn9c102p+hv71331r */
153static const __u8 sn_hv7131[] = {
154/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
155 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
156/* rega regb regc regd rege regf reg10 reg11 */
157 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
158/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
159 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
160/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
162};
163
164static const __u8 sn_mi0360[] = {
165/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
166 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
167/* rega regb regc regd rege regf reg10 reg11 */
168 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
169/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
170 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
171/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
173};
174
175static const __u8 sn_mo4000[] = {
176/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
177 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
178/* reg9 rega regb regc regd rege regf reg10 reg11*/
179 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
180/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
181 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
182/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
184 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
185 0xd3, 0xdf, 0xea, 0xf5
186};
187
188static const __u8 sn_ov7648[] = {
189 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
190 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
191 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
192};
193
194static const __u8 sn_ov7660[] = {
195/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
196 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
197/* reg9 rega regb regc regd rege regf reg10 reg11*/
198 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
199/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
200 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00,
201/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
203};
204
205/* sequence specific to the sensors - !! index = SENSOR_xxx */
206static const __u8 *sn_tb[] = {
207 sn_hv7131,
208 sn_mi0360,
209 sn_mo4000,
210 sn_ov7648,
211 sn_ov7660
212};
213
214static const __u8 regsn20[] = {
215 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
216 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
217};
218static const __u8 regsn20_sn9c120[] = {
219 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
220 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
221};
222static const __u8 regsn20_sn9c325[] = {
223 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
224 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
225};
226
227static const __u8 reg84[] = {
228 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
229 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
230/* 0x00, 0x00, 0x00, 0x00, 0x00 */
231 0xf7, 0x0f, 0x0a, 0x00, 0x00
232};
233static const __u8 reg84_sn9c120_1[] = {
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x0c, 0x00, 0x00
237};
238static const __u8 reg84_sn9c120_2[] = {
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 0x00, 0x00, 0x0c, 0x02, 0x3b
242};
243static const __u8 reg84_sn9c120_3[] = {
244 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
245 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
246 0xf5, 0x0f, 0x0c, 0x02, 0x3b
247};
248static const __u8 reg84_sn9c325[] = {
249 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
250 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
251 0xf8, 0x0f, 0x00, 0x00, 0x00
252};
253
254static const __u8 hv7131r_sensor_init[][8] = {
255 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
256 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
257 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
258 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
259 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
260 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
261 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
262
263 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
264 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
265 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
266 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
267 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
268 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
269 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
270 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
271
272 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
273 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
274 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
277
278 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
280 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
281 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
283 {}
284};
285static const __u8 mi0360_sensor_init[][8] = {
286 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
287 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
288 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
289 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
290 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
291 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
292 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
305 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
306 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
308 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
309 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
310 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
311 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
312 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
313 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
315 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
316 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
317 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
318 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
319
320 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
321 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
322 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
323 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
324 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
325
326 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
327 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
328 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
329 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
330
331 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
332 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
333/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
334/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
335 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
336 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
337 {}
338};
339static const __u8 mo4000_sensor_init[][8] = {
340 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
358 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
359 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
360 {}
361};
362static const __u8 ov7660_sensor_init[][8] = {
363 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
364 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
365 /* Outformat ?? rawRGB */
366 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
367 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
368/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
369 /* GAIN BLUE RED VREF */
370 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
371 /* COM 1 BAVE GEAVE AECHH */
372 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
373 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
374 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
375/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
376 /* AECH CLKRC COM7 COM8 */
377 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
378 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
379 /* HSTART HSTOP VSTRT VSTOP */
380 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
381 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
382 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
383 /* BOS GBOS GROS ROS (BGGR offset) */
384 {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
385/* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
386 /* AEW AEB VPT BBIAS */
387 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
388 /* GbBIAS RSVD EXHCH EXHCL */
389 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
390 /* RBIAS ADVFL ASDVFH YAVE */
391 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
392 /* HSYST HSYEN HREF */
393 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
394 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
395 /* ADC ACOM OFON TSLB */
396 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
397 /* COM11 COM12 COM13 COM14 */
398 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
399 /* EDGE COM15 COM16 COM17 */
400 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
401 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
402 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
403 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
404 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
405 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
406 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
407 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
408 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
409 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
410 /* LCC1 LCC2 LCC3 LCC4 */
411 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
412 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
413 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
414 /* band gap reference [0..3] DBLV */
415 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
416 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
418 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
419 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
420 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
421 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
422 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
423 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
424 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
425/****** (some exchanges in the win trace) ******/
426 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
427 /* bits[3..0]reserved */
428 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
429 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
430 /* VREF vertical frame ctrl */
431 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
432 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
433 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
434 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
435/* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
436 {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10},
437 {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
438/****** (some exchanges in the win trace) ******/
439 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
440 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
441 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
442 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},
444/****** (some exchanges in the win trace) ******/
445/**********startsensor KO if changed !!****/
446 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
447 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
448 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
449 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
450/* here may start the isoc exchanges */
451 {}
452};
453/* reg0x04 reg0x07 reg 0x10 */
454/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
455
456static const __u8 ov7648_sensor_init[][8] = {
457 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
458 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
459 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
460 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
461 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
462 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
464 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
465 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
466 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
467 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
468 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
469 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
471 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
472 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
473 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
474 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
475 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
476 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
477 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
478 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
479 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
480 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
481 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
482 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
483 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
484 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
485 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
486 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
487 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
488 * This is currently setting a
489 * blue tint, and some things more , i leave it here for future test if
490 * somene is having problems with color on this sensor
491 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
492 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
493 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
494 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
495 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
496 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
497 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
498 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
499 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
500 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
501 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
502 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
503 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
504 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
505 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
506 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
507 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
508/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
509 {}
510};
511
512static const __u8 qtable4[] = {
513 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
514 0x06, 0x08, 0x0A, 0x11,
515 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
516 0x19, 0x19, 0x17, 0x15,
517 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
518 0x21, 0x2E, 0x21, 0x23,
519 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
520 0x25, 0x29, 0x2C, 0x29,
521 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
522 0x17, 0x1B, 0x29, 0x29,
523 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
524 0x29, 0x29, 0x29, 0x29,
525 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
526 0x29, 0x29, 0x29, 0x29,
527 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
528 0x29, 0x29, 0x29, 0x29
529};
530
531/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
532static void reg_r(struct gspca_dev *gspca_dev,
533 __u16 value, int len)
534{
535 usb_control_msg(gspca_dev->dev,
536 usb_rcvctrlpipe(gspca_dev->dev, 0),
537 0,
538 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
539 value, 0,
540 gspca_dev->usb_buf, len,
541 500);
542}
543
544static void reg_w(struct gspca_dev *gspca_dev,
545 __u16 value,
546 const __u8 *buffer,
547 int len)
548{
549 if (len <= sizeof gspca_dev->usb_buf) {
550 memcpy(gspca_dev->usb_buf, buffer, len);
551 usb_control_msg(gspca_dev->dev,
552 usb_sndctrlpipe(gspca_dev->dev, 0),
553 0x08,
554 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
555 value, 0,
556 gspca_dev->usb_buf, len,
557 500);
558 } else {
559 __u8 *tmpbuf;
560
561 tmpbuf = kmalloc(len, GFP_KERNEL);
562 memcpy(tmpbuf, buffer, len);
563 usb_control_msg(gspca_dev->dev,
564 usb_sndctrlpipe(gspca_dev->dev, 0),
565 0x08,
566 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
567 value, 0,
568 tmpbuf, len,
569 500);
570 kfree(tmpbuf);
571 }
572}
573
574/* I2C write 2 bytes */
575static void i2c_w2(struct gspca_dev *gspca_dev,
576 const __u8 *buffer)
577{
578 struct sd *sd = (struct sd *) gspca_dev;
579 __u8 mode[8];
580
581 /* is i2c ready */
582 mode[0] = 0x81 | (2 << 4);
583 mode[1] = sd->i2c_base;
584 mode[2] = buffer[0];
585 mode[3] = buffer[1];
586 mode[4] = 0;
587 mode[5] = 0;
588 mode[6] = 0;
589 mode[7] = 0x10;
590 reg_w(gspca_dev, 0x08, mode, 8);
591}
592
593/* I2C write 8 bytes */
594static void i2c_w8(struct gspca_dev *gspca_dev,
595 const __u8 *buffer)
596{
597 reg_w(gspca_dev, 0x08, buffer, 8);
598 msleep(1);
599}
600
601/* read 5 bytes in gspca_dev->usb_buf */
602static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
603{
604 struct sd *sd = (struct sd *) gspca_dev;
605 __u8 mode[8];
606
607 mode[0] = 0x81 | 0x10;
608 mode[1] = sd->i2c_base;
609 mode[2] = reg;
610 mode[3] = 0;
611 mode[4] = 0;
612 mode[5] = 0;
613 mode[6] = 0;
614 mode[7] = 0x10;
615 i2c_w8(gspca_dev, mode);
616 mode[0] = 0x81 | (5 << 4) | 0x02;
617 mode[2] = 0;
618 i2c_w8(gspca_dev, mode);
619 reg_r(gspca_dev, 0x0a, 5);
620}
621
622static int probesensor(struct gspca_dev *gspca_dev)
623{
624 struct sd *sd = (struct sd *) gspca_dev;
625 __u8 reg02;
626 static const __u8 datasend[] = { 2, 0 };
627 /* reg val1 val2 val3 val4 */
628
629 i2c_w2(gspca_dev, datasend);
630/* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
631 msleep(10);
632 reg02 = 0x66;
633 reg_w(gspca_dev, 0x02, &reg02, 1); /* Gpio on */
634 msleep(10);
635 i2c_r5(gspca_dev, 0); /* read sensor id */
636 if (gspca_dev->usb_buf[0] == 0x02
637 && gspca_dev->usb_buf[1] == 0x09
638 && gspca_dev->usb_buf[2] == 0x01
639 && gspca_dev->usb_buf[3] == 0x00
640 && gspca_dev->usb_buf[4] == 0x00) {
641 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
642 sd->sensor = SENSOR_HV7131R;
643 return SENSOR_HV7131R;
644 }
645 PDEBUG(D_PROBE, "Find Sensor %d %d %d",
646 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
647 gspca_dev->usb_buf[2]);
648 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
649 return -ENODEV;
650}
651
652static int configure_gpio(struct gspca_dev *gspca_dev,
653 const __u8 *sn9c1xx)
654{
655 struct sd *sd = (struct sd *) gspca_dev;
656 __u8 data;
657 __u8 regF1;
658 const __u8 *reg9a;
659 static const __u8 reg9a_def[] =
660 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
661 static const __u8 reg9a_sn9c120[] = /* from win trace */
662 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
663 static const __u8 reg9a_sn9c325[] =
664 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
665
666
667 regF1 = 0x00;
668 reg_w(gspca_dev, 0xf1, &regF1, 1);
669 reg_w(gspca_dev, 0x01, &sn9c1xx[0], 1); /*fixme:jfm was [1] en v1*/
670
671 /* configure gpio */
672 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
673 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
674 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm was 3 */
675 switch (sd->bridge) {
676 case BRIDGE_SN9C325:
677 reg9a = reg9a_sn9c325;
678 break;
679 case BRIDGE_SN9C120:
680 reg9a = reg9a_sn9c120;
681 break;
682 default:
683 reg9a = reg9a_def;
684 break;
685 }
686 reg_w(gspca_dev, 0x9a, reg9a, 6);
687
688 data = 0x60; /*fixme:jfm 60 00 00 (3) */
689 reg_w(gspca_dev, 0xd4, &data, 1);
690
691 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
692
693 switch (sd->bridge) {
694 case BRIDGE_SN9C120: /* from win trace */
695 data = 0x61;
696 reg_w(gspca_dev, 0x01, &data, 1);
697 data = 0x20;
698 reg_w(gspca_dev, 0x17, &data, 1);
699 data = 0x60;
700 reg_w(gspca_dev, 0x01, &data, 1);
701 break;
702 case BRIDGE_SN9C325:
703 data = 0x43;
704 reg_w(gspca_dev, 0x01, &data, 1);
705 data = 0xae;
706 reg_w(gspca_dev, 0x17, &data, 1);
707 data = 0x42;
708 reg_w(gspca_dev, 0x01, &data, 1);
709 break;
710 default:
711 data = 0x43;
712 reg_w(gspca_dev, 0x01, &data, 1);
713 data = 0x61;
714 reg_w(gspca_dev, 0x17, &data, 1);
715 data = 0x42;
716 reg_w(gspca_dev, 0x01, &data, 1);
717 }
718
719 if (sd->sensor == SENSOR_HV7131R) {
720 if (probesensor(gspca_dev) < 0)
721 return -ENODEV;
722 }
723 return 0;
724}
725
726static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
727{
728 int i = 0;
729 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
730 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
731
732 while (hv7131r_sensor_init[i][0]) {
733 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
734 i++;
735 }
736 i2c_w8(gspca_dev, SetSensorClk);
737}
738
739static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
740{
741 int i = 0;
742
743 while (mi0360_sensor_init[i][0]) {
744 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
745 i++;
746 }
747}
748
749static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
750{
751 int i = 0;
752
753 while (mo4000_sensor_init[i][0]) {
754 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
755 i++;
756 }
757}
758
759static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
760{
761 int i = 0;
762
763 while (ov7648_sensor_init[i][0]) {
764 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
765 i++;
766 }
767}
768
769static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
770{
771 int i = 0;
772
773 while (ov7660_sensor_init[i][0]) {
774 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
775 i++;
776 }
777}
778
779/* this function is called at probe time */
780static int sd_config(struct gspca_dev *gspca_dev,
781 const struct usb_device_id *id)
782{
783 struct sd *sd = (struct sd *) gspca_dev;
784 struct cam *cam;
785 __u16 vendor;
786 __u16 product;
787
788 vendor = id->idVendor;
789 product = id->idProduct;
790 sd->sensor = -1;
791 switch (vendor) {
792 case 0x0458: /* Genius */
793/* switch (product) {
794 case 0x7025: */
795 sd->bridge = BRIDGE_SN9C120;
796 sd->sensor = SENSOR_MI0360;
797 sd->i2c_base = 0x5d;
798/* break;
799 } */
800 break;
801 case 0x045e:
802/* switch (product) {
803 case 0x00f5:
804 case 0x00f7: */
805 sd->bridge = BRIDGE_SN9C105;
806 sd->sensor = SENSOR_OV7660;
807 sd->i2c_base = 0x21;
808/* break;
809 } */
810 break;
811 case 0x0471: /* Philips */
812/* switch (product) {
813 case 0x0327:
814 case 0x0328:
815 case 0x0330: */
816 sd->bridge = BRIDGE_SN9C105;
817 sd->sensor = SENSOR_MI0360;
818 sd->i2c_base = 0x5d;
819/* break;
820 } */
821 break;
822 case 0x0c45: /* Sonix */
823 switch (product) {
824 case 0x6040:
825 sd->bridge = BRIDGE_SN9C102P;
826/* sd->sensor = SENSOR_MI0360; * from BW600.inf */
827/*fixme: MI0360 base=5d ? */
828 sd->sensor = SENSOR_HV7131R; /* gspcav1 value */
829 sd->i2c_base = 0x11;
830 break;
831/* case 0x607a: * from BW600.inf
832 sd->bridge = BRIDGE_SN9C102P;
833 sd->sensor = SENSOR_OV7648;
834 sd->i2c_base = 0x??;
835 break; */
836 case 0x607c:
837 sd->bridge = BRIDGE_SN9C102P;
838 sd->sensor = SENSOR_HV7131R;
839 sd->i2c_base = 0x11;
840 break;
841/* case 0x607e: * from BW600.inf
842 sd->bridge = BRIDGE_SN9C102P;
843 sd->sensor = SENSOR_OV7630;
844 sd->i2c_base = 0x??;
845 break; */
846 case 0x60c0:
847 sd->bridge = BRIDGE_SN9C105;
848 sd->sensor = SENSOR_MI0360;
849 sd->i2c_base = 0x5d;
850 break;
851/* case 0x60c8: * from BW600.inf
852 sd->bridge = BRIDGE_SN9C105;
853 sd->sensor = SENSOR_OM6801;
854 sd->i2c_base = 0x??;
855 break; */
856/* case 0x60cc: * from BW600.inf
857 sd->bridge = BRIDGE_SN9C105;
858 sd->sensor = SENSOR_HV7131GP;
859 sd->i2c_base = 0x??;
860 break; */
861 case 0x60ec:
862 sd->bridge = BRIDGE_SN9C105;
863 sd->sensor = SENSOR_MO4000;
864 sd->i2c_base = 0x21;
865 break;
866/* case 0x60ef: * from BW600.inf
867 sd->bridge = BRIDGE_SN9C105;
868 sd->sensor = SENSOR_ICM105C;
869 sd->i2c_base = 0x??;
870 break; */
871/* case 0x60fa: * from BW600.inf
872 sd->bridge = BRIDGE_SN9C105;
873 sd->sensor = SENSOR_OV7648;
874 sd->i2c_base = 0x??;
875 break; */
876 case 0x60fb:
877 sd->bridge = BRIDGE_SN9C105;
878 sd->sensor = SENSOR_OV7660;
879 sd->i2c_base = 0x21;
880 break;
881 case 0x60fc:
882 sd->bridge = BRIDGE_SN9C105;
883 sd->sensor = SENSOR_HV7131R;
884 sd->i2c_base = 0x11;
885 break;
886/* case 0x60fe: * from BW600.inf
887 sd->bridge = BRIDGE_SN9C105;
888 sd->sensor = SENSOR_OV7630;
889 sd->i2c_base = 0x??;
890 break; */
891/* case 0x6108: * from BW600.inf
892 sd->bridge = BRIDGE_SN9C120;
893 sd->sensor = SENSOR_OM6801;
894 sd->i2c_base = 0x??;
895 break; */
896/* case 0x6122: * from BW600.inf
897 sd->bridge = BRIDGE_SN9C110;
898 sd->sensor = SENSOR_ICM105C;
899 sd->i2c_base = 0x??;
900 break; */
901 case 0x612a:
902/* sd->bridge = BRIDGE_SN9C110; * in BW600.inf */
903 sd->bridge = BRIDGE_SN9C325;
904 sd->sensor = SENSOR_OV7648;
905 sd->i2c_base = 0x21;
906/*fixme: sensor_init has base = 00 et 6e!*/
907 break;
908/* case 0x6123: * from BW600.inf
909 sd->bridge = BRIDGE_SN9C110;
910 sd->sensor = SENSOR_SanyoCCD;
911 sd->i2c_base = 0x??;
912 break; */
913 case 0x612c:
914 sd->bridge = BRIDGE_SN9C110;
915 sd->sensor = SENSOR_MO4000;
916 sd->i2c_base = 0x21;
917 break;
918/* case 0x612e: * from BW600.inf
919 sd->bridge = BRIDGE_SN9C110;
920 sd->sensor = SENSOR_OV7630;
921 sd->i2c_base = 0x??;
922 break; */
923/* case 0x612f: * from BW600.inf
924 sd->bridge = BRIDGE_SN9C110;
925 sd->sensor = SENSOR_ICM105C;
926 sd->i2c_base = 0x??;
927 break; */
928 case 0x6130:
929 sd->bridge = BRIDGE_SN9C120;
930 sd->sensor = SENSOR_MI0360;
931 sd->i2c_base = 0x5d;
932 break;
933 case 0x6138:
934 sd->bridge = BRIDGE_SN9C120;
935 sd->sensor = SENSOR_MO4000;
936 sd->i2c_base = 0x21;
937 break;
938/* case 0x613a: * from BW600.inf
939 sd->bridge = BRIDGE_SN9C120;
940 sd->sensor = SENSOR_OV7648;
941 sd->i2c_base = 0x??;
942 break; */
943 case 0x613b:
944 sd->bridge = BRIDGE_SN9C120;
945 sd->sensor = SENSOR_OV7660;
946 sd->i2c_base = 0x21;
947 break;
948 case 0x613c:
949 sd->bridge = BRIDGE_SN9C120;
950 sd->sensor = SENSOR_HV7131R;
951 sd->i2c_base = 0x11;
952 break;
953/* case 0x613e: * from BW600.inf
954 sd->bridge = BRIDGE_SN9C120;
955 sd->sensor = SENSOR_OV7630;
956 sd->i2c_base = 0x??;
957 break; */
958 }
959 break;
960 }
961 if (sd->sensor < 0) {
962 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
963 vendor, product);
964 return -EINVAL;
965 }
966
967 cam = &gspca_dev->cam;
968 cam->dev_name = (char *) id->driver_info;
969 cam->epaddr = 0x01;
970 cam->cam_mode = vga_mode;
971 cam->nmodes = ARRAY_SIZE(vga_mode);
972
973 sd->qindex = 4; /* set the quantization table */
974 sd->brightness = BRIGHTNESS_DEF;
975 sd->contrast = CONTRAST_DEF;
976 sd->colors = COLOR_DEF;
977 sd->autogain = AUTOGAIN_DEF;
978 return 0;
979}
980
981/* this function is called at open time */
982static int sd_open(struct gspca_dev *gspca_dev)
983{
984 struct sd *sd = (struct sd *) gspca_dev;
985/* const __u8 *sn9c1xx; */
986 __u8 regF1;
987 __u8 regGpio[] = { 0x29, 0x74 };
988
989 /* setup a selector by bridge */
990 regF1 = 0x01;
991 reg_w(gspca_dev, 0xf1, &regF1, 1);
992 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
993 regF1 = gspca_dev->usb_buf[0];
994 reg_w(gspca_dev, 0xf1, &regF1, 1);
995 reg_r(gspca_dev, 0x00, 1);
996 regF1 = gspca_dev->usb_buf[0];
997 switch (sd->bridge) {
998 case BRIDGE_SN9C102P:
999 if (regF1 != 0x11)
1000 return -ENODEV;
1001 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
1002 break;
1003 case BRIDGE_SN9C105:
1004 if (regF1 != 0x11)
1005 return -ENODEV;
1006 reg_w(gspca_dev, 0x02, regGpio, 2);
1007 break;
1008 case BRIDGE_SN9C110:
1009 if (regF1 != 0x12)
1010 return -ENODEV;
1011 regGpio[1] = 0x62;
1012 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
1013 break;
1014 case BRIDGE_SN9C120:
1015 if (regF1 != 0x12)
1016 return -ENODEV;
1017 regGpio[1] = 0x70;
1018 reg_w(gspca_dev, 0x02, regGpio, 2);
1019 break;
1020 default:
1021/* case BRIDGE_SN9C325: */
1022 if (regF1 != 0x12)
1023 return -ENODEV;
1024 regGpio[1] = 0x62;
1025 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
1026 break;
1027 }
1028
1029 regF1 = 0x01;
1030 reg_w(gspca_dev, 0xf1, &regF1, 1);
1031
1032 return 0;
1033}
1034
1035static unsigned int setexposure(struct gspca_dev *gspca_dev,
1036 unsigned int expo)
1037{
1038 struct sd *sd = (struct sd *) gspca_dev;
1039 static const __u8 doit[] = /* update sensor */
1040 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1041 static const __u8 sensorgo[] = /* sensor on */
1042 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1043 static const __u8 gainMo[] =
1044 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1045
1046 switch (sd->sensor) {
1047 case SENSOR_HV7131R: {
1048 __u8 Expodoit[] =
1049 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1050
1051 Expodoit[3] = expo >> 16;
1052 Expodoit[4] = expo >> 8;
1053 Expodoit[5] = expo;
1054 i2c_w8(gspca_dev, Expodoit);
1055 break;
1056 }
1057 case SENSOR_MI0360: {
1058 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1059 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1060
1061 if (expo > 0x0635)
1062 expo = 0x0635;
1063 else if (expo < 0x0001)
1064 expo = 0x0001;
1065 expoMi[3] = expo >> 8;
1066 expoMi[4] = expo;
1067 i2c_w8(gspca_dev, expoMi);
1068 i2c_w8(gspca_dev, doit);
1069 i2c_w8(gspca_dev, sensorgo);
1070 break;
1071 }
1072 case SENSOR_MO4000: {
1073 __u8 expoMof[] =
1074 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1075 __u8 expoMo10[] =
1076 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1077
1078 if (expo > 0x1fff)
1079 expo = 0x1fff;
1080 else if (expo < 0x0001)
1081 expo = 0x0001;
1082 expoMof[3] = (expo & 0x03fc) >> 2;
1083 i2c_w8(gspca_dev, expoMof);
1084 expoMo10[3] = ((expo & 0x1c00) >> 10)
1085 | ((expo & 0x0003) << 4);
1086 i2c_w8(gspca_dev, expoMo10);
1087 i2c_w8(gspca_dev, gainMo);
1088 PDEBUG(D_CONF, "set exposure %d",
1089 ((expoMo10[3] & 0x07) << 10)
1090 | (expoMof[3] << 2)
1091 | ((expoMo10[3] & 0x30) >> 4));
1092 break;
1093 }
1094 }
1095 return expo;
1096}
1097
1098static void setbrightness(struct gspca_dev *gspca_dev)
1099{
1100 struct sd *sd = (struct sd *) gspca_dev;
1101 unsigned int expo;
1102 __u8 k2;
1103
1104 switch (sd->sensor) {
1105 case SENSOR_HV7131R:
1106 expo = sd->brightness << 4;
1107 if (expo > 0x002dc6c0)
1108 expo = 0x002dc6c0;
1109 else if (expo < 0x02a0)
1110 expo = 0x02a0;
1111 sd->exposure = setexposure(gspca_dev, expo);
1112 break;
1113 case SENSOR_MI0360:
1114 expo = sd->brightness >> 4;
1115 sd->exposure = setexposure(gspca_dev, expo);
1116 break;
1117 case SENSOR_MO4000:
1118 expo = sd->brightness >> 4;
1119 sd->exposure = setexposure(gspca_dev, expo);
1120 break;
1121 case SENSOR_OV7660:
1122 return; /*jfm??*/
1123 }
1124
1125 k2 = sd->brightness >> 10;
1126 reg_w(gspca_dev, 0x96, &k2, 1);
1127}
1128
1129static void setcontrast(struct gspca_dev *gspca_dev)
1130{
1131 struct sd *sd = (struct sd *) gspca_dev;
1132 __u8 k2;
1133 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1134
1135 if (sd->sensor == SENSOR_OV7660)
1136 return; /*jfm??*/
1137 k2 = sd->contrast;
1138 contrast[2] = k2;
1139 contrast[0] = (k2 + 1) >> 1;
1140 contrast[4] = (k2 + 1) / 5;
1141 reg_w(gspca_dev, 0x84, contrast, 6);
1142}
1143
1144static void setcolors(struct gspca_dev *gspca_dev)
1145{
1146 struct sd *sd = (struct sd *) gspca_dev;
1147 __u8 data;
1148 int colour;
1149
1150 colour = sd->colors - 128;
1151 if (colour > 0)
1152 data = (colour + 32) & 0x7f; /* blue */
1153 else
1154 data = (-colour + 32) & 0x7f; /* red */
1155 reg_w(gspca_dev, 0x05, &data, 1);
1156}
1157
1158/* -- start the camera -- */
1159static void sd_start(struct gspca_dev *gspca_dev)
1160{
1161 struct sd *sd = (struct sd *) gspca_dev;
1162 int i;
1163 __u8 data;
1164 __u8 reg1;
1165 __u8 reg17;
1166 const __u8 *sn9c1xx;
1167 int mode;
1168 static const __u8 DC29[] = { 0x6a, 0x50, 0x00, 0x00, 0x50, 0x3c };
1169 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1170 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1171 static const __u8 CA_sn9c120[] =
1172 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1173 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1174 static const __u8 CE_sn9c325[] =
1175 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1176
1177 sn9c1xx = sn_tb[(int) sd->sensor];
1178 configure_gpio(gspca_dev, sn9c1xx);
1179
1180/*fixme:jfm this sequence should appear at end of sd_start */
1181/* with
1182 data = 0x44;
1183 reg_w(gspca_dev, 0x01, &data, 1); */
1184 reg_w(gspca_dev, 0x15, &sn9c1xx[0x15], 1);
1185 reg_w(gspca_dev, 0x16, &sn9c1xx[0x16], 1);
1186 reg_w(gspca_dev, 0x12, &sn9c1xx[0x12], 1);
1187 reg_w(gspca_dev, 0x13, &sn9c1xx[0x13], 1);
1188 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
1189 reg_w(gspca_dev, 0xd2, &DC29[0], 1);
1190 reg_w(gspca_dev, 0xd3, &DC29[1], 1);
1191 reg_w(gspca_dev, 0xc6, &DC29[2], 1);
1192 reg_w(gspca_dev, 0xc7, &DC29[3], 1);
1193 reg_w(gspca_dev, 0xc8, &DC29[4], 1);
1194 reg_w(gspca_dev, 0xc9, &DC29[5], 1);
1195/*fixme:jfm end of ending sequence */
1196 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
1197 switch (sd->bridge) {
1198 case BRIDGE_SN9C325:
1199 data = 0xae;
1200 break;
1201 case BRIDGE_SN9C120:
1202 data = 0xa0;
1203 break;
1204 default:
1205 data = 0x60;
1206 break;
1207 }
1208 reg_w(gspca_dev, 0x17, &data, 1);
1209 reg_w(gspca_dev, 0x05, &sn9c1xx[5], 1);
1210 reg_w(gspca_dev, 0x07, &sn9c1xx[7], 1);
1211 reg_w(gspca_dev, 0x06, &sn9c1xx[6], 1);
1212 reg_w(gspca_dev, 0x14, &sn9c1xx[0x14], 1);
1213 switch (sd->bridge) {
1214 case BRIDGE_SN9C325:
1215 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1216 sizeof regsn20_sn9c325);
1217 for (i = 0; i < 8; i++)
1218 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1219 sizeof reg84_sn9c325);
1220 data = 0x0a;
1221 reg_w(gspca_dev, 0x9a, &data, 1);
1222 data = 0x60;
1223 reg_w(gspca_dev, 0x99, &data, 1);
1224 break;
1225 case BRIDGE_SN9C120:
1226 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1227 sizeof regsn20_sn9c120);
1228 for (i = 0; i < 2; i++)
1229 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1230 sizeof reg84_sn9c120_1);
1231 for (i = 0; i < 6; i++)
1232 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1233 sizeof reg84_sn9c120_2);
1234 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1235 sizeof reg84_sn9c120_3);
1236 data = 0x05;
1237 reg_w(gspca_dev, 0x9a, &data, 1);
1238 data = 0x5b;
1239 reg_w(gspca_dev, 0x99, &data, 1);
1240 break;
1241 default:
1242 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
1243 for (i = 0; i < 8; i++)
1244 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1245 data = 0x08;
1246 reg_w(gspca_dev, 0x9a, &data, 1);
1247 data = 0x59;
1248 reg_w(gspca_dev, 0x99, &data, 1);
1249 break;
1250 }
1251
1252 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1253 reg1 = 0x02;
1254 reg17 = 0x61;
1255 switch (sd->sensor) {
1256 case SENSOR_HV7131R:
1257 hv7131R_InitSensor(gspca_dev);
1258 if (mode)
1259 reg1 = 0x46; /* 320 clk 48Mhz */
1260 else
1261 reg1 = 0x06; /* 640 clk 24Mz */
1262 break;
1263 case SENSOR_MI0360:
1264 mi0360_InitSensor(gspca_dev);
1265 if (mode)
1266 reg1 = 0x46; /* 320 clk 48Mhz */
1267 else
1268 reg1 = 0x06; /* 640 clk 24Mz */
1269 break;
1270 case SENSOR_MO4000:
1271 mo4000_InitSensor(gspca_dev);
1272 if (mode) {
1273/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1274 reg1 = 0x06; /* clk 24Mz */
1275 } else {
1276 reg17 = 0x22; /* 640 MCKSIZE */
1277 reg1 = 0x06; /* 640 clk 24Mz */
1278 }
1279 break;
1280 case SENSOR_OV7648:
1281 reg17 = 0xa2;
1282 reg1 = 0x44;
1283 ov7648_InitSensor(gspca_dev);
1284/* if (mode)
1285 ; * 320x2...
1286 else
1287 ; * 640x... */
1288 break;
1289 default:
1290/* case SENSOR_OV7660: */
1291 ov7660_InitSensor(gspca_dev);
1292 if (mode) {
1293/* reg17 = 0x21; * 320 */
1294/* reg1 = 0x44; */
1295 reg1 = 0x46;
1296 } else {
1297 reg17 = 0xa2; /* 640 */
1298 reg1 = 0x40;
1299 }
1300 break;
1301 }
1302 reg_w(gspca_dev, 0xc0, C0, 6);
1303 switch (sd->bridge) {
1304 case BRIDGE_SN9C120: /*jfm ?? */
1305 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
1306 break;
1307 default:
1308 reg_w(gspca_dev, 0xca, CA, 4);
1309 break;
1310 }
1311 switch (sd->bridge) {
1312 case BRIDGE_SN9C120: /*jfm ?? */
1313 case BRIDGE_SN9C325:
1314 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
1315 break;
1316 default:
1317 reg_w(gspca_dev, 0xce, CE, 4);
1318 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1319 break;
1320 }
1321
1322 /* here change size mode 0 -> VGA; 1 -> CIF */
1323 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
1324 reg_w(gspca_dev, 0x18, &data, 1);
1325
1326 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1327 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1328
1329 data = sn9c1xx[0x18] | (mode << 4);
1330 reg_w(gspca_dev, 0x18, &data, 1);
1331
1332 reg_w(gspca_dev, 0x17, &reg17, 1);
1333 reg_w(gspca_dev, 0x01, &reg1, 1);
1334 setbrightness(gspca_dev);
1335 setcontrast(gspca_dev);
1336}
1337
1338static void sd_stopN(struct gspca_dev *gspca_dev)
1339{
1340 struct sd *sd = (struct sd *) gspca_dev;
1341 static const __u8 stophv7131[] =
1342 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1343 static const __u8 stopmi0360[] =
1344 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1345 __u8 regF1;
1346 __u8 data;
1347 const __u8 *sn9c1xx;
1348
1349 data = 0x0b;
1350 switch (sd->sensor) {
1351 case SENSOR_HV7131R:
1352 i2c_w8(gspca_dev, stophv7131);
1353 data = 0x2b;
1354 break;
1355 case SENSOR_MI0360:
1356 i2c_w8(gspca_dev, stopmi0360);
1357 data = 0x29;
1358 break;
1359 case SENSOR_MO4000:
1360 break;
1361 case SENSOR_OV7648:
1362 data = 0x29;
1363 break;
1364 default:
1365/* case SENSOR_OV7660: */
1366 break;
1367 }
1368 sn9c1xx = sn_tb[(int) sd->sensor];
1369 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1370 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 1);
1371 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1372 reg_w(gspca_dev, 0x01, &data, 1);
1373 regF1 = 0x01;
1374 reg_w(gspca_dev, 0xf1, &regF1, 1);
1375}
1376
1377static void sd_stop0(struct gspca_dev *gspca_dev)
1378{
1379}
1380
1381static void sd_close(struct gspca_dev *gspca_dev)
1382{
1383}
1384
1385static void setautogain(struct gspca_dev *gspca_dev)
1386{
1387 struct sd *sd = (struct sd *) gspca_dev;
1388 /* Thanks S., without your advice, autobright should not work :) */
1389 int delta;
1390 int expotimes = 0;
1391 __u8 luma_mean = 130;
1392 __u8 luma_delta = 20;
1393
1394 delta = sd->avg_lum;
1395 if (delta < luma_mean - luma_delta ||
1396 delta > luma_mean + luma_delta) {
1397 switch (sd->sensor) {
1398 case SENSOR_HV7131R:
1399 expotimes = sd->exposure >> 8;
1400 expotimes += (luma_mean - delta) >> 4;
1401 if (expotimes < 0)
1402 expotimes = 0;
1403 sd->exposure = setexposure(gspca_dev,
1404 (unsigned int) (expotimes << 8));
1405 break;
1406 case SENSOR_MO4000:
1407 case SENSOR_MI0360:
1408 expotimes = sd->exposure;
1409 expotimes += (luma_mean - delta) >> 6;
1410 if (expotimes < 0)
1411 expotimes = 0;
1412 sd->exposure = setexposure(gspca_dev,
1413 (unsigned int) expotimes);
1414 setcolors(gspca_dev);
1415 break;
1416 }
1417 }
1418}
1419
1420static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1421 struct gspca_frame *frame, /* target */
1422 __u8 *data, /* isoc packet */
1423 int len) /* iso packet length */
1424{
1425 struct sd *sd = (struct sd *) gspca_dev;
1426 int sof, avg_lum;
1427
1428 sof = len - 64;
1429 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1430
1431 /* end of frame */
1432 gspca_frame_add(gspca_dev, LAST_PACKET,
1433 frame, data, sof + 2);
1434 if (sd->ag_cnt < 0)
1435 return;
1436 if (--sd->ag_cnt >= 0)
1437 return;
1438 sd->ag_cnt = AG_CNT_START;
1439/* w1 w2 w3 */
1440/* w4 w5 w6 */
1441/* w7 w8 */
1442/* w4 */
1443 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1444/* w6 */
1445 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1446/* w2 */
1447 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1448/* w8 */
1449 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1450/* w5 */
1451 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1452 avg_lum >>= 4;
1453 sd->avg_lum = avg_lum;
1454 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1455 setautogain(gspca_dev);
1456 return;
1457 }
1458 if (gspca_dev->last_packet_type == LAST_PACKET) {
1459
1460 /* put the JPEG 422 header */
1461 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1462 }
1463 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1464}
1465
1466static unsigned int getexposure(struct gspca_dev *gspca_dev)
1467{
1468 struct sd *sd = (struct sd *) gspca_dev;
1469 __u8 hexpo, mexpo, lexpo;
1470
1471 switch (sd->sensor) {
1472 case SENSOR_HV7131R:
1473 /* read sensor exposure */
1474 i2c_r5(gspca_dev, 0x25);
1475 return (gspca_dev->usb_buf[0] << 16)
1476 | (gspca_dev->usb_buf[1] << 8)
1477 | gspca_dev->usb_buf[2];
1478 case SENSOR_MI0360:
1479 /* read sensor exposure */
1480 i2c_r5(gspca_dev, 0x09);
1481 return (gspca_dev->usb_buf[0] << 8)
1482 | gspca_dev->usb_buf[1];
1483 case SENSOR_MO4000:
1484 i2c_r5(gspca_dev, 0x0e);
1485 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1486 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1487 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
1488 PDEBUG(D_CONF, "exposure %d",
1489 (hexpo << 10) | (mexpo << 2) | lexpo);
1490 return (hexpo << 10) | (mexpo << 2) | lexpo;
1491 default:
1492/* case SENSOR_OV7660: */
1493 /* read sensor exposure */
1494 i2c_r5(gspca_dev, 0x04);
1495 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1496 lexpo = gspca_dev->usb_buf[0] & 0x02;
1497 i2c_r5(gspca_dev, 0x08);
1498 mexpo = gspca_dev->usb_buf[2];
1499 return (hexpo << 10) | (mexpo << 2) | lexpo;
1500 }
1501}
1502
1503static void getbrightness(struct gspca_dev *gspca_dev)
1504{
1505 struct sd *sd = (struct sd *) gspca_dev;
1506
1507 /* hardcoded registers seem not readable */
1508 switch (sd->sensor) {
1509 case SENSOR_HV7131R:
1510/* sd->brightness = 0x7fff; */
1511 sd->brightness = getexposure(gspca_dev) >> 4;
1512 break;
1513 case SENSOR_MI0360:
1514 sd->brightness = getexposure(gspca_dev) << 4;
1515 break;
1516 case SENSOR_MO4000:
1517/* sd->brightness = 0x1fff; */
1518 sd->brightness = getexposure(gspca_dev) << 4;
1519 break;
1520 }
1521}
1522
1523static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1524{
1525 struct sd *sd = (struct sd *) gspca_dev;
1526
1527 sd->brightness = val;
1528 if (gspca_dev->streaming)
1529 setbrightness(gspca_dev);
1530 return 0;
1531}
1532
1533static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1534{
1535 struct sd *sd = (struct sd *) gspca_dev;
1536
1537 getbrightness(gspca_dev);
1538 *val = sd->brightness;
1539 return 0;
1540}
1541
1542static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1543{
1544 struct sd *sd = (struct sd *) gspca_dev;
1545
1546 sd->contrast = val;
1547 if (gspca_dev->streaming)
1548 setcontrast(gspca_dev);
1549 return 0;
1550}
1551
1552static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1553{
1554 struct sd *sd = (struct sd *) gspca_dev;
1555
1556 *val = sd->contrast;
1557 return 0;
1558}
1559
1560static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1561{
1562 struct sd *sd = (struct sd *) gspca_dev;
1563
1564 sd->colors = val;
1565 if (gspca_dev->streaming)
1566 setcolors(gspca_dev);
1567 return 0;
1568}
1569
1570static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1571{
1572 struct sd *sd = (struct sd *) gspca_dev;
1573
1574 *val = sd->colors;
1575 return 0;
1576}
1577
1578static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1579{
1580 struct sd *sd = (struct sd *) gspca_dev;
1581
1582 sd->autogain = val;
1583 if (val)
1584 sd->ag_cnt = AG_CNT_START;
1585 else
1586 sd->ag_cnt = -1;
1587 return 0;
1588}
1589
1590static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1591{
1592 struct sd *sd = (struct sd *) gspca_dev;
1593
1594 *val = sd->autogain;
1595 return 0;
1596}
1597
1598/* sub-driver description */
1599static const struct sd_desc sd_desc = {
1600 .name = MODULE_NAME,
1601 .ctrls = sd_ctrls,
1602 .nctrls = ARRAY_SIZE(sd_ctrls),
1603 .config = sd_config,
1604 .open = sd_open,
1605 .start = sd_start,
1606 .stopN = sd_stopN,
1607 .stop0 = sd_stop0,
1608 .close = sd_close,
1609 .pkt_scan = sd_pkt_scan,
1610};
1611
1612/* -- module initialisation -- */
1613#define DVNM(name) .driver_info = (kernel_ulong_t) name
1614static const __devinitdata struct usb_device_id device_table[] = {
1615#ifndef CONFIG_USB_SN9C102
1616 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1617 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1618 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1619 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1620 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
1621#endif
1622 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1623 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1624 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1625 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1626 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1627 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1628 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1629 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1630 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
1631#ifndef CONFIG_USB_SN9C102
1632 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1633 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1634 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1635 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
1636#endif
1637 {}
1638};
1639MODULE_DEVICE_TABLE(usb, device_table);
1640
1641/* -- device connect -- */
1642static int sd_probe(struct usb_interface *intf,
1643 const struct usb_device_id *id)
1644{
1645 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1646 THIS_MODULE);
1647}
1648
1649static struct usb_driver sd_driver = {
1650 .name = MODULE_NAME,
1651 .id_table = device_table,
1652 .probe = sd_probe,
1653 .disconnect = gspca_disconnect,
1654};
1655
1656/* -- module insert / remove -- */
1657static int __init sd_mod_init(void)
1658{
1659 if (usb_register(&sd_driver) < 0)
1660 return -1;
1661 info("v%s registered", version);
1662 return 0;
1663}
1664static void __exit sd_mod_exit(void)
1665{
1666 usb_deregister(&sd_driver);
1667 info("deregistered");
1668}
1669
1670module_init(sd_mod_init);
1671module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
new file mode 100644
index 000000000000..156206118795
--- /dev/null
+++ b/drivers/media/video/gspca/spca500.c
@@ -0,0 +1,1216 @@
1/*
2 * SPCA500 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca500"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 __u8 packet[ISO_MAX_SIZE + 128];
39 /* !! no more than 128 ff in an ISO packet */
40
41 unsigned char brightness;
42 unsigned char contrast;
43 unsigned char colors;
44
45 char qindex;
46 char subtype;
47#define AgfaCl20 0
48#define AiptekPocketDV 1
49#define BenqDC1016 2
50#define CreativePCCam300 3
51#define DLinkDSC350 4
52#define Gsmartmini 5
53#define IntelPocketPCCamera 6
54#define KodakEZ200 7
55#define LogitechClickSmart310 8
56#define LogitechClickSmart510 9
57#define LogitechTraveler 10
58#define MustekGsmart300 11
59#define Optimedia 12
60#define PalmPixDC85 13
61#define ToptroIndus 14
62};
63
64/* V4L2 controls supported by the driver */
65static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
71
72static struct ctrl sd_ctrls[] = {
73 {
74 {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
79 .maximum = 255,
80 .step = 1,
81#define BRIGHTNESS_DEF 127
82 .default_value = BRIGHTNESS_DEF,
83 },
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
86 },
87 {
88 {
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
93 .maximum = 63,
94 .step = 1,
95#define CONTRAST_DEF 31
96 .default_value = CONTRAST_DEF,
97 },
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
100 },
101 {
102 {
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
107 .maximum = 63,
108 .step = 1,
109#define COLOR_DEF 31
110 .default_value = COLOR_DEF,
111 },
112 .set = sd_setcolors,
113 .get = sd_getcolors,
114 },
115};
116
117static struct v4l2_pix_format vga_mode[] = {
118 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
119 .bytesperline = 320,
120 .sizeimage = 320 * 240 * 3 / 8 + 590,
121 .colorspace = V4L2_COLORSPACE_JPEG,
122 .priv = 1},
123 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
124 .bytesperline = 640,
125 .sizeimage = 640 * 480 * 3 / 8 + 590,
126 .colorspace = V4L2_COLORSPACE_JPEG,
127 .priv = 0},
128};
129
130static struct v4l2_pix_format sif_mode[] = {
131 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
132 .bytesperline = 176,
133 .sizeimage = 176 * 144 * 3 / 8 + 590,
134 .colorspace = V4L2_COLORSPACE_JPEG,
135 .priv = 1},
136 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
137 .bytesperline = 352,
138 .sizeimage = 352 * 288 * 3 / 8 + 590,
139 .colorspace = V4L2_COLORSPACE_JPEG,
140 .priv = 0},
141};
142
143/* Frame packet header offsets for the spca500 */
144#define SPCA500_OFFSET_PADDINGLB 2
145#define SPCA500_OFFSET_PADDINGHB 3
146#define SPCA500_OFFSET_MODE 4
147#define SPCA500_OFFSET_IMGWIDTH 5
148#define SPCA500_OFFSET_IMGHEIGHT 6
149#define SPCA500_OFFSET_IMGMODE 7
150#define SPCA500_OFFSET_QTBLINDEX 8
151#define SPCA500_OFFSET_FRAMSEQ 9
152#define SPCA500_OFFSET_CDSPINFO 10
153#define SPCA500_OFFSET_GPIO 11
154#define SPCA500_OFFSET_AUGPIO 12
155#define SPCA500_OFFSET_DATA 16
156
157
158static const __u16 spca500_visual_defaults[][3] = {
159 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
160 * hue (H byte) = 0,
161 * saturation/hue enable,
162 * brightness/contrast enable.
163 */
164 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
165 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
166 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
167 * hue (H byte) = 0, saturation/hue enable,
168 * brightness/contrast enable.
169 * was 0x0003, now 0x0000.
170 */
171 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
172 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
173 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
174 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
175 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
176 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
177 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
178 {0x0c, 0x0004, 0x0000},
179 /* set interface */
180 {}
181};
182static const __u16 Clicksmart510_defaults[][3] = {
183 {0x00, 0x00, 0x8211},
184 {0x00, 0x01, 0x82c0},
185 {0x00, 0x10, 0x82cb},
186 {0x00, 0x0f, 0x800d},
187 {0x00, 0x82, 0x8225},
188 {0x00, 0x21, 0x8228},
189 {0x00, 0x00, 0x8203},
190 {0x00, 0x00, 0x8204},
191 {0x00, 0x08, 0x8205},
192 {0x00, 0xf8, 0x8206},
193 {0x00, 0x28, 0x8207},
194 {0x00, 0xa0, 0x8208},
195 {0x00, 0x08, 0x824a},
196 {0x00, 0x08, 0x8214},
197 {0x00, 0x80, 0x82c1},
198 {0x00, 0x00, 0x82c2},
199 {0x00, 0x00, 0x82ca},
200 {0x00, 0x80, 0x82c1},
201 {0x00, 0x04, 0x82c2},
202 {0x00, 0x00, 0x82ca},
203 {0x00, 0xfc, 0x8100},
204 {0x00, 0xfc, 0x8105},
205 {0x00, 0x30, 0x8101},
206 {0x00, 0x00, 0x8102},
207 {0x00, 0x00, 0x8103},
208 {0x00, 0x66, 0x8107},
209 {0x00, 0x00, 0x816b},
210 {0x00, 0x00, 0x8155},
211 {0x00, 0x01, 0x8156},
212 {0x00, 0x60, 0x8157},
213 {0x00, 0x40, 0x8158},
214 {0x00, 0x0a, 0x8159},
215 {0x00, 0x06, 0x815a},
216 {0x00, 0x00, 0x813f},
217 {0x00, 0x00, 0x8200},
218 {0x00, 0x19, 0x8201},
219 {0x00, 0x00, 0x82c1},
220 {0x00, 0xa0, 0x82c2},
221 {0x00, 0x00, 0x82ca},
222 {0x00, 0x00, 0x8117},
223 {0x00, 0x00, 0x8118},
224 {0x00, 0x65, 0x8119},
225 {0x00, 0x00, 0x811a},
226 {0x00, 0x00, 0x811b},
227 {0x00, 0x55, 0x811c},
228 {0x00, 0x65, 0x811d},
229 {0x00, 0x55, 0x811e},
230 {0x00, 0x16, 0x811f},
231 {0x00, 0x19, 0x8120},
232 {0x00, 0x80, 0x8103},
233 {0x00, 0x83, 0x816b},
234 {0x00, 0x25, 0x8168},
235 {0x00, 0x01, 0x820f},
236 {0x00, 0xff, 0x8115},
237 {0x00, 0x48, 0x8116},
238 {0x00, 0x50, 0x8151},
239 {0x00, 0x40, 0x8152},
240 {0x00, 0x78, 0x8153},
241 {0x00, 0x40, 0x8154},
242 {0x00, 0x00, 0x8167},
243 {0x00, 0x20, 0x8168},
244 {0x00, 0x00, 0x816a},
245 {0x00, 0x03, 0x816b},
246 {0x00, 0x20, 0x8169},
247 {0x00, 0x60, 0x8157},
248 {0x00, 0x00, 0x8190},
249 {0x00, 0x00, 0x81a1},
250 {0x00, 0x00, 0x81b2},
251 {0x00, 0x27, 0x8191},
252 {0x00, 0x27, 0x81a2},
253 {0x00, 0x27, 0x81b3},
254 {0x00, 0x4b, 0x8192},
255 {0x00, 0x4b, 0x81a3},
256 {0x00, 0x4b, 0x81b4},
257 {0x00, 0x66, 0x8193},
258 {0x00, 0x66, 0x81a4},
259 {0x00, 0x66, 0x81b5},
260 {0x00, 0x79, 0x8194},
261 {0x00, 0x79, 0x81a5},
262 {0x00, 0x79, 0x81b6},
263 {0x00, 0x8a, 0x8195},
264 {0x00, 0x8a, 0x81a6},
265 {0x00, 0x8a, 0x81b7},
266 {0x00, 0x9b, 0x8196},
267 {0x00, 0x9b, 0x81a7},
268 {0x00, 0x9b, 0x81b8},
269 {0x00, 0xa6, 0x8197},
270 {0x00, 0xa6, 0x81a8},
271 {0x00, 0xa6, 0x81b9},
272 {0x00, 0xb2, 0x8198},
273 {0x00, 0xb2, 0x81a9},
274 {0x00, 0xb2, 0x81ba},
275 {0x00, 0xbe, 0x8199},
276 {0x00, 0xbe, 0x81aa},
277 {0x00, 0xbe, 0x81bb},
278 {0x00, 0xc8, 0x819a},
279 {0x00, 0xc8, 0x81ab},
280 {0x00, 0xc8, 0x81bc},
281 {0x00, 0xd2, 0x819b},
282 {0x00, 0xd2, 0x81ac},
283 {0x00, 0xd2, 0x81bd},
284 {0x00, 0xdb, 0x819c},
285 {0x00, 0xdb, 0x81ad},
286 {0x00, 0xdb, 0x81be},
287 {0x00, 0xe4, 0x819d},
288 {0x00, 0xe4, 0x81ae},
289 {0x00, 0xe4, 0x81bf},
290 {0x00, 0xed, 0x819e},
291 {0x00, 0xed, 0x81af},
292 {0x00, 0xed, 0x81c0},
293 {0x00, 0xf7, 0x819f},
294 {0x00, 0xf7, 0x81b0},
295 {0x00, 0xf7, 0x81c1},
296 {0x00, 0xff, 0x81a0},
297 {0x00, 0xff, 0x81b1},
298 {0x00, 0xff, 0x81c2},
299 {0x00, 0x03, 0x8156},
300 {0x00, 0x00, 0x8211},
301 {0x00, 0x20, 0x8168},
302 {0x00, 0x01, 0x8202},
303 {0x00, 0x30, 0x8101},
304 {0x00, 0x00, 0x8111},
305 {0x00, 0x00, 0x8112},
306 {0x00, 0x00, 0x8113},
307 {0x00, 0x00, 0x8114},
308 {}
309};
310
311static const __u8 qtable_creative_pccam[2][64] = {
312 { /* Q-table Y-components */
313 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
314 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
315 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
316 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
317 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
318 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
319 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
320 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
321 { /* Q-table C-components */
322 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
323 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
326 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
327 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
328 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
329 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
330};
331
332static const __u8 qtable_kodak_ez200[2][64] = {
333 { /* Q-table Y-components */
334 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
335 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
336 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
337 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
338 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
339 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
340 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
341 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
342 { /* Q-table C-components */
343 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
344 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
347 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
348 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
349 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
350 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
351};
352
353static const __u8 qtable_pocketdv[2][64] = {
354 { /* Q-table Y-components start registers 0x8800 */
355 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
356 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
357 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
358 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
359 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
360 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
361 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
362 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
363 },
364 { /* Q-table C-components start registers 0x8840 */
365 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
366 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
367 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
368 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
369 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
370 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
371 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
372 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
373};
374
375/* read 'len' bytes to gspca_dev->usb_buf */
376static void reg_r(struct gspca_dev *gspca_dev,
377 __u16 index,
378 __u16 length)
379{
380 usb_control_msg(gspca_dev->dev,
381 usb_rcvctrlpipe(gspca_dev->dev, 0),
382 0,
383 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
384 0, /* value */
385 index, gspca_dev->usb_buf, length, 500);
386}
387
388static int reg_w(struct gspca_dev *gspca_dev,
389 __u16 req, __u16 index, __u16 value)
390{
391 int ret;
392
393 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
394 ret = usb_control_msg(gspca_dev->dev,
395 usb_sndctrlpipe(gspca_dev->dev, 0),
396 req,
397 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
398 value, index, NULL, 0, 500);
399 if (ret < 0)
400 PDEBUG(D_ERR, "reg write: error %d", ret);
401 return ret;
402}
403
404/* returns: negative is error, pos or zero is data */
405static int reg_r_12(struct gspca_dev *gspca_dev,
406 __u16 req, /* bRequest */
407 __u16 index, /* wIndex */
408 __u16 length) /* wLength (1 or 2 only) */
409{
410 int ret;
411
412 gspca_dev->usb_buf[1] = 0;
413 ret = usb_control_msg(gspca_dev->dev,
414 usb_rcvctrlpipe(gspca_dev->dev, 0),
415 req,
416 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
417 0, /* value */
418 index,
419 gspca_dev->usb_buf, length,
420 500); /* timeout */
421 if (ret < 0) {
422 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
423 return -1;
424 }
425 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
426}
427
428/*
429 * Simple function to wait for a given 8-bit value to be returned from
430 * a reg_read call.
431 * Returns: negative is error or timeout, zero is success.
432 */
433static int reg_r_wait(struct gspca_dev *gspca_dev,
434 __u16 reg, __u16 index, __u16 value)
435{
436 int ret, cnt = 20;
437
438 while (--cnt > 0) {
439 ret = reg_r_12(gspca_dev, reg, index, 1);
440 if (ret == value)
441 return 0;
442 msleep(50);
443 }
444 return -EIO;
445}
446
447static int write_vector(struct gspca_dev *gspca_dev,
448 const __u16 data[][3])
449{
450 int ret, i = 0;
451
452 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
453 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
454 if (ret < 0)
455 return ret;
456 i++;
457 }
458 return 0;
459}
460
461static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
462 unsigned int request,
463 unsigned int ybase,
464 unsigned int cbase,
465 const __u8 qtable[2][64])
466{
467 int i, err;
468
469 /* loop over y components */
470 for (i = 0; i < 64; i++) {
471 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
472 if (err < 0)
473 return err;
474 }
475
476 /* loop over c components */
477 for (i = 0; i < 64; i++) {
478 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
479 if (err < 0)
480 return err;
481 }
482 return 0;
483}
484
485static void spca500_ping310(struct gspca_dev *gspca_dev)
486{
487 reg_r(gspca_dev, 0x0d04, 2);
488 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
489 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
490}
491
492static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
493{
494 reg_r(gspca_dev, 0x0d05, 2);
495 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
496 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
497 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
498 spca500_ping310(gspca_dev);
499
500 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
501 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
502 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
503 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
504 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
505 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
506 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
507 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
508 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
509 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
510 /* 00 for adjust shutter */
511 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
512 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
513 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
514}
515
516static void spca500_setmode(struct gspca_dev *gspca_dev,
517 __u8 xmult, __u8 ymult)
518{
519 int mode;
520
521 /* set x multiplier */
522 reg_w(gspca_dev, 0, 0x8001, xmult);
523
524 /* set y multiplier */
525 reg_w(gspca_dev, 0, 0x8002, ymult);
526
527 /* use compressed mode, VGA, with mode specific subsample */
528 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
529 reg_w(gspca_dev, 0, 0x8003, mode << 4);
530}
531
532static int spca500_full_reset(struct gspca_dev *gspca_dev)
533{
534 int err;
535
536 /* send the reset command */
537 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
538 if (err < 0)
539 return err;
540
541 /* wait for the reset to complete */
542 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
543 if (err < 0)
544 return err;
545 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
546 if (err < 0)
547 return err;
548 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
549 if (err < 0) {
550 PDEBUG(D_ERR, "reg_r_wait() failed");
551 return err;
552 }
553 /* all ok */
554 return 0;
555}
556
557/* Synchro the Bridge with sensor */
558/* Maybe that will work on all spca500 chip */
559/* because i only own a clicksmart310 try for that chip */
560/* using spca50x_set_packet_size() cause an Ooops here */
561/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
562/* up-port the same feature as in 2.4.x kernel */
563static int spca500_synch310(struct gspca_dev *gspca_dev)
564{
565 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
566 PDEBUG(D_ERR, "Set packet size: set interface error");
567 goto error;
568 }
569 spca500_ping310(gspca_dev);
570
571 reg_r(gspca_dev, 0x0d00, 1);
572
573 /* need alt setting here */
574 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
575
576 /* Windoze use pipe with altsetting 6 why 7 here */
577 if (usb_set_interface(gspca_dev->dev,
578 gspca_dev->iface,
579 gspca_dev->alt) < 0) {
580 PDEBUG(D_ERR, "Set packet size: set interface error");
581 goto error;
582 }
583 return 0;
584error:
585 return -EBUSY;
586}
587
588static void spca500_reinit(struct gspca_dev *gspca_dev)
589{
590 int err;
591 __u8 Data;
592
593 /* some unknow command from Aiptek pocket dv and family300 */
594
595 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
596 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
597 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
598
599 /* enable drop packet */
600 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
601
602 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
603 qtable_pocketdv);
604 if (err < 0)
605 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
606
607 /* set qtable index */
608 reg_w(gspca_dev, 0x00, 0x8880, 2);
609 /* family cam Quicksmart stuff */
610 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
611 /* Set agc transfer: synced inbetween frames */
612 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
613 /* Init SDRAM - needed for SDRAM access */
614 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
615 /*Start init sequence or stream */
616 reg_w(gspca_dev, 0, 0x8003, 0x00);
617 /* switch to video camera mode */
618 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
619 msleep(2000);
620 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
621 reg_r(gspca_dev, 0x816b, 1);
622 Data = gspca_dev->usb_buf[0];
623 reg_w(gspca_dev, 0x00, 0x816b, Data);
624 }
625}
626
627/* this function is called at probe time */
628static int sd_config(struct gspca_dev *gspca_dev,
629 const struct usb_device_id *id)
630{
631 struct sd *sd = (struct sd *) gspca_dev;
632 struct cam *cam;
633 __u16 vendor;
634 __u16 product;
635
636 vendor = id->idVendor;
637 product = id->idProduct;
638 switch (vendor) {
639 case 0x040a: /* Kodak cameras */
640/* switch (product) { */
641/* case 0x0300: */
642 sd->subtype = KodakEZ200;
643/* break; */
644/* } */
645 break;
646 case 0x041e: /* Creative cameras */
647/* switch (product) { */
648/* case 0x400a: */
649 sd->subtype = CreativePCCam300;
650/* break; */
651/* } */
652 break;
653 case 0x046d: /* Logitech Labtec */
654 switch (product) {
655 case 0x0890:
656 sd->subtype = LogitechTraveler;
657 break;
658 case 0x0900:
659 sd->subtype = LogitechClickSmart310;
660 break;
661 case 0x0901:
662 sd->subtype = LogitechClickSmart510;
663 break;
664 }
665 break;
666 case 0x04a5: /* Benq */
667/* switch (product) { */
668/* case 0x300c: */
669 sd->subtype = BenqDC1016;
670/* break; */
671/* } */
672 break;
673 case 0x04fc: /* SunPlus */
674/* switch (product) { */
675/* case 0x7333: */
676 sd->subtype = PalmPixDC85;
677/* break; */
678/* } */
679 break;
680 case 0x055f: /* Mustek cameras */
681 switch (product) {
682 case 0xc200:
683 sd->subtype = MustekGsmart300;
684 break;
685 case 0xc220:
686 sd->subtype = Gsmartmini;
687 break;
688 }
689 break;
690 case 0x06bd: /* Agfa Cl20 */
691/* switch (product) { */
692/* case 0x0404: */
693 sd->subtype = AgfaCl20;
694/* break; */
695/* } */
696 break;
697 case 0x06be: /* Optimedia */
698/* switch (product) { */
699/* case 0x0800: */
700 sd->subtype = Optimedia;
701/* break; */
702/* } */
703 break;
704 case 0x084d: /* D-Link / Minton */
705/* switch (product) { */
706/* case 0x0003: * DSC-350 / S-Cam F5 */
707 sd->subtype = DLinkDSC350;
708/* break; */
709/* } */
710 break;
711 case 0x08ca: /* Aiptek */
712/* switch (product) { */
713/* case 0x0103: */
714 sd->subtype = AiptekPocketDV;
715/* break; */
716/* } */
717 break;
718 case 0x2899: /* ToptroIndustrial */
719/* switch (product) { */
720/* case 0x012c: */
721 sd->subtype = ToptroIndus;
722/* break; */
723/* } */
724 break;
725 case 0x8086: /* Intel */
726/* switch (product) { */
727/* case 0x0630: * Pocket PC Camera */
728 sd->subtype = IntelPocketPCCamera;
729/* break; */
730/* } */
731 break;
732 }
733 cam = &gspca_dev->cam;
734 cam->dev_name = (char *) id->driver_info;
735 cam->epaddr = 0x01;
736 if (sd->subtype != LogitechClickSmart310) {
737 cam->cam_mode = vga_mode;
738 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
739 } else {
740 cam->cam_mode = sif_mode;
741 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
742 }
743 sd->qindex = 5;
744 sd->brightness = BRIGHTNESS_DEF;
745 sd->contrast = CONTRAST_DEF;
746 sd->colors = COLOR_DEF;
747 return 0;
748}
749
750/* this function is called at open time */
751static int sd_open(struct gspca_dev *gspca_dev)
752{
753 struct sd *sd = (struct sd *) gspca_dev;
754
755 /* initialisation of spca500 based cameras is deferred */
756 PDEBUG(D_STREAM, "SPCA500 init");
757 if (sd->subtype == LogitechClickSmart310)
758 spca500_clksmart310_init(gspca_dev);
759/* else
760 spca500_initialise(gspca_dev); */
761 PDEBUG(D_STREAM, "SPCA500 init done");
762 return 0;
763}
764
765static void sd_start(struct gspca_dev *gspca_dev)
766{
767 struct sd *sd = (struct sd *) gspca_dev;
768 int err;
769 __u8 Data;
770 __u8 xmult, ymult;
771
772 if (sd->subtype == LogitechClickSmart310) {
773 xmult = 0x16;
774 ymult = 0x12;
775 } else {
776 xmult = 0x28;
777 ymult = 0x1e;
778 }
779
780 /* is there a sensor here ? */
781 reg_r(gspca_dev, 0x8a04, 1);
782 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
783 gspca_dev->usb_buf[0]);
784 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
785 gspca_dev->curr_mode, xmult, ymult);
786
787 /* setup qtable */
788 switch (sd->subtype) {
789 case LogitechClickSmart310:
790 spca500_setmode(gspca_dev, xmult, ymult);
791
792 /* enable drop packet */
793 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
794 reg_w(gspca_dev, 0x00, 0x8880, 3);
795 err = spca50x_setup_qtable(gspca_dev,
796 0x00, 0x8800, 0x8840,
797 qtable_creative_pccam);
798 if (err < 0)
799 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
800 /* Init SDRAM - needed for SDRAM access */
801 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
802
803 /* switch to video camera mode */
804 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
805 msleep(500);
806 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
807 PDEBUG(D_ERR, "reg_r_wait() failed");
808
809 reg_r(gspca_dev, 0x816b, 1);
810 Data = gspca_dev->usb_buf[0];
811 reg_w(gspca_dev, 0x00, 0x816b, Data);
812
813 spca500_synch310(gspca_dev);
814
815 write_vector(gspca_dev, spca500_visual_defaults);
816 spca500_setmode(gspca_dev, xmult, ymult);
817 /* enable drop packet */
818 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
819 PDEBUG(D_ERR, "failed to enable drop packet");
820 reg_w(gspca_dev, 0x00, 0x8880, 3);
821 err = spca50x_setup_qtable(gspca_dev,
822 0x00, 0x8800, 0x8840,
823 qtable_creative_pccam);
824 if (err < 0)
825 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
826
827 /* Init SDRAM - needed for SDRAM access */
828 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
829
830 /* switch to video camera mode */
831 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
832
833 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
834 PDEBUG(D_ERR, "reg_r_wait() failed");
835
836 reg_r(gspca_dev, 0x816b, 1);
837 Data = gspca_dev->usb_buf[0];
838 reg_w(gspca_dev, 0x00, 0x816b, Data);
839 break;
840 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
841 case IntelPocketPCCamera: /* FIXME: Temporary fix for
842 * Intel Pocket PC Camera
843 * - NWG (Sat 29th March 2003) */
844
845 /* do a full reset */
846 err = spca500_full_reset(gspca_dev);
847 if (err < 0)
848 PDEBUG(D_ERR, "spca500_full_reset failed");
849
850 /* enable drop packet */
851 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
852 if (err < 0)
853 PDEBUG(D_ERR, "failed to enable drop packet");
854 reg_w(gspca_dev, 0x00, 0x8880, 3);
855 err = spca50x_setup_qtable(gspca_dev,
856 0x00, 0x8800, 0x8840,
857 qtable_creative_pccam);
858 if (err < 0)
859 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
860
861 spca500_setmode(gspca_dev, xmult, ymult);
862 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
863
864 /* switch to video camera mode */
865 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
866
867 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
868 PDEBUG(D_ERR, "reg_r_wait() failed");
869
870 reg_r(gspca_dev, 0x816b, 1);
871 Data = gspca_dev->usb_buf[0];
872 reg_w(gspca_dev, 0x00, 0x816b, Data);
873
874/* write_vector(gspca_dev, spca500_visual_defaults); */
875 break;
876 case KodakEZ200: /* Kodak EZ200 */
877
878 /* do a full reset */
879 err = spca500_full_reset(gspca_dev);
880 if (err < 0)
881 PDEBUG(D_ERR, "spca500_full_reset failed");
882 /* enable drop packet */
883 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
884 reg_w(gspca_dev, 0x00, 0x8880, 0);
885 err = spca50x_setup_qtable(gspca_dev,
886 0x00, 0x8800, 0x8840,
887 qtable_kodak_ez200);
888 if (err < 0)
889 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
890 spca500_setmode(gspca_dev, xmult, ymult);
891
892 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
893
894 /* switch to video camera mode */
895 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
896
897 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
898 PDEBUG(D_ERR, "reg_r_wait() failed");
899
900 reg_r(gspca_dev, 0x816b, 1);
901 Data = gspca_dev->usb_buf[0];
902 reg_w(gspca_dev, 0x00, 0x816b, Data);
903
904/* write_vector(gspca_dev, spca500_visual_defaults); */
905 break;
906
907 case BenqDC1016:
908 case DLinkDSC350: /* FamilyCam 300 */
909 case AiptekPocketDV: /* Aiptek PocketDV */
910 case Gsmartmini: /*Mustek Gsmart Mini */
911 case MustekGsmart300: /* Mustek Gsmart 300 */
912 case PalmPixDC85:
913 case Optimedia:
914 case ToptroIndus:
915 case AgfaCl20:
916 spca500_reinit(gspca_dev);
917 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
918 /* enable drop packet */
919 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
920
921 err = spca50x_setup_qtable(gspca_dev,
922 0x00, 0x8800, 0x8840, qtable_pocketdv);
923 if (err < 0)
924 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
925 reg_w(gspca_dev, 0x00, 0x8880, 2);
926
927 /* familycam Quicksmart pocketDV stuff */
928 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
929 /* Set agc transfer: synced inbetween frames */
930 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
931 /* Init SDRAM - needed for SDRAM access */
932 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
933
934 spca500_setmode(gspca_dev, xmult, ymult);
935 /* switch to video camera mode */
936 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
937
938 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
939
940 reg_r(gspca_dev, 0x816b, 1);
941 Data = gspca_dev->usb_buf[0];
942 reg_w(gspca_dev, 0x00, 0x816b, Data);
943 break;
944 case LogitechTraveler:
945 case LogitechClickSmart510:
946 reg_w(gspca_dev, 0x02, 0x00, 0x00);
947 /* enable drop packet */
948 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
949
950 err = spca50x_setup_qtable(gspca_dev,
951 0x00, 0x8800,
952 0x8840, qtable_creative_pccam);
953 if (err < 0)
954 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
955 reg_w(gspca_dev, 0x00, 0x8880, 3);
956 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
957 /* Init SDRAM - needed for SDRAM access */
958 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
959
960 spca500_setmode(gspca_dev, xmult, ymult);
961
962 /* switch to video camera mode */
963 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
964 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
965
966 reg_r(gspca_dev, 0x816b, 1);
967 Data = gspca_dev->usb_buf[0];
968 reg_w(gspca_dev, 0x00, 0x816b, Data);
969 write_vector(gspca_dev, Clicksmart510_defaults);
970 break;
971 }
972}
973
974static void sd_stopN(struct gspca_dev *gspca_dev)
975{
976 reg_w(gspca_dev, 0, 0x8003, 0x00);
977
978 /* switch to video camera mode */
979 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
980 reg_r(gspca_dev, 0x8000, 1);
981 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
982 gspca_dev->usb_buf[0]);
983}
984
985static void sd_stop0(struct gspca_dev *gspca_dev)
986{
987}
988
989static void sd_close(struct gspca_dev *gspca_dev)
990{
991}
992
993static void sd_pkt_scan(struct gspca_dev *gspca_dev,
994 struct gspca_frame *frame, /* target */
995 __u8 *data, /* isoc packet */
996 int len) /* iso packet length */
997{
998 struct sd *sd = (struct sd *) gspca_dev;
999 int i;
1000 __u8 *s, *d;
1001 static __u8 ffd9[] = {0xff, 0xd9};
1002
1003/* frames are jpeg 4.1.1 without 0xff escape */
1004 if (data[0] == 0xff) {
1005 if (data[1] != 0x01) { /* drop packet */
1006/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1007 return;
1008 }
1009 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1010 ffd9, 2);
1011
1012 /* put the JPEG header in the new frame */
1013 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x22);
1014
1015 data += SPCA500_OFFSET_DATA;
1016 len -= SPCA500_OFFSET_DATA;
1017 } else {
1018 data += 1;
1019 len -= 1;
1020 }
1021
1022 /* add 0x00 after 0xff */
1023 for (i = len; --i >= 0; )
1024 if (data[i] == 0xff)
1025 break;
1026 if (i < 0) { /* no 0xff */
1027 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1028 return;
1029 }
1030 s = data;
1031 d = sd->packet;
1032 for (i = 0; i < len; i++) {
1033 *d++ = *s++;
1034 if (s[-1] == 0xff)
1035 *d++ = 0x00;
1036 }
1037 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1038 sd->packet, d - sd->packet);
1039}
1040
1041static void setbrightness(struct gspca_dev *gspca_dev)
1042{
1043 struct sd *sd = (struct sd *) gspca_dev;
1044
1045 reg_w(gspca_dev, 0x00, 0x8167,
1046 (__u8) (sd->brightness - 128));
1047}
1048
1049static void getbrightness(struct gspca_dev *gspca_dev)
1050{
1051 struct sd *sd = (struct sd *) gspca_dev;
1052 int ret;
1053
1054 ret = reg_r_12(gspca_dev, 0x00, 0x8167, 1);
1055 if (ret >= 0)
1056 sd->brightness = ret + 128;
1057}
1058
1059static void setcontrast(struct gspca_dev *gspca_dev)
1060{
1061 struct sd *sd = (struct sd *) gspca_dev;
1062
1063 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
1064}
1065
1066static void getcontrast(struct gspca_dev *gspca_dev)
1067{
1068 struct sd *sd = (struct sd *) gspca_dev;
1069 int ret;
1070
1071 ret = reg_r_12(gspca_dev, 0x0, 0x8168, 1);
1072 if (ret >= 0)
1073 sd->contrast = ret;
1074}
1075
1076static void setcolors(struct gspca_dev *gspca_dev)
1077{
1078 struct sd *sd = (struct sd *) gspca_dev;
1079
1080 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
1081}
1082
1083static void getcolors(struct gspca_dev *gspca_dev)
1084{
1085 struct sd *sd = (struct sd *) gspca_dev;
1086 int ret;
1087
1088 ret = reg_r_12(gspca_dev, 0x0, 0x8169, 1);
1089 if (ret >= 0)
1090 sd->colors = ret;
1091}
1092
1093static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1094{
1095 struct sd *sd = (struct sd *) gspca_dev;
1096
1097 sd->brightness = val;
1098 if (gspca_dev->streaming)
1099 setbrightness(gspca_dev);
1100 return 0;
1101}
1102
1103static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1104{
1105 struct sd *sd = (struct sd *) gspca_dev;
1106
1107 getbrightness(gspca_dev);
1108 *val = sd->brightness;
1109 return 0;
1110}
1111
1112static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1113{
1114 struct sd *sd = (struct sd *) gspca_dev;
1115
1116 sd->contrast = val;
1117 if (gspca_dev->streaming)
1118 setcontrast(gspca_dev);
1119 return 0;
1120}
1121
1122static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1123{
1124 struct sd *sd = (struct sd *) gspca_dev;
1125
1126 getcontrast(gspca_dev);
1127 *val = sd->contrast;
1128 return 0;
1129}
1130
1131static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1132{
1133 struct sd *sd = (struct sd *) gspca_dev;
1134
1135 sd->colors = val;
1136 if (gspca_dev->streaming)
1137 setcolors(gspca_dev);
1138 return 0;
1139}
1140
1141static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1142{
1143 struct sd *sd = (struct sd *) gspca_dev;
1144
1145 getcolors(gspca_dev);
1146 *val = sd->colors;
1147 return 0;
1148}
1149
1150/* sub-driver description */
1151static struct sd_desc sd_desc = {
1152 .name = MODULE_NAME,
1153 .ctrls = sd_ctrls,
1154 .nctrls = ARRAY_SIZE(sd_ctrls),
1155 .config = sd_config,
1156 .open = sd_open,
1157 .start = sd_start,
1158 .stopN = sd_stopN,
1159 .stop0 = sd_stop0,
1160 .close = sd_close,
1161 .pkt_scan = sd_pkt_scan,
1162};
1163
1164/* -- module initialisation -- */
1165#define DVNM(name) .driver_info = (kernel_ulong_t) name
1166static const __devinitdata struct usb_device_id device_table[] = {
1167 {USB_DEVICE(0x040a, 0x0300), DVNM("Kodak EZ200")},
1168 {USB_DEVICE(0x041e, 0x400a), DVNM("Creative PC-CAM 300")},
1169 {USB_DEVICE(0x046d, 0x0890), DVNM("Logitech QuickCam traveler")},
1170 {USB_DEVICE(0x046d, 0x0900), DVNM("Logitech Inc. ClickSmart 310")},
1171 {USB_DEVICE(0x046d, 0x0901), DVNM("Logitech Inc. ClickSmart 510")},
1172 {USB_DEVICE(0x04a5, 0x300c), DVNM("Benq DC1016")},
1173 {USB_DEVICE(0x04fc, 0x7333), DVNM("PalmPixDC85")},
1174 {USB_DEVICE(0x055f, 0xc200), DVNM("Mustek Gsmart 300")},
1175 {USB_DEVICE(0x055f, 0xc220), DVNM("Gsmart Mini")},
1176 {USB_DEVICE(0x06bd, 0x0404), DVNM("Agfa CL20")},
1177 {USB_DEVICE(0x06be, 0x0800), DVNM("Optimedia")},
1178 {USB_DEVICE(0x084d, 0x0003), DVNM("D-Link DSC-350")},
1179 {USB_DEVICE(0x08ca, 0x0103), DVNM("Aiptek PocketDV")},
1180 {USB_DEVICE(0x2899, 0x012c), DVNM("Toptro Industrial")},
1181 {USB_DEVICE(0x8086, 0x0630), DVNM("Intel Pocket PC Camera")},
1182 {}
1183};
1184MODULE_DEVICE_TABLE(usb, device_table);
1185
1186/* -- device connect -- */
1187static int sd_probe(struct usb_interface *intf,
1188 const struct usb_device_id *id)
1189{
1190 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1191 THIS_MODULE);
1192}
1193
1194static struct usb_driver sd_driver = {
1195 .name = MODULE_NAME,
1196 .id_table = device_table,
1197 .probe = sd_probe,
1198 .disconnect = gspca_disconnect,
1199};
1200
1201/* -- module insert / remove -- */
1202static int __init sd_mod_init(void)
1203{
1204 if (usb_register(&sd_driver) < 0)
1205 return -1;
1206 PDEBUG(D_PROBE, "v%s registered", version);
1207 return 0;
1208}
1209static void __exit sd_mod_exit(void)
1210{
1211 usb_deregister(&sd_driver);
1212 PDEBUG(D_PROBE, "deregistered");
1213}
1214
1215module_init(sd_mod_init);
1216module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c
new file mode 100644
index 000000000000..50e929de0203
--- /dev/null
+++ b/drivers/media/video/gspca/spca501.c
@@ -0,0 +1,2229 @@
1/*
2 * SPCA501 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca501"
23
24#include "gspca.h"
25
26#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
27static const char version[] = "2.1.7";
28
29MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/SPCA501 USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
37 unsigned short contrast;
38 __u8 brightness;
39 __u8 colors;
40
41 char subtype;
42#define Arowana300KCMOSCamera 0
43#define IntelCreateAndShare 1
44#define KodakDVC325 2
45#define MystFromOriUnknownCamera 3
46#define SmileIntlCamera 4
47#define ThreeComHomeConnectLite 5
48#define ViewQuestM318B 6
49};
50
51/* V4L2 controls supported by the driver */
52static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
54static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
55static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
56static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
57static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
58
59static struct ctrl sd_ctrls[] = {
60#define MY_BRIGHTNESS 0
61 {
62 {
63 .id = V4L2_CID_BRIGHTNESS,
64 .type = V4L2_CTRL_TYPE_INTEGER,
65 .name = "Brightness",
66 .minimum = 0,
67 .maximum = 127,
68 .step = 1,
69 .default_value = 63,
70 },
71 .set = sd_setbrightness,
72 .get = sd_getbrightness,
73 },
74#define MY_CONTRAST 1
75 {
76 {
77 .id = V4L2_CID_CONTRAST,
78 .type = V4L2_CTRL_TYPE_INTEGER,
79 .name = "Contrast",
80 .minimum = 0,
81 .maximum = 0xffff,
82 .step = 1,
83 .default_value = 0xaa00,
84 },
85 .set = sd_setcontrast,
86 .get = sd_getcontrast,
87 },
88#define MY_COLOR 2
89 {
90 {
91 .id = V4L2_CID_SATURATION,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "Color",
94 .minimum = 0,
95 .maximum = 63,
96 .step = 1,
97 .default_value = 31,
98 },
99 .set = sd_setcolors,
100 .get = sd_getcolors,
101 },
102};
103
104static struct v4l2_pix_format vga_mode[] = {
105 {160, 120, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
106 .bytesperline = 160,
107 .sizeimage = 160 * 120 * 3 / 2,
108 .colorspace = V4L2_COLORSPACE_SRGB,
109 .priv = 2},
110 {320, 240, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
111 .bytesperline = 320,
112 .sizeimage = 320 * 240 * 3 / 2,
113 .colorspace = V4L2_COLORSPACE_SRGB,
114 .priv = 1},
115 {640, 480, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
116 .bytesperline = 640,
117 .sizeimage = 640 * 480 * 3 / 2,
118 .colorspace = V4L2_COLORSPACE_SRGB,
119 .priv = 0},
120};
121
122#define SPCA50X_REG_USB 0x2 /* spca505 501 */
123/*
124 * Data to initialize a SPCA501. From a capture file provided by Bill Roehl
125 * With SPCA501 chip description
126 */
127#define CCDSP_SET /* set CCDSP parameters */
128#define TG_SET /* set time generator set */
129#undef DSPWIN_SET /* set DSP windows parameters */
130#undef ALTER_GAMA /* Set alternate set to YUV transform coeffs. */
131#define SPCA501_SNAPBIT 0x80
132#define SPCA501_SNAPCTRL 0x10
133/* Frame packet header offsets for the spca501 */
134#define SPCA501_OFFSET_GPIO 1
135#define SPCA501_OFFSET_TYPE 2
136#define SPCA501_OFFSET_TURN3A 3
137#define SPCA501_OFFSET_FRAMSEQ 4
138#define SPCA501_OFFSET_COMPRESS 5
139#define SPCA501_OFFSET_QUANT 6
140#define SPCA501_OFFSET_QUANT2 7
141#define SPCA501_OFFSET_DATA 8
142
143#define SPCA501_PROP_COMP_ENABLE(d) ((d) & 1)
144#define SPCA501_PROP_SNAP(d) ((d) & 0x40)
145#define SPCA501_PROP_SNAP_CTRL(d) ((d) & 0x10)
146#define SPCA501_PROP_COMP_THRESH(d) (((d) & 0x0e) >> 1)
147#define SPCA501_PROP_COMP_QUANT(d) (((d) & 0x70) >> 4)
148
149/* SPCA501 CCDSP control */
150#define SPCA501_REG_CCDSP 0x01
151/* SPCA501 control/status registers */
152#define SPCA501_REG_CTLRL 0x02
153
154/* registers for color correction and YUV transformation */
155#define SPCA501_A11 0x08
156#define SPCA501_A12 0x09
157#define SPCA501_A13 0x0A
158#define SPCA501_A21 0x0B
159#define SPCA501_A22 0x0C
160#define SPCA501_A23 0x0D
161#define SPCA501_A31 0x0E
162#define SPCA501_A32 0x0F
163#define SPCA501_A33 0x10
164
165/* Data for video camera initialization before capturing */
166static const __u16 spca501_open_data[][3] = {
167 /* bmRequest,value,index */
168
169 {0x2, 0x50, 0x00}, /* C/S enable soft reset */
170 {0x2, 0x40, 0x00}, /* C/S disable soft reset */
171 {0x2, 0x02, 0x05}, /* C/S general purpose I/O data */
172 {0x2, 0x03, 0x05}, /* C/S general purpose I/O data */
173
174#ifdef CCDSP_SET
175 {0x1, 0x38, 0x01}, /* CCDSP options */
176 {0x1, 0x05, 0x02}, /* CCDSP Optical black level for user settings */
177 {0x1, 0xC0, 0x03}, /* CCDSP Optical black settings */
178
179 {0x1, 0x67, 0x07},
180 {0x1, 0x63, 0x3f}, /* CCDSP CCD gamma enable */
181 {0x1, 0x03, 0x56}, /* Add gamma correction */
182
183 {0x1, 0xFF, 0x15}, /* CCDSP High luminance for white balance */
184 {0x1, 0x01, 0x16}, /* CCDSP Low luminance for white balance */
185
186/* Color correction and RGB-to-YUV transformation coefficients changing */
187#ifdef ALTER_GAMA
188 {0x0, 0x00, 0x08}, /* A11 */
189 {0x0, 0x00, 0x09}, /* A12 */
190 {0x0, 0x90, 0x0A}, /* A13 */
191 {0x0, 0x12, 0x0B}, /* A21 */
192 {0x0, 0x00, 0x0C}, /* A22 */
193 {0x0, 0x00, 0x0D}, /* A23 */
194 {0x0, 0x00, 0x0E}, /* A31 */
195 {0x0, 0x02, 0x0F}, /* A32 */
196 {0x0, 0x00, 0x10}, /* A33 */
197#else
198 {0x1, 0x2a, 0x08}, /* A11 0x31 */
199 {0x1, 0xf8, 0x09}, /* A12 f8 */
200 {0x1, 0xf8, 0x0A}, /* A13 f8 */
201 {0x1, 0xf8, 0x0B}, /* A21 f8 */
202 {0x1, 0x14, 0x0C}, /* A22 0x14 */
203 {0x1, 0xf8, 0x0D}, /* A23 f8 */
204 {0x1, 0xf8, 0x0E}, /* A31 f8 */
205 {0x1, 0xf8, 0x0F}, /* A32 f8 */
206 {0x1, 0x20, 0x10}, /* A33 0x20 */
207#endif
208 {0x1, 0x00, 0x11}, /* R offset */
209 {0x1, 0x00, 0x12}, /* G offset */
210 {0x1, 0x00, 0x13}, /* B offset */
211 {0x1, 0x00, 0x14}, /* GB offset */
212
213#endif
214
215#ifdef TG_SET
216 /* Time generator manipulations */
217 {0x0, 0xfc, 0x0}, /* Set up high bits of shutter speed */
218 {0x0, 0x01, 0x1}, /* Set up low bits of shutter speed */
219
220 {0x0, 0xe4, 0x04}, /* DCLK*2 clock phase adjustment */
221 {0x0, 0x08, 0x05}, /* ADCK phase adjustment, inv. ext. VB */
222 {0x0, 0x03, 0x06}, /* FR phase adjustment */
223 {0x0, 0x01, 0x07}, /* FCDS phase adjustment */
224 {0x0, 0x39, 0x08}, /* FS phase adjustment */
225 {0x0, 0x88, 0x0a}, /* FH1 phase and delay adjustment */
226 {0x0, 0x03, 0x0f}, /* pixel identification */
227 {0x0, 0x00, 0x11}, /* clock source selection (default) */
228
229 /*VERY strange manipulations with
230 * select DMCLP or OBPX to be ADCLP output (0x0C)
231 * OPB always toggle or not (0x0D) but they allow
232 * us to set up brightness
233 */
234 {0x0, 0x01, 0x0c},
235 {0x0, 0xe0, 0x0d},
236 /* Done */
237#endif
238
239#ifdef DSPWIN_SET
240 {0x1, 0xa0, 0x01}, /* Setting image processing parameters */
241 {0x1, 0x1c, 0x17}, /* Changing Windows positions X1 */
242 {0x1, 0xe2, 0x19}, /* X2 */
243 {0x1, 0x1c, 0x1b}, /* X3 */
244 {0x1, 0xe2, 0x1d}, /* X4 */
245 {0x1, 0x5f, 0x1f}, /* X5 */
246 {0x1, 0x32, 0x20}, /* Y5 */
247 {0x1, 0x01, 0x10}, /* Changing A33 */
248#endif
249
250 {0x2, 0x204a, 0x07},/* Setting video compression & resolution 160x120 */
251 {0x2, 0x94, 0x06}, /* Setting video no compression */
252 {}
253};
254
255/*
256 The SPCAxxx docs from Sunplus document these values
257 in tables, one table per register number. In the data
258 below, dmRequest is the register number, index is the Addr,
259 and value is a combination of Bit values.
260 Bit Value (hex)
261 0 01
262 1 02
263 2 04
264 3 08
265 4 10
266 5 20
267 6 40
268 7 80
269 */
270
271/* Data for chip initialization (set default values) */
272static const __u16 spca501_init_data[][3] = {
273 /* Set all the values to powerup defaults */
274 /* bmRequest,value,index */
275 {0x0, 0xAA, 0x00},
276 {0x0, 0x02, 0x01},
277 {0x0, 0x01, 0x02},
278 {0x0, 0x02, 0x03},
279 {0x0, 0xCE, 0x04},
280 {0x0, 0x00, 0x05},
281 {0x0, 0x00, 0x06},
282 {0x0, 0x00, 0x07},
283 {0x0, 0x00, 0x08},
284 {0x0, 0x00, 0x09},
285 {0x0, 0x90, 0x0A},
286 {0x0, 0x12, 0x0B},
287 {0x0, 0x00, 0x0C},
288 {0x0, 0x00, 0x0D},
289 {0x0, 0x00, 0x0E},
290 {0x0, 0x02, 0x0F},
291 {0x0, 0x00, 0x10},
292 {0x0, 0x00, 0x11},
293 {0x0, 0x00, 0x12},
294 {0x0, 0x00, 0x13},
295 {0x0, 0x00, 0x14},
296 {0x0, 0x00, 0x15},
297 {0x0, 0x00, 0x16},
298 {0x0, 0x00, 0x17},
299 {0x0, 0x00, 0x18},
300 {0x0, 0x00, 0x19},
301 {0x0, 0x00, 0x1A},
302 {0x0, 0x00, 0x1B},
303 {0x0, 0x00, 0x1C},
304 {0x0, 0x00, 0x1D},
305 {0x0, 0x00, 0x1E},
306 {0x0, 0x00, 0x1F},
307 {0x0, 0x00, 0x20},
308 {0x0, 0x00, 0x21},
309 {0x0, 0x00, 0x22},
310 {0x0, 0x00, 0x23},
311 {0x0, 0x00, 0x24},
312 {0x0, 0x00, 0x25},
313 {0x0, 0x00, 0x26},
314 {0x0, 0x00, 0x27},
315 {0x0, 0x00, 0x28},
316 {0x0, 0x00, 0x29},
317 {0x0, 0x00, 0x2A},
318 {0x0, 0x00, 0x2B},
319 {0x0, 0x00, 0x2C},
320 {0x0, 0x00, 0x2D},
321 {0x0, 0x00, 0x2E},
322 {0x0, 0x00, 0x2F},
323 {0x0, 0x00, 0x30},
324 {0x0, 0x00, 0x31},
325 {0x0, 0x00, 0x32},
326 {0x0, 0x00, 0x33},
327 {0x0, 0x00, 0x34},
328 {0x0, 0x00, 0x35},
329 {0x0, 0x00, 0x36},
330 {0x0, 0x00, 0x37},
331 {0x0, 0x00, 0x38},
332 {0x0, 0x00, 0x39},
333 {0x0, 0x00, 0x3A},
334 {0x0, 0x00, 0x3B},
335 {0x0, 0x00, 0x3C},
336 {0x0, 0x00, 0x3D},
337 {0x0, 0x00, 0x3E},
338 {0x0, 0x00, 0x3F},
339 {0x0, 0x00, 0x40},
340 {0x0, 0x00, 0x41},
341 {0x0, 0x00, 0x42},
342 {0x0, 0x00, 0x43},
343 {0x0, 0x00, 0x44},
344 {0x0, 0x00, 0x45},
345 {0x0, 0x00, 0x46},
346 {0x0, 0x00, 0x47},
347 {0x0, 0x00, 0x48},
348 {0x0, 0x00, 0x49},
349 {0x0, 0x00, 0x4A},
350 {0x0, 0x00, 0x4B},
351 {0x0, 0x00, 0x4C},
352 {0x0, 0x00, 0x4D},
353 {0x0, 0x00, 0x4E},
354 {0x0, 0x00, 0x4F},
355 {0x0, 0x00, 0x50},
356 {0x0, 0x00, 0x51},
357 {0x0, 0x00, 0x52},
358 {0x0, 0x00, 0x53},
359 {0x0, 0x00, 0x54},
360 {0x0, 0x00, 0x55},
361 {0x0, 0x00, 0x56},
362 {0x0, 0x00, 0x57},
363 {0x0, 0x00, 0x58},
364 {0x0, 0x00, 0x59},
365 {0x0, 0x00, 0x5A},
366 {0x0, 0x00, 0x5B},
367 {0x0, 0x00, 0x5C},
368 {0x0, 0x00, 0x5D},
369 {0x0, 0x00, 0x5E},
370 {0x0, 0x00, 0x5F},
371 {0x0, 0x00, 0x60},
372 {0x0, 0x00, 0x61},
373 {0x0, 0x00, 0x62},
374 {0x0, 0x00, 0x63},
375 {0x0, 0x00, 0x64},
376 {0x0, 0x00, 0x65},
377 {0x0, 0x00, 0x66},
378 {0x0, 0x00, 0x67},
379 {0x0, 0x00, 0x68},
380 {0x0, 0x00, 0x69},
381 {0x0, 0x00, 0x6A},
382 {0x0, 0x00, 0x6B},
383 {0x0, 0x00, 0x6C},
384 {0x0, 0x00, 0x6D},
385 {0x0, 0x00, 0x6E},
386 {0x0, 0x00, 0x6F},
387 {0x0, 0x00, 0x70},
388 {0x0, 0x00, 0x71},
389 {0x0, 0x00, 0x72},
390 {0x0, 0x00, 0x73},
391 {0x0, 0x00, 0x74},
392 {0x0, 0x00, 0x75},
393 {0x0, 0x00, 0x76},
394 {0x0, 0x00, 0x77},
395 {0x0, 0x00, 0x78},
396 {0x0, 0x00, 0x79},
397 {0x0, 0x00, 0x7A},
398 {0x0, 0x00, 0x7B},
399 {0x0, 0x00, 0x7C},
400 {0x0, 0x00, 0x7D},
401 {0x0, 0x00, 0x7E},
402 {0x0, 0x00, 0x7F},
403 {0x0, 0x00, 0x80},
404 {0x0, 0x00, 0x81},
405 {0x0, 0x00, 0x82},
406 {0x0, 0x00, 0x83},
407 {0x0, 0x00, 0x84},
408 {0x0, 0x00, 0x85},
409 {0x0, 0x00, 0x86},
410 {0x0, 0x00, 0x87},
411 {0x0, 0x00, 0x88},
412 {0x0, 0x00, 0x89},
413 {0x0, 0x00, 0x8A},
414 {0x0, 0x00, 0x8B},
415 {0x0, 0x00, 0x8C},
416 {0x0, 0x00, 0x8D},
417 {0x0, 0x00, 0x8E},
418 {0x0, 0x00, 0x8F},
419 {0x0, 0x00, 0x90},
420 {0x0, 0x00, 0x91},
421 {0x0, 0x00, 0x92},
422 {0x0, 0x00, 0x93},
423 {0x0, 0x00, 0x94},
424 {0x0, 0x00, 0x95},
425 {0x0, 0x00, 0x96},
426 {0x0, 0x00, 0x97},
427 {0x0, 0x00, 0x98},
428 {0x0, 0x00, 0x99},
429 {0x0, 0x00, 0x9A},
430 {0x0, 0x00, 0x9B},
431 {0x0, 0x00, 0x9C},
432 {0x0, 0x00, 0x9D},
433 {0x0, 0x00, 0x9E},
434 {0x0, 0x00, 0x9F},
435 {0x0, 0x00, 0xA0},
436 {0x0, 0x00, 0xA1},
437 {0x0, 0x00, 0xA2},
438 {0x0, 0x00, 0xA3},
439 {0x0, 0x00, 0xA4},
440 {0x0, 0x00, 0xA5},
441 {0x0, 0x00, 0xA6},
442 {0x0, 0x00, 0xA7},
443 {0x0, 0x00, 0xA8},
444 {0x0, 0x00, 0xA9},
445 {0x0, 0x00, 0xAA},
446 {0x0, 0x00, 0xAB},
447 {0x0, 0x00, 0xAC},
448 {0x0, 0x00, 0xAD},
449 {0x0, 0x00, 0xAE},
450 {0x0, 0x00, 0xAF},
451 {0x0, 0x00, 0xB0},
452 {0x0, 0x00, 0xB1},
453 {0x0, 0x00, 0xB2},
454 {0x0, 0x00, 0xB3},
455 {0x0, 0x00, 0xB4},
456 {0x0, 0x00, 0xB5},
457 {0x0, 0x00, 0xB6},
458 {0x0, 0x00, 0xB7},
459 {0x0, 0x00, 0xB8},
460 {0x0, 0x00, 0xB9},
461 {0x0, 0x00, 0xBA},
462 {0x0, 0x00, 0xBB},
463 {0x0, 0x00, 0xBC},
464 {0x0, 0x00, 0xBD},
465 {0x0, 0x00, 0xBE},
466 {0x0, 0x00, 0xBF},
467 {0x0, 0x00, 0xC0},
468 {0x0, 0x00, 0xC1},
469 {0x0, 0x00, 0xC2},
470 {0x0, 0x00, 0xC3},
471 {0x0, 0x00, 0xC4},
472 {0x0, 0x00, 0xC5},
473 {0x0, 0x00, 0xC6},
474 {0x0, 0x00, 0xC7},
475 {0x0, 0x00, 0xC8},
476 {0x0, 0x00, 0xC9},
477 {0x0, 0x00, 0xCA},
478 {0x0, 0x00, 0xCB},
479 {0x0, 0x00, 0xCC},
480 {0x1, 0xF4, 0x00},
481 {0x1, 0x38, 0x01},
482 {0x1, 0x40, 0x02},
483 {0x1, 0x0A, 0x03},
484 {0x1, 0x40, 0x04},
485 {0x1, 0x40, 0x05},
486 {0x1, 0x40, 0x06},
487 {0x1, 0x67, 0x07},
488 {0x1, 0x31, 0x08},
489 {0x1, 0x00, 0x09},
490 {0x1, 0x00, 0x0A},
491 {0x1, 0x00, 0x0B},
492 {0x1, 0x14, 0x0C},
493 {0x1, 0x00, 0x0D},
494 {0x1, 0x00, 0x0E},
495 {0x1, 0x00, 0x0F},
496 {0x1, 0x1E, 0x10},
497 {0x1, 0x00, 0x11},
498 {0x1, 0x00, 0x12},
499 {0x1, 0x00, 0x13},
500 {0x1, 0x00, 0x14},
501 {0x1, 0xFF, 0x15},
502 {0x1, 0x01, 0x16},
503 {0x1, 0x32, 0x17},
504 {0x1, 0x23, 0x18},
505 {0x1, 0xCE, 0x19},
506 {0x1, 0x23, 0x1A},
507 {0x1, 0x32, 0x1B},
508 {0x1, 0x8D, 0x1C},
509 {0x1, 0xCE, 0x1D},
510 {0x1, 0x8D, 0x1E},
511 {0x1, 0x00, 0x1F},
512 {0x1, 0x00, 0x20},
513 {0x1, 0xFF, 0x3E},
514 {0x1, 0x02, 0x3F},
515 {0x1, 0x00, 0x40},
516 {0x1, 0x00, 0x41},
517 {0x1, 0x00, 0x42},
518 {0x1, 0x00, 0x43},
519 {0x1, 0x00, 0x44},
520 {0x1, 0x00, 0x45},
521 {0x1, 0x00, 0x46},
522 {0x1, 0x00, 0x47},
523 {0x1, 0x00, 0x48},
524 {0x1, 0x00, 0x49},
525 {0x1, 0x00, 0x4A},
526 {0x1, 0x00, 0x4B},
527 {0x1, 0x00, 0x4C},
528 {0x1, 0x00, 0x4D},
529 {0x1, 0x00, 0x4E},
530 {0x1, 0x00, 0x4F},
531 {0x1, 0x00, 0x50},
532 {0x1, 0x00, 0x51},
533 {0x1, 0x00, 0x52},
534 {0x1, 0x00, 0x53},
535 {0x1, 0x00, 0x54},
536 {0x1, 0x00, 0x55},
537 {0x1, 0x00, 0x56},
538 {0x1, 0x00, 0x57},
539 {0x1, 0x00, 0x58},
540 {0x1, 0x00, 0x59},
541 {0x1, 0x00, 0x5A},
542 {0x2, 0x03, 0x00},
543 {0x2, 0x00, 0x01},
544 {0x2, 0x00, 0x05},
545 {0x2, 0x00, 0x06},
546 {0x2, 0x00, 0x07},
547 {0x2, 0x00, 0x10},
548 {0x2, 0x00, 0x11},
549 /* Strange - looks like the 501 driver doesn't do anything
550 * at insert time except read the EEPROM
551 */
552 {}
553};
554
555/* Data for video camera init before capture.
556 * Capture and decoding by Colin Peart.
557 * This is is for the 3com HomeConnect Lite which is spca501a based.
558 */
559static const __u16 spca501_3com_open_data[][3] = {
560 /* bmRequest,value,index */
561 {0x2, 0x0050, 0x0000}, /* C/S Enable TG soft reset, timing mode=010 */
562 {0x2, 0x0043, 0x0000}, /* C/S Disable TG soft reset, timing mode=010 */
563 {0x2, 0x0002, 0x0005}, /* C/S GPIO */
564 {0x2, 0x0003, 0x0005}, /* C/S GPIO */
565
566#ifdef CCDSP_SET
567 {0x1, 0x0020, 0x0001}, /* CCDSP Options */
568
569 {0x1, 0x0020, 0x0002}, /* CCDSP Black Level */
570 {0x1, 0x006e, 0x0007}, /* CCDSP Gamma options */
571 {0x1, 0x0090, 0x0015}, /* CCDSP Luminance Low */
572 {0x1, 0x00ff, 0x0016}, /* CCDSP Luminance High */
573 {0x1, 0x0003, 0x003F}, /* CCDSP Gamma correction toggle */
574
575#ifdef ALTER_GAMMA
576 {0x1, 0x0010, 0x0008}, /* CCDSP YUV A11 */
577 {0x1, 0x0000, 0x0009}, /* CCDSP YUV A12 */
578 {0x1, 0x0000, 0x000a}, /* CCDSP YUV A13 */
579 {0x1, 0x0000, 0x000b}, /* CCDSP YUV A21 */
580 {0x1, 0x0010, 0x000c}, /* CCDSP YUV A22 */
581 {0x1, 0x0000, 0x000d}, /* CCDSP YUV A23 */
582 {0x1, 0x0000, 0x000e}, /* CCDSP YUV A31 */
583 {0x1, 0x0000, 0x000f}, /* CCDSP YUV A32 */
584 {0x1, 0x0010, 0x0010}, /* CCDSP YUV A33 */
585 {0x1, 0x0000, 0x0011}, /* CCDSP R Offset */
586 {0x1, 0x0000, 0x0012}, /* CCDSP G Offset */
587 {0x1, 0x0001, 0x0013}, /* CCDSP B Offset */
588 {0x1, 0x0001, 0x0014}, /* CCDSP BG Offset */
589 {0x1, 0x003f, 0x00C1}, /* CCDSP Gamma Correction Enable */
590#endif
591#endif
592
593#ifdef TG_SET
594 {0x0, 0x00fc, 0x0000}, /* TG Shutter Speed High Bits */
595 {0x0, 0x0000, 0x0001}, /* TG Shutter Speed Low Bits */
596 {0x0, 0x00e4, 0x0004}, /* TG DCLK*2 Adjust */
597 {0x0, 0x0008, 0x0005}, /* TG ADCK Adjust */
598 {0x0, 0x0003, 0x0006}, /* TG FR Phase Adjust */
599 {0x0, 0x0001, 0x0007}, /* TG FCDS Phase Adjust */
600 {0x0, 0x0039, 0x0008}, /* TG FS Phase Adjust */
601 {0x0, 0x0088, 0x000a}, /* TG MH1 */
602 {0x0, 0x0003, 0x000f}, /* TG Pixel ID */
603
604 /* Like below, unexplained toglleing */
605 {0x0, 0x0080, 0x000c},
606 {0x0, 0x0000, 0x000d},
607 {0x0, 0x0080, 0x000c},
608 {0x0, 0x0004, 0x000d},
609 {0x0, 0x0000, 0x000c},
610 {0x0, 0x0000, 0x000d},
611 {0x0, 0x0040, 0x000c},
612 {0x0, 0x0017, 0x000d},
613 {0x0, 0x00c0, 0x000c},
614 {0x0, 0x0000, 0x000d},
615 {0x0, 0x0080, 0x000c},
616 {0x0, 0x0006, 0x000d},
617 {0x0, 0x0080, 0x000c},
618 {0x0, 0x0004, 0x000d},
619 {0x0, 0x0002, 0x0003},
620#endif
621
622#ifdef DSPWIN_SET
623 {0x1, 0x001c, 0x0017}, /* CCDSP W1 Start X */
624 {0x1, 0x00e2, 0x0019}, /* CCDSP W2 Start X */
625 {0x1, 0x001c, 0x001b}, /* CCDSP W3 Start X */
626 {0x1, 0x00e2, 0x001d}, /* CCDSP W4 Start X */
627 {0x1, 0x00aa, 0x001f}, /* CCDSP W5 Start X */
628 {0x1, 0x0070, 0x0020}, /* CCDSP W5 Start Y */
629#endif
630 {0x0, 0x0001, 0x0010}, /* TG Start Clock */
631
632/* {0x2, 0x006a, 0x0001}, * C/S Enable ISOSYNCH Packet Engine */
633 {0x2, 0x0068, 0x0001}, /* C/S Diable ISOSYNCH Packet Engine */
634 {0x2, 0x0000, 0x0005},
635 {0x2, 0x0043, 0x0000}, /* C/S Set Timing Mode, Disable TG soft reset */
636 {0x2, 0x0043, 0x0000}, /* C/S Set Timing Mode, Disable TG soft reset */
637 {0x2, 0x0002, 0x0005}, /* C/S GPIO */
638 {0x2, 0x0003, 0x0005}, /* C/S GPIO */
639
640 {0x2, 0x006a, 0x0001}, /* C/S Enable ISOSYNCH Packet Engine */
641 {}
642};
643
644/*
645 * Data used to initialize a SPCA501C with HV7131B sensor.
646 * From a capture file taken with USBSnoop v 1.5
647 * I have a "SPCA501C pc camera chipset" manual by sunplus, but some
648 * of the value meanings are obscure or simply "reserved".
649 * to do list:
650 * 1) Understand what every value means
651 * 2) Understand why some values seem to appear more than once
652 * 3) Write a small comment for each line of the following arrays.
653 */
654static const __u16 spca501c_arowana_open_data[][3] = {
655 /* bmRequest,value,index */
656 {0x02, 0x0007, 0x0005},
657 {0x02, 0xa048, 0x0000},
658 {0x05, 0x0022, 0x0004},
659 {0x01, 0x0006, 0x0011},
660 {0x01, 0x00ff, 0x0012},
661 {0x01, 0x0014, 0x0013},
662 {0x01, 0x0000, 0x0014},
663 {0x01, 0x0042, 0x0051},
664 {0x01, 0x0040, 0x0052},
665 {0x01, 0x0051, 0x0053},
666 {0x01, 0x0040, 0x0054},
667 {0x01, 0x0000, 0x0055},
668 {0x00, 0x0025, 0x0000},
669 {0x00, 0x0026, 0x0000},
670 {0x00, 0x0001, 0x0000},
671 {0x00, 0x0027, 0x0000},
672 {0x00, 0x008a, 0x0000},
673 {}
674};
675
676static const __u16 spca501c_arowana_init_data[][3] = {
677 /* bmRequest,value,index */
678 {0x02, 0x0007, 0x0005},
679 {0x02, 0xa048, 0x0000},
680 {0x05, 0x0022, 0x0004},
681 {0x01, 0x0006, 0x0011},
682 {0x01, 0x00ff, 0x0012},
683 {0x01, 0x0014, 0x0013},
684 {0x01, 0x0000, 0x0014},
685 {0x01, 0x0042, 0x0051},
686 {0x01, 0x0040, 0x0052},
687 {0x01, 0x0051, 0x0053},
688 {0x01, 0x0040, 0x0054},
689 {0x01, 0x0000, 0x0055},
690 {0x00, 0x0025, 0x0000},
691 {0x00, 0x0026, 0x0000},
692 {0x00, 0x0001, 0x0000},
693 {0x00, 0x0027, 0x0000},
694 {0x00, 0x008a, 0x0000},
695 {0x02, 0x0000, 0x0005},
696 {0x02, 0x0007, 0x0005},
697 {0x02, 0x2000, 0x0000},
698 {0x05, 0x0022, 0x0004},
699 {0x05, 0x0015, 0x0001},
700 {0x05, 0x00ea, 0x0000},
701 {0x05, 0x0021, 0x0001},
702 {0x05, 0x00d2, 0x0000},
703 {0x05, 0x0023, 0x0001},
704 {0x05, 0x0003, 0x0000},
705 {0x05, 0x0030, 0x0001},
706 {0x05, 0x002b, 0x0000},
707 {0x05, 0x0031, 0x0001},
708 {0x05, 0x0023, 0x0000},
709 {0x05, 0x0032, 0x0001},
710 {0x05, 0x0023, 0x0000},
711 {0x05, 0x0033, 0x0001},
712 {0x05, 0x0023, 0x0000},
713 {0x05, 0x0034, 0x0001},
714 {0x05, 0x0002, 0x0000},
715 {0x05, 0x0050, 0x0001},
716 {0x05, 0x0000, 0x0000},
717 {0x05, 0x0051, 0x0001},
718 {0x05, 0x0000, 0x0000},
719 {0x05, 0x0052, 0x0001},
720 {0x05, 0x0000, 0x0000},
721 {0x05, 0x0054, 0x0001},
722 {0x05, 0x0001, 0x0000},
723 {0x00, 0x0000, 0x0001},
724 {0x00, 0x0000, 0x0002},
725 {0x00, 0x000c, 0x0003},
726 {0x00, 0x0000, 0x0004},
727 {0x00, 0x0090, 0x0005},
728 {0x00, 0x0000, 0x0006},
729 {0x00, 0x0040, 0x0007},
730 {0x00, 0x00c0, 0x0008},
731 {0x00, 0x004a, 0x0009},
732 {0x00, 0x0000, 0x000a},
733 {0x00, 0x0000, 0x000b},
734 {0x00, 0x0001, 0x000c},
735 {0x00, 0x0001, 0x000d},
736 {0x00, 0x0000, 0x000e},
737 {0x00, 0x0002, 0x000f},
738 {0x00, 0x0001, 0x0010},
739 {0x00, 0x0000, 0x0011},
740 {0x00, 0x0000, 0x0012},
741 {0x00, 0x0002, 0x0020},
742 {0x00, 0x0080, 0x0021},
743 {0x00, 0x0001, 0x0022},
744 {0x00, 0x00e0, 0x0023},
745 {0x00, 0x0000, 0x0024},
746 {0x00, 0x00d5, 0x0025},
747 {0x00, 0x0000, 0x0026},
748 {0x00, 0x000b, 0x0027},
749 {0x00, 0x0000, 0x0046},
750 {0x00, 0x0000, 0x0047},
751 {0x00, 0x0000, 0x0048},
752 {0x00, 0x0000, 0x0049},
753 {0x00, 0x0008, 0x004a},
754 {0xff, 0x0000, 0x00d0},
755 {0xff, 0x00d8, 0x00d1},
756 {0xff, 0x0000, 0x00d4},
757 {0xff, 0x0000, 0x00d5},
758 {0x01, 0x00a6, 0x0000},
759 {0x01, 0x0028, 0x0001},
760 {0x01, 0x0000, 0x0002},
761 {0x01, 0x000a, 0x0003},
762 {0x01, 0x0040, 0x0004},
763 {0x01, 0x0066, 0x0007},
764 {0x01, 0x0011, 0x0008},
765 {0x01, 0x0032, 0x0009},
766 {0x01, 0x00fd, 0x000a},
767 {0x01, 0x0038, 0x000b},
768 {0x01, 0x00d1, 0x000c},
769 {0x01, 0x00f7, 0x000d},
770 {0x01, 0x00ed, 0x000e},
771 {0x01, 0x00d8, 0x000f},
772 {0x01, 0x0038, 0x0010},
773 {0x01, 0x00ff, 0x0015},
774 {0x01, 0x0001, 0x0016},
775 {0x01, 0x0032, 0x0017},
776 {0x01, 0x0023, 0x0018},
777 {0x01, 0x00ce, 0x0019},
778 {0x01, 0x0023, 0x001a},
779 {0x01, 0x0032, 0x001b},
780 {0x01, 0x008d, 0x001c},
781 {0x01, 0x00ce, 0x001d},
782 {0x01, 0x008d, 0x001e},
783 {0x01, 0x0000, 0x001f},
784 {0x01, 0x0000, 0x0020},
785 {0x01, 0x00ff, 0x003e},
786 {0x01, 0x0003, 0x003f},
787 {0x01, 0x0000, 0x0040},
788 {0x01, 0x0035, 0x0041},
789 {0x01, 0x0053, 0x0042},
790 {0x01, 0x0069, 0x0043},
791 {0x01, 0x007c, 0x0044},
792 {0x01, 0x008c, 0x0045},
793 {0x01, 0x009a, 0x0046},
794 {0x01, 0x00a8, 0x0047},
795 {0x01, 0x00b4, 0x0048},
796 {0x01, 0x00bf, 0x0049},
797 {0x01, 0x00ca, 0x004a},
798 {0x01, 0x00d4, 0x004b},
799 {0x01, 0x00dd, 0x004c},
800 {0x01, 0x00e7, 0x004d},
801 {0x01, 0x00ef, 0x004e},
802 {0x01, 0x00f8, 0x004f},
803 {0x01, 0x00ff, 0x0050},
804 {0x01, 0x0001, 0x0056},
805 {0x01, 0x0060, 0x0057},
806 {0x01, 0x0040, 0x0058},
807 {0x01, 0x0011, 0x0059},
808 {0x01, 0x0001, 0x005a},
809 {0x02, 0x0007, 0x0005},
810 {0x02, 0xa048, 0x0000},
811 {0x02, 0x0007, 0x0005},
812 {0x02, 0x0015, 0x0006},
813 {0x02, 0x100a, 0x0007},
814 {0x02, 0xa048, 0x0000},
815 {0x02, 0xc002, 0x0001},
816 {0x02, 0x000f, 0x0005},
817 {0x02, 0xa048, 0x0000},
818 {0x05, 0x0022, 0x0004},
819 {0x05, 0x0025, 0x0001},
820 {0x05, 0x0000, 0x0000},
821 {0x05, 0x0026, 0x0001},
822 {0x05, 0x0001, 0x0000},
823 {0x05, 0x0027, 0x0001},
824 {0x05, 0x0000, 0x0000},
825 {0x05, 0x0001, 0x0001},
826 {0x05, 0x0000, 0x0000},
827 {0x05, 0x0021, 0x0001},
828 {0x05, 0x00d2, 0x0000},
829 {0x05, 0x0020, 0x0001},
830 {0x05, 0x0000, 0x0000},
831 {0x00, 0x0090, 0x0005},
832 {0x01, 0x00a6, 0x0000},
833 {0x02, 0x0007, 0x0005},
834 {0x02, 0x2000, 0x0000},
835 {0x05, 0x0022, 0x0004},
836 {0x05, 0x0015, 0x0001},
837 {0x05, 0x00ea, 0x0000},
838 {0x05, 0x0021, 0x0001},
839 {0x05, 0x00d2, 0x0000},
840 {0x05, 0x0023, 0x0001},
841 {0x05, 0x0003, 0x0000},
842 {0x05, 0x0030, 0x0001},
843 {0x05, 0x002b, 0x0000},
844 {0x05, 0x0031, 0x0001},
845 {0x05, 0x0023, 0x0000},
846 {0x05, 0x0032, 0x0001},
847 {0x05, 0x0023, 0x0000},
848 {0x05, 0x0033, 0x0001},
849 {0x05, 0x0023, 0x0000},
850 {0x05, 0x0034, 0x0001},
851 {0x05, 0x0002, 0x0000},
852 {0x05, 0x0050, 0x0001},
853 {0x05, 0x0000, 0x0000},
854 {0x05, 0x0051, 0x0001},
855 {0x05, 0x0000, 0x0000},
856 {0x05, 0x0052, 0x0001},
857 {0x05, 0x0000, 0x0000},
858 {0x05, 0x0054, 0x0001},
859 {0x05, 0x0001, 0x0000},
860 {0x00, 0x0000, 0x0001},
861 {0x00, 0x0000, 0x0002},
862 {0x00, 0x000c, 0x0003},
863 {0x00, 0x0000, 0x0004},
864 {0x00, 0x0090, 0x0005},
865 {0x00, 0x0000, 0x0006},
866 {0x00, 0x0040, 0x0007},
867 {0x00, 0x00c0, 0x0008},
868 {0x00, 0x004a, 0x0009},
869 {0x00, 0x0000, 0x000a},
870 {0x00, 0x0000, 0x000b},
871 {0x00, 0x0001, 0x000c},
872 {0x00, 0x0001, 0x000d},
873 {0x00, 0x0000, 0x000e},
874 {0x00, 0x0002, 0x000f},
875 {0x00, 0x0001, 0x0010},
876 {0x00, 0x0000, 0x0011},
877 {0x00, 0x0000, 0x0012},
878 {0x00, 0x0002, 0x0020},
879 {0x00, 0x0080, 0x0021},
880 {0x00, 0x0001, 0x0022},
881 {0x00, 0x00e0, 0x0023},
882 {0x00, 0x0000, 0x0024},
883 {0x00, 0x00d5, 0x0025},
884 {0x00, 0x0000, 0x0026},
885 {0x00, 0x000b, 0x0027},
886 {0x00, 0x0000, 0x0046},
887 {0x00, 0x0000, 0x0047},
888 {0x00, 0x0000, 0x0048},
889 {0x00, 0x0000, 0x0049},
890 {0x00, 0x0008, 0x004a},
891 {0xff, 0x0000, 0x00d0},
892 {0xff, 0x00d8, 0x00d1},
893 {0xff, 0x0000, 0x00d4},
894 {0xff, 0x0000, 0x00d5},
895 {0x01, 0x00a6, 0x0000},
896 {0x01, 0x0028, 0x0001},
897 {0x01, 0x0000, 0x0002},
898 {0x01, 0x000a, 0x0003},
899 {0x01, 0x0040, 0x0004},
900 {0x01, 0x0066, 0x0007},
901 {0x01, 0x0011, 0x0008},
902 {0x01, 0x0032, 0x0009},
903 {0x01, 0x00fd, 0x000a},
904 {0x01, 0x0038, 0x000b},
905 {0x01, 0x00d1, 0x000c},
906 {0x01, 0x00f7, 0x000d},
907 {0x01, 0x00ed, 0x000e},
908 {0x01, 0x00d8, 0x000f},
909 {0x01, 0x0038, 0x0010},
910 {0x01, 0x00ff, 0x0015},
911 {0x01, 0x0001, 0x0016},
912 {0x01, 0x0032, 0x0017},
913 {0x01, 0x0023, 0x0018},
914 {0x01, 0x00ce, 0x0019},
915 {0x01, 0x0023, 0x001a},
916 {0x01, 0x0032, 0x001b},
917 {0x01, 0x008d, 0x001c},
918 {0x01, 0x00ce, 0x001d},
919 {0x01, 0x008d, 0x001e},
920 {0x01, 0x0000, 0x001f},
921 {0x01, 0x0000, 0x0020},
922 {0x01, 0x00ff, 0x003e},
923 {0x01, 0x0003, 0x003f},
924 {0x01, 0x0000, 0x0040},
925 {0x01, 0x0035, 0x0041},
926 {0x01, 0x0053, 0x0042},
927 {0x01, 0x0069, 0x0043},
928 {0x01, 0x007c, 0x0044},
929 {0x01, 0x008c, 0x0045},
930 {0x01, 0x009a, 0x0046},
931 {0x01, 0x00a8, 0x0047},
932 {0x01, 0x00b4, 0x0048},
933 {0x01, 0x00bf, 0x0049},
934 {0x01, 0x00ca, 0x004a},
935 {0x01, 0x00d4, 0x004b},
936 {0x01, 0x00dd, 0x004c},
937 {0x01, 0x00e7, 0x004d},
938 {0x01, 0x00ef, 0x004e},
939 {0x01, 0x00f8, 0x004f},
940 {0x01, 0x00ff, 0x0050},
941 {0x01, 0x0001, 0x0056},
942 {0x01, 0x0060, 0x0057},
943 {0x01, 0x0040, 0x0058},
944 {0x01, 0x0011, 0x0059},
945 {0x01, 0x0001, 0x005a},
946 {0x02, 0x0007, 0x0005},
947 {0x02, 0xa048, 0x0000},
948 {0x02, 0x0007, 0x0005},
949 {0x02, 0x0015, 0x0006},
950 {0x02, 0x100a, 0x0007},
951 {0x02, 0xa048, 0x0000},
952 {0x02, 0xc002, 0x0001},
953 {0x02, 0x000f, 0x0005},
954 {0x02, 0xa048, 0x0000},
955 {0x05, 0x0022, 0x0004},
956 {0x05, 0x0025, 0x0001},
957 {0x05, 0x0000, 0x0000},
958 {0x05, 0x0026, 0x0001},
959 {0x05, 0x0001, 0x0000},
960 {0x05, 0x0027, 0x0001},
961 {0x05, 0x0000, 0x0000},
962 {0x05, 0x0001, 0x0001},
963 {0x05, 0x0000, 0x0000},
964 {0x05, 0x0021, 0x0001},
965 {0x05, 0x00d2, 0x0000},
966 {0x05, 0x0020, 0x0001},
967 {0x05, 0x0000, 0x0000},
968 {0x00, 0x0090, 0x0005},
969 {0x01, 0x00a6, 0x0000},
970 {0x01, 0x0003, 0x003f},
971 {0x01, 0x0001, 0x0056},
972 {0x01, 0x0011, 0x0008},
973 {0x01, 0x0032, 0x0009},
974 {0x01, 0xfffd, 0x000a},
975 {0x01, 0x0023, 0x000b},
976 {0x01, 0xffea, 0x000c},
977 {0x01, 0xfff4, 0x000d},
978 {0x01, 0xfffc, 0x000e},
979 {0x01, 0xffe3, 0x000f},
980 {0x01, 0x001f, 0x0010},
981 {0x01, 0x00a8, 0x0001},
982 {0x01, 0x0067, 0x0007},
983 {0x01, 0x0032, 0x0017},
984 {0x01, 0x0023, 0x0018},
985 {0x01, 0x00ce, 0x0019},
986 {0x01, 0x0023, 0x001a},
987 {0x01, 0x0032, 0x001b},
988 {0x01, 0x008d, 0x001c},
989 {0x01, 0x00ce, 0x001d},
990 {0x01, 0x008d, 0x001e},
991 {0x01, 0x00c8, 0x0015},
992 {0x01, 0x0032, 0x0016},
993 {0x01, 0x0000, 0x0011},
994 {0x01, 0x0000, 0x0012},
995 {0x01, 0x0000, 0x0013},
996 {0x01, 0x000a, 0x0003},
997 {0x02, 0xc002, 0x0001},
998 {0x02, 0x0007, 0x0005},
999 {0x02, 0xc000, 0x0001},
1000 {0x02, 0x0000, 0x0005},
1001 {0x02, 0x0007, 0x0005},
1002 {0x02, 0x2000, 0x0000},
1003 {0x05, 0x0022, 0x0004},
1004 {0x05, 0x0015, 0x0001},
1005 {0x05, 0x00ea, 0x0000},
1006 {0x05, 0x0021, 0x0001},
1007 {0x05, 0x00d2, 0x0000},
1008 {0x05, 0x0023, 0x0001},
1009 {0x05, 0x0003, 0x0000},
1010 {0x05, 0x0030, 0x0001},
1011 {0x05, 0x002b, 0x0000},
1012 {0x05, 0x0031, 0x0001},
1013 {0x05, 0x0023, 0x0000},
1014 {0x05, 0x0032, 0x0001},
1015 {0x05, 0x0023, 0x0000},
1016 {0x05, 0x0033, 0x0001},
1017 {0x05, 0x0023, 0x0000},
1018 {0x05, 0x0034, 0x0001},
1019 {0x05, 0x0002, 0x0000},
1020 {0x05, 0x0050, 0x0001},
1021 {0x05, 0x0000, 0x0000},
1022 {0x05, 0x0051, 0x0001},
1023 {0x05, 0x0000, 0x0000},
1024 {0x05, 0x0052, 0x0001},
1025 {0x05, 0x0000, 0x0000},
1026 {0x05, 0x0054, 0x0001},
1027 {0x05, 0x0001, 0x0000},
1028 {0x00, 0x0000, 0x0001},
1029 {0x00, 0x0000, 0x0002},
1030 {0x00, 0x000c, 0x0003},
1031 {0x00, 0x0000, 0x0004},
1032 {0x00, 0x0090, 0x0005},
1033 {0x00, 0x0000, 0x0006},
1034 {0x00, 0x0040, 0x0007},
1035 {0x00, 0x00c0, 0x0008},
1036 {0x00, 0x004a, 0x0009},
1037 {0x00, 0x0000, 0x000a},
1038 {0x00, 0x0000, 0x000b},
1039 {0x00, 0x0001, 0x000c},
1040 {0x00, 0x0001, 0x000d},
1041 {0x00, 0x0000, 0x000e},
1042 {0x00, 0x0002, 0x000f},
1043 {0x00, 0x0001, 0x0010},
1044 {0x00, 0x0000, 0x0011},
1045 {0x00, 0x0000, 0x0012},
1046 {0x00, 0x0002, 0x0020},
1047 {0x00, 0x0080, 0x0021},
1048 {0x00, 0x0001, 0x0022},
1049 {0x00, 0x00e0, 0x0023},
1050 {0x00, 0x0000, 0x0024},
1051 {0x00, 0x00d5, 0x0025},
1052 {0x00, 0x0000, 0x0026},
1053 {0x00, 0x000b, 0x0027},
1054 {0x00, 0x0000, 0x0046},
1055 {0x00, 0x0000, 0x0047},
1056 {0x00, 0x0000, 0x0048},
1057 {0x00, 0x0000, 0x0049},
1058 {0x00, 0x0008, 0x004a},
1059 {0xff, 0x0000, 0x00d0},
1060 {0xff, 0x00d8, 0x00d1},
1061 {0xff, 0x0000, 0x00d4},
1062 {0xff, 0x0000, 0x00d5},
1063 {0x01, 0x00a6, 0x0000},
1064 {0x01, 0x0028, 0x0001},
1065 {0x01, 0x0000, 0x0002},
1066 {0x01, 0x000a, 0x0003},
1067 {0x01, 0x0040, 0x0004},
1068 {0x01, 0x0066, 0x0007},
1069 {0x01, 0x0011, 0x0008},
1070 {0x01, 0x0032, 0x0009},
1071 {0x01, 0x00fd, 0x000a},
1072 {0x01, 0x0038, 0x000b},
1073 {0x01, 0x00d1, 0x000c},
1074 {0x01, 0x00f7, 0x000d},
1075 {0x01, 0x00ed, 0x000e},
1076 {0x01, 0x00d8, 0x000f},
1077 {0x01, 0x0038, 0x0010},
1078 {0x01, 0x00ff, 0x0015},
1079 {0x01, 0x0001, 0x0016},
1080 {0x01, 0x0032, 0x0017},
1081 {0x01, 0x0023, 0x0018},
1082 {0x01, 0x00ce, 0x0019},
1083 {0x01, 0x0023, 0x001a},
1084 {0x01, 0x0032, 0x001b},
1085 {0x01, 0x008d, 0x001c},
1086 {0x01, 0x00ce, 0x001d},
1087 {0x01, 0x008d, 0x001e},
1088 {0x01, 0x0000, 0x001f},
1089 {0x01, 0x0000, 0x0020},
1090 {0x01, 0x00ff, 0x003e},
1091 {0x01, 0x0003, 0x003f},
1092 {0x01, 0x0000, 0x0040},
1093 {0x01, 0x0035, 0x0041},
1094 {0x01, 0x0053, 0x0042},
1095 {0x01, 0x0069, 0x0043},
1096 {0x01, 0x007c, 0x0044},
1097 {0x01, 0x008c, 0x0045},
1098 {0x01, 0x009a, 0x0046},
1099 {0x01, 0x00a8, 0x0047},
1100 {0x01, 0x00b4, 0x0048},
1101 {0x01, 0x00bf, 0x0049},
1102 {0x01, 0x00ca, 0x004a},
1103 {0x01, 0x00d4, 0x004b},
1104 {0x01, 0x00dd, 0x004c},
1105 {0x01, 0x00e7, 0x004d},
1106 {0x01, 0x00ef, 0x004e},
1107 {0x01, 0x00f8, 0x004f},
1108 {0x01, 0x00ff, 0x0050},
1109 {0x01, 0x0001, 0x0056},
1110 {0x01, 0x0060, 0x0057},
1111 {0x01, 0x0040, 0x0058},
1112 {0x01, 0x0011, 0x0059},
1113 {0x01, 0x0001, 0x005a},
1114 {0x02, 0x0007, 0x0005},
1115 {0x02, 0xa048, 0x0000},
1116 {0x02, 0x0007, 0x0005},
1117 {0x02, 0x0015, 0x0006},
1118 {0x02, 0x100a, 0x0007},
1119 {0x02, 0xa048, 0x0000},
1120 {0x02, 0xc002, 0x0001},
1121 {0x02, 0x000f, 0x0005},
1122 {0x02, 0xa048, 0x0000},
1123 {0x05, 0x0022, 0x0004},
1124 {0x05, 0x0025, 0x0001},
1125 {0x05, 0x0000, 0x0000},
1126 {0x05, 0x0026, 0x0001},
1127 {0x05, 0x0001, 0x0000},
1128 {0x05, 0x0027, 0x0001},
1129 {0x05, 0x0000, 0x0000},
1130 {0x05, 0x0001, 0x0001},
1131 {0x05, 0x0000, 0x0000},
1132 {0x05, 0x0021, 0x0001},
1133 {0x05, 0x00d2, 0x0000},
1134 {0x05, 0x0020, 0x0001},
1135 {0x05, 0x0000, 0x0000},
1136 {0x00, 0x0090, 0x0005},
1137 {0x01, 0x00a6, 0x0000},
1138 {0x02, 0x0007, 0x0005},
1139 {0x02, 0x2000, 0x0000},
1140 {0x05, 0x0022, 0x0004},
1141 {0x05, 0x0015, 0x0001},
1142 {0x05, 0x00ea, 0x0000},
1143 {0x05, 0x0021, 0x0001},
1144 {0x05, 0x00d2, 0x0000},
1145 {0x05, 0x0023, 0x0001},
1146 {0x05, 0x0003, 0x0000},
1147 {0x05, 0x0030, 0x0001},
1148 {0x05, 0x002b, 0x0000},
1149 {0x05, 0x0031, 0x0001},
1150 {0x05, 0x0023, 0x0000},
1151 {0x05, 0x0032, 0x0001},
1152 {0x05, 0x0023, 0x0000},
1153 {0x05, 0x0033, 0x0001},
1154 {0x05, 0x0023, 0x0000},
1155 {0x05, 0x0034, 0x0001},
1156 {0x05, 0x0002, 0x0000},
1157 {0x05, 0x0050, 0x0001},
1158 {0x05, 0x0000, 0x0000},
1159 {0x05, 0x0051, 0x0001},
1160 {0x05, 0x0000, 0x0000},
1161 {0x05, 0x0052, 0x0001},
1162 {0x05, 0x0000, 0x0000},
1163 {0x05, 0x0054, 0x0001},
1164 {0x05, 0x0001, 0x0000},
1165 {0x00, 0x0000, 0x0001},
1166 {0x00, 0x0000, 0x0002},
1167 {0x00, 0x000c, 0x0003},
1168 {0x00, 0x0000, 0x0004},
1169 {0x00, 0x0090, 0x0005},
1170 {0x00, 0x0000, 0x0006},
1171 {0x00, 0x0040, 0x0007},
1172 {0x00, 0x00c0, 0x0008},
1173 {0x00, 0x004a, 0x0009},
1174 {0x00, 0x0000, 0x000a},
1175 {0x00, 0x0000, 0x000b},
1176 {0x00, 0x0001, 0x000c},
1177 {0x00, 0x0001, 0x000d},
1178 {0x00, 0x0000, 0x000e},
1179 {0x00, 0x0002, 0x000f},
1180 {0x00, 0x0001, 0x0010},
1181 {0x00, 0x0000, 0x0011},
1182 {0x00, 0x0000, 0x0012},
1183 {0x00, 0x0002, 0x0020},
1184 {0x00, 0x0080, 0x0021},
1185 {0x00, 0x0001, 0x0022},
1186 {0x00, 0x00e0, 0x0023},
1187 {0x00, 0x0000, 0x0024},
1188 {0x00, 0x00d5, 0x0025},
1189 {0x00, 0x0000, 0x0026},
1190 {0x00, 0x000b, 0x0027},
1191 {0x00, 0x0000, 0x0046},
1192 {0x00, 0x0000, 0x0047},
1193 {0x00, 0x0000, 0x0048},
1194 {0x00, 0x0000, 0x0049},
1195 {0x00, 0x0008, 0x004a},
1196 {0xff, 0x0000, 0x00d0},
1197 {0xff, 0x00d8, 0x00d1},
1198 {0xff, 0x0000, 0x00d4},
1199 {0xff, 0x0000, 0x00d5},
1200 {0x01, 0x00a6, 0x0000},
1201 {0x01, 0x0028, 0x0001},
1202 {0x01, 0x0000, 0x0002},
1203 {0x01, 0x000a, 0x0003},
1204 {0x01, 0x0040, 0x0004},
1205 {0x01, 0x0066, 0x0007},
1206 {0x01, 0x0011, 0x0008},
1207 {0x01, 0x0032, 0x0009},
1208 {0x01, 0x00fd, 0x000a},
1209 {0x01, 0x0038, 0x000b},
1210 {0x01, 0x00d1, 0x000c},
1211 {0x01, 0x00f7, 0x000d},
1212 {0x01, 0x00ed, 0x000e},
1213 {0x01, 0x00d8, 0x000f},
1214 {0x01, 0x0038, 0x0010},
1215 {0x01, 0x00ff, 0x0015},
1216 {0x01, 0x0001, 0x0016},
1217 {0x01, 0x0032, 0x0017},
1218 {0x01, 0x0023, 0x0018},
1219 {0x01, 0x00ce, 0x0019},
1220 {0x01, 0x0023, 0x001a},
1221 {0x01, 0x0032, 0x001b},
1222 {0x01, 0x008d, 0x001c},
1223 {0x01, 0x00ce, 0x001d},
1224 {0x01, 0x008d, 0x001e},
1225 {0x01, 0x0000, 0x001f},
1226 {0x01, 0x0000, 0x0020},
1227 {0x01, 0x00ff, 0x003e},
1228 {0x01, 0x0003, 0x003f},
1229 {0x01, 0x0000, 0x0040},
1230 {0x01, 0x0035, 0x0041},
1231 {0x01, 0x0053, 0x0042},
1232 {0x01, 0x0069, 0x0043},
1233 {0x01, 0x007c, 0x0044},
1234 {0x01, 0x008c, 0x0045},
1235 {0x01, 0x009a, 0x0046},
1236 {0x01, 0x00a8, 0x0047},
1237 {0x01, 0x00b4, 0x0048},
1238 {0x01, 0x00bf, 0x0049},
1239 {0x01, 0x00ca, 0x004a},
1240 {0x01, 0x00d4, 0x004b},
1241 {0x01, 0x00dd, 0x004c},
1242 {0x01, 0x00e7, 0x004d},
1243 {0x01, 0x00ef, 0x004e},
1244 {0x01, 0x00f8, 0x004f},
1245 {0x01, 0x00ff, 0x0050},
1246 {0x01, 0x0001, 0x0056},
1247 {0x01, 0x0060, 0x0057},
1248 {0x01, 0x0040, 0x0058},
1249 {0x01, 0x0011, 0x0059},
1250 {0x01, 0x0001, 0x005a},
1251 {0x02, 0x0007, 0x0005},
1252 {0x02, 0xa048, 0x0000},
1253 {0x02, 0x0007, 0x0005},
1254 {0x02, 0x0015, 0x0006},
1255 {0x02, 0x100a, 0x0007},
1256 {0x02, 0xa048, 0x0000},
1257 {0x02, 0xc002, 0x0001},
1258 {0x02, 0x000f, 0x0005},
1259 {0x02, 0xa048, 0x0000},
1260 {0x05, 0x0022, 0x0004},
1261 {0x05, 0x0025, 0x0001},
1262 {0x05, 0x0000, 0x0000},
1263 {0x05, 0x0026, 0x0001},
1264 {0x05, 0x0001, 0x0000},
1265 {0x05, 0x0027, 0x0001},
1266 {0x05, 0x0000, 0x0000},
1267 {0x05, 0x0001, 0x0001},
1268 {0x05, 0x0000, 0x0000},
1269 {0x05, 0x0021, 0x0001},
1270 {0x05, 0x00d2, 0x0000},
1271 {0x05, 0x0020, 0x0001},
1272 {0x05, 0x0000, 0x0000},
1273 {0x00, 0x0090, 0x0005},
1274 {0x01, 0x00a6, 0x0000},
1275 {0x05, 0x0026, 0x0001},
1276 {0x05, 0x0001, 0x0000},
1277 {0x05, 0x0027, 0x0001},
1278 {0x05, 0x000f, 0x0000},
1279 {0x01, 0x0003, 0x003f},
1280 {0x01, 0x0001, 0x0056},
1281 {0x01, 0x0011, 0x0008},
1282 {0x01, 0x0032, 0x0009},
1283 {0x01, 0xfffd, 0x000a},
1284 {0x01, 0x0023, 0x000b},
1285 {0x01, 0xffea, 0x000c},
1286 {0x01, 0xfff4, 0x000d},
1287 {0x01, 0xfffc, 0x000e},
1288 {0x01, 0xffe3, 0x000f},
1289 {0x01, 0x001f, 0x0010},
1290 {0x01, 0x00a8, 0x0001},
1291 {0x01, 0x0067, 0x0007},
1292 {0x01, 0x0042, 0x0051},
1293 {0x01, 0x0051, 0x0053},
1294 {0x01, 0x000a, 0x0003},
1295 {0x02, 0xc002, 0x0001},
1296 {0x02, 0x0007, 0x0005},
1297 {0x02, 0xc000, 0x0001},
1298 {0x02, 0x0000, 0x0005},
1299 {0x02, 0x0007, 0x0005},
1300 {0x02, 0x2000, 0x0000},
1301 {0x05, 0x0022, 0x0004},
1302 {0x05, 0x0015, 0x0001},
1303 {0x05, 0x00ea, 0x0000},
1304 {0x05, 0x0021, 0x0001},
1305 {0x05, 0x00d2, 0x0000},
1306 {0x05, 0x0023, 0x0001},
1307 {0x05, 0x0003, 0x0000},
1308 {0x05, 0x0030, 0x0001},
1309 {0x05, 0x002b, 0x0000},
1310 {0x05, 0x0031, 0x0001},
1311 {0x05, 0x0023, 0x0000},
1312 {0x05, 0x0032, 0x0001},
1313 {0x05, 0x0023, 0x0000},
1314 {0x05, 0x0033, 0x0001},
1315 {0x05, 0x0023, 0x0000},
1316 {0x05, 0x0034, 0x0001},
1317 {0x05, 0x0002, 0x0000},
1318 {0x05, 0x0050, 0x0001},
1319 {0x05, 0x0000, 0x0000},
1320 {0x05, 0x0051, 0x0001},
1321 {0x05, 0x0000, 0x0000},
1322 {0x05, 0x0052, 0x0001},
1323 {0x05, 0x0000, 0x0000},
1324 {0x05, 0x0054, 0x0001},
1325 {0x05, 0x0001, 0x0000},
1326 {0x00, 0x0000, 0x0001},
1327 {0x00, 0x0000, 0x0002},
1328 {0x00, 0x000c, 0x0003},
1329 {0x00, 0x0000, 0x0004},
1330 {0x00, 0x0090, 0x0005},
1331 {0x00, 0x0000, 0x0006},
1332 {0x00, 0x0040, 0x0007},
1333 {0x00, 0x00c0, 0x0008},
1334 {0x00, 0x004a, 0x0009},
1335 {0x00, 0x0000, 0x000a},
1336 {0x00, 0x0000, 0x000b},
1337 {0x00, 0x0001, 0x000c},
1338 {0x00, 0x0001, 0x000d},
1339 {0x00, 0x0000, 0x000e},
1340 {0x00, 0x0002, 0x000f},
1341 {0x00, 0x0001, 0x0010},
1342 {0x00, 0x0000, 0x0011},
1343 {0x00, 0x0000, 0x0012},
1344 {0x00, 0x0002, 0x0020},
1345 {0x00, 0x0080, 0x0021},
1346 {0x00, 0x0001, 0x0022},
1347 {0x00, 0x00e0, 0x0023},
1348 {0x00, 0x0000, 0x0024},
1349 {0x00, 0x00d5, 0x0025},
1350 {0x00, 0x0000, 0x0026},
1351 {0x00, 0x000b, 0x0027},
1352 {0x00, 0x0000, 0x0046},
1353 {0x00, 0x0000, 0x0047},
1354 {0x00, 0x0000, 0x0048},
1355 {0x00, 0x0000, 0x0049},
1356 {0x00, 0x0008, 0x004a},
1357 {0xff, 0x0000, 0x00d0},
1358 {0xff, 0x00d8, 0x00d1},
1359 {0xff, 0x0000, 0x00d4},
1360 {0xff, 0x0000, 0x00d5},
1361 {0x01, 0x00a6, 0x0000},
1362 {0x01, 0x0028, 0x0001},
1363 {0x01, 0x0000, 0x0002},
1364 {0x01, 0x000a, 0x0003},
1365 {0x01, 0x0040, 0x0004},
1366 {0x01, 0x0066, 0x0007},
1367 {0x01, 0x0011, 0x0008},
1368 {0x01, 0x0032, 0x0009},
1369 {0x01, 0x00fd, 0x000a},
1370 {0x01, 0x0038, 0x000b},
1371 {0x01, 0x00d1, 0x000c},
1372 {0x01, 0x00f7, 0x000d},
1373 {0x01, 0x00ed, 0x000e},
1374 {0x01, 0x00d8, 0x000f},
1375 {0x01, 0x0038, 0x0010},
1376 {0x01, 0x00ff, 0x0015},
1377 {0x01, 0x0001, 0x0016},
1378 {0x01, 0x0032, 0x0017},
1379 {0x01, 0x0023, 0x0018},
1380 {0x01, 0x00ce, 0x0019},
1381 {0x01, 0x0023, 0x001a},
1382 {0x01, 0x0032, 0x001b},
1383 {0x01, 0x008d, 0x001c},
1384 {0x01, 0x00ce, 0x001d},
1385 {0x01, 0x008d, 0x001e},
1386 {0x01, 0x0000, 0x001f},
1387 {0x01, 0x0000, 0x0020},
1388 {0x01, 0x00ff, 0x003e},
1389 {0x01, 0x0003, 0x003f},
1390 {0x01, 0x0000, 0x0040},
1391 {0x01, 0x0035, 0x0041},
1392 {0x01, 0x0053, 0x0042},
1393 {0x01, 0x0069, 0x0043},
1394 {0x01, 0x007c, 0x0044},
1395 {0x01, 0x008c, 0x0045},
1396 {0x01, 0x009a, 0x0046},
1397 {0x01, 0x00a8, 0x0047},
1398 {0x01, 0x00b4, 0x0048},
1399 {0x01, 0x00bf, 0x0049},
1400 {0x01, 0x00ca, 0x004a},
1401 {0x01, 0x00d4, 0x004b},
1402 {0x01, 0x00dd, 0x004c},
1403 {0x01, 0x00e7, 0x004d},
1404 {0x01, 0x00ef, 0x004e},
1405 {0x01, 0x00f8, 0x004f},
1406 {0x01, 0x00ff, 0x0050},
1407 {0x01, 0x0001, 0x0056},
1408 {0x01, 0x0060, 0x0057},
1409 {0x01, 0x0040, 0x0058},
1410 {0x01, 0x0011, 0x0059},
1411 {0x01, 0x0001, 0x005a},
1412 {0x02, 0x0007, 0x0005},
1413 {0x02, 0xa048, 0x0000},
1414 {0x02, 0x0007, 0x0005},
1415 {0x02, 0x0015, 0x0006},
1416 {0x02, 0x100a, 0x0007},
1417 {0x02, 0xa048, 0x0000},
1418 {0x02, 0xc002, 0x0001},
1419 {0x02, 0x000f, 0x0005},
1420 {0x02, 0xa048, 0x0000},
1421 {0x05, 0x0022, 0x0004},
1422 {0x05, 0x0025, 0x0001},
1423 {0x05, 0x0000, 0x0000},
1424 {0x05, 0x0026, 0x0001},
1425 {0x05, 0x0001, 0x0000},
1426 {0x05, 0x0027, 0x0001},
1427 {0x05, 0x0000, 0x0000},
1428 {0x05, 0x0001, 0x0001},
1429 {0x05, 0x0000, 0x0000},
1430 {0x05, 0x0021, 0x0001},
1431 {0x05, 0x00d2, 0x0000},
1432 {0x05, 0x0020, 0x0001},
1433 {0x05, 0x0000, 0x0000},
1434 {0x00, 0x0090, 0x0005},
1435 {0x01, 0x00a6, 0x0000},
1436 {0x02, 0x0007, 0x0005},
1437 {0x02, 0x2000, 0x0000},
1438 {0x05, 0x0022, 0x0004},
1439 {0x05, 0x0015, 0x0001},
1440 {0x05, 0x00ea, 0x0000},
1441 {0x05, 0x0021, 0x0001},
1442 {0x05, 0x00d2, 0x0000},
1443 {0x05, 0x0023, 0x0001},
1444 {0x05, 0x0003, 0x0000},
1445 {0x05, 0x0030, 0x0001},
1446 {0x05, 0x002b, 0x0000},
1447 {0x05, 0x0031, 0x0001},
1448 {0x05, 0x0023, 0x0000},
1449 {0x05, 0x0032, 0x0001},
1450 {0x05, 0x0023, 0x0000},
1451 {0x05, 0x0033, 0x0001},
1452 {0x05, 0x0023, 0x0000},
1453 {0x05, 0x0034, 0x0001},
1454 {0x05, 0x0002, 0x0000},
1455 {0x05, 0x0050, 0x0001},
1456 {0x05, 0x0000, 0x0000},
1457 {0x05, 0x0051, 0x0001},
1458 {0x05, 0x0000, 0x0000},
1459 {0x05, 0x0052, 0x0001},
1460 {0x05, 0x0000, 0x0000},
1461 {0x05, 0x0054, 0x0001},
1462 {0x05, 0x0001, 0x0000},
1463 {0x00, 0x0000, 0x0001},
1464 {0x00, 0x0000, 0x0002},
1465 {0x00, 0x000c, 0x0003},
1466 {0x00, 0x0000, 0x0004},
1467 {0x00, 0x0090, 0x0005},
1468 {0x00, 0x0000, 0x0006},
1469 {0x00, 0x0040, 0x0007},
1470 {0x00, 0x00c0, 0x0008},
1471 {0x00, 0x004a, 0x0009},
1472 {0x00, 0x0000, 0x000a},
1473 {0x00, 0x0000, 0x000b},
1474 {0x00, 0x0001, 0x000c},
1475 {0x00, 0x0001, 0x000d},
1476 {0x00, 0x0000, 0x000e},
1477 {0x00, 0x0002, 0x000f},
1478 {0x00, 0x0001, 0x0010},
1479 {0x00, 0x0000, 0x0011},
1480 {0x00, 0x0000, 0x0012},
1481 {0x00, 0x0002, 0x0020},
1482 {0x00, 0x0080, 0x0021},
1483 {0x00, 0x0001, 0x0022},
1484 {0x00, 0x00e0, 0x0023},
1485 {0x00, 0x0000, 0x0024},
1486 {0x00, 0x00d5, 0x0025},
1487 {0x00, 0x0000, 0x0026},
1488 {0x00, 0x000b, 0x0027},
1489 {0x00, 0x0000, 0x0046},
1490 {0x00, 0x0000, 0x0047},
1491 {0x00, 0x0000, 0x0048},
1492 {0x00, 0x0000, 0x0049},
1493 {0x00, 0x0008, 0x004a},
1494 {0xff, 0x0000, 0x00d0},
1495 {0xff, 0x00d8, 0x00d1},
1496 {0xff, 0x0000, 0x00d4},
1497 {0xff, 0x0000, 0x00d5},
1498 {0x01, 0x00a6, 0x0000},
1499 {0x01, 0x0028, 0x0001},
1500 {0x01, 0x0000, 0x0002},
1501 {0x01, 0x000a, 0x0003},
1502 {0x01, 0x0040, 0x0004},
1503 {0x01, 0x0066, 0x0007},
1504 {0x01, 0x0011, 0x0008},
1505 {0x01, 0x0032, 0x0009},
1506 {0x01, 0x00fd, 0x000a},
1507 {0x01, 0x0038, 0x000b},
1508 {0x01, 0x00d1, 0x000c},
1509 {0x01, 0x00f7, 0x000d},
1510 {0x01, 0x00ed, 0x000e},
1511 {0x01, 0x00d8, 0x000f},
1512 {0x01, 0x0038, 0x0010},
1513 {0x01, 0x00ff, 0x0015},
1514 {0x01, 0x0001, 0x0016},
1515 {0x01, 0x0032, 0x0017},
1516 {0x01, 0x0023, 0x0018},
1517 {0x01, 0x00ce, 0x0019},
1518 {0x01, 0x0023, 0x001a},
1519 {0x01, 0x0032, 0x001b},
1520 {0x01, 0x008d, 0x001c},
1521 {0x01, 0x00ce, 0x001d},
1522 {0x01, 0x008d, 0x001e},
1523 {0x01, 0x0000, 0x001f},
1524 {0x01, 0x0000, 0x0020},
1525 {0x01, 0x00ff, 0x003e},
1526 {0x01, 0x0003, 0x003f},
1527 {0x01, 0x0000, 0x0040},
1528 {0x01, 0x0035, 0x0041},
1529 {0x01, 0x0053, 0x0042},
1530 {0x01, 0x0069, 0x0043},
1531 {0x01, 0x007c, 0x0044},
1532 {0x01, 0x008c, 0x0045},
1533 {0x01, 0x009a, 0x0046},
1534 {0x01, 0x00a8, 0x0047},
1535 {0x01, 0x00b4, 0x0048},
1536 {0x01, 0x00bf, 0x0049},
1537 {0x01, 0x00ca, 0x004a},
1538 {0x01, 0x00d4, 0x004b},
1539 {0x01, 0x00dd, 0x004c},
1540 {0x01, 0x00e7, 0x004d},
1541 {0x01, 0x00ef, 0x004e},
1542 {0x01, 0x00f8, 0x004f},
1543 {0x01, 0x00ff, 0x0050},
1544 {0x01, 0x0001, 0x0056},
1545 {0x01, 0x0060, 0x0057},
1546 {0x01, 0x0040, 0x0058},
1547 {0x01, 0x0011, 0x0059},
1548 {0x01, 0x0001, 0x005a},
1549 {0x02, 0x0007, 0x0005},
1550 {0x02, 0xa048, 0x0000},
1551 {0x02, 0x0007, 0x0005},
1552 {0x02, 0x0015, 0x0006},
1553 {0x02, 0x100a, 0x0007},
1554 {0x02, 0xa048, 0x0000},
1555 {0x02, 0xc002, 0x0001},
1556 {0x02, 0x000f, 0x0005},
1557 {0x02, 0xa048, 0x0000},
1558 {0x05, 0x0022, 0x0004},
1559 {0x05, 0x0025, 0x0001},
1560 {0x05, 0x0000, 0x0000},
1561 {0x05, 0x0026, 0x0001},
1562 {0x05, 0x0001, 0x0000},
1563 {0x05, 0x0027, 0x0001},
1564 {0x05, 0x0000, 0x0000},
1565 {0x05, 0x0001, 0x0001},
1566 {0x05, 0x0000, 0x0000},
1567 {0x05, 0x0021, 0x0001},
1568 {0x05, 0x00d2, 0x0000},
1569 {0x05, 0x0020, 0x0001},
1570 {0x05, 0x0000, 0x0000},
1571 {0x00, 0x0090, 0x0005},
1572 {0x01, 0x00a6, 0x0000},
1573 {0x05, 0x0026, 0x0001},
1574 {0x05, 0x0001, 0x0000},
1575 {0x05, 0x0027, 0x0001},
1576 {0x05, 0x001e, 0x0000},
1577 {0x01, 0x0003, 0x003f},
1578 {0x01, 0x0001, 0x0056},
1579 {0x01, 0x0011, 0x0008},
1580 {0x01, 0x0032, 0x0009},
1581 {0x01, 0xfffd, 0x000a},
1582 {0x01, 0x0023, 0x000b},
1583 {0x01, 0xffea, 0x000c},
1584 {0x01, 0xfff4, 0x000d},
1585 {0x01, 0xfffc, 0x000e},
1586 {0x01, 0xffe3, 0x000f},
1587 {0x01, 0x001f, 0x0010},
1588 {0x01, 0x00a8, 0x0001},
1589 {0x01, 0x0067, 0x0007},
1590 {0x01, 0x0042, 0x0051},
1591 {0x01, 0x0051, 0x0053},
1592 {0x01, 0x000a, 0x0003},
1593 {0x02, 0xc002, 0x0001},
1594 {0x02, 0x0007, 0x0005},
1595 {0x01, 0x0042, 0x0051},
1596 {0x01, 0x0051, 0x0053},
1597 {0x05, 0x0026, 0x0001},
1598 {0x05, 0x0001, 0x0000},
1599 {0x05, 0x0027, 0x0001},
1600 {0x05, 0x002d, 0x0000},
1601 {0x01, 0x0003, 0x003f},
1602 {0x01, 0x0001, 0x0056},
1603 {0x02, 0xc000, 0x0001},
1604 {0x02, 0x0000, 0x0005},
1605 {}
1606};
1607
1608/* Unknow camera from Ori Usbid 0x0000:0x0000 */
1609/* Based on snoops from Ori Cohen */
1610static const __u16 spca501c_mysterious_open_data[][3] = {
1611 {0x02, 0x000f, 0x0005},
1612 {0x02, 0xa048, 0x0000},
1613 {0x05, 0x0022, 0x0004},
1614/* DSP Registers */
1615 {0x01, 0x0016, 0x0011}, /* RGB offset */
1616 {0x01, 0x0000, 0x0012},
1617 {0x01, 0x0006, 0x0013},
1618 {0x01, 0x0078, 0x0051},
1619 {0x01, 0x0040, 0x0052},
1620 {0x01, 0x0046, 0x0053},
1621 {0x01, 0x0040, 0x0054},
1622 {0x00, 0x0025, 0x0000},
1623/* {0x00, 0x0000, 0x0000 }, */
1624/* Part 2 */
1625/* TG Registers */
1626 {0x00, 0x0026, 0x0000},
1627 {0x00, 0x0001, 0x0000},
1628 {0x00, 0x0027, 0x0000},
1629 {0x00, 0x008a, 0x0000},
1630 {0x02, 0x0007, 0x0005},
1631 {0x02, 0x2000, 0x0000},
1632 {0x05, 0x0022, 0x0004},
1633 {0x05, 0x0015, 0x0001},
1634 {0x05, 0x00ea, 0x0000},
1635 {0x05, 0x0021, 0x0001},
1636 {0x05, 0x00d2, 0x0000},
1637 {0x05, 0x0023, 0x0001},
1638 {0x05, 0x0003, 0x0000},
1639 {0x05, 0x0030, 0x0001},
1640 {0x05, 0x002b, 0x0000},
1641 {0x05, 0x0031, 0x0001},
1642 {0x05, 0x0023, 0x0000},
1643 {0x05, 0x0032, 0x0001},
1644 {0x05, 0x0023, 0x0000},
1645 {0x05, 0x0033, 0x0001},
1646 {0x05, 0x0023, 0x0000},
1647 {0x05, 0x0034, 0x0001},
1648 {0x05, 0x0002, 0x0000},
1649 {0x05, 0x0050, 0x0001},
1650 {0x05, 0x0000, 0x0000},
1651 {0x05, 0x0051, 0x0001},
1652 {0x05, 0x0000, 0x0000},
1653 {0x05, 0x0052, 0x0001},
1654 {0x05, 0x0000, 0x0000},
1655 {0x05, 0x0054, 0x0001},
1656 {0x05, 0x0001, 0x0000},
1657 {}
1658};
1659
1660/* Based on snoops from Ori Cohen */
1661static const __u16 spca501c_mysterious_init_data[][3] = {
1662/* Part 3 */
1663/* TG registers */
1664/* {0x00, 0x0000, 0x0000}, */
1665 {0x00, 0x0000, 0x0001},
1666 {0x00, 0x0000, 0x0002},
1667 {0x00, 0x0006, 0x0003},
1668 {0x00, 0x0000, 0x0004},
1669 {0x00, 0x0090, 0x0005},
1670 {0x00, 0x0000, 0x0006},
1671 {0x00, 0x0040, 0x0007},
1672 {0x00, 0x00c0, 0x0008},
1673 {0x00, 0x004a, 0x0009},
1674 {0x00, 0x0000, 0x000a},
1675 {0x00, 0x0000, 0x000b},
1676 {0x00, 0x0001, 0x000c},
1677 {0x00, 0x0001, 0x000d},
1678 {0x00, 0x0000, 0x000e},
1679 {0x00, 0x0002, 0x000f},
1680 {0x00, 0x0001, 0x0010},
1681 {0x00, 0x0000, 0x0011},
1682 {0x00, 0x0001, 0x0012},
1683 {0x00, 0x0002, 0x0020},
1684 {0x00, 0x0080, 0x0021}, /* 640 */
1685 {0x00, 0x0001, 0x0022},
1686 {0x00, 0x00e0, 0x0023}, /* 480 */
1687 {0x00, 0x0000, 0x0024}, /* Offset H hight */
1688 {0x00, 0x00d3, 0x0025}, /* low */
1689 {0x00, 0x0000, 0x0026}, /* Offset V */
1690 {0x00, 0x000d, 0x0027}, /* low */
1691 {0x00, 0x0000, 0x0046},
1692 {0x00, 0x0000, 0x0047},
1693 {0x00, 0x0000, 0x0048},
1694 {0x00, 0x0000, 0x0049},
1695 {0x00, 0x0008, 0x004a},
1696/* DSP Registers */
1697 {0x01, 0x00a6, 0x0000},
1698 {0x01, 0x0028, 0x0001},
1699 {0x01, 0x0000, 0x0002},
1700 {0x01, 0x000a, 0x0003}, /* Level Calc bit7 ->1 Auto */
1701 {0x01, 0x0040, 0x0004},
1702 {0x01, 0x0066, 0x0007},
1703 {0x01, 0x000f, 0x0008}, /* A11 Color correction coeff */
1704 {0x01, 0x002d, 0x0009}, /* A12 */
1705 {0x01, 0x0005, 0x000a}, /* A13 */
1706 {0x01, 0x0023, 0x000b}, /* A21 */
1707 {0x01, 0x00e0, 0x000c}, /* A22 */
1708 {0x01, 0x00fd, 0x000d}, /* A23 */
1709 {0x01, 0x00f4, 0x000e}, /* A31 */
1710 {0x01, 0x00e4, 0x000f}, /* A32 */
1711 {0x01, 0x0028, 0x0010}, /* A33 */
1712 {0x01, 0x00ff, 0x0015}, /* Reserved */
1713 {0x01, 0x0001, 0x0016}, /* Reserved */
1714 {0x01, 0x0032, 0x0017}, /* Win1 Start begin */
1715 {0x01, 0x0023, 0x0018},
1716 {0x01, 0x00ce, 0x0019},
1717 {0x01, 0x0023, 0x001a},
1718 {0x01, 0x0032, 0x001b},
1719 {0x01, 0x008d, 0x001c},
1720 {0x01, 0x00ce, 0x001d},
1721 {0x01, 0x008d, 0x001e},
1722 {0x01, 0x0000, 0x001f},
1723 {0x01, 0x0000, 0x0020}, /* Win1 Start end */
1724 {0x01, 0x00ff, 0x003e}, /* Reserved begin */
1725 {0x01, 0x0002, 0x003f},
1726 {0x01, 0x0000, 0x0040},
1727 {0x01, 0x0035, 0x0041},
1728 {0x01, 0x0053, 0x0042},
1729 {0x01, 0x0069, 0x0043},
1730 {0x01, 0x007c, 0x0044},
1731 {0x01, 0x008c, 0x0045},
1732 {0x01, 0x009a, 0x0046},
1733 {0x01, 0x00a8, 0x0047},
1734 {0x01, 0x00b4, 0x0048},
1735 {0x01, 0x00bf, 0x0049},
1736 {0x01, 0x00ca, 0x004a},
1737 {0x01, 0x00d4, 0x004b},
1738 {0x01, 0x00dd, 0x004c},
1739 {0x01, 0x00e7, 0x004d},
1740 {0x01, 0x00ef, 0x004e},
1741 {0x01, 0x00f8, 0x004f},
1742 {0x01, 0x00ff, 0x0050},
1743 {0x01, 0x0003, 0x0056}, /* Reserved end */
1744 {0x01, 0x0060, 0x0057}, /* Edge Gain */
1745 {0x01, 0x0040, 0x0058},
1746 {0x01, 0x0011, 0x0059}, /* Edge Bandwidth */
1747 {0x01, 0x0001, 0x005a},
1748 {0x02, 0x0007, 0x0005},
1749 {0x02, 0xa048, 0x0000},
1750 {0x02, 0x0007, 0x0005},
1751 {0x02, 0x0015, 0x0006},
1752 {0x02, 0x200a, 0x0007},
1753 {0x02, 0xa048, 0x0000},
1754 {0x02, 0xc000, 0x0001},
1755 {0x02, 0x000f, 0x0005},
1756 {0x02, 0xa048, 0x0000},
1757 {0x05, 0x0022, 0x0004},
1758 {0x05, 0x0025, 0x0001},
1759 {0x05, 0x0000, 0x0000},
1760/* Part 4 */
1761 {0x05, 0x0026, 0x0001},
1762 {0x05, 0x0001, 0x0000},
1763 {0x05, 0x0027, 0x0001},
1764 {0x05, 0x0000, 0x0000},
1765 {0x05, 0x0001, 0x0001},
1766 {0x05, 0x0000, 0x0000},
1767 {0x05, 0x0021, 0x0001},
1768 {0x05, 0x00d2, 0x0000},
1769 {0x05, 0x0020, 0x0001},
1770 {0x05, 0x0000, 0x0000},
1771 {0x00, 0x0090, 0x0005},
1772 {0x01, 0x00a6, 0x0000},
1773 {0x02, 0x0000, 0x0005},
1774 {0x05, 0x0026, 0x0001},
1775 {0x05, 0x0001, 0x0000},
1776 {0x05, 0x0027, 0x0001},
1777 {0x05, 0x004e, 0x0000},
1778/* Part 5 */
1779 {0x01, 0x0003, 0x003f},
1780 {0x01, 0x0001, 0x0056},
1781 {0x01, 0x000f, 0x0008},
1782 {0x01, 0x002d, 0x0009},
1783 {0x01, 0x0005, 0x000a},
1784 {0x01, 0x0023, 0x000b},
1785 {0x01, 0xffe0, 0x000c},
1786 {0x01, 0xfffd, 0x000d},
1787 {0x01, 0xfff4, 0x000e},
1788 {0x01, 0xffe4, 0x000f},
1789 {0x01, 0x0028, 0x0010},
1790 {0x01, 0x00a8, 0x0001},
1791 {0x01, 0x0066, 0x0007},
1792 {0x01, 0x0032, 0x0017},
1793 {0x01, 0x0023, 0x0018},
1794 {0x01, 0x00ce, 0x0019},
1795 {0x01, 0x0023, 0x001a},
1796 {0x01, 0x0032, 0x001b},
1797 {0x01, 0x008d, 0x001c},
1798 {0x01, 0x00ce, 0x001d},
1799 {0x01, 0x008d, 0x001e},
1800 {0x01, 0x00c8, 0x0015}, /* c8 Poids fort Luma */
1801 {0x01, 0x0032, 0x0016}, /* 32 */
1802 {0x01, 0x0016, 0x0011}, /* R 00 */
1803 {0x01, 0x0016, 0x0012}, /* G 00 */
1804 {0x01, 0x0016, 0x0013}, /* B 00 */
1805 {0x01, 0x000a, 0x0003},
1806 {0x02, 0xc002, 0x0001},
1807 {0x02, 0x0007, 0x0005},
1808 {}
1809};
1810
1811static int reg_write(struct usb_device *dev,
1812 __u16 req, __u16 index, __u16 value)
1813{
1814 int ret;
1815
1816 ret = usb_control_msg(dev,
1817 usb_sndctrlpipe(dev, 0),
1818 req,
1819 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1820 value, index, NULL, 0, 500);
1821 PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x",
1822 req, index, value);
1823 if (ret < 0)
1824 PDEBUG(D_ERR, "reg write: error %d", ret);
1825 return ret;
1826}
1827
1828/* returns: negative is error, pos or zero is data */
1829static int reg_read(struct gspca_dev *gspca_dev,
1830 __u16 req, /* bRequest */
1831 __u16 index, /* wIndex */
1832 __u16 length) /* wLength (1 or 2 only) */
1833{
1834 int ret;
1835
1836 gspca_dev->usb_buf[1] = 0;
1837 ret = usb_control_msg(gspca_dev->dev,
1838 usb_rcvctrlpipe(gspca_dev->dev, 0),
1839 req,
1840 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1841 0, /* value */
1842 index,
1843 gspca_dev->usb_buf, length,
1844 500); /* timeout */
1845 if (ret < 0) {
1846 PDEBUG(D_ERR, "reg_read err %d", ret);
1847 return -1;
1848 }
1849 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
1850}
1851
1852static int write_vector(struct gspca_dev *gspca_dev,
1853 const __u16 data[][3])
1854{
1855 struct usb_device *dev = gspca_dev->dev;
1856 int ret, i = 0;
1857
1858 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
1859 ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
1860 if (ret < 0) {
1861 PDEBUG(D_ERR,
1862 "Reg write failed for 0x%02x,0x%02x,0x%02x",
1863 data[i][0], data[i][1], data[i][2]);
1864 return ret;
1865 }
1866 i++;
1867 }
1868 return 0;
1869}
1870
1871static void setbrightness(struct gspca_dev *gspca_dev)
1872{
1873 struct sd *sd = (struct sd *) gspca_dev;
1874
1875 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, sd->brightness);
1876 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, sd->brightness);
1877 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, sd->brightness);
1878}
1879
1880static void getbrightness(struct gspca_dev *gspca_dev)
1881{
1882 struct sd *sd = (struct sd *) gspca_dev;
1883 __u16 brightness;
1884
1885 brightness = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x11, 2);
1886 sd->brightness = brightness << 1;
1887}
1888
1889static void setcontrast(struct gspca_dev *gspca_dev)
1890{
1891 struct sd *sd = (struct sd *) gspca_dev;
1892
1893 reg_write(gspca_dev->dev, 0x00, 0x00,
1894 (sd->contrast >> 8) & 0xff);
1895 reg_write(gspca_dev->dev, 0x00, 0x01,
1896 sd->contrast & 0xff);
1897}
1898
1899static void getcontrast(struct gspca_dev *gspca_dev)
1900{
1901/* spca50x->contrast = 0xaa01; */
1902}
1903
1904static void setcolors(struct gspca_dev *gspca_dev)
1905{
1906 struct sd *sd = (struct sd *) gspca_dev;
1907
1908 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, sd->colors);
1909}
1910
1911static void getcolors(struct gspca_dev *gspca_dev)
1912{
1913 struct sd *sd = (struct sd *) gspca_dev;
1914
1915 sd->colors = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x0c, 2);
1916/* sd->hue = (reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x13, */
1917/* 2) & 0xFF) << 8; */
1918}
1919
1920/* this function is called at probe time */
1921static int sd_config(struct gspca_dev *gspca_dev,
1922 const struct usb_device_id *id)
1923{
1924 struct sd *sd = (struct sd *) gspca_dev;
1925 struct cam *cam;
1926 __u16 vendor;
1927 __u16 product;
1928
1929 vendor = id->idVendor;
1930 product = id->idProduct;
1931 switch (vendor) {
1932 case 0x0000: /* Unknow Camera */
1933/* switch (product) { */
1934/* case 0x0000: */
1935 sd->subtype = MystFromOriUnknownCamera;
1936/* break; */
1937/* } */
1938 break;
1939 case 0x040a: /* Kodak cameras */
1940/* switch (product) { */
1941/* case 0x0002: */
1942 sd->subtype = KodakDVC325;
1943/* break; */
1944/* } */
1945 break;
1946 case 0x0497: /* Smile International */
1947/* switch (product) { */
1948/* case 0xc001: */
1949 sd->subtype = SmileIntlCamera;
1950/* break; */
1951/* } */
1952 break;
1953 case 0x0506: /* 3COM cameras */
1954/* switch (product) { */
1955/* case 0x00df: */
1956 sd->subtype = ThreeComHomeConnectLite;
1957/* break; */
1958/* } */
1959 break;
1960 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
1961 switch (product) {
1962 case 0x0401:
1963 sd->subtype = IntelCreateAndShare;
1964 break;
1965 case 0x0402:
1966 sd->subtype = ViewQuestM318B;
1967 break;
1968 }
1969 break;
1970 case 0x1776: /* Arowana */
1971/* switch (product) { */
1972/* case 0x501c: */
1973 sd->subtype = Arowana300KCMOSCamera;
1974/* break; */
1975/* } */
1976 break;
1977 }
1978 cam = &gspca_dev->cam;
1979 cam->dev_name = (char *) id->driver_info;
1980 cam->epaddr = 0x01;
1981 cam->cam_mode = vga_mode;
1982 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1983 sd->brightness = sd_ctrls[MY_BRIGHTNESS].qctrl.default_value;
1984 sd->contrast = sd_ctrls[MY_CONTRAST].qctrl.default_value;
1985 sd->colors = sd_ctrls[MY_COLOR].qctrl.default_value;
1986
1987 switch (sd->subtype) {
1988 case Arowana300KCMOSCamera:
1989 case SmileIntlCamera:
1990 /* Arowana 300k CMOS Camera data */
1991 if (write_vector(gspca_dev, spca501c_arowana_init_data))
1992 goto error;
1993 break;
1994 case MystFromOriUnknownCamera:
1995 /* UnKnow Ori CMOS Camera data */
1996 if (write_vector(gspca_dev, spca501c_mysterious_open_data))
1997 goto error;
1998 break;
1999 default:
2000 /* generic spca501 init data */
2001 if (write_vector(gspca_dev, spca501_init_data))
2002 goto error;
2003 break;
2004 }
2005 return 0;
2006error:
2007 return -EINVAL;
2008}
2009
2010/* this function is called at open time */
2011static int sd_open(struct gspca_dev *gspca_dev)
2012{
2013 struct sd *sd = (struct sd *) gspca_dev;
2014
2015 switch (sd->subtype) {
2016 case ThreeComHomeConnectLite:
2017 /* Special handling for 3com data */
2018 write_vector(gspca_dev, spca501_3com_open_data);
2019 break;
2020 case Arowana300KCMOSCamera:
2021 case SmileIntlCamera:
2022 /* Arowana 300k CMOS Camera data */
2023 write_vector(gspca_dev, spca501c_arowana_open_data);
2024 break;
2025 case MystFromOriUnknownCamera:
2026 /* UnKnow CMOS Camera data */
2027 write_vector(gspca_dev, spca501c_mysterious_init_data);
2028 break;
2029 default:
2030 /* Generic 501 open data */
2031 write_vector(gspca_dev, spca501_open_data);
2032 }
2033 PDEBUG(D_STREAM, "Initializing SPCA501 finished");
2034 return 0;
2035}
2036
2037static void sd_start(struct gspca_dev *gspca_dev)
2038{
2039 struct usb_device *dev = gspca_dev->dev;
2040 int mode;
2041
2042 /* memorize the wanted pixel format */
2043 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2044
2045 /* Enable ISO packet machine CTRL reg=2,
2046 * index=1 bitmask=0x2 (bit ordinal 1) */
2047 reg_write(dev, SPCA50X_REG_USB, 0x6, 0x94);
2048 switch (mode) {
2049 case 0: /* 640x480 */
2050 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x004a);
2051 break;
2052 case 1: /* 320x240 */
2053 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x104a);
2054 break;
2055 default:
2056/* case 2: * 160x120 */
2057 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x204a);
2058 break;
2059 }
2060 reg_write(dev, SPCA501_REG_CTLRL, 0x01, 0x02);
2061
2062 /* HDG atleast the Intel CreateAndShare needs to have one of its
2063 * brightness / contrast / color set otherwise it assumes what seems
2064 * max contrast. Note that strange enough setting any of these is
2065 * enough to fix the max contrast problem, to be sure we set all 3 */
2066 setbrightness(gspca_dev);
2067 setcontrast(gspca_dev);
2068 setcolors(gspca_dev);
2069}
2070
2071static void sd_stopN(struct gspca_dev *gspca_dev)
2072{
2073 /* Disable ISO packet
2074 * machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */
2075 reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
2076}
2077
2078static void sd_stop0(struct gspca_dev *gspca_dev)
2079{
2080}
2081
2082/* this function is called at close time */
2083static void sd_close(struct gspca_dev *gspca_dev)
2084{
2085 reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
2086}
2087
2088static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2089 struct gspca_frame *frame, /* target */
2090 __u8 *data, /* isoc packet */
2091 int len) /* iso packet length */
2092{
2093 switch (data[0]) {
2094 case 0: /* start of frame */
2095 frame = gspca_frame_add(gspca_dev,
2096 LAST_PACKET,
2097 frame,
2098 data, 0);
2099 data += SPCA501_OFFSET_DATA;
2100 len -= SPCA501_OFFSET_DATA;
2101 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
2102 data, len);
2103 return;
2104 case 0xff: /* drop */
2105/* gspca_dev->last_packet_type = DISCARD_PACKET; */
2106 return;
2107 }
2108 data++;
2109 len--;
2110 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
2111 data, len);
2112}
2113
2114static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
2115{
2116 struct sd *sd = (struct sd *) gspca_dev;
2117
2118 sd->brightness = val;
2119 if (gspca_dev->streaming)
2120 setbrightness(gspca_dev);
2121 return 0;
2122}
2123
2124static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
2125{
2126 struct sd *sd = (struct sd *) gspca_dev;
2127
2128 getbrightness(gspca_dev);
2129 *val = sd->brightness;
2130 return 0;
2131}
2132
2133static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
2134{
2135 struct sd *sd = (struct sd *) gspca_dev;
2136
2137 sd->contrast = val;
2138 if (gspca_dev->streaming)
2139 setcontrast(gspca_dev);
2140 return 0;
2141}
2142
2143static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
2144{
2145 struct sd *sd = (struct sd *) gspca_dev;
2146
2147 getcontrast(gspca_dev);
2148 *val = sd->contrast;
2149 return 0;
2150}
2151
2152static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
2153{
2154 struct sd *sd = (struct sd *) gspca_dev;
2155
2156 sd->colors = val;
2157 if (gspca_dev->streaming)
2158 setcolors(gspca_dev);
2159 return 0;
2160}
2161
2162static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
2163{
2164 struct sd *sd = (struct sd *) gspca_dev;
2165
2166 getcolors(gspca_dev);
2167 *val = sd->colors;
2168 return 0;
2169}
2170
2171/* sub-driver description */
2172static const struct sd_desc sd_desc = {
2173 .name = MODULE_NAME,
2174 .ctrls = sd_ctrls,
2175 .nctrls = ARRAY_SIZE(sd_ctrls),
2176 .config = sd_config,
2177 .open = sd_open,
2178 .start = sd_start,
2179 .stopN = sd_stopN,
2180 .stop0 = sd_stop0,
2181 .close = sd_close,
2182 .pkt_scan = sd_pkt_scan,
2183};
2184
2185/* -- module initialisation -- */
2186#define DVNM(name) .driver_info = (kernel_ulong_t) name
2187static const __devinitdata struct usb_device_id device_table[] = {
2188 {USB_DEVICE(0x040a, 0x0002), DVNM("Kodak DVC-325")},
2189 {USB_DEVICE(0x0497, 0xc001), DVNM("Smile International")},
2190 {USB_DEVICE(0x0506, 0x00df), DVNM("3Com HomeConnect Lite")},
2191 {USB_DEVICE(0x0733, 0x0401), DVNM("Intel Create and Share")},
2192 {USB_DEVICE(0x0733, 0x0402), DVNM("ViewQuest M318B")},
2193 {USB_DEVICE(0x1776, 0x501c), DVNM("Arowana 300K CMOS Camera")},
2194 {USB_DEVICE(0x0000, 0x0000), DVNM("MystFromOri Unknow Camera")},
2195 {}
2196};
2197MODULE_DEVICE_TABLE(usb, device_table);
2198
2199/* -- device connect -- */
2200static int sd_probe(struct usb_interface *intf,
2201 const struct usb_device_id *id)
2202{
2203 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2204 THIS_MODULE);
2205}
2206
2207static struct usb_driver sd_driver = {
2208 .name = MODULE_NAME,
2209 .id_table = device_table,
2210 .probe = sd_probe,
2211 .disconnect = gspca_disconnect,
2212};
2213
2214/* -- module insert / remove -- */
2215static int __init sd_mod_init(void)
2216{
2217 if (usb_register(&sd_driver) < 0)
2218 return -1;
2219 PDEBUG(D_PROBE, "v%s registered", version);
2220 return 0;
2221}
2222static void __exit sd_mod_exit(void)
2223{
2224 usb_deregister(&sd_driver);
2225 PDEBUG(D_PROBE, "deregistered");
2226}
2227
2228module_init(sd_mod_init);
2229module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
new file mode 100644
index 000000000000..ddea6e140aa8
--- /dev/null
+++ b/drivers/media/video/gspca/spca505.c
@@ -0,0 +1,951 @@
1/*
2 * SPCA505 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca505"
23
24#include "gspca.h"
25
26#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
27static const char version[] = "2.1.7";
28
29MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
37 int buflen;
38 unsigned char tmpbuf[640 * 480 * 3 / 2]; /* YYUV per line */
39 unsigned char tmpbuf2[640 * 480 * 2]; /* YUYV */
40
41 unsigned char brightness;
42
43 char subtype;
44#define IntelPCCameraPro 0
45#define Nxultra 1
46};
47
48/* V4L2 controls supported by the driver */
49static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
50static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
51
52static struct ctrl sd_ctrls[] = {
53#define SD_BRIGHTNESS 0
54 {
55 {
56 .id = V4L2_CID_BRIGHTNESS,
57 .type = V4L2_CTRL_TYPE_INTEGER,
58 .name = "Brightness",
59 .minimum = 0,
60 .maximum = 255,
61 .step = 1,
62 .default_value = 127,
63 },
64 .set = sd_setbrightness,
65 .get = sd_getbrightness,
66 },
67};
68
69static struct v4l2_pix_format vga_mode[] = {
70 {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
71 .bytesperline = 160 * 2,
72 .sizeimage = 160 * 120 * 2,
73 .colorspace = V4L2_COLORSPACE_SRGB,
74 .priv = 5},
75 {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
76 .bytesperline = 176 * 2,
77 .sizeimage = 176 * 144 * 2,
78 .colorspace = V4L2_COLORSPACE_SRGB,
79 .priv = 4},
80 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
81 .bytesperline = 320 * 2,
82 .sizeimage = 320 * 240 * 2,
83 .colorspace = V4L2_COLORSPACE_SRGB,
84 .priv = 2},
85 {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
86 .bytesperline = 352 * 2,
87 .sizeimage = 352 * 288 * 2,
88 .colorspace = V4L2_COLORSPACE_SRGB,
89 .priv = 1},
90 {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
91 .bytesperline = 640 * 2,
92 .sizeimage = 640 * 480 * 2,
93 .colorspace = V4L2_COLORSPACE_SRGB,
94 .priv = 0},
95};
96
97#define SPCA50X_OFFSET_DATA 10
98
99#define SPCA50X_REG_USB 0x02 /* spca505 501 */
100
101#define SPCA50X_USB_CTRL 0x00 /* spca505 */
102#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
103#define SPCA50X_REG_GLOBAL 0x03 /* spca505 */
104#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
105#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
106
107#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
108#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
109#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */
110
111/*
112 * Data to initialize a SPCA505. Common to the CCD and external modes
113 */
114static const __u16 spca505_init_data[][3] = {
115 /* line bmRequest,value,index */
116 /* 1819 */
117 {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
118 /* Sensor reset */
119 /* 1822 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
120 /* 1825 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
121 /* Block USB reset */
122 /* 1828 */ {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL,
123 SPCA50X_GLOBAL_MISC0},
124
125 /* 1831 */ {0x5, 0x01, 0x10},
126 /* Maybe power down some stuff */
127 /* 1834 */ {0x5, 0x0f, 0x11},
128
129 /* Setup internal CCD ? */
130 /* 1837 */ {0x6, 0x10, 0x08},
131 /* 1840 */ {0x6, 0x00, 0x09},
132 /* 1843 */ {0x6, 0x00, 0x0a},
133 /* 1846 */ {0x6, 0x00, 0x0b},
134 /* 1849 */ {0x6, 0x10, 0x0c},
135 /* 1852 */ {0x6, 0x00, 0x0d},
136 /* 1855 */ {0x6, 0x00, 0x0e},
137 /* 1858 */ {0x6, 0x00, 0x0f},
138 /* 1861 */ {0x6, 0x10, 0x10},
139 /* 1864 */ {0x6, 0x02, 0x11},
140 /* 1867 */ {0x6, 0x00, 0x12},
141 /* 1870 */ {0x6, 0x04, 0x13},
142 /* 1873 */ {0x6, 0x02, 0x14},
143 /* 1876 */ {0x6, 0x8a, 0x51},
144 /* 1879 */ {0x6, 0x40, 0x52},
145 /* 1882 */ {0x6, 0xb6, 0x53},
146 /* 1885 */ {0x6, 0x3d, 0x54},
147 {}
148};
149
150/*
151 * Data to initialize the camera using the internal CCD
152 */
153static const __u16 spca505_open_data_ccd[][3] = {
154 /* line bmRequest,value,index */
155 /* Internal CCD data set */
156 /* 1891 */ {0x3, 0x04, 0x01},
157 /* This could be a reset */
158 /* 1894 */ {0x3, 0x00, 0x01},
159
160 /* Setup compression and image registers. 0x6 and 0x7 seem to be
161 related to H&V hold, and are resolution mode specific */
162 /* 1897 */ {0x4, 0x10, 0x01},
163 /* DIFF(0x50), was (0x10) */
164 /* 1900 */ {0x4, 0x00, 0x04},
165 /* 1903 */ {0x4, 0x00, 0x05},
166 /* 1906 */ {0x4, 0x20, 0x06},
167 /* 1909 */ {0x4, 0x20, 0x07},
168
169 /* 1912 */ {0x8, 0x0a, 0x00},
170 /* DIFF (0x4a), was (0xa) */
171
172 /* 1915 */ {0x5, 0x00, 0x10},
173 /* 1918 */ {0x5, 0x00, 0x11},
174 /* 1921 */ {0x5, 0x00, 0x00},
175 /* DIFF not written */
176 /* 1924 */ {0x5, 0x00, 0x01},
177 /* DIFF not written */
178 /* 1927 */ {0x5, 0x00, 0x02},
179 /* DIFF not written */
180 /* 1930 */ {0x5, 0x00, 0x03},
181 /* DIFF not written */
182 /* 1933 */ {0x5, 0x00, 0x04},
183 /* DIFF not written */
184 /* 1936 */ {0x5, 0x80, 0x05},
185 /* DIFF not written */
186 /* 1939 */ {0x5, 0xe0, 0x06},
187 /* DIFF not written */
188 /* 1942 */ {0x5, 0x20, 0x07},
189 /* DIFF not written */
190 /* 1945 */ {0x5, 0xa0, 0x08},
191 /* DIFF not written */
192 /* 1948 */ {0x5, 0x0, 0x12},
193 /* DIFF not written */
194 /* 1951 */ {0x5, 0x02, 0x0f},
195 /* DIFF not written */
196 /* 1954 */ {0x5, 0x10, 0x46},
197 /* DIFF not written */
198 /* 1957 */ {0x5, 0x8, 0x4a},
199 /* DIFF not written */
200
201 /* 1960 */ {0x3, 0x08, 0x03},
202 /* DIFF (0x3,0x28,0x3) */
203 /* 1963 */ {0x3, 0x08, 0x01},
204 /* 1966 */ {0x3, 0x0c, 0x03},
205 /* DIFF not written */
206 /* 1969 */ {0x3, 0x21, 0x00},
207 /* DIFF (0x39) */
208
209/* Extra block copied from init to hopefully ensure CCD is in a sane state */
210 /* 1837 */ {0x6, 0x10, 0x08},
211 /* 1840 */ {0x6, 0x00, 0x09},
212 /* 1843 */ {0x6, 0x00, 0x0a},
213 /* 1846 */ {0x6, 0x00, 0x0b},
214 /* 1849 */ {0x6, 0x10, 0x0c},
215 /* 1852 */ {0x6, 0x00, 0x0d},
216 /* 1855 */ {0x6, 0x00, 0x0e},
217 /* 1858 */ {0x6, 0x00, 0x0f},
218 /* 1861 */ {0x6, 0x10, 0x10},
219 /* 1864 */ {0x6, 0x02, 0x11},
220 /* 1867 */ {0x6, 0x00, 0x12},
221 /* 1870 */ {0x6, 0x04, 0x13},
222 /* 1873 */ {0x6, 0x02, 0x14},
223 /* 1876 */ {0x6, 0x8a, 0x51},
224 /* 1879 */ {0x6, 0x40, 0x52},
225 /* 1882 */ {0x6, 0xb6, 0x53},
226 /* 1885 */ {0x6, 0x3d, 0x54},
227 /* End of extra block */
228
229 /* 1972 */ {0x6, 0x3f, 0x1},
230 /* Block skipped */
231 /* 1975 */ {0x6, 0x10, 0x02},
232 /* 1978 */ {0x6, 0x64, 0x07},
233 /* 1981 */ {0x6, 0x10, 0x08},
234 /* 1984 */ {0x6, 0x00, 0x09},
235 /* 1987 */ {0x6, 0x00, 0x0a},
236 /* 1990 */ {0x6, 0x00, 0x0b},
237 /* 1993 */ {0x6, 0x10, 0x0c},
238 /* 1996 */ {0x6, 0x00, 0x0d},
239 /* 1999 */ {0x6, 0x00, 0x0e},
240 /* 2002 */ {0x6, 0x00, 0x0f},
241 /* 2005 */ {0x6, 0x10, 0x10},
242 /* 2008 */ {0x6, 0x02, 0x11},
243 /* 2011 */ {0x6, 0x00, 0x12},
244 /* 2014 */ {0x6, 0x04, 0x13},
245 /* 2017 */ {0x6, 0x02, 0x14},
246 /* 2020 */ {0x6, 0x8a, 0x51},
247 /* 2023 */ {0x6, 0x40, 0x52},
248 /* 2026 */ {0x6, 0xb6, 0x53},
249 /* 2029 */ {0x6, 0x3d, 0x54},
250 /* 2032 */ {0x6, 0x60, 0x57},
251 /* 2035 */ {0x6, 0x20, 0x58},
252 /* 2038 */ {0x6, 0x15, 0x59},
253 /* 2041 */ {0x6, 0x05, 0x5a},
254
255 /* 2044 */ {0x5, 0x01, 0xc0},
256 /* 2047 */ {0x5, 0x10, 0xcb},
257 /* 2050 */ {0x5, 0x80, 0xc1},
258 /* */
259 /* 2053 */ {0x5, 0x0, 0xc2},
260 /* 4 was 0 */
261 /* 2056 */ {0x5, 0x00, 0xca},
262 /* 2059 */ {0x5, 0x80, 0xc1},
263 /* */
264 /* 2062 */ {0x5, 0x04, 0xc2},
265 /* 2065 */ {0x5, 0x00, 0xca},
266 /* 2068 */ {0x5, 0x0, 0xc1},
267 /* */
268 /* 2071 */ {0x5, 0x00, 0xc2},
269 /* 2074 */ {0x5, 0x00, 0xca},
270 /* 2077 */ {0x5, 0x40, 0xc1},
271 /* */
272 /* 2080 */ {0x5, 0x17, 0xc2},
273 /* 2083 */ {0x5, 0x00, 0xca},
274 /* 2086 */ {0x5, 0x80, 0xc1},
275 /* */
276 /* 2089 */ {0x5, 0x06, 0xc2},
277 /* 2092 */ {0x5, 0x00, 0xca},
278 /* 2095 */ {0x5, 0x80, 0xc1},
279 /* */
280 /* 2098 */ {0x5, 0x04, 0xc2},
281 /* 2101 */ {0x5, 0x00, 0xca},
282
283 /* 2104 */ {0x3, 0x4c, 0x3},
284 /* 2107 */ {0x3, 0x18, 0x1},
285
286 /* 2110 */ {0x6, 0x70, 0x51},
287 /* 2113 */ {0x6, 0xbe, 0x53},
288 /* 2116 */ {0x6, 0x71, 0x57},
289 /* 2119 */ {0x6, 0x20, 0x58},
290 /* 2122 */ {0x6, 0x05, 0x59},
291 /* 2125 */ {0x6, 0x15, 0x5a},
292
293 /* 2128 */ {0x4, 0x00, 0x08},
294 /* Compress = OFF (0x1 to turn on) */
295 /* 2131 */ {0x4, 0x12, 0x09},
296 /* 2134 */ {0x4, 0x21, 0x0a},
297 /* 2137 */ {0x4, 0x10, 0x0b},
298 /* 2140 */ {0x4, 0x21, 0x0c},
299 /* 2143 */ {0x4, 0x05, 0x00},
300 /* was 5 (Image Type ? ) */
301 /* 2146 */ {0x4, 0x00, 0x01},
302
303 /* 2149 */ {0x6, 0x3f, 0x01},
304
305 /* 2152 */ {0x4, 0x00, 0x04},
306 /* 2155 */ {0x4, 0x00, 0x05},
307 /* 2158 */ {0x4, 0x40, 0x06},
308 /* 2161 */ {0x4, 0x40, 0x07},
309
310 /* 2164 */ {0x6, 0x1c, 0x17},
311 /* 2167 */ {0x6, 0xe2, 0x19},
312 /* 2170 */ {0x6, 0x1c, 0x1b},
313 /* 2173 */ {0x6, 0xe2, 0x1d},
314 /* 2176 */ {0x6, 0xaa, 0x1f},
315 /* 2179 */ {0x6, 0x70, 0x20},
316
317 /* 2182 */ {0x5, 0x01, 0x10},
318 /* 2185 */ {0x5, 0x00, 0x11},
319 /* 2188 */ {0x5, 0x01, 0x00},
320 /* 2191 */ {0x5, 0x05, 0x01},
321 /* 2194 */ {0x5, 0x00, 0xc1},
322 /* */
323 /* 2197 */ {0x5, 0x00, 0xc2},
324 /* 2200 */ {0x5, 0x00, 0xca},
325
326 /* 2203 */ {0x6, 0x70, 0x51},
327 /* 2206 */ {0x6, 0xbe, 0x53},
328 {}
329};
330
331/*
332 Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
333 * SPCA505b chip based cameras initialization data
334 *
335 */
336/* jfm */
337#define initial_brightness 0x7f /* 0x0(white)-0xff(black) */
338/* #define initial_brightness 0x0 //0x0(white)-0xff(black) */
339/*
340 * Data to initialize a SPCA505. Common to the CCD and external modes
341 */
342static const __u16 spca505b_init_data[][3] = {
343/* start */
344 {0x02, 0x00, 0x00}, /* init */
345 {0x02, 0x00, 0x01},
346 {0x02, 0x00, 0x02},
347 {0x02, 0x00, 0x03},
348 {0x02, 0x00, 0x04},
349 {0x02, 0x00, 0x05},
350 {0x02, 0x00, 0x06},
351 {0x02, 0x00, 0x07},
352 {0x02, 0x00, 0x08},
353 {0x02, 0x00, 0x09},
354 {0x03, 0x00, 0x00},
355 {0x03, 0x00, 0x01},
356 {0x03, 0x00, 0x02},
357 {0x03, 0x00, 0x03},
358 {0x03, 0x00, 0x04},
359 {0x03, 0x00, 0x05},
360 {0x03, 0x00, 0x06},
361 {0x04, 0x00, 0x00},
362 {0x04, 0x00, 0x02},
363 {0x04, 0x00, 0x04},
364 {0x04, 0x00, 0x05},
365 {0x04, 0x00, 0x06},
366 {0x04, 0x00, 0x07},
367 {0x04, 0x00, 0x08},
368 {0x04, 0x00, 0x09},
369 {0x04, 0x00, 0x0a},
370 {0x04, 0x00, 0x0b},
371 {0x04, 0x00, 0x0c},
372 {0x07, 0x00, 0x00},
373 {0x07, 0x00, 0x03},
374 {0x08, 0x00, 0x00},
375 {0x08, 0x00, 0x01},
376 {0x08, 0x00, 0x02},
377 {0x00, 0x01, 0x00},
378 {0x00, 0x01, 0x01},
379 {0x00, 0x01, 0x34},
380 {0x00, 0x01, 0x35},
381 {0x06, 0x18, 0x08},
382 {0x06, 0xfc, 0x09},
383 {0x06, 0xfc, 0x0a},
384 {0x06, 0xfc, 0x0b},
385 {0x06, 0x18, 0x0c},
386 {0x06, 0xfc, 0x0d},
387 {0x06, 0xfc, 0x0e},
388 {0x06, 0xfc, 0x0f},
389 {0x06, 0x18, 0x10},
390 {0x06, 0xfe, 0x12},
391 {0x06, 0x00, 0x11},
392 {0x06, 0x00, 0x14},
393 {0x06, 0x00, 0x13},
394 {0x06, 0x28, 0x51},
395 {0x06, 0xff, 0x53},
396 {0x02, 0x00, 0x08},
397
398 {0x03, 0x00, 0x03},
399 {0x03, 0x10, 0x03},
400 {}
401};
402
403/*
404 * Data to initialize the camera using the internal CCD
405 */
406static const __u16 spca505b_open_data_ccd[][3] = {
407
408/* {0x02,0x00,0x00}, */
409 {0x03, 0x04, 0x01}, /* rst */
410 {0x03, 0x00, 0x01},
411 {0x03, 0x00, 0x00},
412 {0x03, 0x21, 0x00},
413 {0x03, 0x00, 0x04},
414 {0x03, 0x00, 0x03},
415 {0x03, 0x18, 0x03},
416 {0x03, 0x08, 0x01},
417 {0x03, 0x1c, 0x03},
418 {0x03, 0x5c, 0x03},
419 {0x03, 0x5c, 0x03},
420 {0x03, 0x18, 0x01},
421
422/* same as 505 */
423 {0x04, 0x10, 0x01},
424 {0x04, 0x00, 0x04},
425 {0x04, 0x00, 0x05},
426 {0x04, 0x20, 0x06},
427 {0x04, 0x20, 0x07},
428
429 {0x08, 0x0a, 0x00},
430
431 {0x05, 0x00, 0x10},
432 {0x05, 0x00, 0x11},
433 {0x05, 0x00, 0x12},
434 {0x05, 0x6f, 0x00},
435 {0x05, initial_brightness >> 6, 0x00},
436 {0x05, initial_brightness << 2, 0x01},
437 {0x05, 0x00, 0x02},
438 {0x05, 0x01, 0x03},
439 {0x05, 0x00, 0x04},
440 {0x05, 0x03, 0x05},
441 {0x05, 0xe0, 0x06},
442 {0x05, 0x20, 0x07},
443 {0x05, 0xa0, 0x08},
444 {0x05, 0x00, 0x12},
445 {0x05, 0x02, 0x0f},
446 {0x05, 128, 0x14}, /* max exposure off (0=on) */
447 {0x05, 0x01, 0xb0},
448 {0x05, 0x01, 0xbf},
449 {0x03, 0x02, 0x06},
450 {0x05, 0x10, 0x46},
451 {0x05, 0x08, 0x4a},
452
453 {0x06, 0x00, 0x01},
454 {0x06, 0x10, 0x02},
455 {0x06, 0x64, 0x07},
456 {0x06, 0x18, 0x08},
457 {0x06, 0xfc, 0x09},
458 {0x06, 0xfc, 0x0a},
459 {0x06, 0xfc, 0x0b},
460 {0x04, 0x00, 0x01},
461 {0x06, 0x18, 0x0c},
462 {0x06, 0xfc, 0x0d},
463 {0x06, 0xfc, 0x0e},
464 {0x06, 0xfc, 0x0f},
465 {0x06, 0x11, 0x10}, /* contrast */
466 {0x06, 0x00, 0x11},
467 {0x06, 0xfe, 0x12},
468 {0x06, 0x00, 0x13},
469 {0x06, 0x00, 0x14},
470 {0x06, 0x9d, 0x51},
471 {0x06, 0x40, 0x52},
472 {0x06, 0x7c, 0x53},
473 {0x06, 0x40, 0x54},
474 {0x06, 0x02, 0x57},
475 {0x06, 0x03, 0x58},
476 {0x06, 0x15, 0x59},
477 {0x06, 0x05, 0x5a},
478 {0x06, 0x03, 0x56},
479 {0x06, 0x02, 0x3f},
480 {0x06, 0x00, 0x40},
481 {0x06, 0x39, 0x41},
482 {0x06, 0x69, 0x42},
483 {0x06, 0x87, 0x43},
484 {0x06, 0x9e, 0x44},
485 {0x06, 0xb1, 0x45},
486 {0x06, 0xbf, 0x46},
487 {0x06, 0xcc, 0x47},
488 {0x06, 0xd5, 0x48},
489 {0x06, 0xdd, 0x49},
490 {0x06, 0xe3, 0x4a},
491 {0x06, 0xe8, 0x4b},
492 {0x06, 0xed, 0x4c},
493 {0x06, 0xf2, 0x4d},
494 {0x06, 0xf7, 0x4e},
495 {0x06, 0xfc, 0x4f},
496 {0x06, 0xff, 0x50},
497
498 {0x05, 0x01, 0xc0},
499 {0x05, 0x10, 0xcb},
500 {0x05, 0x40, 0xc1},
501 {0x05, 0x04, 0xc2},
502 {0x05, 0x00, 0xca},
503 {0x05, 0x40, 0xc1},
504 {0x05, 0x09, 0xc2},
505 {0x05, 0x00, 0xca},
506 {0x05, 0xc0, 0xc1},
507 {0x05, 0x09, 0xc2},
508 {0x05, 0x00, 0xca},
509 {0x05, 0x40, 0xc1},
510 {0x05, 0x59, 0xc2},
511 {0x05, 0x00, 0xca},
512 {0x04, 0x00, 0x01},
513 {0x05, 0x80, 0xc1},
514 {0x05, 0xec, 0xc2},
515 {0x05, 0x0, 0xca},
516
517 {0x06, 0x02, 0x57},
518 {0x06, 0x01, 0x58},
519 {0x06, 0x15, 0x59},
520 {0x06, 0x0a, 0x5a},
521 {0x06, 0x01, 0x57},
522 {0x06, 0x8a, 0x03},
523 {0x06, 0x0a, 0x6c},
524 {0x06, 0x30, 0x01},
525 {0x06, 0x20, 0x02},
526 {0x06, 0x00, 0x03},
527
528 {0x05, 0x8c, 0x25},
529
530 {0x06, 0x4d, 0x51}, /* maybe saturation (4d) */
531 {0x06, 0x84, 0x53}, /* making green (84) */
532 {0x06, 0x00, 0x57}, /* sharpness (1) */
533 {0x06, 0x18, 0x08},
534 {0x06, 0xfc, 0x09},
535 {0x06, 0xfc, 0x0a},
536 {0x06, 0xfc, 0x0b},
537 {0x06, 0x18, 0x0c}, /* maybe hue (18) */
538 {0x06, 0xfc, 0x0d},
539 {0x06, 0xfc, 0x0e},
540 {0x06, 0xfc, 0x0f},
541 {0x06, 0x18, 0x10}, /* maybe contrast (18) */
542
543 {0x05, 0x01, 0x02},
544
545 {0x04, 0x00, 0x08}, /* compression */
546 {0x04, 0x12, 0x09},
547 {0x04, 0x21, 0x0a},
548 {0x04, 0x10, 0x0b},
549 {0x04, 0x21, 0x0c},
550 {0x04, 0x1d, 0x00}, /* imagetype (1d) */
551 {0x04, 0x41, 0x01}, /* hardware snapcontrol */
552
553 {0x04, 0x00, 0x04},
554 {0x04, 0x00, 0x05},
555 {0x04, 0x10, 0x06},
556 {0x04, 0x10, 0x07},
557 {0x04, 0x40, 0x06},
558 {0x04, 0x40, 0x07},
559 {0x04, 0x00, 0x04},
560 {0x04, 0x00, 0x05},
561
562 {0x06, 0x1c, 0x17},
563 {0x06, 0xe2, 0x19},
564 {0x06, 0x1c, 0x1b},
565 {0x06, 0xe2, 0x1d},
566 {0x06, 0x5f, 0x1f},
567 {0x06, 0x32, 0x20},
568
569 {0x05, initial_brightness >> 6, 0x00},
570 {0x05, initial_brightness << 2, 0x01},
571 {0x05, 0x06, 0xc1},
572 {0x05, 0x58, 0xc2},
573 {0x05, 0x0, 0xca},
574 {0x05, 0x0, 0x11},
575 {}
576};
577
578static int reg_write(struct usb_device *dev,
579 __u16 reg, __u16 index, __u16 value)
580{
581 int ret;
582
583 ret = usb_control_msg(dev,
584 usb_sndctrlpipe(dev, 0),
585 reg,
586 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
587 value, index, NULL, 0, 500);
588 PDEBUG(D_PACK, "reg write: 0x%02x,0x%02x:0x%02x, 0x%x",
589 reg, index, value, ret);
590 if (ret < 0)
591 PDEBUG(D_ERR, "reg write: error %d", ret);
592 return ret;
593}
594
595/* returns: negative is error, pos or zero is data */
596static int reg_read(struct gspca_dev *gspca_dev,
597 __u16 reg, /* bRequest */
598 __u16 index, /* wIndex */
599 __u16 length) /* wLength (1 or 2 only) */
600{
601 int ret;
602
603 gspca_dev->usb_buf[1] = 0;
604 ret = usb_control_msg(gspca_dev->dev,
605 usb_rcvctrlpipe(gspca_dev->dev, 0),
606 reg,
607 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
608 (__u16) 0, /* value */
609 (__u16) index,
610 gspca_dev->usb_buf, length,
611 500); /* timeout */
612 if (ret < 0) {
613 PDEBUG(D_ERR, "reg_read err %d", ret);
614 return -1;
615 }
616 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
617}
618
619static int write_vector(struct gspca_dev *gspca_dev,
620 const __u16 data[][3])
621{
622 struct usb_device *dev = gspca_dev->dev;
623 int ret, i = 0;
624
625 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
626 ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
627 if (ret < 0) {
628 PDEBUG(D_ERR,
629 "Register write failed for 0x%x,0x%x,0x%x",
630 data[i][0], data[i][1], data[i][2]);
631 return ret;
632 }
633 i++;
634 }
635 return 0;
636}
637
638/* this function is called at probe time */
639static int sd_config(struct gspca_dev *gspca_dev,
640 const struct usb_device_id *id)
641{
642 struct sd *sd = (struct sd *) gspca_dev;
643 struct cam *cam;
644 __u16 vendor;
645 __u16 product;
646
647 vendor = id->idVendor;
648 product = id->idProduct;
649 switch (vendor) {
650 case 0x041e: /* Creative cameras */
651/* switch (product) { */
652/* case 0x401d: * here505b */
653 sd->subtype = Nxultra;
654/* break; */
655/* } */
656 break;
657 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
658/* switch (product) { */
659/* case 0x0430: */
660/* fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
661 sd->subtype = IntelPCCameraPro;
662/* break; */
663/* } */
664 break;
665 }
666
667 cam = &gspca_dev->cam;
668 cam->dev_name = (char *) id->driver_info;
669 cam->epaddr = 0x01;
670 cam->cam_mode = vga_mode;
671 if (sd->subtype != IntelPCCameraPro)
672 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
673 else /* no 640x480 for IntelPCCameraPro */
674 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0] - 1;
675 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
676
677 if (sd->subtype == Nxultra) {
678 if (write_vector(gspca_dev, spca505b_init_data))
679 return -EIO;
680 } else {
681 if (write_vector(gspca_dev, spca505_init_data))
682 return -EIO;
683 }
684 return 0;
685}
686
687/* this function is called at open time */
688static int sd_open(struct gspca_dev *gspca_dev)
689{
690 struct sd *sd = (struct sd *) gspca_dev;
691 int ret;
692
693 PDEBUG(D_STREAM, "Initializing SPCA505");
694 if (sd->subtype == Nxultra)
695 write_vector(gspca_dev, spca505b_open_data_ccd);
696 else
697 write_vector(gspca_dev, spca505_open_data_ccd);
698 ret = reg_read(gspca_dev, 6, 0x16, 2);
699
700 if (ret < 0) {
701 PDEBUG(D_ERR|D_STREAM,
702 "register read failed for after vector read err = %d",
703 ret);
704 return -EIO;
705 }
706 PDEBUG(D_STREAM,
707 "After vector read returns : 0x%x should be 0x0101",
708 ret & 0xffff);
709
710 ret = reg_write(gspca_dev->dev, 6, 0x16, 0x0a);
711 if (ret < 0) {
712 PDEBUG(D_ERR, "register write failed for (6,0xa,0x16) err=%d",
713 ret);
714 return -EIO;
715 }
716 reg_write(gspca_dev->dev, 5, 0xc2, 18);
717 return 0;
718}
719
720static void sd_start(struct gspca_dev *gspca_dev)
721{
722 struct usb_device *dev = gspca_dev->dev;
723 int ret;
724
725 /* necessary because without it we can see stream
726 * only once after loading module */
727 /* stopping usb registers Tomasz change */
728 reg_write(dev, 0x02, 0x0, 0x0);
729 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
730 case 0:
731 reg_write(dev, 0x04, 0x00, 0x00);
732 reg_write(dev, 0x04, 0x06, 0x10);
733 reg_write(dev, 0x04, 0x07, 0x10);
734 break;
735 case 1:
736 reg_write(dev, 0x04, 0x00, 0x01);
737 reg_write(dev, 0x04, 0x06, 0x1a);
738 reg_write(dev, 0x04, 0x07, 0x1a);
739 break;
740 case 2:
741 reg_write(dev, 0x04, 0x00, 0x02);
742 reg_write(dev, 0x04, 0x06, 0x1c);
743 reg_write(dev, 0x04, 0x07, 0x1d);
744 break;
745 case 4:
746 reg_write(dev, 0x04, 0x00, 0x04);
747 reg_write(dev, 0x04, 0x06, 0x34);
748 reg_write(dev, 0x04, 0x07, 0x34);
749 break;
750 default:
751/* case 5: */
752 reg_write(dev, 0x04, 0x00, 0x05);
753 reg_write(dev, 0x04, 0x06, 0x40);
754 reg_write(dev, 0x04, 0x07, 0x40);
755 break;
756 }
757/* Enable ISO packet machine - should we do this here or in ISOC init ? */
758 ret = reg_write(dev, SPCA50X_REG_USB,
759 SPCA50X_USB_CTRL,
760 SPCA50X_CUSB_ENABLE);
761
762/* reg_write(dev, 0x5, 0x0, 0x0); */
763/* reg_write(dev, 0x5, 0x0, 0x1); */
764/* reg_write(dev, 0x5, 0x11, 0x2); */
765}
766
767static void sd_stopN(struct gspca_dev *gspca_dev)
768{
769 /* Disable ISO packet machine */
770 reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
771}
772
773static void sd_stop0(struct gspca_dev *gspca_dev)
774{
775}
776
777/* this function is called at close time */
778static void sd_close(struct gspca_dev *gspca_dev)
779{
780 /* This maybe reset or power control */
781 reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
782 reg_write(gspca_dev->dev, 0x03, 0x01, 0x0);
783 reg_write(gspca_dev->dev, 0x03, 0x00, 0x1);
784 reg_write(gspca_dev->dev, 0x05, 0x10, 0x1);
785 reg_write(gspca_dev->dev, 0x05, 0x11, 0xf);
786}
787
788/* convert YYUV per line to YUYV (YUV 4:2:2) */
789static void yyuv_decode(unsigned char *out,
790 unsigned char *in,
791 int width,
792 int height)
793{
794 unsigned char *Ui, *Vi, *yi, *yi1;
795 unsigned char *out1;
796 int i, j;
797
798 yi = in;
799 for (i = height / 2; --i >= 0; ) {
800 out1 = out + width * 2; /* next line */
801 yi1 = yi + width;
802 Ui = yi1 + width;
803 Vi = Ui + width / 2;
804 for (j = width / 2; --j >= 0; ) {
805 *out++ = 128 + *yi++;
806 *out++ = 128 + *Ui;
807 *out++ = 128 + *yi++;
808 *out++ = 128 + *Vi;
809
810 *out1++ = 128 + *yi1++;
811 *out1++ = 128 + *Ui++;
812 *out1++ = 128 + *yi1++;
813 *out1++ = 128 + *Vi++;
814 }
815 yi += width * 2;
816 out = out1;
817 }
818}
819
820static void sd_pkt_scan(struct gspca_dev *gspca_dev,
821 struct gspca_frame *frame, /* target */
822 __u8 *data, /* isoc packet */
823 int len) /* iso packet length */
824{
825 struct sd *sd = (struct sd *) gspca_dev;
826
827 switch (data[0]) {
828 case 0: /* start of frame */
829 if (gspca_dev->last_packet_type == FIRST_PACKET) {
830 yyuv_decode(sd->tmpbuf2, sd->tmpbuf,
831 gspca_dev->width,
832 gspca_dev->height);
833 frame = gspca_frame_add(gspca_dev,
834 LAST_PACKET,
835 frame,
836 sd->tmpbuf2,
837 gspca_dev->width
838 * gspca_dev->height
839 * 2);
840 }
841 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
842 data, 0);
843 data += SPCA50X_OFFSET_DATA;
844 len -= SPCA50X_OFFSET_DATA;
845 if (len > 0)
846 memcpy(sd->tmpbuf, data, len);
847 else
848 len = 0;
849 sd->buflen = len;
850 return;
851 case 0xff: /* drop */
852/* gspca_dev->last_packet_type = DISCARD_PACKET; */
853 return;
854 }
855 data += 1;
856 len -= 1;
857 memcpy(&sd->tmpbuf[sd->buflen], data, len);
858 sd->buflen += len;
859}
860
861static void setbrightness(struct gspca_dev *gspca_dev)
862{
863 struct sd *sd = (struct sd *) gspca_dev;
864
865 __u8 brightness = sd->brightness;
866 reg_write(gspca_dev->dev, 5, 0x00, (255 - brightness) >> 6);
867 reg_write(gspca_dev->dev, 5, 0x01, (255 - brightness) << 2);
868
869}
870static void getbrightness(struct gspca_dev *gspca_dev)
871{
872 struct sd *sd = (struct sd *) gspca_dev;
873
874 sd->brightness = 255
875 - ((reg_read(gspca_dev, 5, 0x01, 1) >> 2)
876 + (reg_read(gspca_dev, 5, 0x0, 1) << 6));
877}
878
879static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
880{
881 struct sd *sd = (struct sd *) gspca_dev;
882
883 sd->brightness = val;
884 if (gspca_dev->streaming)
885 setbrightness(gspca_dev);
886 return 0;
887}
888
889static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
890{
891 struct sd *sd = (struct sd *) gspca_dev;
892
893 getbrightness(gspca_dev);
894 *val = sd->brightness;
895 return 0;
896}
897
898/* sub-driver description */
899static const struct sd_desc sd_desc = {
900 .name = MODULE_NAME,
901 .ctrls = sd_ctrls,
902 .nctrls = ARRAY_SIZE(sd_ctrls),
903 .config = sd_config,
904 .open = sd_open,
905 .start = sd_start,
906 .stopN = sd_stopN,
907 .stop0 = sd_stop0,
908 .close = sd_close,
909 .pkt_scan = sd_pkt_scan,
910};
911
912/* -- module initialisation -- */
913#define DVNM(name) .driver_info = (kernel_ulong_t) name
914static const __devinitdata struct usb_device_id device_table[] = {
915 {USB_DEVICE(0x041e, 0x401d), DVNM("Creative Webcam NX ULTRA")},
916 {USB_DEVICE(0x0733, 0x0430), DVNM("Intel PC Camera Pro")},
917 {}
918};
919MODULE_DEVICE_TABLE(usb, device_table);
920
921/* -- device connect -- */
922static int sd_probe(struct usb_interface *intf,
923 const struct usb_device_id *id)
924{
925 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
926 THIS_MODULE);
927}
928
929static struct usb_driver sd_driver = {
930 .name = MODULE_NAME,
931 .id_table = device_table,
932 .probe = sd_probe,
933 .disconnect = gspca_disconnect,
934};
935
936/* -- module insert / remove -- */
937static int __init sd_mod_init(void)
938{
939 if (usb_register(&sd_driver) < 0)
940 return -1;
941 PDEBUG(D_PROBE, "v%s registered", version);
942 return 0;
943}
944static void __exit sd_mod_exit(void)
945{
946 usb_deregister(&sd_driver);
947 PDEBUG(D_PROBE, "deregistered");
948}
949
950module_init(sd_mod_init);
951module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
new file mode 100644
index 000000000000..143203c1fd9f
--- /dev/null
+++ b/drivers/media/video/gspca/spca506.c
@@ -0,0 +1,847 @@
1/*
2 * SPCA506 chip based cameras function
3 * M Xhaard 15/04/2004 based on different work Mark Taylor and others
4 * and my own snoopy file on a pv-321c donate by a german compagny
5 * "Firma Frank Gmbh" from Saarbruecken
6 *
7 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#define MODULE_NAME "spca506"
25
26#include "gspca.h"
27
28#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
29static const char version[] = "2.1.7";
30
31MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
32MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver");
33MODULE_LICENSE("GPL");
34
35/* specific webcam descriptor */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
39 int buflen;
40 __u8 tmpbuf[640 * 480 * 3]; /* YYUV per line */
41 __u8 tmpbuf2[640 * 480 * 2]; /* YUYV */
42
43 unsigned char brightness;
44 unsigned char contrast;
45 unsigned char colors;
46 unsigned char hue;
47 char norme;
48 char channel;
49};
50
51/* V4L2 controls supported by the driver */
52static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
54static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
55static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
56static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
57static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
58static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
59static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
60
61static struct ctrl sd_ctrls[] = {
62#define SD_BRIGHTNESS 0
63 {
64 {
65 .id = V4L2_CID_BRIGHTNESS,
66 .type = V4L2_CTRL_TYPE_INTEGER,
67 .name = "Brightness",
68 .minimum = 0,
69 .maximum = 0xff,
70 .step = 1,
71 .default_value = 0x80,
72 },
73 .set = sd_setbrightness,
74 .get = sd_getbrightness,
75 },
76#define SD_CONTRAST 1
77 {
78 {
79 .id = V4L2_CID_CONTRAST,
80 .type = V4L2_CTRL_TYPE_INTEGER,
81 .name = "Contrast",
82 .minimum = 0,
83 .maximum = 0xff,
84 .step = 1,
85 .default_value = 0x47,
86 },
87 .set = sd_setcontrast,
88 .get = sd_getcontrast,
89 },
90#define SD_COLOR 2
91 {
92 {
93 .id = V4L2_CID_SATURATION,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "Saturation",
96 .minimum = 0,
97 .maximum = 0xff,
98 .step = 1,
99 .default_value = 0x40,
100 },
101 .set = sd_setcolors,
102 .get = sd_getcolors,
103 },
104#define SD_HUE 3
105 {
106 {
107 .id = V4L2_CID_HUE,
108 .type = V4L2_CTRL_TYPE_INTEGER,
109 .name = "Hue",
110 .minimum = 0,
111 .maximum = 0xff,
112 .step = 1,
113 .default_value = 0,
114 },
115 .set = sd_sethue,
116 .get = sd_gethue,
117 },
118};
119
120static struct v4l2_pix_format vga_mode[] = {
121 {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
122 .bytesperline = 160 * 2,
123 .sizeimage = 160 * 120 * 2,
124 .colorspace = V4L2_COLORSPACE_SRGB,
125 .priv = 5},
126 {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
127 .bytesperline = 176 * 2,
128 .sizeimage = 176 * 144 * 2,
129 .colorspace = V4L2_COLORSPACE_SRGB,
130 .priv = 4},
131 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
132 .bytesperline = 320 * 2,
133 .sizeimage = 320 * 240 * 2,
134 .colorspace = V4L2_COLORSPACE_SRGB,
135 .priv = 2},
136 {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
137 .bytesperline = 352 * 2,
138 .sizeimage = 352 * 288 * 2,
139 .colorspace = V4L2_COLORSPACE_SRGB,
140 .priv = 1},
141 {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
142 .bytesperline = 640 * 2,
143 .sizeimage = 640 * 480 * 2,
144 .colorspace = V4L2_COLORSPACE_SRGB,
145 .priv = 0},
146};
147
148#define SPCA50X_OFFSET_DATA 10
149
150#define SAA7113_bright 0x0a /* defaults 0x80 */
151#define SAA7113_contrast 0x0b /* defaults 0x47 */
152#define SAA7113_saturation 0x0c /* defaults 0x40 */
153#define SAA7113_hue 0x0d /* defaults 0x00 */
154#define SAA7113_I2C_BASE_WRITE 0x4a
155
156/* read 'len' bytes to gspca_dev->usb_buf */
157static void reg_r(struct gspca_dev *gspca_dev,
158 __u16 req,
159 __u16 index,
160 __u16 length)
161{
162 usb_control_msg(gspca_dev->dev,
163 usb_rcvctrlpipe(gspca_dev->dev, 0),
164 req,
165 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
166 0, /* value */
167 index, gspca_dev->usb_buf, length,
168 500);
169}
170
171static void reg_w(struct usb_device *dev,
172 __u16 req,
173 __u16 value,
174 __u16 index)
175{
176 usb_control_msg(dev,
177 usb_sndctrlpipe(dev, 0),
178 req,
179 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
180 value, index,
181 NULL, 0, 500);
182}
183
184static void spca506_Initi2c(struct gspca_dev *gspca_dev)
185{
186 reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
187}
188
189static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,
190 __u16 reg)
191{
192 int retry = 60;
193
194 reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
195 reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);
196 while (retry--) {
197 reg_r(gspca_dev, 0x07, 0x0003, 2);
198 if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)
199 break;
200 }
201}
202
203static int spca506_ReadI2c(struct gspca_dev *gspca_dev, __u16 reg)
204{
205 int retry = 60;
206
207 reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
208 reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
209 reg_w(gspca_dev->dev, 0x07, 0x01, 0x0002);
210 while (--retry) {
211 reg_r(gspca_dev, 0x07, 0x0003, 2);
212 if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)
213 break;
214 }
215 if (retry == 0)
216 return -1;
217 reg_r(gspca_dev, 0x07, 0x0000, 1);
218 return gspca_dev->usb_buf[0];
219}
220
221static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,
222 __u16 norme,
223 __u16 channel)
224{
225 struct sd *sd = (struct sd *) gspca_dev;
226/* fixme: check if channel == 0..3 and 6..9 (8 values) */
227 __u8 setbit0 = 0x00;
228 __u8 setbit1 = 0x00;
229 __u8 videomask = 0x00;
230
231 PDEBUG(D_STREAM, "** Open Set Norme **");
232 spca506_Initi2c(gspca_dev);
233 /* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */
234 /* Composite channel bit1 -> 1 S-video bit 1 -> 0 */
235 /* and exclude SAA7113 reserved channel set default 0 otherwise */
236 if (norme & V4L2_STD_NTSC)
237 setbit0 = 0x01;
238 if (channel == 4 || channel == 5 || channel > 9)
239 channel = 0;
240 if (channel < 4)
241 setbit1 = 0x02;
242 videomask = (0x48 | setbit0 | setbit1);
243 reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);
244 spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);
245
246 if (norme & V4L2_STD_NTSC)
247 spca506_WriteI2c(gspca_dev, 0x33, 0x0e);
248 /* Chrominance Control NTSC N */
249 else if (norme & V4L2_STD_SECAM)
250 spca506_WriteI2c(gspca_dev, 0x53, 0x0e);
251 /* Chrominance Control SECAM */
252 else
253 spca506_WriteI2c(gspca_dev, 0x03, 0x0e);
254 /* Chrominance Control PAL BGHIV */
255
256 sd->norme = norme;
257 sd->channel = channel;
258 PDEBUG(D_STREAM, "Set Video Byte to 0x%2x", videomask);
259 PDEBUG(D_STREAM, "Set Norme: %08x Channel %d", norme, channel);
260}
261
262static void spca506_GetNormeInput(struct gspca_dev *gspca_dev,
263 __u16 *norme, __u16 *channel)
264{
265 struct sd *sd = (struct sd *) gspca_dev;
266
267 /* Read the register is not so good value change so
268 we use your own copy in spca50x struct */
269 *norme = sd->norme;
270 *channel = sd->channel;
271 PDEBUG(D_STREAM, "Get Norme: %d Channel %d", *norme, *channel);
272}
273
274static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,
275 __u16 xmult, __u16 ymult)
276{
277 struct usb_device *dev = gspca_dev->dev;
278
279 PDEBUG(D_STREAM, "** SetSize **");
280 reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);
281 /* Soft snap 0x40 Hard 0x41 */
282 reg_w(dev, 0x04, 0x41, 0x0001);
283 reg_w(dev, 0x04, 0x00, 0x0002);
284 /* reserved */
285 reg_w(dev, 0x04, 0x00, 0x0003);
286
287 /* reserved */
288 reg_w(dev, 0x04, 0x00, 0x0004);
289 /* reserved */
290 reg_w(dev, 0x04, 0x01, 0x0005);
291 /* reserced */
292 reg_w(dev, 0x04, xmult, 0x0006);
293 /* reserved */
294 reg_w(dev, 0x04, ymult, 0x0007);
295 /* compression 1 */
296 reg_w(dev, 0x04, 0x00, 0x0008);
297 /* T=64 -> 2 */
298 reg_w(dev, 0x04, 0x00, 0x0009);
299 /* threshold2D */
300 reg_w(dev, 0x04, 0x21, 0x000a);
301 /* quantization */
302 reg_w(dev, 0x04, 0x00, 0x000b);
303}
304
305/* this function is called at probe time */
306static int sd_config(struct gspca_dev *gspca_dev,
307 const struct usb_device_id *id)
308{
309 struct sd *sd = (struct sd *) gspca_dev;
310 struct cam *cam;
311
312 cam = &gspca_dev->cam;
313 cam->dev_name = (char *) id->driver_info;
314 cam->epaddr = 0x01;
315 cam->cam_mode = vga_mode;
316 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
317 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
318 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
319 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
320 sd->hue = sd_ctrls[SD_HUE].qctrl.default_value;
321 return 0;
322}
323
324/* this function is called at open time */
325static int sd_open(struct gspca_dev *gspca_dev)
326{
327 struct usb_device *dev = gspca_dev->dev;
328
329 reg_w(dev, 0x03, 0x00, 0x0004);
330 reg_w(dev, 0x03, 0xFF, 0x0003);
331 reg_w(dev, 0x03, 0x00, 0x0000);
332 reg_w(dev, 0x03, 0x1c, 0x0001);
333 reg_w(dev, 0x03, 0x18, 0x0001);
334 /* Init on PAL and composite input0 */
335 spca506_SetNormeInput(gspca_dev, 0, 0);
336 reg_w(dev, 0x03, 0x1c, 0x0001);
337 reg_w(dev, 0x03, 0x18, 0x0001);
338 reg_w(dev, 0x05, 0x00, 0x0000);
339 reg_w(dev, 0x05, 0xef, 0x0001);
340 reg_w(dev, 0x05, 0x00, 0x00c1);
341 reg_w(dev, 0x05, 0x00, 0x00c2);
342 reg_w(dev, 0x06, 0x18, 0x0002);
343 reg_w(dev, 0x06, 0xf5, 0x0011);
344 reg_w(dev, 0x06, 0x02, 0x0012);
345 reg_w(dev, 0x06, 0xfb, 0x0013);
346 reg_w(dev, 0x06, 0x00, 0x0014);
347 reg_w(dev, 0x06, 0xa4, 0x0051);
348 reg_w(dev, 0x06, 0x40, 0x0052);
349 reg_w(dev, 0x06, 0x71, 0x0053);
350 reg_w(dev, 0x06, 0x40, 0x0054);
351 /************************************************/
352 reg_w(dev, 0x03, 0x00, 0x0004);
353 reg_w(dev, 0x03, 0x00, 0x0003);
354 reg_w(dev, 0x03, 0x00, 0x0004);
355 reg_w(dev, 0x03, 0xFF, 0x0003);
356 reg_w(dev, 0x02, 0x00, 0x0000);
357 reg_w(dev, 0x03, 0x60, 0x0000);
358 reg_w(dev, 0x03, 0x18, 0x0001);
359 /* for a better reading mx :) */
360 /*sdca506_WriteI2c(value,register) */
361 spca506_Initi2c(gspca_dev);
362 spca506_WriteI2c(gspca_dev, 0x08, 0x01);
363 spca506_WriteI2c(gspca_dev, 0xc0, 0x02);
364 /* input composite video */
365 spca506_WriteI2c(gspca_dev, 0x33, 0x03);
366 spca506_WriteI2c(gspca_dev, 0x00, 0x04);
367 spca506_WriteI2c(gspca_dev, 0x00, 0x05);
368 spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
369 spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
370 spca506_WriteI2c(gspca_dev, 0x98, 0x08);
371 spca506_WriteI2c(gspca_dev, 0x03, 0x09);
372 spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
373 spca506_WriteI2c(gspca_dev, 0x47, 0x0b);
374 spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
375 spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
376 spca506_WriteI2c(gspca_dev, 0x03, 0x0e); /* Chroma Pal adjust */
377 spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
378 spca506_WriteI2c(gspca_dev, 0x00, 0x10);
379 spca506_WriteI2c(gspca_dev, 0x0c, 0x11);
380 spca506_WriteI2c(gspca_dev, 0xb8, 0x12);
381 spca506_WriteI2c(gspca_dev, 0x01, 0x13);
382 spca506_WriteI2c(gspca_dev, 0x00, 0x14);
383 spca506_WriteI2c(gspca_dev, 0x00, 0x15);
384 spca506_WriteI2c(gspca_dev, 0x00, 0x16);
385 spca506_WriteI2c(gspca_dev, 0x00, 0x17);
386 spca506_WriteI2c(gspca_dev, 0x00, 0x18);
387 spca506_WriteI2c(gspca_dev, 0x00, 0x19);
388 spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
389 spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
390 spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
391 spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
392 spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
393 spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
394 spca506_WriteI2c(gspca_dev, 0x02, 0x40);
395 spca506_WriteI2c(gspca_dev, 0xff, 0x41);
396 spca506_WriteI2c(gspca_dev, 0xff, 0x42);
397 spca506_WriteI2c(gspca_dev, 0xff, 0x43);
398 spca506_WriteI2c(gspca_dev, 0xff, 0x44);
399 spca506_WriteI2c(gspca_dev, 0xff, 0x45);
400 spca506_WriteI2c(gspca_dev, 0xff, 0x46);
401 spca506_WriteI2c(gspca_dev, 0xff, 0x47);
402 spca506_WriteI2c(gspca_dev, 0xff, 0x48);
403 spca506_WriteI2c(gspca_dev, 0xff, 0x49);
404 spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
405 spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
406 spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
407 spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
408 spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
409 spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
410 spca506_WriteI2c(gspca_dev, 0xff, 0x50);
411 spca506_WriteI2c(gspca_dev, 0xff, 0x51);
412 spca506_WriteI2c(gspca_dev, 0xff, 0x52);
413 spca506_WriteI2c(gspca_dev, 0xff, 0x53);
414 spca506_WriteI2c(gspca_dev, 0xff, 0x54);
415 spca506_WriteI2c(gspca_dev, 0xff, 0x55);
416 spca506_WriteI2c(gspca_dev, 0xff, 0x56);
417 spca506_WriteI2c(gspca_dev, 0xff, 0x57);
418 spca506_WriteI2c(gspca_dev, 0x00, 0x58);
419 spca506_WriteI2c(gspca_dev, 0x54, 0x59);
420 spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
421 spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
422 spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
423 spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
424 spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
425 spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
426 spca506_WriteI2c(gspca_dev, 0x00, 0x60);
427 spca506_WriteI2c(gspca_dev, 0x05, 0x61);
428 spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
429 PDEBUG(D_STREAM, "** Close Init *");
430 return 0;
431}
432
433static void sd_start(struct gspca_dev *gspca_dev)
434{
435 struct usb_device *dev = gspca_dev->dev;
436 __u16 norme;
437 __u16 channel;
438
439 /**************************************/
440 reg_w(dev, 0x03, 0x00, 0x0004);
441 reg_w(dev, 0x03, 0x00, 0x0003);
442 reg_w(dev, 0x03, 0x00, 0x0004);
443 reg_w(dev, 0x03, 0xFF, 0x0003);
444 reg_w(dev, 0x02, 0x00, 0x0000);
445 reg_w(dev, 0x03, 0x60, 0x0000);
446 reg_w(dev, 0x03, 0x18, 0x0001);
447
448 /*sdca506_WriteI2c(value,register) */
449 spca506_Initi2c(gspca_dev);
450 spca506_WriteI2c(gspca_dev, 0x08, 0x01); /* Increment Delay */
451/* spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */
452 spca506_WriteI2c(gspca_dev, 0x33, 0x03);
453 /* Analog Input Control 2 */
454 spca506_WriteI2c(gspca_dev, 0x00, 0x04);
455 /* Analog Input Control 3 */
456 spca506_WriteI2c(gspca_dev, 0x00, 0x05);
457 /* Analog Input Control 4 */
458 spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
459 /* Horizontal Sync Start 0xe9-0x0d */
460 spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
461 /* Horizontal Sync Stop 0x0d-0xf0 */
462
463 spca506_WriteI2c(gspca_dev, 0x98, 0x08); /* Sync Control */
464/* Defaults value */
465 spca506_WriteI2c(gspca_dev, 0x03, 0x09); /* Luminance Control */
466 spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
467 /* Luminance Brightness */
468 spca506_WriteI2c(gspca_dev, 0x47, 0x0b); /* Luminance Contrast */
469 spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
470 /* Chrominance Saturation */
471 spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
472 /* Chrominance Hue Control */
473 spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
474 /* Chrominance Gain Control */
475 /**************************************/
476 spca506_WriteI2c(gspca_dev, 0x00, 0x10);
477 /* Format/Delay Control */
478 spca506_WriteI2c(gspca_dev, 0x0c, 0x11); /* Output Control 1 */
479 spca506_WriteI2c(gspca_dev, 0xb8, 0x12); /* Output Control 2 */
480 spca506_WriteI2c(gspca_dev, 0x01, 0x13); /* Output Control 3 */
481 spca506_WriteI2c(gspca_dev, 0x00, 0x14); /* reserved */
482 spca506_WriteI2c(gspca_dev, 0x00, 0x15); /* VGATE START */
483 spca506_WriteI2c(gspca_dev, 0x00, 0x16); /* VGATE STOP */
484 spca506_WriteI2c(gspca_dev, 0x00, 0x17); /* VGATE Control (MSB) */
485 spca506_WriteI2c(gspca_dev, 0x00, 0x18);
486 spca506_WriteI2c(gspca_dev, 0x00, 0x19);
487 spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
488 spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
489 spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
490 spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
491 spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
492 spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
493 spca506_WriteI2c(gspca_dev, 0x02, 0x40);
494 spca506_WriteI2c(gspca_dev, 0xff, 0x41);
495 spca506_WriteI2c(gspca_dev, 0xff, 0x42);
496 spca506_WriteI2c(gspca_dev, 0xff, 0x43);
497 spca506_WriteI2c(gspca_dev, 0xff, 0x44);
498 spca506_WriteI2c(gspca_dev, 0xff, 0x45);
499 spca506_WriteI2c(gspca_dev, 0xff, 0x46);
500 spca506_WriteI2c(gspca_dev, 0xff, 0x47);
501 spca506_WriteI2c(gspca_dev, 0xff, 0x48);
502 spca506_WriteI2c(gspca_dev, 0xff, 0x49);
503 spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
504 spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
505 spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
506 spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
507 spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
508 spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
509 spca506_WriteI2c(gspca_dev, 0xff, 0x50);
510 spca506_WriteI2c(gspca_dev, 0xff, 0x51);
511 spca506_WriteI2c(gspca_dev, 0xff, 0x52);
512 spca506_WriteI2c(gspca_dev, 0xff, 0x53);
513 spca506_WriteI2c(gspca_dev, 0xff, 0x54);
514 spca506_WriteI2c(gspca_dev, 0xff, 0x55);
515 spca506_WriteI2c(gspca_dev, 0xff, 0x56);
516 spca506_WriteI2c(gspca_dev, 0xff, 0x57);
517 spca506_WriteI2c(gspca_dev, 0x00, 0x58);
518 spca506_WriteI2c(gspca_dev, 0x54, 0x59);
519 spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
520 spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
521 spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
522 spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
523 spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
524 spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
525 spca506_WriteI2c(gspca_dev, 0x00, 0x60);
526 spca506_WriteI2c(gspca_dev, 0x05, 0x61);
527 spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
528 /**************************************/
529 reg_w(dev, 0x05, 0x00, 0x0003);
530 reg_w(dev, 0x05, 0x00, 0x0004);
531 reg_w(dev, 0x03, 0x10, 0x0001);
532 reg_w(dev, 0x03, 0x78, 0x0000);
533 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
534 case 0:
535 spca506_Setsize(gspca_dev, 0, 0x10, 0x10);
536 break;
537 case 1:
538 spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);
539 break;
540 case 2:
541 spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);
542 break;
543 case 4:
544 spca506_Setsize(gspca_dev, 4, 0x34, 0x34);
545 break;
546 default:
547/* case 5: */
548 spca506_Setsize(gspca_dev, 5, 0x40, 0x40);
549 break;
550 }
551
552 /* compress setting and size */
553 /* set i2c luma */
554 reg_w(dev, 0x02, 0x01, 0x0000);
555 reg_w(dev, 0x03, 0x12, 0x0000);
556 reg_r(gspca_dev, 0x04, 0x0001, 2);
557 PDEBUG(D_STREAM, "webcam started");
558 spca506_GetNormeInput(gspca_dev, &norme, &channel);
559 spca506_SetNormeInput(gspca_dev, norme, channel);
560}
561
562static void sd_stopN(struct gspca_dev *gspca_dev)
563{
564 struct usb_device *dev = gspca_dev->dev;
565
566 reg_w(dev, 0x02, 0x00, 0x0000);
567 reg_w(dev, 0x03, 0x00, 0x0004);
568 reg_w(dev, 0x03, 0x00, 0x0003);
569}
570
571static void sd_stop0(struct gspca_dev *gspca_dev)
572{
573}
574
575static void sd_close(struct gspca_dev *gspca_dev)
576{
577}
578
579/* convert YYUV per line to YUYV (YUV 4:2:2) */
580static void yyuv_decode(unsigned char *out,
581 unsigned char *in,
582 int width,
583 int height)
584{
585 unsigned char *Ui, *Vi, *yi, *yi1;
586 unsigned char *out1;
587 int i, j;
588
589 yi = in;
590 for (i = height / 2; --i >= 0; ) {
591 out1 = out + width * 2; /* next line */
592 yi1 = yi + width;
593 Ui = yi1 + width;
594 Vi = Ui + width / 2;
595 for (j = width / 2; --j >= 0; ) {
596 *out++ = 128 + *yi++;
597 *out++ = 128 + *Ui;
598 *out++ = 128 + *yi++;
599 *out++ = 128 + *Vi;
600
601 *out1++ = 128 + *yi1++;
602 *out1++ = 128 + *Ui++;
603 *out1++ = 128 + *yi1++;
604 *out1++ = 128 + *Vi++;
605 }
606 yi += width * 2;
607 out = out1;
608 }
609}
610
611static void sd_pkt_scan(struct gspca_dev *gspca_dev,
612 struct gspca_frame *frame, /* target */
613 __u8 *data, /* isoc packet */
614 int len) /* iso packet length */
615{
616 struct sd *sd = (struct sd *) gspca_dev;
617
618 switch (data[0]) {
619 case 0: /* start of frame */
620 if (gspca_dev->last_packet_type == FIRST_PACKET) {
621 yyuv_decode(sd->tmpbuf2, sd->tmpbuf,
622 gspca_dev->width,
623 gspca_dev->height);
624 frame = gspca_frame_add(gspca_dev,
625 LAST_PACKET,
626 frame,
627 sd->tmpbuf2,
628 gspca_dev->width
629 * gspca_dev->height
630 * 2);
631 }
632 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
633 data, 0);
634 data += SPCA50X_OFFSET_DATA;
635 len -= SPCA50X_OFFSET_DATA;
636 if (len > 0)
637 memcpy(sd->tmpbuf, data, len);
638 else
639 len = 0;
640 sd->buflen = len;
641 return;
642 case 0xff: /* drop */
643/* gspca_dev->last_packet_type = DISCARD_PACKET; */
644 return;
645 }
646 data += 1;
647 len -= 1;
648 memcpy(&sd->tmpbuf[sd->buflen], data, len);
649 sd->buflen += len;
650}
651
652static void setbrightness(struct gspca_dev *gspca_dev)
653{
654 struct sd *sd = (struct sd *) gspca_dev;
655
656 spca506_Initi2c(gspca_dev);
657 spca506_WriteI2c(gspca_dev, sd->brightness, SAA7113_bright);
658 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
659}
660
661static void getbrightness(struct gspca_dev *gspca_dev)
662{
663 struct sd *sd = (struct sd *) gspca_dev;
664
665 sd->brightness = spca506_ReadI2c(gspca_dev, SAA7113_bright);
666}
667
668static void setcontrast(struct gspca_dev *gspca_dev)
669{
670 struct sd *sd = (struct sd *) gspca_dev;
671
672 spca506_Initi2c(gspca_dev);
673 spca506_WriteI2c(gspca_dev, sd->contrast, SAA7113_contrast);
674 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
675}
676
677static void getcontrast(struct gspca_dev *gspca_dev)
678{
679 struct sd *sd = (struct sd *) gspca_dev;
680
681 sd->contrast = spca506_ReadI2c(gspca_dev, SAA7113_contrast);
682}
683
684static void setcolors(struct gspca_dev *gspca_dev)
685{
686 struct sd *sd = (struct sd *) gspca_dev;
687
688 spca506_Initi2c(gspca_dev);
689 spca506_WriteI2c(gspca_dev, sd->colors, SAA7113_saturation);
690 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
691}
692
693static void getcolors(struct gspca_dev *gspca_dev)
694{
695 struct sd *sd = (struct sd *) gspca_dev;
696
697 sd->colors = spca506_ReadI2c(gspca_dev, SAA7113_saturation);
698}
699
700static void sethue(struct gspca_dev *gspca_dev)
701{
702 struct sd *sd = (struct sd *) gspca_dev;
703
704 spca506_Initi2c(gspca_dev);
705 spca506_WriteI2c(gspca_dev, sd->hue, SAA7113_hue);
706 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
707}
708
709static void gethue(struct gspca_dev *gspca_dev)
710{
711 struct sd *sd = (struct sd *) gspca_dev;
712
713 sd->hue = spca506_ReadI2c(gspca_dev, SAA7113_hue);
714}
715
716static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
717{
718 struct sd *sd = (struct sd *) gspca_dev;
719
720 sd->brightness = val;
721 if (gspca_dev->streaming)
722 setbrightness(gspca_dev);
723 return 0;
724}
725
726static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
727{
728 struct sd *sd = (struct sd *) gspca_dev;
729
730 getbrightness(gspca_dev);
731 *val = sd->brightness;
732 return 0;
733}
734
735static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
736{
737 struct sd *sd = (struct sd *) gspca_dev;
738
739 sd->contrast = val;
740 if (gspca_dev->streaming)
741 setcontrast(gspca_dev);
742 return 0;
743}
744
745static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
746{
747 struct sd *sd = (struct sd *) gspca_dev;
748
749 getcontrast(gspca_dev);
750 *val = sd->contrast;
751 return 0;
752}
753
754static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
755{
756 struct sd *sd = (struct sd *) gspca_dev;
757
758 sd->colors = val;
759 if (gspca_dev->streaming)
760 setcolors(gspca_dev);
761 return 0;
762}
763
764static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
765{
766 struct sd *sd = (struct sd *) gspca_dev;
767
768 getcolors(gspca_dev);
769 *val = sd->colors;
770 return 0;
771}
772
773static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
774{
775 struct sd *sd = (struct sd *) gspca_dev;
776
777 sd->hue = val;
778 if (gspca_dev->streaming)
779 sethue(gspca_dev);
780 return 0;
781}
782
783static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
784{
785 struct sd *sd = (struct sd *) gspca_dev;
786
787 gethue(gspca_dev);
788 *val = sd->hue;
789 return 0;
790}
791
792/* sub-driver description */
793static struct sd_desc sd_desc = {
794 .name = MODULE_NAME,
795 .ctrls = sd_ctrls,
796 .nctrls = ARRAY_SIZE(sd_ctrls),
797 .config = sd_config,
798 .open = sd_open,
799 .start = sd_start,
800 .stopN = sd_stopN,
801 .stop0 = sd_stop0,
802 .close = sd_close,
803 .pkt_scan = sd_pkt_scan,
804};
805
806/* -- module initialisation -- */
807#define DVNM(name) .driver_info = (kernel_ulong_t) name
808static __devinitdata struct usb_device_id device_table[] = {
809 {USB_DEVICE(0x06e1, 0xa190), DVNM("ADS Instant VCD")},
810/* {USB_DEVICE(0x0733, 0x0430), DVNM("UsbGrabber PV321c")}, */
811 {USB_DEVICE(0x0734, 0x043b), DVNM("3DeMon USB Capture aka")},
812 {USB_DEVICE(0x99fa, 0x8988), DVNM("Grandtec V.cap")},
813 {}
814};
815MODULE_DEVICE_TABLE(usb, device_table);
816
817/* -- device connect -- */
818static int sd_probe(struct usb_interface *intf,
819 const struct usb_device_id *id)
820{
821 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
822 THIS_MODULE);
823}
824
825static struct usb_driver sd_driver = {
826 .name = MODULE_NAME,
827 .id_table = device_table,
828 .probe = sd_probe,
829 .disconnect = gspca_disconnect,
830};
831
832/* -- module insert / remove -- */
833static int __init sd_mod_init(void)
834{
835 if (usb_register(&sd_driver) < 0)
836 return -1;
837 PDEBUG(D_PROBE, "v%s registered", version);
838 return 0;
839}
840static void __exit sd_mod_exit(void)
841{
842 usb_deregister(&sd_driver);
843 PDEBUG(D_PROBE, "deregistered");
844}
845
846module_init(sd_mod_init);
847module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
new file mode 100644
index 000000000000..d8cd93866a4a
--- /dev/null
+++ b/drivers/media/video/gspca/spca508.c
@@ -0,0 +1,1791 @@
1/*
2 * SPCA508 chip based cameras subdriver
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define MODULE_NAME "spca508"
22
23#include "gspca.h"
24
25#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
26static const char version[] = "2.1.7";
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* specific webcam descriptor */
33struct sd {
34 struct gspca_dev gspca_dev; /* !! must be the first item */
35
36 int buflen;
37 unsigned char tmpbuf[352 * 288 * 3 / 2]; /* YUVY per line */
38 unsigned char tmpbuf2[352 * 288 * 2]; /* YUYV */
39
40 unsigned char brightness;
41
42 char subtype;
43#define CreativeVista 0
44#define HamaUSBSightcam 1
45#define HamaUSBSightcam2 2
46#define IntelEasyPCCamera 3
47#define MicroInnovationIC200 4
48#define ViewQuestVQ110 5
49};
50
51/* V4L2 controls supported by the driver */
52static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
54
55static struct ctrl sd_ctrls[] = {
56 {
57 {
58 .id = V4L2_CID_BRIGHTNESS,
59 .type = V4L2_CTRL_TYPE_INTEGER,
60 .name = "Brightness",
61 .minimum = 0,
62 .maximum = 255,
63 .step = 1,
64#define BRIGHTNESS_DEF 128
65 .default_value = BRIGHTNESS_DEF,
66 },
67 .set = sd_setbrightness,
68 .get = sd_getbrightness,
69 },
70};
71
72static struct v4l2_pix_format sif_mode[] = {
73 {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
74 .bytesperline = 160 * 2,
75 .sizeimage = 160 * 120 * 2,
76 .colorspace = V4L2_COLORSPACE_SRGB,
77 .priv = 3},
78 {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
79 .bytesperline = 176 * 2,
80 .sizeimage = 176 * 144 * 2,
81 .colorspace = V4L2_COLORSPACE_SRGB,
82 .priv = 2},
83 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
84 .bytesperline = 320 * 2,
85 .sizeimage = 320 * 240 * 2,
86 .colorspace = V4L2_COLORSPACE_SRGB,
87 .priv = 1},
88 {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
89 .bytesperline = 352 * 2,
90 .sizeimage = 352 * 288 * 2,
91 .colorspace = V4L2_COLORSPACE_SRGB,
92 .priv = 0},
93};
94
95/* Frame packet header offsets for the spca508 */
96#define SPCA508_OFFSET_TYPE 1
97#define SPCA508_OFFSET_COMPRESS 2
98#define SPCA508_OFFSET_FRAMSEQ 8
99#define SPCA508_OFFSET_WIN1LUM 11
100#define SPCA508_OFFSET_DATA 37
101
102#define SPCA508_SNAPBIT 0x20
103#define SPCA508_SNAPCTRL 0x40
104/*************** I2c ****************/
105#define SPCA508_INDEX_I2C_BASE 0x8800
106
107/*
108 * Initialization data: this is the first set-up data written to the
109 * device (before the open data).
110 */
111static const __u16 spca508_init_data[][3] =
112#define IGN(x) /* nothing */
113{
114 /* line URB value, index */
115 /* 44274 1804 */ {0x0000, 0x870b},
116
117 /* 44299 1805 */ {0x0020, 0x8112},
118 /* Video drop enable, ISO streaming disable */
119 /* 44324 1806 */ {0x0003, 0x8111},
120 /* Reset compression & memory */
121 /* 44349 1807 */ {0x0000, 0x8110},
122 /* Disable all outputs */
123 /* 44372 1808 */ /* READ {0x0000, 0x8114} -> 0000: 00 */
124 /* 44398 1809 */ {0x0000, 0x8114},
125 /* SW GPIO data */
126 /* 44423 1810 */ {0x0008, 0x8110},
127 /* Enable charge pump output */
128 /* 44527 1811 */ {0x0002, 0x8116},
129 /* 200 kHz pump clock */
130 /* 44555 1812 */
131 /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */
132 /* 44590 1813 */ {0x0003, 0x8111},
133 /* Reset compression & memory */
134 /* 44615 1814 */ {0x0000, 0x8111},
135 /* Normal mode (not reset) */
136 /* 44640 1815 */ {0x0098, 0x8110},
137 /* Enable charge pump output, sync.serial,external 2x clock */
138 /* 44665 1816 */ {0x000d, 0x8114},
139 /* SW GPIO data */
140 /* 44690 1817 */ {0x0002, 0x8116},
141 /* 200 kHz pump clock */
142 /* 44715 1818 */ {0x0020, 0x8112},
143 /* Video drop enable, ISO streaming disable */
144/* --------------------------------------- */
145 /* 44740 1819 */ {0x000f, 0x8402},
146 /* memory bank */
147 /* 44765 1820 */ {0x0000, 0x8403},
148 /* ... address */
149/* --------------------------------------- */
150/* 0x88__ is Synchronous Serial Interface. */
151/* TBD: This table could be expressed more compactly */
152/* using spca508_write_i2c_vector(). */
153/* TBD: Should see if the values in spca50x_i2c_data */
154/* would work with the VQ110 instead of the values */
155/* below. */
156 /* 44790 1821 */ {0x00c0, 0x8804},
157 /* SSI slave addr */
158 /* 44815 1822 */ {0x0008, 0x8802},
159 /* 375 Khz SSI clock */
160 /* 44838 1823 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
161 /* 44862 1824 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
162 /* 44888 1825 */ {0x0008, 0x8802},
163 /* 375 Khz SSI clock */
164 /* 44913 1826 */ {0x0012, 0x8801},
165 /* SSI reg addr */
166 /* 44938 1827 */ {0x0080, 0x8800},
167 /* SSI data to write */
168 /* 44961 1828 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
169 /* 44985 1829 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
170 /* 45009 1830 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
171 /* 45035 1831 */ {0x0008, 0x8802},
172 /* 375 Khz SSI clock */
173 /* 45060 1832 */ {0x0012, 0x8801},
174 /* SSI reg addr */
175 /* 45085 1833 */ {0x0000, 0x8800},
176 /* SSI data to write */
177 /* 45108 1834 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
178 /* 45132 1835 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
179 /* 45156 1836 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
180 /* 45182 1837 */ {0x0008, 0x8802},
181 /* 375 Khz SSI clock */
182 /* 45207 1838 */ {0x0011, 0x8801},
183 /* SSI reg addr */
184 /* 45232 1839 */ {0x0040, 0x8800},
185 /* SSI data to write */
186 /* 45255 1840 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
187 /* 45279 1841 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
188 /* 45303 1842 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
189 /* 45329 1843 */ {0x0008, 0x8802},
190 /* 45354 1844 */ {0x0013, 0x8801},
191 /* 45379 1845 */ {0x0000, 0x8800},
192 /* 45402 1846 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
193 /* 45426 1847 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
194 /* 45450 1848 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
195 /* 45476 1849 */ {0x0008, 0x8802},
196 /* 45501 1850 */ {0x0014, 0x8801},
197 /* 45526 1851 */ {0x0000, 0x8800},
198 /* 45549 1852 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
199 /* 45573 1853 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
200 /* 45597 1854 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
201 /* 45623 1855 */ {0x0008, 0x8802},
202 /* 45648 1856 */ {0x0015, 0x8801},
203 /* 45673 1857 */ {0x0001, 0x8800},
204 /* 45696 1858 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
205 /* 45720 1859 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
206 /* 45744 1860 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
207 /* 45770 1861 */ {0x0008, 0x8802},
208 /* 45795 1862 */ {0x0016, 0x8801},
209 /* 45820 1863 */ {0x0003, 0x8800},
210 /* 45843 1864 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
211 /* 45867 1865 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
212 /* 45891 1866 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
213 /* 45917 1867 */ {0x0008, 0x8802},
214 /* 45942 1868 */ {0x0017, 0x8801},
215 /* 45967 1869 */ {0x0036, 0x8800},
216 /* 45990 1870 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
217 /* 46014 1871 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
218 /* 46038 1872 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
219 /* 46064 1873 */ {0x0008, 0x8802},
220 /* 46089 1874 */ {0x0018, 0x8801},
221 /* 46114 1875 */ {0x00ec, 0x8800},
222 /* 46137 1876 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
223 /* 46161 1877 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
224 /* 46185 1878 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
225 /* 46211 1879 */ {0x0008, 0x8802},
226 /* 46236 1880 */ {0x001a, 0x8801},
227 /* 46261 1881 */ {0x0094, 0x8800},
228 /* 46284 1882 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
229 /* 46308 1883 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
230 /* 46332 1884 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
231 /* 46358 1885 */ {0x0008, 0x8802},
232 /* 46383 1886 */ {0x001b, 0x8801},
233 /* 46408 1887 */ {0x0000, 0x8800},
234 /* 46431 1888 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
235 /* 46455 1889 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
236 /* 46479 1890 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
237 /* 46505 1891 */ {0x0008, 0x8802},
238 /* 46530 1892 */ {0x0027, 0x8801},
239 /* 46555 1893 */ {0x00a2, 0x8800},
240 /* 46578 1894 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
241 /* 46602 1895 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
242 /* 46626 1896 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
243 /* 46652 1897 */ {0x0008, 0x8802},
244 /* 46677 1898 */ {0x0028, 0x8801},
245 /* 46702 1899 */ {0x0040, 0x8800},
246 /* 46725 1900 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
247 /* 46749 1901 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
248 /* 46773 1902 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
249 /* 46799 1903 */ {0x0008, 0x8802},
250 /* 46824 1904 */ {0x002a, 0x8801},
251 /* 46849 1905 */ {0x0084, 0x8800},
252 /* 46872 1906 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
253 /* 46896 1907 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
254 /* 46920 1908 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
255 /* 46946 1909 */ {0x0008, 0x8802},
256 /* 46971 1910 */ {0x002b, 0x8801},
257 /* 46996 1911 */ {0x00a8, 0x8800},
258 /* 47019 1912 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
259 /* 47043 1913 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
260 /* 47067 1914 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
261 /* 47093 1915 */ {0x0008, 0x8802},
262 /* 47118 1916 */ {0x002c, 0x8801},
263 /* 47143 1917 */ {0x00fe, 0x8800},
264 /* 47166 1918 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
265 /* 47190 1919 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
266 /* 47214 1920 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
267 /* 47240 1921 */ {0x0008, 0x8802},
268 /* 47265 1922 */ {0x002d, 0x8801},
269 /* 47290 1923 */ {0x0003, 0x8800},
270 /* 47313 1924 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
271 /* 47337 1925 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
272 /* 47361 1926 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
273 /* 47387 1927 */ {0x0008, 0x8802},
274 /* 47412 1928 */ {0x0038, 0x8801},
275 /* 47437 1929 */ {0x0083, 0x8800},
276 /* 47460 1930 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
277 /* 47484 1931 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
278 /* 47508 1932 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
279 /* 47534 1933 */ {0x0008, 0x8802},
280 /* 47559 1934 */ {0x0033, 0x8801},
281 /* 47584 1935 */ {0x0081, 0x8800},
282 /* 47607 1936 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
283 /* 47631 1937 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
284 /* 47655 1938 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
285 /* 47681 1939 */ {0x0008, 0x8802},
286 /* 47706 1940 */ {0x0034, 0x8801},
287 /* 47731 1941 */ {0x004a, 0x8800},
288 /* 47754 1942 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
289 /* 47778 1943 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
290 /* 47802 1944 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
291 /* 47828 1945 */ {0x0008, 0x8802},
292 /* 47853 1946 */ {0x0039, 0x8801},
293 /* 47878 1947 */ {0x0000, 0x8800},
294 /* 47901 1948 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
295 /* 47925 1949 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
296 /* 47949 1950 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
297 /* 47975 1951 */ {0x0008, 0x8802},
298 /* 48000 1952 */ {0x0010, 0x8801},
299 /* 48025 1953 */ {0x00a8, 0x8800},
300 /* 48048 1954 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
301 /* 48072 1955 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
302 /* 48096 1956 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
303 /* 48122 1957 */ {0x0008, 0x8802},
304 /* 48147 1958 */ {0x0006, 0x8801},
305 /* 48172 1959 */ {0x0058, 0x8800},
306 /* 48195 1960 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
307 /* 48219 1961 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
308 /* 48243 1962 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
309 /* 48269 1963 */ {0x0008, 0x8802},
310 /* 48294 1964 */ {0x0000, 0x8801},
311 /* 48319 1965 */ {0x0004, 0x8800},
312 /* 48342 1966 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
313 /* 48366 1967 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
314 /* 48390 1968 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
315 /* 48416 1969 */ {0x0008, 0x8802},
316 /* 48441 1970 */ {0x0040, 0x8801},
317 /* 48466 1971 */ {0x0080, 0x8800},
318 /* 48489 1972 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
319 /* 48513 1973 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
320 /* 48537 1974 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
321 /* 48563 1975 */ {0x0008, 0x8802},
322 /* 48588 1976 */ {0x0041, 0x8801},
323 /* 48613 1977 */ {0x000c, 0x8800},
324 /* 48636 1978 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
325 /* 48660 1979 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
326 /* 48684 1980 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
327 /* 48710 1981 */ {0x0008, 0x8802},
328 /* 48735 1982 */ {0x0042, 0x8801},
329 /* 48760 1983 */ {0x000c, 0x8800},
330 /* 48783 1984 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
331 /* 48807 1985 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
332 /* 48831 1986 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
333 /* 48857 1987 */ {0x0008, 0x8802},
334 /* 48882 1988 */ {0x0043, 0x8801},
335 /* 48907 1989 */ {0x0028, 0x8800},
336 /* 48930 1990 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
337 /* 48954 1991 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
338 /* 48978 1992 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
339 /* 49004 1993 */ {0x0008, 0x8802},
340 /* 49029 1994 */ {0x0044, 0x8801},
341 /* 49054 1995 */ {0x0080, 0x8800},
342 /* 49077 1996 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
343 /* 49101 1997 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
344 /* 49125 1998 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
345 /* 49151 1999 */ {0x0008, 0x8802},
346 /* 49176 2000 */ {0x0045, 0x8801},
347 /* 49201 2001 */ {0x0020, 0x8800},
348 /* 49224 2002 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
349 /* 49248 2003 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
350 /* 49272 2004 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
351 /* 49298 2005 */ {0x0008, 0x8802},
352 /* 49323 2006 */ {0x0046, 0x8801},
353 /* 49348 2007 */ {0x0020, 0x8800},
354 /* 49371 2008 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
355 /* 49395 2009 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
356 /* 49419 2010 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
357 /* 49445 2011 */ {0x0008, 0x8802},
358 /* 49470 2012 */ {0x0047, 0x8801},
359 /* 49495 2013 */ {0x0080, 0x8800},
360 /* 49518 2014 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
361 /* 49542 2015 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
362 /* 49566 2016 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
363 /* 49592 2017 */ {0x0008, 0x8802},
364 /* 49617 2018 */ {0x0048, 0x8801},
365 /* 49642 2019 */ {0x004c, 0x8800},
366 /* 49665 2020 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
367 /* 49689 2021 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
368 /* 49713 2022 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
369 /* 49739 2023 */ {0x0008, 0x8802},
370 /* 49764 2024 */ {0x0049, 0x8801},
371 /* 49789 2025 */ {0x0084, 0x8800},
372 /* 49812 2026 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
373 /* 49836 2027 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
374 /* 49860 2028 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
375 /* 49886 2029 */ {0x0008, 0x8802},
376 /* 49911 2030 */ {0x004a, 0x8801},
377 /* 49936 2031 */ {0x0084, 0x8800},
378 /* 49959 2032 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
379 /* 49983 2033 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
380 /* 50007 2034 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
381 /* 50033 2035 */ {0x0008, 0x8802},
382 /* 50058 2036 */ {0x004b, 0x8801},
383 /* 50083 2037 */ {0x0084, 0x8800},
384 /* 50106 2038 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
385 /* --------------------------------------- */
386 /* 50132 2039 */ {0x0012, 0x8700},
387 /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
388 /* 50157 2040 */ {0x0000, 0x8701},
389 /* CKx1 clock delay adj */
390 /* 50182 2041 */ {0x0000, 0x8701},
391 /* CKx1 clock delay adj */
392 /* 50207 2042 */ {0x0001, 0x870c},
393 /* CKOx2 output */
394 /* --------------------------------------- */
395 /* 50232 2043 */ {0x0080, 0x8600},
396 /* Line memory read counter (L) */
397 /* 50257 2044 */ {0x0001, 0x8606},
398 /* reserved */
399 /* 50282 2045 */ {0x0064, 0x8607},
400 /* Line memory read counter (H) 0x6480=25,728 */
401 /* 50307 2046 */ {0x002a, 0x8601},
402 /* CDSP sharp interpolation mode,
403 * line sel for color sep, edge enhance enab */
404 /* 50332 2047 */ {0x0000, 0x8602},
405 /* optical black level for user settng = 0 */
406 /* 50357 2048 */ {0x0080, 0x8600},
407 /* Line memory read counter (L) */
408 /* 50382 2049 */ {0x000a, 0x8603},
409 /* optical black level calc mode: auto; optical black offset = 10 */
410 /* 50407 2050 */ {0x00df, 0x865b},
411 /* Horiz offset for valid pixels (L)=0xdf */
412 /* 50432 2051 */ {0x0012, 0x865c},
413 /* Vert offset for valid lines (L)=0x12 */
414
415/* The following two lines seem to be the "wrong" resolution. */
416/* But perhaps these indicate the actual size of the sensor */
417/* rather than the size of the current video mode. */
418 /* 50457 2052 */ {0x0058, 0x865d},
419 /* Horiz valid pixels (*4) (L) = 352 */
420 /* 50482 2053 */ {0x0048, 0x865e},
421 /* Vert valid lines (*4) (L) = 288 */
422
423 /* 50507 2054 */ {0x0015, 0x8608},
424 /* A11 Coef ... */
425 /* 50532 2055 */ {0x0030, 0x8609},
426 /* 50557 2056 */ {0x00fb, 0x860a},
427 /* 50582 2057 */ {0x003e, 0x860b},
428 /* 50607 2058 */ {0x00ce, 0x860c},
429 /* 50632 2059 */ {0x00f4, 0x860d},
430 /* 50657 2060 */ {0x00eb, 0x860e},
431 /* 50682 2061 */ {0x00dc, 0x860f},
432 /* 50707 2062 */ {0x0039, 0x8610},
433 /* 50732 2063 */ {0x0001, 0x8611},
434 /* R offset for white balance ... */
435 /* 50757 2064 */ {0x0000, 0x8612},
436 /* 50782 2065 */ {0x0001, 0x8613},
437 /* 50807 2066 */ {0x0000, 0x8614},
438 /* 50832 2067 */ {0x005b, 0x8651},
439 /* R gain for white balance ... */
440 /* 50857 2068 */ {0x0040, 0x8652},
441 /* 50882 2069 */ {0x0060, 0x8653},
442 /* 50907 2070 */ {0x0040, 0x8654},
443 /* 50932 2071 */ {0x0000, 0x8655},
444 /* 50957 2072 */ {0x0001, 0x863f},
445 /* Fixed gamma correction enable, USB control,
446 * lum filter disable, lum noise clip disable */
447 /* 50982 2073 */ {0x00a1, 0x8656},
448 /* Window1 size 256x256, Windows2 size 64x64,
449 * gamma look-up disable, new edge enhancement enable */
450 /* 51007 2074 */ {0x0018, 0x8657},
451 /* Edge gain high thresh */
452 /* 51032 2075 */ {0x0020, 0x8658},
453 /* Edge gain low thresh */
454 /* 51057 2076 */ {0x000a, 0x8659},
455 /* Edge bandwidth high threshold */
456 /* 51082 2077 */ {0x0005, 0x865a},
457 /* Edge bandwidth low threshold */
458 /* -------------------------------- */
459 /* 51107 2078 */ {0x0030, 0x8112},
460 /* Video drop enable, ISO streaming enable */
461 /* 51130 2079 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
462 /* 51154 2080 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
463 /* 51180 2081 */ {0xa908, 0x8802},
464 /* 51205 2082 */ {0x0034, 0x8801},
465 /* SSI reg addr */
466 /* 51230 2083 */ {0x00ca, 0x8800},
467 /* SSI data to write */
468 /* 51253 2084 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
469 /* 51277 2085 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
470 /* 51301 2086 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
471 /* 51327 2087 */ {0x1f08, 0x8802},
472 /* 51352 2088 */ {0x0006, 0x8801},
473 /* 51377 2089 */ {0x0080, 0x8800},
474 /* 51400 2090 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
475
476/* ----- Read back coefs we wrote earlier. */
477 /* 51424 2091 */ /* READ { 0, 0x0000, 0x8608 } -> 0000: 15 */
478 /* 51448 2092 */ /* READ { 0, 0x0000, 0x8609 } -> 0000: 30 */
479 /* 51472 2093 */ /* READ { 0, 0x0000, 0x860a } -> 0000: fb */
480 /* 51496 2094 */ /* READ { 0, 0x0000, 0x860b } -> 0000: 3e */
481 /* 51520 2095 */ /* READ { 0, 0x0000, 0x860c } -> 0000: ce */
482 /* 51544 2096 */ /* READ { 0, 0x0000, 0x860d } -> 0000: f4 */
483 /* 51568 2097 */ /* READ { 0, 0x0000, 0x860e } -> 0000: eb */
484 /* 51592 2098 */ /* READ { 0, 0x0000, 0x860f } -> 0000: dc */
485 /* 51616 2099 */ /* READ { 0, 0x0000, 0x8610 } -> 0000: 39 */
486 /* 51640 2100 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
487 /* 51664 2101 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
488 /* 51690 2102 */ {0xb008, 0x8802},
489 /* 51715 2103 */ {0x0006, 0x8801},
490 /* 51740 2104 */ {0x007d, 0x8800},
491 /* 51763 2105 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
492
493
494 /* This chunk is seemingly redundant with */
495 /* earlier commands (A11 Coef...), but if I disable it, */
496 /* the image appears too dark. Maybe there was some kind of */
497 /* reset since the earlier commands, so this is necessary again. */
498 /* 51789 2106 */ {0x0015, 0x8608},
499 /* 51814 2107 */ {0x0030, 0x8609},
500 /* 51839 2108 */ {0xfffb, 0x860a},
501 /* 51864 2109 */ {0x003e, 0x860b},
502 /* 51889 2110 */ {0xffce, 0x860c},
503 /* 51914 2111 */ {0xfff4, 0x860d},
504 /* 51939 2112 */ {0xffeb, 0x860e},
505 /* 51964 2113 */ {0xffdc, 0x860f},
506 /* 51989 2114 */ {0x0039, 0x8610},
507 /* 52014 2115 */ {0x0018, 0x8657},
508
509 /* 52039 2116 */ {0x0000, 0x8508},
510 /* Disable compression. */
511 /* Previous line was:
512 * 52039 2116 * { 0, 0x0021, 0x8508 }, * Enable compression. */
513 /* 52064 2117 */ {0x0032, 0x850b},
514 /* compression stuff */
515 /* 52089 2118 */ {0x0003, 0x8509},
516 /* compression stuff */
517 /* 52114 2119 */ {0x0011, 0x850a},
518 /* compression stuff */
519 /* 52139 2120 */ {0x0021, 0x850d},
520 /* compression stuff */
521 /* 52164 2121 */ {0x0010, 0x850c},
522 /* compression stuff */
523 /* 52189 2122 */ {0x0003, 0x8500},
524 /* *** Video mode: 160x120 */
525 /* 52214 2123 */ {0x0001, 0x8501},
526 /* Hardware-dominated snap control */
527 /* 52239 2124 */ {0x0061, 0x8656},
528 /* Window1 size 128x128, Windows2 size 128x128,
529 * gamma look-up disable, new edge enhancement enable */
530 /* 52264 2125 */ {0x0018, 0x8617},
531 /* Window1 start X (*2) */
532 /* 52289 2126 */ {0x0008, 0x8618},
533 /* Window1 start Y (*2) */
534 /* 52314 2127 */ {0x0061, 0x8656},
535 /* Window1 size 128x128, Windows2 size 128x128,
536 * gamma look-up disable, new edge enhancement enable */
537 /* 52339 2128 */ {0x0058, 0x8619},
538 /* Window2 start X (*2) */
539 /* 52364 2129 */ {0x0008, 0x861a},
540 /* Window2 start Y (*2) */
541 /* 52389 2130 */ {0x00ff, 0x8615},
542 /* High lum thresh for white balance */
543 /* 52414 2131 */ {0x0000, 0x8616},
544 /* Low lum thresh for white balance */
545 /* 52439 2132 */ {0x0012, 0x8700},
546 /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
547 /* 52464 2133 */ {0x0012, 0x8700},
548 /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
549 /* 52487 2134 */ /* READ { 0, 0x0000, 0x8656 } -> 0000: 61 */
550 /* 52513 2135 */ {0x0028, 0x8802},
551 /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
552 /* 52536 2136 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
553 /* 52560 2137 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28 */
554 /* 52586 2138 */ {0x1f28, 0x8802},
555 /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
556 /* 52611 2139 */ {0x0010, 0x8801},
557 /* SSI reg addr */
558 /* 52636 2140 */ {0x003e, 0x8800},
559 /* SSI data to write */
560 /* 52659 2141 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
561 /* 52685 2142 */ {0x0028, 0x8802},
562 /* 52708 2143 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
563 /* 52732 2144 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28 */
564 /* 52758 2145 */ {0x1f28, 0x8802},
565 /* 52783 2146 */ {0x0000, 0x8801},
566 /* 52808 2147 */ {0x001f, 0x8800},
567 /* 52831 2148 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
568 /* 52857 2149 */ {0x0001, 0x8602},
569 /* optical black level for user settning = 1 */
570
571 /* Original: */
572 /* 52882 2150 */ {0x0023, 0x8700},
573 /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
574 /* 52907 2151 */ {0x000f, 0x8602},
575 /* optical black level for user settning = 15 */
576
577 /* 52932 2152 */ {0x0028, 0x8802},
578 /* 52955 2153 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
579 /* 52979 2154 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28 */
580 /* 53005 2155 */ {0x1f28, 0x8802},
581 /* 53030 2156 */ {0x0010, 0x8801},
582 /* 53055 2157 */ {0x007b, 0x8800},
583 /* 53078 2158 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
584 /* 53104 2159 */ {0x002f, 0x8651},
585 /* R gain for white balance ... */
586 /* 53129 2160 */ {0x0080, 0x8653},
587 /* 53152 2161 */ /* READ { 0, 0x0000, 0x8655 } -> 0000: 00 */
588 /* 53178 2162 */ {0x0000, 0x8655},
589
590 /* 53203 2163 */ {0x0030, 0x8112},
591 /* Video drop enable, ISO streaming enable */
592 /* 53228 2164 */ {0x0020, 0x8112},
593 /* Video drop enable, ISO streaming disable */
594 /* 53252 2165 */
595 /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
596 {}
597};
598
599
600/*
601 * Initialization data for Intel EasyPC Camera CS110
602 */
603static const __u16 spca508cs110_init_data[][3] = {
604 {0x0000, 0x870b}, /* Reset CTL3 */
605 {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
606 {0x0000, 0x8111}, /* Normal operation on reset */
607 {0x0090, 0x8110},
608 /* External Clock 2x & Synchronous Serial Interface Output */
609 {0x0020, 0x8112}, /* Video Drop packet enable */
610 {0x0000, 0x8114}, /* Software GPIO output data */
611 {0x0001, 0x8114},
612 {0x0001, 0x8114},
613 {0x0001, 0x8114},
614 {0x0003, 0x8114},
615
616 /* Initial sequence Synchronous Serial Interface */
617 {0x000f, 0x8402}, /* Memory bank Address */
618 {0x0000, 0x8403}, /* Memory bank Address */
619 {0x00ba, 0x8804}, /* SSI Slave address */
620 {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */
621 {0x0010, 0x8802}, /* 93.75kHz SSI Clock two DataByte */
622
623 {0x0001, 0x8801},
624 {0x000a, 0x8805},/* a - NWG: Dunno what this is about */
625 {0x0000, 0x8800},
626 {0x0010, 0x8802},
627
628 {0x0002, 0x8801},
629 {0x0000, 0x8805},
630 {0x0000, 0x8800},
631 {0x0010, 0x8802},
632
633 {0x0003, 0x8801},
634 {0x0027, 0x8805},
635 {0x0001, 0x8800},
636 {0x0010, 0x8802},
637
638 {0x0004, 0x8801},
639 {0x0065, 0x8805},
640 {0x0001, 0x8800},
641 {0x0010, 0x8802},
642
643 {0x0005, 0x8801},
644 {0x0003, 0x8805},
645 {0x0000, 0x8800},
646 {0x0010, 0x8802},
647
648 {0x0006, 0x8801},
649 {0x001c, 0x8805},
650 {0x0000, 0x8800},
651 {0x0010, 0x8802},
652
653 {0x0007, 0x8801},
654 {0x002a, 0x8805},
655 {0x0000, 0x8800},
656 {0x0010, 0x8802},
657
658 {0x0002, 0x8704}, /* External input CKIx1 */
659 {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */
660 {0x009a, 0x8600}, /* Line memory Read Counter (L) */
661 {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */
662 {0x0003, 0x865c}, /* 3 Vertical Offset for Valid Lines(L) */
663 {0x0058, 0x865d}, /* 58 Horizontal Valid Pixel Window(L) */
664
665 {0x0006, 0x8660}, /* Nibble data + input order */
666
667 {0x000a, 0x8602}, /* Optical black level set to 0x0a */
668/* 1945 */ {0x0000, 0x8603}, /* Optical black level Offset */
669
670/* 1962 * {0, 0x0000, 0x8611}, * 0 R Offset for white Balance */
671/* 1963 * {0, 0x0000, 0x8612}, * 1 Gr Offset for white Balance */
672/* 1964 * {0, 0x0000, 0x8613}, * 1f B Offset for white Balance */
673/* 1965 * {0, 0x0000, 0x8614}, * f0 Gb Offset for white Balance */
674
675 {0x0040, 0x8651}, /* 2b BLUE gain for white balance good at all 60 */
676 {0x0030, 0x8652}, /* 41 Gr Gain for white Balance (L) */
677 {0x0035, 0x8653}, /* 26 RED gain for white balance */
678 {0x0035, 0x8654}, /* 40Gb Gain for white Balance (L) */
679 {0x0041, 0x863f},
680 /* Fixed Gamma correction enabled (makes colours look better) */
681
682/* 2422 */ {0x0000, 0x8655},
683 /* High bits for white balance*****brightness control*** */
684 {}
685};
686
687static const __u16 spca508_sightcam_init_data[][3] = {
688/* This line seems to setup the frame/canvas */
689 /*368 */ {0x000f, 0x8402},
690
691/* Theese 6 lines are needed to startup the webcam */
692 /*398 */ {0x0090, 0x8110},
693 /*399 */ {0x0001, 0x8114},
694 /*400 */ {0x0001, 0x8114},
695 /*401 */ {0x0001, 0x8114},
696 /*402 */ {0x0003, 0x8114},
697 /*403 */ {0x0080, 0x8804},
698
699/* This part seems to make the pictures darker? (autobrightness?) */
700 /*436 */ {0x0001, 0x8801},
701 /*437 */ {0x0004, 0x8800},
702 /*439 */ {0x0003, 0x8801},
703 /*440 */ {0x00e0, 0x8800},
704 /*442 */ {0x0004, 0x8801},
705 /*443 */ {0x00b4, 0x8800},
706 /*445 */ {0x0005, 0x8801},
707 /*446 */ {0x0000, 0x8800},
708
709 /*448 */ {0x0006, 0x8801},
710 /*449 */ {0x00e0, 0x8800},
711 /*451 */ {0x0007, 0x8801},
712 /*452 */ {0x000c, 0x8800},
713
714/* This section is just needed, it probably
715 * does something like the previous section,
716 * but the cam won't start if it's not included.
717 */
718 /*484 */ {0x0014, 0x8801},
719 /*485 */ {0x0008, 0x8800},
720 /*487 */ {0x0015, 0x8801},
721 /*488 */ {0x0067, 0x8800},
722 /*490 */ {0x0016, 0x8801},
723 /*491 */ {0x0000, 0x8800},
724 /*493 */ {0x0017, 0x8801},
725 /*494 */ {0x0020, 0x8800},
726 /*496 */ {0x0018, 0x8801},
727 /*497 */ {0x0044, 0x8800},
728
729/* Makes the picture darker - and the
730 * cam won't start if not included
731 */
732 /*505 */ {0x001e, 0x8801},
733 /*506 */ {0x00ea, 0x8800},
734 /*508 */ {0x001f, 0x8801},
735 /*509 */ {0x0001, 0x8800},
736 /*511 */ {0x0003, 0x8801},
737 /*512 */ {0x00e0, 0x8800},
738
739/* seems to place the colors ontop of each other #1 */
740 /*517 */ {0x0006, 0x8704},
741 /*518 */ {0x0001, 0x870c},
742 /*519 */ {0x0016, 0x8600},
743 /*520 */ {0x0002, 0x8606},
744
745/* if not included the pictures becomes _very_ dark */
746 /*521 */ {0x0064, 0x8607},
747 /*522 */ {0x003a, 0x8601},
748 /*523 */ {0x0000, 0x8602},
749
750/* seems to place the colors ontop of each other #2 */
751 /*524 */ {0x0016, 0x8600},
752 /*525 */ {0x0018, 0x8617},
753 /*526 */ {0x0008, 0x8618},
754 /*527 */ {0x00a1, 0x8656},
755
756/* webcam won't start if not included */
757 /*528 */ {0x0007, 0x865b},
758 /*529 */ {0x0001, 0x865c},
759 /*530 */ {0x0058, 0x865d},
760 /*531 */ {0x0048, 0x865e},
761
762/* adjusts the colors */
763 /*541 */ {0x0049, 0x8651},
764 /*542 */ {0x0040, 0x8652},
765 /*543 */ {0x004c, 0x8653},
766 /*544 */ {0x0040, 0x8654},
767 {}
768};
769
770static const __u16 spca508_sightcam2_init_data[][3] = {
771/* 35 */ {0x0020, 0x8112},
772
773/* 36 */ {0x000f, 0x8402},
774/* 37 */ {0x0000, 0x8403},
775
776/* 38 */ {0x0008, 0x8201},
777/* 39 */ {0x0008, 0x8200},
778/* 40 */ {0x0001, 0x8200},
779/* 43 */ {0x0009, 0x8201},
780/* 44 */ {0x0008, 0x8200},
781/* 45 */ {0x0001, 0x8200},
782/* 48 */ {0x000a, 0x8201},
783/* 49 */ {0x0008, 0x8200},
784/* 50 */ {0x0001, 0x8200},
785/* 53 */ {0x000b, 0x8201},
786/* 54 */ {0x0008, 0x8200},
787/* 55 */ {0x0001, 0x8200},
788/* 58 */ {0x000c, 0x8201},
789/* 59 */ {0x0008, 0x8200},
790/* 60 */ {0x0001, 0x8200},
791/* 63 */ {0x000d, 0x8201},
792/* 64 */ {0x0008, 0x8200},
793/* 65 */ {0x0001, 0x8200},
794/* 68 */ {0x000e, 0x8201},
795/* 69 */ {0x0008, 0x8200},
796/* 70 */ {0x0001, 0x8200},
797/* 73 */ {0x0007, 0x8201},
798/* 74 */ {0x0008, 0x8200},
799/* 75 */ {0x0001, 0x8200},
800/* 78 */ {0x000f, 0x8201},
801/* 79 */ {0x0008, 0x8200},
802/* 80 */ {0x0001, 0x8200},
803
804/* 84 */ {0x0018, 0x8660},
805/* 85 */ {0x0010, 0x8201},
806
807/* 86 */ {0x0008, 0x8200},
808/* 87 */ {0x0001, 0x8200},
809/* 90 */ {0x0011, 0x8201},
810/* 91 */ {0x0008, 0x8200},
811/* 92 */ {0x0001, 0x8200},
812
813/* 95 */ {0x0000, 0x86b0},
814/* 96 */ {0x0034, 0x86b1},
815/* 97 */ {0x0000, 0x86b2},
816/* 98 */ {0x0049, 0x86b3},
817/* 99 */ {0x0000, 0x86b4},
818/* 100 */ {0x0000, 0x86b4},
819
820/* 101 */ {0x0012, 0x8201},
821/* 102 */ {0x0008, 0x8200},
822/* 103 */ {0x0001, 0x8200},
823/* 106 */ {0x0013, 0x8201},
824/* 107 */ {0x0008, 0x8200},
825/* 108 */ {0x0001, 0x8200},
826
827/* 111 */ {0x0001, 0x86b0},
828/* 112 */ {0x00aa, 0x86b1},
829/* 113 */ {0x0000, 0x86b2},
830/* 114 */ {0x00e4, 0x86b3},
831/* 115 */ {0x0000, 0x86b4},
832/* 116 */ {0x0000, 0x86b4},
833
834/* 118 */ {0x0018, 0x8660},
835
836/* 119 */ {0x0090, 0x8110},
837/* 120 */ {0x0001, 0x8114},
838/* 121 */ {0x0001, 0x8114},
839/* 122 */ {0x0001, 0x8114},
840/* 123 */ {0x0003, 0x8114},
841
842/* 124 */ {0x0080, 0x8804},
843/* 157 */ {0x0003, 0x8801},
844/* 158 */ {0x0012, 0x8800},
845/* 160 */ {0x0004, 0x8801},
846/* 161 */ {0x0005, 0x8800},
847/* 163 */ {0x0005, 0x8801},
848/* 164 */ {0x0000, 0x8800},
849/* 166 */ {0x0006, 0x8801},
850/* 167 */ {0x0000, 0x8800},
851/* 169 */ {0x0007, 0x8801},
852/* 170 */ {0x0000, 0x8800},
853/* 172 */ {0x0008, 0x8801},
854/* 173 */ {0x0005, 0x8800},
855/* 175 */ {0x000a, 0x8700},
856/* 176 */ {0x000e, 0x8801},
857/* 177 */ {0x0004, 0x8800},
858/* 179 */ {0x0005, 0x8801},
859/* 180 */ {0x0047, 0x8800},
860/* 182 */ {0x0006, 0x8801},
861/* 183 */ {0x0000, 0x8800},
862/* 185 */ {0x0007, 0x8801},
863/* 186 */ {0x00c0, 0x8800},
864/* 188 */ {0x0008, 0x8801},
865/* 189 */ {0x0003, 0x8800},
866/* 191 */ {0x0013, 0x8801},
867/* 192 */ {0x0001, 0x8800},
868/* 194 */ {0x0009, 0x8801},
869/* 195 */ {0x0000, 0x8800},
870/* 197 */ {0x000a, 0x8801},
871/* 198 */ {0x0000, 0x8800},
872/* 200 */ {0x000b, 0x8801},
873/* 201 */ {0x0000, 0x8800},
874/* 203 */ {0x000c, 0x8801},
875/* 204 */ {0x0000, 0x8800},
876/* 206 */ {0x000e, 0x8801},
877/* 207 */ {0x0004, 0x8800},
878/* 209 */ {0x000f, 0x8801},
879/* 210 */ {0x0000, 0x8800},
880/* 212 */ {0x0010, 0x8801},
881/* 213 */ {0x0006, 0x8800},
882/* 215 */ {0x0011, 0x8801},
883/* 216 */ {0x0006, 0x8800},
884/* 218 */ {0x0012, 0x8801},
885/* 219 */ {0x0000, 0x8800},
886/* 221 */ {0x0013, 0x8801},
887/* 222 */ {0x0001, 0x8800},
888
889/* 224 */ {0x000a, 0x8700},
890/* 225 */ {0x0000, 0x8702},
891/* 226 */ {0x0000, 0x8703},
892/* 227 */ {0x00c2, 0x8704},
893/* 228 */ {0x0001, 0x870c},
894
895/* 229 */ {0x0044, 0x8600},
896/* 230 */ {0x0002, 0x8606},
897/* 231 */ {0x0064, 0x8607},
898/* 232 */ {0x003a, 0x8601},
899/* 233 */ {0x0008, 0x8602},
900/* 234 */ {0x0044, 0x8600},
901/* 235 */ {0x0018, 0x8617},
902/* 236 */ {0x0008, 0x8618},
903/* 237 */ {0x00a1, 0x8656},
904/* 238 */ {0x0004, 0x865b},
905/* 239 */ {0x0002, 0x865c},
906/* 240 */ {0x0058, 0x865d},
907/* 241 */ {0x0048, 0x865e},
908/* 242 */ {0x0012, 0x8608},
909/* 243 */ {0x002c, 0x8609},
910/* 244 */ {0x0002, 0x860a},
911/* 245 */ {0x002c, 0x860b},
912/* 246 */ {0x00db, 0x860c},
913/* 247 */ {0x00f9, 0x860d},
914/* 248 */ {0x00f1, 0x860e},
915/* 249 */ {0x00e3, 0x860f},
916/* 250 */ {0x002c, 0x8610},
917/* 251 */ {0x006c, 0x8651},
918/* 252 */ {0x0041, 0x8652},
919/* 253 */ {0x0059, 0x8653},
920/* 254 */ {0x0040, 0x8654},
921/* 255 */ {0x00fa, 0x8611},
922/* 256 */ {0x00ff, 0x8612},
923/* 257 */ {0x00f8, 0x8613},
924/* 258 */ {0x0000, 0x8614},
925/* 259 */ {0x0001, 0x863f},
926/* 260 */ {0x0000, 0x8640},
927/* 261 */ {0x0026, 0x8641},
928/* 262 */ {0x0045, 0x8642},
929/* 263 */ {0x0060, 0x8643},
930/* 264 */ {0x0075, 0x8644},
931/* 265 */ {0x0088, 0x8645},
932/* 266 */ {0x009b, 0x8646},
933/* 267 */ {0x00b0, 0x8647},
934/* 268 */ {0x00c5, 0x8648},
935/* 269 */ {0x00d2, 0x8649},
936/* 270 */ {0x00dc, 0x864a},
937/* 271 */ {0x00e5, 0x864b},
938/* 272 */ {0x00eb, 0x864c},
939/* 273 */ {0x00f0, 0x864d},
940/* 274 */ {0x00f6, 0x864e},
941/* 275 */ {0x00fa, 0x864f},
942/* 276 */ {0x00ff, 0x8650},
943/* 277 */ {0x0060, 0x8657},
944/* 278 */ {0x0010, 0x8658},
945/* 279 */ {0x0018, 0x8659},
946/* 280 */ {0x0005, 0x865a},
947/* 281 */ {0x0018, 0x8660},
948/* 282 */ {0x0003, 0x8509},
949/* 283 */ {0x0011, 0x850a},
950/* 284 */ {0x0032, 0x850b},
951/* 285 */ {0x0010, 0x850c},
952/* 286 */ {0x0021, 0x850d},
953/* 287 */ {0x0001, 0x8500},
954/* 288 */ {0x0000, 0x8508},
955/* 289 */ {0x0012, 0x8608},
956/* 290 */ {0x002c, 0x8609},
957/* 291 */ {0x0002, 0x860a},
958/* 292 */ {0x0039, 0x860b},
959/* 293 */ {0x00d0, 0x860c},
960/* 294 */ {0x00f7, 0x860d},
961/* 295 */ {0x00ed, 0x860e},
962/* 296 */ {0x00db, 0x860f},
963/* 297 */ {0x0039, 0x8610},
964/* 298 */ {0x0012, 0x8657},
965/* 299 */ {0x000c, 0x8619},
966/* 300 */ {0x0004, 0x861a},
967/* 301 */ {0x00a1, 0x8656},
968/* 302 */ {0x00c8, 0x8615},
969/* 303 */ {0x0032, 0x8616},
970
971/* 306 */ {0x0030, 0x8112},
972/* 313 */ {0x0020, 0x8112},
973/* 314 */ {0x0020, 0x8112},
974/* 315 */ {0x000f, 0x8402},
975/* 316 */ {0x0000, 0x8403},
976
977/* 317 */ {0x0090, 0x8110},
978/* 318 */ {0x0001, 0x8114},
979/* 319 */ {0x0001, 0x8114},
980/* 320 */ {0x0001, 0x8114},
981/* 321 */ {0x0003, 0x8114},
982/* 322 */ {0x0080, 0x8804},
983
984/* 355 */ {0x0003, 0x8801},
985/* 356 */ {0x0012, 0x8800},
986/* 358 */ {0x0004, 0x8801},
987/* 359 */ {0x0005, 0x8800},
988/* 361 */ {0x0005, 0x8801},
989/* 362 */ {0x0047, 0x8800},
990/* 364 */ {0x0006, 0x8801},
991/* 365 */ {0x0000, 0x8800},
992/* 367 */ {0x0007, 0x8801},
993/* 368 */ {0x00c0, 0x8800},
994/* 370 */ {0x0008, 0x8801},
995/* 371 */ {0x0003, 0x8800},
996/* 373 */ {0x000a, 0x8700},
997/* 374 */ {0x000e, 0x8801},
998/* 375 */ {0x0004, 0x8800},
999/* 377 */ {0x0005, 0x8801},
1000/* 378 */ {0x0047, 0x8800},
1001/* 380 */ {0x0006, 0x8801},
1002/* 381 */ {0x0000, 0x8800},
1003/* 383 */ {0x0007, 0x8801},
1004/* 384 */ {0x00c0, 0x8800},
1005/* 386 */ {0x0008, 0x8801},
1006/* 387 */ {0x0003, 0x8800},
1007/* 389 */ {0x0013, 0x8801},
1008/* 390 */ {0x0001, 0x8800},
1009/* 392 */ {0x0009, 0x8801},
1010/* 393 */ {0x0000, 0x8800},
1011/* 395 */ {0x000a, 0x8801},
1012/* 396 */ {0x0000, 0x8800},
1013/* 398 */ {0x000b, 0x8801},
1014/* 399 */ {0x0000, 0x8800},
1015/* 401 */ {0x000c, 0x8801},
1016/* 402 */ {0x0000, 0x8800},
1017/* 404 */ {0x000e, 0x8801},
1018/* 405 */ {0x0004, 0x8800},
1019/* 407 */ {0x000f, 0x8801},
1020/* 408 */ {0x0000, 0x8800},
1021/* 410 */ {0x0010, 0x8801},
1022/* 411 */ {0x0006, 0x8800},
1023/* 413 */ {0x0011, 0x8801},
1024/* 414 */ {0x0006, 0x8800},
1025/* 416 */ {0x0012, 0x8801},
1026/* 417 */ {0x0000, 0x8800},
1027/* 419 */ {0x0013, 0x8801},
1028/* 420 */ {0x0001, 0x8800},
1029/* 422 */ {0x000a, 0x8700},
1030/* 423 */ {0x0000, 0x8702},
1031/* 424 */ {0x0000, 0x8703},
1032/* 425 */ {0x00c2, 0x8704},
1033/* 426 */ {0x0001, 0x870c},
1034/* 427 */ {0x0044, 0x8600},
1035/* 428 */ {0x0002, 0x8606},
1036/* 429 */ {0x0064, 0x8607},
1037/* 430 */ {0x003a, 0x8601},
1038/* 431 */ {0x0008, 0x8602},
1039/* 432 */ {0x0044, 0x8600},
1040/* 433 */ {0x0018, 0x8617},
1041/* 434 */ {0x0008, 0x8618},
1042/* 435 */ {0x00a1, 0x8656},
1043/* 436 */ {0x0004, 0x865b},
1044/* 437 */ {0x0002, 0x865c},
1045/* 438 */ {0x0058, 0x865d},
1046/* 439 */ {0x0048, 0x865e},
1047/* 440 */ {0x0012, 0x8608},
1048/* 441 */ {0x002c, 0x8609},
1049/* 442 */ {0x0002, 0x860a},
1050/* 443 */ {0x002c, 0x860b},
1051/* 444 */ {0x00db, 0x860c},
1052/* 445 */ {0x00f9, 0x860d},
1053/* 446 */ {0x00f1, 0x860e},
1054/* 447 */ {0x00e3, 0x860f},
1055/* 448 */ {0x002c, 0x8610},
1056/* 449 */ {0x006c, 0x8651},
1057/* 450 */ {0x0041, 0x8652},
1058/* 451 */ {0x0059, 0x8653},
1059/* 452 */ {0x0040, 0x8654},
1060/* 453 */ {0x00fa, 0x8611},
1061/* 454 */ {0x00ff, 0x8612},
1062/* 455 */ {0x00f8, 0x8613},
1063/* 456 */ {0x0000, 0x8614},
1064/* 457 */ {0x0001, 0x863f},
1065/* 458 */ {0x0000, 0x8640},
1066/* 459 */ {0x0026, 0x8641},
1067/* 460 */ {0x0045, 0x8642},
1068/* 461 */ {0x0060, 0x8643},
1069/* 462 */ {0x0075, 0x8644},
1070/* 463 */ {0x0088, 0x8645},
1071/* 464 */ {0x009b, 0x8646},
1072/* 465 */ {0x00b0, 0x8647},
1073/* 466 */ {0x00c5, 0x8648},
1074/* 467 */ {0x00d2, 0x8649},
1075/* 468 */ {0x00dc, 0x864a},
1076/* 469 */ {0x00e5, 0x864b},
1077/* 470 */ {0x00eb, 0x864c},
1078/* 471 */ {0x00f0, 0x864d},
1079/* 472 */ {0x00f6, 0x864e},
1080/* 473 */ {0x00fa, 0x864f},
1081/* 474 */ {0x00ff, 0x8650},
1082/* 475 */ {0x0060, 0x8657},
1083/* 476 */ {0x0010, 0x8658},
1084/* 477 */ {0x0018, 0x8659},
1085/* 478 */ {0x0005, 0x865a},
1086/* 479 */ {0x0018, 0x8660},
1087/* 480 */ {0x0003, 0x8509},
1088/* 481 */ {0x0011, 0x850a},
1089/* 482 */ {0x0032, 0x850b},
1090/* 483 */ {0x0010, 0x850c},
1091/* 484 */ {0x0021, 0x850d},
1092/* 485 */ {0x0001, 0x8500},
1093/* 486 */ {0x0000, 0x8508},
1094
1095/* 487 */ {0x0012, 0x8608},
1096/* 488 */ {0x002c, 0x8609},
1097/* 489 */ {0x0002, 0x860a},
1098/* 490 */ {0x0039, 0x860b},
1099/* 491 */ {0x00d0, 0x860c},
1100/* 492 */ {0x00f7, 0x860d},
1101/* 493 */ {0x00ed, 0x860e},
1102/* 494 */ {0x00db, 0x860f},
1103/* 495 */ {0x0039, 0x8610},
1104/* 496 */ {0x0012, 0x8657},
1105/* 497 */ {0x0064, 0x8619},
1106
1107/* This line starts it all, it is not needed here */
1108/* since it has been build into the driver */
1109/* jfm: don't start now */
1110/* 590 * {0x0030, 0x8112}, */
1111 {}
1112};
1113
1114/*
1115 * Initialization data for Creative Webcam Vista
1116 */
1117static const __u16 spca508_vista_init_data[][3] = {
1118 {0x0008, 0x8200}, /* Clear register */
1119 {0x0000, 0x870b}, /* Reset CTL3 */
1120 {0x0020, 0x8112}, /* Video Drop packet enable */
1121 {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
1122 {0x0000, 0x8110}, /* Disable everything */
1123 {0x0000, 0x8114}, /* Software GPIO output data */
1124 {0x0000, 0x8114},
1125
1126 {0x0003, 0x8111},
1127 {0x0000, 0x8111},
1128 {0x0090, 0x8110}, /* Enable: SSI output, External 2X clock output */
1129 {0x0020, 0x8112},
1130 {0x0000, 0x8114},
1131 {0x0001, 0x8114},
1132 {0x0001, 0x8114},
1133 {0x0001, 0x8114},
1134 {0x0003, 0x8114},
1135
1136 {0x000f, 0x8402}, /* Memory bank Address */
1137 {0x0000, 0x8403}, /* Memory bank Address */
1138 {0x00ba, 0x8804}, /* SSI Slave address */
1139 {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */
1140
1141 /* READ { 0, 0x0001, 0x8803 } ->
1142 0000: 00 */
1143 /* READ { 0, 0x0001, 0x8802 } ->
1144 0000: 10 */
1145 {0x0010, 0x8802}, /* Will write 2 bytes (DATA1+DATA2) */
1146 {0x0020, 0x8801}, /* Register address for SSI read/write */
1147 {0x0044, 0x8805}, /* DATA2 */
1148 {0x0004, 0x8800}, /* DATA1 -> write triggered */
1149 /* READ { 0, 0x0001, 0x8803 } ->
1150 0000: 00 */
1151
1152 /* READ { 0, 0x0001, 0x8803 } ->
1153 0000: 00 */
1154 /* READ { 0, 0x0001, 0x8802 } ->
1155 0000: 10 */
1156 {0x0010, 0x8802},
1157 {0x0009, 0x8801},
1158 {0x0042, 0x8805},
1159 {0x0001, 0x8800},
1160 /* READ { 0, 0x0001, 0x8803 } ->
1161 0000: 00 */
1162
1163 /* READ { 0, 0x0001, 0x8803 } ->
1164 0000: 00 */
1165 /* READ { 0, 0x0001, 0x8802 } ->
1166 0000: 10 */
1167 {0x0010, 0x8802},
1168 {0x003c, 0x8801},
1169 {0x0001, 0x8805},
1170 {0x0000, 0x8800},
1171 /* READ { 0, 0x0001, 0x8803 } ->
1172 0000: 00 */
1173
1174 /* READ { 0, 0x0001, 0x8803 } ->
1175 0000: 00 */
1176 /* READ { 0, 0x0001, 0x8802 } ->
1177 0000: 10 */
1178 {0x0010, 0x8802},
1179 {0x0001, 0x8801},
1180 {0x000a, 0x8805},
1181 {0x0000, 0x8800},
1182 /* READ { 0, 0x0001, 0x8803 } ->
1183 0000: 00 */
1184
1185 /* READ { 0, 0x0001, 0x8803 } ->
1186 0000: 00 */
1187 /* READ { 0, 0x0001, 0x8802 } ->
1188 0000: 10 */
1189 {0x0010, 0x8802},
1190 {0x0002, 0x8801},
1191 {0x0000, 0x8805},
1192 {0x0000, 0x8800},
1193 /* READ { 0, 0x0001, 0x8803 } ->
1194 0000: 00 */
1195
1196 /* READ { 0, 0x0001, 0x8803 } ->
1197 0000: 00 */
1198 /* READ { 0, 0x0001, 0x8802 } ->
1199 0000: 10 */
1200 {0x0010, 0x8802},
1201 {0x0003, 0x8801},
1202 {0x0027, 0x8805},
1203 {0x0001, 0x8800},
1204 /* READ { 0, 0x0001, 0x8803 } ->
1205 0000: 00 */
1206
1207 /* READ { 0, 0x0001, 0x8803 } ->
1208 0000: 00 */
1209 /* READ { 0, 0x0001, 0x8802 } ->
1210 0000: 10 */
1211 {0x0010, 0x8802},
1212 {0x0004, 0x8801},
1213 {0x0065, 0x8805},
1214 {0x0001, 0x8800},
1215 /* READ { 0, 0x0001, 0x8803 } ->
1216 0000: 00 */
1217
1218 /* READ { 0, 0x0001, 0x8803 } ->
1219 0000: 00 */
1220 /* READ { 0, 0x0001, 0x8802 } ->
1221 0000: 10 */
1222 {0x0010, 0x8802},
1223 {0x0005, 0x8801},
1224 {0x0003, 0x8805},
1225 {0x0000, 0x8800},
1226 /* READ { 0, 0x0001, 0x8803 } ->
1227 0000: 00 */
1228
1229 /* READ { 0, 0x0001, 0x8803 } ->
1230 0000: 00 */
1231 /* READ { 0, 0x0001, 0x8802 } ->
1232 0000: 10 */
1233 {0x0010, 0x8802},
1234 {0x0006, 0x8801},
1235 {0x001c, 0x8805},
1236 {0x0000, 0x8800},
1237 /* READ { 0, 0x0001, 0x8803 } ->
1238 0000: 00 */
1239
1240 /* READ { 0, 0x0001, 0x8803 } ->
1241 0000: 00 */
1242 /* READ { 0, 0x0001, 0x8802 } ->
1243 0000: 10 */
1244 {0x0010, 0x8802},
1245 {0x0007, 0x8801},
1246 {0x002a, 0x8805},
1247 {0x0000, 0x8800},
1248 /* READ { 0, 0x0001, 0x8803 } ->
1249 0000: 00 */
1250
1251 /* READ { 0, 0x0001, 0x8803 } ->
1252 0000: 00 */
1253 /* READ { 0, 0x0001, 0x8802 } ->
1254 0000: 10 */
1255 {0x0010, 0x8802},
1256 {0x000e, 0x8801},
1257 {0x0000, 0x8805},
1258 {0x0000, 0x8800},
1259 /* READ { 0, 0x0001, 0x8803 } ->
1260 0000: 00 */
1261
1262 /* READ { 0, 0x0001, 0x8803 } ->
1263 0000: 00 */
1264 /* READ { 0, 0x0001, 0x8802 } ->
1265 0000: 10 */
1266 {0x0010, 0x8802},
1267 {0x0028, 0x8801},
1268 {0x002e, 0x8805},
1269 {0x0000, 0x8800},
1270 /* READ { 0, 0x0001, 0x8803 } ->
1271 0000: 00 */
1272
1273 /* READ { 0, 0x0001, 0x8803 } ->
1274 0000: 00 */
1275 /* READ { 0, 0x0001, 0x8802 } ->
1276 0000: 10 */
1277 {0x0010, 0x8802},
1278 {0x0039, 0x8801},
1279 {0x0013, 0x8805},
1280 {0x0000, 0x8800},
1281 /* READ { 0, 0x0001, 0x8803 } ->
1282 0000: 00 */
1283
1284 /* READ { 0, 0x0001, 0x8803 } ->
1285 0000: 00 */
1286 /* READ { 0, 0x0001, 0x8802 } ->
1287 0000: 10 */
1288 {0x0010, 0x8802},
1289 {0x003b, 0x8801},
1290 {0x000c, 0x8805},
1291 {0x0000, 0x8800},
1292 /* READ { 0, 0x0001, 0x8803 } ->
1293 0000: 00 */
1294
1295 /* READ { 0, 0x0001, 0x8803 } ->
1296 0000: 00 */
1297 /* READ { 0, 0x0001, 0x8802 } ->
1298 0000: 10 */
1299 {0x0010, 0x8802},
1300 {0x0035, 0x8801},
1301 {0x0028, 0x8805},
1302 {0x0000, 0x8800},
1303 /* READ { 0, 0x0001, 0x8803 } ->
1304 0000: 00 */
1305
1306 /* READ { 0, 0x0001, 0x8803 } ->
1307 0000: 00 */
1308 /* READ { 0, 0x0001, 0x8802 } ->
1309 0000: 10 */
1310 {0x0010, 0x8802},
1311 {0x0009, 0x8801},
1312 {0x0042, 0x8805},
1313 {0x0001, 0x8800},
1314 /* READ { 0, 0x0001, 0x8803 } ->
1315 0000: 00 */
1316
1317 {0x0050, 0x8703},
1318 {0x0002, 0x8704}, /* External input CKIx1 */
1319 {0x0001, 0x870C}, /* Select CKOx2 output */
1320 {0x009A, 0x8600}, /* Line memory Read Counter (L) */
1321 {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */
1322 {0x0023, 0x8601},
1323 {0x0010, 0x8602},
1324 {0x000A, 0x8603},
1325 {0x009A, 0x8600},
1326 {0x0001, 0x865B}, /* 1 Horizontal Offset for Valid Pixel(L) */
1327 {0x0003, 0x865C}, /* Vertical offset for valid lines (L) */
1328 {0x0058, 0x865D}, /* Horizontal valid pixels window (L) */
1329 {0x0048, 0x865E}, /* Vertical valid lines window (L) */
1330 {0x0000, 0x865F},
1331
1332 {0x0006, 0x8660},
1333 /* Enable nibble data input, select nibble input order */
1334
1335 {0x0013, 0x8608}, /* A11 Coeficients for color correction */
1336 {0x0028, 0x8609},
1337 /* Note: these values are confirmed at the end of array */
1338 {0x0005, 0x860A}, /* ... */
1339 {0x0025, 0x860B},
1340 {0x00E1, 0x860C},
1341 {0x00FA, 0x860D},
1342 {0x00F4, 0x860E},
1343 {0x00E8, 0x860F},
1344 {0x0025, 0x8610}, /* A33 Coef. */
1345 {0x00FC, 0x8611}, /* White balance offset: R */
1346 {0x0001, 0x8612}, /* White balance offset: Gr */
1347 {0x00FE, 0x8613}, /* White balance offset: B */
1348 {0x0000, 0x8614}, /* White balance offset: Gb */
1349
1350 {0x0064, 0x8651}, /* R gain for white balance (L) */
1351 {0x0040, 0x8652}, /* Gr gain for white balance (L) */
1352 {0x0066, 0x8653}, /* B gain for white balance (L) */
1353 {0x0040, 0x8654}, /* Gb gain for white balance (L) */
1354 {0x0001, 0x863F}, /* Enable fixed gamma correction */
1355
1356 {0x00A1, 0x8656}, /* Size - Window1: 256x256, Window2: 128x128 */
1357 /* UV division: UV no change, Enable New edge enhancement */
1358 {0x0018, 0x8657}, /* Edge gain high threshold */
1359 {0x0020, 0x8658}, /* Edge gain low threshold */
1360 {0x000A, 0x8659}, /* Edge bandwidth high threshold */
1361 {0x0005, 0x865A}, /* Edge bandwidth low threshold */
1362 {0x0064, 0x8607}, /* UV filter enable */
1363
1364 {0x0016, 0x8660},
1365 {0x0000, 0x86B0}, /* Bad pixels compensation address */
1366 {0x00DC, 0x86B1}, /* X coord for bad pixels compensation (L) */
1367 {0x0000, 0x86B2},
1368 {0x0009, 0x86B3}, /* Y coord for bad pixels compensation (L) */
1369 {0x0000, 0x86B4},
1370
1371 {0x0001, 0x86B0},
1372 {0x00F5, 0x86B1},
1373 {0x0000, 0x86B2},
1374 {0x00C6, 0x86B3},
1375 {0x0000, 0x86B4},
1376
1377 {0x0002, 0x86B0},
1378 {0x001C, 0x86B1},
1379 {0x0001, 0x86B2},
1380 {0x00D7, 0x86B3},
1381 {0x0000, 0x86B4},
1382
1383 {0x0003, 0x86B0},
1384 {0x001C, 0x86B1},
1385 {0x0001, 0x86B2},
1386 {0x00D8, 0x86B3},
1387 {0x0000, 0x86B4},
1388
1389 {0x0004, 0x86B0},
1390 {0x001D, 0x86B1},
1391 {0x0001, 0x86B2},
1392 {0x00D8, 0x86B3},
1393 {0x0000, 0x86B4},
1394 {0x001E, 0x8660},
1395
1396 /* READ { 0, 0x0000, 0x8608 } ->
1397 0000: 13 */
1398 /* READ { 0, 0x0000, 0x8609 } ->
1399 0000: 28 */
1400 /* READ { 0, 0x0000, 0x8610 } ->
1401 0000: 05 */
1402 /* READ { 0, 0x0000, 0x8611 } ->
1403 0000: 25 */
1404 /* READ { 0, 0x0000, 0x8612 } ->
1405 0000: e1 */
1406 /* READ { 0, 0x0000, 0x8613 } ->
1407 0000: fa */
1408 /* READ { 0, 0x0000, 0x8614 } ->
1409 0000: f4 */
1410 /* READ { 0, 0x0000, 0x8615 } ->
1411 0000: e8 */
1412 /* READ { 0, 0x0000, 0x8616 } ->
1413 0000: 25 */
1414 {}
1415};
1416
1417static int reg_write(struct usb_device *dev,
1418 __u16 index, __u16 value)
1419{
1420 int ret;
1421
1422 ret = usb_control_msg(dev,
1423 usb_sndctrlpipe(dev, 0),
1424 0, /* request */
1425 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1426 value, index, NULL, 0, 500);
1427 PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
1428 index, value);
1429 if (ret < 0)
1430 PDEBUG(D_ERR|D_USBO, "reg write: error %d", ret);
1431 return ret;
1432}
1433
1434/* read 1 byte */
1435/* returns: negative is error, pos or zero is data */
1436static int reg_read(struct gspca_dev *gspca_dev,
1437 __u16 index) /* wIndex */
1438{
1439 int ret;
1440
1441 ret = usb_control_msg(gspca_dev->dev,
1442 usb_rcvctrlpipe(gspca_dev->dev, 0),
1443 0, /* register */
1444 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1445 0, /* value */
1446 index,
1447 gspca_dev->usb_buf, 1,
1448 500); /* timeout */
1449 PDEBUG(D_USBI, "reg read i:%04x --> %02x",
1450 index, gspca_dev->usb_buf[0]);
1451 if (ret < 0) {
1452 PDEBUG(D_ERR|D_USBI, "reg_read err %d", ret);
1453 return ret;
1454 }
1455 return gspca_dev->usb_buf[0];
1456}
1457
1458static int write_vector(struct gspca_dev *gspca_dev,
1459 const __u16 data[][3])
1460{
1461 struct usb_device *dev = gspca_dev->dev;
1462 int ret, i = 0;
1463
1464 while (data[i][1] != 0) {
1465 ret = reg_write(dev, data[i][1], data[i][0]);
1466 if (ret < 0)
1467 return ret;
1468 i++;
1469 }
1470 return 0;
1471}
1472
1473/* this function is called at probe time */
1474static int sd_config(struct gspca_dev *gspca_dev,
1475 const struct usb_device_id *id)
1476{
1477 struct sd *sd = (struct sd *) gspca_dev;
1478 struct cam *cam;
1479 __u16 product;
1480 int data1, data2;
1481
1482 product = id->idProduct;
1483 switch (id->idVendor) {
1484 case 0x0130: /* Clone webcam */
1485/* switch (product) { */
1486/* case 0x0130: */
1487 sd->subtype = HamaUSBSightcam; /* same as Hama 0010 */
1488/* break; */
1489/* } */
1490 break;
1491 case 0x041e: /* Creative cameras */
1492/* switch (product) { */
1493/* case 0x4018: */
1494 sd->subtype = CreativeVista;
1495/* break; */
1496/* } */
1497 break;
1498 case 0x0461: /* MicroInnovation */
1499/* switch (product) { */
1500/* case 0x0815: */
1501 sd->subtype = MicroInnovationIC200;
1502/* break; */
1503/* } */
1504 break;
1505 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
1506/* switch (product) { */
1507/* case 0x110: */
1508 sd->subtype = ViewQuestVQ110;
1509/* break; */
1510/* } */
1511 break;
1512 case 0x0af9: /* Hama cameras */
1513 switch (product) {
1514 case 0x0010:
1515 sd->subtype = HamaUSBSightcam;
1516 break;
1517 case 0x0011:
1518 sd->subtype = HamaUSBSightcam2;
1519 break;
1520 }
1521 break;
1522 case 0x8086: /* Intel */
1523/* switch (product) { */
1524/* case 0x0110: */
1525 sd->subtype = IntelEasyPCCamera;
1526/* break; */
1527/* } */
1528 break;
1529 }
1530
1531 /* Read from global register the USB product and vendor IDs, just to
1532 * prove that we can communicate with the device. This works, which
1533 * confirms at we are communicating properly and that the device
1534 * is a 508. */
1535 data1 = reg_read(gspca_dev, 0x8104);
1536 data2 = reg_read(gspca_dev, 0x8105);
1537 PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);
1538
1539 data1 = reg_read(gspca_dev, 0x8106);
1540 data2 = reg_read(gspca_dev, 0x8107);
1541 PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);
1542
1543 data1 = reg_read(gspca_dev, 0x8621);
1544 PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
1545
1546 cam = &gspca_dev->cam;
1547 cam->dev_name = (char *) id->driver_info;
1548 cam->epaddr = 0x01;
1549 cam->cam_mode = sif_mode;
1550 cam->nmodes = ARRAY_SIZE(sif_mode);
1551 sd->brightness = BRIGHTNESS_DEF;
1552
1553 switch (sd->subtype) {
1554 case ViewQuestVQ110:
1555 if (write_vector(gspca_dev, spca508_init_data))
1556 return -1;
1557 break;
1558 default:
1559/* case MicroInnovationIC200: */
1560/* case IntelEasyPCCamera: */
1561 if (write_vector(gspca_dev, spca508cs110_init_data))
1562 return -1;
1563 break;
1564 case HamaUSBSightcam:
1565 if (write_vector(gspca_dev, spca508_sightcam_init_data))
1566 return -1;
1567 break;
1568 case HamaUSBSightcam2:
1569 if (write_vector(gspca_dev, spca508_sightcam2_init_data))
1570 return -1;
1571 break;
1572 case CreativeVista:
1573 if (write_vector(gspca_dev, spca508_vista_init_data))
1574 return -1;
1575 break;
1576 }
1577 return 0; /* success */
1578}
1579
1580/* this function is called at open time */
1581static int sd_open(struct gspca_dev *gspca_dev)
1582{
1583/* write_vector(gspca_dev, spca508_open_data); */
1584 return 0;
1585}
1586
1587static void sd_start(struct gspca_dev *gspca_dev)
1588{
1589 int mode;
1590
1591 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1592 reg_write(gspca_dev->dev, 0x8500, mode);
1593 switch (mode) {
1594 case 0:
1595 case 1:
1596 reg_write(gspca_dev->dev, 0x8700, 0x28); /* clock */
1597 break;
1598 default:
1599/* case 2: */
1600/* case 3: */
1601 reg_write(gspca_dev->dev, 0x8700, 0x23); /* clock */
1602 break;
1603 }
1604 reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
1605}
1606
1607static void sd_stopN(struct gspca_dev *gspca_dev)
1608{
1609 /* Video ISO disable, Video Drop Packet enable: */
1610 reg_write(gspca_dev->dev, 0x8112, 0x20);
1611}
1612
1613static void sd_stop0(struct gspca_dev *gspca_dev)
1614{
1615}
1616
1617/* this function is called at close time */
1618static void sd_close(struct gspca_dev *gspca_dev)
1619{
1620}
1621
1622/* convert YUVY per line to YUYV (YUV 4:2:2) */
1623static void yuvy_decode(unsigned char *out,
1624 unsigned char *in,
1625 int width,
1626 int height)
1627{
1628 unsigned char *Ui, *Vi, *yi, *yi1;
1629 unsigned char *out1;
1630 int i, j;
1631
1632 yi = in;
1633 for (i = height / 2; --i >= 0; ) {
1634 out1 = out + width * 2; /* next line */
1635 Ui = yi + width;
1636 Vi = Ui + width / 2;
1637 yi1 = Vi + width / 2;
1638 for (j = width / 2; --j >= 0; ) {
1639 *out++ = 128 + *yi++;
1640 *out++ = 128 + *Ui;
1641 *out++ = 128 + *yi++;
1642 *out++ = 128 + *Vi;
1643
1644 *out1++ = 128 + *yi1++;
1645 *out1++ = 128 + *Ui++;
1646 *out1++ = 128 + *yi1++;
1647 *out1++ = 128 + *Vi++;
1648 }
1649 yi += width * 2;
1650 out = out1;
1651 }
1652}
1653
1654static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1655 struct gspca_frame *frame, /* target */
1656 __u8 *data, /* isoc packet */
1657 int len) /* iso packet length */
1658{
1659 struct sd *sd = (struct sd *) gspca_dev;
1660
1661 switch (data[0]) {
1662 case 0: /* start of frame */
1663 if (gspca_dev->last_packet_type == FIRST_PACKET) {
1664 yuvy_decode(sd->tmpbuf2, sd->tmpbuf,
1665 gspca_dev->width,
1666 gspca_dev->height);
1667 frame = gspca_frame_add(gspca_dev,
1668 LAST_PACKET,
1669 frame,
1670 sd->tmpbuf2,
1671 gspca_dev->width
1672 * gspca_dev->height
1673 * 2);
1674 }
1675 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1676 data, 0);
1677 data += SPCA508_OFFSET_DATA;
1678 len -= SPCA508_OFFSET_DATA;
1679 if (len > 0)
1680 memcpy(sd->tmpbuf, data, len);
1681 else
1682 len = 0;
1683 sd->buflen = len;
1684 return;
1685 case 0xff: /* drop */
1686/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1687 return;
1688 }
1689 data += 1;
1690 len -= 1;
1691 memcpy(&sd->tmpbuf[sd->buflen], data, len);
1692 sd->buflen += len;
1693}
1694
1695static void setbrightness(struct gspca_dev *gspca_dev)
1696{
1697 struct sd *sd = (struct sd *) gspca_dev;
1698 __u8 brightness = sd->brightness;
1699
1700 /* MX seem contrast */
1701 reg_write(gspca_dev->dev, 0x8651, brightness);
1702 reg_write(gspca_dev->dev, 0x8652, brightness);
1703 reg_write(gspca_dev->dev, 0x8653, brightness);
1704 reg_write(gspca_dev->dev, 0x8654, brightness);
1705}
1706
1707static void getbrightness(struct gspca_dev *gspca_dev)
1708{
1709 struct sd *sd = (struct sd *) gspca_dev;
1710
1711 sd->brightness = reg_read(gspca_dev, 0x8651);
1712}
1713
1714static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1715{
1716 struct sd *sd = (struct sd *) gspca_dev;
1717
1718 sd->brightness = val;
1719 if (gspca_dev->streaming)
1720 setbrightness(gspca_dev);
1721 return 0;
1722}
1723
1724static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1725{
1726 struct sd *sd = (struct sd *) gspca_dev;
1727
1728 getbrightness(gspca_dev);
1729 *val = sd->brightness;
1730 return 0;
1731}
1732
1733/* sub-driver description */
1734static const struct sd_desc sd_desc = {
1735 .name = MODULE_NAME,
1736 .ctrls = sd_ctrls,
1737 .nctrls = ARRAY_SIZE(sd_ctrls),
1738 .config = sd_config,
1739 .open = sd_open,
1740 .start = sd_start,
1741 .stopN = sd_stopN,
1742 .stop0 = sd_stop0,
1743 .close = sd_close,
1744 .pkt_scan = sd_pkt_scan,
1745};
1746
1747/* -- module initialisation -- */
1748#define DVNM(name) .driver_info = (kernel_ulong_t) name
1749static const __devinitdata struct usb_device_id device_table[] = {
1750 {USB_DEVICE(0x0130, 0x0130), DVNM("Clone Digital Webcam 11043")},
1751 {USB_DEVICE(0x041e, 0x4018), DVNM("Creative Webcam Vista (PD1100)")},
1752 {USB_DEVICE(0x0461, 0x0815), DVNM("Micro Innovation IC200")},
1753 {USB_DEVICE(0x0733, 0x0110), DVNM("ViewQuest VQ110")},
1754 {USB_DEVICE(0x0af9, 0x0010), DVNM("Hama USB Sightcam 100")},
1755 {USB_DEVICE(0x0af9, 0x0011), DVNM("Hama USB Sightcam 100")},
1756 {USB_DEVICE(0x8086, 0x0110), DVNM("Intel Easy PC Camera")},
1757 {}
1758};
1759MODULE_DEVICE_TABLE(usb, device_table);
1760
1761/* -- device connect -- */
1762static int sd_probe(struct usb_interface *intf,
1763 const struct usb_device_id *id)
1764{
1765 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1766 THIS_MODULE);
1767}
1768
1769static struct usb_driver sd_driver = {
1770 .name = MODULE_NAME,
1771 .id_table = device_table,
1772 .probe = sd_probe,
1773 .disconnect = gspca_disconnect,
1774};
1775
1776/* -- module insert / remove -- */
1777static int __init sd_mod_init(void)
1778{
1779 if (usb_register(&sd_driver) < 0)
1780 return -1;
1781 PDEBUG(D_PROBE, "v%s registered", version);
1782 return 0;
1783}
1784static void __exit sd_mod_exit(void)
1785{
1786 usb_deregister(&sd_driver);
1787 PDEBUG(D_PROBE, "deregistered");
1788}
1789
1790module_init(sd_mod_init);
1791module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
new file mode 100644
index 000000000000..b659bd0f788d
--- /dev/null
+++ b/drivers/media/video/gspca/spca561.c
@@ -0,0 +1,1052 @@
1/*
2 * Sunplus spca561 subdriver
3 *
4 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
5 *
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#define MODULE_NAME "spca561"
24
25#include "gspca.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 unsigned short contrast;
39 __u8 brightness;
40 __u8 autogain;
41
42 __u8 chip_revision;
43 signed char ag_cnt;
44#define AG_CNT_START 13
45};
46
47/* V4L2 controls supported by the driver */
48static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
49static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
50static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
52static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
54
55static struct ctrl sd_ctrls[] = {
56#define SD_BRIGHTNESS 0
57 {
58 {
59 .id = V4L2_CID_BRIGHTNESS,
60 .type = V4L2_CTRL_TYPE_INTEGER,
61 .name = "Brightness",
62 .minimum = 0,
63 .maximum = 63,
64 .step = 1,
65 .default_value = 32,
66 },
67 .set = sd_setbrightness,
68 .get = sd_getbrightness,
69 },
70#define SD_CONTRAST 1
71 {
72 {
73 .id = V4L2_CID_CONTRAST,
74 .type = V4L2_CTRL_TYPE_INTEGER,
75 .name = "Contrast",
76 .minimum = 0,
77 .maximum = 0x3fff,
78 .step = 1,
79 .default_value = 0x2000,
80 },
81 .set = sd_setcontrast,
82 .get = sd_getcontrast,
83 },
84#define SD_AUTOGAIN 2
85 {
86 {
87 .id = V4L2_CID_AUTOGAIN,
88 .type = V4L2_CTRL_TYPE_BOOLEAN,
89 .name = "Auto Gain",
90 .minimum = 0,
91 .maximum = 1,
92 .step = 1,
93 .default_value = 1,
94 },
95 .set = sd_setautogain,
96 .get = sd_getautogain,
97 },
98};
99
100static struct v4l2_pix_format sif_mode[] = {
101 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
102 .bytesperline = 160,
103 .sizeimage = 160 * 120,
104 .colorspace = V4L2_COLORSPACE_SRGB,
105 .priv = 3},
106 {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
107 .bytesperline = 176,
108 .sizeimage = 176 * 144,
109 .colorspace = V4L2_COLORSPACE_SRGB,
110 .priv = 2},
111 {320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
112 .bytesperline = 320,
113 .sizeimage = 320 * 240 * 4 / 8,
114 .colorspace = V4L2_COLORSPACE_SRGB,
115 .priv = 1},
116 {352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
117 .bytesperline = 352,
118 .sizeimage = 352 * 288 * 4 / 8,
119 .colorspace = V4L2_COLORSPACE_SRGB,
120 .priv = 0},
121};
122
123/*
124 * Initialization data
125 * I'm not very sure how to split initialization from open data
126 * chunks. For now, we'll consider everything as initialization
127 */
128/* Frame packet header offsets for the spca561 */
129#define SPCA561_OFFSET_SNAP 1
130#define SPCA561_OFFSET_TYPE 2
131#define SPCA561_OFFSET_COMPRESS 3
132#define SPCA561_OFFSET_FRAMSEQ 4
133#define SPCA561_OFFSET_GPIO 5
134#define SPCA561_OFFSET_USBBUFF 6
135#define SPCA561_OFFSET_WIN2GRAVE 7
136#define SPCA561_OFFSET_WIN2RAVE 8
137#define SPCA561_OFFSET_WIN2BAVE 9
138#define SPCA561_OFFSET_WIN2GBAVE 10
139#define SPCA561_OFFSET_WIN1GRAVE 11
140#define SPCA561_OFFSET_WIN1RAVE 12
141#define SPCA561_OFFSET_WIN1BAVE 13
142#define SPCA561_OFFSET_WIN1GBAVE 14
143#define SPCA561_OFFSET_FREQ 15
144#define SPCA561_OFFSET_VSYNC 16
145#define SPCA561_OFFSET_DATA 1
146#define SPCA561_INDEX_I2C_BASE 0x8800
147#define SPCA561_SNAPBIT 0x20
148#define SPCA561_SNAPCTRL 0x40
149enum {
150 Rev072A = 0,
151 Rev012A,
152};
153
154static void reg_w_val(struct usb_device *dev, __u16 index, __u16 value)
155{
156 int ret;
157
158 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
159 0, /* request */
160 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
161 value, index, NULL, 0, 500);
162 PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
163 if (ret < 0)
164 PDEBUG(D_ERR, "reg write: error %d", ret);
165}
166
167static void write_vector(struct gspca_dev *gspca_dev,
168 const __u16 data[][2])
169{
170 struct usb_device *dev = gspca_dev->dev;
171 int i;
172
173 i = 0;
174 while (data[i][1] != 0) {
175 reg_w_val(dev, data[i][1], data[i][0]);
176 i++;
177 }
178}
179
180/* read 'len' bytes to gspca_dev->usb_buf */
181static void reg_r(struct gspca_dev *gspca_dev,
182 __u16 index, __u16 length)
183{
184 usb_control_msg(gspca_dev->dev,
185 usb_rcvctrlpipe(gspca_dev->dev, 0),
186 0, /* request */
187 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
188 0, /* value */
189 index, gspca_dev->usb_buf, length, 500);
190}
191
192static void reg_w_buf(struct gspca_dev *gspca_dev,
193 __u16 index, const __u8 *buffer, __u16 len)
194{
195 memcpy(gspca_dev->usb_buf, buffer, len);
196 usb_control_msg(gspca_dev->dev,
197 usb_sndctrlpipe(gspca_dev->dev, 0),
198 0, /* request */
199 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
200 0, /* value */
201 index, gspca_dev->usb_buf, len, 500);
202}
203
204static void i2c_init(struct gspca_dev *gspca_dev, __u8 mode)
205{
206 reg_w_val(gspca_dev->dev, 0x92, 0x8804);
207 reg_w_val(gspca_dev->dev, mode, 0x8802);
208}
209
210static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg)
211{
212 int retry = 60;
213 __u8 DataLow;
214 __u8 DataHight;
215
216 DataLow = valeur;
217 DataHight = valeur >> 8;
218 reg_w_val(gspca_dev->dev, reg, 0x8801);
219 reg_w_val(gspca_dev->dev, DataLow, 0x8805);
220 reg_w_val(gspca_dev->dev, DataHight, 0x8800);
221 while (retry--) {
222 reg_r(gspca_dev, 0x8803, 1);
223 if (!gspca_dev->usb_buf[0])
224 break;
225 }
226}
227
228static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
229{
230 int retry = 60;
231 __u8 value;
232 __u8 vallsb;
233
234 reg_w_val(gspca_dev->dev, 0x92, 0x8804);
235 reg_w_val(gspca_dev->dev, reg, 0x8801);
236 reg_w_val(gspca_dev->dev, (mode | 0x01), 0x8802);
237 while (retry--) {
238 reg_r(gspca_dev, 0x8803, 1);
239 if (!gspca_dev->usb_buf)
240 break;
241 }
242 if (retry == 0)
243 return -1;
244 reg_r(gspca_dev, 0x8800, 1);
245 value = gspca_dev->usb_buf[0];
246 reg_r(gspca_dev, 0x8805, 1);
247 vallsb = gspca_dev->usb_buf[0];
248 return ((int) value << 8) | vallsb;
249}
250
251static const __u16 spca561_init_data[][2] = {
252 {0x0000, 0x8114}, /* Software GPIO output data */
253 {0x0001, 0x8114}, /* Software GPIO output data */
254 {0x0000, 0x8112}, /* Some kind of reset */
255 {0x0003, 0x8701}, /* PCLK clock delay adjustment */
256 {0x0001, 0x8703}, /* HSYNC from cmos inverted */
257 {0x0011, 0x8118}, /* Enable and conf sensor */
258 {0x0001, 0x8118}, /* Conf sensor */
259 {0x0092, 0x8804}, /* I know nothing about these */
260 {0x0010, 0x8802}, /* 0x88xx registers, so I won't */
261 /***************/
262 {0x000d, 0x8805}, /* sensor default setting */
263 {0x0001, 0x8801}, /* 1 <- 0x0d */
264 {0x0000, 0x8800},
265 {0x0018, 0x8805},
266 {0x0002, 0x8801}, /* 2 <- 0x18 */
267 {0x0000, 0x8800},
268 {0x0065, 0x8805},
269 {0x0004, 0x8801}, /* 4 <- 0x01 0x65 */
270 {0x0001, 0x8800},
271 {0x0021, 0x8805},
272 {0x0005, 0x8801}, /* 5 <- 0x21 */
273 {0x0000, 0x8800},
274 {0x00aa, 0x8805},
275 {0x0007, 0x8801}, /* 7 <- 0xaa */
276 {0x0000, 0x8800},
277 {0x0004, 0x8805},
278 {0x0020, 0x8801}, /* 0x20 <- 0x15 0x04 */
279 {0x0015, 0x8800},
280 {0x0002, 0x8805},
281 {0x0039, 0x8801}, /* 0x39 <- 0x02 */
282 {0x0000, 0x8800},
283 {0x0010, 0x8805},
284 {0x0035, 0x8801}, /* 0x35 <- 0x10 */
285 {0x0000, 0x8800},
286 {0x0049, 0x8805},
287 {0x0009, 0x8801}, /* 0x09 <- 0x10 0x49 */
288 {0x0010, 0x8800},
289 {0x000b, 0x8805},
290 {0x0028, 0x8801}, /* 0x28 <- 0x0b */
291 {0x0000, 0x8800},
292 {0x000f, 0x8805},
293 {0x003b, 0x8801}, /* 0x3b <- 0x0f */
294 {0x0000, 0x8800},
295 {0x0000, 0x8805},
296 {0x003c, 0x8801}, /* 0x3c <- 0x00 */
297 {0x0000, 0x8800},
298 /***************/
299 {0x0018, 0x8601}, /* Pixel/line selection for color separation */
300 {0x0000, 0x8602}, /* Optical black level for user setting */
301 {0x0060, 0x8604}, /* Optical black horizontal offset */
302 {0x0002, 0x8605}, /* Optical black vertical offset */
303 {0x0000, 0x8603}, /* Non-automatic optical black level */
304 {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
305 {0x0000, 0x865f}, /* Vertical valid pixels window (x2) */
306 {0x00b0, 0x865d}, /* Horizontal valid pixels window (x2) */
307 {0x0090, 0x865e}, /* Vertical valid lines window (x2) */
308 {0x00e0, 0x8406}, /* Memory buffer threshold */
309 {0x0000, 0x8660}, /* Compensation memory stuff */
310 {0x0002, 0x8201}, /* Output address for r/w serial EEPROM */
311 {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */
312 {0x0001, 0x8200}, /* OprMode to be executed by hardware */
313 {0x0007, 0x8201}, /* Output address for r/w serial EEPROM */
314 {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */
315 {0x0001, 0x8200}, /* OprMode to be executed by hardware */
316 {0x0010, 0x8660}, /* Compensation memory stuff */
317 {0x0018, 0x8660}, /* Compensation memory stuff */
318
319 {0x0004, 0x8611}, /* R offset for white balance */
320 {0x0004, 0x8612}, /* Gr offset for white balance */
321 {0x0007, 0x8613}, /* B offset for white balance */
322 {0x0000, 0x8614}, /* Gb offset for white balance */
323 {0x008c, 0x8651}, /* R gain for white balance */
324 {0x008c, 0x8652}, /* Gr gain for white balance */
325 {0x00b5, 0x8653}, /* B gain for white balance */
326 {0x008c, 0x8654}, /* Gb gain for white balance */
327 {0x0002, 0x8502}, /* Maximum average bit rate stuff */
328
329 {0x0011, 0x8802},
330 {0x0087, 0x8700}, /* Set master clock (96Mhz????) */
331 {0x0081, 0x8702}, /* Master clock output enable */
332
333 {0x0000, 0x8500}, /* Set image type (352x288 no compression) */
334 /* Originally was 0x0010 (352x288 compression) */
335
336 {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
337 {0x0003, 0x865c}, /* Vertical offset for valid lines */
338 /***************//* sensor active */
339 {0x0003, 0x8801}, /* 0x03 <- 0x01 0x21 //289 */
340 {0x0021, 0x8805},
341 {0x0001, 0x8800},
342 {0x0004, 0x8801}, /* 0x04 <- 0x01 0x65 //357 */
343 {0x0065, 0x8805},
344 {0x0001, 0x8800},
345 {0x0005, 0x8801}, /* 0x05 <- 0x2f */
346 {0x002f, 0x8805},
347 {0x0000, 0x8800},
348 {0x0006, 0x8801}, /* 0x06 <- 0 */
349 {0x0000, 0x8805},
350 {0x0000, 0x8800},
351 {0x000a, 0x8801}, /* 0x0a <- 2 */
352 {0x0002, 0x8805},
353 {0x0000, 0x8800},
354 {0x0009, 0x8801}, /* 0x09 <- 0x1061 */
355 {0x0061, 0x8805},
356 {0x0010, 0x8800},
357 {0x0035, 0x8801}, /* 0x35 <-0x14 */
358 {0x0014, 0x8805},
359 {0x0000, 0x8800},
360 {0x0030, 0x8112}, /* ISO and drop packet enable */
361 {0x0000, 0x8112}, /* Some kind of reset ???? */
362 {0x0009, 0x8118}, /* Enable sensor and set standby */
363 {0x0000, 0x8114}, /* Software GPIO output data */
364 {0x0000, 0x8114}, /* Software GPIO output data */
365 {0x0001, 0x8114}, /* Software GPIO output data */
366 {0x0000, 0x8112}, /* Some kind of reset ??? */
367 {0x0003, 0x8701},
368 {0x0001, 0x8703},
369 {0x0011, 0x8118},
370 {0x0001, 0x8118},
371 /***************/
372 {0x0092, 0x8804},
373 {0x0010, 0x8802},
374 {0x000d, 0x8805},
375 {0x0001, 0x8801},
376 {0x0000, 0x8800},
377 {0x0018, 0x8805},
378 {0x0002, 0x8801},
379 {0x0000, 0x8800},
380 {0x0065, 0x8805},
381 {0x0004, 0x8801},
382 {0x0001, 0x8800},
383 {0x0021, 0x8805},
384 {0x0005, 0x8801},
385 {0x0000, 0x8800},
386 {0x00aa, 0x8805},
387 {0x0007, 0x8801}, /* mode 0xaa */
388 {0x0000, 0x8800},
389 {0x0004, 0x8805},
390 {0x0020, 0x8801},
391 {0x0015, 0x8800}, /* mode 0x0415 */
392 {0x0002, 0x8805},
393 {0x0039, 0x8801},
394 {0x0000, 0x8800},
395 {0x0010, 0x8805},
396 {0x0035, 0x8801},
397 {0x0000, 0x8800},
398 {0x0049, 0x8805},
399 {0x0009, 0x8801},
400 {0x0010, 0x8800},
401 {0x000b, 0x8805},
402 {0x0028, 0x8801},
403 {0x0000, 0x8800},
404 {0x000f, 0x8805},
405 {0x003b, 0x8801},
406 {0x0000, 0x8800},
407 {0x0000, 0x8805},
408 {0x003c, 0x8801},
409 {0x0000, 0x8800},
410 {0x0002, 0x8502},
411 {0x0039, 0x8801},
412 {0x0000, 0x8805},
413 {0x0000, 0x8800},
414
415 {0x0087, 0x8700}, /* overwrite by start */
416 {0x0081, 0x8702},
417 {0x0000, 0x8500},
418/* {0x0010, 0x8500}, -- Previous line was this */
419 {0x0002, 0x865b},
420 {0x0003, 0x865c},
421 /***************/
422 {0x0003, 0x8801}, /* 0x121-> 289 */
423 {0x0021, 0x8805},
424 {0x0001, 0x8800},
425 {0x0004, 0x8801}, /* 0x165 -> 357 */
426 {0x0065, 0x8805},
427 {0x0001, 0x8800},
428 {0x0005, 0x8801}, /* 0x2f //blanking control colonne */
429 {0x002f, 0x8805},
430 {0x0000, 0x8800},
431 {0x0006, 0x8801}, /* 0x00 //blanking mode row */
432 {0x0000, 0x8805},
433 {0x0000, 0x8800},
434 {0x000a, 0x8801}, /* 0x01 //0x02 */
435 {0x0001, 0x8805},
436 {0x0000, 0x8800},
437 {0x0009, 0x8801}, /* 0x1061 - setexposure times && pixel clock
438 * 0001 0 | 000 0110 0001 */
439 {0x0061, 0x8805}, /* 61 31 */
440 {0x0008, 0x8800}, /* 08 */
441 {0x0035, 0x8801}, /* 0x14 - set gain general */
442 {0x001f, 0x8805}, /* 0x14 */
443 {0x0000, 0x8800},
444 {0x0030, 0x8112},
445 {}
446};
447
448static void sensor_reset(struct gspca_dev *gspca_dev)
449{
450 reg_w_val(gspca_dev->dev, 0x8631, 0xc8);
451 reg_w_val(gspca_dev->dev, 0x8634, 0xc8);
452 reg_w_val(gspca_dev->dev, 0x8112, 0x00);
453 reg_w_val(gspca_dev->dev, 0x8114, 0x00);
454 reg_w_val(gspca_dev->dev, 0x8118, 0x21);
455 i2c_init(gspca_dev, 0x14);
456 i2c_write(gspca_dev, 1, 0x0d);
457 i2c_write(gspca_dev, 0, 0x0d);
458}
459
460/******************** QC Express etch2 stuff ********************/
461static const __u16 Pb100_1map8300[][2] = {
462 /* reg, value */
463 {0x8320, 0x3304},
464
465 {0x8303, 0x0125}, /* image area */
466 {0x8304, 0x0169},
467 {0x8328, 0x000b},
468 {0x833c, 0x0001},
469
470 {0x832f, 0x0419},
471 {0x8307, 0x00aa},
472 {0x8301, 0x0003},
473 {0x8302, 0x000e},
474 {}
475};
476static const __u16 Pb100_2map8300[][2] = {
477 /* reg, value */
478 {0x8339, 0x0000},
479 {0x8307, 0x00aa},
480 {}
481};
482
483static const __u16 spca561_161rev12A_data1[][2] = {
484 {0x21, 0x8118},
485 {0x01, 0x8114},
486 {0x00, 0x8112},
487 {0x92, 0x8804},
488 {0x04, 0x8802}, /* windows uses 08 */
489 {}
490};
491static const __u16 spca561_161rev12A_data2[][2] = {
492 {0x21, 0x8118},
493 {0x10, 0x8500},
494 {0x07, 0x8601},
495 {0x07, 0x8602},
496 {0x04, 0x8501},
497 {0x21, 0x8118},
498
499 {0x07, 0x8201}, /* windows uses 02 */
500 {0x08, 0x8200},
501 {0x01, 0x8200},
502
503 {0x00, 0x8114},
504 {0x01, 0x8114}, /* windows uses 00 */
505
506 {0x90, 0x8604},
507 {0x00, 0x8605},
508 {0xb0, 0x8603},
509
510 /* sensor gains */
511 {0x00, 0x8610}, /* *red */
512 {0x00, 0x8611}, /* 3f *green */
513 {0x00, 0x8612}, /* green *blue */
514 {0x00, 0x8613}, /* blue *green */
515 {0x35, 0x8614}, /* green *red */
516 {0x35, 0x8615}, /* 40 *green */
517 {0x35, 0x8616}, /* 7a *blue */
518 {0x35, 0x8617}, /* 40 *green */
519
520 {0x0c, 0x8620}, /* 0c */
521 {0xc8, 0x8631}, /* c8 */
522 {0xc8, 0x8634}, /* c8 */
523 {0x23, 0x8635}, /* 23 */
524 {0x1f, 0x8636}, /* 1f */
525 {0xdd, 0x8637}, /* dd */
526 {0xe1, 0x8638}, /* e1 */
527 {0x1d, 0x8639}, /* 1d */
528 {0x21, 0x863a}, /* 21 */
529 {0xe3, 0x863b}, /* e3 */
530 {0xdf, 0x863c}, /* df */
531 {0xf0, 0x8505},
532 {0x32, 0x850a},
533 {}
534};
535
536static void sensor_mapwrite(struct gspca_dev *gspca_dev,
537 const __u16 sensormap[][2])
538{
539 int i = 0;
540 __u8 usbval[2];
541
542 while (sensormap[i][0]) {
543 usbval[0] = sensormap[i][1];
544 usbval[1] = sensormap[i][1] >> 8;
545 reg_w_buf(gspca_dev, sensormap[i][0], usbval, 2);
546 i++;
547 }
548}
549static void init_161rev12A(struct gspca_dev *gspca_dev)
550{
551 sensor_reset(gspca_dev);
552 write_vector(gspca_dev, spca561_161rev12A_data1);
553 sensor_mapwrite(gspca_dev, Pb100_1map8300);
554 write_vector(gspca_dev, spca561_161rev12A_data2);
555 sensor_mapwrite(gspca_dev, Pb100_2map8300);
556}
557
558/* this function is called at probe time */
559static int sd_config(struct gspca_dev *gspca_dev,
560 const struct usb_device_id *id)
561{
562 struct sd *sd = (struct sd *) gspca_dev;
563 struct cam *cam;
564 __u16 vendor, product;
565 __u8 data1, data2;
566
567 /* Read frm global register the USB product and vendor IDs, just to
568 * prove that we can communicate with the device. This works, which
569 * confirms at we are communicating properly and that the device
570 * is a 561. */
571 reg_r(gspca_dev, 0x8104, 1);
572 data1 = gspca_dev->usb_buf[0];
573 reg_r(gspca_dev, 0x8105, 1);
574 data2 = gspca_dev->usb_buf[0];
575 vendor = (data2 << 8) | data1;
576 reg_r(gspca_dev, 0x8106, 1);
577 data1 = gspca_dev->usb_buf[0];
578 reg_r(gspca_dev, 0x8107, 1);
579 data2 = gspca_dev->usb_buf[0];
580 product = (data2 << 8) | data1;
581 if (vendor != id->idVendor || product != id->idProduct) {
582 PDEBUG(D_PROBE, "Bad vendor / product from device");
583 return -EINVAL;
584 }
585 switch (product) {
586 case 0x0928:
587 case 0x0929:
588 case 0x092a:
589 case 0x092b:
590 case 0x092c:
591 case 0x092d:
592 case 0x092e:
593 case 0x092f:
594 case 0x403b:
595 sd->chip_revision = Rev012A;
596 break;
597 default:
598/* case 0x0561:
599 case 0x0815: * ?? in spca508.c
600 case 0x401a:
601 case 0x7004:
602 case 0x7e50:
603 case 0xa001:
604 case 0xcdee: */
605 sd->chip_revision = Rev072A;
606 break;
607 }
608 cam = &gspca_dev->cam;
609 cam->dev_name = (char *) id->driver_info;
610 cam->epaddr = 0x01;
611 gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */
612 cam->cam_mode = sif_mode;
613 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
614 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
615 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
616 sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
617 return 0;
618}
619
620/* this function is called at open time */
621static int sd_open(struct gspca_dev *gspca_dev)
622{
623 struct sd *sd = (struct sd *) gspca_dev;
624
625 switch (sd->chip_revision) {
626 case Rev072A:
627 PDEBUG(D_STREAM, "Chip revision id: 072a");
628 write_vector(gspca_dev, spca561_init_data);
629 break;
630 default:
631/* case Rev012A: */
632 PDEBUG(D_STREAM, "Chip revision id: 012a");
633 init_161rev12A(gspca_dev);
634 break;
635 }
636 return 0;
637}
638
639static void setcontrast(struct gspca_dev *gspca_dev)
640{
641 struct sd *sd = (struct sd *) gspca_dev;
642 struct usb_device *dev = gspca_dev->dev;
643 __u8 lowb;
644 int expotimes;
645
646 switch (sd->chip_revision) {
647 case Rev072A:
648 lowb = sd->contrast >> 8;
649 reg_w_val(dev, lowb, 0x8651);
650 reg_w_val(dev, lowb, 0x8652);
651 reg_w_val(dev, lowb, 0x8653);
652 reg_w_val(dev, lowb, 0x8654);
653 break;
654 case Rev012A: {
655 __u8 Reg8391[] =
656 { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 };
657
658 /* Write camera sensor settings */
659 expotimes = (sd->contrast >> 5) & 0x07ff;
660 Reg8391[0] = expotimes & 0xff; /* exposure */
661 Reg8391[1] = 0x18 | (expotimes >> 8);
662 Reg8391[2] = sd->brightness; /* gain */
663 reg_w_buf(gspca_dev, 0x8391, Reg8391, 8);
664 reg_w_buf(gspca_dev, 0x8390, Reg8391, 8);
665 break;
666 }
667 }
668}
669
670static void sd_start(struct gspca_dev *gspca_dev)
671{
672 struct sd *sd = (struct sd *) gspca_dev;
673 struct usb_device *dev = gspca_dev->dev;
674 int Clck;
675 __u8 Reg8307[] = { 0xaa, 0x00 };
676 int mode;
677
678 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
679 switch (sd->chip_revision) {
680 case Rev072A:
681 switch (mode) {
682 default:
683/* case 0:
684 case 1: */
685 Clck = 0x25;
686 break;
687 case 2:
688 Clck = 0x22;
689 break;
690 case 3:
691 Clck = 0x21;
692 break;
693 }
694 reg_w_val(dev, 0x8500, mode); /* mode */
695 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
696 reg_w_val(dev, 0x8112, 0x10 | 0x20);
697 break;
698 default:
699/* case Rev012A: */
700 switch (mode) {
701 case 0:
702 case 1:
703 Clck = 0x8a;
704 break;
705 case 2:
706 Clck = 0x85;
707 break;
708 default:
709 Clck = 0x83;
710 break;
711 }
712 if (mode <= 1) {
713 /* Use compression on 320x240 and above */
714 reg_w_val(dev, 0x8500, 0x10 | mode);
715 } else {
716 /* I couldn't get the compression to work below 320x240
717 * Fortunately at these resolutions the bandwidth
718 * is sufficient to push raw frames at ~20fps */
719 reg_w_val(dev, 0x8500, mode);
720 } /* -- qq@kuku.eu.org */
721 reg_w_buf(gspca_dev, 0x8307, Reg8307, 2);
722 reg_w_val(gspca_dev->dev, 0x8700, Clck);
723 /* 0x8f 0x85 0x27 clock */
724 reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
725 reg_w_val(gspca_dev->dev, 0x850b, 0x03);
726 setcontrast(gspca_dev);
727 break;
728 }
729}
730
731static void sd_stopN(struct gspca_dev *gspca_dev)
732{
733 reg_w_val(gspca_dev->dev, 0x8112, 0x20);
734}
735
736static void sd_stop0(struct gspca_dev *gspca_dev)
737{
738}
739
740/* this function is called at close time */
741static void sd_close(struct gspca_dev *gspca_dev)
742{
743 reg_w_val(gspca_dev->dev, 0x8114, 0);
744}
745
746static void setautogain(struct gspca_dev *gspca_dev)
747{
748 struct sd *sd = (struct sd *) gspca_dev;
749 int expotimes = 0;
750 int pixelclk = 0;
751 int gainG = 0;
752 __u8 R, Gr, Gb, B;
753 int y;
754 __u8 luma_mean = 110;
755 __u8 luma_delta = 20;
756 __u8 spring = 4;
757
758 switch (sd->chip_revision) {
759 case Rev072A:
760 reg_r(gspca_dev, 0x8621, 1);
761 Gr = gspca_dev->usb_buf[0];
762 reg_r(gspca_dev, 0x8622, 1);
763 R = gspca_dev->usb_buf[0];
764 reg_r(gspca_dev, 0x8623, 1);
765 B = gspca_dev->usb_buf[0];
766 reg_r(gspca_dev, 0x8624, 1);
767 Gb = gspca_dev->usb_buf[0];
768 y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;
769 /* u= (128*B-(43*(Gr+Gb+R))) >> 8; */
770 /* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */
771 /* PDEBUG(D_CONF,"reading Y %d U %d V %d ",y,u,v); */
772
773 if (y < luma_mean - luma_delta ||
774 y > luma_mean + luma_delta) {
775 expotimes = i2c_read(gspca_dev, 0x09, 0x10);
776 pixelclk = 0x0800;
777 expotimes = expotimes & 0x07ff;
778 /* PDEBUG(D_PACK,
779 "Exposition Times 0x%03X Clock 0x%04X ",
780 expotimes,pixelclk); */
781 gainG = i2c_read(gspca_dev, 0x35, 0x10);
782 /* PDEBUG(D_PACK,
783 "reading Gain register %d", gainG); */
784
785 expotimes += (luma_mean - y) >> spring;
786 gainG += (luma_mean - y) / 50;
787 /* PDEBUG(D_PACK,
788 "compute expotimes %d gain %d",
789 expotimes,gainG); */
790
791 if (gainG > 0x3f)
792 gainG = 0x3f;
793 else if (gainG < 4)
794 gainG = 3;
795 i2c_write(gspca_dev, gainG, 0x35);
796
797 if (expotimes >= 0x0256)
798 expotimes = 0x0256;
799 else if (expotimes < 4)
800 expotimes = 3;
801 i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
802 }
803 break;
804 case Rev012A:
805 /* sensor registers is access and memory mapped to 0x8300 */
806 /* readind all 0x83xx block the sensor */
807 /*
808 * The data from the header seem wrong where is the luma
809 * and chroma mean value
810 * at the moment set exposure in contrast set
811 */
812 break;
813 }
814}
815
816static void sd_pkt_scan(struct gspca_dev *gspca_dev,
817 struct gspca_frame *frame, /* target */
818 __u8 *data, /* isoc packet */
819 int len) /* iso packet length */
820{
821 struct sd *sd = (struct sd *) gspca_dev;
822
823 switch (data[0]) {
824 case 0: /* start of frame */
825 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
826 data, 0);
827 if (sd->ag_cnt >= 0) {
828 if (--sd->ag_cnt < 0) {
829 sd->ag_cnt = AG_CNT_START;
830 setautogain(gspca_dev);
831 }
832 }
833 data += SPCA561_OFFSET_DATA;
834 len -= SPCA561_OFFSET_DATA;
835 if (data[1] & 0x10) {
836 /* compressed bayer */
837 gspca_frame_add(gspca_dev, FIRST_PACKET,
838 frame, data, len);
839 } else {
840 /* raw bayer (with a header, which we skip) */
841 data += 20;
842 len -= 20;
843 gspca_frame_add(gspca_dev, FIRST_PACKET,
844 frame, data, len);
845 }
846 return;
847 case 0xff: /* drop */
848/* gspca_dev->last_packet_type = DISCARD_PACKET; */
849 return;
850 }
851 data++;
852 len--;
853 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
854}
855
856static void setbrightness(struct gspca_dev *gspca_dev)
857{
858 struct sd *sd = (struct sd *) gspca_dev;
859 __u8 value;
860
861 switch (sd->chip_revision) {
862 case Rev072A:
863 value = sd->brightness;
864 reg_w_val(gspca_dev->dev, value, 0x8611);
865 reg_w_val(gspca_dev->dev, value, 0x8612);
866 reg_w_val(gspca_dev->dev, value, 0x8613);
867 reg_w_val(gspca_dev->dev, value, 0x8614);
868 break;
869 default:
870/* case Rev012A: */
871 setcontrast(gspca_dev);
872 break;
873 }
874}
875
876static void getbrightness(struct gspca_dev *gspca_dev)
877{
878 struct sd *sd = (struct sd *) gspca_dev;
879 __u16 tot;
880
881 switch (sd->chip_revision) {
882 case Rev072A:
883 tot = 0;
884 reg_r(gspca_dev, 0x8611, 1);
885 tot += gspca_dev->usb_buf[0];
886 reg_r(gspca_dev, 0x8612, 1);
887 tot += gspca_dev->usb_buf[0];
888 reg_r(gspca_dev, 0x8613, 1);
889 tot += gspca_dev->usb_buf[0];
890 reg_r(gspca_dev, 0x8614, 1);
891 tot += gspca_dev->usb_buf[0];
892 sd->brightness = tot >> 2;
893 break;
894 default:
895/* case Rev012A: */
896 /* no way to read sensor settings */
897 break;
898 }
899}
900
901static void getcontrast(struct gspca_dev *gspca_dev)
902{
903 struct sd *sd = (struct sd *) gspca_dev;
904 __u16 tot;
905
906 switch (sd->chip_revision) {
907 case Rev072A:
908 tot = 0;
909 reg_r(gspca_dev, 0x8651, 1);
910 tot += gspca_dev->usb_buf[0];
911 reg_r(gspca_dev, 0x8652, 1);
912 tot += gspca_dev->usb_buf[0];
913 reg_r(gspca_dev, 0x8653, 1);
914 tot += gspca_dev->usb_buf[0];
915 reg_r(gspca_dev, 0x8654, 1);
916 tot += gspca_dev->usb_buf[0];
917 sd->contrast = tot << 6;
918 break;
919 default:
920/* case Rev012A: */
921 /* no way to read sensor settings */
922 break;
923 }
924 PDEBUG(D_CONF, "get contrast %d", sd->contrast);
925}
926
927static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
928{
929 struct sd *sd = (struct sd *) gspca_dev;
930
931 sd->brightness = val;
932 if (gspca_dev->streaming)
933 setbrightness(gspca_dev);
934 return 0;
935}
936
937static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
938{
939 struct sd *sd = (struct sd *) gspca_dev;
940
941 getbrightness(gspca_dev);
942 *val = sd->brightness;
943 return 0;
944}
945
946static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
947{
948 struct sd *sd = (struct sd *) gspca_dev;
949
950 sd->contrast = val;
951 if (gspca_dev->streaming)
952 setcontrast(gspca_dev);
953 return 0;
954}
955
956static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
957{
958 struct sd *sd = (struct sd *) gspca_dev;
959
960 getcontrast(gspca_dev);
961 *val = sd->contrast;
962 return 0;
963}
964
965static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
966{
967 struct sd *sd = (struct sd *) gspca_dev;
968
969 sd->autogain = val;
970 if (val)
971 sd->ag_cnt = AG_CNT_START;
972 else
973 sd->ag_cnt = -1;
974 return 0;
975}
976
977static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
978{
979 struct sd *sd = (struct sd *) gspca_dev;
980
981 *val = sd->autogain;
982 return 0;
983}
984
985/* sub-driver description */
986static const struct sd_desc sd_desc = {
987 .name = MODULE_NAME,
988 .ctrls = sd_ctrls,
989 .nctrls = ARRAY_SIZE(sd_ctrls),
990 .config = sd_config,
991 .open = sd_open,
992 .start = sd_start,
993 .stopN = sd_stopN,
994 .stop0 = sd_stop0,
995 .close = sd_close,
996 .pkt_scan = sd_pkt_scan,
997};
998
999/* -- module initialisation -- */
1000#define DVNM(name) .driver_info = (kernel_ulong_t) name
1001static const __devinitdata struct usb_device_id device_table[] = {
1002 {USB_DEVICE(0x041e, 0x401a), DVNM("Creative Webcam Vista (PD1100)")},
1003 {USB_DEVICE(0x041e, 0x403b), DVNM("Creative Webcam Vista (VF0010)")},
1004 {USB_DEVICE(0x0458, 0x7004), DVNM("Genius VideoCAM Express V2")},
1005 {USB_DEVICE(0x046d, 0x0928), DVNM("Logitech QC Express Etch2")},
1006 {USB_DEVICE(0x046d, 0x0929), DVNM("Labtec Webcam Elch2")},
1007 {USB_DEVICE(0x046d, 0x092a), DVNM("Logitech QC for Notebook")},
1008 {USB_DEVICE(0x046d, 0x092b), DVNM("Labtec Webcam Plus")},
1009 {USB_DEVICE(0x046d, 0x092c), DVNM("Logitech QC chat Elch2")},
1010 {USB_DEVICE(0x046d, 0x092d), DVNM("Logitech QC Elch2")},
1011 {USB_DEVICE(0x046d, 0x092e), DVNM("Logitech QC Elch2")},
1012 {USB_DEVICE(0x046d, 0x092f), DVNM("Logitech QC Elch2")},
1013 {USB_DEVICE(0x04fc, 0x0561), DVNM("Flexcam 100")},
1014 {USB_DEVICE(0x060b, 0xa001), DVNM("Maxell Compact Pc PM3")},
1015 {USB_DEVICE(0x10fd, 0x7e50), DVNM("FlyCam Usb 100")},
1016 {USB_DEVICE(0xabcd, 0xcdee), DVNM("Petcam")},
1017 {}
1018};
1019
1020MODULE_DEVICE_TABLE(usb, device_table);
1021
1022/* -- device connect -- */
1023static int sd_probe(struct usb_interface *intf,
1024 const struct usb_device_id *id)
1025{
1026 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1027 THIS_MODULE);
1028}
1029
1030static struct usb_driver sd_driver = {
1031 .name = MODULE_NAME,
1032 .id_table = device_table,
1033 .probe = sd_probe,
1034 .disconnect = gspca_disconnect,
1035};
1036
1037/* -- module insert / remove -- */
1038static int __init sd_mod_init(void)
1039{
1040 if (usb_register(&sd_driver) < 0)
1041 return -1;
1042 PDEBUG(D_PROBE, "v%s registered", version);
1043 return 0;
1044}
1045static void __exit sd_mod_exit(void)
1046{
1047 usb_deregister(&sd_driver);
1048 PDEBUG(D_PROBE, "deregistered");
1049}
1050
1051module_init(sd_mod_init);
1052module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
new file mode 100644
index 000000000000..c78ee0d3e59b
--- /dev/null
+++ b/drivers/media/video/gspca/stk014.c
@@ -0,0 +1,592 @@
1/*
2 * Syntek DV4000 (STK014) subdriver
3 *
4 * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define MODULE_NAME "stk014"
22
23#include "gspca.h"
24#include "jpeg.h"
25
26#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
27static const char version[] = "2.1.7";
28
29MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
30MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
37 unsigned char brightness;
38 unsigned char contrast;
39 unsigned char colors;
40 unsigned char lightfreq;
41};
42
43/* global parameters */
44static int sd_quant = 7; /* <= 4 KO - 7: good (enough!) */
45
46/* V4L2 controls supported by the driver */
47static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
48static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
49static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
50static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
51static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
52static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
53static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
54static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
55
56static struct ctrl sd_ctrls[] = {
57 {
58 {
59 .id = V4L2_CID_BRIGHTNESS,
60 .type = V4L2_CTRL_TYPE_INTEGER,
61 .name = "Brightness",
62 .minimum = 0,
63 .maximum = 255,
64 .step = 1,
65#define BRIGHTNESS_DEF 127
66 .default_value = BRIGHTNESS_DEF,
67 },
68 .set = sd_setbrightness,
69 .get = sd_getbrightness,
70 },
71 {
72 {
73 .id = V4L2_CID_CONTRAST,
74 .type = V4L2_CTRL_TYPE_INTEGER,
75 .name = "Contrast",
76 .minimum = 0,
77 .maximum = 255,
78 .step = 1,
79#define CONTRAST_DEF 127
80 .default_value = CONTRAST_DEF,
81 },
82 .set = sd_setcontrast,
83 .get = sd_getcontrast,
84 },
85 {
86 {
87 .id = V4L2_CID_SATURATION,
88 .type = V4L2_CTRL_TYPE_INTEGER,
89 .name = "Color",
90 .minimum = 0,
91 .maximum = 255,
92 .step = 1,
93#define COLOR_DEF 127
94 .default_value = COLOR_DEF,
95 },
96 .set = sd_setcolors,
97 .get = sd_getcolors,
98 },
99 {
100 {
101 .id = V4L2_CID_POWER_LINE_FREQUENCY,
102 .type = V4L2_CTRL_TYPE_MENU,
103 .name = "Light frequency filter",
104 .minimum = 1,
105 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
106 .step = 1,
107#define FREQ_DEF 1
108 .default_value = FREQ_DEF,
109 },
110 .set = sd_setfreq,
111 .get = sd_getfreq,
112 },
113};
114
115static struct v4l2_pix_format vga_mode[] = {
116 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
117 .bytesperline = 320,
118 .sizeimage = 320 * 240 * 3 / 8 + 590,
119 .colorspace = V4L2_COLORSPACE_JPEG,
120 .priv = 1},
121 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
122 .bytesperline = 640,
123 .sizeimage = 640 * 480 * 3 / 8 + 590,
124 .colorspace = V4L2_COLORSPACE_JPEG,
125 .priv = 0},
126};
127
128/* -- read a register -- */
129static int reg_r(struct gspca_dev *gspca_dev,
130 __u16 index)
131{
132 struct usb_device *dev = gspca_dev->dev;
133 int ret;
134
135 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
136 0x00,
137 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
138 0x00,
139 index,
140 gspca_dev->usb_buf, 1,
141 500);
142 if (ret < 0) {
143 PDEBUG(D_ERR, "reg_r err %d", ret);
144 return ret;
145 }
146 return gspca_dev->usb_buf[0];
147}
148
149/* -- write a register -- */
150static int reg_w(struct gspca_dev *gspca_dev,
151 __u16 index, __u16 value)
152{
153 struct usb_device *dev = gspca_dev->dev;
154 int ret;
155
156 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
157 0x01,
158 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
159 value,
160 index,
161 NULL,
162 0,
163 500);
164 if (ret < 0)
165 PDEBUG(D_ERR, "reg_w err %d", ret);
166 return ret;
167}
168
169/* -- get a bulk value (4 bytes) -- */
170static int rcv_val(struct gspca_dev *gspca_dev,
171 int ads)
172{
173 struct usb_device *dev = gspca_dev->dev;
174 int alen, ret;
175
176 reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
177 reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
178 reg_w(gspca_dev, 0x636, ads & 0xff);
179 reg_w(gspca_dev, 0x637, 0);
180 reg_w(gspca_dev, 0x638, 4); /* len & 0xff */
181 reg_w(gspca_dev, 0x639, 0); /* len >> 8 */
182 reg_w(gspca_dev, 0x63a, 0);
183 reg_w(gspca_dev, 0x63b, 0);
184 reg_w(gspca_dev, 0x630, 5);
185 ret = usb_bulk_msg(dev,
186 usb_rcvbulkpipe(dev, 5),
187 gspca_dev->usb_buf,
188 4, /* length */
189 &alen,
190 500); /* timeout in milliseconds */
191 return ret;
192}
193
194/* -- send a bulk value -- */
195static int snd_val(struct gspca_dev *gspca_dev,
196 int ads,
197 unsigned int val)
198{
199 struct usb_device *dev = gspca_dev->dev;
200 int alen, ret;
201 __u8 seq = 0;
202
203 if (ads == 0x003f08) {
204 ret = reg_r(gspca_dev, 0x0704);
205 if (ret < 0)
206 goto ko;
207 ret = reg_r(gspca_dev, 0x0705);
208 if (ret < 0)
209 goto ko;
210 seq = ret; /* keep the sequence number */
211 ret = reg_r(gspca_dev, 0x0650);
212 if (ret < 0)
213 goto ko;
214 reg_w(gspca_dev, 0x654, seq);
215 } else {
216 reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
217 }
218 reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
219 reg_w(gspca_dev, 0x656, ads & 0xff);
220 reg_w(gspca_dev, 0x657, 0);
221 reg_w(gspca_dev, 0x658, 0x04); /* size */
222 reg_w(gspca_dev, 0x659, 0);
223 reg_w(gspca_dev, 0x65a, 0);
224 reg_w(gspca_dev, 0x65b, 0);
225 reg_w(gspca_dev, 0x650, 5);
226 gspca_dev->usb_buf[0] = val >> 24;
227 gspca_dev->usb_buf[1] = val >> 16;
228 gspca_dev->usb_buf[2] = val >> 8;
229 gspca_dev->usb_buf[3] = val;
230 ret = usb_bulk_msg(dev,
231 usb_sndbulkpipe(dev, 6),
232 gspca_dev->usb_buf,
233 4,
234 &alen,
235 500); /* timeout in milliseconds */
236 if (ret < 0)
237 goto ko;
238 if (ads == 0x003f08) {
239 seq += 4;
240 seq &= 0x3f;
241 reg_w(gspca_dev, 0x705, seq);
242 }
243 return ret;
244ko:
245 PDEBUG(D_ERR, "snd_val err %d", ret);
246 return ret;
247}
248
249/* set a camera parameter */
250static int set_par(struct gspca_dev *gspca_dev,
251 int parval)
252{
253 return snd_val(gspca_dev, 0x003f08, parval);
254}
255
256static void setbrightness(struct gspca_dev *gspca_dev)
257{
258 struct sd *sd = (struct sd *) gspca_dev;
259 int parval;
260
261 parval = 0x06000000 /* whiteness */
262 + (sd->brightness << 16);
263 set_par(gspca_dev, parval);
264}
265
266static void setcontrast(struct gspca_dev *gspca_dev)
267{
268 struct sd *sd = (struct sd *) gspca_dev;
269 int parval;
270
271 parval = 0x07000000 /* contrast */
272 + (sd->contrast << 16);
273 set_par(gspca_dev, parval);
274}
275
276static void setcolors(struct gspca_dev *gspca_dev)
277{
278 struct sd *sd = (struct sd *) gspca_dev;
279 int parval;
280
281 parval = 0x08000000 /* saturation */
282 + (sd->colors << 16);
283 set_par(gspca_dev, parval);
284}
285
286static void setfreq(struct gspca_dev *gspca_dev)
287{
288 struct sd *sd = (struct sd *) gspca_dev;
289
290 set_par(gspca_dev, sd->lightfreq == 1
291 ? 0x33640000 /* 50 Hz */
292 : 0x33780000); /* 60 Hz */
293}
294
295/* this function is called at probe time */
296static int sd_config(struct gspca_dev *gspca_dev,
297 const struct usb_device_id *id)
298{
299 struct sd *sd = (struct sd *) gspca_dev;
300 struct cam *cam = &gspca_dev->cam;
301
302 cam->dev_name = (char *) id->driver_info;
303 cam->epaddr = 0x02;
304 gspca_dev->cam.cam_mode = vga_mode;
305 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
306 sd->brightness = BRIGHTNESS_DEF;
307 sd->contrast = CONTRAST_DEF;
308 sd->colors = COLOR_DEF;
309 sd->lightfreq = FREQ_DEF;
310 return 0;
311}
312
313/* this function is called at open time */
314static int sd_open(struct gspca_dev *gspca_dev)
315{
316 int ret;
317
318 /* check if the device responds */
319 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
320 ret = reg_r(gspca_dev, 0x0740);
321 if (ret < 0)
322 return ret;
323 if (ret != 0xff) {
324 PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", ret);
325 return -1;
326 }
327 return 0;
328}
329
330/* -- start the camera -- */
331static void sd_start(struct gspca_dev *gspca_dev)
332{
333 int ret, value;
334
335 /* work on alternate 1 */
336 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
337
338 set_par(gspca_dev, 0x10000000);
339 set_par(gspca_dev, 0x00000000);
340 set_par(gspca_dev, 0x8002e001);
341 set_par(gspca_dev, 0x14000000);
342 if (gspca_dev->width > 320)
343 value = 0x8002e001; /* 640x480 */
344 else
345 value = 0x4001f000; /* 320x240 */
346 set_par(gspca_dev, value);
347 ret = usb_set_interface(gspca_dev->dev,
348 gspca_dev->iface,
349 gspca_dev->alt);
350 if (ret < 0) {
351 PDEBUG(D_ERR|D_STREAM, "set intf %d %d failed",
352 gspca_dev->iface, gspca_dev->alt);
353 goto out;
354 }
355 ret = reg_r(gspca_dev, 0x0630);
356 if (ret < 0)
357 goto out;
358 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
359 ret = reg_r(gspca_dev, 0x0650);
360 if (ret < 0)
361 goto out;
362 snd_val(gspca_dev, 0x000020, 0xffffffff);
363 reg_w(gspca_dev, 0x0620, 0);
364 reg_w(gspca_dev, 0x0630, 0);
365 reg_w(gspca_dev, 0x0640, 0);
366 reg_w(gspca_dev, 0x0650, 0);
367 reg_w(gspca_dev, 0x0660, 0);
368 setbrightness(gspca_dev); /* whiteness */
369 setcontrast(gspca_dev); /* contrast */
370 setcolors(gspca_dev); /* saturation */
371 set_par(gspca_dev, 0x09800000); /* Red ? */
372 set_par(gspca_dev, 0x0a800000); /* Green ? */
373 set_par(gspca_dev, 0x0b800000); /* Blue ? */
374 set_par(gspca_dev, 0x0d030000); /* Gamma ? */
375 setfreq(gspca_dev); /* light frequency */
376
377 /* start the video flow */
378 set_par(gspca_dev, 0x01000000);
379 set_par(gspca_dev, 0x01000000);
380 PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
381 return;
382out:
383 PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret);
384}
385
386static void sd_stopN(struct gspca_dev *gspca_dev)
387{
388 struct usb_device *dev = gspca_dev->dev;
389
390 set_par(gspca_dev, 0x02000000);
391 set_par(gspca_dev, 0x02000000);
392 usb_set_interface(dev, gspca_dev->iface, 1);
393 reg_r(gspca_dev, 0x0630);
394 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
395 reg_r(gspca_dev, 0x0650);
396 snd_val(gspca_dev, 0x000020, 0xffffffff);
397 reg_w(gspca_dev, 0x0620, 0);
398 reg_w(gspca_dev, 0x0630, 0);
399 reg_w(gspca_dev, 0x0640, 0);
400 reg_w(gspca_dev, 0x0650, 0);
401 reg_w(gspca_dev, 0x0660, 0);
402 PDEBUG(D_STREAM, "camera stopped");
403}
404
405static void sd_stop0(struct gspca_dev *gspca_dev)
406{
407}
408
409static void sd_close(struct gspca_dev *gspca_dev)
410{
411}
412
413static void sd_pkt_scan(struct gspca_dev *gspca_dev,
414 struct gspca_frame *frame, /* target */
415 __u8 *data, /* isoc packet */
416 int len) /* iso packet length */
417{
418 static unsigned char ffd9[] = {0xff, 0xd9};
419
420 /* a frame starts with:
421 * - 0xff 0xfe
422 * - 0x08 0x00 - length (little endian ?!)
423 * - 4 bytes = size of whole frame (BE - including header)
424 * - 0x00 0x0c
425 * - 0xff 0xd8
426 * - .. JPEG image with escape sequences (ff 00)
427 * (without ending - ff d9)
428 */
429 if (data[0] == 0xff && data[1] == 0xfe) {
430 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
431 ffd9, 2);
432
433 /* put the JPEG 411 header */
434 jpeg_put_header(gspca_dev, frame, sd_quant, 0x22);
435
436 /* beginning of the frame */
437#define STKHDRSZ 12
438 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
439 data + STKHDRSZ, len - STKHDRSZ);
440#undef STKHDRSZ
441 return;
442 }
443 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
444}
445
446static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
447{
448 struct sd *sd = (struct sd *) gspca_dev;
449
450 sd->brightness = val;
451 if (gspca_dev->streaming)
452 setbrightness(gspca_dev);
453 return 0;
454}
455
456static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
457{
458 struct sd *sd = (struct sd *) gspca_dev;
459
460 *val = sd->brightness;
461 return 0;
462}
463
464static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
465{
466 struct sd *sd = (struct sd *) gspca_dev;
467
468 sd->contrast = val;
469 if (gspca_dev->streaming)
470 setcontrast(gspca_dev);
471 return 0;
472}
473
474static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
475{
476 struct sd *sd = (struct sd *) gspca_dev;
477
478 *val = sd->contrast;
479 return 0;
480}
481
482static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
483{
484 struct sd *sd = (struct sd *) gspca_dev;
485
486 sd->colors = val;
487 if (gspca_dev->streaming)
488 setcolors(gspca_dev);
489 return 0;
490}
491
492static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
493{
494 struct sd *sd = (struct sd *) gspca_dev;
495
496 *val = sd->colors;
497 return 0;
498}
499
500static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
501{
502 struct sd *sd = (struct sd *) gspca_dev;
503
504 sd->lightfreq = val;
505 if (gspca_dev->streaming)
506 setfreq(gspca_dev);
507 return 0;
508}
509
510static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
511{
512 struct sd *sd = (struct sd *) gspca_dev;
513
514 *val = sd->lightfreq;
515 return 0;
516}
517
518static int sd_querymenu(struct gspca_dev *gspca_dev,
519 struct v4l2_querymenu *menu)
520{
521 switch (menu->id) {
522 case V4L2_CID_POWER_LINE_FREQUENCY:
523 switch (menu->index) {
524 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
525 strcpy((char *) menu->name, "50 Hz");
526 return 0;
527 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
528 strcpy((char *) menu->name, "60 Hz");
529 return 0;
530 }
531 break;
532 }
533 return -EINVAL;
534}
535
536/* sub-driver description */
537static const struct sd_desc sd_desc = {
538 .name = MODULE_NAME,
539 .ctrls = sd_ctrls,
540 .nctrls = ARRAY_SIZE(sd_ctrls),
541 .config = sd_config,
542 .open = sd_open,
543 .start = sd_start,
544 .stopN = sd_stopN,
545 .stop0 = sd_stop0,
546 .close = sd_close,
547 .pkt_scan = sd_pkt_scan,
548 .querymenu = sd_querymenu,
549};
550
551/* -- module initialisation -- */
552#define DVNM(name) .driver_info = (kernel_ulong_t) name
553static const __devinitdata struct usb_device_id device_table[] = {
554 {USB_DEVICE(0x05e1, 0x0893), DVNM("Syntek DV4000")},
555 {}
556};
557MODULE_DEVICE_TABLE(usb, device_table);
558
559/* -- device connect -- */
560static int sd_probe(struct usb_interface *intf,
561 const struct usb_device_id *id)
562{
563 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
564 THIS_MODULE);
565}
566
567static struct usb_driver sd_driver = {
568 .name = MODULE_NAME,
569 .id_table = device_table,
570 .probe = sd_probe,
571 .disconnect = gspca_disconnect,
572};
573
574/* -- module insert / remove -- */
575static int __init sd_mod_init(void)
576{
577 if (usb_register(&sd_driver) < 0)
578 return -1;
579 info("v%s registered", version);
580 return 0;
581}
582static void __exit sd_mod_exit(void)
583{
584 usb_deregister(&sd_driver);
585 info("deregistered");
586}
587
588module_init(sd_mod_init);
589module_exit(sd_mod_exit);
590
591module_param_named(quant, sd_quant, int, 0644);
592MODULE_PARM_DESC(quant, "Quantization index (0..8)");
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
new file mode 100644
index 000000000000..abd7bef9b3d1
--- /dev/null
+++ b/drivers/media/video/gspca/sunplus.c
@@ -0,0 +1,1677 @@
1/*
2 * Sunplus spca504(abc) spca533 spca536 library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "sunplus"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 8)
28static const char version[] = "2.1.8";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 __u8 packet[ISO_MAX_SIZE + 128];
39 /* !! no more than 128 ff in an ISO packet */
40
41 unsigned char brightness;
42 unsigned char contrast;
43 unsigned char colors;
44 unsigned char autogain;
45
46 char qindex;
47 char bridge;
48#define BRIDGE_SPCA504 0
49#define BRIDGE_SPCA504B 1
50#define BRIDGE_SPCA504C 2
51#define BRIDGE_SPCA533 3
52#define BRIDGE_SPCA536 4
53 char subtype;
54#define AiptekMiniPenCam13 1
55#define LogitechClickSmart420 2
56#define LogitechClickSmart820 3
57#define MegapixV4 4
58};
59
60/* V4L2 controls supported by the driver */
61static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
69
70static struct ctrl sd_ctrls[] = {
71#define SD_BRIGHTNESS 0
72 {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
78 .maximum = 0xff,
79 .step = 1,
80 .default_value = 0,
81 },
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
84 },
85#define SD_CONTRAST 1
86 {
87 {
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Contrast",
91 .minimum = 0,
92 .maximum = 0xff,
93 .step = 1,
94 .default_value = 0x20,
95 },
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
98 },
99#define SD_COLOR 2
100 {
101 {
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Color",
105 .minimum = 0,
106 .maximum = 0xff,
107 .step = 1,
108 .default_value = 0x1a,
109 },
110 .set = sd_setcolors,
111 .get = sd_getcolors,
112 },
113#define SD_AUTOGAIN 3
114 {
115 {
116 .id = V4L2_CID_AUTOGAIN,
117 .type = V4L2_CTRL_TYPE_BOOLEAN,
118 .name = "Auto Gain",
119 .minimum = 0,
120 .maximum = 1,
121 .step = 1,
122 .default_value = 1,
123 },
124 .set = sd_setautogain,
125 .get = sd_getautogain,
126 },
127};
128
129static struct v4l2_pix_format vga_mode[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 320,
132 .sizeimage = 320 * 240 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 2},
135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 640,
137 .sizeimage = 640 * 480 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 1},
140};
141
142static struct v4l2_pix_format custom_mode[] = {
143 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .bytesperline = 320,
145 .sizeimage = 320 * 240 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
147 .priv = 2},
148 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
149 .bytesperline = 464,
150 .sizeimage = 464 * 480 * 3 / 8 + 590,
151 .colorspace = V4L2_COLORSPACE_JPEG,
152 .priv = 1},
153};
154
155static struct v4l2_pix_format vga_mode2[] = {
156 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
157 .bytesperline = 176,
158 .sizeimage = 176 * 144 * 3 / 8 + 590,
159 .colorspace = V4L2_COLORSPACE_JPEG,
160 .priv = 4},
161 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
162 .bytesperline = 320,
163 .sizeimage = 320 * 240 * 3 / 8 + 590,
164 .colorspace = V4L2_COLORSPACE_JPEG,
165 .priv = 3},
166 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
167 .bytesperline = 352,
168 .sizeimage = 352 * 288 * 3 / 8 + 590,
169 .colorspace = V4L2_COLORSPACE_JPEG,
170 .priv = 2},
171 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
172 .bytesperline = 640,
173 .sizeimage = 640 * 480 * 3 / 8 + 590,
174 .colorspace = V4L2_COLORSPACE_JPEG,
175 .priv = 1},
176};
177
178#define SPCA50X_OFFSET_DATA 10
179#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
180#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
181#define SPCA504_PCCAM600_OFFSET_MODE 5
182#define SPCA504_PCCAM600_OFFSET_DATA 14
183 /* Frame packet header offsets for the spca533 */
184#define SPCA533_OFFSET_DATA 16
185#define SPCA533_OFFSET_FRAMSEQ 15
186/* Frame packet header offsets for the spca536 */
187#define SPCA536_OFFSET_DATA 4
188#define SPCA536_OFFSET_FRAMSEQ 1
189
190/* Initialisation data for the Creative PC-CAM 600 */
191static const __u16 spca504_pccam600_init_data[][3] = {
192/* {0xa0, 0x0000, 0x0503}, * capture mode */
193 {0x00, 0x0000, 0x2000},
194 {0x00, 0x0013, 0x2301},
195 {0x00, 0x0003, 0x2000},
196 {0x00, 0x0001, 0x21ac},
197 {0x00, 0x0001, 0x21a6},
198 {0x00, 0x0000, 0x21a7}, /* brightness */
199 {0x00, 0x0020, 0x21a8}, /* contrast */
200 {0x00, 0x0001, 0x21ac}, /* sat/hue */
201 {0x00, 0x0000, 0x21ad}, /* hue */
202 {0x00, 0x001a, 0x21ae}, /* saturation */
203 {0x00, 0x0002, 0x21a3}, /* gamma */
204 {0x30, 0x0154, 0x0008},
205 {0x30, 0x0004, 0x0006},
206 {0x30, 0x0258, 0x0009},
207 {0x30, 0x0004, 0x0000},
208 {0x30, 0x0093, 0x0004},
209 {0x30, 0x0066, 0x0005},
210 {0x00, 0x0000, 0x2000},
211 {0x00, 0x0013, 0x2301},
212 {0x00, 0x0003, 0x2000},
213 {0x00, 0x0013, 0x2301},
214 {0x00, 0x0003, 0x2000},
215 {}
216};
217
218/* Creative PC-CAM 600 specific open data, sent before using the
219 * generic initialisation data from spca504_open_data.
220 */
221static const __u16 spca504_pccam600_open_data[][3] = {
222 {0x00, 0x0001, 0x2501},
223 {0x20, 0x0500, 0x0001}, /* snapshot mode */
224 {0x00, 0x0003, 0x2880},
225 {0x00, 0x0001, 0x2881},
226 {}
227};
228
229/* Initialisation data for the logitech clicksmart 420 */
230static const __u16 spca504A_clicksmart420_init_data[][3] = {
231/* {0xa0, 0x0000, 0x0503}, * capture mode */
232 {0x00, 0x0000, 0x2000},
233 {0x00, 0x0013, 0x2301},
234 {0x00, 0x0003, 0x2000},
235 {0x00, 0x0001, 0x21ac},
236 {0x00, 0x0001, 0x21a6},
237 {0x00, 0x0000, 0x21a7}, /* brightness */
238 {0x00, 0x0020, 0x21a8}, /* contrast */
239 {0x00, 0x0001, 0x21ac}, /* sat/hue */
240 {0x00, 0x0000, 0x21ad}, /* hue */
241 {0x00, 0x001a, 0x21ae}, /* saturation */
242 {0x00, 0x0002, 0x21a3}, /* gamma */
243 {0x30, 0x0004, 0x000a},
244 {0xb0, 0x0001, 0x0000},
245
246
247 {0x0a1, 0x0080, 0x0001},
248 {0x30, 0x0049, 0x0000},
249 {0x30, 0x0060, 0x0005},
250 {0x0c, 0x0004, 0x0000},
251 {0x00, 0x0000, 0x0000},
252 {0x00, 0x0000, 0x2000},
253 {0x00, 0x0013, 0x2301},
254 {0x00, 0x0003, 0x2000},
255 {0x00, 0x0000, 0x2000},
256
257 {}
258};
259
260/* clicksmart 420 open data ? */
261static const __u16 spca504A_clicksmart420_open_data[][3] = {
262 {0x00, 0x0001, 0x2501},
263 {0x20, 0x0502, 0x0000},
264 {0x06, 0x0000, 0x0000},
265 {0x00, 0x0004, 0x2880},
266 {0x00, 0x0001, 0x2881},
267/* look like setting a qTable */
268 {0x00, 0x0006, 0x2800},
269 {0x00, 0x0004, 0x2801},
270 {0x00, 0x0004, 0x2802},
271 {0x00, 0x0006, 0x2803},
272 {0x00, 0x000a, 0x2804},
273 {0x00, 0x0010, 0x2805},
274 {0x00, 0x0014, 0x2806},
275 {0x00, 0x0018, 0x2807},
276 {0x00, 0x0005, 0x2808},
277 {0x00, 0x0005, 0x2809},
278 {0x00, 0x0006, 0x280a},
279 {0x00, 0x0008, 0x280b},
280 {0x00, 0x000a, 0x280c},
281 {0x00, 0x0017, 0x280d},
282 {0x00, 0x0018, 0x280e},
283 {0x00, 0x0016, 0x280f},
284
285 {0x00, 0x0006, 0x2810},
286 {0x00, 0x0005, 0x2811},
287 {0x00, 0x0006, 0x2812},
288 {0x00, 0x000a, 0x2813},
289 {0x00, 0x0010, 0x2814},
290 {0x00, 0x0017, 0x2815},
291 {0x00, 0x001c, 0x2816},
292 {0x00, 0x0016, 0x2817},
293 {0x00, 0x0006, 0x2818},
294 {0x00, 0x0007, 0x2819},
295 {0x00, 0x0009, 0x281a},
296 {0x00, 0x000c, 0x281b},
297 {0x00, 0x0014, 0x281c},
298 {0x00, 0x0023, 0x281d},
299 {0x00, 0x0020, 0x281e},
300 {0x00, 0x0019, 0x281f},
301
302 {0x00, 0x0007, 0x2820},
303 {0x00, 0x0009, 0x2821},
304 {0x00, 0x000f, 0x2822},
305 {0x00, 0x0016, 0x2823},
306 {0x00, 0x001b, 0x2824},
307 {0x00, 0x002c, 0x2825},
308 {0x00, 0x0029, 0x2826},
309 {0x00, 0x001f, 0x2827},
310 {0x00, 0x000a, 0x2828},
311 {0x00, 0x000e, 0x2829},
312 {0x00, 0x0016, 0x282a},
313 {0x00, 0x001a, 0x282b},
314 {0x00, 0x0020, 0x282c},
315 {0x00, 0x002a, 0x282d},
316 {0x00, 0x002d, 0x282e},
317 {0x00, 0x0025, 0x282f},
318
319 {0x00, 0x0014, 0x2830},
320 {0x00, 0x001a, 0x2831},
321 {0x00, 0x001f, 0x2832},
322 {0x00, 0x0023, 0x2833},
323 {0x00, 0x0029, 0x2834},
324 {0x00, 0x0030, 0x2835},
325 {0x00, 0x0030, 0x2836},
326 {0x00, 0x0028, 0x2837},
327 {0x00, 0x001d, 0x2838},
328 {0x00, 0x0025, 0x2839},
329 {0x00, 0x0026, 0x283a},
330 {0x00, 0x0027, 0x283b},
331 {0x00, 0x002d, 0x283c},
332 {0x00, 0x0028, 0x283d},
333 {0x00, 0x0029, 0x283e},
334 {0x00, 0x0028, 0x283f},
335
336 {0x00, 0x0007, 0x2840},
337 {0x00, 0x0007, 0x2841},
338 {0x00, 0x000a, 0x2842},
339 {0x00, 0x0013, 0x2843},
340 {0x00, 0x0028, 0x2844},
341 {0x00, 0x0028, 0x2845},
342 {0x00, 0x0028, 0x2846},
343 {0x00, 0x0028, 0x2847},
344 {0x00, 0x0007, 0x2848},
345 {0x00, 0x0008, 0x2849},
346 {0x00, 0x000a, 0x284a},
347 {0x00, 0x001a, 0x284b},
348 {0x00, 0x0028, 0x284c},
349 {0x00, 0x0028, 0x284d},
350 {0x00, 0x0028, 0x284e},
351 {0x00, 0x0028, 0x284f},
352
353 {0x00, 0x000a, 0x2850},
354 {0x00, 0x000a, 0x2851},
355 {0x00, 0x0016, 0x2852},
356 {0x00, 0x0028, 0x2853},
357 {0x00, 0x0028, 0x2854},
358 {0x00, 0x0028, 0x2855},
359 {0x00, 0x0028, 0x2856},
360 {0x00, 0x0028, 0x2857},
361 {0x00, 0x0013, 0x2858},
362 {0x00, 0x001a, 0x2859},
363 {0x00, 0x0028, 0x285a},
364 {0x00, 0x0028, 0x285b},
365 {0x00, 0x0028, 0x285c},
366 {0x00, 0x0028, 0x285d},
367 {0x00, 0x0028, 0x285e},
368 {0x00, 0x0028, 0x285f},
369
370 {0x00, 0x0028, 0x2860},
371 {0x00, 0x0028, 0x2861},
372 {0x00, 0x0028, 0x2862},
373 {0x00, 0x0028, 0x2863},
374 {0x00, 0x0028, 0x2864},
375 {0x00, 0x0028, 0x2865},
376 {0x00, 0x0028, 0x2866},
377 {0x00, 0x0028, 0x2867},
378 {0x00, 0x0028, 0x2868},
379 {0x00, 0x0028, 0x2869},
380 {0x00, 0x0028, 0x286a},
381 {0x00, 0x0028, 0x286b},
382 {0x00, 0x0028, 0x286c},
383 {0x00, 0x0028, 0x286d},
384 {0x00, 0x0028, 0x286e},
385 {0x00, 0x0028, 0x286f},
386
387 {0x00, 0x0028, 0x2870},
388 {0x00, 0x0028, 0x2871},
389 {0x00, 0x0028, 0x2872},
390 {0x00, 0x0028, 0x2873},
391 {0x00, 0x0028, 0x2874},
392 {0x00, 0x0028, 0x2875},
393 {0x00, 0x0028, 0x2876},
394 {0x00, 0x0028, 0x2877},
395 {0x00, 0x0028, 0x2878},
396 {0x00, 0x0028, 0x2879},
397 {0x00, 0x0028, 0x287a},
398 {0x00, 0x0028, 0x287b},
399 {0x00, 0x0028, 0x287c},
400 {0x00, 0x0028, 0x287d},
401 {0x00, 0x0028, 0x287e},
402 {0x00, 0x0028, 0x287f},
403
404 {0xa0, 0x0000, 0x0503},
405 {}
406};
407
408static const __u8 qtable_creative_pccam[2][64] = {
409 { /* Q-table Y-components */
410 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
411 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
412 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
413 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
414 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
415 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
416 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
417 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
418 { /* Q-table C-components */
419 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
421 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
424 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
425 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
426 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
427};
428
429/* FIXME: This Q-table is identical to the Creative PC-CAM one,
430 * except for one byte. Possibly a typo?
431 * NWG: 18/05/2003.
432 */
433static const __u8 qtable_spca504_default[2][64] = {
434 { /* Q-table Y-components */
435 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
436 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
437 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
438 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
439 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
440 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
441 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
442 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
443 },
444 { /* Q-table C-components */
445 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
446 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
447 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
450 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
451 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
452 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
453};
454
455static void reg_r(struct usb_device *dev,
456 __u16 req,
457 __u16 index,
458 __u8 *buffer, __u16 length)
459{
460 usb_control_msg(dev,
461 usb_rcvctrlpipe(dev, 0),
462 req,
463 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
464 0, /* value */
465 index, buffer, length,
466 500);
467}
468
469static void reg_w(struct usb_device *dev,
470 __u16 req,
471 __u16 value,
472 __u16 index,
473 __u8 *buffer, __u16 length)
474{
475 usb_control_msg(dev,
476 usb_sndctrlpipe(dev, 0),
477 req,
478 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
479 value, index, buffer, length,
480 500);
481}
482
483/* write req / index / value */
484static int reg_w_riv(struct usb_device *dev,
485 __u16 req, __u16 index, __u16 value)
486{
487 int ret;
488
489 ret = usb_control_msg(dev,
490 usb_sndctrlpipe(dev, 0),
491 req,
492 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
493 value, index, NULL, 0, 500);
494 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
495 req, index, value, ret);
496 if (ret < 0)
497 PDEBUG(D_ERR, "reg write: error %d", ret);
498 return ret;
499}
500
501/* read 1 byte */
502static int reg_r_1(struct gspca_dev *gspca_dev,
503 __u16 value) /* wValue */
504{
505 int ret;
506
507 ret = usb_control_msg(gspca_dev->dev,
508 usb_rcvctrlpipe(gspca_dev->dev, 0),
509 0x20, /* request */
510 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
511 value,
512 0, /* index */
513 gspca_dev->usb_buf, 1,
514 500); /* timeout */
515 if (ret < 0) {
516 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
517 return 0;
518 }
519 return gspca_dev->usb_buf[0];
520}
521
522/* read 1 or 2 bytes - returns < 0 if error */
523static int reg_r_12(struct gspca_dev *gspca_dev,
524 __u16 req, /* bRequest */
525 __u16 index, /* wIndex */
526 __u16 length) /* wLength (1 or 2 only) */
527{
528 int ret;
529
530 gspca_dev->usb_buf[1] = 0;
531 ret = usb_control_msg(gspca_dev->dev,
532 usb_rcvctrlpipe(gspca_dev->dev, 0),
533 req,
534 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
535 0, /* value */
536 index,
537 gspca_dev->usb_buf, length,
538 500);
539 if (ret < 0) {
540 PDEBUG(D_ERR, "reg_read err %d", ret);
541 return -1;
542 }
543 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
544}
545
546static int write_vector(struct gspca_dev *gspca_dev,
547 const __u16 data[][3])
548{
549 struct usb_device *dev = gspca_dev->dev;
550 int ret, i = 0;
551
552 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
553 ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
554 if (ret < 0) {
555 PDEBUG(D_ERR,
556 "Register write failed for 0x%x,0x%x,0x%x",
557 data[i][0], data[i][1], data[i][2]);
558 return ret;
559 }
560 i++;
561 }
562 return 0;
563}
564
565static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
566 unsigned int request,
567 unsigned int ybase,
568 unsigned int cbase,
569 const __u8 qtable[2][64])
570{
571 struct usb_device *dev = gspca_dev->dev;
572 int i, err;
573
574 /* loop over y components */
575 for (i = 0; i < 64; i++) {
576 err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
577 if (err < 0)
578 return err;
579 }
580
581 /* loop over c components */
582 for (i = 0; i < 64; i++) {
583 err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
584 if (err < 0)
585 return err;
586 }
587 return 0;
588}
589
590static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
591 __u16 req, __u16 idx, __u16 val)
592{
593 struct usb_device *dev = gspca_dev->dev;
594 __u8 notdone;
595
596 reg_w_riv(dev, req, idx, val);
597 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
598 reg_w_riv(dev, req, idx, val);
599
600 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
601
602 msleep(200);
603 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
604 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
605}
606
607static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
608 __u16 req,
609 __u16 idx, __u16 val, __u8 stat, __u8 count)
610{
611 struct usb_device *dev = gspca_dev->dev;
612 __u8 status;
613 __u8 endcode;
614
615 reg_w_riv(dev, req, idx, val);
616 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
617 endcode = stat;
618 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
619 if (!count)
620 return;
621 count = 200;
622 while (--count > 0) {
623 msleep(10);
624 /* gsmart mini2 write a each wait setting 1 ms is enought */
625/* reg_w_riv(dev, req, idx, val); */
626 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
627 if (status == endcode) {
628 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
629 status, 200 - count);
630 break;
631 }
632 }
633}
634
635static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
636{
637 int count = 10;
638
639 while (--count > 0) {
640 reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
641 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
642 break;
643 msleep(10);
644 }
645 return gspca_dev->usb_buf[0];
646}
647
648static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
649{
650 struct usb_device *dev = gspca_dev->dev;
651 int count = 50;
652
653 while (--count > 0) {
654 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
655 if (gspca_dev->usb_buf[0] != 0) {
656 gspca_dev->usb_buf[0] = 0;
657 reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
658 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
659 spca504B_PollingDataReady(gspca_dev);
660 break;
661 }
662 msleep(10);
663 }
664}
665
666static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
667{
668 struct usb_device *dev = gspca_dev->dev;
669 __u8 *data;
670
671 data = kmalloc(64, GFP_KERNEL);
672 reg_r(dev, 0x20, 0, data, 5);
673 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
674 data[0], data[1], data[2], data[3], data[4]);
675 reg_r(dev, 0x23, 0, data, 64);
676 reg_r(dev, 0x23, 1, data, 64);
677 kfree(data);
678}
679
680static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683 struct usb_device *dev = gspca_dev->dev;
684 __u8 Size;
685 __u8 Type;
686 int rc;
687
688 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
689 Type = 0;
690 switch (sd->bridge) {
691 case BRIDGE_SPCA533:
692 reg_w(dev, 0x31, 0, 0, NULL, 0);
693 spca504B_WaitCmdStatus(gspca_dev);
694 rc = spca504B_PollingDataReady(gspca_dev);
695 spca50x_GetFirmware(gspca_dev);
696 gspca_dev->usb_buf[0] = 2; /* type */
697 reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
698 reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
699
700 gspca_dev->usb_buf[0] = Size;
701 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
702 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
703 rc = spca504B_PollingDataReady(gspca_dev);
704
705 /* Init the cam width height with some values get on init ? */
706 reg_w(dev, 0x31, 0, 4, NULL, 0);
707 spca504B_WaitCmdStatus(gspca_dev);
708 rc = spca504B_PollingDataReady(gspca_dev);
709 break;
710 default:
711/* case BRIDGE_SPCA504B: */
712/* case BRIDGE_SPCA536: */
713 gspca_dev->usb_buf[0] = Size;
714 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
715 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
716 Type = 6;
717 gspca_dev->usb_buf[0] = Type;
718 reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
719 reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */
720 rc = spca504B_PollingDataReady(gspca_dev);
721 break;
722 case BRIDGE_SPCA504:
723 Size += 3;
724 if (sd->subtype == AiptekMiniPenCam13) {
725 /* spca504a aiptek */
726 spca504A_acknowledged_command(gspca_dev,
727 0x08, Size, 0,
728 0x80 | (Size & 0x0f), 1);
729 spca504A_acknowledged_command(gspca_dev,
730 1, 3, 0, 0x9f, 0);
731 } else {
732 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
733 }
734 break;
735 case BRIDGE_SPCA504C:
736 /* capture mode */
737 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
738 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
739 break;
740 }
741}
742
743static void spca504_wait_status(struct gspca_dev *gspca_dev)
744{
745 int cnt;
746
747 cnt = 256;
748 while (--cnt > 0) {
749 /* With this we get the status, when return 0 it's all ok */
750 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
751 return;
752 msleep(10);
753 }
754}
755
756static void spca504B_setQtable(struct gspca_dev *gspca_dev)
757{
758 struct usb_device *dev = gspca_dev->dev;
759
760 gspca_dev->usb_buf[0] = 3;
761 reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
762 reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
763 spca504B_PollingDataReady(gspca_dev);
764}
765
766static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
767{
768 struct sd *sd = (struct sd *) gspca_dev;
769 struct usb_device *dev = gspca_dev->dev;
770 int pollreg = 1;
771
772 switch (sd->bridge) {
773 case BRIDGE_SPCA504:
774 case BRIDGE_SPCA504C:
775 pollreg = 0;
776 /* fall thru */
777 default:
778/* case BRIDGE_SPCA533: */
779/* case BRIDGE_SPCA504B: */
780 reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
781 reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
782 reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
783 reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
784 reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
785 reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
786 break;
787 case BRIDGE_SPCA536:
788 reg_w(dev, 0, 0, 0x20f0, NULL, 0);
789 reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
790 reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
791 reg_w(dev, 0, 1, 0x20f4, NULL, 0);
792 reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
793 reg_w(dev, 0, 0, 0x2089, NULL, 0);
794 break;
795 }
796 if (pollreg)
797 spca504B_PollingDataReady(gspca_dev);
798}
799
800/* this function is called at probe time */
801static int sd_config(struct gspca_dev *gspca_dev,
802 const struct usb_device_id *id)
803{
804 struct sd *sd = (struct sd *) gspca_dev;
805 struct usb_device *dev = gspca_dev->dev;
806 struct cam *cam;
807 __u16 vendor;
808 __u16 product;
809 __u8 fw;
810
811 vendor = id->idVendor;
812 product = id->idProduct;
813 switch (vendor) {
814 case 0x041e: /* Creative cameras */
815/* switch (product) { */
816/* case 0x400b: */
817/* case 0x4012: */
818/* case 0x4013: */
819/* sd->bridge = BRIDGE_SPCA504C; */
820/* break; */
821/* } */
822 break;
823 case 0x0458: /* Genius KYE cameras */
824/* switch (product) { */
825/* case 0x7006: */
826 sd->bridge = BRIDGE_SPCA504B;
827/* break; */
828/* } */
829 break;
830 case 0x0461: /* MicroInnovation */
831/* switch (product) { */
832/* case 0x0821: */
833 sd->bridge = BRIDGE_SPCA533;
834/* break; */
835/* } */
836 break;
837 case 0x046d: /* Logitech Labtec */
838 switch (product) {
839 case 0x0905:
840 sd->subtype = LogitechClickSmart820;
841 sd->bridge = BRIDGE_SPCA533;
842 break;
843 case 0x0960:
844 sd->subtype = LogitechClickSmart420;
845 sd->bridge = BRIDGE_SPCA504C;
846 break;
847 }
848 break;
849 case 0x0471: /* Philips */
850/* switch (product) { */
851/* case 0x0322: */
852 sd->bridge = BRIDGE_SPCA504B;
853/* break; */
854/* } */
855 break;
856 case 0x04a5: /* Benq */
857 switch (product) {
858 case 0x3003:
859 sd->bridge = BRIDGE_SPCA504B;
860 break;
861 case 0x3008:
862 case 0x300a:
863 sd->bridge = BRIDGE_SPCA533;
864 break;
865 }
866 break;
867 case 0x04f1: /* JVC */
868/* switch (product) { */
869/* case 0x1001: */
870 sd->bridge = BRIDGE_SPCA504B;
871/* break; */
872/* } */
873 break;
874 case 0x04fc: /* SunPlus */
875 switch (product) {
876 case 0x500c:
877 sd->bridge = BRIDGE_SPCA504B;
878 break;
879 case 0x504a:
880/* try to get the firmware as some cam answer 2.0.1.2.2
881 * and should be a spca504b then overwrite that setting */
882 reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
883 fw = gspca_dev->usb_buf[0];
884 if (fw == 1) {
885 sd->subtype = AiptekMiniPenCam13;
886 sd->bridge = BRIDGE_SPCA504;
887 } else if (fw == 2) {
888 sd->bridge = BRIDGE_SPCA504B;
889 } else
890 return -ENODEV;
891 break;
892 case 0x504b:
893 sd->bridge = BRIDGE_SPCA504B;
894 break;
895 case 0x5330:
896 sd->bridge = BRIDGE_SPCA533;
897 break;
898 case 0x5360:
899 sd->bridge = BRIDGE_SPCA536;
900 break;
901 case 0xffff:
902 sd->bridge = BRIDGE_SPCA504B;
903 break;
904 }
905 break;
906 case 0x052b: /* ?? Megapix */
907/* switch (product) { */
908/* case 0x1513: */
909 sd->subtype = MegapixV4;
910 sd->bridge = BRIDGE_SPCA533;
911/* break; */
912/* } */
913 break;
914 case 0x0546: /* Polaroid */
915 switch (product) {
916 case 0x3155:
917 sd->bridge = BRIDGE_SPCA533;
918 break;
919 case 0x3191:
920 case 0x3273:
921 sd->bridge = BRIDGE_SPCA504B;
922 break;
923 }
924 break;
925 case 0x055f: /* Mustek cameras */
926 switch (product) {
927 case 0xc211:
928 sd->bridge = BRIDGE_SPCA536;
929 break;
930 case 0xc230:
931 case 0xc232:
932 sd->bridge = BRIDGE_SPCA533;
933 break;
934 case 0xc360:
935 sd->bridge = BRIDGE_SPCA536;
936 break;
937 case 0xc420:
938 sd->bridge = BRIDGE_SPCA504;
939 break;
940 case 0xc430:
941 case 0xc440:
942 sd->bridge = BRIDGE_SPCA533;
943 break;
944 case 0xc520:
945 sd->bridge = BRIDGE_SPCA504;
946 break;
947 case 0xc530:
948 case 0xc540:
949 case 0xc630:
950 case 0xc650:
951 sd->bridge = BRIDGE_SPCA533;
952 break;
953 }
954 break;
955 case 0x05da: /* Digital Dream cameras */
956/* switch (product) { */
957/* case 0x1018: */
958 sd->bridge = BRIDGE_SPCA504B;
959/* break; */
960/* } */
961 break;
962 case 0x06d6: /* Trust */
963/* switch (product) { */
964/* case 0x0031: */
965 sd->bridge = BRIDGE_SPCA533; /* SPCA533A */
966/* break; */
967/* } */
968 break;
969 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
970 switch (product) {
971 case 0x1311:
972 case 0x1314:
973 case 0x2211:
974 case 0x2221:
975 sd->bridge = BRIDGE_SPCA533;
976 break;
977 case 0x3261:
978 case 0x3281:
979 sd->bridge = BRIDGE_SPCA536;
980 break;
981 }
982 break;
983 case 0x08ca: /* Aiptek */
984 switch (product) {
985 case 0x0104:
986 case 0x0106:
987 sd->bridge = BRIDGE_SPCA533;
988 break;
989 case 0x2008:
990 sd->bridge = BRIDGE_SPCA504B;
991 break;
992 case 0x2010:
993 sd->bridge = BRIDGE_SPCA533;
994 break;
995 case 0x2016:
996 case 0x2018:
997 sd->bridge = BRIDGE_SPCA504B;
998 break;
999 case 0x2020:
1000 case 0x2022:
1001 sd->bridge = BRIDGE_SPCA533;
1002 break;
1003 case 0x2024:
1004 sd->bridge = BRIDGE_SPCA536;
1005 break;
1006 case 0x2028:
1007 sd->bridge = BRIDGE_SPCA533;
1008 break;
1009 case 0x2040:
1010 case 0x2042:
1011 case 0x2050:
1012 case 0x2060:
1013 sd->bridge = BRIDGE_SPCA536;
1014 break;
1015 }
1016 break;
1017 case 0x0d64: /* SunPlus */
1018/* switch (product) { */
1019/* case 0x0303: */
1020 sd->bridge = BRIDGE_SPCA536;
1021/* break; */
1022/* } */
1023 break;
1024 }
1025
1026 cam = &gspca_dev->cam;
1027 cam->dev_name = (char *) id->driver_info;
1028 cam->epaddr = 0x01;
1029
1030 switch (sd->bridge) {
1031 default:
1032/* case BRIDGE_SPCA504B: */
1033/* case BRIDGE_SPCA504: */
1034/* case BRIDGE_SPCA536: */
1035 cam->cam_mode = vga_mode;
1036 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1037 break;
1038 case BRIDGE_SPCA533:
1039 cam->cam_mode = custom_mode;
1040 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
1041 break;
1042 case BRIDGE_SPCA504C:
1043 cam->cam_mode = vga_mode2;
1044 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
1045 break;
1046 }
1047 sd->qindex = 5; /* set the quantization table */
1048 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1049 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1050 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1051 return 0;
1052}
1053
1054/* this function is called at open time */
1055static int sd_open(struct gspca_dev *gspca_dev)
1056{
1057 struct sd *sd = (struct sd *) gspca_dev;
1058 struct usb_device *dev = gspca_dev->dev;
1059 int rc;
1060 __u8 i;
1061 __u8 info[6];
1062 int err_code;
1063
1064 switch (sd->bridge) {
1065 case BRIDGE_SPCA504B:
1066 reg_w(dev, 0x1d, 0, 0, NULL, 0);
1067 reg_w(dev, 0, 1, 0x2306, NULL, 0);
1068 reg_w(dev, 0, 0, 0x0d04, NULL, 0);
1069 reg_w(dev, 0, 0, 0x2000, NULL, 0);
1070 reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
1071 reg_w(dev, 0, 0, 0x2306, NULL, 0);
1072 /* fall thru */
1073 case BRIDGE_SPCA533:
1074 rc = spca504B_PollingDataReady(gspca_dev);
1075 spca50x_GetFirmware(gspca_dev);
1076 break;
1077 case BRIDGE_SPCA536:
1078 spca50x_GetFirmware(gspca_dev);
1079 reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
1080 gspca_dev->usb_buf[0] = 0;
1081 reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
1082 reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
1083 rc = spca504B_PollingDataReady(gspca_dev);
1084 reg_w(dev, 0x34, 0, 0, NULL, 0);
1085 spca504B_WaitCmdStatus(gspca_dev);
1086 break;
1087 case BRIDGE_SPCA504C: /* pccam600 */
1088 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
1089 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
1090 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
1091 spca504_wait_status(gspca_dev);
1092 if (sd->subtype == LogitechClickSmart420)
1093 write_vector(gspca_dev,
1094 spca504A_clicksmart420_open_data);
1095 else
1096 write_vector(gspca_dev, spca504_pccam600_open_data);
1097 err_code = spca50x_setup_qtable(gspca_dev,
1098 0x00, 0x2800,
1099 0x2840, qtable_creative_pccam);
1100 if (err_code < 0) {
1101 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
1102 return err_code;
1103 }
1104 break;
1105 default:
1106/* case BRIDGE_SPCA504: */
1107 PDEBUG(D_STREAM, "Opening SPCA504");
1108 if (sd->subtype == AiptekMiniPenCam13) {
1109 /*****************************/
1110 for (i = 0; i < 6; i++)
1111 info[i] = reg_r_1(gspca_dev, i);
1112 PDEBUG(D_STREAM,
1113 "Read info: %d %d %d %d %d %d."
1114 " Should be 1,0,2,2,0,0",
1115 info[0], info[1], info[2],
1116 info[3], info[4], info[5]);
1117 /* spca504a aiptek */
1118 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1119 spca504A_acknowledged_command(gspca_dev, 0x24,
1120 8, 3, 0x9e, 1);
1121 /* Twice sequencial need status 0xff->0x9e->0x9d */
1122 spca504A_acknowledged_command(gspca_dev, 0x24,
1123 8, 3, 0x9e, 0);
1124
1125 spca504A_acknowledged_command(gspca_dev, 0x24,
1126 0, 0, 0x9d, 1);
1127 /******************************/
1128 /* spca504a aiptek */
1129 spca504A_acknowledged_command(gspca_dev, 0x08,
1130 6, 0, 0x86, 1);
1131/* reg_write (dev, 0, 0x2000, 0); */
1132/* reg_write (dev, 0, 0x2883, 1); */
1133/* spca504A_acknowledged_command (gspca_dev, 0x08,
1134 6, 0, 0x86, 1); */
1135/* spca504A_acknowledged_command (gspca_dev, 0x24,
1136 0, 0, 0x9D, 1); */
1137 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1138 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1139 spca504A_acknowledged_command(gspca_dev, 0x01,
1140 0x0f, 0, 0xff, 0);
1141 }
1142 /* setup qtable */
1143 reg_w_riv(dev, 0, 0x2000, 0);
1144 reg_w_riv(dev, 0, 0x2883, 1);
1145 err_code = spca50x_setup_qtable(gspca_dev,
1146 0x00, 0x2800,
1147 0x2840,
1148 qtable_spca504_default);
1149 if (err_code < 0) {
1150 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
1151 return err_code;
1152 }
1153 break;
1154 }
1155 return 0;
1156}
1157
1158static void sd_start(struct gspca_dev *gspca_dev)
1159{
1160 struct sd *sd = (struct sd *) gspca_dev;
1161 struct usb_device *dev = gspca_dev->dev;
1162 int rc;
1163 int enable;
1164 __u8 i;
1165 __u8 info[6];
1166
1167 if (sd->bridge == BRIDGE_SPCA504B)
1168 spca504B_setQtable(gspca_dev);
1169 spca504B_SetSizeType(gspca_dev);
1170 switch (sd->bridge) {
1171 default:
1172/* case BRIDGE_SPCA504B: */
1173/* case BRIDGE_SPCA533: */
1174/* case BRIDGE_SPCA536: */
1175 if (sd->subtype == MegapixV4 ||
1176 sd->subtype == LogitechClickSmart820) {
1177 reg_w(dev, 0xf0, 0, 0, NULL, 0);
1178 spca504B_WaitCmdStatus(gspca_dev);
1179 reg_r(dev, 0xf0, 4, NULL, 0);
1180 spca504B_WaitCmdStatus(gspca_dev);
1181 } else {
1182 reg_w(dev, 0x31, 0, 4, NULL, 0);
1183 spca504B_WaitCmdStatus(gspca_dev);
1184 rc = spca504B_PollingDataReady(gspca_dev);
1185 }
1186 break;
1187 case BRIDGE_SPCA504:
1188 if (sd->subtype == AiptekMiniPenCam13) {
1189 for (i = 0; i < 6; i++)
1190 info[i] = reg_r_1(gspca_dev, i);
1191 PDEBUG(D_STREAM,
1192 "Read info: %d %d %d %d %d %d."
1193 " Should be 1,0,2,2,0,0",
1194 info[0], info[1], info[2],
1195 info[3], info[4], info[5]);
1196 /* spca504a aiptek */
1197 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1198 spca504A_acknowledged_command(gspca_dev, 0x24,
1199 8, 3, 0x9e, 1);
1200 /* Twice sequencial need status 0xff->0x9e->0x9d */
1201 spca504A_acknowledged_command(gspca_dev, 0x24,
1202 8, 3, 0x9e, 0);
1203 spca504A_acknowledged_command(gspca_dev, 0x24,
1204 0, 0, 0x9d, 1);
1205 } else {
1206 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1207 for (i = 0; i < 6; i++)
1208 info[i] = reg_r_1(gspca_dev, i);
1209 PDEBUG(D_STREAM,
1210 "Read info: %d %d %d %d %d %d."
1211 " Should be 1,0,2,2,0,0",
1212 info[0], info[1], info[2],
1213 info[3], info[4], info[5]);
1214 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1215 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1216 }
1217 spca504B_SetSizeType(gspca_dev);
1218 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1219 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1220 break;
1221 case BRIDGE_SPCA504C:
1222 if (sd->subtype == LogitechClickSmart420) {
1223 write_vector(gspca_dev,
1224 spca504A_clicksmart420_init_data);
1225 } else {
1226 write_vector(gspca_dev, spca504_pccam600_init_data);
1227 }
1228 enable = (sd->autogain ? 0x04 : 0x01);
1229 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1230 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
1231
1232 /* set default exposure compensation and whiteness balance */
1233 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1234 reg_w_riv(dev, 0x30, 0x0002, 1600);
1235 spca504B_SetSizeType(gspca_dev);
1236 break;
1237 }
1238 sp5xx_initContBrigHueRegisters(gspca_dev);
1239}
1240
1241static void sd_stopN(struct gspca_dev *gspca_dev)
1242{
1243 struct sd *sd = (struct sd *) gspca_dev;
1244 struct usb_device *dev = gspca_dev->dev;
1245
1246 switch (sd->bridge) {
1247 default:
1248/* case BRIDGE_SPCA533: */
1249/* case BRIDGE_SPCA536: */
1250/* case BRIDGE_SPCA504B: */
1251 reg_w(dev, 0x31, 0, 0, NULL, 0);
1252 spca504B_WaitCmdStatus(gspca_dev);
1253 spca504B_PollingDataReady(gspca_dev);
1254 break;
1255 case BRIDGE_SPCA504:
1256 case BRIDGE_SPCA504C:
1257 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1258
1259 if (sd->subtype == AiptekMiniPenCam13) {
1260 /* spca504a aiptek */
1261/* spca504A_acknowledged_command(gspca_dev, 0x08,
1262 6, 0, 0x86, 1); */
1263 spca504A_acknowledged_command(gspca_dev, 0x24,
1264 0x00, 0x00, 0x9d, 1);
1265 spca504A_acknowledged_command(gspca_dev, 0x01,
1266 0x0f, 0x00, 0xff, 1);
1267 } else {
1268 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1269 reg_w_riv(dev, 0x01, 0x000f, 0x00);
1270 }
1271 break;
1272 }
1273}
1274
1275static void sd_stop0(struct gspca_dev *gspca_dev)
1276{
1277}
1278
1279static void sd_close(struct gspca_dev *gspca_dev)
1280{
1281}
1282
1283static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1284 struct gspca_frame *frame, /* target */
1285 __u8 *data, /* isoc packet */
1286 int len) /* iso packet length */
1287{
1288 struct sd *sd = (struct sd *) gspca_dev;
1289 int i, sof = 0;
1290 unsigned char *s, *d;
1291 static unsigned char ffd9[] = {0xff, 0xd9};
1292
1293/* frames are jpeg 4.1.1 without 0xff escape */
1294 switch (sd->bridge) {
1295 case BRIDGE_SPCA533:
1296 if (data[0] == 0xff) {
1297 if (data[1] != 0x01) { /* drop packet */
1298/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1299 return;
1300 }
1301 sof = 1;
1302 data += SPCA533_OFFSET_DATA;
1303 len -= SPCA533_OFFSET_DATA;
1304 } else {
1305 data += 1;
1306 len -= 1;
1307 }
1308 break;
1309 case BRIDGE_SPCA536:
1310 if (data[0] == 0xff) {
1311 sof = 1;
1312 data += SPCA536_OFFSET_DATA;
1313 len -= SPCA536_OFFSET_DATA;
1314 } else {
1315 data += 2;
1316 len -= 2;
1317 }
1318 break;
1319 default:
1320/* case BRIDGE_SPCA504: */
1321/* case BRIDGE_SPCA504B: */
1322 switch (data[0]) {
1323 case 0xfe: /* start of frame */
1324 sof = 1;
1325 data += SPCA50X_OFFSET_DATA;
1326 len -= SPCA50X_OFFSET_DATA;
1327 break;
1328 case 0xff: /* drop packet */
1329/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1330 return;
1331 default:
1332 data += 1;
1333 len -= 1;
1334 break;
1335 }
1336 break;
1337 case BRIDGE_SPCA504C:
1338 switch (data[0]) {
1339 case 0xfe: /* start of frame */
1340 sof = 1;
1341 data += SPCA504_PCCAM600_OFFSET_DATA;
1342 len -= SPCA504_PCCAM600_OFFSET_DATA;
1343 break;
1344 case 0xff: /* drop packet */
1345/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1346 return;
1347 default:
1348 data += 1;
1349 len -= 1;
1350 break;
1351 }
1352 break;
1353 }
1354 if (sof) { /* start of frame */
1355 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1356 ffd9, 2);
1357
1358 /* put the JPEG header in the new frame */
1359 jpeg_put_header(gspca_dev, frame,
1360 ((struct sd *) gspca_dev)->qindex,
1361 0x22);
1362 }
1363
1364 /* add 0x00 after 0xff */
1365 for (i = len; --i >= 0; )
1366 if (data[i] == 0xff)
1367 break;
1368 if (i < 0) { /* no 0xff */
1369 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1370 return;
1371 }
1372 s = data;
1373 d = sd->packet;
1374 for (i = 0; i < len; i++) {
1375 *d++ = *s++;
1376 if (s[-1] == 0xff)
1377 *d++ = 0x00;
1378 }
1379 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1380 sd->packet, d - sd->packet);
1381}
1382
1383static void setbrightness(struct gspca_dev *gspca_dev)
1384{
1385 struct sd *sd = (struct sd *) gspca_dev;
1386 struct usb_device *dev = gspca_dev->dev;
1387
1388 switch (sd->bridge) {
1389 default:
1390/* case BRIDGE_SPCA533: */
1391/* case BRIDGE_SPCA504B: */
1392/* case BRIDGE_SPCA504: */
1393/* case BRIDGE_SPCA504C: */
1394 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
1395 break;
1396 case BRIDGE_SPCA536:
1397 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
1398 break;
1399 }
1400}
1401
1402static void getbrightness(struct gspca_dev *gspca_dev)
1403{
1404 struct sd *sd = (struct sd *) gspca_dev;
1405 __u16 brightness = 0;
1406
1407 switch (sd->bridge) {
1408 default:
1409/* case BRIDGE_SPCA533: */
1410/* case BRIDGE_SPCA504B: */
1411/* case BRIDGE_SPCA504: */
1412/* case BRIDGE_SPCA504C: */
1413 brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
1414 break;
1415 case BRIDGE_SPCA536:
1416 brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
1417 break;
1418 }
1419 sd->brightness = ((brightness & 0xff) - 128) % 255;
1420}
1421
1422static void setcontrast(struct gspca_dev *gspca_dev)
1423{
1424 struct sd *sd = (struct sd *) gspca_dev;
1425 struct usb_device *dev = gspca_dev->dev;
1426
1427 switch (sd->bridge) {
1428 default:
1429/* case BRIDGE_SPCA533: */
1430/* case BRIDGE_SPCA504B: */
1431/* case BRIDGE_SPCA504: */
1432/* case BRIDGE_SPCA504C: */
1433 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
1434 break;
1435 case BRIDGE_SPCA536:
1436 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
1437 break;
1438 }
1439}
1440
1441static void getcontrast(struct gspca_dev *gspca_dev)
1442{
1443 struct sd *sd = (struct sd *) gspca_dev;
1444
1445 switch (sd->bridge) {
1446 default:
1447/* case BRIDGE_SPCA533: */
1448/* case BRIDGE_SPCA504B: */
1449/* case BRIDGE_SPCA504: */
1450/* case BRIDGE_SPCA504C: */
1451 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
1452 break;
1453 case BRIDGE_SPCA536:
1454 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
1455 break;
1456 }
1457}
1458
1459static void setcolors(struct gspca_dev *gspca_dev)
1460{
1461 struct sd *sd = (struct sd *) gspca_dev;
1462 struct usb_device *dev = gspca_dev->dev;
1463
1464 switch (sd->bridge) {
1465 default:
1466/* case BRIDGE_SPCA533: */
1467/* case BRIDGE_SPCA504B: */
1468/* case BRIDGE_SPCA504: */
1469/* case BRIDGE_SPCA504C: */
1470 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
1471 break;
1472 case BRIDGE_SPCA536:
1473 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
1474 break;
1475 }
1476}
1477
1478static void getcolors(struct gspca_dev *gspca_dev)
1479{
1480 struct sd *sd = (struct sd *) gspca_dev;
1481
1482 switch (sd->bridge) {
1483 default:
1484/* case BRIDGE_SPCA533: */
1485/* case BRIDGE_SPCA504B: */
1486/* case BRIDGE_SPCA504: */
1487/* case BRIDGE_SPCA504C: */
1488 sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
1489 break;
1490 case BRIDGE_SPCA536:
1491 sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
1492 break;
1493 }
1494}
1495
1496static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1497{
1498 struct sd *sd = (struct sd *) gspca_dev;
1499
1500 sd->brightness = val;
1501 if (gspca_dev->streaming)
1502 setbrightness(gspca_dev);
1503 return 0;
1504}
1505
1506static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1507{
1508 struct sd *sd = (struct sd *) gspca_dev;
1509
1510 getbrightness(gspca_dev);
1511 *val = sd->brightness;
1512 return 0;
1513}
1514
1515static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1516{
1517 struct sd *sd = (struct sd *) gspca_dev;
1518
1519 sd->contrast = val;
1520 if (gspca_dev->streaming)
1521 setcontrast(gspca_dev);
1522 return 0;
1523}
1524
1525static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1526{
1527 struct sd *sd = (struct sd *) gspca_dev;
1528
1529 getcontrast(gspca_dev);
1530 *val = sd->contrast;
1531 return 0;
1532}
1533
1534static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1535{
1536 struct sd *sd = (struct sd *) gspca_dev;
1537
1538 sd->colors = val;
1539 if (gspca_dev->streaming)
1540 setcolors(gspca_dev);
1541 return 0;
1542}
1543
1544static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1545{
1546 struct sd *sd = (struct sd *) gspca_dev;
1547
1548 getcolors(gspca_dev);
1549 *val = sd->colors;
1550 return 0;
1551}
1552
1553static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1554{
1555 struct sd *sd = (struct sd *) gspca_dev;
1556
1557 sd->autogain = val;
1558 return 0;
1559}
1560
1561static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1562{
1563 struct sd *sd = (struct sd *) gspca_dev;
1564
1565 *val = sd->autogain;
1566 return 0;
1567}
1568
1569/* sub-driver description */
1570static const struct sd_desc sd_desc = {
1571 .name = MODULE_NAME,
1572 .ctrls = sd_ctrls,
1573 .nctrls = ARRAY_SIZE(sd_ctrls),
1574 .config = sd_config,
1575 .open = sd_open,
1576 .start = sd_start,
1577 .stopN = sd_stopN,
1578 .stop0 = sd_stop0,
1579 .close = sd_close,
1580 .pkt_scan = sd_pkt_scan,
1581};
1582
1583/* -- module initialisation -- */
1584#define DVNM(name) .driver_info = (kernel_ulong_t) name
1585static const __devinitdata struct usb_device_id device_table[] = {
1586 {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
1587 {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
1588 {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
1589 {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
1590 {USB_DEVICE(0x0461, 0x0821), DVNM("Fujifilm MV-1")},
1591 {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
1592 {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
1593 {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
1594 {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
1595 {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
1596 {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
1597 {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
1598 {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
1599 {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
1600 {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
1601 {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
1602 {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
1603 {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
1604 {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
1605 {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
1606 {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
1607 {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
1608 {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
1609 {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
1610 {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
1611 {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
1612 {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
1613 {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
1614 {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
1615 {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
1616 {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
1617 {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
1618 {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
1619 {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
1620 {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
1621 {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
1622 {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
1623 {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
1624 {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
1625 {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
1626 {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
1627 {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
1628 {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
1629 {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
1630 {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
1631 {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
1632 {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
1633 {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
1634 {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
1635 {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
1636 {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
1637 {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
1638 {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
1639 {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
1640 {USB_DEVICE(0x08ca, 0x2050), DVNM("Medion MD 41437")},
1641 {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
1642 {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
1643 {}
1644};
1645MODULE_DEVICE_TABLE(usb, device_table);
1646
1647/* -- device connect -- */
1648static int sd_probe(struct usb_interface *intf,
1649 const struct usb_device_id *id)
1650{
1651 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1652 THIS_MODULE);
1653}
1654
1655static struct usb_driver sd_driver = {
1656 .name = MODULE_NAME,
1657 .id_table = device_table,
1658 .probe = sd_probe,
1659 .disconnect = gspca_disconnect,
1660};
1661
1662/* -- module insert / remove -- */
1663static int __init sd_mod_init(void)
1664{
1665 if (usb_register(&sd_driver) < 0)
1666 return -1;
1667 PDEBUG(D_PROBE, "v%s registered", version);
1668 return 0;
1669}
1670static void __exit sd_mod_exit(void)
1671{
1672 usb_deregister(&sd_driver);
1673 PDEBUG(D_PROBE, "deregistered");
1674}
1675
1676module_init(sd_mod_init);
1677module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
new file mode 100644
index 000000000000..00f47e463a05
--- /dev/null
+++ b/drivers/media/video/gspca/t613.c
@@ -0,0 +1,1038 @@
1/*
2 *Notes: * t613 + tas5130A
3 * * Focus to light do not balance well as in win.
4 * Quality in win is not good, but its kinda better.
5 * * Fix some "extraneous bytes", most of apps will show the image anyway
6 * * Gamma table, is there, but its really doing something?
7 * * 7~8 Fps, its ok, max on win its 10.
8 * Costantino Leandro
9 *
10 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#define MODULE_NAME "t613"
28#include "gspca.h"
29#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
30static const char version[] = "2.1.7";
31
32#define MAX_GAMMA 0x10 /* 0 to 15 */
33
34/* From LUVCVIEW */
35#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
36
37MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
38MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
39MODULE_LICENSE("GPL");
40
41struct sd {
42 struct gspca_dev gspca_dev; /* !! must be the first item */
43
44 unsigned char brightness;
45 unsigned char contrast;
46 unsigned char colors;
47 unsigned char autogain;
48 unsigned char gamma;
49 unsigned char sharpness;
50 unsigned char freq;
51 unsigned char whitebalance;
52 unsigned char mirror;
53 unsigned char effect;
54};
55
56/* V4L2 controls supported by the driver */
57static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
58static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
59static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
60static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
61static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_querymenu(struct gspca_dev *gspca_dev,
78 struct v4l2_querymenu *menu);
79
80static struct ctrl sd_ctrls[] = {
81#define SD_BRIGHTNESS 0
82 {
83 {
84 .id = V4L2_CID_BRIGHTNESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "Brightness",
87 .minimum = 0,
88 .maximum = 0x0f,
89 .step = 1,
90 .default_value = 0x09,
91 },
92 .set = sd_setbrightness,
93 .get = sd_getbrightness,
94 },
95#define SD_CONTRAST 1
96 {
97 {
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Contrast",
101 .minimum = 0,
102 .maximum = 0x0d,
103 .step = 1,
104 .default_value = 0x07,
105 },
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
108 },
109#define SD_COLOR 2
110 {
111 {
112 .id = V4L2_CID_SATURATION,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Color",
115 .minimum = 0,
116 .maximum = 0x0f,
117 .step = 1,
118 .default_value = 0x05,
119 },
120 .set = sd_setcolors,
121 .get = sd_getcolors,
122 },
123#define SD_GAMMA 3
124 {
125 {
126 .id = V4L2_CID_GAMMA, /* (gamma on win) */
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Gamma (Untested)",
129 .minimum = 0,
130 .maximum = MAX_GAMMA,
131 .step = 1,
132 .default_value = 0x09,
133 },
134 .set = sd_setgamma,
135 .get = sd_getgamma,
136 },
137#define SD_AUTOGAIN 4
138 {
139 {
140 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
141 * some apps dont bring up the
142 * backligth_compensation control) */
143 .type = V4L2_CTRL_TYPE_INTEGER,
144 .name = "Low Light",
145 .minimum = 0,
146 .maximum = 1,
147 .step = 1,
148 .default_value = 0x01,
149 },
150 .set = sd_setlowlight,
151 .get = sd_getlowlight,
152 },
153#define SD_MIRROR 5
154 {
155 {
156 .id = V4L2_CID_HFLIP,
157 .type = V4L2_CTRL_TYPE_BOOLEAN,
158 .name = "Mirror Image",
159 .minimum = 0,
160 .maximum = 1,
161 .step = 1,
162 .default_value = 0,
163 },
164 .set = sd_setflip,
165 .get = sd_getflip
166 },
167#define SD_LIGHTFREQ 6
168 {
169 {
170 .id = V4L2_CID_POWER_LINE_FREQUENCY,
171 .type = V4L2_CTRL_TYPE_MENU,
172 .name = "Light Frequency Filter",
173 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
174 .maximum = 2,
175 .step = 1,
176 .default_value = 1,
177 },
178 .set = sd_setfreq,
179 .get = sd_getfreq},
180
181#define SD_WHITE_BALANCE 7
182 {
183 {
184 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "White Balance",
187 .minimum = 0,
188 .maximum = 1,
189 .step = 1,
190 .default_value = 1,
191 },
192 .set = sd_setwhitebalance,
193 .get = sd_getwhitebalance
194 },
195#define SD_SHARPNESS 8 /* (aka definition on win) */
196 {
197 {
198 .id = V4L2_CID_SHARPNESS,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "Sharpness",
201 .minimum = 0,
202 .maximum = MAX_GAMMA, /* 0 to 16 */
203 .step = 1,
204 .default_value = 0x06,
205 },
206 .set = sd_setsharpness,
207 .get = sd_getsharpness,
208 },
209#define SD_EFFECTS 9
210 {
211 {
212 .id = V4L2_CID_EFFECTS,
213 .type = V4L2_CTRL_TYPE_MENU,
214 .name = "Webcam Effects",
215 .minimum = 0,
216 .maximum = 4,
217 .step = 1,
218 .default_value = 0,
219 },
220 .set = sd_seteffect,
221 .get = sd_geteffect
222 },
223};
224
225static char *effects_control[] = {
226 "Normal",
227 "Emboss", /* disabled */
228 "Monochrome",
229 "Sepia",
230 "Sketch",
231 "Sun Effect", /* disabled */
232 "Negative",
233};
234
235static struct v4l2_pix_format vga_mode_t16[] = {
236 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
237 .bytesperline = 160,
238 .sizeimage = 160 * 120 * 3 / 8 + 590,
239 .colorspace = V4L2_COLORSPACE_JPEG,
240 .priv = 4},
241 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
242 .bytesperline = 176,
243 .sizeimage = 176 * 144 * 3 / 8 + 590,
244 .colorspace = V4L2_COLORSPACE_JPEG,
245 .priv = 3},
246 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
247 .bytesperline = 320,
248 .sizeimage = 320 * 240 * 3 / 8 + 590,
249 .colorspace = V4L2_COLORSPACE_JPEG,
250 .priv = 2},
251 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
252 .bytesperline = 352,
253 .sizeimage = 352 * 288 * 3 / 8 + 590,
254 .colorspace = V4L2_COLORSPACE_JPEG,
255 .priv = 1},
256 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
257 .bytesperline = 640,
258 .sizeimage = 640 * 480 * 3 / 8 + 590,
259 .colorspace = V4L2_COLORSPACE_JPEG,
260 .priv = 0},
261};
262
263#define T16_OFFSET_DATA 631
264#define MAX_EFFECTS 7
265/* easily done by soft, this table could be removed,
266 * i keep it here just in case */
267static const __u8 effects_table[MAX_EFFECTS][6] = {
268 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
269 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
270 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
271 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
272 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
273 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
274 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
275};
276
277static const __u8 gamma_table[MAX_GAMMA][34] = {
278 {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,
279 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
280 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
281 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
282 0xa0, 0xff},
283 {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75,
284 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD,
285 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4,
286 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7,
287 0xa0, 0xff},
288 {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B,
289 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6,
290 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0,
291 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6,
292 0xa0, 0xff},
293 {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,
294 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E,
295 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB,
296 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
297 0xa0, 0xff},
298 {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55,
299 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
300 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6,
301 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4,
302 0xa0, 0xff},
303 {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48,
304 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
305 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE,
306 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3,
307 0xa0, 0xff},
308 {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,
309 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
310 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
311 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
312 0xa0, 0xff},
313 {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,
314 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70,
315 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0,
316 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0,
317 0xa0, 0xff},
318 {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,
319 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79,
320 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6,
321 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0,
322 0xa0, 0xff},
323 {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,
324 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
325 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
326 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
327 0xa0, 0xff},
328 {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44,
329 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E,
330 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4,
331 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0,
332 0xa0, 0xff},
333 {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52,
334 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B,
335 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB,
336 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
337 0xa0, 0xff},
338 {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E,
339 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8,
340 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3,
341 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6,
342 0xA0, 0xFF},
343 {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83,
344 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7,
345 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC,
346 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9,
347 0xa0, 0xff},
348 {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A,
349 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6,
350 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3,
351 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA,
352 0xa0, 0xff},
353 {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7,
354 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8,
355 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED,
356 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC,
357 0xA0, 0xFF}
358};
359
360static const __u8 tas5130a_sensor_init[][8] = {
361 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
362 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
363 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
364 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
365 {},
366};
367
368/* read 1 byte */
369static int reg_r_1(struct gspca_dev *gspca_dev,
370 __u16 index)
371{
372 usb_control_msg(gspca_dev->dev,
373 usb_rcvctrlpipe(gspca_dev->dev, 0),
374 0, /* request */
375 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
376 0, /* value */
377 index,
378 gspca_dev->usb_buf, 1, 500);
379 return gspca_dev->usb_buf[0];
380}
381
382static void reg_w(struct gspca_dev *gspca_dev,
383 __u16 value,
384 __u16 index,
385 const __u8 *buffer, __u16 len)
386{
387 if (buffer == NULL) {
388 usb_control_msg(gspca_dev->dev,
389 usb_sndctrlpipe(gspca_dev->dev, 0),
390 0,
391 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
392 value, index,
393 NULL, 0, 500);
394 return;
395 }
396 if (len <= sizeof gspca_dev->usb_buf) {
397 memcpy(gspca_dev->usb_buf, buffer, len);
398 usb_control_msg(gspca_dev->dev,
399 usb_sndctrlpipe(gspca_dev->dev, 0),
400 0,
401 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
402 value, index,
403 gspca_dev->usb_buf, len, 500);
404 } else {
405 __u8 *tmpbuf;
406
407 tmpbuf = kmalloc(len, GFP_KERNEL);
408 memcpy(tmpbuf, buffer, len);
409 usb_control_msg(gspca_dev->dev,
410 usb_sndctrlpipe(gspca_dev->dev, 0),
411 0,
412 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
413 value, index,
414 tmpbuf, len, 500);
415 kfree(tmpbuf);
416 }
417}
418
419/* this function is called at probe time */
420static int sd_config(struct gspca_dev *gspca_dev,
421 const struct usb_device_id *id)
422{
423 struct sd *sd = (struct sd *) gspca_dev;
424 struct cam *cam;
425
426 cam = &gspca_dev->cam;
427 cam->dev_name = (char *) id->driver_info;
428 cam->epaddr = 0x01;
429
430 cam->cam_mode = vga_mode_t16;
431 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
432
433 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
434 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
435 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
436 sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
437 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
438 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
439 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
440 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
441 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
442 return 0;
443}
444
445static int init_default_parameters(struct gspca_dev *gspca_dev)
446{
447 /* some of this registers are not really neded, because
448 * they are overriden by setbrigthness, setcontrast, etc,
449 * but wont hurt anyway, and can help someone with similar webcam
450 * to see the initial parameters.*/
451 int i = 0;
452 __u8 test_byte;
453
454 static const __u8 read_indexs[] =
455 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
456 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
457 static const __u8 n1[6] =
458 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
459 static const __u8 n2[2] =
460 {0x08, 0x00};
461 static const __u8 nset[6] =
462 { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
463 static const __u8 n3[6] =
464 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
465 static const __u8 n4[0x46] =
466 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
467 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
468 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
469 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
470 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
471 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
472 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
473 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
474 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
475 static const __u8 nset4[18] = {
476 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
477 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
478 0xe8, 0xe0
479 };
480 /* ojo puede ser 0xe6 en vez de 0xe9 */
481 static const __u8 nset2[20] = {
482 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
483 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
484 0xd8, 0xc8, 0xd9, 0xfc
485 };
486 static const __u8 missing[8] =
487 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
488 static const __u8 nset3[18] = {
489 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
490 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
491 0xcf, 0xe0
492 };
493 static const __u8 nset5[4] =
494 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
495 static const __u8 nset6[34] = {
496 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
497 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
498 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
499 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
500 0xa0, 0xff
501 }; /* Gamma */
502 static const __u8 nset7[4] =
503 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
504 static const __u8 nset9[4] =
505 { 0x0b, 0x04, 0x0a, 0x78 };
506 static const __u8 nset8[6] =
507 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
508 static const __u8 nset10[6] =
509 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
510
511 reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06);
512 reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06);
513 reg_r_1(gspca_dev, 0x0063);
514 reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02);
515
516 while (read_indexs[i] != 0x00) {
517 test_byte = reg_r_1(gspca_dev, read_indexs[i]);
518 PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i],
519 test_byte);
520 i++;
521 }
522
523 reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06);
524 reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46);
525 reg_r_1(gspca_dev, 0x0080);
526 reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0);
527 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
528 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
529 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
530 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
531 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
532 reg_w(gspca_dev, 0x00, 0x338e, NULL, 0);
533 reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04);
534 reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0);
535 reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22);
536 reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0);
537 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
538
539 reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08);
540
541 reg_w(gspca_dev, 0x00, 0x2087, NULL, 0);
542 reg_w(gspca_dev, 0x00, 0x2088, NULL, 0);
543 reg_w(gspca_dev, 0x00, 0x2089, NULL, 0);
544
545 reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04);
546 reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06);
547 reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06);
548 reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04);
549
550 reg_w(gspca_dev, 0x00, 0x2880, NULL, 0);
551 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
552 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
553 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
554
555 return 0;
556}
557
558static void setbrightness(struct gspca_dev *gspca_dev)
559{
560 struct sd *sd = (struct sd *) gspca_dev;
561 unsigned int brightness;
562 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
563 brightness = sd->brightness;
564
565 if (brightness < 7) {
566 set6[3] = 0x70 - (brightness * 0xa);
567 } else {
568 set6[1] = 0x24;
569 set6[3] = 0x00 + ((brightness - 7) * 0xa);
570 }
571
572 reg_w(gspca_dev, 0x01, 0x0000, set6, 4);
573}
574
575static void setflip(struct gspca_dev *gspca_dev)
576{
577 struct sd *sd = (struct sd *) gspca_dev;
578
579 __u8 flipcmd[8] =
580 { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
581
582 if (sd->mirror == 1)
583 flipcmd[3] = 0x01;
584
585 reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8);
586}
587
588static void seteffect(struct gspca_dev *gspca_dev)
589{
590 struct sd *sd = (struct sd *) gspca_dev;
591
592 reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
593 if (sd->effect == 1 || sd->effect == 5) {
594 PDEBUG(D_CONF,
595 "This effect have been disabled for webcam \"safety\"");
596 return;
597 }
598
599 if (sd->effect == 1 || sd->effect == 4)
600 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
601 else
602 reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0);
603}
604
605static void setwhitebalance(struct gspca_dev *gspca_dev)
606{
607 struct sd *sd = (struct sd *) gspca_dev;
608
609 __u8 white_balance[8] =
610 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
611
612 if (sd->whitebalance == 1)
613 white_balance[7] = 0x3c;
614
615 reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8);
616}
617
618static void setlightfreq(struct gspca_dev *gspca_dev)
619{
620 struct sd *sd = (struct sd *) gspca_dev;
621 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
622
623 if (sd->freq == 2) /* 60hz */
624 freq[1] = 0x00;
625
626 reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4);
627}
628
629static void setcontrast(struct gspca_dev *gspca_dev)
630{
631 struct sd *sd = (struct sd *) gspca_dev;
632 unsigned int contrast = sd->contrast;
633 __u16 reg_to_write = 0x00;
634
635 if (contrast < 7)
636 reg_to_write = 0x8ea9 - (0x200 * contrast);
637 else
638 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
639
640 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
641}
642
643static void setcolors(struct gspca_dev *gspca_dev)
644{
645 struct sd *sd = (struct sd *) gspca_dev;
646 __u16 reg_to_write;
647
648 reg_to_write = 0xc0bb + sd->colors * 0x100;
649 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
650}
651
652static void setgamma(struct gspca_dev *gspca_dev)
653{
654}
655
656static void setsharpness(struct gspca_dev *gspca_dev)
657{
658 struct sd *sd = (struct sd *) gspca_dev;
659 __u16 reg_to_write;
660
661 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
662
663 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
664}
665
666static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
667{
668 struct sd *sd = (struct sd *) gspca_dev;
669
670 sd->brightness = val;
671 if (gspca_dev->streaming)
672 setbrightness(gspca_dev);
673 return 0;
674}
675
676static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
677{
678 struct sd *sd = (struct sd *) gspca_dev;
679
680 *val = sd->brightness;
681 return *val;
682}
683
684static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
685{
686 struct sd *sd = (struct sd *) gspca_dev;
687
688 sd->whitebalance = val;
689 if (gspca_dev->streaming)
690 setwhitebalance(gspca_dev);
691 return 0;
692}
693
694static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
695{
696 struct sd *sd = (struct sd *) gspca_dev;
697
698 *val = sd->whitebalance;
699 return *val;
700}
701
702static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
703{
704 struct sd *sd = (struct sd *) gspca_dev;
705
706 sd->mirror = val;
707 if (gspca_dev->streaming)
708 setflip(gspca_dev);
709 return 0;
710}
711
712static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
713{
714 struct sd *sd = (struct sd *) gspca_dev;
715
716 *val = sd->mirror;
717 return *val;
718}
719
720static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
721{
722 struct sd *sd = (struct sd *) gspca_dev;
723
724 sd->effect = val;
725 if (gspca_dev->streaming)
726 seteffect(gspca_dev);
727 return 0;
728}
729
730static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
731{
732 struct sd *sd = (struct sd *) gspca_dev;
733
734 *val = sd->effect;
735 return *val;
736}
737
738static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
739{
740 struct sd *sd = (struct sd *) gspca_dev;
741
742 sd->contrast = val;
743 if (gspca_dev->streaming)
744 setcontrast(gspca_dev);
745 return 0;
746}
747
748static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
749{
750 struct sd *sd = (struct sd *) gspca_dev;
751
752 *val = sd->contrast;
753 return *val;
754}
755
756static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
757{
758 struct sd *sd = (struct sd *) gspca_dev;
759
760 sd->colors = val;
761 if (gspca_dev->streaming)
762 setcolors(gspca_dev);
763 return 0;
764}
765
766static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
767{
768 struct sd *sd = (struct sd *) gspca_dev;
769
770 *val = sd->colors;
771 return 0;
772}
773
774static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
775{
776 struct sd *sd = (struct sd *) gspca_dev;
777
778 sd->gamma = val;
779 if (gspca_dev->streaming)
780 setgamma(gspca_dev);
781 return 0;
782}
783
784static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
785{
786 struct sd *sd = (struct sd *) gspca_dev;
787 *val = sd->gamma;
788 return 0;
789}
790
791static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
792{
793 struct sd *sd = (struct sd *) gspca_dev;
794
795 sd->freq = val;
796 if (gspca_dev->streaming)
797 setlightfreq(gspca_dev);
798 return 0;
799}
800
801static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
802{
803 struct sd *sd = (struct sd *) gspca_dev;
804
805 *val = sd->freq;
806 return 0;
807}
808
809static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
810{
811 struct sd *sd = (struct sd *) gspca_dev;
812
813 sd->sharpness = val;
814 if (gspca_dev->streaming)
815 setsharpness(gspca_dev);
816 return 0;
817}
818
819static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
820{
821 struct sd *sd = (struct sd *) gspca_dev;
822
823 *val = sd->sharpness;
824 return 0;
825}
826
827/* Low Light set here......*/
828static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
829{
830 struct sd *sd = (struct sd *) gspca_dev;
831
832 sd->autogain = val;
833 if (val != 0)
834 reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0);
835 else
836 reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0);
837 return 0;
838}
839
840static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
841{
842 struct sd *sd = (struct sd *) gspca_dev;
843
844 *val = sd->autogain;
845 return 0;
846}
847
848static void sd_start(struct gspca_dev *gspca_dev)
849{
850 int mode;
851
852 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
853 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
854 static const __u8 t3[] =
855 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
856 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
857 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
858
859 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
860 switch (mode) {
861 case 1: /* 352x288 */
862 t2[1] = 0x40;
863 break;
864 case 2: /* 320x240 */
865 t2[1] = 0x10;
866 break;
867 case 3: /* 176x144 */
868 t2[1] = 0x50;
869 break;
870 case 4: /* 160x120 */
871 t2[1] = 0x20;
872 break;
873 default: /* 640x480 (0x00) */
874 break;
875 }
876
877 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
878 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
879 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
880 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
881 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
882 /* just in case and to keep sync with logs (for mine) */
883 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
884 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
885 /* just in case and to keep sync with logs (for mine) */
886 reg_w(gspca_dev, 0x01, 0x0000, t1, 4);
887 reg_w(gspca_dev, 0x01, 0x0000, t2, 6);
888 reg_r_1(gspca_dev, 0x0012);
889 reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10);
890 reg_w(gspca_dev, 0x00, 0x0013, NULL, 0);
891 reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4);
892 /* restart on each start, just in case, sometimes regs goes wrong
893 * when using controls from app */
894 setbrightness(gspca_dev);
895 setcontrast(gspca_dev);
896 setcolors(gspca_dev);
897}
898
899static void sd_stopN(struct gspca_dev *gspca_dev)
900{
901}
902
903static void sd_stop0(struct gspca_dev *gspca_dev)
904{
905}
906
907static void sd_close(struct gspca_dev *gspca_dev)
908{
909}
910
911static void sd_pkt_scan(struct gspca_dev *gspca_dev,
912 struct gspca_frame *frame, /* target */
913 __u8 *data, /* isoc packet */
914 int len) /* iso packet length */
915{
916 int sof = 0;
917 static __u8 ffd9[] = { 0xff, 0xd9 };
918
919 if (data[0] == 0x5a) {
920 /* Control Packet, after this came the header again,
921 * but extra bytes came in the packet before this,
922 * sometimes an EOF arrives, sometimes not... */
923 return;
924 }
925
926 if (data[len - 1] == 0xff && data[len] == 0xd9) {
927 /* Just in case, i have seen packets with the marker,
928 * other's do not include it... */
929 data += 2;
930 len -= 4;
931 } else if (data[2] == 0xff && data[3] == 0xd8) {
932 sof = 1;
933 data += 2;
934 len -= 2;
935 } else {
936 data += 2;
937 len -= 2;
938 }
939
940 if (sof) {
941 /* extra bytes....., could be processed too but would be
942 * a waste of time, right now leave the application and
943 * libjpeg do it for ourserlves.. */
944 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
945 ffd9, 2);
946 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
947 return;
948 }
949
950 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
951}
952
953static int sd_querymenu(struct gspca_dev *gspca_dev,
954 struct v4l2_querymenu *menu)
955{
956 switch (menu->id) {
957 case V4L2_CID_POWER_LINE_FREQUENCY:
958 switch (menu->index) {
959 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
960 strcpy((char *) menu->name, "50 Hz");
961 return 0;
962 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
963 strcpy((char *) menu->name, "60 Hz");
964 return 0;
965 }
966 break;
967 case V4L2_CID_EFFECTS:
968 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
969 strncpy((char *) menu->name,
970 effects_control[menu->index], 32);
971 return 0;
972 }
973 break;
974 }
975 return -EINVAL;
976}
977
978/* this function is called at open time */
979static int sd_open(struct gspca_dev *gspca_dev)
980{
981 init_default_parameters(gspca_dev);
982 return 0;
983}
984
985/* sub-driver description */
986static const struct sd_desc sd_desc = {
987 .name = MODULE_NAME,
988 .ctrls = sd_ctrls,
989 .nctrls = ARRAY_SIZE(sd_ctrls),
990 .config = sd_config,
991 .open = sd_open,
992 .start = sd_start,
993 .stopN = sd_stopN,
994 .stop0 = sd_stop0,
995 .close = sd_close,
996 .pkt_scan = sd_pkt_scan,
997 .querymenu = sd_querymenu,
998};
999
1000/* -- module initialisation -- */
1001#define DVNM(name) .driver_info = (kernel_ulong_t) name
1002static const __devinitdata struct usb_device_id device_table[] = {
1003 {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
1004 {}
1005};
1006MODULE_DEVICE_TABLE(usb, device_table);
1007
1008/* -- device connect -- */
1009static int sd_probe(struct usb_interface *intf,
1010 const struct usb_device_id *id)
1011{
1012 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1013 THIS_MODULE);
1014}
1015
1016static struct usb_driver sd_driver = {
1017 .name = MODULE_NAME,
1018 .id_table = device_table,
1019 .probe = sd_probe,
1020 .disconnect = gspca_disconnect,
1021};
1022
1023/* -- module insert / remove -- */
1024static int __init sd_mod_init(void)
1025{
1026 if (usb_register(&sd_driver) < 0)
1027 return -1;
1028 PDEBUG(D_PROBE, "v%s registered", version);
1029 return 0;
1030}
1031static void __exit sd_mod_exit(void)
1032{
1033 usb_deregister(&sd_driver);
1034 PDEBUG(D_PROBE, "deregistered");
1035}
1036
1037module_init(sd_mod_init);
1038module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c
new file mode 100644
index 000000000000..0b793899095f
--- /dev/null
+++ b/drivers/media/video/gspca/tv8532.c
@@ -0,0 +1,670 @@
1/*
2 * Quickcam cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21#define MODULE_NAME "tv8532"
22
23#include "gspca.h"
24
25#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
26static const char version[] = "2.1.7";
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("TV8532 USB Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* specific webcam descriptor */
33struct sd {
34 struct gspca_dev gspca_dev; /* !! must be the first item */
35
36 int buflen; /* current length of tmpbuf */
37 __u8 tmpbuf[352 * 288 + 10 * 288]; /* no protection... */
38 __u8 tmpbuf2[352 * 288]; /* no protection... */
39
40 unsigned short brightness;
41 unsigned short contrast;
42
43 char packet;
44 char synchro;
45};
46
47/* V4L2 controls supported by the driver */
48static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
49static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
50static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
52
53static struct ctrl sd_ctrls[] = {
54#define SD_BRIGHTNESS 0
55 {
56 {
57 .id = V4L2_CID_BRIGHTNESS,
58 .type = V4L2_CTRL_TYPE_INTEGER,
59 .name = "Brightness",
60 .minimum = 1,
61 .maximum = 0x2ff,
62 .step = 1,
63 .default_value = 0x18f,
64 },
65 .set = sd_setbrightness,
66 .get = sd_getbrightness,
67 },
68#define SD_CONTRAST 1
69 {
70 {
71 .id = V4L2_CID_CONTRAST,
72 .type = V4L2_CTRL_TYPE_INTEGER,
73 .name = "Contrast",
74 .minimum = 0,
75 .maximum = 0xffff,
76 .step = 1,
77 .default_value = 0x7fff,
78 },
79 .set = sd_setcontrast,
80 .get = sd_getcontrast,
81 },
82};
83
84static struct v4l2_pix_format sif_mode[] = {
85 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
86 .bytesperline = 176,
87 .sizeimage = 176 * 144,
88 .colorspace = V4L2_COLORSPACE_SRGB,
89 .priv = 1},
90 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
91 .bytesperline = 352,
92 .sizeimage = 352 * 288,
93 .colorspace = V4L2_COLORSPACE_SRGB,
94 .priv = 0},
95};
96
97/*
98 * Initialization data: this is the first set-up data written to the
99 * device (before the open data).
100 */
101#define TESTCLK 0x10 /* reg 0x2c -> 0x12 //10 */
102#define TESTCOMP 0x90 /* reg 0x28 -> 0x80 */
103#define TESTLINE 0x81 /* reg 0x29 -> 0x81 */
104#define QCIFLINE 0x41 /* reg 0x29 -> 0x81 */
105#define TESTPTL 0x14 /* reg 0x2D -> 0x14 */
106#define TESTPTH 0x01 /* reg 0x2E -> 0x01 */
107#define TESTPTBL 0x12 /* reg 0x2F -> 0x0a */
108#define TESTPTBH 0x01 /* reg 0x30 -> 0x01 */
109#define ADWIDTHL 0xe8 /* reg 0x0c -> 0xe8 */
110#define ADWIDTHH 0x03 /* reg 0x0d -> 0x03 */
111#define ADHEIGHL 0x90 /* reg 0x0e -> 0x91 //93 */
112#define ADHEIGHH 0x01 /* reg 0x0f -> 0x01 */
113#define EXPOL 0x8f /* reg 0x1c -> 0x8f */
114#define EXPOH 0x01 /* reg 0x1d -> 0x01 */
115#define ADCBEGINL 0x44 /* reg 0x10 -> 0x46 //47 */
116#define ADCBEGINH 0x00 /* reg 0x11 -> 0x00 */
117#define ADRBEGINL 0x0a /* reg 0x14 -> 0x0b //0x0c */
118#define ADRBEGINH 0x00 /* reg 0x15 -> 0x00 */
119#define TV8532_CMD_UPDATE 0x84
120
121#define TV8532_EEprom_Add 0x03
122#define TV8532_EEprom_DataL 0x04
123#define TV8532_EEprom_DataM 0x05
124#define TV8532_EEprom_DataH 0x06
125#define TV8532_EEprom_TableLength 0x07
126#define TV8532_EEprom_Write 0x08
127#define TV8532_PART_CTRL 0x00
128#define TV8532_CTRL 0x01
129#define TV8532_CMD_EEprom_Open 0x30
130#define TV8532_CMD_EEprom_Close 0x29
131#define TV8532_UDP_UPDATE 0x31
132#define TV8532_GPIO 0x39
133#define TV8532_GPIO_OE 0x3B
134#define TV8532_REQ_RegWrite 0x02
135#define TV8532_REQ_RegRead 0x03
136
137#define TV8532_ADWIDTH_L 0x0C
138#define TV8532_ADWIDTH_H 0x0D
139#define TV8532_ADHEIGHT_L 0x0E
140#define TV8532_ADHEIGHT_H 0x0F
141#define TV8532_EXPOSURE 0x1C
142#define TV8532_QUANT_COMP 0x28
143#define TV8532_MODE_PACKET 0x29
144#define TV8532_SETCLK 0x2C
145#define TV8532_POINT_L 0x2D
146#define TV8532_POINT_H 0x2E
147#define TV8532_POINTB_L 0x2F
148#define TV8532_POINTB_H 0x30
149#define TV8532_BUDGET_L 0x2A
150#define TV8532_BUDGET_H 0x2B
151#define TV8532_VID_L 0x34
152#define TV8532_VID_H 0x35
153#define TV8532_PID_L 0x36
154#define TV8532_PID_H 0x37
155#define TV8532_DeviceID 0x83
156#define TV8532_AD_SLOPE 0x91
157#define TV8532_AD_BITCTRL 0x94
158#define TV8532_AD_COLBEGIN_L 0x10
159#define TV8532_AD_COLBEGIN_H 0x11
160#define TV8532_AD_ROWBEGIN_L 0x14
161#define TV8532_AD_ROWBEGIN_H 0x15
162
163static const __u32 tv_8532_eeprom_data[] = {
164/* add dataL dataM dataH */
165 0x00010001, 0x01018011, 0x02050014, 0x0305001c,
166 0x040d001e, 0x0505001f, 0x06050519, 0x0705011b,
167 0x0805091e, 0x090d892e, 0x0a05892f, 0x0b050dd9,
168 0x0c0509f1, 0
169};
170
171static int reg_r(struct gspca_dev *gspca_dev,
172 __u16 index)
173{
174 usb_control_msg(gspca_dev->dev,
175 usb_rcvctrlpipe(gspca_dev->dev, 0),
176 TV8532_REQ_RegRead,
177 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
178 0, /* value */
179 index, gspca_dev->usb_buf, 1,
180 500);
181 return gspca_dev->usb_buf[0];
182}
183
184/* write 1 byte */
185static void reg_w_1(struct gspca_dev *gspca_dev,
186 __u16 index, __u8 value)
187{
188 gspca_dev->usb_buf[0] = value;
189 usb_control_msg(gspca_dev->dev,
190 usb_sndctrlpipe(gspca_dev->dev, 0),
191 TV8532_REQ_RegWrite,
192 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
193 0, /* value */
194 index, gspca_dev->usb_buf, 1, 500);
195}
196
197/* write 2 bytes */
198static void reg_w_2(struct gspca_dev *gspca_dev,
199 __u16 index, __u8 val1, __u8 val2)
200{
201 gspca_dev->usb_buf[0] = val1;
202 gspca_dev->usb_buf[1] = val2;
203 usb_control_msg(gspca_dev->dev,
204 usb_sndctrlpipe(gspca_dev->dev, 0),
205 TV8532_REQ_RegWrite,
206 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
207 0, /* value */
208 index, gspca_dev->usb_buf, 2, 500);
209}
210
211static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev)
212{
213 int i = 0;
214 __u8 reg, data0, data1, data2;
215
216 reg_w_1(gspca_dev, TV8532_GPIO, 0xb0);
217 reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Open);
218/* msleep(1); */
219 while (tv_8532_eeprom_data[i]) {
220 reg = (tv_8532_eeprom_data[i] & 0xff000000) >> 24;
221 reg_w_1(gspca_dev, TV8532_EEprom_Add, reg);
222 /* msleep(1); */
223 data0 = (tv_8532_eeprom_data[i] & 0x000000ff);
224 reg_w_1(gspca_dev, TV8532_EEprom_DataL, data0);
225 /* msleep(1); */
226 data1 = (tv_8532_eeprom_data[i] & 0x0000ff00) >> 8;
227 reg_w_1(gspca_dev, TV8532_EEprom_DataM, data1);
228 /* msleep(1); */
229 data2 = (tv_8532_eeprom_data[i] & 0x00ff0000) >> 16;
230 reg_w_1(gspca_dev, TV8532_EEprom_DataH, data2);
231 /* msleep(1); */
232 reg_w_1(gspca_dev, TV8532_EEprom_Write, 0);
233 /* msleep(10); */
234 i++;
235 }
236 reg_w_1(gspca_dev, TV8532_EEprom_TableLength, i);
237/* msleep(1); */
238 reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Close);
239 msleep(10);
240}
241
242/* this function is called at probe time */
243static int sd_config(struct gspca_dev *gspca_dev,
244 const struct usb_device_id *id)
245{
246 struct sd *sd = (struct sd *) gspca_dev;
247 struct cam *cam;
248
249 tv_8532WriteEEprom(gspca_dev);
250
251 cam = &gspca_dev->cam;
252 cam->dev_name = (char *) id->driver_info;
253 cam->epaddr = 1;
254 cam->cam_mode = sif_mode;
255 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
256
257 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
258 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
259 return 0;
260}
261
262static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev)
263{
264 __u8 data;
265
266 data = reg_r(gspca_dev, 0x0001);
267 PDEBUG(D_USBI, "register 0x01-> %x", data);
268 data = reg_r(gspca_dev, 0x0002);
269 PDEBUG(D_USBI, "register 0x02-> %x", data);
270 reg_r(gspca_dev, TV8532_ADWIDTH_L);
271 reg_r(gspca_dev, TV8532_ADWIDTH_H);
272 reg_r(gspca_dev, TV8532_QUANT_COMP);
273 reg_r(gspca_dev, TV8532_MODE_PACKET);
274 reg_r(gspca_dev, TV8532_SETCLK);
275 reg_r(gspca_dev, TV8532_POINT_L);
276 reg_r(gspca_dev, TV8532_POINT_H);
277 reg_r(gspca_dev, TV8532_POINTB_L);
278 reg_r(gspca_dev, TV8532_POINTB_H);
279 reg_r(gspca_dev, TV8532_BUDGET_L);
280 reg_r(gspca_dev, TV8532_BUDGET_H);
281 reg_r(gspca_dev, TV8532_VID_L);
282 reg_r(gspca_dev, TV8532_VID_H);
283 reg_r(gspca_dev, TV8532_PID_L);
284 reg_r(gspca_dev, TV8532_PID_H);
285 reg_r(gspca_dev, TV8532_DeviceID);
286 reg_r(gspca_dev, TV8532_AD_COLBEGIN_L);
287 reg_r(gspca_dev, TV8532_AD_COLBEGIN_H);
288 reg_r(gspca_dev, TV8532_AD_ROWBEGIN_L);
289 reg_r(gspca_dev, TV8532_AD_ROWBEGIN_H);
290}
291
292static void tv_8532_setReg(struct gspca_dev *gspca_dev)
293{
294 reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L,
295 ADCBEGINL); /* 0x10 */
296 reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H,
297 ADCBEGINH); /* also digital gain */
298 reg_w_1(gspca_dev, TV8532_PART_CTRL,
299 TV8532_CMD_UPDATE); /* 0x00<-0x84 */
300
301 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0a);
302 /******************************************************/
303 reg_w_1(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL); /* 0e */
304 reg_w_1(gspca_dev, TV8532_ADHEIGHT_H, ADHEIGHH); /* 0f */
305 reg_w_2(gspca_dev, TV8532_EXPOSURE,
306 EXPOL, EXPOH); /* 350d 0x014c; 1c */
307 reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L,
308 ADCBEGINL); /* 0x10 */
309 reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H,
310 ADCBEGINH); /* also digital gain */
311 reg_w_1(gspca_dev, TV8532_AD_ROWBEGIN_L,
312 ADRBEGINL); /* 0x14 */
313
314 reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00); /* 0x91 */
315 reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x02); /* 0x94 */
316
317 reg_w_1(gspca_dev, TV8532_CTRL,
318 TV8532_CMD_EEprom_Close); /* 0x01 */
319
320 reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00); /* 0x91 */
321 reg_w_1(gspca_dev, TV8532_PART_CTRL,
322 TV8532_CMD_UPDATE); /* 0x00<-0x84 */
323}
324
325static void tv_8532_PollReg(struct gspca_dev *gspca_dev)
326{
327 int i;
328
329 /* strange polling from tgc */
330 for (i = 0; i < 10; i++) {
331 reg_w_1(gspca_dev, TV8532_SETCLK,
332 TESTCLK); /* 0x48; //0x08; 0x2c */
333 reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE);
334 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */
335 }
336}
337
338/* this function is called at open time */
339static int sd_open(struct gspca_dev *gspca_dev)
340{
341 reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
342 reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
343 tv_8532ReadRegisters(gspca_dev);
344 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
345 reg_w_2(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL,
346 ADHEIGHH); /* 401d 0x0169; 0e */
347 reg_w_2(gspca_dev, TV8532_EXPOSURE, EXPOL,
348 EXPOH); /* 350d 0x014c; 1c */
349 reg_w_1(gspca_dev, TV8532_ADWIDTH_L, ADWIDTHL); /* 0x20; 0x0c */
350 reg_w_1(gspca_dev, TV8532_ADWIDTH_H, ADWIDTHH); /* 0x0d */
351
352 /*******************************************************************/
353 reg_w_1(gspca_dev, TV8532_QUANT_COMP,
354 TESTCOMP); /* 0x72 compressed mode 0x28 */
355 reg_w_1(gspca_dev, TV8532_MODE_PACKET,
356 TESTLINE); /* 0x84; // CIF | 4 packet 0x29 */
357
358 /************************************************/
359 reg_w_1(gspca_dev, TV8532_SETCLK,
360 TESTCLK); /* 0x48; //0x08; 0x2c */
361 reg_w_1(gspca_dev, TV8532_POINT_L,
362 TESTPTL); /* 0x38; 0x2d */
363 reg_w_1(gspca_dev, TV8532_POINT_H,
364 TESTPTH); /* 0x04; 0x2e */
365 reg_w_1(gspca_dev, TV8532_POINTB_L,
366 TESTPTBL); /* 0x04; 0x2f */
367 reg_w_1(gspca_dev, TV8532_POINTB_H,
368 TESTPTBH); /* 0x04; 0x30 */
369 reg_w_1(gspca_dev, TV8532_PART_CTRL,
370 TV8532_CMD_UPDATE); /* 0x00<-0x84 */
371 /*************************************************/
372 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */
373 msleep(200);
374 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */
375 /*************************************************/
376 tv_8532_setReg(gspca_dev);
377 /*************************************************/
378 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
379 /*************************************************/
380 tv_8532_setReg(gspca_dev);
381 /*************************************************/
382 tv_8532_PollReg(gspca_dev);
383 return 0;
384}
385
386static void setbrightness(struct gspca_dev *gspca_dev)
387{
388 struct sd *sd = (struct sd *) gspca_dev;
389 int brightness = sd->brightness;
390
391 reg_w_2(gspca_dev, TV8532_EXPOSURE,
392 brightness >> 8, brightness); /* 1c */
393 reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE);
394}
395
396/* -- start the camera -- */
397static void sd_start(struct gspca_dev *gspca_dev)
398{
399 reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
400 reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
401 tv_8532ReadRegisters(gspca_dev);
402 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
403 reg_w_2(gspca_dev, TV8532_ADHEIGHT_L,
404 ADHEIGHL, ADHEIGHH); /* 401d 0x0169; 0e */
405/* reg_w_2(gspca_dev, TV8532_EXPOSURE,
406 EXPOL, EXPOH); * 350d 0x014c; 1c */
407 setbrightness(gspca_dev);
408
409 reg_w_1(gspca_dev, TV8532_ADWIDTH_L, ADWIDTHL); /* 0x20; 0x0c */
410 reg_w_1(gspca_dev, TV8532_ADWIDTH_H, ADWIDTHH); /* 0x0d */
411
412 /************************************************/
413 reg_w_1(gspca_dev, TV8532_QUANT_COMP,
414 TESTCOMP); /* 0x72 compressed mode 0x28 */
415 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
416 /* 176x144 */
417 reg_w_1(gspca_dev, TV8532_MODE_PACKET,
418 QCIFLINE); /* 0x84; // CIF | 4 packet 0x29 */
419 } else {
420 /* 352x288 */
421 reg_w_1(gspca_dev, TV8532_MODE_PACKET,
422 TESTLINE); /* 0x84; // CIF | 4 packet 0x29 */
423 }
424 /************************************************/
425 reg_w_1(gspca_dev, TV8532_SETCLK,
426 TESTCLK); /* 0x48; //0x08; 0x2c */
427 reg_w_1(gspca_dev, TV8532_POINT_L,
428 TESTPTL); /* 0x38; 0x2d */
429 reg_w_1(gspca_dev, TV8532_POINT_H,
430 TESTPTH); /* 0x04; 0x2e */
431 reg_w_1(gspca_dev, TV8532_POINTB_L,
432 TESTPTBL); /* 0x04; 0x2f */
433 reg_w_1(gspca_dev, TV8532_POINTB_H,
434 TESTPTBH); /* 0x04; 0x30 */
435 reg_w_1(gspca_dev, TV8532_PART_CTRL,
436 TV8532_CMD_UPDATE); /* 0x00<-0x84 */
437 /************************************************/
438 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */
439 msleep(200);
440 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */
441 /************************************************/
442 tv_8532_setReg(gspca_dev);
443 /************************************************/
444 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
445 /************************************************/
446 tv_8532_setReg(gspca_dev);
447 /************************************************/
448 tv_8532_PollReg(gspca_dev);
449 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */
450}
451
452static void sd_stopN(struct gspca_dev *gspca_dev)
453{
454 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
455}
456
457static void sd_stop0(struct gspca_dev *gspca_dev)
458{
459}
460
461static void sd_close(struct gspca_dev *gspca_dev)
462{
463}
464
465static void tv8532_preprocess(struct gspca_dev *gspca_dev)
466{
467 struct sd *sd = (struct sd *) gspca_dev;
468/* we should received a whole frame with header and EOL marker
469 * in gspca_dev->tmpbuf and return a GBRG pattern in gspca_dev->tmpbuf2
470 * sequence 2bytes header the Alternate pixels bayer GB 4 bytes
471 * Alternate pixels bayer RG 4 bytes EOL */
472 int width = gspca_dev->width;
473 int height = gspca_dev->height;
474 unsigned char *dst = sd->tmpbuf2;
475 unsigned char *data = sd->tmpbuf;
476 int i;
477
478 /* precompute where is the good bayer line */
479 if (((data[3] + data[width + 7]) >> 1)
480 + (data[4] >> 2)
481 + (data[width + 6] >> 1) >= ((data[2] + data[width + 6]) >> 1)
482 + (data[3] >> 2)
483 + (data[width + 5] >> 1))
484 data += 3;
485 else
486 data += 2;
487 for (i = 0; i < height / 2; i++) {
488 memcpy(dst, data, width);
489 data += width + 3;
490 dst += width;
491 memcpy(dst, data, width);
492 data += width + 7;
493 dst += width;
494 }
495}
496
497static void sd_pkt_scan(struct gspca_dev *gspca_dev,
498 struct gspca_frame *frame, /* target */
499 __u8 *data, /* isoc packet */
500 int len) /* iso packet length */
501{
502 struct sd *sd = (struct sd *) gspca_dev;
503
504 if (data[0] != 0x80) {
505 sd->packet++;
506 if (sd->buflen + len > sizeof sd->tmpbuf) {
507 if (gspca_dev->last_packet_type != DISCARD_PACKET) {
508 PDEBUG(D_PACK, "buffer overflow");
509 gspca_dev->last_packet_type = DISCARD_PACKET;
510 }
511 return;
512 }
513 memcpy(&sd->tmpbuf[sd->buflen], data, len);
514 sd->buflen += len;
515 return;
516 }
517
518 /* here we detect 0x80 */
519 /* counter is limited so we need few header for a frame :) */
520
521 /* header 0x80 0x80 0x80 0x80 0x80 */
522 /* packet 00 63 127 145 00 */
523 /* sof 0 1 1 0 0 */
524
525 /* update sequence */
526 if (sd->packet == 63 || sd->packet == 127)
527 sd->synchro = 1;
528
529 /* is there a frame start ? */
530 if (sd->packet >= (gspca_dev->height >> 1) - 1) {
531 PDEBUG(D_PACK, "SOF > %d packet %d", sd->synchro,
532 sd->packet);
533 if (!sd->synchro) { /* start of frame */
534 if (gspca_dev->last_packet_type == FIRST_PACKET) {
535 tv8532_preprocess(gspca_dev);
536 frame = gspca_frame_add(gspca_dev,
537 LAST_PACKET,
538 frame, sd->tmpbuf2,
539 gspca_dev->width *
540 gspca_dev->width);
541 }
542 gspca_frame_add(gspca_dev, FIRST_PACKET,
543 frame, data, 0);
544 memcpy(sd->tmpbuf, data, len);
545 sd->buflen = len;
546 sd->packet = 0;
547 return;
548 }
549 if (gspca_dev->last_packet_type != DISCARD_PACKET) {
550 PDEBUG(D_PACK,
551 "Warning wrong TV8532 frame detection %d",
552 sd->packet);
553 gspca_dev->last_packet_type = DISCARD_PACKET;
554 }
555 return;
556 }
557
558 if (!sd->synchro) {
559 /* Drop packet frame corrupt */
560 PDEBUG(D_PACK, "DROP SOF %d packet %d",
561 sd->synchro, sd->packet);
562 sd->packet = 0;
563 gspca_dev->last_packet_type = DISCARD_PACKET;
564 return;
565 }
566 sd->synchro = 1;
567 sd->packet++;
568 memcpy(&sd->tmpbuf[sd->buflen], data, len);
569 sd->buflen += len;
570}
571
572static void setcontrast(struct gspca_dev *gspca_dev)
573{
574}
575
576static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
577{
578 struct sd *sd = (struct sd *) gspca_dev;
579
580 sd->brightness = val;
581 if (gspca_dev->streaming)
582 setbrightness(gspca_dev);
583 return 0;
584}
585
586static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
587{
588 struct sd *sd = (struct sd *) gspca_dev;
589
590 *val = sd->brightness;
591 return 0;
592}
593
594static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
595{
596 struct sd *sd = (struct sd *) gspca_dev;
597
598 sd->contrast = val;
599 if (gspca_dev->streaming)
600 setcontrast(gspca_dev);
601 return 0;
602}
603
604static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
605{
606 struct sd *sd = (struct sd *) gspca_dev;
607
608 *val = sd->contrast;
609 return 0;
610}
611
612/* sub-driver description */
613static const struct sd_desc sd_desc = {
614 .name = MODULE_NAME,
615 .ctrls = sd_ctrls,
616 .nctrls = ARRAY_SIZE(sd_ctrls),
617 .config = sd_config,
618 .open = sd_open,
619 .start = sd_start,
620 .stopN = sd_stopN,
621 .stop0 = sd_stop0,
622 .close = sd_close,
623 .pkt_scan = sd_pkt_scan,
624};
625
626/* -- module initialisation -- */
627#define DVNM(name) .driver_info = (kernel_ulong_t) name
628static const __devinitdata struct usb_device_id device_table[] = {
629 {USB_DEVICE(0x046d, 0x0920), DVNM("QC Express")},
630 {USB_DEVICE(0x046d, 0x0921), DVNM("Labtec Webcam")},
631 {USB_DEVICE(0x0545, 0x808b), DVNM("Veo Stingray")},
632 {USB_DEVICE(0x0545, 0x8333), DVNM("Veo Stingray")},
633 {USB_DEVICE(0x0923, 0x010f), DVNM("ICM532 cams")},
634 {}
635};
636
637MODULE_DEVICE_TABLE(usb, device_table);
638
639/* -- device connect -- */
640static int sd_probe(struct usb_interface *intf,
641 const struct usb_device_id *id)
642{
643 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
644 THIS_MODULE);
645}
646
647static struct usb_driver sd_driver = {
648 .name = MODULE_NAME,
649 .id_table = device_table,
650 .probe = sd_probe,
651 .disconnect = gspca_disconnect,
652};
653
654/* -- module insert / remove -- */
655static int __init sd_mod_init(void)
656{
657 if (usb_register(&sd_driver) < 0)
658 return -1;
659 PDEBUG(D_PROBE, "v%s registered", version);
660 return 0;
661}
662
663static void __exit sd_mod_exit(void)
664{
665 usb_deregister(&sd_driver);
666 PDEBUG(D_PROBE, "deregistered");
667}
668
669module_init(sd_mod_init);
670module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
new file mode 100644
index 000000000000..fcf2c9e32573
--- /dev/null
+++ b/drivers/media/video/gspca/vc032x.c
@@ -0,0 +1,1818 @@
1/*
2 * Z-star vc0321 library
3 * Copyright (C) 2006 Koninski Artur takeshi87@o2.pl
4 * Copyright (C) 2006 Michel Xhaard
5 *
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#define MODULE_NAME "vc032x"
24
25#include "gspca.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/VC032X USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 unsigned char autogain;
39 unsigned char lightfreq;
40
41 char qindex;
42 char bridge;
43#define BRIDGE_VC0321 0
44#define BRIDGE_VC0323 1
45 char sensor;
46#define SENSOR_HV7131R 0
47#define SENSOR_MI1320 1
48#define SENSOR_MI1310_SOC 2
49#define SENSOR_OV7660 3
50#define SENSOR_OV7670 4
51#define SENSOR_PO3130NC 5
52};
53
54/* V4L2 controls supported by the driver */
55static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
56static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
57static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
58static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
59
60static struct ctrl sd_ctrls[] = {
61 {
62 {
63 .id = V4L2_CID_AUTOGAIN,
64 .type = V4L2_CTRL_TYPE_BOOLEAN,
65 .name = "Auto Gain",
66 .minimum = 0,
67 .maximum = 1,
68 .step = 1,
69#define AUTOGAIN_DEF 1
70 .default_value = AUTOGAIN_DEF,
71 },
72 .set = sd_setautogain,
73 .get = sd_getautogain,
74 },
75 {
76 {
77 .id = V4L2_CID_POWER_LINE_FREQUENCY,
78 .type = V4L2_CTRL_TYPE_MENU,
79 .name = "Light frequency filter",
80 .minimum = 0,
81 .maximum = 2, /* 0: No, 1: 50Hz, 2:60Hz */
82 .step = 1,
83#define FREQ_DEF 1
84 .default_value = FREQ_DEF,
85 .default_value = 1,
86 },
87 .set = sd_setfreq,
88 .get = sd_getfreq,
89 },
90};
91
92static struct v4l2_pix_format vc0321_mode[] = {
93 {320, 240, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
94 .bytesperline = 320 * 2,
95 .sizeimage = 320 * 240 * 2,
96 .colorspace = V4L2_COLORSPACE_SRGB,
97 .priv = 1},
98 {640, 480, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
99 .bytesperline = 640 * 2,
100 .sizeimage = 640 * 480 * 2,
101 .colorspace = V4L2_COLORSPACE_SRGB,
102 .priv = 0},
103};
104static struct v4l2_pix_format vc0323_mode[] = {
105 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
106 .bytesperline = 320,
107 .sizeimage = 320 * 240 * 3 / 8 + 590,
108 .colorspace = V4L2_COLORSPACE_JPEG,
109 .priv = 1},
110 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
111 .bytesperline = 640,
112 .sizeimage = 640 * 480 * 3 / 8 + 590,
113 .colorspace = V4L2_COLORSPACE_JPEG,
114 .priv = 0},
115};
116
117static const __u8 mi1310_socinitVGA_JPG[][4] = {
118 {0xb0, 0x03, 0x19, 0xcc},
119 {0xb0, 0x04, 0x02, 0xcc},
120 {0xb3, 0x00, 0x64, 0xcc},
121 {0xb3, 0x00, 0x65, 0xcc},
122 {0xb3, 0x05, 0x00, 0xcc},
123 {0xb3, 0x06, 0x00, 0xcc},
124 {0xb3, 0x08, 0x01, 0xcc},
125 {0xb3, 0x09, 0x0c, 0xcc},
126 {0xb3, 0x34, 0x02, 0xcc},
127 {0xb3, 0x35, 0xdd, 0xcc},
128 {0xb3, 0x02, 0x00, 0xcc},
129 {0xb3, 0x03, 0x0a, 0xcc},
130 {0xb3, 0x04, 0x05, 0xcc},
131 {0xb3, 0x20, 0x00, 0xcc},
132 {0xb3, 0x21, 0x00, 0xcc},
133 {0xb3, 0x22, 0x03, 0xcc},
134 {0xb3, 0x23, 0xc0, 0xcc},
135 {0xb3, 0x14, 0x00, 0xcc},
136 {0xb3, 0x15, 0x00, 0xcc},
137 {0xb3, 0x16, 0x04, 0xcc},
138 {0xb3, 0x17, 0xff, 0xcc},
139 {0xb3, 0x00, 0x65, 0xcc},
140 {0xb8, 0x00, 0x00, 0xcc},
141 {0xbc, 0x00, 0xd0, 0xcc},
142 {0xbc, 0x01, 0x01, 0xcc},
143 {0xf0, 0x00, 0x02, 0xbb},
144 {0xc8, 0x9f, 0x0b, 0xbb},
145 {0x5b, 0x00, 0x01, 0xbb},
146 {0x2f, 0xde, 0x20, 0xbb},
147 {0xf0, 0x00, 0x00, 0xbb},
148 {0x20, 0x03, 0x02, 0xbb},
149 {0xf0, 0x00, 0x01, 0xbb},
150 {0x05, 0x00, 0x07, 0xbb},
151 {0x34, 0x00, 0x00, 0xbb},
152 {0x35, 0xff, 0x00, 0xbb},
153 {0xdc, 0x07, 0x02, 0xbb},
154 {0xdd, 0x3c, 0x18, 0xbb},
155 {0xde, 0x92, 0x6d, 0xbb},
156 {0xdf, 0xcd, 0xb1, 0xbb},
157 {0xe0, 0xff, 0xe7, 0xbb},
158 {0x06, 0xf0, 0x0d, 0xbb},
159 {0x06, 0x70, 0x0e, 0xbb},
160 {0x4c, 0x00, 0x01, 0xbb},
161 {0x4d, 0x00, 0x01, 0xbb},
162 {0xf0, 0x00, 0x02, 0xbb},
163 {0x2e, 0x0c, 0x55, 0xbb},
164 {0x21, 0xb6, 0x6e, 0xbb},
165 {0x36, 0x30, 0x10, 0xbb},
166 {0x37, 0x00, 0xc1, 0xbb},
167 {0xf0, 0x00, 0x00, 0xbb},
168 {0x07, 0x00, 0x84, 0xbb},
169 {0x08, 0x02, 0x4a, 0xbb},
170 {0x05, 0x01, 0x10, 0xbb},
171 {0x06, 0x00, 0x39, 0xbb},
172 {0xf0, 0x00, 0x02, 0xbb},
173 {0x58, 0x02, 0x67, 0xbb},
174 {0x57, 0x02, 0x00, 0xbb},
175 {0x5a, 0x02, 0x67, 0xbb},
176 {0x59, 0x02, 0x00, 0xbb},
177 {0x5c, 0x12, 0x0d, 0xbb},
178 {0x5d, 0x16, 0x11, 0xbb},
179 {0x39, 0x06, 0x18, 0xbb},
180 {0x3a, 0x06, 0x18, 0xbb},
181 {0x3b, 0x06, 0x18, 0xbb},
182 {0x3c, 0x06, 0x18, 0xbb},
183 {0x64, 0x7b, 0x5b, 0xbb},
184 {0xf0, 0x00, 0x02, 0xbb},
185 {0x36, 0x30, 0x10, 0xbb},
186 {0x37, 0x00, 0xc0, 0xbb},
187 {0xbc, 0x0e, 0x00, 0xcc},
188 {0xbc, 0x0f, 0x05, 0xcc},
189 {0xbc, 0x10, 0xc0, 0xcc},
190 {0xbc, 0x11, 0x03, 0xcc},
191 {0xb6, 0x00, 0x00, 0xcc},
192 {0xb6, 0x03, 0x02, 0xcc},
193 {0xb6, 0x02, 0x80, 0xcc},
194 {0xb6, 0x05, 0x01, 0xcc},
195 {0xb6, 0x04, 0xe0, 0xcc},
196 {0xb6, 0x12, 0xf8, 0xcc},
197 {0xb6, 0x13, 0x25, 0xcc},
198 {0xb6, 0x18, 0x02, 0xcc},
199 {0xb6, 0x17, 0x58, 0xcc},
200 {0xb6, 0x16, 0x00, 0xcc},
201 {0xb6, 0x22, 0x12, 0xcc},
202 {0xb6, 0x23, 0x0b, 0xcc},
203 {0xbf, 0xc0, 0x39, 0xcc},
204 {0xbf, 0xc1, 0x04, 0xcc},
205 {0xbf, 0xcc, 0x00, 0xcc},
206 {0xbc, 0x02, 0x18, 0xcc},
207 {0xbc, 0x03, 0x50, 0xcc},
208 {0xbc, 0x04, 0x18, 0xcc},
209 {0xbc, 0x05, 0x00, 0xcc},
210 {0xbc, 0x06, 0x00, 0xcc},
211 {0xbc, 0x08, 0x30, 0xcc},
212 {0xbc, 0x09, 0x40, 0xcc},
213 {0xbc, 0x0a, 0x10, 0xcc},
214 {0xbc, 0x0b, 0x00, 0xcc},
215 {0xbc, 0x0c, 0x00, 0xcc},
216 {0xb3, 0x5c, 0x01, 0xcc},
217 {0xf0, 0x00, 0x01, 0xbb},
218 {0x80, 0x00, 0x03, 0xbb},
219 {0x81, 0xc7, 0x14, 0xbb},
220 {0x82, 0xeb, 0xe8, 0xbb},
221 {0x83, 0xfe, 0xf4, 0xbb},
222 {0x84, 0xcd, 0x10, 0xbb},
223 {0x85, 0xf3, 0xee, 0xbb},
224 {0x86, 0xff, 0xf1, 0xbb},
225 {0x87, 0xcd, 0x10, 0xbb},
226 {0x88, 0xf3, 0xee, 0xbb},
227 {0x89, 0x01, 0xf1, 0xbb},
228 {0x8a, 0xe5, 0x17, 0xbb},
229 {0x8b, 0xe8, 0xe2, 0xbb},
230 {0x8c, 0xf7, 0xed, 0xbb},
231 {0x8d, 0x00, 0xff, 0xbb},
232 {0x8e, 0xec, 0x10, 0xbb},
233 {0x8f, 0xf0, 0xed, 0xbb},
234 {0x90, 0xf9, 0xf2, 0xbb},
235 {0x91, 0x00, 0x00, 0xbb},
236 {0x92, 0xe9, 0x0d, 0xbb},
237 {0x93, 0xf4, 0xf2, 0xbb},
238 {0x94, 0xfb, 0xf5, 0xbb},
239 {0x95, 0x00, 0xff, 0xbb},
240 {0xb6, 0x0f, 0x08, 0xbb},
241 {0xb7, 0x3d, 0x16, 0xbb},
242 {0xb8, 0x0c, 0x04, 0xbb},
243 {0xb9, 0x1c, 0x07, 0xbb},
244 {0xba, 0x0a, 0x03, 0xbb},
245 {0xbb, 0x1b, 0x09, 0xbb},
246 {0xbc, 0x17, 0x0d, 0xbb},
247 {0xbd, 0x23, 0x1d, 0xbb},
248 {0xbe, 0x00, 0x28, 0xbb},
249 {0xbf, 0x11, 0x09, 0xbb},
250 {0xc0, 0x16, 0x15, 0xbb},
251 {0xc1, 0x00, 0x1b, 0xbb},
252 {0xc2, 0x0e, 0x07, 0xbb},
253 {0xc3, 0x14, 0x10, 0xbb},
254 {0xc4, 0x00, 0x17, 0xbb},
255 {0x06, 0x74, 0x8e, 0xbb},
256 {0xf0, 0x00, 0x01, 0xbb},
257 {0x06, 0xf4, 0x8e, 0xbb},
258 {0x00, 0x00, 0x50, 0xdd},
259 {0x06, 0x74, 0x8e, 0xbb},
260 {0xf0, 0x00, 0x02, 0xbb},
261 {0x24, 0x50, 0x20, 0xbb},
262 {0xf0, 0x00, 0x02, 0xbb},
263 {0x34, 0x0c, 0x50, 0xbb},
264 {0xb3, 0x01, 0x41, 0xcc},
265 {0xf0, 0x00, 0x00, 0xbb},
266 {0x03, 0x03, 0xc0, 0xbb},
267 {},
268};
269static const __u8 mi1310_socinitQVGA_JPG[][4] = {
270 {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc},
271 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
272 {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x00, 0xcc},
273 {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc},
274 {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc},
275 {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc},
276 {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
277 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x03, 0xcc},
278 {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc},
279 {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x04, 0xcc},
280 {0xb3, 0x17, 0xff, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
281 {0xb8, 0x00, 0x00, 0xcc}, {0xbc, 0x00, 0xf0, 0xcc},
282 {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x02, 0xbb},
283 {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb},
284 {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
285 {0x20, 0x03, 0x02, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
286 {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb},
287 {0x35, 0xff, 0x00, 0xbb}, {0xdc, 0x07, 0x02, 0xbb},
288 {0xdd, 0x3c, 0x18, 0xbb}, {0xde, 0x92, 0x6d, 0xbb},
289 {0xdf, 0xcd, 0xb1, 0xbb}, {0xe0, 0xff, 0xe7, 0xbb},
290 {0x06, 0xf0, 0x0d, 0xbb}, {0x06, 0x70, 0x0e, 0xbb},
291 {0x4c, 0x00, 0x01, 0xbb}, {0x4d, 0x00, 0x01, 0xbb},
292 {0xf0, 0x00, 0x02, 0xbb}, {0x2e, 0x0c, 0x55, 0xbb},
293 {0x21, 0xb6, 0x6e, 0xbb}, {0x36, 0x30, 0x10, 0xbb},
294 {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
295 {0x07, 0x00, 0x84, 0xbb}, {0x08, 0x02, 0x4a, 0xbb},
296 {0x05, 0x01, 0x10, 0xbb}, {0x06, 0x00, 0x39, 0xbb},
297 {0xf0, 0x00, 0x02, 0xbb}, {0x58, 0x02, 0x67, 0xbb},
298 {0x57, 0x02, 0x00, 0xbb}, {0x5a, 0x02, 0x67, 0xbb},
299 {0x59, 0x02, 0x00, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb},
300 {0x5d, 0x16, 0x11, 0xbb}, {0x39, 0x06, 0x18, 0xbb},
301 {0x3a, 0x06, 0x18, 0xbb}, {0x3b, 0x06, 0x18, 0xbb},
302 {0x3c, 0x06, 0x18, 0xbb}, {0x64, 0x7b, 0x5b, 0xbb},
303 {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x30, 0x10, 0xbb},
304 {0x37, 0x00, 0xc0, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc},
305 {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc},
306 {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc},
307 {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc},
308 {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc},
309 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x25, 0xcc},
310 {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc},
311 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
312 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc},
313 {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc},
314 {0xb3, 0x5c, 0x01, 0xcc}, {0xf0, 0x00, 0x01, 0xbb},
315 {0x80, 0x00, 0x03, 0xbb}, {0x81, 0xc7, 0x14, 0xbb},
316 {0x82, 0xeb, 0xe8, 0xbb}, {0x83, 0xfe, 0xf4, 0xbb},
317 {0x84, 0xcd, 0x10, 0xbb}, {0x85, 0xf3, 0xee, 0xbb},
318 {0x86, 0xff, 0xf1, 0xbb}, {0x87, 0xcd, 0x10, 0xbb},
319 {0x88, 0xf3, 0xee, 0xbb}, {0x89, 0x01, 0xf1, 0xbb},
320 {0x8a, 0xe5, 0x17, 0xbb}, {0x8b, 0xe8, 0xe2, 0xbb},
321 {0x8c, 0xf7, 0xed, 0xbb}, {0x8d, 0x00, 0xff, 0xbb},
322 {0x8e, 0xec, 0x10, 0xbb}, {0x8f, 0xf0, 0xed, 0xbb},
323 {0x90, 0xf9, 0xf2, 0xbb}, {0x91, 0x00, 0x00, 0xbb},
324 {0x92, 0xe9, 0x0d, 0xbb}, {0x93, 0xf4, 0xf2, 0xbb},
325 {0x94, 0xfb, 0xf5, 0xbb}, {0x95, 0x00, 0xff, 0xbb},
326 {0xb6, 0x0f, 0x08, 0xbb}, {0xb7, 0x3d, 0x16, 0xbb},
327 {0xb8, 0x0c, 0x04, 0xbb}, {0xb9, 0x1c, 0x07, 0xbb},
328 {0xba, 0x0a, 0x03, 0xbb}, {0xbb, 0x1b, 0x09, 0xbb},
329 {0xbc, 0x17, 0x0d, 0xbb}, {0xbd, 0x23, 0x1d, 0xbb},
330 {0xbe, 0x00, 0x28, 0xbb}, {0xbf, 0x11, 0x09, 0xbb},
331 {0xc0, 0x16, 0x15, 0xbb}, {0xc1, 0x00, 0x1b, 0xbb},
332 {0xc2, 0x0e, 0x07, 0xbb}, {0xc3, 0x14, 0x10, 0xbb},
333 {0xc4, 0x00, 0x17, 0xbb}, {0x06, 0x74, 0x8e, 0xbb},
334 {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0xf4, 0x8e, 0xbb},
335 {0x00, 0x00, 0x50, 0xdd}, {0x06, 0x74, 0x8e, 0xbb},
336 {0xf0, 0x00, 0x02, 0xbb}, {0x24, 0x50, 0x20, 0xbb},
337 {0xf0, 0x00, 0x02, 0xbb}, {0x34, 0x0c, 0x50, 0xbb},
338 {0xb3, 0x01, 0x41, 0xcc}, {0xf0, 0x00, 0x00, 0xbb},
339 {0x03, 0x03, 0xc0, 0xbb},
340 {},
341};
342
343static const __u8 mi1320_gamma[17] = {
344 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
345 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
346};
347static const __u8 mi1320_matrix[9] = {
348 0x54, 0xda, 0x06, 0xf1, 0x50, 0xf4, 0xf7, 0xea, 0x52
349};
350static const __u8 mi1320_initVGA_data[][4] = {
351 {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
352 {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
353 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
354 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
355 {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
356 {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
357 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc},
358 {0xb3, 0x35, 0xc8, 0xcc}, {0xb3, 0x02, 0x00, 0xcc},
359 {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
360 {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
361 {0xb3, 0x22, 0x03, 0xcc}, {0xb3, 0x23, 0xc0, 0xcc},
362 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
363 {0xb3, 0x16, 0x04, 0xcc}, {0xb3, 0x17, 0xff, 0xcc},
364 {0xb3, 0x00, 0x67, 0xcc}, {0xbc, 0x00, 0xd0, 0xcc},
365 {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x00, 0xbb},
366 {0x0d, 0x00, 0x09, 0xbb}, {0x00, 0x01, 0x00, 0xdd},
367 {0x0d, 0x00, 0x08, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
368 {0xa1, 0x05, 0x00, 0xbb}, {0xa4, 0x03, 0xc0, 0xbb},
369 {0xf0, 0x00, 0x02, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
370 {0xc8, 0x9f, 0x0b, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
371 {0xf0, 0x00, 0x00, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
372 {0x20, 0x01, 0x00, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
373 {0xf0, 0x00, 0x01, 0xbb}, {0x9d, 0x3c, 0xa0, 0xbb},
374 {0x47, 0x30, 0x30, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
375 {0x0a, 0x80, 0x11, 0xbb}, {0x35, 0x00, 0x22, 0xbb},
376 {0xf0, 0x00, 0x02, 0xbb}, {0x9d, 0xc5, 0x05, 0xbb},
377 {0xdc, 0x0f, 0xfc, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
378 {0x06, 0x74, 0x0e, 0xbb}, {0x80, 0x00, 0x06, 0xbb},
379 {0x81, 0x04, 0x00, 0xbb}, {0x82, 0x01, 0x02, 0xbb},
380 {0x83, 0x03, 0x02, 0xbb}, {0x84, 0x05, 0x00, 0xbb},
381 {0x85, 0x01, 0x00, 0xbb}, {0x86, 0x03, 0x02, 0xbb},
382 {0x87, 0x05, 0x00, 0xbb}, {0x88, 0x01, 0x00, 0xbb},
383 {0x89, 0x02, 0x02, 0xbb}, {0x8a, 0xfd, 0x04, 0xbb},
384 {0x8b, 0xfc, 0xfd, 0xbb}, {0x8c, 0xff, 0xfd, 0xbb},
385 {0x8d, 0x00, 0x00, 0xbb}, {0x8e, 0xfe, 0x05, 0xbb},
386 {0x8f, 0xfc, 0xfd, 0xbb}, {0x90, 0xfe, 0xfd, 0xbb},
387 {0x91, 0x00, 0x00, 0xbb}, {0x92, 0xfe, 0x03, 0xbb},
388 {0x93, 0xfd, 0xfe, 0xbb}, {0x94, 0xff, 0xfd, 0xbb},
389 {0x95, 0x00, 0x00, 0xbb}, {0xb6, 0x07, 0x05, 0xbb},
390 {0xb7, 0x13, 0x06, 0xbb}, {0xb8, 0x08, 0x06, 0xbb},
391 {0xb9, 0x14, 0x08, 0xbb}, {0xba, 0x06, 0x05, 0xbb},
392 {0xbb, 0x13, 0x06, 0xbb}, {0xbc, 0x03, 0x01, 0xbb},
393 {0xbd, 0x03, 0x04, 0xbb}, {0xbe, 0x00, 0x02, 0xbb},
394 {0xbf, 0x03, 0x01, 0xbb}, {0xc0, 0x02, 0x04, 0xbb},
395 {0xc1, 0x00, 0x04, 0xbb}, {0xc2, 0x02, 0x01, 0xbb},
396 {0xc3, 0x01, 0x03, 0xbb}, {0xc4, 0x00, 0x04, 0xbb},
397 {0xf0, 0x00, 0x00, 0xbb}, {0x05, 0x01, 0x13, 0xbb},
398 {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb},
399 {0x08, 0x00, 0x27, 0xbb}, {0x20, 0x01, 0x03, 0xbb},
400 {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb},
401 {0x24, 0x80, 0x00, 0xbb}, {0x59, 0x00, 0xff, 0xbb},
402 {0xf0, 0x00, 0x02, 0xbb}, {0x39, 0x03, 0x0d, 0xbb},
403 {0x3a, 0x06, 0x1b, 0xbb}, {0x3b, 0x00, 0x95, 0xbb},
404 {0x3c, 0x04, 0xdb, 0xbb}, {0x57, 0x02, 0x00, 0xbb},
405 {0x58, 0x02, 0x66, 0xbb}, {0x59, 0x00, 0xff, 0xbb},
406 {0x5a, 0x01, 0x33, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb},
407 {0x5d, 0x16, 0x11, 0xbb}, {0x64, 0x5e, 0x1c, 0xbb},
408 {0xf0, 0x00, 0x02, 0xbb}, {0x2f, 0xd1, 0x00, 0xbb},
409 {0x5b, 0x00, 0x01, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
410 {0x36, 0x68, 0x10, 0xbb}, {0x00, 0x00, 0x30, 0xdd},
411 {0x37, 0x82, 0x00, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc},
412 {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc},
413 {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc},
414 {0xb6, 0x03, 0x05, 0xcc}, {0xb6, 0x02, 0x00, 0xcc},
415 {0xb6, 0x05, 0x04, 0xcc}, {0xb6, 0x04, 0x00, 0xcc},
416 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x29, 0xcc},
417 {0xb6, 0x18, 0x0a, 0xcc}, {0xb6, 0x17, 0x00, 0xcc},
418 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
419 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x26, 0xcc},
420 {0xbf, 0xc1, 0x02, 0xcc}, {0xbf, 0xcc, 0x04, 0xcc},
421 {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc},
422 {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc},
423 {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc},
424 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc},
425 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
426 {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
427 {}
428};
429static const __u8 mi1320_initQVGA_data[][4] = {
430 {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
431 {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
432 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
433 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
434 {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x01, 0xcc},
435 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
436 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc},
437 {0xb3, 0x35, 0xc8, 0xcc}, {0xb3, 0x02, 0x00, 0xcc},
438 {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
439 {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
440 {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc},
441 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
442 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
443 {0xb3, 0x00, 0x65, 0xcc}, {0xb8, 0x00, 0x00, 0xcc},
444 {0xbc, 0x00, 0xd0, 0xcc}, {0xbc, 0x01, 0x01, 0xcc},
445 {0xf0, 0x00, 0x00, 0xbb}, {0x0d, 0x00, 0x09, 0xbb},
446 {0x00, 0x01, 0x00, 0xdd}, {0x0d, 0x00, 0x08, 0xbb},
447 {0xf0, 0x00, 0x00, 0xbb}, {0x02, 0x00, 0x64, 0xbb},
448 {0x05, 0x01, 0x78, 0xbb}, {0x06, 0x00, 0x11, 0xbb},
449 {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb},
450 {0x20, 0x01, 0x00, 0xbb}, {0x21, 0x80, 0x00, 0xbb},
451 {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb},
452 {0x59, 0x00, 0xff, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
453 {0x9d, 0x3c, 0xa0, 0xbb}, {0x47, 0x30, 0x30, 0xbb},
454 {0xf0, 0x00, 0x00, 0xbb}, {0x0a, 0x80, 0x11, 0xbb},
455 {0x35, 0x00, 0x22, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
456 {0x9d, 0xc5, 0x05, 0xbb}, {0xdc, 0x0f, 0xfc, 0xbb},
457 {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0x74, 0x0e, 0xbb},
458 {0x80, 0x00, 0x06, 0xbb}, {0x81, 0x04, 0x00, 0xbb},
459 {0x82, 0x01, 0x02, 0xbb}, {0x83, 0x03, 0x02, 0xbb},
460 {0x84, 0x05, 0x00, 0xbb}, {0x85, 0x01, 0x00, 0xbb},
461 {0x86, 0x03, 0x02, 0xbb}, {0x87, 0x05, 0x00, 0xbb},
462 {0x88, 0x01, 0x00, 0xbb}, {0x89, 0x02, 0x02, 0xbb},
463 {0x8a, 0xfd, 0x04, 0xbb}, {0x8b, 0xfc, 0xfd, 0xbb},
464 {0x8c, 0xff, 0xfd, 0xbb}, {0x8d, 0x00, 0x00, 0xbb},
465 {0x8e, 0xfe, 0x05, 0xbb}, {0x8f, 0xfc, 0xfd, 0xbb},
466 {0x90, 0xfe, 0xfd, 0xbb}, {0x91, 0x00, 0x00, 0xbb},
467 {0x92, 0xfe, 0x03, 0xbb}, {0x93, 0xfd, 0xfe, 0xbb},
468 {0x94, 0xff, 0xfd, 0xbb}, {0x95, 0x00, 0x00, 0xbb},
469 {0xb6, 0x07, 0x05, 0xbb}, {0xb7, 0x13, 0x06, 0xbb},
470 {0xb8, 0x08, 0x06, 0xbb}, {0xb9, 0x14, 0x08, 0xbb},
471 {0xba, 0x06, 0x05, 0xbb}, {0xbb, 0x13, 0x06, 0xbb},
472 {0xbc, 0x03, 0x01, 0xbb}, {0xbd, 0x03, 0x04, 0xbb},
473 {0xbe, 0x00, 0x02, 0xbb}, {0xbf, 0x03, 0x01, 0xbb},
474 {0xc0, 0x02, 0x04, 0xbb}, {0xc1, 0x00, 0x04, 0xbb},
475 {0xc2, 0x02, 0x01, 0xbb}, {0xc3, 0x01, 0x03, 0xbb},
476 {0xc4, 0x00, 0x04, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
477 {0xc8, 0x00, 0x00, 0xbb}, {0x2e, 0x00, 0x00, 0xbb},
478 {0x2e, 0x0c, 0x5b, 0xbb}, {0x2f, 0xd1, 0x00, 0xbb},
479 {0x39, 0x03, 0xca, 0xbb}, {0x3a, 0x06, 0x80, 0xbb},
480 {0x3b, 0x01, 0x52, 0xbb}, {0x3c, 0x05, 0x40, 0xbb},
481 {0x57, 0x01, 0x9c, 0xbb}, {0x58, 0x01, 0xee, 0xbb},
482 {0x59, 0x00, 0xf0, 0xbb}, {0x5a, 0x01, 0x20, 0xbb},
483 {0x5c, 0x1d, 0x17, 0xbb}, {0x5d, 0x22, 0x1c, 0xbb},
484 {0x64, 0x1e, 0x1c, 0xbb}, {0x5b, 0x00, 0x01, 0xbb},
485 {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x68, 0x10, 0xbb},
486 {0x00, 0x00, 0x30, 0xdd}, {0x37, 0x81, 0x00, 0xbb},
487 {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc},
488 {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc},
489 {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc},
490 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc},
491 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
492 {0xbf, 0xc0, 0x26, 0xcc}, {0xbf, 0xc1, 0x02, 0xcc},
493 {0xbf, 0xcc, 0x04, 0xcc}, {0xb3, 0x5c, 0x01, 0xcc},
494 {0xb3, 0x01, 0x41, 0xcc},
495 {}
496};
497
498static const __u8 po3130_gamma[17] = {
499 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
500 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
501};
502static const __u8 po3130_matrix[9] = {
503 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
504};
505
506static const __u8 po3130_initVGA_data[][4] = {
507 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
508 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
509 {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc},
510 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
511 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
512 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x03, 0x1a, 0xcc},
513 {0xb3, 0x04, 0x15, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
514 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
515 {0xb3, 0x23, 0xe8, 0xcc}, {0xb8, 0x08, 0xe8, 0xcc},
516 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
517 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
518 {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0xf6, 0xcc},
519 {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x71, 0xcc},
520 {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc},
521 {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
522 {0xb8, 0x2c, 0x50, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
523 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
524 {0xb8, 0x30, 0x50, 0xcc}, {0xb8, 0x31, 0xf8, 0xcc},
525 {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc},
526 {0xb8, 0x34, 0x50, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
527 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
528 {0x00, 0x1e, 0xc6, 0xaa}, {0x00, 0x20, 0x44, 0xaa},
529 {0x00, 0xad, 0x02, 0xaa}, {0x00, 0xae, 0x2c, 0xaa},
530 {0x00, 0x12, 0x08, 0xaa}, {0x00, 0x17, 0x41, 0xaa},
531 {0x00, 0x19, 0x41, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
532 {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x36, 0xc0, 0xaa},
533 {0x00, 0x37, 0xc8, 0xaa}, {0x00, 0x3b, 0x36, 0xaa},
534 {0x00, 0x4b, 0xfe, 0xaa}, {0x00, 0x51, 0x1c, 0xaa},
535 {0x00, 0x52, 0x01, 0xaa}, {0x00, 0x55, 0x0a, 0xaa},
536 {0x00, 0x59, 0x02, 0xaa}, {0x00, 0x5a, 0x04, 0xaa},
537 {0x00, 0x5c, 0x10, 0xaa}, {0x00, 0x5d, 0x10, 0xaa},
538 {0x00, 0x5e, 0x10, 0xaa}, {0x00, 0x5f, 0x10, 0xaa},
539 {0x00, 0x61, 0x00, 0xaa}, {0x00, 0x62, 0x18, 0xaa},
540 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x70, 0x68, 0xaa},
541 {0x00, 0x80, 0x71, 0xaa}, {0x00, 0x81, 0x08, 0xaa},
542 {0x00, 0x82, 0x00, 0xaa}, {0x00, 0x83, 0x55, 0xaa},
543 {0x00, 0x84, 0x06, 0xaa}, {0x00, 0x85, 0x06, 0xaa},
544 {0x00, 0x86, 0x13, 0xaa}, {0x00, 0x87, 0x18, 0xaa},
545 {0x00, 0xaa, 0x3f, 0xaa}, {0x00, 0xab, 0x44, 0xaa},
546 {0x00, 0xb0, 0x68, 0xaa}, {0x00, 0xb5, 0x10, 0xaa},
547 {0x00, 0xb8, 0x20, 0xaa}, {0x00, 0xb9, 0xa0, 0xaa},
548 {0x00, 0xbc, 0x04, 0xaa}, {0x00, 0x8b, 0x40, 0xaa},
549 {0x00, 0x8c, 0x91, 0xaa}, {0x00, 0x8d, 0x8f, 0xaa},
550 {0x00, 0x8e, 0x91, 0xaa}, {0x00, 0x8f, 0x43, 0xaa},
551 {0x00, 0x90, 0x92, 0xaa}, {0x00, 0x91, 0x89, 0xaa},
552 {0x00, 0x92, 0x9d, 0xaa}, {0x00, 0x93, 0x46, 0xaa},
553 {0x00, 0xd6, 0x22, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
554 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
555 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
556 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
557 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
558 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
559 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0xd6, 0x62, 0xaa},
560 {0x00, 0x73, 0x00, 0xaa}, {0x00, 0x74, 0x10, 0xaa},
561 {0x00, 0x75, 0x20, 0xaa}, {0x00, 0x76, 0x2b, 0xaa},
562 {0x00, 0x77, 0x36, 0xaa}, {0x00, 0x78, 0x49, 0xaa},
563 {0x00, 0x79, 0x5a, 0xaa}, {0x00, 0x7a, 0x7f, 0xaa},
564 {0x00, 0x7b, 0x9b, 0xaa}, {0x00, 0x7c, 0xba, 0xaa},
565 {0x00, 0x7d, 0xd4, 0xaa}, {0x00, 0x7e, 0xea, 0xaa},
566 {0x00, 0xd6, 0xa2, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
567 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
568 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
569 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
570 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
571 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
572 {0x00, 0x7e, 0xea, 0xaa},
573 {0x00, 0x4c, 0x07, 0xaa},
574 {0x00, 0x4b, 0xe0, 0xaa}, {0x00, 0x4e, 0x77, 0xaa},
575 {0x00, 0x59, 0x02, 0xaa}, {0x00, 0x4d, 0x0a, 0xaa},
576/* {0x00, 0xd1, 0x00, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
577 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc}, */
578 {0x00, 0xd1, 0x3c, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
579 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
580 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
581 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
582 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
583 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
584 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
585 {0xb9, 0x08, 0x3c, 0xcc}, {0x00, 0x05, 0x00, 0xaa},
586 {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
587 {}
588};
589static const __u8 po3130_rundata[][4] = {
590 {0x00, 0x47, 0x45, 0xaa}, {0x00, 0x48, 0x9b, 0xaa},
591 {0x00, 0x49, 0x3a, 0xaa}, {0x00, 0x4a, 0x01, 0xaa},
592 {0x00, 0x44, 0x40, 0xaa},
593/* {0x00, 0xd5, 0x7c, 0xaa}, */
594 {0x00, 0xad, 0x04, 0xaa}, {0x00, 0xae, 0x00, 0xaa},
595 {0x00, 0xb0, 0x78, 0xaa}, {0x00, 0x98, 0x02, 0xaa},
596 {0x00, 0x94, 0x25, 0xaa}, {0x00, 0x95, 0x25, 0xaa},
597 {0x00, 0x59, 0x68, 0xaa}, {0x00, 0x44, 0x20, 0xaa},
598 {0x00, 0x17, 0x50, 0xaa}, {0x00, 0x19, 0x50, 0xaa},
599 {0x00, 0xd1, 0x3c, 0xaa}, {0x00, 0xd1, 0x3c, 0xaa},
600 {0x00, 0x1e, 0x06, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
601 {}
602};
603
604static const __u8 po3130_initQVGA_data[][4] = {
605 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
606 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x09, 0xcc},
607 {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc},
608 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
609 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
610 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x03, 0x1a, 0xcc},
611 {0xb3, 0x04, 0x15, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
612 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
613 {0xb3, 0x23, 0xe0, 0xcc}, {0xb8, 0x08, 0xe0, 0xcc},
614 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
615 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
616 {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0xf6, 0xcc},
617 {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc},
618 {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc},
619 {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
620 {0xb8, 0x2c, 0x50, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
621 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
622 {0xb8, 0x30, 0x50, 0xcc}, {0xb8, 0x31, 0xf8, 0xcc},
623 {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc},
624 {0xb8, 0x34, 0x50, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
625 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
626 {0x00, 0x1e, 0xc6, 0xaa}, {0x00, 0x20, 0x44, 0xaa},
627 {0x00, 0xad, 0x02, 0xaa}, {0x00, 0xae, 0x2c, 0xaa},
628 {0x00, 0x12, 0x08, 0xaa}, {0x00, 0x17, 0x41, 0xaa},
629 {0x00, 0x19, 0x41, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
630 {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x36, 0xc0, 0xaa},
631 {0x00, 0x37, 0xc8, 0xaa}, {0x00, 0x3b, 0x36, 0xaa},
632 {0x00, 0x4b, 0xfe, 0xaa}, {0x00, 0x51, 0x1c, 0xaa},
633 {0x00, 0x52, 0x01, 0xaa}, {0x00, 0x55, 0x0a, 0xaa},
634 {0x00, 0x59, 0x6f, 0xaa}, {0x00, 0x5a, 0x04, 0xaa},
635 {0x00, 0x5c, 0x10, 0xaa}, {0x00, 0x5d, 0x10, 0xaa},
636 {0x00, 0x5e, 0x10, 0xaa}, {0x00, 0x5f, 0x10, 0xaa},
637 {0x00, 0x61, 0x00, 0xaa}, {0x00, 0x62, 0x18, 0xaa},
638 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x70, 0x68, 0xaa},
639 {0x00, 0x80, 0x71, 0xaa}, {0x00, 0x81, 0x08, 0xaa},
640 {0x00, 0x82, 0x00, 0xaa}, {0x00, 0x83, 0x55, 0xaa},
641 {0x00, 0x84, 0x06, 0xaa}, {0x00, 0x85, 0x06, 0xaa},
642 {0x00, 0x86, 0x13, 0xaa}, {0x00, 0x87, 0x18, 0xaa},
643 {0x00, 0xaa, 0x3f, 0xaa}, {0x00, 0xab, 0x44, 0xaa},
644 {0x00, 0xb0, 0x68, 0xaa}, {0x00, 0xb5, 0x10, 0xaa},
645 {0x00, 0xb8, 0x20, 0xaa}, {0x00, 0xb9, 0xa0, 0xaa},
646 {0x00, 0xbc, 0x04, 0xaa}, {0x00, 0x8b, 0x40, 0xaa},
647 {0x00, 0x8c, 0x91, 0xaa}, {0x00, 0x8d, 0x8f, 0xaa},
648 {0x00, 0x8e, 0x91, 0xaa}, {0x00, 0x8f, 0x43, 0xaa},
649 {0x00, 0x90, 0x92, 0xaa}, {0x00, 0x91, 0x89, 0xaa},
650 {0x00, 0x92, 0x9d, 0xaa}, {0x00, 0x93, 0x46, 0xaa},
651 {0x00, 0xd6, 0x22, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
652 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
653 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
654 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
655 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
656 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
657 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0xd6, 0x62, 0xaa},
658 {0x00, 0x73, 0x00, 0xaa}, {0x00, 0x74, 0x10, 0xaa},
659 {0x00, 0x75, 0x20, 0xaa}, {0x00, 0x76, 0x2b, 0xaa},
660 {0x00, 0x77, 0x36, 0xaa}, {0x00, 0x78, 0x49, 0xaa},
661 {0x00, 0x79, 0x5a, 0xaa}, {0x00, 0x7a, 0x7f, 0xaa},
662 {0x00, 0x7b, 0x9b, 0xaa}, {0x00, 0x7c, 0xba, 0xaa},
663 {0x00, 0x7d, 0xd4, 0xaa}, {0x00, 0x7e, 0xea, 0xaa},
664 {0x00, 0xd6, 0xa2, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
665 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
666 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
667 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
668 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
669 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
670 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0x4c, 0x07, 0xaa},
671 {0x00, 0x4b, 0xe0, 0xaa}, {0x00, 0x4e, 0x77, 0xaa},
672 {0x00, 0x59, 0x66, 0xaa}, {0x00, 0x4d, 0x0a, 0xaa},
673 {0x00, 0xd1, 0x00, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
674 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
675 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
676 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
677 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
678 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
679 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
680 {0xb9, 0x08, 0x3c, 0xcc}, {0xbc, 0x02, 0x18, 0xcc},
681 {0xbc, 0x03, 0x50, 0xcc}, {0xbc, 0x04, 0x18, 0xcc},
682 {0xbc, 0x05, 0x00, 0xcc}, {0xbc, 0x06, 0x00, 0xcc},
683 {0xbc, 0x08, 0x30, 0xcc}, {0xbc, 0x09, 0x40, 0xcc},
684 {0xbc, 0x0a, 0x10, 0xcc}, {0xbc, 0x0b, 0x00, 0xcc},
685 {0xbc, 0x0c, 0x00, 0xcc}, {0x00, 0x05, 0x00, 0xaa},
686 {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
687 {}
688};
689
690static const __u8 hv7131r_gamma[17] = {
691/* 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
692 * 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff */
693 0x04, 0x1a, 0x36, 0x55, 0x6f, 0x87, 0x9d, 0xb0, 0xc1,
694 0xcf, 0xda, 0xe4, 0xec, 0xf3, 0xf8, 0xfd, 0xff
695};
696static const __u8 hv7131r_matrix[9] = {
697 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
698};
699static const __u8 hv7131r_initVGA_data[][4] = {
700 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
701 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
702 {0xb3, 0x00, 0x24, 0xcc},
703 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
704 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
705 {0xb3, 0x06, 0x01, 0xcc},
706 {0xb3, 0x01, 0x45, 0xcc}, {0xb3, 0x03, 0x0b, 0xcc},
707 {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
708 {0xb3, 0x21, 0x00, 0xcc},
709 {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc},
710 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
711 {0xb3, 0x16, 0x02, 0xcc},
712 {0xb3, 0x17, 0x7f, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
713 {0xb3, 0x35, 0x91, 0xcc}, {0xb3, 0x00, 0x27, 0xcc},
714 {0xbc, 0x00, 0x73, 0xcc},
715 {0xb8, 0x00, 0x23, 0xcc}, {0x00, 0x01, 0x0c, 0xaa},
716 {0x00, 0x14, 0x01, 0xaa}, {0x00, 0x15, 0xe6, 0xaa},
717 {0x00, 0x16, 0x02, 0xaa},
718 {0x00, 0x17, 0x86, 0xaa}, {0x00, 0x23, 0x00, 0xaa},
719 {0x00, 0x25, 0x09, 0xaa}, {0x00, 0x26, 0x27, 0xaa},
720 {0x00, 0x27, 0xc0, 0xaa},
721 {0xb8, 0x2c, 0x60, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
722 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
723 {0xb8, 0x30, 0x50, 0xcc},
724 {0xb8, 0x31, 0xf8, 0xcc}, {0xb8, 0x32, 0xf8, 0xcc},
725 {0xb8, 0x33, 0xf8, 0xcc}, {0xb8, 0x34, 0x65, 0xcc},
726 {0xb8, 0x35, 0x00, 0xcc},
727 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
728 {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x01, 0x7d, 0xcc},
729 {0xb8, 0x81, 0x09, 0xcc},
730 {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0xfe, 0x00, 0xcc},
731 {0xb8, 0xff, 0x28, 0xcc}, {0xb9, 0x00, 0x28, 0xcc},
732 {0xb9, 0x01, 0x28, 0xcc},
733 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
734 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
735 {0xb9, 0x06, 0x3c, 0xcc},
736 {0xb9, 0x07, 0x3c, 0xcc}, {0xb9, 0x08, 0x3c, 0xcc},
737 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
738 {0x00, 0x30, 0x18, 0xaa},
739 {}
740};
741
742static const __u8 hv7131r_initQVGA_data[][4] = {
743 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
744 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
745 {0xb3, 0x00, 0x24, 0xcc},
746 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
747 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
748 {0xb3, 0x06, 0x01, 0xcc},
749 {0xb3, 0x03, 0x0b, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
750 {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
751 {0xb3, 0x22, 0x01, 0xcc},
752 {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc},
753 {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x02, 0xcc},
754 {0xb3, 0x17, 0x7f, 0xcc},
755 {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0x91, 0xcc},
756 {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc},
757 {0xb8, 0x00, 0x21, 0xcc},
758 {0x00, 0x01, 0x0c, 0xaa}, {0x00, 0x14, 0x01, 0xaa},
759 {0x00, 0x15, 0xe6, 0xaa}, {0x00, 0x16, 0x02, 0xaa},
760 {0x00, 0x17, 0x86, 0xaa},
761 {0x00, 0x23, 0x00, 0xaa}, {0x00, 0x25, 0x01, 0xaa},
762 {0x00, 0x26, 0xd4, 0xaa}, {0x00, 0x27, 0xc0, 0xaa},
763 {0xbc, 0x02, 0x08, 0xcc},
764 {0xbc, 0x03, 0x70, 0xcc}, {0xbc, 0x04, 0x08, 0xcc},
765 {0xbc, 0x05, 0x00, 0xcc}, {0xbc, 0x06, 0x00, 0xcc},
766 {0xbc, 0x08, 0x3c, 0xcc},
767 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x04, 0xcc},
768 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
769 {0xb8, 0xfe, 0x02, 0xcc},
770 {0xb8, 0xff, 0x07, 0xcc}, {0xb9, 0x00, 0x14, 0xcc},
771 {0xb9, 0x01, 0x14, 0xcc}, {0xb9, 0x02, 0x14, 0xcc},
772 {0xb9, 0x03, 0x00, 0xcc},
773 {0xb9, 0x04, 0x02, 0xcc}, {0xb9, 0x05, 0x05, 0xcc},
774 {0xb9, 0x06, 0x0f, 0xcc}, {0xb9, 0x07, 0x0f, 0xcc},
775 {0xb9, 0x08, 0x0f, 0xcc},
776 {0xb8, 0x2c, 0x60, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
777 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
778 {0xb8, 0x30, 0x50, 0xcc},
779 {0xb8, 0x31, 0xf8, 0xcc}, {0xb8, 0x32, 0xf8, 0xcc},
780 {0xb8, 0x33, 0xf8, 0xcc},
781 {0xb8, 0x34, 0x65, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
782 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
783 {0xb8, 0x27, 0x20, 0xcc},
784 {0xb8, 0x01, 0x7d, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
785 {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0xfe, 0x00, 0xcc},
786 {0xb8, 0xff, 0x28, 0xcc},
787 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
788 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
789 {0xb9, 0x04, 0x00, 0xcc},
790 {0xb9, 0x05, 0x3c, 0xcc}, {0xb9, 0x06, 0x3c, 0xcc},
791 {0xb9, 0x07, 0x3c, 0xcc}, {0xb9, 0x08, 0x3c, 0xcc},
792 {0xb8, 0x8e, 0x00, 0xcc},
793 {0xb8, 0x8f, 0xff, 0xcc}, {0x00, 0x30, 0x18, 0xaa},
794 {}
795};
796
797static const __u8 ov7660_gamma[17] = {
798 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
799 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
800};
801static const __u8 ov7660_matrix[9] = {
802 0x5a, 0xf0, 0xf6, 0xf3, 0x57, 0xf6, 0xf3, 0xef, 0x62
803};
804static const __u8 ov7660_initVGA_data[][4] = {
805 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
806 {0x00, 0x00, 0x50, 0xdd},
807 {0xb0, 0x03, 0x01, 0xcc},
808 {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
809 {0xb3, 0x05, 0x01, 0xcc},
810 {0xb3, 0x06, 0x03, 0xcc},
811 {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
812 {0xb3, 0x05, 0x00, 0xcc},
813 {0xb3, 0x06, 0x01, 0xcc},
814 {0xb3, 0x15, 0x00, 0xcc},/* 0xb315 <-0 href startl */
815 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
816 {0xb3, 0x21, 0x00, 0xcc},
817 {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc},
818 {0xb3, 0x1f, 0x02, 0xcc},
819 {0xb3, 0x34, 0x01, 0xcc},
820 {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
821 {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
822 {0xb8, 0x01, 0x7d, 0xcc},
823 {0xbc, 0x00, 0x73, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
824 {0xb8, 0x27, 0x20, 0xcc},
825 {0xb8, 0x8f, 0x50, 0xcc},
826 {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa},
827 {0x00, 0x12, 0x80, 0xaa},
828 {0x00, 0x12, 0x05, 0xaa},
829 {0x00, 0x1e, 0x01, 0xaa},
830 {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
831 {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
832 {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa},
833 {0x00, 0x13, 0xa7, 0xaa},
834 {0x00, 0x40, 0xc1, 0xaa}, {0x00, 0x35, 0x00, 0xaa},
835 {0x00, 0x36, 0x00, 0xaa},
836 {0x00, 0x3c, 0x68, 0xaa}, {0x00, 0x1b, 0x05, 0xaa},
837 {0x00, 0x39, 0x43, 0xaa},
838 {0x00, 0x8d, 0xcf, 0xaa},
839 {0x00, 0x8b, 0xcc, 0xaa}, {0x00, 0x8c, 0xcc, 0xaa},
840 {0x00, 0x0f, 0x62, 0xaa},
841 {0x00, 0x35, 0x84, 0xaa},
842 {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */
843 {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
844 {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
845 {0x00, 0x9e, 0x40, 0xaa}, {0xb8, 0x8f, 0x50, 0xcc},
846 {0x00, 0x01, 0x80, 0xaa},
847 {0x00, 0x02, 0x80, 0xaa},
848 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
849 {0xb9, 0x00, 0x28, 0xcc},
850 {0xb9, 0x01, 0x28, 0xcc}, {0xb9, 0x02, 0x28, 0xcc},
851 {0xb9, 0x03, 0x00, 0xcc},
852 {0xb9, 0x04, 0x00, 0xcc},
853 {0xb9, 0x05, 0x3c, 0xcc}, {0xb9, 0x06, 0x3c, 0xcc},
854 {0xb9, 0x07, 0x3c, 0xcc},
855 {0xb9, 0x08, 0x3c, 0xcc},
856
857 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
858
859 {0x00, 0x29, 0x3c, 0xaa}, {0xb3, 0x01, 0x45, 0xcc},
860 {}
861};
862static const __u8 ov7660_initQVGA_data[][4] = {
863 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
864 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
865 {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
866 {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x03, 0xcc},
867 {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
868 {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x01, 0xcc},
869 {0xb3, 0x15, 0x00, 0xcc},/* 0xb315 <-0 href startl */
870 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
871 {0xb3, 0x21, 0x00, 0xcc},
872 {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc},
873 {0xb3, 0x1f, 0x02, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
874 {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
875 {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
876 {0xb8, 0x01, 0x7d, 0xcc},
877/* sizer */
878 {0xbc, 0x00, 0xd3, 0xcc},
879 {0xb8, 0x81, 0x09, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
880 {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x8f, 0x50, 0xcc},
881 {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa},
882 {0x00, 0x12, 0x80, 0xaa}, {0x00, 0x12, 0x05, 0xaa},
883 {0x00, 0x1e, 0x01, 0xaa},
884 {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
885 {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
886 {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa},
887 {0x00, 0x13, 0xa7, 0xaa},
888 {0x00, 0x40, 0xc1, 0xaa}, {0x00, 0x35, 0x00, 0xaa},
889 {0x00, 0x36, 0x00, 0xaa},
890 {0x00, 0x3c, 0x68, 0xaa}, {0x00, 0x1b, 0x05, 0xaa},
891 {0x00, 0x39, 0x43, 0xaa}, {0x00, 0x8d, 0xcf, 0xaa},
892 {0x00, 0x8b, 0xcc, 0xaa}, {0x00, 0x8c, 0xcc, 0xaa},
893 {0x00, 0x0f, 0x62, 0xaa}, {0x00, 0x35, 0x84, 0xaa},
894 {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */
895 {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
896 {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
897 {0x00, 0x9e, 0x40, 0xaa}, {0xb8, 0x8f, 0x50, 0xcc},
898 {0x00, 0x01, 0x80, 0xaa},
899 {0x00, 0x02, 0x80, 0xaa},
900/* sizer filters */
901 {0xbc, 0x02, 0x08, 0xcc},
902 {0xbc, 0x03, 0x70, 0xcc},
903 {0xb8, 0x35, 0x00, 0xcc},
904 {0xb8, 0x36, 0x00, 0xcc},
905 {0xb8, 0x37, 0x00, 0xcc},
906 {0xbc, 0x04, 0x08, 0xcc},
907 {0xbc, 0x05, 0x00, 0xcc},
908 {0xbc, 0x06, 0x00, 0xcc},
909 {0xbc, 0x08, 0x3c, 0xcc},
910 {0xbc, 0x09, 0x40, 0xcc},
911 {0xbc, 0x0a, 0x04, 0xcc},
912 {0xbc, 0x0b, 0x00, 0xcc},
913 {0xbc, 0x0c, 0x00, 0xcc},
914/* */
915 {0xb8, 0xfe, 0x00, 0xcc},
916 {0xb8, 0xff, 0x28, 0xcc},
917/* */
918 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
919 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
920 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
921 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
922 {0xb9, 0x08, 0x3c, 0xcc},
923/* */
924 {0xb8, 0x8e, 0x00, 0xcc},
925 {0xb8, 0x8f, 0xff, 0xcc}, /* ff */
926 {0x00, 0x29, 0x3c, 0xaa},
927 {0xb3, 0x01, 0x45, 0xcc}, /* 45 */
928 {}
929};
930
931static const __u8 ov7660_50HZ[][4] = {
932 {0x00, 0x3b, 0x08, 0xaa},
933 {0x00, 0x9d, 0x40, 0xaa},
934 {0x00, 0x13, 0xa7, 0xaa},
935 {}
936};
937
938static const __u8 ov7660_60HZ[][4] = {
939 {0x00, 0x3b, 0x00, 0xaa},
940 {0x00, 0x9e, 0x40, 0xaa},
941 {0x00, 0x13, 0xa7, 0xaa},
942 {}
943};
944
945static const __u8 ov7660_NoFliker[][4] = {
946 {0x00, 0x13, 0x87, 0xaa},
947 {}
948};
949
950static const __u8 ov7670_initVGA_JPG[][4] = {
951 {0xb3, 0x01, 0x05, 0xcc},
952 {0x00, 0x00, 0x30, 0xdd}, {0xb0, 0x03, 0x19, 0xcc},
953 {0x00, 0x00, 0x10, 0xdd},
954 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd},
955 {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc},
956 {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
957 {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc},
958 {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc},
959 {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc},
960 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
961 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
962 {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
963 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
964 {0xb3, 0x23, 0xe0, 0xcc}, {0xbc, 0x00, 0x41, 0xcc},
965 {0xbc, 0x01, 0x01, 0xcc}, {0x00, 0x12, 0x80, 0xaa},
966 {0x00, 0x00, 0x20, 0xdd}, {0x00, 0x12, 0x00, 0xaa},
967 {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x6b, 0x0a, 0xaa},
968 {0x00, 0x3a, 0x04, 0xaa}, {0x00, 0x40, 0xc0, 0xaa},
969 {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x7a, 0x29, 0xaa},
970 {0x00, 0x7b, 0x0e, 0xaa}, {0x00, 0x7c, 0x1a, 0xaa},
971 {0x00, 0x7d, 0x31, 0xaa}, {0x00, 0x7e, 0x53, 0xaa},
972 {0x00, 0x7f, 0x60, 0xaa}, {0x00, 0x80, 0x6b, 0xaa},
973 {0x00, 0x81, 0x73, 0xaa}, {0x00, 0x82, 0x7b, 0xaa},
974 {0x00, 0x83, 0x82, 0xaa}, {0x00, 0x84, 0x89, 0xaa},
975 {0x00, 0x85, 0x96, 0xaa}, {0x00, 0x86, 0xa1, 0xaa},
976 {0x00, 0x87, 0xb7, 0xaa}, {0x00, 0x88, 0xcc, 0xaa},
977 {0x00, 0x89, 0xe1, 0xaa}, {0x00, 0x13, 0xe0, 0xaa},
978 {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x10, 0x00, 0xaa},
979 {0x00, 0x0d, 0x40, 0xaa}, {0x00, 0x14, 0x28, 0xaa},
980 {0x00, 0xa5, 0x05, 0xaa}, {0x00, 0xab, 0x07, 0xaa},
981 {0x00, 0x24, 0x95, 0xaa}, {0x00, 0x25, 0x33, 0xaa},
982 {0x00, 0x26, 0xe3, 0xaa}, {0x00, 0x9f, 0x88, 0xaa},
983 {0x00, 0xa0, 0x78, 0xaa}, {0x00, 0x55, 0x90, 0xaa},
984 {0x00, 0xa1, 0x03, 0xaa}, {0x00, 0xa6, 0xe0, 0xaa},
985 {0x00, 0xa7, 0xd8, 0xaa}, {0x00, 0xa8, 0xf0, 0xaa},
986 {0x00, 0xa9, 0x90, 0xaa}, {0x00, 0xaa, 0x14, 0xaa},
987 {0x00, 0x13, 0xe5, 0xaa}, {0x00, 0x0e, 0x61, 0xaa},
988 {0x00, 0x0f, 0x4b, 0xaa}, {0x00, 0x16, 0x02, 0xaa},
989 {0x00, 0x1e, 0x07, 0xaa}, {0x00, 0x21, 0x02, 0xaa},
990 {0x00, 0x22, 0x91, 0xaa}, {0x00, 0x29, 0x07, 0xaa},
991 {0x00, 0x33, 0x0b, 0xaa}, {0x00, 0x35, 0x0b, 0xaa},
992 {0x00, 0x37, 0x1d, 0xaa}, {0x00, 0x38, 0x71, 0xaa},
993 {0x00, 0x39, 0x2a, 0xaa}, {0x00, 0x3c, 0x78, 0xaa},
994 {0x00, 0x4d, 0x40, 0xaa}, {0x00, 0x4e, 0x20, 0xaa},
995 {0x00, 0x74, 0x19, 0xaa}, {0x00, 0x8d, 0x4f, 0xaa},
996 {0x00, 0x8e, 0x00, 0xaa}, {0x00, 0x8f, 0x00, 0xaa},
997 {0x00, 0x90, 0x00, 0xaa}, {0x00, 0x91, 0x00, 0xaa},
998 {0x00, 0x96, 0x00, 0xaa}, {0x00, 0x9a, 0x80, 0xaa},
999 {0x00, 0xb0, 0x84, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa},
1000 {0x00, 0xb2, 0x0e, 0xaa}, {0x00, 0xb3, 0x82, 0xaa},
1001 {0x00, 0xb8, 0x0a, 0xaa}, {0x00, 0x43, 0x14, 0xaa},
1002 {0x00, 0x44, 0xf0, 0xaa}, {0x00, 0x45, 0x45, 0xaa},
1003 {0x00, 0x46, 0x63, 0xaa}, {0x00, 0x47, 0x2d, 0xaa},
1004 {0x00, 0x48, 0x46, 0xaa}, {0x00, 0x59, 0x88, 0xaa},
1005 {0x00, 0x5a, 0xa0, 0xaa}, {0x00, 0x5b, 0xc6, 0xaa},
1006 {0x00, 0x5c, 0x7d, 0xaa}, {0x00, 0x5d, 0x5f, 0xaa},
1007 {0x00, 0x5e, 0x19, 0xaa}, {0x00, 0x6c, 0x0a, 0xaa},
1008 {0x00, 0x6d, 0x55, 0xaa}, {0x00, 0x6e, 0x11, 0xaa},
1009 {0x00, 0x6f, 0x9e, 0xaa}, {0x00, 0x69, 0x00, 0xaa},
1010 {0x00, 0x6a, 0x40, 0xaa}, {0x00, 0x01, 0x40, 0xaa},
1011 {0x00, 0x02, 0x40, 0xaa}, {0x00, 0x13, 0xe7, 0xaa},
1012 {0x00, 0x5f, 0xf0, 0xaa}, {0x00, 0x60, 0xf0, 0xaa},
1013 {0x00, 0x61, 0xf0, 0xaa}, {0x00, 0x27, 0xa0, 0xaa},
1014 {0x00, 0x28, 0x80, 0xaa}, {0x00, 0x2c, 0x90, 0xaa},
1015 {0x00, 0x4f, 0x66, 0xaa}, {0x00, 0x50, 0x66, 0xaa},
1016 {0x00, 0x51, 0x00, 0xaa}, {0x00, 0x52, 0x22, 0xaa},
1017 {0x00, 0x53, 0x5e, 0xaa}, {0x00, 0x54, 0x80, 0xaa},
1018 {0x00, 0x58, 0x9e, 0xaa}, {0x00, 0x41, 0x08, 0xaa},
1019 {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x85, 0xaa},
1020 {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa},
1021 {0x00, 0x77, 0x0a, 0xaa}, {0x00, 0x3d, 0x88, 0xaa},
1022 {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa},
1023 {0x00, 0x41, 0x38, 0xaa}, {0x00, 0x62, 0x30, 0xaa},
1024 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x64, 0x08, 0xaa},
1025 {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x0b, 0xaa},
1026 {0x00, 0x65, 0x00, 0xaa}, {0x00, 0x66, 0x05, 0xaa},
1027 {0x00, 0x56, 0x50, 0xaa}, {0x00, 0x34, 0x11, 0xaa},
1028 {0x00, 0xa4, 0x88, 0xaa}, {0x00, 0x96, 0x00, 0xaa},
1029 {0x00, 0x97, 0x30, 0xaa}, {0x00, 0x98, 0x20, 0xaa},
1030 {0x00, 0x99, 0x30, 0xaa}, {0x00, 0x9a, 0x84, 0xaa},
1031 {0x00, 0x9b, 0x29, 0xaa}, {0x00, 0x9c, 0x03, 0xaa},
1032 {0x00, 0x78, 0x04, 0xaa}, {0x00, 0x79, 0x01, 0xaa},
1033 {0x00, 0xc8, 0xf0, 0xaa}, {0x00, 0x79, 0x0f, 0xaa},
1034 {0x00, 0xc8, 0x00, 0xaa}, {0x00, 0x79, 0x10, 0xaa},
1035 {0x00, 0xc8, 0x7e, 0xaa}, {0x00, 0x79, 0x0a, 0xaa},
1036 {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x0b, 0xaa},
1037 {0x00, 0xc8, 0x01, 0xaa}, {0x00, 0x79, 0x0c, 0xaa},
1038 {0x00, 0xc8, 0x0f, 0xaa}, {0x00, 0x79, 0x0d, 0xaa},
1039 {0x00, 0xc8, 0x20, 0xaa}, {0x00, 0x79, 0x09, 0xaa},
1040 {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x02, 0xaa},
1041 {0x00, 0xc8, 0xc0, 0xaa}, {0x00, 0x79, 0x03, 0xaa},
1042 {0x00, 0xc8, 0x40, 0xaa}, {0x00, 0x79, 0x05, 0xaa},
1043 {0x00, 0xc8, 0x30, 0xaa}, {0x00, 0x79, 0x26, 0xaa},
1044 {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x3a, 0x04, 0xaa},
1045 {0x00, 0x12, 0x00, 0xaa}, {0x00, 0x40, 0xc0, 0xaa},
1046 {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x17, 0x14, 0xaa},
1047 {0x00, 0x18, 0x02, 0xaa}, {0x00, 0x32, 0x92, 0xaa},
1048 {0x00, 0x19, 0x02, 0xaa}, {0x00, 0x1a, 0x7a, 0xaa},
1049 {0x00, 0x03, 0x0a, 0xaa}, {0x00, 0x0c, 0x00, 0xaa},
1050 {0x00, 0x3e, 0x00, 0xaa}, {0x00, 0x70, 0x3a, 0xaa},
1051 {0x00, 0x71, 0x35, 0xaa}, {0x00, 0x72, 0x11, 0xaa},
1052 {0x00, 0x73, 0xf0, 0xaa}, {0x00, 0xa2, 0x02, 0xaa},
1053 {0x00, 0xb1, 0x00, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa},
1054 {0x00, 0x1e, 0x37, 0xaa}, {0x00, 0xaa, 0x14, 0xaa},
1055 {0x00, 0x24, 0x80, 0xaa}, {0x00, 0x25, 0x74, 0xaa},
1056 {0x00, 0x26, 0xd3, 0xaa}, {0x00, 0x0d, 0x00, 0xaa},
1057 {0x00, 0x14, 0x18, 0xaa}, {0x00, 0x9d, 0x99, 0xaa},
1058 {0x00, 0x9e, 0x7f, 0xaa}, {0x00, 0x64, 0x08, 0xaa},
1059 {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x06, 0xaa},
1060 {0x00, 0x66, 0x05, 0xaa}, {0x00, 0x41, 0x08, 0xaa},
1061 {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x07, 0xaa},
1062 {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa},
1063 {0x00, 0x77, 0x00, 0xaa}, {0x00, 0x3d, 0xc2, 0xaa},
1064 {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa},
1065 {0x00, 0x41, 0x38, 0xaa}, {0xb6, 0x00, 0x00, 0xcc},
1066 {0xb6, 0x03, 0x02, 0xcc}, {0xb6, 0x02, 0x80, 0xcc},
1067 {0xb6, 0x05, 0x01, 0xcc}, {0xb6, 0x04, 0xe0, 0xcc},
1068 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x13, 0xcc},
1069 {0xb6, 0x18, 0x02, 0xcc}, {0xb6, 0x17, 0x58, 0xcc},
1070 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
1071 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc},
1072 {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc},
1073 {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x45, 0xcc},
1074 {0x00, 0x77, 0x05, 0xaa},
1075 {},
1076};
1077
1078static const __u8 ov7670_initQVGA_JPG[][4] = {
1079 {0xb3, 0x01, 0x05, 0xcc}, {0x00, 0x00, 0x30, 0xdd},
1080 {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x10, 0xdd},
1081 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd},
1082 {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc},
1083 {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
1084 {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc},
1085 {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc},
1086 {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc},
1087 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
1088 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1089 {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
1090 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
1091 {0xb3, 0x23, 0xe0, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc},
1092 {0xbc, 0x01, 0x01, 0xcc}, {0x00, 0x12, 0x80, 0xaa},
1093 {0x00, 0x00, 0x20, 0xdd}, {0x00, 0x12, 0x00, 0xaa},
1094 {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x6b, 0x0a, 0xaa},
1095 {0x00, 0x3a, 0x04, 0xaa}, {0x00, 0x40, 0xc0, 0xaa},
1096 {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x7a, 0x29, 0xaa},
1097 {0x00, 0x7b, 0x0e, 0xaa}, {0x00, 0x7c, 0x1a, 0xaa},
1098 {0x00, 0x7d, 0x31, 0xaa}, {0x00, 0x7e, 0x53, 0xaa},
1099 {0x00, 0x7f, 0x60, 0xaa}, {0x00, 0x80, 0x6b, 0xaa},
1100 {0x00, 0x81, 0x73, 0xaa}, {0x00, 0x82, 0x7b, 0xaa},
1101 {0x00, 0x83, 0x82, 0xaa}, {0x00, 0x84, 0x89, 0xaa},
1102 {0x00, 0x85, 0x96, 0xaa}, {0x00, 0x86, 0xa1, 0xaa},
1103 {0x00, 0x87, 0xb7, 0xaa}, {0x00, 0x88, 0xcc, 0xaa},
1104 {0x00, 0x89, 0xe1, 0xaa}, {0x00, 0x13, 0xe0, 0xaa},
1105 {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x10, 0x00, 0xaa},
1106 {0x00, 0x0d, 0x40, 0xaa}, {0x00, 0x14, 0x28, 0xaa},
1107 {0x00, 0xa5, 0x05, 0xaa}, {0x00, 0xab, 0x07, 0xaa},
1108 {0x00, 0x24, 0x95, 0xaa}, {0x00, 0x25, 0x33, 0xaa},
1109 {0x00, 0x26, 0xe3, 0xaa}, {0x00, 0x9f, 0x88, 0xaa},
1110 {0x00, 0xa0, 0x78, 0xaa}, {0x00, 0x55, 0x90, 0xaa},
1111 {0x00, 0xa1, 0x03, 0xaa}, {0x00, 0xa6, 0xe0, 0xaa},
1112 {0x00, 0xa7, 0xd8, 0xaa}, {0x00, 0xa8, 0xf0, 0xaa},
1113 {0x00, 0xa9, 0x90, 0xaa}, {0x00, 0xaa, 0x14, 0xaa},
1114 {0x00, 0x13, 0xe5, 0xaa}, {0x00, 0x0e, 0x61, 0xaa},
1115 {0x00, 0x0f, 0x4b, 0xaa}, {0x00, 0x16, 0x02, 0xaa},
1116 {0x00, 0x1e, 0x07, 0xaa}, {0x00, 0x21, 0x02, 0xaa},
1117 {0x00, 0x22, 0x91, 0xaa}, {0x00, 0x29, 0x07, 0xaa},
1118 {0x00, 0x33, 0x0b, 0xaa}, {0x00, 0x35, 0x0b, 0xaa},
1119 {0x00, 0x37, 0x1d, 0xaa}, {0x00, 0x38, 0x71, 0xaa},
1120 {0x00, 0x39, 0x2a, 0xaa}, {0x00, 0x3c, 0x78, 0xaa},
1121 {0x00, 0x4d, 0x40, 0xaa}, {0x00, 0x4e, 0x20, 0xaa},
1122 {0x00, 0x74, 0x19, 0xaa}, {0x00, 0x8d, 0x4f, 0xaa},
1123 {0x00, 0x8e, 0x00, 0xaa}, {0x00, 0x8f, 0x00, 0xaa},
1124 {0x00, 0x90, 0x00, 0xaa}, {0x00, 0x91, 0x00, 0xaa},
1125 {0x00, 0x96, 0x00, 0xaa}, {0x00, 0x9a, 0x80, 0xaa},
1126 {0x00, 0xb0, 0x84, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa},
1127 {0x00, 0xb2, 0x0e, 0xaa}, {0x00, 0xb3, 0x82, 0xaa},
1128 {0x00, 0xb8, 0x0a, 0xaa}, {0x00, 0x43, 0x14, 0xaa},
1129 {0x00, 0x44, 0xf0, 0xaa}, {0x00, 0x45, 0x45, 0xaa},
1130 {0x00, 0x46, 0x63, 0xaa}, {0x00, 0x47, 0x2d, 0xaa},
1131 {0x00, 0x48, 0x46, 0xaa}, {0x00, 0x59, 0x88, 0xaa},
1132 {0x00, 0x5a, 0xa0, 0xaa}, {0x00, 0x5b, 0xc6, 0xaa},
1133 {0x00, 0x5c, 0x7d, 0xaa}, {0x00, 0x5d, 0x5f, 0xaa},
1134 {0x00, 0x5e, 0x19, 0xaa}, {0x00, 0x6c, 0x0a, 0xaa},
1135 {0x00, 0x6d, 0x55, 0xaa}, {0x00, 0x6e, 0x11, 0xaa},
1136 {0x00, 0x6f, 0x9e, 0xaa}, {0x00, 0x69, 0x00, 0xaa},
1137 {0x00, 0x6a, 0x40, 0xaa}, {0x00, 0x01, 0x40, 0xaa},
1138 {0x00, 0x02, 0x40, 0xaa}, {0x00, 0x13, 0xe7, 0xaa},
1139 {0x00, 0x5f, 0xf0, 0xaa}, {0x00, 0x60, 0xf0, 0xaa},
1140 {0x00, 0x61, 0xf0, 0xaa}, {0x00, 0x27, 0xa0, 0xaa},
1141 {0x00, 0x28, 0x80, 0xaa}, {0x00, 0x2c, 0x90, 0xaa},
1142 {0x00, 0x4f, 0x66, 0xaa}, {0x00, 0x50, 0x66, 0xaa},
1143 {0x00, 0x51, 0x00, 0xaa}, {0x00, 0x52, 0x22, 0xaa},
1144 {0x00, 0x53, 0x5e, 0xaa}, {0x00, 0x54, 0x80, 0xaa},
1145 {0x00, 0x58, 0x9e, 0xaa}, {0x00, 0x41, 0x08, 0xaa},
1146 {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x85, 0xaa},
1147 {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa},
1148 {0x00, 0x77, 0x0a, 0xaa}, {0x00, 0x3d, 0x88, 0xaa},
1149 {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa},
1150 {0x00, 0x41, 0x38, 0xaa}, {0x00, 0x62, 0x30, 0xaa},
1151 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x64, 0x08, 0xaa},
1152 {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x0b, 0xaa},
1153 {0x00, 0x65, 0x00, 0xaa}, {0x00, 0x66, 0x05, 0xaa},
1154 {0x00, 0x56, 0x50, 0xaa}, {0x00, 0x34, 0x11, 0xaa},
1155 {0x00, 0xa4, 0x88, 0xaa}, {0x00, 0x96, 0x00, 0xaa},
1156 {0x00, 0x97, 0x30, 0xaa}, {0x00, 0x98, 0x20, 0xaa},
1157 {0x00, 0x99, 0x30, 0xaa}, {0x00, 0x9a, 0x84, 0xaa},
1158 {0x00, 0x9b, 0x29, 0xaa}, {0x00, 0x9c, 0x03, 0xaa},
1159 {0x00, 0x78, 0x04, 0xaa}, {0x00, 0x79, 0x01, 0xaa},
1160 {0x00, 0xc8, 0xf0, 0xaa}, {0x00, 0x79, 0x0f, 0xaa},
1161 {0x00, 0xc8, 0x00, 0xaa}, {0x00, 0x79, 0x10, 0xaa},
1162 {0x00, 0xc8, 0x7e, 0xaa}, {0x00, 0x79, 0x0a, 0xaa},
1163 {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x0b, 0xaa},
1164 {0x00, 0xc8, 0x01, 0xaa}, {0x00, 0x79, 0x0c, 0xaa},
1165 {0x00, 0xc8, 0x0f, 0xaa}, {0x00, 0x79, 0x0d, 0xaa},
1166 {0x00, 0xc8, 0x20, 0xaa}, {0x00, 0x79, 0x09, 0xaa},
1167 {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x02, 0xaa},
1168 {0x00, 0xc8, 0xc0, 0xaa}, {0x00, 0x79, 0x03, 0xaa},
1169 {0x00, 0xc8, 0x40, 0xaa}, {0x00, 0x79, 0x05, 0xaa},
1170 {0x00, 0xc8, 0x30, 0xaa}, {0x00, 0x79, 0x26, 0xaa},
1171 {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x3a, 0x04, 0xaa},
1172 {0x00, 0x12, 0x00, 0xaa}, {0x00, 0x40, 0xc0, 0xaa},
1173 {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x17, 0x14, 0xaa},
1174 {0x00, 0x18, 0x02, 0xaa}, {0x00, 0x32, 0x92, 0xaa},
1175 {0x00, 0x19, 0x02, 0xaa}, {0x00, 0x1a, 0x7a, 0xaa},
1176 {0x00, 0x03, 0x0a, 0xaa}, {0x00, 0x0c, 0x00, 0xaa},
1177 {0x00, 0x3e, 0x00, 0xaa}, {0x00, 0x70, 0x3a, 0xaa},
1178 {0x00, 0x71, 0x35, 0xaa}, {0x00, 0x72, 0x11, 0xaa},
1179 {0x00, 0x73, 0xf0, 0xaa}, {0x00, 0xa2, 0x02, 0xaa},
1180 {0x00, 0xb1, 0x00, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa},
1181 {0x00, 0x1e, 0x37, 0xaa}, {0x00, 0xaa, 0x14, 0xaa},
1182 {0x00, 0x24, 0x80, 0xaa}, {0x00, 0x25, 0x74, 0xaa},
1183 {0x00, 0x26, 0xd3, 0xaa}, {0x00, 0x0d, 0x00, 0xaa},
1184 {0x00, 0x14, 0x18, 0xaa}, {0x00, 0x9d, 0x99, 0xaa},
1185 {0x00, 0x9e, 0x7f, 0xaa}, {0x00, 0x64, 0x08, 0xaa},
1186 {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x06, 0xaa},
1187 {0x00, 0x66, 0x05, 0xaa}, {0x00, 0x41, 0x08, 0xaa},
1188 {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x07, 0xaa},
1189 {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa},
1190 {0x00, 0x77, 0x00, 0xaa}, {0x00, 0x3d, 0xc2, 0xaa},
1191 {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa},
1192 {0x00, 0x41, 0x38, 0xaa}, {0xb6, 0x00, 0x00, 0xcc},
1193 {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc},
1194 {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc},
1195 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x21, 0xcc},
1196 {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc},
1197 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
1198 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc},
1199 {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc},
1200 {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc},
1201 {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc},
1202 {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc},
1203 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc},
1204 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
1205 {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x45, 0xcc},
1206 {0x00, 0x77, 0x05, 0xaa },
1207 {},
1208};
1209
1210struct sensor_info {
1211 int sensorId;
1212 __u8 I2cAdd;
1213 __u8 IdAdd;
1214 __u16 VpId;
1215 __u8 m1;
1216 __u8 m2;
1217 __u8 op;
1218 };
1219
1220static const struct sensor_info sensor_info_data[] = {
1221/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */
1222 {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
1223 {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
1224 {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01},
1225 {SENSOR_MI1320, 0x80 | 0xc8, 0x00, 0x148c, 0x64, 0x65, 0x01},
1226 {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05},
1227 {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
1228};
1229
1230/* read 'len' bytes in gspca_dev->usb_buf */
1231static void reg_r(struct gspca_dev *gspca_dev,
1232 __u16 req,
1233 __u16 index,
1234 __u16 len)
1235{
1236 usb_control_msg(gspca_dev->dev,
1237 usb_rcvctrlpipe(gspca_dev->dev, 0),
1238 req,
1239 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1240 1, /* value */
1241 index, gspca_dev->usb_buf, len,
1242 500);
1243}
1244
1245static void reg_w(struct usb_device *dev,
1246 __u16 req,
1247 __u16 value,
1248 __u16 index)
1249{
1250 usb_control_msg(dev,
1251 usb_sndctrlpipe(dev, 0),
1252 req,
1253 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1254 value, index, NULL, 0,
1255 500);
1256}
1257
1258static void read_sensor_register(struct gspca_dev *gspca_dev,
1259 __u16 address, __u16 *value)
1260{
1261 struct usb_device *dev = gspca_dev->dev;
1262 __u8 ldata, mdata, hdata;
1263 int retry = 50;
1264
1265 *value = 0;
1266
1267 reg_r(gspca_dev, 0xa1, 0xb33f, 1);
1268 /*PDEBUG(D_PROBE, " I2c Bus Busy Wait 0x%02X ", tmpvalue); */
1269 if (!(gspca_dev->usb_buf[0] & 0x02)) {
1270 PDEBUG(D_ERR, "I2c Bus Busy Wait %d",
1271 gspca_dev->usb_buf[0] & 0x02);
1272 return;
1273 }
1274 reg_w(dev, 0xa0, address, 0xb33a);
1275 reg_w(dev, 0xa0, 0x02, 0xb339);
1276
1277 reg_r(gspca_dev, 0xa1, 0xb33b, 1);
1278 while (retry-- && gspca_dev->usb_buf[0]) {
1279 reg_r(gspca_dev, 0xa1, 0xb33b, 1);
1280/* PDEBUG(D_PROBE, "Read again 0xb33b %d", tmpvalue); */
1281 msleep(1);
1282 }
1283 reg_r(gspca_dev, 0xa1, 0xb33e, 1);
1284 hdata = gspca_dev->usb_buf[0];
1285 reg_r(gspca_dev, 0xa1, 0xb33d, 1);
1286 mdata = gspca_dev->usb_buf[0];
1287 reg_r(gspca_dev, 0xa1, 0xb33c, 1);
1288 ldata = gspca_dev->usb_buf[0];
1289 PDEBUG(D_PROBE, "Read Sensor h (0x%02X) m (0x%02X) l (0x%02X)",
1290 hdata, mdata, ldata);
1291 reg_r(gspca_dev, 0xa1, 0xb334, 1);
1292 if (gspca_dev->usb_buf[0] == 0x02)
1293 *value = (ldata << 8) + mdata;
1294 else
1295 *value = ldata;
1296}
1297
1298static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
1299{
1300 struct usb_device *dev = gspca_dev->dev;
1301 int i;
1302 __u16 value;
1303 const struct sensor_info *ptsensor_info;
1304
1305 reg_r(gspca_dev, 0xa1, 0xbfcf, 1);
1306 PDEBUG(D_PROBE, "check sensor header %d", gspca_dev->usb_buf[0]);
1307 for (i = 0; i < ARRAY_SIZE(sensor_info_data); i++) {
1308 ptsensor_info = &sensor_info_data[i];
1309 reg_w(dev, 0xa0, 0x02, 0xb334);
1310 reg_w(dev, 0xa0, ptsensor_info->m1, 0xb300);
1311 reg_w(dev, 0xa0, ptsensor_info->m2, 0xb300);
1312 reg_w(dev, 0xa0, 0x01, 0xb308);
1313 reg_w(dev, 0xa0, 0x0c, 0xb309);
1314 reg_w(dev, 0xa0, ptsensor_info->I2cAdd, 0xb335);
1315/* PDEBUG(D_PROBE,
1316 "check sensor VC032X -> %d Add -> ox%02X!",
1317 i, ptsensor_info->I2cAdd); */
1318 reg_w(dev, 0xa0, ptsensor_info->op, 0xb301);
1319 read_sensor_register(gspca_dev, ptsensor_info->IdAdd, &value);
1320 if (value == ptsensor_info->VpId) {
1321/* PDEBUG(D_PROBE, "find sensor VC032X -> ox%04X!",
1322 ptsensor_info->VpId); */
1323 return ptsensor_info->sensorId;
1324 }
1325 }
1326 return -1;
1327}
1328
1329static __u8 i2c_write(struct gspca_dev *gspca_dev,
1330 __u8 reg, const __u8 *val, __u8 size)
1331{
1332 struct usb_device *dev = gspca_dev->dev;
1333
1334 if (size > 3 || size < 1)
1335 return -EINVAL;
1336 reg_r(gspca_dev, 0xa1, 0xb33f, 1);
1337 reg_w(dev, 0xa0, size, 0xb334);
1338 reg_w(dev, 0xa0, reg, 0xb33a);
1339 switch (size) {
1340 case 1:
1341 reg_w(dev, 0xa0, val[0], 0xb336);
1342 break;
1343 case 2:
1344 reg_w(dev, 0xa0, val[0], 0xb336);
1345 reg_w(dev, 0xa0, val[1], 0xb337);
1346 break;
1347 case 3:
1348 reg_w(dev, 0xa0, val[0], 0xb336);
1349 reg_w(dev, 0xa0, val[1], 0xb337);
1350 reg_w(dev, 0xa0, val[2], 0xb338);
1351 break;
1352 default:
1353 reg_w(dev, 0xa0, 0x01, 0xb334);
1354 return -EINVAL;
1355 }
1356 reg_w(dev, 0xa0, 0x01, 0xb339);
1357 reg_r(gspca_dev, 0xa1, 0xb33b, 1);
1358 return gspca_dev->usb_buf[0] == 0;
1359}
1360
1361static void put_tab_to_reg(struct gspca_dev *gspca_dev,
1362 const __u8 *tab, __u8 tabsize, __u16 addr)
1363{
1364 int j;
1365 __u16 ad = addr;
1366
1367 for (j = 0; j < tabsize; j++)
1368 reg_w(gspca_dev->dev, 0xa0, tab[j], ad++);
1369}
1370
1371static void usb_exchange(struct gspca_dev *gspca_dev,
1372 const __u8 data[][4])
1373{
1374 struct usb_device *dev = gspca_dev->dev;
1375 int i = 0;
1376
1377 for (;;) {
1378 switch (data[i][3]) {
1379 default:
1380 return;
1381 case 0xcc: /* normal write */
1382 reg_w(dev, 0xa0, data[i][2],
1383 ((data[i][0])<<8) | data[i][1]);
1384 break;
1385 case 0xaa: /* i2c op */
1386 i2c_write(gspca_dev, data[i][1], &data[i][2], 1);
1387 break;
1388 case 0xbb: /* i2c op */
1389 i2c_write(gspca_dev, data[i][0], &data[i][1], 2);
1390 break;
1391 case 0xdd:
1392 msleep(data[i][2] + 10);
1393 break;
1394 }
1395 i++;
1396 }
1397 /*not reached*/
1398}
1399
1400/*
1401 "GammaT"=hex:04,17,31,4f,6a,83,99,ad,bf,ce,da,e5,ee,f5,fb,ff,ff
1402 "MatrixT"=hex:60,f9,e5,e7,50,05,f3,e6,66
1403 */
1404
1405static void vc0321_reset(struct gspca_dev *gspca_dev)
1406{
1407 reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb04d);
1408 reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb301);
1409 msleep(100);
1410 reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb003);
1411 msleep(100);
1412}
1413
1414/* this function is called at probe time */
1415static int sd_config(struct gspca_dev *gspca_dev,
1416 const struct usb_device_id *id)
1417{
1418 struct sd *sd = (struct sd *) gspca_dev;
1419 struct usb_device *dev = gspca_dev->dev;
1420 struct cam *cam;
1421 int sensor;
1422 __u16 product;
1423
1424 product = id->idProduct;
1425 sd->bridge = BRIDGE_VC0321;
1426 switch (id->idVendor) {
1427 case 0x0ac8: /* Vimicro z-star */
1428 switch (product) {
1429 case 0x0323:
1430 sd->bridge = BRIDGE_VC0323;
1431 break;
1432 }
1433 break;
1434 case 0x17ef: /* Lenovo */
1435/* switch (product) { */
1436/* case 0x4802: * Lenovo MI1310_SOC */
1437 sd->bridge = BRIDGE_VC0323;
1438/* break; */
1439/* } */
1440 break;
1441 }
1442
1443 cam = &gspca_dev->cam;
1444 cam->dev_name = (char *) id->driver_info;
1445 cam->epaddr = 0x02;
1446 if (sd->bridge == BRIDGE_VC0321) {
1447 cam->cam_mode = vc0321_mode;
1448 cam->nmodes = ARRAY_SIZE(vc0321_mode);
1449 } else {
1450 cam->cam_mode = vc0323_mode;
1451 cam->nmodes = ARRAY_SIZE(vc0323_mode);
1452 }
1453
1454 vc0321_reset(gspca_dev);
1455 sensor = vc032x_probe_sensor(gspca_dev);
1456 switch (sensor) {
1457 case -1:
1458 PDEBUG(D_PROBE, "Unknown sensor...");
1459 return -EINVAL;
1460 case SENSOR_HV7131R:
1461 PDEBUG(D_PROBE, "Find Sensor HV7131R");
1462 sd->sensor = SENSOR_HV7131R;
1463 break;
1464 case SENSOR_MI1310_SOC:
1465 PDEBUG(D_PROBE, "Find Sensor MI1310_SOC");
1466 sd->sensor = SENSOR_MI1310_SOC;
1467 break;
1468 case SENSOR_MI1320:
1469 PDEBUG(D_PROBE, "Find Sensor MI1320");
1470 sd->sensor = SENSOR_MI1320;
1471 break;
1472 case SENSOR_OV7660:
1473 PDEBUG(D_PROBE, "Find Sensor OV7660");
1474 sd->sensor = SENSOR_OV7660;
1475 break;
1476 case SENSOR_OV7670:
1477 PDEBUG(D_PROBE, "Find Sensor OV7670");
1478 sd->sensor = SENSOR_OV7670;
1479 break;
1480 case SENSOR_PO3130NC:
1481 PDEBUG(D_PROBE, "Find Sensor PO3130NC");
1482 sd->sensor = SENSOR_PO3130NC;
1483 break;
1484 }
1485
1486 sd->qindex = 7;
1487 sd->autogain = AUTOGAIN_DEF;
1488 sd->lightfreq = FREQ_DEF;
1489
1490 if (sd->bridge == BRIDGE_VC0321) {
1491 reg_r(gspca_dev, 0x8a, 0, 3);
1492 reg_w(dev, 0x87, 0x00, 0x0f0f);
1493
1494 reg_r(gspca_dev, 0x8b, 0, 3);
1495 reg_w(dev, 0x88, 0x00, 0x0202);
1496 }
1497 return 0;
1498}
1499
1500/* this function is called at open time */
1501static int sd_open(struct gspca_dev *gspca_dev)
1502{
1503 return 0;
1504}
1505
1506static void setquality(struct gspca_dev *gspca_dev)
1507{
1508}
1509
1510static void setautogain(struct gspca_dev *gspca_dev)
1511{
1512}
1513
1514static void setlightfreq(struct gspca_dev *gspca_dev)
1515{
1516 struct sd *sd = (struct sd *) gspca_dev;
1517 static const __u8 (*ov7660_freq_tb[3])[4] =
1518 {ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ};
1519
1520 if (sd->sensor != SENSOR_OV7660)
1521 return;
1522 usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]);
1523}
1524
1525static void sd_start(struct gspca_dev *gspca_dev)
1526{
1527 struct sd *sd = (struct sd *) gspca_dev;
1528 const __u8 *GammaT = NULL;
1529 const __u8 *MatrixT = NULL;
1530 int mode;
1531
1532 /* Assume start use the good resolution from gspca_dev->mode */
1533 if (sd->bridge == BRIDGE_VC0321) {
1534 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfec);
1535 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfed);
1536 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfee);
1537 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfef);
1538 }
1539
1540 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1541 switch (sd->sensor) {
1542 case SENSOR_HV7131R:
1543 GammaT = hv7131r_gamma;
1544 MatrixT = hv7131r_matrix;
1545 if (mode) {
1546 /* 320x240 */
1547 usb_exchange(gspca_dev, hv7131r_initQVGA_data);
1548 } else {
1549 /* 640x480 */
1550 usb_exchange(gspca_dev, hv7131r_initVGA_data);
1551 }
1552 break;
1553 case SENSOR_OV7660:
1554 GammaT = ov7660_gamma;
1555 MatrixT = ov7660_matrix;
1556 if (mode) {
1557 /* 320x240 */
1558 usb_exchange(gspca_dev, ov7660_initQVGA_data);
1559 } else {
1560 /* 640x480 */
1561 usb_exchange(gspca_dev, ov7660_initVGA_data);
1562 }
1563 break;
1564 case SENSOR_OV7670:
1565 /*GammaT = ov7660_gamma; */
1566 /*MatrixT = ov7660_matrix; */
1567 if (mode) {
1568 /* 320x240 */
1569 usb_exchange(gspca_dev, ov7670_initQVGA_JPG);
1570 } else {
1571 /* 640x480 */
1572 usb_exchange(gspca_dev, ov7670_initVGA_JPG);
1573 }
1574 break;
1575 case SENSOR_MI1310_SOC:
1576 if (mode) {
1577 /* 320x240 */
1578 usb_exchange(gspca_dev, mi1310_socinitQVGA_JPG);
1579 } else {
1580 /* 640x480 */
1581 usb_exchange(gspca_dev, mi1310_socinitVGA_JPG);
1582 }
1583 break;
1584 case SENSOR_MI1320:
1585 GammaT = mi1320_gamma;
1586 MatrixT = mi1320_matrix;
1587 if (mode) {
1588 /* 320x240 */
1589 usb_exchange(gspca_dev, mi1320_initQVGA_data);
1590 } else {
1591 /* 640x480 */
1592 usb_exchange(gspca_dev, mi1320_initVGA_data);
1593 }
1594 break;
1595 case SENSOR_PO3130NC:
1596 GammaT = po3130_gamma;
1597 MatrixT = po3130_matrix;
1598 if (mode) {
1599 /* 320x240 */
1600 usb_exchange(gspca_dev, po3130_initQVGA_data);
1601 } else {
1602 /* 640x480 */
1603 usb_exchange(gspca_dev, po3130_initVGA_data);
1604 }
1605 usb_exchange(gspca_dev, po3130_rundata);
1606 break;
1607 default:
1608 PDEBUG(D_PROBE, "Damned !! no sensor found Bye");
1609 return;
1610 }
1611 if (GammaT && MatrixT) {
1612 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a);
1613 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b);
1614 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c);
1615 put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c);
1616
1617 /* Seem SHARPNESS */
1618 /*
1619 reg_w(gspca_dev->dev, 0xa0, 0x80, 0xb80a);
1620 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb80b);
1621 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb80e);
1622 */
1623 /* all 0x40 ??? do nothing
1624 reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb822);
1625 reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb823);
1626 reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb824);
1627 */
1628 /* Only works for HV7131R ??
1629 reg_r (gspca_dev, 0xa1, 0xb881, 1);
1630 reg_w(gspca_dev->dev, 0xa0, 0xfe01, 0xb881);
1631 reg_w(gspca_dev->dev, 0xa0, 0x79, 0xb801);
1632 */
1633 /* only hv7131r et ov7660
1634 reg_w(gspca_dev->dev, 0xa0, 0x20, 0xb827);
1635 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb826); * ISP_GAIN 80
1636 reg_w(gspca_dev->dev, 0xa0, 0x23, 0xb800); * ISP CTRL_BAS
1637 */
1638 /* set the led on 0x0892 0x0896 */
1639 reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff);
1640 msleep(100);
1641 setquality(gspca_dev);
1642 setautogain(gspca_dev);
1643 setlightfreq(gspca_dev);
1644 }
1645}
1646
1647static void sd_stopN(struct gspca_dev *gspca_dev)
1648{
1649 struct usb_device *dev = gspca_dev->dev;
1650
1651 reg_w(dev, 0x89, 0xffff, 0xffff);
1652 reg_w(dev, 0xa0, 0x01, 0xb301);
1653 reg_w(dev, 0xa0, 0x09, 0xb003);
1654}
1655
1656static void sd_stop0(struct gspca_dev *gspca_dev)
1657{
1658 struct usb_device *dev = gspca_dev->dev;
1659
1660 reg_w(dev, 0x89, 0xffff, 0xffff);
1661}
1662
1663/* this function is called at close time */
1664static void sd_close(struct gspca_dev *gspca_dev)
1665{
1666/* struct usb_device *dev = gspca_dev->dev;
1667 __u8 buffread;
1668
1669 reg_w(dev, 0x89, 0xffff, 0xffff);
1670 reg_w(dev, 0xa0, 0x01, 0xb301);
1671 reg_w(dev, 0xa0, 0x09, 0xb303);
1672 reg_w(dev, 0x89, 0xffff, 0xffff);
1673*/
1674}
1675
1676static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1677 struct gspca_frame *frame, /* target */
1678 __u8 *data, /* isoc packet */
1679 int len) /* iso pkt length */
1680{
1681 struct sd *sd = (struct sd *) gspca_dev;
1682
1683 if (data[0] == 0xff && data[1] == 0xd8) {
1684 PDEBUG(D_PACK,
1685 "vc032x header packet found len %d", len);
1686 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1687 data, 0);
1688 if (sd->bridge == BRIDGE_VC0321) {
1689#define VCHDRSZ 46
1690 data += VCHDRSZ;
1691 len -= VCHDRSZ;
1692#undef VCHDRSZ
1693 }
1694 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1695 data, len);
1696 return;
1697 }
1698 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1699}
1700
1701static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1702{
1703 struct sd *sd = (struct sd *) gspca_dev;
1704
1705 sd->autogain = val;
1706 if (gspca_dev->streaming)
1707 setautogain(gspca_dev);
1708 return 0;
1709}
1710
1711static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1712{
1713 struct sd *sd = (struct sd *) gspca_dev;
1714
1715 *val = sd->autogain;
1716 return 0;
1717}
1718
1719static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1720{
1721 struct sd *sd = (struct sd *) gspca_dev;
1722
1723 sd->lightfreq = val;
1724 if (gspca_dev->streaming)
1725 setlightfreq(gspca_dev);
1726 return 0;
1727}
1728
1729static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1730{
1731 struct sd *sd = (struct sd *) gspca_dev;
1732
1733 *val = sd->lightfreq;
1734 return 0;
1735}
1736
1737static int sd_querymenu(struct gspca_dev *gspca_dev,
1738 struct v4l2_querymenu *menu)
1739{
1740 switch (menu->id) {
1741 case V4L2_CID_POWER_LINE_FREQUENCY:
1742 switch (menu->index) {
1743 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1744 strcpy((char *) menu->name, "NoFliker");
1745 return 0;
1746 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1747 strcpy((char *) menu->name, "50 Hz");
1748 return 0;
1749 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1750 strcpy((char *) menu->name, "60 Hz");
1751 return 0;
1752 }
1753 break;
1754 }
1755 return -EINVAL;
1756}
1757
1758/* sub-driver description */
1759static const struct sd_desc sd_desc = {
1760 .name = MODULE_NAME,
1761 .ctrls = sd_ctrls,
1762 .nctrls = ARRAY_SIZE(sd_ctrls),
1763 .config = sd_config,
1764 .open = sd_open,
1765 .start = sd_start,
1766 .stopN = sd_stopN,
1767 .stop0 = sd_stop0,
1768 .close = sd_close,
1769 .pkt_scan = sd_pkt_scan,
1770 .querymenu = sd_querymenu,
1771};
1772
1773/* -- module initialisation -- */
1774#define DVNM(name) .driver_info = (kernel_ulong_t) name
1775static const __devinitdata struct usb_device_id device_table[] = {
1776 {USB_DEVICE(0x046d, 0x0892), DVNM("Logitech Orbicam")},
1777 {USB_DEVICE(0x046d, 0x0896), DVNM("Logitech Orbicam")},
1778 {USB_DEVICE(0x0ac8, 0x0321), DVNM("Vimicro generic vc0321")},
1779 {USB_DEVICE(0x0ac8, 0x0323), DVNM("Vimicro Vc0323")},
1780 {USB_DEVICE(0x0ac8, 0x0328), DVNM("A4Tech PK-130MG")},
1781 {USB_DEVICE(0x0ac8, 0xc001), DVNM("Sony embedded vimicro")},
1782 {USB_DEVICE(0x0ac8, 0xc002), DVNM("Sony embedded vimicro")},
1783 {USB_DEVICE(0x17ef, 0x4802), DVNM("Lenovo Vc0323+MI1310_SOC")},
1784 {}
1785};
1786MODULE_DEVICE_TABLE(usb, device_table);
1787
1788/* -- device connect -- */
1789static int sd_probe(struct usb_interface *intf,
1790 const struct usb_device_id *id)
1791{
1792 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1793 THIS_MODULE);
1794}
1795
1796static struct usb_driver sd_driver = {
1797 .name = MODULE_NAME,
1798 .id_table = device_table,
1799 .probe = sd_probe,
1800 .disconnect = gspca_disconnect,
1801};
1802
1803/* -- module insert / remove -- */
1804static int __init sd_mod_init(void)
1805{
1806 if (usb_register(&sd_driver) < 0)
1807 return -1;
1808 PDEBUG(D_PROBE, "v%s registered", version);
1809 return 0;
1810}
1811static void __exit sd_mod_exit(void)
1812{
1813 usb_deregister(&sd_driver);
1814 PDEBUG(D_PROBE, "deregistered");
1815}
1816
1817module_init(sd_mod_init);
1818module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/zc3xx-reg.h b/drivers/media/video/gspca/zc3xx-reg.h
new file mode 100644
index 000000000000..f52e09c2cc19
--- /dev/null
+++ b/drivers/media/video/gspca/zc3xx-reg.h
@@ -0,0 +1,261 @@
1/*
2 * zc030x registers
3 *
4 * Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
5 *
6 * The register aliases used here came from this driver:
7 * http://zc0302.sourceforge.net/zc0302.php
8 *
9 * This code is placed under the terms of the GNU General Public License v2
10 */
11
12/* Define the register map */
13#define ZC3XX_R000_SYSTEMCONTROL 0x0000
14#define ZC3XX_R001_SYSTEMOPERATING 0x0001
15
16/* Picture size */
17#define ZC3XX_R002_CLOCKSELECT 0x0002
18#define ZC3XX_R003_FRAMEWIDTHHIGH 0x0003
19#define ZC3XX_R004_FRAMEWIDTHLOW 0x0004
20#define ZC3XX_R005_FRAMEHEIGHTHIGH 0x0005
21#define ZC3XX_R006_FRAMEHEIGHTLOW 0x0006
22
23/* JPEG control */
24#define ZC3XX_R008_CLOCKSETTING 0x0008
25
26/* Test mode */
27#define ZC3XX_R00B_TESTMODECONTROL 0x000b
28
29/* Frame retreiving */
30#define ZC3XX_R00C_LASTACQTIME 0x000c
31#define ZC3XX_R00D_MONITORRES 0x000d
32#define ZC3XX_R00E_TIMESTAMPHIGH 0x000e
33#define ZC3XX_R00F_TIMESTAMPLOW 0x000f
34#define ZC3XX_R018_FRAMELOST 0x0018
35#define ZC3XX_R019_AUTOADJUSTFPS 0x0019
36#define ZC3XX_R01A_LASTFRAMESTATE 0x001a
37#define ZC3XX_R025_DATACOUNTER 0x0025
38
39/* Stream and sensor specific */
40#define ZC3XX_R010_CMOSSENSORSELECT 0x0010
41#define ZC3XX_R011_VIDEOSTATUS 0x0011
42#define ZC3XX_R012_VIDEOCONTROLFUNC 0x0012
43
44/* Horizontal and vertical synchros */
45#define ZC3XX_R01D_HSYNC_0 0x001d
46#define ZC3XX_R01E_HSYNC_1 0x001e
47#define ZC3XX_R01F_HSYNC_2 0x001f
48#define ZC3XX_R020_HSYNC_3 0x0020
49
50/* Target picture size in byte */
51#define ZC3XX_R022_TARGETPICTSIZE_0 0x0022
52#define ZC3XX_R023_TARGETPICTSIZE_1 0x0023
53#define ZC3XX_R024_TARGETPICTSIZE_2 0x0024
54
55/* Audio registers */
56#define ZC3XX_R030_AUDIOADC 0x0030
57#define ZC3XX_R031_AUDIOSTREAMSTATUS 0x0031
58#define ZC3XX_R032_AUDIOSTATUS 0x0032
59
60/* Sensor interface */
61#define ZC3XX_R080_HBLANKHIGH 0x0080
62#define ZC3XX_R081_HBLANKLOW 0x0081
63#define ZC3XX_R082_RESETLEVELADDR 0x0082
64#define ZC3XX_R083_RGAINADDR 0x0083
65#define ZC3XX_R084_GGAINADDR 0x0084
66#define ZC3XX_R085_BGAINADDR 0x0085
67#define ZC3XX_R086_EXPTIMEHIGH 0x0086
68#define ZC3XX_R087_EXPTIMEMID 0x0087
69#define ZC3XX_R088_EXPTIMELOW 0x0088
70#define ZC3XX_R089_RESETBLACKHIGH 0x0089
71#define ZC3XX_R08A_RESETWHITEHIGH 0x008a
72#define ZC3XX_R08B_I2CDEVICEADDR 0x008b
73#define ZC3XX_R08C_I2CIDLEANDNACK 0x008c
74#define ZC3XX_R08D_COMPABILITYMODE 0x008d
75#define ZC3XX_R08E_COMPABILITYMODE2 0x008e
76
77/* I2C control */
78#define ZC3XX_R090_I2CCOMMAND 0x0090
79#define ZC3XX_R091_I2CSTATUS 0x0091
80#define ZC3XX_R092_I2CADDRESSSELECT 0x0092
81#define ZC3XX_R093_I2CSETVALUE 0x0093
82#define ZC3XX_R094_I2CWRITEACK 0x0094
83#define ZC3XX_R095_I2CREAD 0x0095
84#define ZC3XX_R096_I2CREADACK 0x0096
85
86/* Window inside the sensor array */
87#define ZC3XX_R097_WINYSTARTHIGH 0x0097
88#define ZC3XX_R098_WINYSTARTLOW 0x0098
89#define ZC3XX_R099_WINXSTARTHIGH 0x0099
90#define ZC3XX_R09A_WINXSTARTLOW 0x009a
91#define ZC3XX_R09B_WINHEIGHTHIGH 0x009b
92#define ZC3XX_R09C_WINHEIGHTLOW 0x009c
93#define ZC3XX_R09D_WINWIDTHHIGH 0x009d
94#define ZC3XX_R09E_WINWIDTHLOW 0x009e
95#define ZC3XX_R119_FIRSTYHIGH 0x0119
96#define ZC3XX_R11A_FIRSTYLOW 0x011a
97#define ZC3XX_R11B_FIRSTXHIGH 0x011b
98#define ZC3XX_R11C_FIRSTXLOW 0x011c
99
100/* Max sensor array size */
101#define ZC3XX_R09F_MAXXHIGH 0x009f
102#define ZC3XX_R0A0_MAXXLOW 0x00a0
103#define ZC3XX_R0A1_MAXYHIGH 0x00a1
104#define ZC3XX_R0A2_MAXYLOW 0x00a2
105#define ZC3XX_R0A3_EXPOSURETIMEHIGH 0x00a3
106#define ZC3XX_R0A4_EXPOSURETIMELOW 0x00a4
107#define ZC3XX_R0A5_EXPOSUREGAIN 0x00a5
108#define ZC3XX_R0A6_EXPOSUREBLACKLVL 0x00a6
109
110/* Other registers */
111#define ZC3XX_R100_OPERATIONMODE 0x0100
112#define ZC3XX_R101_SENSORCORRECTION 0x0101
113
114/* Gains */
115#define ZC3XX_R116_RGAIN 0x0116
116#define ZC3XX_R117_GGAIN 0x0117
117#define ZC3XX_R118_BGAIN 0x0118
118#define ZC3XX_R11D_GLOBALGAIN 0x011d
119#define ZC3XX_R1A8_DIGITALGAIN 0x01a8
120#define ZC3XX_R1A9_DIGITALLIMITDIFF 0x01a9
121#define ZC3XX_R1AA_DIGITALGAINSTEP 0x01aa
122
123/* Auto correction */
124#define ZC3XX_R180_AUTOCORRECTENABLE 0x0180
125#define ZC3XX_R181_WINXSTART 0x0181
126#define ZC3XX_R182_WINXWIDTH 0x0182
127#define ZC3XX_R183_WINXCENTER 0x0183
128#define ZC3XX_R184_WINYSTART 0x0184
129#define ZC3XX_R185_WINYWIDTH 0x0185
130#define ZC3XX_R186_WINYCENTER 0x0186
131
132/* Gain range */
133#define ZC3XX_R187_MAXGAIN 0x0187
134#define ZC3XX_R188_MINGAIN 0x0188
135
136/* Auto exposure and white balance */
137#define ZC3XX_R189_AWBSTATUS 0x0189
138#define ZC3XX_R18A_AWBFREEZE 0x018a
139#define ZC3XX_R18B_AESTATUS 0x018b
140#define ZC3XX_R18C_AEFREEZE 0x018c
141#define ZC3XX_R18F_AEUNFREEZE 0x018f
142#define ZC3XX_R190_EXPOSURELIMITHIGH 0x0190
143#define ZC3XX_R191_EXPOSURELIMITMID 0x0191
144#define ZC3XX_R192_EXPOSURELIMITLOW 0x0192
145#define ZC3XX_R195_ANTIFLICKERHIGH 0x0195
146#define ZC3XX_R196_ANTIFLICKERMID 0x0196
147#define ZC3XX_R197_ANTIFLICKERLOW 0x0197
148
149/* What is this ? */
150#define ZC3XX_R18D_YTARGET 0x018d
151#define ZC3XX_R18E_RESETLVL 0x018e
152
153/* Color */
154#define ZC3XX_R1A0_REDMEANAFTERAGC 0x01a0
155#define ZC3XX_R1A1_GREENMEANAFTERAGC 0x01a1
156#define ZC3XX_R1A2_BLUEMEANAFTERAGC 0x01a2
157#define ZC3XX_R1A3_REDMEANAFTERAWB 0x01a3
158#define ZC3XX_R1A4_GREENMEANAFTERAWB 0x01a4
159#define ZC3XX_R1A5_BLUEMEANAFTERAWB 0x01a5
160#define ZC3XX_R1A6_YMEANAFTERAE 0x01a6
161#define ZC3XX_R1A7_CALCGLOBALMEAN 0x01a7
162
163#define ZC3XX_R1A2_BLUEMEANAFTERAGC 0x01a2
164
165/* Matrixes */
166
167/* Color matrix is like :
168 R' = R * RGB00 + G * RGB01 + B * RGB02 + RGB03
169 G' = R * RGB10 + G * RGB11 + B * RGB22 + RGB13
170 B' = R * RGB20 + G * RGB21 + B * RGB12 + RGB23
171 */
172#define ZC3XX_R10A_RGB00 0x010a
173#define ZC3XX_R10B_RGB01 0x010b
174#define ZC3XX_R10C_RGB02 0x010c
175#define ZC3XX_R113_RGB03 0x0113
176#define ZC3XX_R10D_RGB10 0x010d
177#define ZC3XX_R10E_RGB11 0x010e
178#define ZC3XX_R10F_RGB12 0x010f
179#define ZC3XX_R114_RGB13 0x0114
180#define ZC3XX_R110_RGB20 0x0110
181#define ZC3XX_R111_RGB21 0x0111
182#define ZC3XX_R112_RGB22 0x0112
183#define ZC3XX_R115_RGB23 0x0115
184
185/* Gamma matrix */
186#define ZC3XX_R120_GAMMA00 0x0120
187#define ZC3XX_R121_GAMMA01 0x0121
188#define ZC3XX_R122_GAMMA02 0x0122
189#define ZC3XX_R123_GAMMA03 0x0123
190#define ZC3XX_R124_GAMMA04 0x0124
191#define ZC3XX_R125_GAMMA05 0x0125
192#define ZC3XX_R126_GAMMA06 0x0126
193#define ZC3XX_R127_GAMMA07 0x0127
194#define ZC3XX_R128_GAMMA08 0x0128
195#define ZC3XX_R129_GAMMA09 0x0129
196#define ZC3XX_R12A_GAMMA0A 0x012a
197#define ZC3XX_R12B_GAMMA0B 0x012b
198#define ZC3XX_R12C_GAMMA0C 0x012c
199#define ZC3XX_R12D_GAMMA0D 0x012d
200#define ZC3XX_R12E_GAMMA0E 0x012e
201#define ZC3XX_R12F_GAMMA0F 0x012f
202#define ZC3XX_R130_GAMMA10 0x0130
203#define ZC3XX_R131_GAMMA11 0x0131
204#define ZC3XX_R132_GAMMA12 0x0132
205#define ZC3XX_R133_GAMMA13 0x0133
206#define ZC3XX_R134_GAMMA14 0x0134
207#define ZC3XX_R135_GAMMA15 0x0135
208#define ZC3XX_R136_GAMMA16 0x0136
209#define ZC3XX_R137_GAMMA17 0x0137
210#define ZC3XX_R138_GAMMA18 0x0138
211#define ZC3XX_R139_GAMMA19 0x0139
212#define ZC3XX_R13A_GAMMA1A 0x013a
213#define ZC3XX_R13B_GAMMA1B 0x013b
214#define ZC3XX_R13C_GAMMA1C 0x013c
215#define ZC3XX_R13D_GAMMA1D 0x013d
216#define ZC3XX_R13E_GAMMA1E 0x013e
217#define ZC3XX_R13F_GAMMA1F 0x013f
218
219/* Luminance gamma */
220#define ZC3XX_R140_YGAMMA00 0x0140
221#define ZC3XX_R141_YGAMMA01 0x0141
222#define ZC3XX_R142_YGAMMA02 0x0142
223#define ZC3XX_R143_YGAMMA03 0x0143
224#define ZC3XX_R144_YGAMMA04 0x0144
225#define ZC3XX_R145_YGAMMA05 0x0145
226#define ZC3XX_R146_YGAMMA06 0x0146
227#define ZC3XX_R147_YGAMMA07 0x0147
228#define ZC3XX_R148_YGAMMA08 0x0148
229#define ZC3XX_R149_YGAMMA09 0x0149
230#define ZC3XX_R14A_YGAMMA0A 0x014a
231#define ZC3XX_R14B_YGAMMA0B 0x014b
232#define ZC3XX_R14C_YGAMMA0C 0x014c
233#define ZC3XX_R14D_YGAMMA0D 0x014d
234#define ZC3XX_R14E_YGAMMA0E 0x014e
235#define ZC3XX_R14F_YGAMMA0F 0x014f
236#define ZC3XX_R150_YGAMMA10 0x0150
237#define ZC3XX_R151_YGAMMA11 0x0151
238
239#define ZC3XX_R1C5_SHARPNESSMODE 0x01c5
240#define ZC3XX_R1C6_SHARPNESS00 0x01c6
241#define ZC3XX_R1C7_SHARPNESS01 0x01c7
242#define ZC3XX_R1C8_SHARPNESS02 0x01c8
243#define ZC3XX_R1C9_SHARPNESS03 0x01c9
244#define ZC3XX_R1CA_SHARPNESS04 0x01ca
245#define ZC3XX_R1CB_SHARPNESS05 0x01cb
246
247/* Synchronization */
248#define ZC3XX_R190_SYNC00LOW 0x0190
249#define ZC3XX_R191_SYNC00MID 0x0191
250#define ZC3XX_R192_SYNC00HIGH 0x0192
251#define ZC3XX_R195_SYNC01LOW 0x0195
252#define ZC3XX_R196_SYNC01MID 0x0196
253#define ZC3XX_R197_SYNC01HIGH 0x0197
254
255/* Dead pixels */
256#define ZC3XX_R250_DEADPIXELSMODE 0x0250
257
258/* EEPROM */
259#define ZC3XX_R300_EEPROMCONFIG 0x0300
260#define ZC3XX_R301_EEPROMACCESS 0x0301
261#define ZC3XX_R302_EEPROMSTATUS 0x0302
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
new file mode 100644
index 000000000000..b761b11c5c6a
--- /dev/null
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -0,0 +1,7623 @@
1/*
2 * Z-Star/Vimicro zc301/zc302p/vc30x library
3 * Copyright (C) 2004 2005 2006 Michel Xhaard
4 * mxhaard@magic.fr
5 *
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#define MODULE_NAME "zc3xx"
24
25#include "gspca.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>, "
31 "Serge A. Suchkov <Serge.A.S@tochka.ru>");
32MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver");
33MODULE_LICENSE("GPL");
34
35static int force_sensor = -1;
36
37#include "jpeg.h"
38#include "zc3xx-reg.h"
39
40/* specific webcam descriptor */
41struct sd {
42 struct gspca_dev gspca_dev; /* !! must be the first item */
43
44 __u8 brightness;
45 __u8 contrast;
46 __u8 gamma;
47 __u8 autogain;
48 __u8 lightfreq;
49 __u8 sharpness;
50
51 char qindex;
52 char sensor; /* Type of image sensor chip */
53/* !! values used in different tables */
54#define SENSOR_CS2102 0
55#define SENSOR_CS2102K 1
56#define SENSOR_GC0305 2
57#define SENSOR_HDCS2020 3
58#define SENSOR_HDCS2020b 4
59#define SENSOR_HV7131B 5
60#define SENSOR_HV7131C 6
61#define SENSOR_ICM105A 7
62#define SENSOR_MC501CB 8
63#define SENSOR_OV7620 9
64/*#define SENSOR_OV7648 9 - same values */
65#define SENSOR_OV7630C 10
66#define SENSOR_PAS106 11
67#define SENSOR_PB0330 12
68#define SENSOR_PO2030 13
69#define SENSOR_TAS5130CK 14
70#define SENSOR_TAS5130CXX 15
71#define SENSOR_TAS5130C_VF0250 16
72#define SENSOR_MAX 17
73 unsigned short chip_revision;
74};
75
76/* V4L2 controls supported by the driver */
77static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
81static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
83static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
84static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
85static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
87static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
89
90static struct ctrl sd_ctrls[] = {
91#define SD_BRIGHTNESS 0
92 {
93 {
94 .id = V4L2_CID_BRIGHTNESS,
95 .type = V4L2_CTRL_TYPE_INTEGER,
96 .name = "Brightness",
97 .minimum = 0,
98 .maximum = 255,
99 .step = 1,
100 .default_value = 128,
101 },
102 .set = sd_setbrightness,
103 .get = sd_getbrightness,
104 },
105#define SD_CONTRAST 1
106 {
107 {
108 .id = V4L2_CID_CONTRAST,
109 .type = V4L2_CTRL_TYPE_INTEGER,
110 .name = "Contrast",
111 .minimum = 0,
112 .maximum = 256,
113 .step = 1,
114 .default_value = 128,
115 },
116 .set = sd_setcontrast,
117 .get = sd_getcontrast,
118 },
119#define SD_GAMMA 2
120 {
121 {
122 .id = V4L2_CID_GAMMA,
123 .type = V4L2_CTRL_TYPE_INTEGER,
124 .name = "Gamma",
125 .minimum = 1,
126 .maximum = 6,
127 .step = 1,
128 .default_value = 4,
129 },
130 .set = sd_setgamma,
131 .get = sd_getgamma,
132 },
133#define SD_AUTOGAIN 3
134 {
135 {
136 .id = V4L2_CID_AUTOGAIN,
137 .type = V4L2_CTRL_TYPE_BOOLEAN,
138 .name = "Auto Gain",
139 .minimum = 0,
140 .maximum = 1,
141 .step = 1,
142 .default_value = 1,
143 },
144 .set = sd_setautogain,
145 .get = sd_getautogain,
146 },
147#define SD_FREQ 4
148 {
149 {
150 .id = V4L2_CID_POWER_LINE_FREQUENCY,
151 .type = V4L2_CTRL_TYPE_MENU,
152 .name = "Light frequency filter",
153 .minimum = 0,
154 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
155 .step = 1,
156 .default_value = 1,
157 },
158 .set = sd_setfreq,
159 .get = sd_getfreq,
160 },
161#define SD_SHARPNESS 5
162 {
163 {
164 .id = V4L2_CID_SHARPNESS,
165 .type = V4L2_CTRL_TYPE_INTEGER,
166 .name = "Sharpness",
167 .minimum = 0,
168 .maximum = 3,
169 .step = 1,
170 .default_value = 2,
171 },
172 .set = sd_setsharpness,
173 .get = sd_getsharpness,
174 },
175};
176
177static struct v4l2_pix_format vga_mode[] = {
178 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
179 .bytesperline = 320,
180 .sizeimage = 320 * 240 * 3 / 8 + 590,
181 .colorspace = V4L2_COLORSPACE_JPEG,
182 .priv = 1},
183 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
184 .bytesperline = 640,
185 .sizeimage = 640 * 480 * 3 / 8 + 590,
186 .colorspace = V4L2_COLORSPACE_JPEG,
187 .priv = 0},
188};
189
190static struct v4l2_pix_format sif_mode[] = {
191 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
192 .bytesperline = 176,
193 .sizeimage = 176 * 144 * 3 / 8 + 590,
194 .colorspace = V4L2_COLORSPACE_JPEG,
195 .priv = 1},
196 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
197 .bytesperline = 352,
198 .sizeimage = 352 * 288 * 3 / 8 + 590,
199 .colorspace = V4L2_COLORSPACE_JPEG,
200 .priv = 0},
201};
202
203/* usb exchanges */
204struct usb_action {
205 __u8 req;
206 __u8 val;
207 __u16 idx;
208};
209
210static const struct usb_action cs2102_Initial[] = {
211 {0xa1, 0x01, 0x0008},
212 {0xa1, 0x01, 0x0008},
213 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
214 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
215 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
216 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
217 {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
218 {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
219 {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
220 {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
221 {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
222 {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
223 {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
224 {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
225 {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
226 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
227 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
228 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
229 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
230 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
231 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
232 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
233 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
234 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
235 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
236 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
237 {0xaa, 0x02, 0x0008},
238 {0xaa, 0x03, 0x0000},
239 {0xaa, 0x11, 0x0000},
240 {0xaa, 0x12, 0x0089},
241 {0xaa, 0x13, 0x0000},
242 {0xaa, 0x14, 0x00e9},
243 {0xaa, 0x20, 0x0000},
244 {0xaa, 0x22, 0x0000},
245 {0xaa, 0x0b, 0x0004},
246 {0xaa, 0x30, 0x0030},
247 {0xaa, 0x31, 0x0030},
248 {0xaa, 0x32, 0x0030},
249 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
250 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
251 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
252 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
253 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
254 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
255 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
256 {0xa0, 0x10, 0x01ae},
257 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
258 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
259 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
260 {0xa0, 0x00, 0x01ad},
261 {0xa1, 0x01, 0x0002},
262 {0xa1, 0x01, 0x0008},
263 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
264 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
265 {0xa1, 0x01, 0x01c8},
266 {0xa1, 0x01, 0x01c9},
267 {0xa1, 0x01, 0x01ca},
268 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
269 {0xa0, 0x24, ZC3XX_R120_GAMMA00}, /* gamma 5 */
270 {0xa0, 0x44, ZC3XX_R121_GAMMA01},
271 {0xa0, 0x64, ZC3XX_R122_GAMMA02},
272 {0xa0, 0x84, ZC3XX_R123_GAMMA03},
273 {0xa0, 0x9d, ZC3XX_R124_GAMMA04},
274 {0xa0, 0xb2, ZC3XX_R125_GAMMA05},
275 {0xa0, 0xc4, ZC3XX_R126_GAMMA06},
276 {0xa0, 0xd3, ZC3XX_R127_GAMMA07},
277 {0xa0, 0xe0, ZC3XX_R128_GAMMA08},
278 {0xa0, 0xeb, ZC3XX_R129_GAMMA09},
279 {0xa0, 0xf4, ZC3XX_R12A_GAMMA0A},
280 {0xa0, 0xfb, ZC3XX_R12B_GAMMA0B},
281 {0xa0, 0xff, ZC3XX_R12C_GAMMA0C},
282 {0xa0, 0xff, ZC3XX_R12D_GAMMA0D},
283 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
284 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
285 {0xa0, 0x18, ZC3XX_R130_GAMMA10},
286 {0xa0, 0x20, ZC3XX_R131_GAMMA11},
287 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
288 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
289 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
290 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
291 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
292 {0xa0, 0x0e, ZC3XX_R137_GAMMA17},
293 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
294 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
295 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
296 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
297 {0xa0, 0x00, ZC3XX_R13C_GAMMA1C},
298 {0xa0, 0x00, ZC3XX_R13D_GAMMA1D},
299 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
300 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
301 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
302 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
303 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
304 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
305 {0xa0, 0x58, ZC3XX_R10E_RGB11},
306 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
307 {0xa0, 0xf4, ZC3XX_R110_RGB20},
308 {0xa0, 0xf4, ZC3XX_R111_RGB21},
309 {0xa0, 0x58, ZC3XX_R112_RGB22},
310 {0xa1, 0x01, 0x0180},
311 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
312 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
313 {0xaa, 0x23, 0x0001},
314 {0xaa, 0x24, 0x0055},
315 {0xaa, 0x25, 0x00cc},
316 {0xaa, 0x21, 0x003f},
317 {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
318 {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID},
319 {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW},
320 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
321 {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID},
322 {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW},
323 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
324 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
325 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
326 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
327 {0xa0, 0x39, ZC3XX_R01D_HSYNC_0},
328 {0xa0, 0x70, ZC3XX_R01E_HSYNC_1},
329 {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2},
330 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
331 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
332 {0xa1, 0x01, 0x0180},
333 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
334 {0xa0, 0x40, ZC3XX_R116_RGAIN},
335 {0xa0, 0x40, ZC3XX_R117_GGAIN},
336 {0xa0, 0x40, ZC3XX_R118_BGAIN},
337 {}
338};
339
340static const struct usb_action cs2102_InitialScale[] = {
341 {0xa1, 0x01, 0x0008},
342 {0xa1, 0x01, 0x0008},
343 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
344 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
345 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
346 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
347 {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
348 {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
349 {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
350 {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
351 {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
352 {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
353 {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
354 {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
355 {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
356 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
357 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
358 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
359 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
360 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
361 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
362 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
363 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
364 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
365 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
366 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
367 {0xaa, 0x02, 0x0008},
368 {0xaa, 0x03, 0x0000},
369 {0xaa, 0x11, 0x0001},
370 {0xaa, 0x12, 0x0087},
371 {0xaa, 0x13, 0x0001},
372 {0xaa, 0x14, 0x00e7},
373 {0xaa, 0x20, 0x0000},
374 {0xaa, 0x22, 0x0000},
375 {0xaa, 0x0b, 0x0004},
376 {0xaa, 0x30, 0x0030},
377 {0xaa, 0x31, 0x0030},
378 {0xaa, 0x32, 0x0030},
379 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
380 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
381 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
382 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
383 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
384 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
385 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
386 {0xa0, 0x15, 0x01ae},
387 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
388 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
389 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
390 {0xa0, 0x00, 0x01ad},
391 {0xa1, 0x01, 0x0002},
392 {0xa1, 0x01, 0x0008},
393 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
394 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
395 {0xa1, 0x01, 0x01c8},
396 {0xa1, 0x01, 0x01c9},
397 {0xa1, 0x01, 0x01ca},
398 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
399 {0xa0, 0x24, ZC3XX_R120_GAMMA00}, /* gamma 5 */
400 {0xa0, 0x44, ZC3XX_R121_GAMMA01},
401 {0xa0, 0x64, ZC3XX_R122_GAMMA02},
402 {0xa0, 0x84, ZC3XX_R123_GAMMA03},
403 {0xa0, 0x9d, ZC3XX_R124_GAMMA04},
404 {0xa0, 0xb2, ZC3XX_R125_GAMMA05},
405 {0xa0, 0xc4, ZC3XX_R126_GAMMA06},
406 {0xa0, 0xd3, ZC3XX_R127_GAMMA07},
407 {0xa0, 0xe0, ZC3XX_R128_GAMMA08},
408 {0xa0, 0xeb, ZC3XX_R129_GAMMA09},
409 {0xa0, 0xf4, ZC3XX_R12A_GAMMA0A},
410 {0xa0, 0xfb, ZC3XX_R12B_GAMMA0B},
411 {0xa0, 0xff, ZC3XX_R12C_GAMMA0C},
412 {0xa0, 0xff, ZC3XX_R12D_GAMMA0D},
413 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
414 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
415 {0xa0, 0x18, ZC3XX_R130_GAMMA10},
416 {0xa0, 0x20, ZC3XX_R131_GAMMA11},
417 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
418 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
419 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
420 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
421 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
422 {0xa0, 0x0e, ZC3XX_R137_GAMMA17},
423 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
424 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
425 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
426 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
427 {0xa0, 0x00, ZC3XX_R13C_GAMMA1C},
428 {0xa0, 0x00, ZC3XX_R13D_GAMMA1D},
429 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
430 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
431 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
432 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
433 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
434 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
435 {0xa0, 0x58, ZC3XX_R10E_RGB11},
436 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
437 {0xa0, 0xf4, ZC3XX_R110_RGB20},
438 {0xa0, 0xf4, ZC3XX_R111_RGB21},
439 {0xa0, 0x58, ZC3XX_R112_RGB22},
440 {0xa1, 0x01, 0x0180},
441 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
442 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
443 {0xaa, 0x23, 0x0000},
444 {0xaa, 0x24, 0x00aa},
445 {0xaa, 0x25, 0x00e6},
446 {0xaa, 0x21, 0x003f},
447 {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
448 {0xa0, 0x55, ZC3XX_R191_EXPOSURELIMITMID},
449 {0xa0, 0xcc, ZC3XX_R192_EXPOSURELIMITLOW},
450 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
451 {0xa0, 0x18, ZC3XX_R196_ANTIFLICKERMID},
452 {0xa0, 0x6a, ZC3XX_R197_ANTIFLICKERLOW},
453 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
454 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
455 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
456 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
457 {0xa0, 0x3f, ZC3XX_R01D_HSYNC_0},
458 {0xa0, 0xa5, ZC3XX_R01E_HSYNC_1},
459 {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
460 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
461 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
462 {0xa1, 0x01, 0x0180},
463 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
464 {0xa0, 0x40, ZC3XX_R116_RGAIN},
465 {0xa0, 0x40, ZC3XX_R117_GGAIN},
466 {0xa0, 0x40, ZC3XX_R118_BGAIN},
467 {}
468};
469static const struct usb_action cs2102_50HZ[] = {
470 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
471 {0xaa, 0x0f, 0x008c}, /* 00,0f,8c,aa */
472 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
473 {0xaa, 0x04, 0x00ac}, /* 00,04,ac,aa */
474 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
475 {0xaa, 0x11, 0x00ac}, /* 00,11,ac,aa */
476 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
477 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
478 {0xaa, 0x1d, 0x00ac}, /* 00,1d,ac,aa */
479 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
480 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
481 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
482 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
483 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
484 {0xa0, 0x42, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,42,cc */
485 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
486 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
487 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
488 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
489 {0xa0, 0x8c, ZC3XX_R01D_HSYNC_0}, /* 00,1d,8c,cc */
490 {0xa0, 0xb0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,b0,cc */
491 {0xa0, 0xd0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,d0,cc */
492 {}
493};
494static const struct usb_action cs2102_50HZScale[] = {
495 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
496 {0xaa, 0x0f, 0x0093}, /* 00,0f,93,aa */
497 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
498 {0xaa, 0x04, 0x00a1}, /* 00,04,a1,aa */
499 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
500 {0xaa, 0x11, 0x00a1}, /* 00,11,a1,aa */
501 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
502 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
503 {0xaa, 0x1d, 0x00a1}, /* 00,1d,a1,aa */
504 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
505 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
506 {0xa0, 0xf7, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f7,cc */
507 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
508 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
509 {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
510 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
511 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
512 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
513 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
514 {0xa0, 0x93, ZC3XX_R01D_HSYNC_0}, /* 00,1d,93,cc */
515 {0xa0, 0xb0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,b0,cc */
516 {0xa0, 0xd0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,d0,cc */
517 {}
518};
519static const struct usb_action cs2102_60HZ[] = {
520 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
521 {0xaa, 0x0f, 0x005d}, /* 00,0f,5d,aa */
522 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
523 {0xaa, 0x04, 0x00aa}, /* 00,04,aa,aa */
524 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
525 {0xaa, 0x11, 0x00aa}, /* 00,11,aa,aa */
526 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
527 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
528 {0xaa, 0x1d, 0x00aa}, /* 00,1d,aa,aa */
529 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
530 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
531 {0xa0, 0xe4, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e4,cc */
532 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
533 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
534 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3a,cc */
535 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
536 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
537 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
538 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
539 {0xa0, 0x5d, ZC3XX_R01D_HSYNC_0}, /* 00,1d,5d,cc */
540 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
541 {0xa0, 0xd0, 0x00c8}, /* 00,c8,d0,cc */
542 {}
543};
544static const struct usb_action cs2102_60HZScale[] = {
545 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
546 {0xaa, 0x0f, 0x00b7}, /* 00,0f,b7,aa */
547 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
548 {0xaa, 0x04, 0x00be}, /* 00,04,be,aa */
549 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
550 {0xaa, 0x11, 0x00be}, /* 00,11,be,aa */
551 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
552 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
553 {0xaa, 0x1d, 0x00be}, /* 00,1d,be,aa */
554 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
555 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
556 {0xa0, 0xfc, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,fc,cc */
557 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
558 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
559 {0xa0, 0x69, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,69,cc */
560 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
561 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
562 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
563 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
564 {0xa0, 0xb7, ZC3XX_R01D_HSYNC_0}, /* 00,1d,b7,cc */
565 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
566 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
567 {}
568};
569static const struct usb_action cs2102_NoFliker[] = {
570 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
571 {0xaa, 0x0f, 0x0059}, /* 00,0f,59,aa */
572 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
573 {0xaa, 0x04, 0x0080}, /* 00,04,80,aa */
574 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
575 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
576 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
577 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
578 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
579 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
580 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
581 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
582 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
583 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
584 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
585 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
586 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
587 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
588 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
589 {0xa0, 0x59, ZC3XX_R01D_HSYNC_0}, /* 00,1d,59,cc */
590 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
591 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
592 {}
593};
594static const struct usb_action cs2102_NoFlikerScale[] = {
595 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
596 {0xaa, 0x0f, 0x0059}, /* 00,0f,59,aa */
597 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
598 {0xaa, 0x04, 0x0080}, /* 00,04,80,aa */
599 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
600 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
601 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
602 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
603 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
604 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
605 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
606 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
607 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
608 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
609 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
610 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
611 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
612 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
613 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
614 {0xa0, 0x59, ZC3XX_R01D_HSYNC_0}, /* 00,1d,59,cc */
615 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
616 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
617 {}
618};
619
620/* CS2102_KOCOM */
621static const struct usb_action cs2102K_Initial[] = {
622 {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
623 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
624 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
625 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
626 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
627 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
628 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
629 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
630 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
631 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
632 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
633 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
634 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
635 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
636 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
637 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
638 {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
639 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
640 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
641 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
642 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
643 {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
644 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
645 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
646 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
647 {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
648 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
649 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
650 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
651 {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
652 {0xa0, 0x7c, ZC3XX_R093_I2CSETVALUE},
653 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
654 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
655 {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
656 {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
657 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
658 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
659 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
660 {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
661 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
662 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
663 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
664 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
665 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
666 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
667 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
668 {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
669 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
670 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
671 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
672 {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
673 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
674 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
675 {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
676 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
677 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
678 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
679 {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
680 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
681 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
682 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
683 {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
684 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
685 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
686 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
687 {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
688 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
689 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
690 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
691 {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
692 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
693 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
694 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
695 {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
696 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
697 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
698 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
699 {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
700 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
701 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
702 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
703 {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
704 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
705 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
706 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
707 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
708 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
709 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
710 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
711 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
712 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
713 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
714 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
715 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
716 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
717 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
718 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
719 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
720 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
721 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
722 {0xa0, 0x00, 0x01ad},
723 {0xa0, 0x01, 0x01b1},
724 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
725 {0xa0, 0x60, ZC3XX_R116_RGAIN},
726 {0xa0, 0x40, ZC3XX_R117_GGAIN},
727 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
728 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
729 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
730 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
731 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
732 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
733 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
734 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
735 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
736 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
737 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
738 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
739 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
740 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
741 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
742 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
743 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
744 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
745 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
746 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
747 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
748 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
749 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
750 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
751 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
752 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
753 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
754 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
755 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
756 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
757 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
758 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
759 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
760 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
761 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
762 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
763 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
764 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
765 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
766 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
767 {0xa0, 0x58, ZC3XX_R10E_RGB11},
768 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
769 {0xa0, 0xf4, ZC3XX_R110_RGB20},
770 {0xa0, 0xf4, ZC3XX_R111_RGB21},
771 {0xa0, 0x58, ZC3XX_R112_RGB22},
772 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
773 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
774 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
775 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
776 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
777 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
778 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
779 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
780 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
781 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
782 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
783 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
784 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
785 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
786 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
787 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
788 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
789 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
790 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
791 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
792 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
793 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
794 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
795 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
796 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
797 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
798 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
799 {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
800 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
801 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
802 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
803 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
804 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
805 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
806 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
807 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
808 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
809 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
810 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
811 {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
812 {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
813 {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
814 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
815 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
816 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
817 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
818 {0xa0, 0x60, ZC3XX_R116_RGAIN},
819 {0xa0, 0x40, ZC3XX_R117_GGAIN},
820 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
821 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
822 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
823 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
824 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
825 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
826 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
827 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
828 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
829 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
830 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
831 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
832 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
833 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
834 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
835 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
836 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
837 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
838 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
839 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
840 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
841 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
842 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
843 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
844 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
845 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
846 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
847 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
848 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
849 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
850 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
851 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
852 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
853 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
854 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
855 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
856 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
857 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
858 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
859 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
860 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
861 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
862 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
863 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
864 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
865 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
866 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
867 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
868 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
869 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
870 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
871 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
872 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
873 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
874 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
875 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
876 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
877 {}
878};
879
880static const struct usb_action cs2102K_InitialScale[] = {
881 {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
882 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
883 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
884 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
885 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
886 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
887 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
888 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
889 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
890 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
891 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
892 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
893 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
894 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
895 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
896 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
897 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
898 {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
899 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
900 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
901 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
902 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
903 {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
904 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
905 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
906 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
907 {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
908 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
909 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
910 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
911 {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
912 {0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE},
913 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
914 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
915 {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
916 {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
917 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
918 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
919 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
920 {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
921 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
922 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
923 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
924 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
925 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
926 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
927 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
928 {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
929 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
930 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
931 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
932 {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
933 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
934 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
935 {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
936 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
937 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
938 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
939 {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
940 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
941 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
942 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
943 {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
944 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
945 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
946 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
947 {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
948 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
949 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
950 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
951 {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
952 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
953 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
954 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
955 {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
956 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
957 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
958 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
959 {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
960 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
961 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
962 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
963 {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
964 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
965 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
966 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
967 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
968 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
969 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
970 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
971 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
972 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
973 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
974 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
975 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
976 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
977 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
978 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
979 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
980 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
981 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
982 {0xa0, 0x00, 0x01ad},
983 {0xa0, 0x01, 0x01b1},
984 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
985 {0xa0, 0x60, ZC3XX_R116_RGAIN},
986 {0xa0, 0x40, ZC3XX_R117_GGAIN},
987 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
988 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
989 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
990 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
991 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
992 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
993 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
994 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
995 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
996 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
997 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
998 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
999 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
1000 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
1001 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
1002 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
1003 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
1004 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
1005 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
1006 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1007 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1008 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
1009 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1010 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1011 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1012 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1013 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1014 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1015 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1016 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1017 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1018 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1019 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1020 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1021 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1022 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1023 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
1024 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
1025 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
1026 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
1027 {0xa0, 0x58, ZC3XX_R10E_RGB11},
1028 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
1029 {0xa0, 0xf4, ZC3XX_R110_RGB20},
1030 {0xa0, 0xf4, ZC3XX_R111_RGB21},
1031 {0xa0, 0x58, ZC3XX_R112_RGB22},
1032 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1033 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1034 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1035 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1036 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1037 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1038 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1039 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1040 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1041 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1042 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1043 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1044 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1045 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1046 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1047 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1048 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1049 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1050 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1051 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1052 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1053 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1054 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1055 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1056 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1057 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1058 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
1059 {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
1060 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1061 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
1062 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
1063 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1064 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1065 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
1066 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1067 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1068 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
1069 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
1070 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
1071 {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
1072 {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
1073 {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
1074 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1075 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1076 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1077 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1078 {0xa0, 0x60, ZC3XX_R116_RGAIN},
1079 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1080 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
1081 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1082 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1083 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
1084 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
1085 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
1086 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1087 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1088 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1089 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1090 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1091 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1092 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1093 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1094 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1095 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1096 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1097 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
1098 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
1099 {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
1100 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1101 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1102 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1103 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1104 {0xa0, 0x0A, ZC3XX_R092_I2CADDRESSSELECT},
1105 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1106 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1107 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1108 {0xa0, 0x0B, ZC3XX_R092_I2CADDRESSSELECT},
1109 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1110 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1111 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1112 {0xa0, 0x0C, ZC3XX_R092_I2CADDRESSSELECT},
1113 {0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE},
1114 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1115 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1116 {0xa0, 0x0D, ZC3XX_R092_I2CADDRESSSELECT},
1117 {0xa0, 0xA3, ZC3XX_R093_I2CSETVALUE},
1118 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1119 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1120 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
1121 {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
1122 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1123 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1124 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
1125 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1126 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1127 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1128 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
1129 {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
1130 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1131 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1132 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
1133 {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
1134 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1135 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1136 {0xa0, 0x0E, ZC3XX_R092_I2CADDRESSSELECT},
1137 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1138 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1139 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1140 {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
1141 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1142 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1143 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1144 {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
1145 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1146 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1147 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1148 {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
1149 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1150 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1151 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1152 {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
1153 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1154 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1155 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1156 {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
1157 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1158 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1159 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1160 {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
1161 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
1162 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1163 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1164 {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
1165 {0xa0, 0x0C, ZC3XX_R093_I2CSETVALUE},
1166 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1167 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1168 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1169 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1170 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1171 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1172 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
1173 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1174 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
1175 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1176 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1177 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1178 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1179 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
1180 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
1181 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1182 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1183 {0xa0, 0x00, 0x01ad},
1184 {0xa0, 0x01, 0x01b1},
1185 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
1186 {0xa0, 0x60, ZC3XX_R116_RGAIN},
1187 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1188 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
1189 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1190 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1191 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1192 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
1193 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
1194 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
1195 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1196 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
1197 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
1198 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
1199 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
1200 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
1201 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
1202 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
1203 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
1204 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
1205 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
1206 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
1207 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1208 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1209 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
1210 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1211 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1212 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1213 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1214 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1215 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1216 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1217 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1218 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1219 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1220 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1221 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1222 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1223 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1224 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
1225 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
1226 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
1227 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
1228 {0xa0, 0x58, ZC3XX_R10E_RGB11},
1229 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
1230 {0xa0, 0xf4, ZC3XX_R110_RGB20},
1231 {0xa0, 0xf4, ZC3XX_R111_RGB21},
1232 {0xa0, 0x58, ZC3XX_R112_RGB22},
1233 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1234 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1235 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1236 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1237 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1238 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1239 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1240 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1241 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1242 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1243 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1244 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1245 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1246 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1247 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1248 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1249 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1250 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1251 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1252 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1253 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1254 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1255 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1256 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1257 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1258 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1259 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
1260 {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
1261 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1262 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
1263 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
1264 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1265 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1266 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
1267 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1268 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1269 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
1270 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
1271 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
1272 {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
1273 {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
1274 {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
1275 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1276 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1277 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1278 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1279 {0xa0, 0x60, ZC3XX_R116_RGAIN},
1280 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1281 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
1282 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1283 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1284 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1285 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1286 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1287 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1288 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
1289 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1290 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1291 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1292 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1293 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1294 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1295 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1296 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
1297 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1298 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1299 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1300 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1301 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1302 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1303 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1304 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1305 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1306 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1307 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1308 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1309 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1310 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1311 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1312 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1313 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1314 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1315 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1316 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
1317 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1318 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1319 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1320 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1321 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1322 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1323 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1324 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
1325 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1326 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1327 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1328 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1329 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1330 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1331 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1332 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1333 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1334 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1335 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1336 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1337 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1338 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1339 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1340 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1341 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1342 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1343 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1344 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1345 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1346 {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
1347 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1348 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1349 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1350 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1351 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1352 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1353 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1354 {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
1355 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1356 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1357 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1358 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1359 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1360 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1361 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1362 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1363 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1364 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1365 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1366 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},
1367 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1368 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1369 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1370 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1371 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1372 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1373 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1374 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1375 {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
1376 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1377 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1378 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1379 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1380 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1381 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1382 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1383 {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
1384 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1385 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1386 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1387 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1388 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1389 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1390 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1391 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1392 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1393 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1394 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1395 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1396 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1397 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1398 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1399 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1400 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1401 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1402 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1403 {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
1404 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1405 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1406 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1407 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1408 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1409 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1410 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1411 {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
1412 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1413 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1414 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1415 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1416 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1417 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1418 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1419 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1420 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1421 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1422 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1423 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1424 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1425 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1426 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1427 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1428 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1429 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1430 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1431 {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
1432 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1433 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1434 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1435 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1436 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1437 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1438 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1439 {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
1440 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1441 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1442 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1443 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1444 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1445 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1446 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1447 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1448 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1449 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1450 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1451 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1452 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1453 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1454 {}
1455};
1456
1457static const struct usb_action gc0305_Initial[] = { /* 640x480 */
1458 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
1459 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
1460 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
1461 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
1462 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
1463 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
1464 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
1465 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
1466 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
1467 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
1468 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
1469 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
1470 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
1471 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
1472 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
1473 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */
1474 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
1475 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
1476 {0xaa, 0x13, 0x0002}, /* 00,13,02,aa */
1477 {0xaa, 0x15, 0x0003}, /* 00,15,03,aa */
1478 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
1479 {0xaa, 0x02, 0x0000}, /* 00,02,00,aa */
1480 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
1481 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa */
1482 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
1483 {0xaa, 0x1f, 0x0008}, /* 00,1f,08,aa */
1484 {0xaa, 0x21, 0x0012}, /* 00,21,12,aa */
1485 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc */
1486 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc */
1487 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc */
1488 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
1489 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa */
1490 {0xaa, 0x0b, 0x00b0}, /* 00,0b,b0,aa */
1491 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa */
1492 {0xaa, 0x0d, 0x00b0}, /* 00,0d,b0,aa */
1493 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa */
1494 {0xaa, 0x0f, 0x00b0}, /* 00,0f,b0,aa */
1495 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
1496 {0xaa, 0x11, 0x00b0}, /* 00,11,b0,aa */
1497 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa */
1498 {0xaa, 0x17, 0x00e6}, /* 00,17,e6,aa */
1499 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa */
1500 {0xaa, 0x19, 0x0086}, /* 00,19,86,aa */
1501 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1502 {0xaa, 0x1b, 0x0020}, /* 00,1b,20,aa */
1503 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */
1504 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
1505 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
1506 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc */
1507 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc */
1508 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
1509 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
1510 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
1511 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
1512 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
1513 {0xa0, 0x85, ZC3XX_R18D_YTARGET}, /* 01,8d,85,cc */
1514 {0xa0, 0x00, 0x011e}, /* 01,1e,00,cc */
1515 {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
1516 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
1517 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
1518 {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
1519 {}
1520};
1521static const struct usb_action gc0305_InitialScale[] = { /* 320x240 */
1522 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
1523 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
1524 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
1525 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
1526 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
1527 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
1528 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
1529 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
1530 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
1531 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
1532 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
1533 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
1534 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
1535 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
1536 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
1537 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */
1538 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
1539 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
1540 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
1541 {0xaa, 0x15, 0x0001}, /* 00,15,01,aa */
1542 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
1543 {0xaa, 0x02, 0x0000}, /* 00,02,00,aa */
1544 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
1545 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa */
1546 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
1547 {0xaa, 0x1f, 0x0008}, /* 00,1f,08,aa */
1548 {0xaa, 0x21, 0x0012}, /* 00,21,12,aa */
1549 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc */
1550 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc */
1551 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc */
1552 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
1553 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa */
1554 {0xaa, 0x0b, 0x00b0}, /* 00,0b,b0,aa */
1555 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa */
1556 {0xaa, 0x0d, 0x00b0}, /* 00,0d,b0,aa */
1557 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa */
1558 {0xaa, 0x0f, 0x00b0}, /* 00,0f,b0,aa */
1559 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
1560 {0xaa, 0x11, 0x00b0}, /* 00,11,b0,aa */
1561 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa */
1562 {0xaa, 0x17, 0x00e8}, /* 00,17,e8,aa */
1563 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa */
1564 {0xaa, 0x19, 0x0088}, /* 00,19,88,aa */
1565 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1566 {0xaa, 0x1b, 0x0020}, /* 00,1b,20,aa */
1567 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */
1568 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
1569 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
1570 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc */
1571 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc */
1572 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
1573 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
1574 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
1575 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
1576 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
1577 {0xa0, 0x00, 0x011e}, /* 01,1e,00,cc */
1578 {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
1579 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
1580 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
1581 {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
1582 {}
1583};
1584static const struct usb_action gc0305_50HZ[] = {
1585 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1586 {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */
1587 {0xaa, 0x84, 0x0038}, /* 00,84,38,aa */ /* win: 00,84,ec */
1588 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1589 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc */
1590 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
1591 /* win: 01,92,10 */
1592 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1593 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1594 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,8e,cc */
1595 /* win: 01,97,ec */
1596 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1597 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1598 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
1599 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1600 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1601 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1602 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1603 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1604 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1605 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
1606/* {0xa0, 0x85, ZC3XX_R18D_YTARGET}, * 01,8d,85,cc *
1607 * if 640x480 */
1608 {}
1609};
1610static const struct usb_action gc0305_60HZ[] = {
1611 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1612 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
1613 {0xaa, 0x84, 0x00ec}, /* 00,84,ec,aa */
1614 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1615 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc */
1616 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */
1617 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1618 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1619 {0xa0, 0xec, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,ec,cc */
1620 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1621 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1622 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
1623 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1624 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1625 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1626 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1627 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1628 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1629 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
1630 {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* 01,8d,80,cc */
1631 {}
1632};
1633
1634static const struct usb_action gc0305_NoFliker[] = {
1635 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc */
1636 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1637 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
1638 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
1639 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1640 {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,00,cc */
1641 {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,48,cc */
1642 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1643 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1644 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
1645 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1646 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1647 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1648 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1649 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1650 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1651 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1652 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
1653 {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* 01,8d,80,cc */
1654 {}
1655};
1656
1657/* play poker with registers at your own risk !! */
1658static const struct usb_action hdcs2020xx_Initial[] = {
1659 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1660 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
1661 {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT},
1662 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
1663 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1664 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1665 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1666 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW},
1667 /* D0 ?? E0 did not start */
1668 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1669 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1670 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1671 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
1672 {0xa0, 0x08, ZC3XX_R098_WINYSTARTLOW},
1673 {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW},
1674 {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW},
1675 {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW},
1676 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
1677 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},
1678 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
1679 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
1680 {0xaa, 0x02, 0x0002},
1681 {0xaa, 0x07, 0x0006},
1682 {0xaa, 0x08, 0x0002},
1683 {0xaa, 0x09, 0x0006},
1684 {0xaa, 0x0a, 0x0001},
1685 {0xaa, 0x0b, 0x0001},
1686 {0xaa, 0x0c, 0x0008},
1687 {0xaa, 0x0d, 0x0000},
1688 {0xaa, 0x10, 0x0000},
1689 {0xaa, 0x12, 0x0005},
1690 {0xaa, 0x13, 0x0063},
1691 {0xaa, 0x15, 0x0070},
1692 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
1693 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1694 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1695 {0xa0, 0x00, 0x01ad},
1696 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1697 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1698 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1699 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1700 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1701 {0xa1, 0x01, 0x0002},
1702 {0xa1, 0x01, 0x0008},
1703 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1704 {0xa0, 0x04, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1705 {0xa1, 0x01, 0x01c8},
1706 {0xa1, 0x01, 0x01c9},
1707 {0xa1, 0x01, 0x01ca},
1708 {0xa0, 0x07, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1709 {0xa0, 0x11, ZC3XX_R120_GAMMA00}, /* gamma ~4 */
1710 {0xa0, 0x37, ZC3XX_R121_GAMMA01},
1711 {0xa0, 0x58, ZC3XX_R122_GAMMA02},
1712 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1713 {0xa0, 0x91, ZC3XX_R124_GAMMA04},
1714 {0xa0, 0xa6, ZC3XX_R125_GAMMA05},
1715 {0xa0, 0xb8, ZC3XX_R126_GAMMA06},
1716 {0xa0, 0xc7, ZC3XX_R127_GAMMA07},
1717 {0xa0, 0xd3, ZC3XX_R128_GAMMA08},
1718 {0xa0, 0xde, ZC3XX_R129_GAMMA09},
1719 {0xa0, 0xe6, ZC3XX_R12A_GAMMA0A},
1720 {0xa0, 0xed, ZC3XX_R12B_GAMMA0B},
1721 {0xa0, 0xf3, ZC3XX_R12C_GAMMA0C},
1722 {0xa0, 0xf8, ZC3XX_R12D_GAMMA0D},
1723 {0xa0, 0xfb, ZC3XX_R12E_GAMMA0E},
1724 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1725 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1726 {0xa0, 0x23, ZC3XX_R131_GAMMA11},
1727 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1728 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1729 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1730 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1731 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1732 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1733 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1734 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1735 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1736 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1737 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1738 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1739 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1740 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1741
1742 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
1743 {0xa0, 0xf5, ZC3XX_R10B_RGB01},
1744 {0xa0, 0xff, ZC3XX_R10C_RGB02},
1745 {0xa0, 0xf9, ZC3XX_R10D_RGB10},
1746 {0xa0, 0x51, ZC3XX_R10E_RGB11},
1747 {0xa0, 0xf5, ZC3XX_R10F_RGB12},
1748 {0xa0, 0xfb, ZC3XX_R110_RGB20},
1749 {0xa0, 0xed, ZC3XX_R111_RGB21},
1750 {0xa0, 0x5f, ZC3XX_R112_RGB22},
1751
1752 {0xa1, 0x01, 0x0180},
1753 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1754 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1755 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
1756 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
1757 {0xaa, 0x20, 0x0004},
1758 {0xaa, 0x21, 0x003d},
1759 {0xaa, 0x03, 0x0041},
1760 {0xaa, 0x04, 0x0010},
1761 {0xaa, 0x05, 0x003d},
1762 {0xaa, 0x0e, 0x0001},
1763 {0xaa, 0x0f, 0x0000},
1764 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
1765 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
1766 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1767 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
1768 {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW},
1769 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1770 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1771 {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW},
1772 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1773 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1774 {0xa0, 0x41, ZC3XX_R01D_HSYNC_0},
1775 {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1},
1776 {0xa0, 0xad, ZC3XX_R01F_HSYNC_2},
1777 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
1778 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},
1779 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},
1780 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
1781 {0xa1, 0x01, 0x0195},
1782 {0xa1, 0x01, 0x0196},
1783 {0xa1, 0x01, 0x0197},
1784 {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW},
1785 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
1786 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1787 {0xa0, 0x1d, ZC3XX_R116_RGAIN},
1788 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1789 {0xa0, 0x85, ZC3XX_R118_BGAIN},
1790 {0xa1, 0x01, 0x0116},
1791 {0xa1, 0x01, 0x0118},
1792 {0xa1, 0x01, 0x0180},
1793 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1794 {0xa0, 0x1d, ZC3XX_R116_RGAIN},
1795 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1796 {0xa0, 0x85, ZC3XX_R118_BGAIN},
1797 {0xa1, 0x01, 0x0116},
1798 {0xa1, 0x01, 0x0118},
1799/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */
1800 {0xa0, 0x00, 0x0007},
1801 {}
1802};
1803
1804static const struct usb_action hdcs2020xx_InitialScale[] = {
1805 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1806 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
1807 {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT},
1808 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
1809 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1810 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1811 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1812 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1813 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1814 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1815 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1816 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
1817 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1818 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
1819 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1820 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
1821 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
1822 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
1823 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
1824 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
1825 {0xaa, 0x02, 0x0002},
1826 {0xaa, 0x07, 0x0006},
1827 {0xaa, 0x08, 0x0002},
1828 {0xaa, 0x09, 0x0006},
1829 {0xaa, 0x0a, 0x0001},
1830 {0xaa, 0x0b, 0x0001},
1831 {0xaa, 0x0c, 0x0008},
1832 {0xaa, 0x0d, 0x0000},
1833 {0xaa, 0x10, 0x0000},
1834 {0xaa, 0x12, 0x0005},
1835 {0xaa, 0x13, 0x0063},
1836 {0xaa, 0x15, 0x0070},
1837 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
1838 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1839 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1840 {0xa0, 0x00, 0x01ad},
1841 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1842 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1843 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1844 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1845 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1846 {0xa1, 0x01, 0x0002},
1847 {0xa1, 0x01, 0x0008},
1848 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1849 {0xa0, 0x04, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1850 {0xa1, 0x01, 0x01c8},
1851 {0xa1, 0x01, 0x01c9},
1852 {0xa1, 0x01, 0x01ca},
1853 {0xa0, 0x07, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1854 {0xa0, 0x11, ZC3XX_R120_GAMMA00}, /* gamma ~4*/
1855 {0xa0, 0x37, ZC3XX_R121_GAMMA01},
1856 {0xa0, 0x58, ZC3XX_R122_GAMMA02},
1857 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1858 {0xa0, 0x91, ZC3XX_R124_GAMMA04},
1859 {0xa0, 0xa6, ZC3XX_R125_GAMMA05},
1860 {0xa0, 0xb8, ZC3XX_R126_GAMMA06},
1861 {0xa0, 0xc7, ZC3XX_R127_GAMMA07},
1862 {0xa0, 0xd3, ZC3XX_R128_GAMMA08},
1863 {0xa0, 0xde, ZC3XX_R129_GAMMA09},
1864 {0xa0, 0xe6, ZC3XX_R12A_GAMMA0A},
1865 {0xa0, 0xed, ZC3XX_R12B_GAMMA0B},
1866 {0xa0, 0xf3, ZC3XX_R12C_GAMMA0C},
1867 {0xa0, 0xf8, ZC3XX_R12D_GAMMA0D},
1868 {0xa0, 0xfb, ZC3XX_R12E_GAMMA0E},
1869 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1870 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1871 {0xa0, 0x23, ZC3XX_R131_GAMMA11},
1872 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1873 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1874 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1875 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1876 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1877 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1878 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1879 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1880 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1881 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1882 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1883 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1884 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1885 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1886 {0xa0, 0x60, ZC3XX_R10A_RGB00}, /* matrix */
1887 {0xa0, 0xff, ZC3XX_R10B_RGB01},
1888 {0xa0, 0xff, ZC3XX_R10C_RGB02},
1889 {0xa0, 0xff, ZC3XX_R10D_RGB10},
1890 {0xa0, 0x60, ZC3XX_R10E_RGB11},
1891 {0xa0, 0xff, ZC3XX_R10F_RGB12},
1892 {0xa0, 0xff, ZC3XX_R110_RGB20},
1893 {0xa0, 0xff, ZC3XX_R111_RGB21},
1894 {0xa0, 0x60, ZC3XX_R112_RGB22},
1895
1896 {0xa1, 0x01, 0x0180},
1897 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1898 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1899 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
1900 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
1901 {0xaa, 0x20, 0x0002},
1902 {0xaa, 0x21, 0x001b},
1903 {0xaa, 0x03, 0x0044},
1904 {0xaa, 0x04, 0x0008},
1905 {0xaa, 0x05, 0x001b},
1906 {0xaa, 0x0e, 0x0001},
1907 {0xaa, 0x0f, 0x0000},
1908 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
1909 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
1910 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1911 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
1912 {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW},
1913 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1914 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1915 {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW},
1916 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1917 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1918 {0xa0, 0x44, ZC3XX_R01D_HSYNC_0},
1919 {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1},
1920 {0xa0, 0xad, ZC3XX_R01F_HSYNC_2},
1921 {0xa0, 0xeb, ZC3XX_R020_HSYNC_3},
1922 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},
1923 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},
1924 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
1925 {0xa1, 0x01, 0x0195},
1926 {0xa1, 0x01, 0x0196},
1927 {0xa1, 0x01, 0x0197},
1928 {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW},
1929 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
1930 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1931 {0xa0, 0x1d, ZC3XX_R116_RGAIN},
1932 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1933 {0xa0, 0x99, ZC3XX_R118_BGAIN},
1934 {0xa1, 0x01, 0x0116},
1935 {0xa1, 0x01, 0x0118},
1936 {0xa1, 0x01, 0x0180},
1937 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1938 {0xa0, 0x1d, ZC3XX_R116_RGAIN},
1939 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1940 {0xa0, 0x99, ZC3XX_R118_BGAIN},
1941/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */
1942 {0xa0, 0x00, 0x0007},
1943/* {0xa0, 0x18, 0x00fe}, */
1944 {}
1945};
1946static const struct usb_action hdcs2020xb_Initial[] = {
1947 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1948 {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
1949 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */
1950 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
1951 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1952 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1953 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1954 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1955 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1956 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1957 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1958 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1959 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1960 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1961 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1962 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
1963 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
1964 {0xaa, 0x1c, 0x0000},
1965 {0xaa, 0x0a, 0x0001},
1966 {0xaa, 0x0b, 0x0006},
1967 {0xaa, 0x0c, 0x007b},
1968 {0xaa, 0x0d, 0x00a7},
1969 {0xaa, 0x03, 0x00fb},
1970 {0xaa, 0x05, 0x0000},
1971 {0xaa, 0x06, 0x0003},
1972 {0xaa, 0x09, 0x0008},
1973
1974 {0xaa, 0x0f, 0x0018}, /* set sensor gain */
1975 {0xaa, 0x10, 0x0018},
1976 {0xaa, 0x11, 0x0018},
1977 {0xaa, 0x12, 0x0018},
1978
1979 {0xaa, 0x15, 0x004e},
1980 {0xaa, 0x1c, 0x0004},
1981 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
1982 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1983 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1984 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1985 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1986 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1987 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1988 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1989 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1990 {0xa1, 0x01, 0x0002},
1991 {0xa1, 0x01, 0x0008},
1992 {0xa1, 0x01, 0x0180},
1993 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
1994 {0xa0, 0x40, ZC3XX_R116_RGAIN},
1995 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1996 {0xa0, 0x40, ZC3XX_R118_BGAIN},
1997 {0xa1, 0x01, 0x0008},
1998 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1999 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2000 {0xa1, 0x01, 0x01c8},
2001 {0xa1, 0x01, 0x01c9},
2002 {0xa1, 0x01, 0x01ca},
2003 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2004 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
2005 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
2006 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
2007 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
2008 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
2009 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
2010 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
2011 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
2012 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
2013 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
2014 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
2015 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
2016 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
2017 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
2018 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
2019 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
2020 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
2021 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
2022 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
2023 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
2024 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
2025 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
2026 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
2027 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
2028 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
2029 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
2030 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
2031 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
2032 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
2033 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
2034 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
2035 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
2036
2037 {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
2038 {0xa0, 0xed, ZC3XX_R10B_RGB01},
2039 {0xa0, 0xed, ZC3XX_R10C_RGB02},
2040 {0xa0, 0xed, ZC3XX_R10D_RGB10},
2041 {0xa0, 0x66, ZC3XX_R10E_RGB11},
2042 {0xa0, 0xed, ZC3XX_R10F_RGB12},
2043 {0xa0, 0xed, ZC3XX_R110_RGB20},
2044 {0xa0, 0xed, ZC3XX_R111_RGB21},
2045 {0xa0, 0x66, ZC3XX_R112_RGB22},
2046
2047 {0xa1, 0x01, 0x0180},
2048 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2049 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2050 {0xaa, 0x13, 0x0031},
2051 {0xaa, 0x14, 0x0001},
2052 {0xaa, 0x0e, 0x0004},
2053 {0xaa, 0x19, 0x00cd},
2054 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
2055 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
2056 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
2057 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2058 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
2059 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
2060 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2061 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2062
2063 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 0x14 */
2064 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
2065 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
2066 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
2067 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
2068 {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
2069 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
2070 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2071 {0xa1, 0x01, 0x0180},
2072 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2073 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2074 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2075 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2076 {}
2077};
2078static const struct usb_action hdcs2020xb_InitialScale[] = {
2079 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2080 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2081 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2082 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
2083 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2084 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2085 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2086 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2087 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2088 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2089 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2090 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2091 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2092 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2093 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2094 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2095 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2096 {0xaa, 0x1c, 0x0000},
2097 {0xaa, 0x0a, 0x0001},
2098 {0xaa, 0x0b, 0x0006},
2099 {0xaa, 0x0c, 0x007a},
2100 {0xaa, 0x0d, 0x00a7},
2101 {0xaa, 0x03, 0x00fb},
2102 {0xaa, 0x05, 0x0000},
2103 {0xaa, 0x06, 0x0003},
2104 {0xaa, 0x09, 0x0008},
2105 {0xaa, 0x0f, 0x0018}, /* original setting */
2106 {0xaa, 0x10, 0x0018},
2107 {0xaa, 0x11, 0x0018},
2108 {0xaa, 0x12, 0x0018},
2109 {0xaa, 0x15, 0x004e},
2110 {0xaa, 0x1c, 0x0004},
2111 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
2112 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2113 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
2114 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2115 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2116 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2117 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2118 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2119 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2120 {0xa1, 0x01, 0x0002},
2121 {0xa1, 0x01, 0x0008},
2122 {0xa1, 0x01, 0x0180},
2123 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
2124 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2125 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2126 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2127 {0xa1, 0x01, 0x0008},
2128 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2129 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2130 {0xa1, 0x01, 0x01c8},
2131 {0xa1, 0x01, 0x01c9},
2132 {0xa1, 0x01, 0x01ca},
2133 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2134 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
2135 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
2136 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
2137 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
2138 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
2139 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
2140 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
2141 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
2142 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
2143 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
2144 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
2145 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
2146 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
2147 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
2148 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
2149 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
2150 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
2151 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
2152 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
2153 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
2154 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
2155 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
2156 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
2157 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
2158 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
2159 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
2160 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
2161 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
2162 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
2163 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
2164 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
2165 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
2166 {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
2167 {0xa0, 0xed, ZC3XX_R10B_RGB01},
2168 {0xa0, 0xed, ZC3XX_R10C_RGB02},
2169 {0xa0, 0xed, ZC3XX_R10D_RGB10},
2170 {0xa0, 0x66, ZC3XX_R10E_RGB11},
2171 {0xa0, 0xed, ZC3XX_R10F_RGB12},
2172 {0xa0, 0xed, ZC3XX_R110_RGB20},
2173 {0xa0, 0xed, ZC3XX_R111_RGB21},
2174 {0xa0, 0x66, ZC3XX_R112_RGB22},
2175 {0xa1, 0x01, 0x0180},
2176 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2177 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2178 /**** set exposure ***/
2179 {0xaa, 0x13, 0x0031},
2180 {0xaa, 0x14, 0x0001},
2181 {0xaa, 0x0e, 0x0004},
2182 {0xaa, 0x19, 0x00cd},
2183 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
2184 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
2185 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
2186 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2187 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
2188 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
2189 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2190 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2191 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
2192 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
2193 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
2194 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
2195 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
2196 {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
2197 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
2198 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2199 {0xa1, 0x01, 0x0180},
2200 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2201 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2202 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2203 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2204 {}
2205};
2206static const struct usb_action hdcs2020b_50HZ[] = {
2207 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2208 {0xaa, 0x13, 0x0018}, /* 00,13,18,aa */
2209 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
2210 {0xaa, 0x0e, 0x0005}, /* 00,0e,05,aa */
2211 {0xaa, 0x19, 0x001f}, /* 00,19,1f,aa */
2212 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2213 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
2214 {0xa0, 0x76, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,76,cc */
2215 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2216 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2217 {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */
2218 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2219 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2220 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
2221 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
2222 {0xa0, 0x05, ZC3XX_R01D_HSYNC_0}, /* 00,1d,05,cc */
2223 {0xa0, 0x1a, ZC3XX_R01E_HSYNC_1}, /* 00,1e,1a,cc */
2224 {0xa0, 0x2f, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2f,cc */
2225 {}
2226};
2227static const struct usb_action hdcs2020b_60HZ[] = {
2228 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2229 {0xaa, 0x13, 0x0031}, /* 00,13,31,aa */
2230 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
2231 {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */
2232 {0xaa, 0x19, 0x00cd}, /* 00,19,cd,aa */
2233 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2234 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
2235 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,62,cc */
2236 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2237 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2238 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */
2239 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2240 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2241 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
2242 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
2243 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
2244 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1}, /* 00,1e,18,cc */
2245 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */
2246 {}
2247};
2248static const struct usb_action hdcs2020b_NoFliker[] = {
2249 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2250 {0xaa, 0x13, 0x0010}, /* 00,13,10,aa */
2251 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
2252 {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */
2253 {0xaa, 0x19, 0x0000}, /* 00,19,00,aa */
2254 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2255 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
2256 {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
2257 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2258 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2259 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
2260 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2261 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2262 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
2263 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
2264 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
2265 {0xa0, 0x17, ZC3XX_R01E_HSYNC_1}, /* 00,1e,17,cc */
2266 {0xa0, 0x2a, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2a,cc */
2267 {}
2268};
2269
2270static const struct usb_action hv7131bxx_Initial[] = {
2271 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2272 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
2273 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
2274 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2275 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2276 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
2277 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2278 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2279 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2280 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2281 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2282 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2283 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2284 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2285 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2286 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2287 {0xaa, 0x30, 0x002d},
2288 {0xaa, 0x01, 0x0005},
2289 {0xaa, 0x11, 0x0000},
2290 {0xaa, 0x13, 0x0001}, /* {0xaa, 0x13, 0x0000}, */
2291 {0xaa, 0x14, 0x0001},
2292 {0xaa, 0x15, 0x00e8},
2293 {0xaa, 0x16, 0x0002},
2294 {0xaa, 0x17, 0x0086},
2295 {0xaa, 0x31, 0x0038},
2296 {0xaa, 0x32, 0x0038},
2297 {0xaa, 0x33, 0x0038},
2298 {0xaa, 0x5b, 0x0001},
2299 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2300 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2301 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2302 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
2303 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
2304 {0xa0, 0x00, 0x01ad},
2305 {0xa0, 0xc0, 0x019b},
2306 {0xa0, 0xa0, 0x019c},
2307 {0xa0, 0x02, ZC3XX_R188_MINGAIN},
2308 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2309 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2310 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2311 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2312 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2313 {0xaa, 0x02, 0x0080}, /* {0xaa, 0x02, 0x0090}; */
2314 {0xa1, 0x01, 0x0002},
2315 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
2316 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
2317 {0xa1, 0x01, 0x0091},
2318 {0xa1, 0x01, 0x0095},
2319 {0xa1, 0x01, 0x0096},
2320
2321 {0xa1, 0x01, 0x0008},
2322 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2323 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2324 {0xa1, 0x01, 0x01c8},
2325 {0xa1, 0x01, 0x01c9},
2326 {0xa1, 0x01, 0x01ca},
2327 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2328
2329 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
2330 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
2331 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
2332 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
2333 {0xa0, 0x50, ZC3XX_R10E_RGB11},
2334 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
2335 {0xa0, 0xf8, ZC3XX_R110_RGB20},
2336 {0xa0, 0xf8, ZC3XX_R111_RGB21},
2337 {0xa0, 0x50, ZC3XX_R112_RGB22},
2338 {0xa1, 0x01, 0x0180},
2339 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
2340 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2341 {0xaa, 0x25, 0x0007},
2342 {0xaa, 0x26, 0x00a1},
2343 {0xaa, 0x27, 0x0020},
2344 {0xaa, 0x20, 0x0000},
2345 {0xaa, 0x21, 0x00a0},
2346 {0xaa, 0x22, 0x0016},
2347 {0xaa, 0x23, 0x0040},
2348
2349 {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2F */
2350 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 4d */
2351 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW},
2352 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2353 {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID},
2354 {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW},
2355 {0xa0, 0x07, ZC3XX_R18C_AEFREEZE},
2356 {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE},
2357 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},
2358 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
2359 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2360 {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1},
2361 {0xa0, 0x16, ZC3XX_R01F_HSYNC_2},
2362 {0xa0, 0x40, ZC3XX_R020_HSYNC_3},
2363 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
2364 {0xa1, 0x01, 0x001d},
2365 {0xa1, 0x01, 0x001e},
2366 {0xa1, 0x01, 0x001f},
2367 {0xa1, 0x01, 0x0020},
2368 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
2369 {0xa1, 0x01, 0x0180},
2370 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2371 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2372 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2373 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2374/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */
2375 {}
2376};
2377
2378static const struct usb_action hv7131bxx_InitialScale[] = {
2379 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2380 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2381 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
2382 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2383 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
2384 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
2385 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2386 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2387 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2388 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2389 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2390 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2391 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2392 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2393 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2394 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2395 {0xaa, 0x30, 0x002d},
2396 {0xaa, 0x01, 0x0005},
2397 {0xaa, 0x11, 0x0001},
2398 {0xaa, 0x13, 0x0000}, /* {0xaa, 0x13, 0x0001}; */
2399 {0xaa, 0x14, 0x0001},
2400 {0xaa, 0x15, 0x00e6},
2401 {0xaa, 0x16, 0x0002},
2402 {0xaa, 0x17, 0x0086},
2403 {0xaa, 0x31, 0x0038},
2404 {0xaa, 0x32, 0x0038},
2405 {0xaa, 0x33, 0x0038},
2406 {0xaa, 0x5b, 0x0001},
2407 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2408 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2409 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2410 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
2411 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
2412 {0xa0, 0x00, 0x01ad},
2413 {0xa0, 0xc0, 0x019b},
2414 {0xa0, 0xa0, 0x019c},
2415 {0xa0, 0x02, ZC3XX_R188_MINGAIN},
2416 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2417 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2418 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2419 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2420 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2421 {0xaa, 0x02, 0x0090}, /* {0xaa, 0x02, 0x0080}, */
2422 {0xa1, 0x01, 0x0002},
2423 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
2424 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
2425 {0xa1, 0x01, 0x0091},
2426 {0xa1, 0x01, 0x0095},
2427 {0xa1, 0x01, 0x0096},
2428 {0xa1, 0x01, 0x0008},
2429 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2430 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2431 {0xa1, 0x01, 0x01c8},
2432 {0xa1, 0x01, 0x01c9},
2433 {0xa1, 0x01, 0x01ca},
2434 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2435
2436 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
2437 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
2438 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
2439 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
2440 {0xa0, 0x50, ZC3XX_R10E_RGB11},
2441 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
2442 {0xa0, 0xf8, ZC3XX_R110_RGB20},
2443 {0xa0, 0xf8, ZC3XX_R111_RGB21},
2444 {0xa0, 0x50, ZC3XX_R112_RGB22},
2445 {0xa1, 0x01, 0x0180},
2446 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
2447 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2448 {0xaa, 0x25, 0x0007},
2449 {0xaa, 0x26, 0x00a1},
2450 {0xaa, 0x27, 0x0020},
2451 {0xaa, 0x20, 0x0000},
2452 {0xaa, 0x21, 0x0040},
2453 {0xaa, 0x22, 0x0013},
2454 {0xaa, 0x23, 0x004c},
2455 {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2f */
2456 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 4d */
2457 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 60 */
2458 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2459 {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID},
2460 {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW},
2461 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
2462 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
2463 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},
2464 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
2465 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2466 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
2467 {0xa0, 0x13, ZC3XX_R01F_HSYNC_2},
2468 {0xa0, 0x4c, ZC3XX_R020_HSYNC_3},
2469 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
2470 {0xa1, 0x01, 0x001d},
2471 {0xa1, 0x01, 0x001e},
2472 {0xa1, 0x01, 0x001f},
2473 {0xa1, 0x01, 0x0020},
2474 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
2475 {0xa1, 0x01, 0x0180},
2476 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2477 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2478 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2479 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2480/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */
2481 {}
2482};
2483
2484static const struct usb_action hv7131cxx_Initial[] = {
2485 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2486 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
2487 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
2488 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2489 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2490 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2491 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2492 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2493 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2494 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2495 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2496 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2497 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2498 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2499 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2500 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2501 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2502 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2503 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2504 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2505 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2506 {0xaa, 0x01, 0x000c},
2507 {0xaa, 0x11, 0x0000},
2508 {0xaa, 0x13, 0x0000},
2509 {0xaa, 0x14, 0x0001},
2510 {0xaa, 0x15, 0x00e8},
2511 {0xaa, 0x16, 0x0002},
2512 {0xaa, 0x17, 0x0088},
2513
2514 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2515 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2516 {0xa0, 0x89, ZC3XX_R18D_YTARGET},
2517 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
2518 {0xa0, 0x00, 0x01ad},
2519 {0xa0, 0xc0, 0x019b},
2520 {0xa0, 0xa0, 0x019c},
2521 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2522 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2523 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2524 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2525 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2526 {0xa1, 0x01, 0x0002},
2527 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
2528 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
2529 {0xa1, 0x01, 0x0091},
2530 {0xa1, 0x01, 0x0095},
2531 {0xa1, 0x01, 0x0096},
2532
2533 {0xa1, 0x01, 0x0008},
2534 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2535 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2536 {0xa1, 0x01, 0x01c8},
2537 {0xa1, 0x01, 0x01c9},
2538 {0xa1, 0x01, 0x01ca},
2539 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2540
2541 {0xa0, 0x60, ZC3XX_R10A_RGB00}, /* matrix */
2542 {0xa0, 0xf0, ZC3XX_R10B_RGB01},
2543 {0xa0, 0xf0, ZC3XX_R10C_RGB02},
2544 {0xa0, 0xf0, ZC3XX_R10D_RGB10},
2545 {0xa0, 0x60, ZC3XX_R10E_RGB11},
2546 {0xa0, 0xf0, ZC3XX_R10F_RGB12},
2547 {0xa0, 0xf0, ZC3XX_R110_RGB20},
2548 {0xa0, 0xf0, ZC3XX_R111_RGB21},
2549 {0xa0, 0x60, ZC3XX_R112_RGB22},
2550 {0xa1, 0x01, 0x0180},
2551 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
2552 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2553 {0xaa, 0x25, 0x0007},
2554 {0xaa, 0x26, 0x0053},
2555 {0xaa, 0x27, 0x0000},
2556
2557 {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2f */
2558 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 9b */
2559 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 80 */
2560 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2561 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},
2562 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},
2563 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2564 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2565 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
2566 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2567 {0xa0, 0x13, ZC3XX_R1AA_DIGITALGAINSTEP},
2568 {0xa1, 0x01, 0x001d},
2569 {0xa1, 0x01, 0x001e},
2570 {0xa1, 0x01, 0x001f},
2571 {0xa1, 0x01, 0x0020},
2572 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
2573 {0xa1, 0x01, 0x0180},
2574 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2575 {}
2576};
2577
2578static const struct usb_action hv7131cxx_InitialScale[] = {
2579 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2580
2581 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* diff */
2582 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
2583 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2584 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2585 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2586
2587 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2588 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2589
2590 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2591 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2592 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2593 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 1e0 */
2594
2595 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2596 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2597 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2598 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2599 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2600 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2601 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2602 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2603 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2604 {0xaa, 0x01, 0x000c},
2605 {0xaa, 0x11, 0x0000},
2606 {0xaa, 0x13, 0x0000},
2607 {0xaa, 0x14, 0x0001},
2608 {0xaa, 0x15, 0x00e8},
2609 {0xaa, 0x16, 0x0002},
2610 {0xaa, 0x17, 0x0088},
2611
2612 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00 */
2613
2614 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2615 {0xa0, 0x89, ZC3XX_R18D_YTARGET},
2616 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
2617 {0xa0, 0x00, 0x01ad},
2618 {0xa0, 0xc0, 0x019b},
2619 {0xa0, 0xa0, 0x019c},
2620 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2621 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2622 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2623 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2624 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2625 {0xa1, 0x01, 0x0002},
2626 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
2627 /* read the i2c chips ident */
2628 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
2629 {0xa1, 0x01, 0x0091},
2630 {0xa1, 0x01, 0x0095},
2631 {0xa1, 0x01, 0x0096},
2632
2633 {0xa1, 0x01, 0x0008},
2634 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2635 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2636 {0xa1, 0x01, 0x01c8},
2637 {0xa1, 0x01, 0x01c9},
2638 {0xa1, 0x01, 0x01ca},
2639 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2640
2641 {0xa0, 0x60, ZC3XX_R10A_RGB00}, /* matrix */
2642 {0xa0, 0xf0, ZC3XX_R10B_RGB01},
2643 {0xa0, 0xf0, ZC3XX_R10C_RGB02},
2644 {0xa0, 0xf0, ZC3XX_R10D_RGB10},
2645 {0xa0, 0x60, ZC3XX_R10E_RGB11},
2646 {0xa0, 0xf0, ZC3XX_R10F_RGB12},
2647 {0xa0, 0xf0, ZC3XX_R110_RGB20},
2648 {0xa0, 0xf0, ZC3XX_R111_RGB21},
2649 {0xa0, 0x60, ZC3XX_R112_RGB22},
2650 {0xa1, 0x01, 0x0180},
2651 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
2652 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2653 {0xaa, 0x25, 0x0007},
2654 {0xaa, 0x26, 0x0053},
2655 {0xaa, 0x27, 0x0000},
2656
2657 {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2f */
2658 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 9b */
2659 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 80 */
2660
2661 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2662 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},
2663 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},
2664
2665 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2666 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2667 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
2668 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2669 {0xa0, 0x13, ZC3XX_R1AA_DIGITALGAINSTEP},
2670 {0xa1, 0x01, 0x001d},
2671 {0xa1, 0x01, 0x001e},
2672 {0xa1, 0x01, 0x001f},
2673 {0xa1, 0x01, 0x0020},
2674 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
2675 {0xa1, 0x01, 0x0180},
2676 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2677 {}
2678};
2679
2680static const struct usb_action icm105axx_Initial[] = {
2681 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2682 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
2683 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2684 {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
2685 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2686 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2687 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2688 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2689 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2690 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2691 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2692 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
2693 {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
2694 {0xa0, 0x01, ZC3XX_R098_WINYSTARTLOW},
2695 {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
2696 {0xa0, 0x01, ZC3XX_R09A_WINXSTARTLOW},
2697 {0xa0, 0x01, ZC3XX_R11A_FIRSTYLOW},
2698 {0xa0, 0x01, ZC3XX_R11C_FIRSTXLOW},
2699 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2700 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2701 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2702 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2703 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
2704 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2705 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2706 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2707 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2708 {0xaa, 0x01, 0x0010},
2709 {0xaa, 0x03, 0x0000},
2710 {0xaa, 0x04, 0x0001},
2711 {0xaa, 0x05, 0x0020},
2712 {0xaa, 0x06, 0x0001},
2713 {0xaa, 0x08, 0x0000},
2714 {0xaa, 0x03, 0x0001},
2715 {0xaa, 0x04, 0x0011},
2716 {0xaa, 0x05, 0x00a0},
2717 {0xaa, 0x06, 0x0001},
2718 {0xaa, 0x08, 0x0000},
2719 {0xaa, 0x03, 0x0002},
2720 {0xaa, 0x04, 0x0013},
2721 {0xaa, 0x05, 0x0020},
2722 {0xaa, 0x06, 0x0001},
2723 {0xaa, 0x08, 0x0000},
2724 {0xaa, 0x03, 0x0003},
2725 {0xaa, 0x04, 0x0015},
2726 {0xaa, 0x05, 0x0020},
2727 {0xaa, 0x06, 0x0005},
2728 {0xaa, 0x08, 0x0000},
2729 {0xaa, 0x03, 0x0004},
2730 {0xaa, 0x04, 0x0017},
2731 {0xaa, 0x05, 0x0020},
2732 {0xaa, 0x06, 0x000d},
2733 {0xaa, 0x08, 0x0000},
2734 {0xaa, 0x03, 0x0005},
2735 {0xaa, 0x04, 0x0019},
2736 {0xaa, 0x05, 0x0020},
2737 {0xaa, 0x06, 0x0005},
2738 {0xaa, 0x08, 0x0000},
2739 {0xaa, 0x03, 0x0006},
2740 {0xaa, 0x04, 0x0017},
2741 {0xaa, 0x05, 0x0026},
2742 {0xaa, 0x06, 0x0005},
2743 {0xaa, 0x08, 0x0000},
2744 {0xaa, 0x03, 0x0007},
2745 {0xaa, 0x04, 0x0019},
2746 {0xaa, 0x05, 0x0022},
2747 {0xaa, 0x06, 0x0005},
2748 {0xaa, 0x08, 0x0000},
2749 {0xaa, 0x03, 0x0008},
2750 {0xaa, 0x04, 0x0021},
2751 {0xaa, 0x05, 0x00aa},
2752 {0xaa, 0x06, 0x0005},
2753 {0xaa, 0x08, 0x0000},
2754 {0xaa, 0x03, 0x0009},
2755 {0xaa, 0x04, 0x0023},
2756 {0xaa, 0x05, 0x00aa},
2757 {0xaa, 0x06, 0x000d},
2758 {0xaa, 0x08, 0x0000},
2759 {0xaa, 0x03, 0x000a},
2760 {0xaa, 0x04, 0x0025},
2761 {0xaa, 0x05, 0x00aa},
2762 {0xaa, 0x06, 0x0005},
2763 {0xaa, 0x08, 0x0000},
2764 {0xaa, 0x03, 0x000b},
2765 {0xaa, 0x04, 0x00ec},
2766 {0xaa, 0x05, 0x002e},
2767 {0xaa, 0x06, 0x0005},
2768 {0xaa, 0x08, 0x0000},
2769 {0xaa, 0x03, 0x000c},
2770 {0xaa, 0x04, 0x00fa},
2771 {0xaa, 0x05, 0x002a},
2772 {0xaa, 0x06, 0x0005},
2773 {0xaa, 0x08, 0x0000},
2774 {0xaa, 0x07, 0x000d},
2775 {0xaa, 0x01, 0x0005},
2776 {0xaa, 0x94, 0x0002},
2777 {0xaa, 0x90, 0x0000},
2778 {0xaa, 0x91, 0x001f},
2779 {0xaa, 0x10, 0x0064},
2780 {0xaa, 0x9b, 0x00f0},
2781 {0xaa, 0x9c, 0x0002},
2782 {0xaa, 0x14, 0x001a},
2783 {0xaa, 0x20, 0x0080},
2784 {0xaa, 0x22, 0x0080},
2785 {0xaa, 0x24, 0x0080},
2786 {0xaa, 0x26, 0x0080},
2787 {0xaa, 0x00, 0x0084},
2788 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2789 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2790 {0xaa, 0xa8, 0x00c0},
2791 {0xa1, 0x01, 0x0002},
2792 {0xa1, 0x01, 0x0008},
2793 {0xa1, 0x01, 0x0180},
2794 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
2795 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2796 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2797 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2798 {0xa1, 0x01, 0x0008},
2799
2800 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2801 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2802 {0xa1, 0x01, 0x01c8},
2803 {0xa1, 0x01, 0x01c9},
2804 {0xa1, 0x01, 0x01ca},
2805 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2806 {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
2807 {0xa0, 0xf7, ZC3XX_R10B_RGB01},
2808 {0xa0, 0xf7, ZC3XX_R10C_RGB02},
2809 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
2810 {0xa0, 0x52, ZC3XX_R10E_RGB11},
2811 {0xa0, 0xf7, ZC3XX_R10F_RGB12},
2812 {0xa0, 0xf7, ZC3XX_R110_RGB20},
2813 {0xa0, 0xf7, ZC3XX_R111_RGB21},
2814 {0xa0, 0x52, ZC3XX_R112_RGB22},
2815 {0xa1, 0x01, 0x0180},
2816 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2817 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2818 {0xaa, 0x0d, 0x0003},
2819 {0xaa, 0x0c, 0x008c},
2820 {0xaa, 0x0e, 0x0095},
2821 {0xaa, 0x0f, 0x0002},
2822 {0xaa, 0x1c, 0x0094},
2823 {0xaa, 0x1d, 0x0002},
2824 {0xaa, 0x20, 0x0080},
2825 {0xaa, 0x22, 0x0080},
2826 {0xaa, 0x24, 0x0080},
2827 {0xaa, 0x26, 0x0080},
2828 {0xaa, 0x00, 0x0084},
2829 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
2830 {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW},
2831 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
2832 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
2833 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW},
2834 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2835 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
2836 {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW},
2837 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2838 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2839 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2840 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
2841 {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0},
2842 {0xa0, 0xec, ZC3XX_R01E_HSYNC_1},
2843 {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2},
2844 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
2845 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
2846 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN},
2847 {0xa0, 0xc0, ZC3XX_R11D_GLOBALGAIN},
2848 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2849 {0xa1, 0x01, 0x0180},
2850 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2851 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2852 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2853 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2854 {}
2855};
2856
2857static const struct usb_action icm105axx_InitialScale[] = {
2858 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2859 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2860 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2861 {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
2862 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2863 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2864 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2865 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2866 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2867 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2868 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2869 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
2870 {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
2871 {0xa0, 0x02, ZC3XX_R098_WINYSTARTLOW},
2872 {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
2873 {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW},
2874 {0xa0, 0x02, ZC3XX_R11A_FIRSTYLOW},
2875 {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW},
2876 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2877 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
2878 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2879 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
2880 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2881 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2882 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2883 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2884 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2885 {0xaa, 0x01, 0x0010},
2886 {0xaa, 0x03, 0x0000},
2887 {0xaa, 0x04, 0x0001},
2888 {0xaa, 0x05, 0x0020},
2889 {0xaa, 0x06, 0x0001},
2890 {0xaa, 0x08, 0x0000},
2891 {0xaa, 0x03, 0x0001},
2892 {0xaa, 0x04, 0x0011},
2893 {0xaa, 0x05, 0x00a0},
2894 {0xaa, 0x06, 0x0001},
2895 {0xaa, 0x08, 0x0000},
2896 {0xaa, 0x03, 0x0002},
2897 {0xaa, 0x04, 0x0013},
2898 {0xaa, 0x05, 0x0020},
2899 {0xaa, 0x06, 0x0001},
2900 {0xaa, 0x08, 0x0000},
2901 {0xaa, 0x03, 0x0003},
2902 {0xaa, 0x04, 0x0015},
2903 {0xaa, 0x05, 0x0020},
2904 {0xaa, 0x06, 0x0005},
2905 {0xaa, 0x08, 0x0000},
2906 {0xaa, 0x03, 0x0004},
2907 {0xaa, 0x04, 0x0017},
2908 {0xaa, 0x05, 0x0020},
2909 {0xaa, 0x06, 0x000d},
2910 {0xaa, 0x08, 0x0000},
2911 {0xaa, 0x03, 0x0005},
2912 {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
2913 {0xa0, 0x19, ZC3XX_R093_I2CSETVALUE},
2914 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
2915 {0xa1, 0x01, 0x0091},
2916 {0xaa, 0x05, 0x0020},
2917 {0xaa, 0x06, 0x0005},
2918 {0xaa, 0x08, 0x0000},
2919 {0xaa, 0x03, 0x0006},
2920 {0xaa, 0x04, 0x0017},
2921 {0xaa, 0x05, 0x0026},
2922 {0xaa, 0x06, 0x0005},
2923 {0xaa, 0x08, 0x0000},
2924 {0xaa, 0x03, 0x0007},
2925 {0xaa, 0x04, 0x0019},
2926 {0xaa, 0x05, 0x0022},
2927 {0xaa, 0x06, 0x0005},
2928 {0xaa, 0x08, 0x0000},
2929 {0xaa, 0x03, 0x0008},
2930 {0xaa, 0x04, 0x0021},
2931 {0xaa, 0x05, 0x00aa},
2932 {0xaa, 0x06, 0x0005},
2933 {0xaa, 0x08, 0x0000},
2934 {0xaa, 0x03, 0x0009},
2935 {0xaa, 0x04, 0x0023},
2936 {0xaa, 0x05, 0x00aa},
2937 {0xaa, 0x06, 0x000d},
2938 {0xaa, 0x08, 0x0000},
2939 {0xaa, 0x03, 0x000a},
2940 {0xaa, 0x04, 0x0025},
2941 {0xaa, 0x05, 0x00aa},
2942 {0xaa, 0x06, 0x0005},
2943 {0xaa, 0x08, 0x0000},
2944 {0xaa, 0x03, 0x000b},
2945 {0xaa, 0x04, 0x00ec},
2946 {0xaa, 0x05, 0x002e},
2947 {0xaa, 0x06, 0x0005},
2948 {0xaa, 0x08, 0x0000},
2949 {0xaa, 0x03, 0x000c},
2950 {0xaa, 0x04, 0x00fa},
2951 {0xaa, 0x05, 0x002a},
2952 {0xaa, 0x06, 0x0005},
2953 {0xaa, 0x08, 0x0000},
2954 {0xaa, 0x07, 0x000d},
2955 {0xaa, 0x01, 0x0005},
2956 {0xaa, 0x94, 0x0002},
2957 {0xaa, 0x90, 0x0000},
2958 {0xaa, 0x91, 0x0010},
2959 {0xaa, 0x10, 0x0064},
2960 {0xaa, 0x9b, 0x00f0},
2961 {0xaa, 0x9c, 0x0002},
2962 {0xaa, 0x14, 0x001a},
2963 {0xaa, 0x20, 0x0080},
2964 {0xaa, 0x22, 0x0080},
2965 {0xaa, 0x24, 0x0080},
2966 {0xaa, 0x26, 0x0080},
2967 {0xaa, 0x00, 0x0084},
2968 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2969 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2970 {0xaa, 0xa8, 0x0080},
2971 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
2972 {0xa1, 0x01, 0x0002},
2973 {0xa1, 0x01, 0x0008},
2974 {0xa1, 0x01, 0x0180},
2975 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
2976 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2977 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2978 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2979 {0xa1, 0x01, 0x0008},
2980
2981 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2982 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2983 {0xa1, 0x01, 0x01c8},
2984 {0xa1, 0x01, 0x01c9},
2985 {0xa1, 0x01, 0x01ca},
2986 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2987
2988 {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
2989 {0xa0, 0xf7, ZC3XX_R10B_RGB01},
2990 {0xa0, 0xf7, ZC3XX_R10C_RGB02},
2991 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
2992 {0xa0, 0x52, ZC3XX_R10E_RGB11},
2993 {0xa0, 0xf7, ZC3XX_R10F_RGB12},
2994 {0xa0, 0xf7, ZC3XX_R110_RGB20},
2995 {0xa0, 0xf7, ZC3XX_R111_RGB21},
2996 {0xa0, 0x52, ZC3XX_R112_RGB22},
2997 {0xa1, 0x01, 0x0180},
2998 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2999 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
3000 {0xaa, 0x0d, 0x0003},
3001 {0xaa, 0x0c, 0x0020},
3002 {0xaa, 0x0e, 0x000e},
3003 {0xaa, 0x0f, 0x0002},
3004 {0xaa, 0x1c, 0x000d},
3005 {0xaa, 0x1d, 0x0002},
3006 {0xaa, 0x20, 0x0080},
3007 {0xaa, 0x22, 0x0080},
3008 {0xaa, 0x24, 0x0080},
3009 {0xaa, 0x26, 0x0080},
3010 {0xaa, 0x00, 0x0084},
3011 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
3012 {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW},
3013 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3014 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
3015 {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW},
3016 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3017 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3018 {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW},
3019 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
3020 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
3021 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
3022 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
3023 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0},
3024 {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1},
3025 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2},
3026 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
3027 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
3028 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3029 {0xa1, 0x01, 0x0180},
3030 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3031 {0xa0, 0x40, ZC3XX_R116_RGAIN},
3032 {0xa0, 0x40, ZC3XX_R117_GGAIN},
3033 {0xa0, 0x40, ZC3XX_R118_BGAIN},
3034 {}
3035};
3036static const struct usb_action icm105a_50HZ[] = {
3037 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3038 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3039 {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */
3040 {0xaa, 0x0e, 0x000e}, /* 00,0e,0e,aa */
3041 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3042 {0xaa, 0x1c, 0x000d}, /* 00,1c,0d,aa */
3043 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3044 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3045 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3046 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3047 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3048 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3049 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3050 {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,0d,cc */
3051 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3052 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3053 {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,1a,cc */
3054 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3055 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3056 {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4b,cc */
3057 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3058 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3059 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
3060 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
3061 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
3062 {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d8,cc */
3063 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
3064 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3065 {}
3066};
3067static const struct usb_action icm105a_50HZScale[] = {
3068 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3069 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3070 {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */
3071 {0xaa, 0x0e, 0x0095}, /* 00,0e,95,aa */
3072 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3073 {0xaa, 0x1c, 0x0094}, /* 00,1c,94,aa */
3074 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3075 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3076 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3077 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3078 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3079 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3080 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3081 {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,94,cc */
3082 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3083 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3084 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
3085 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3086 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3087 {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,84,cc */
3088 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3089 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3090 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
3091 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
3092 {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e3,cc */
3093 {0xa0, 0xec, ZC3XX_R01E_HSYNC_1}, /* 00,1e,ec,cc */
3094 {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f5,cc */
3095 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3096 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
3097 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
3098 {}
3099};
3100static const struct usb_action icm105a_60HZ[] = {
3101 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3102 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3103 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
3104 {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
3105 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3106 {0xaa, 0x1c, 0x0008}, /* 00,1c,08,aa */
3107 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3108 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3109 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3110 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3111 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3112 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3113 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3114 {0xa0, 0x08, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,08,cc */
3115 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3116 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3117 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */
3118 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3119 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3120 {0xa0, 0x41, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,41,cc */
3121 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3122 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3123 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
3124 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
3125 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
3126 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
3127 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
3128 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3129 {}
3130};
3131static const struct usb_action icm105a_60HZScale[] = {
3132 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3133 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3134 {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */
3135 {0xaa, 0x0e, 0x0086}, /* 00,0e,86,aa */
3136 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3137 {0xaa, 0x1c, 0x0085}, /* 00,1c,85,aa */
3138 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3139 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3140 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3141 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3142 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3143 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3144 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3145 {0xa0, 0x85, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,85,cc */
3146 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3147 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3148 {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,08,cc */
3149 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3150 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3151 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */
3152 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3153 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3154 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
3155 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
3156 {0xa0, 0xc2, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c2,cc */
3157 {0xa0, 0xd6, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d6,cc */
3158 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
3159 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3160 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
3161 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
3162 {}
3163};
3164static const struct usb_action icm105a_NoFliker[] = {
3165 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3166 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3167 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
3168 {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
3169 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3170 {0xaa, 0x1c, 0x0000}, /* 00,1c,00,aa */
3171 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3172 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3173 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3174 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3175 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3176 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3177 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3178 {0xa0, 0x00, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,00,cc */
3179 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3180 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3181 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
3182 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3183 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3184 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
3185 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3186 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3187 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
3188 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
3189 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
3190 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
3191 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
3192 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3193 {}
3194};
3195static const struct usb_action icm105a_NoFlikerScale[] = {
3196 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3197 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3198 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
3199 {0xaa, 0x0e, 0x0081}, /* 00,0e,81,aa */
3200 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3201 {0xaa, 0x1c, 0x0080}, /* 00,1c,80,aa */
3202 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3203 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3204 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3205 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3206 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3207 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3208 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3209 {0xa0, 0x80, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,80,cc */
3210 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3211 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3212 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
3213 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3214 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3215 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
3216 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3217 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3218 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
3219 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
3220 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
3221 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
3222 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
3223 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3224 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
3225 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
3226 {}
3227};
3228
3229static const struct usb_action MC501CB_InitialScale[] = {
3230 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3231 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */
3232 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
3233 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3234 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
3235 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3236 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3237 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3238 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3239 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3240 {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
3241 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3242 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3243 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3244 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3245 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
3246 {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
3247 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
3248 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
3249 {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
3250 {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
3251 {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
3252 {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
3253 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3254 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
3255 {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
3256 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
3257 {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
3258 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3259 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
3260 {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
3261 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
3262 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3263 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
3264 {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
3265 {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
3266 {0xaa, 0x18, 0x00de}, /* 00,18,de,aa */
3267 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3268 {0xaa, 0x1a, 0x0086}, /* 00,1a,86,aa */
3269 {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
3270 {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
3271 {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
3272 {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
3273 {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
3274 {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
3275 {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
3276 {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
3277 {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
3278 {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
3279 {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
3280 {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
3281 {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
3282 {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
3283 {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
3284 {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
3285 {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
3286 {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
3287 {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
3288 {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
3289 {0xaa, 0xa0, ZC3XX_R01A_LASTFRAMESTATE}, /* 00,a0,1a,aa */
3290 {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
3291 {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
3292 {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
3293 {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
3294 {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
3295 {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
3296 {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
3297 {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
3298 {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
3299 {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
3300 {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
3301 {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
3302 {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
3303 {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
3304 {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
3305 {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
3306 {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
3307 {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
3308 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3309 {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
3310 {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
3311 {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
3312 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3313 {0xaa, 0x1c, 0x0050}, /* 00,1C,50,aa */
3314 {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
3315 {0xaa, 0x3b, 0x001d}, /* 00,3b,1D,aa */
3316 {0xaa, 0x3c, 0x004c}, /* 00,3c,4C,aa */
3317 {0xaa, 0x3d, 0x0018}, /* 00,3d,18,aa */
3318 {0xaa, 0x3e, 0x006a}, /* 00,3e,6A,aa */
3319 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
3320 {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
3321 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3322 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3323 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
3324 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3325 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3326 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3327 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3328 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3329 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3330 {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
3331 {0xaa, 0x51, 0x0027}, /* 00,51,27,aa */
3332 {0xaa, 0x52, 0x0020}, /* 00,52,20,aa */
3333 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3334 {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
3335 {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
3336 {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
3337 {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
3338 {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
3339 {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
3340
3341 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3342 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3343 {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
3344 {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
3345 {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
3346 {}
3347};
3348
3349static const struct usb_action MC501CB_Initial[] = { /* 320x240 */
3350 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3351 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
3352 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
3353 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3354 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
3355 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3356 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3357 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3358 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3359 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3360 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
3361 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3362 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3363 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3364 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3365 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
3366 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */
3367 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
3368 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
3369 {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
3370 {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
3371 {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
3372 {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
3373 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3374 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
3375 {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
3376 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
3377 {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
3378 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3379 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
3380 {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
3381 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
3382 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3383 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
3384 {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
3385 {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
3386 {0xaa, 0x18, 0x00d8}, /* 00,18,d8,aa */
3387 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3388 {0xaa, 0x1a, 0x0088}, /* 00,1a,88,aa */
3389 {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
3390 {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
3391 {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
3392 {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
3393 {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
3394 {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
3395 {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
3396 {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
3397 {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
3398 {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
3399 {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
3400 {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
3401 {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
3402 {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
3403 {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
3404 {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
3405 {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
3406 {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
3407 {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
3408 {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
3409 {0xaa, 0xa0, ZC3XX_R01A_LASTFRAMESTATE}, /* 00,a0,1a,aa */
3410 {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
3411 {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
3412 {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
3413 {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
3414 {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
3415 {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
3416 {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
3417 {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
3418 {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
3419 {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
3420 {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
3421 {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
3422 {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
3423 {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
3424 {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
3425 {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
3426 {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
3427 {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
3428 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3429 {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
3430 {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
3431 {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
3432 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3433 {0xaa, 0x1c, 0x0050}, /* 00,1c,50,aa */
3434 {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
3435 {0xaa, 0x3b, 0x003a}, /* 00,3b,3A,aa */
3436 {0xaa, 0x3c, 0x0098}, /* 00,3c,98,aa */
3437 {0xaa, 0x3d, 0x0030}, /* 00,3d,30,aa */
3438 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3439 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
3440 {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
3441 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3442 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3443 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
3444 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3445 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3446 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3447 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3448 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3449 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3450 {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
3451 {0xaa, 0x51, 0x004e}, /* 00,51,4E,aa */
3452 {0xaa, 0x52, 0x0041}, /* 00,52,41,aa */
3453 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3454 {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
3455 {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
3456 {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
3457 {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
3458 {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
3459 {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
3460 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3461 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3462 {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
3463 {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
3464 {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
3465 {}
3466};
3467
3468static const struct usb_action MC501CB_50HZ[] = {
3469 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3470 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3471 {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
3472 {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
3473 {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
3474 {0xaa, 0x3c, 0x004c}, /* 00,3C,4C,aa */
3475 {0xaa, 0x3d, 0x001d}, /* 00,3D,1D,aa */
3476 {0xaa, 0x3e, 0x004c}, /* 00,3E,4C,aa */
3477 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3478 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3479 {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */
3480 {0xaa, 0x37, 0x0098}, /* 00,37,98,aa */
3481 {0xaa, 0x3b, 0x003a}, /* 00,3B,3A,aa */
3482 {}
3483};
3484
3485static const struct usb_action MC501CB_50HZScale[] = {
3486 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3487 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3488 {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */
3489 {0xaa, 0x37, 0x0098}, /* 00,37,98,aa */
3490 {0xaa, 0x3b, 0x003a}, /* 00,3B,3A,aa */
3491 {0xaa, 0x3c, 0x0098}, /* 00,3C,98,aa */
3492 {0xaa, 0x3d, 0x003a}, /* 00,3D,3A,aa */
3493 {0xaa, 0x3e, 0x0098}, /* 00,3E,98,aa */
3494 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3495 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3496 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3497 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3498 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3499 {}
3500};
3501
3502static const struct usb_action MC501CB_60HZ[] = {
3503 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3504 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3505 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3506 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3507 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3508 {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
3509 {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
3510 {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
3511 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3512 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3513 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3514 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3515 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3516 {}
3517};
3518
3519static const struct usb_action MC501CB_60HZScale[] = {
3520 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3521 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3522 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3523 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3524 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3525 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3526 {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
3527 {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
3528 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3529 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3530 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3531 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3532 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3533 {}
3534};
3535
3536static const struct usb_action MC501CB_NoFliker[] = {
3537 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3538 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3539 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3540 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3541 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3542 {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
3543 {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
3544 {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
3545 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3546 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3547 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3548 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3549 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3550 {}
3551};
3552
3553static const struct usb_action MC501CB_NoFlikerScale[] = {
3554 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3555 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3556 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3557 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3558 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3559 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3560 {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
3561 {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
3562 {}
3563};
3564
3565/* from zs211.inf - HKR,%OV7620%,Initial - 640x480 */
3566static const struct usb_action OV7620_mode0[] = {
3567 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3568 {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */
3569 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
3570 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3571 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
3572 {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
3573 {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */
3574 {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */
3575 {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */
3576 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */
3577 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
3578 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3579 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3580 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3581 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3582 {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
3583 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3584 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3585 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3586 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3587 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3588 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3589 {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
3590 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
3591 {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
3592 {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
3593 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3594 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3595 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
3596 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
3597 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3598 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
3599 {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
3600 {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
3601 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3602 {0xaa, 0x1a, 0x00f1}, /* 00,1a,f1,aa */
3603 {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
3604 {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
3605 {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
3606 {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
3607 {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
3608 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
3609 {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
3610 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3611 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3612 {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
3613 {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
3614 {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
3615 {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
3616 {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
3617 {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
3618 {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
3619 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
3620 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3621 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3622 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3623 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3624 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3625 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3626 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3627 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3628 {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */
3629 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
3630 {0xa0, 0x40, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,40,cc */
3631 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3632 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
3633 {}
3634};
3635
3636/* from zs211.inf - HKR,%OV7620%,InitialScale - 320x240 */
3637static const struct usb_action OV7620_mode1[] = {
3638 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3639 {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, /* 00,02,50,cc */
3640 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
3641 /* mx change? */
3642 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3643 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
3644 {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
3645 {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */
3646 {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */
3647 {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */
3648 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */
3649 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
3650 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3651 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3652 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3653 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3654 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
3655 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3656 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3657 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3658 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3659 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3660 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3661 {0xa0, 0xd6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d6,cc */
3662 /* OV7648 00,9c,d8,cc */
3663 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
3664 {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
3665 {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
3666 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3667 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3668 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
3669 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
3670 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3671 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
3672 {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
3673 {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
3674 {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
3675 {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
3676 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3677 {0xaa, 0x1a, 0x00f2}, /* 00,1a,f2,aa */
3678 {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
3679 {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
3680 {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
3681 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
3682 {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
3683 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3684 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3685 {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
3686 {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
3687 {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
3688 {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
3689 {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
3690 {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
3691 {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
3692 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
3693 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3694 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3695 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3696 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3697 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3698 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3699 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3700 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3701 {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */
3702 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
3703 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,50,cc */
3704 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3705 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
3706 {}
3707};
3708
3709/* from zs211.inf - HKR,%OV7620%\AE,50HZ */
3710static const struct usb_action OV7620_50HZ[] = {
3711 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3712 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3713 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3714 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3715 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3716 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3717 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3718 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3719 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3720 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3721 {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
3722 {0xaa, 0x10, 0x0082}, /* 00,10,82,aa */
3723 {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */
3724/* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc
3725 if mode0 (640x480) */
3726 {}
3727};
3728
3729/* from zs211.inf - HKR,%OV7620%\AE,60HZ */
3730static const struct usb_action OV7620_60HZ[] = {
3731 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3732 /* (bug in zs211.inf) */
3733 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3734 {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
3735 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3736 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3737 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3738 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3739 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3740 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3741 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3742 {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
3743 {0xaa, 0x10, 0x0020}, /* 00,10,20,aa */
3744 {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */
3745/* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc
3746 * if mode0 (640x480) */
3747/* ?? in gspca v1, it was
3748 {0xa0, 0x00, 0x0039}, * 00,00,00,dd *
3749 {0xa1, 0x01, 0x0037}, */
3750 {}
3751};
3752
3753/* from zs211.inf - HKR,%OV7620%\AE,NoFliker */
3754static const struct usb_action OV7620_NoFliker[] = {
3755 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3756 /* (bug in zs211.inf) */
3757 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3758 {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
3759 {0xaa, 0x75, 0x008e}, /* 00,75,8e,aa */
3760 {0xaa, 0x2d, 0x0001}, /* 00,2d,01,aa */
3761 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3762 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3763 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3764 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3765 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3766 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,01,cc */
3767/* {0xa0, 0x44, ZC3XX_R002_CLOCKSELECT}, * 00,02,44,cc
3768 - if mode1 (320x240) */
3769/* ?? was
3770 {0xa0, 0x00, 0x0039}, * 00,00,00,dd *
3771 {0xa1, 0x01, 0x0037}, */
3772 {}
3773};
3774
3775static const struct usb_action ov7630c_Initial[] = {
3776 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3777 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
3778 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3779 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
3780 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3781 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3782 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
3783 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
3784 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3785 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
3786 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
3787 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
3788 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
3789 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3790 {0xaa, 0x12, 0x0080},
3791 {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
3792 {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
3793 {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
3794 {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
3795 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
3796 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
3797 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
3798 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3799 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
3800 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},
3801 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
3802 {0xaa, 0x12, 0x0069},
3803 {0xaa, 0x04, 0x0020},
3804 {0xaa, 0x06, 0x0050},
3805 {0xaa, 0x13, 0x0083},
3806 {0xaa, 0x14, 0x0000},
3807 {0xaa, 0x15, 0x0024},
3808 {0xaa, 0x17, 0x0018},
3809 {0xaa, 0x18, 0x00ba},
3810 {0xaa, 0x19, 0x0002},
3811 {0xaa, 0x1a, 0x00f6},
3812 {0xaa, 0x1b, 0x0002},
3813 {0xaa, 0x20, 0x00c2},
3814 {0xaa, 0x24, 0x0060},
3815 {0xaa, 0x25, 0x0040},
3816 {0xaa, 0x26, 0x0030},
3817 {0xaa, 0x27, 0x00ea},
3818 {0xaa, 0x28, 0x00a0},
3819 {0xaa, 0x21, 0x0000},
3820 {0xaa, 0x2a, 0x0081},
3821 {0xaa, 0x2b, 0x0096},
3822 {0xaa, 0x2d, 0x0094},
3823 {0xaa, 0x2f, 0x003d},
3824 {0xaa, 0x30, 0x0024},
3825 {0xaa, 0x60, 0x0000},
3826 {0xaa, 0x61, 0x0040},
3827 {0xaa, 0x68, 0x007c},
3828 {0xaa, 0x6f, 0x0015},
3829 {0xaa, 0x75, 0x0088},
3830 {0xaa, 0x77, 0x00b5},
3831 {0xaa, 0x01, 0x0060},
3832 {0xaa, 0x02, 0x0060},
3833 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
3834 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
3835 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3836 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3837 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
3838 {0xa0, 0x00, 0x01ad},
3839 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3840 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3841 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3842 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3843 {0xa0, 0x60, ZC3XX_R116_RGAIN},
3844 {0xa0, 0x46, ZC3XX_R118_BGAIN},
3845 {0xa0, 0x04, ZC3XX_R113_RGB03},
3846/* 0x10, */
3847 {0xa1, 0x01, 0x0002},
3848 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
3849 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
3850 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
3851 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
3852 {0xa0, 0x50, ZC3XX_R10E_RGB11},
3853 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
3854 {0xa0, 0xf8, ZC3XX_R110_RGB20},
3855 {0xa0, 0xf8, ZC3XX_R111_RGB21},
3856 {0xa0, 0x50, ZC3XX_R112_RGB22},
3857/* 0x03, */
3858 {0xa1, 0x01, 0x0008},
3859 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
3860 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
3861 {0xa1, 0x01, 0x01c8},
3862 {0xa1, 0x01, 0x01c9},
3863 {0xa1, 0x01, 0x01ca},
3864 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
3865 {0xa0, 0x01, ZC3XX_R120_GAMMA00}, /* gamma 2 ?*/
3866 {0xa0, 0x0c, ZC3XX_R121_GAMMA01},
3867 {0xa0, 0x1f, ZC3XX_R122_GAMMA02},
3868 {0xa0, 0x3a, ZC3XX_R123_GAMMA03},
3869 {0xa0, 0x53, ZC3XX_R124_GAMMA04},
3870 {0xa0, 0x6d, ZC3XX_R125_GAMMA05},
3871 {0xa0, 0x85, ZC3XX_R126_GAMMA06},
3872 {0xa0, 0x9c, ZC3XX_R127_GAMMA07},
3873 {0xa0, 0xb0, ZC3XX_R128_GAMMA08},
3874 {0xa0, 0xc2, ZC3XX_R129_GAMMA09},
3875 {0xa0, 0xd1, ZC3XX_R12A_GAMMA0A},
3876 {0xa0, 0xde, ZC3XX_R12B_GAMMA0B},
3877 {0xa0, 0xe9, ZC3XX_R12C_GAMMA0C},
3878 {0xa0, 0xf2, ZC3XX_R12D_GAMMA0D},
3879 {0xa0, 0xf9, ZC3XX_R12E_GAMMA0E},
3880 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
3881 {0xa0, 0x05, ZC3XX_R130_GAMMA10},
3882 {0xa0, 0x0f, ZC3XX_R131_GAMMA11},
3883 {0xa0, 0x16, ZC3XX_R132_GAMMA12},
3884 {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
3885 {0xa0, 0x19, ZC3XX_R134_GAMMA14},
3886 {0xa0, 0x19, ZC3XX_R135_GAMMA15},
3887 {0xa0, 0x17, ZC3XX_R136_GAMMA16},
3888 {0xa0, 0x15, ZC3XX_R137_GAMMA17},
3889 {0xa0, 0x12, ZC3XX_R138_GAMMA18},
3890 {0xa0, 0x10, ZC3XX_R139_GAMMA19},
3891 {0xa0, 0x0e, ZC3XX_R13A_GAMMA1A},
3892 {0xa0, 0x0b, ZC3XX_R13B_GAMMA1B},
3893 {0xa0, 0x09, ZC3XX_R13C_GAMMA1C},
3894 {0xa0, 0x08, ZC3XX_R13D_GAMMA1D},
3895 {0xa0, 0x06, ZC3XX_R13E_GAMMA1E},
3896 {0xa0, 0x03, ZC3XX_R13F_GAMMA1F},
3897 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
3898 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
3899 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
3900 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
3901 {0xa0, 0x50, ZC3XX_R10E_RGB11},
3902 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
3903 {0xa0, 0xf8, ZC3XX_R110_RGB20},
3904 {0xa0, 0xf8, ZC3XX_R111_RGB21},
3905 {0xa0, 0x50, ZC3XX_R112_RGB22},
3906
3907 {0xa1, 0x01, 0x0180},
3908 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
3909 {0xaa, 0x10, 0x001b},
3910 {0xaa, 0x76, 0x0002},
3911 {0xaa, 0x2a, 0x0081},
3912 {0xaa, 0x2b, 0x0000},
3913 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3914 {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID},
3915 {0xa0, 0xb8, ZC3XX_R192_EXPOSURELIMITLOW},
3916 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3917 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3918 {0xa0, 0x37, ZC3XX_R197_ANTIFLICKERLOW},
3919 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
3920 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
3921 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
3922 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
3923 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
3924 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
3925 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
3926 {0xaa, 0x13, 0x0083}, /* 40 */
3927 {0xa1, 0x01, 0x0180},
3928 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3929 {}
3930};
3931
3932static const struct usb_action ov7630c_InitialScale[] = {
3933 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3934 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
3935 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3936 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3937 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
3938 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
3939 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3940 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
3941 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
3942 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
3943 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
3944 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3945
3946 {0xaa, 0x12, 0x0080},
3947 {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
3948 {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
3949 {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
3950 {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
3951 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
3952 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
3953 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
3954 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3955 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
3956 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
3957 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
3958 {0xaa, 0x12, 0x0069}, /* i2c */
3959 {0xaa, 0x04, 0x0020},
3960 {0xaa, 0x06, 0x0050},
3961 {0xaa, 0x13, 0x00c3},
3962 {0xaa, 0x14, 0x0000},
3963 {0xaa, 0x15, 0x0024},
3964 {0xaa, 0x19, 0x0003},
3965 {0xaa, 0x1a, 0x00f6},
3966 {0xaa, 0x1b, 0x0002},
3967 {0xaa, 0x20, 0x00c2},
3968 {0xaa, 0x24, 0x0060},
3969 {0xaa, 0x25, 0x0040},
3970 {0xaa, 0x26, 0x0030},
3971 {0xaa, 0x27, 0x00ea},
3972 {0xaa, 0x28, 0x00a0},
3973 {0xaa, 0x21, 0x0000},
3974 {0xaa, 0x2a, 0x0081},
3975 {0xaa, 0x2b, 0x0096},
3976 {0xaa, 0x2d, 0x0084},
3977 {0xaa, 0x2f, 0x003d},
3978 {0xaa, 0x30, 0x0024},
3979 {0xaa, 0x60, 0x0000},
3980 {0xaa, 0x61, 0x0040},
3981 {0xaa, 0x68, 0x007c},
3982 {0xaa, 0x6f, 0x0015},
3983 {0xaa, 0x75, 0x0088},
3984 {0xaa, 0x77, 0x00b5},
3985 {0xaa, 0x01, 0x0060},
3986 {0xaa, 0x02, 0x0060},
3987 {0xaa, 0x17, 0x0018},
3988 {0xaa, 0x18, 0x00ba},
3989 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
3990 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
3991 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3992 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3993 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
3994 {0xa0, 0x00, 0x01ad},
3995 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3996 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3997 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3998 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3999 {0xa0, 0x60, ZC3XX_R116_RGAIN},
4000 {0xa0, 0x46, ZC3XX_R118_BGAIN},
4001 {0xa0, 0x04, ZC3XX_R113_RGB03},
4002
4003 {0xa1, 0x01, 0x0002},
4004 {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
4005 {0xa0, 0xfe, ZC3XX_R10B_RGB01},
4006 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
4007 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
4008 {0xa0, 0x4d, ZC3XX_R10E_RGB11},
4009 {0xa0, 0xfc, ZC3XX_R10F_RGB12},
4010 {0xa0, 0x00, ZC3XX_R110_RGB20},
4011 {0xa0, 0xf6, ZC3XX_R111_RGB21},
4012 {0xa0, 0x4a, ZC3XX_R112_RGB22},
4013
4014 {0xa1, 0x01, 0x0008},
4015 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
4016 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4017 {0xa1, 0x01, 0x01c8},
4018 {0xa1, 0x01, 0x01c9},
4019 {0xa1, 0x01, 0x01ca},
4020 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4021 {0xa0, 0x16, ZC3XX_R120_GAMMA00}, /* gamma ~4 */
4022 {0xa0, 0x3a, ZC3XX_R121_GAMMA01},
4023 {0xa0, 0x5b, ZC3XX_R122_GAMMA02},
4024 {0xa0, 0x7c, ZC3XX_R123_GAMMA03},
4025 {0xa0, 0x94, ZC3XX_R124_GAMMA04},
4026 {0xa0, 0xa9, ZC3XX_R125_GAMMA05},
4027 {0xa0, 0xbb, ZC3XX_R126_GAMMA06},
4028 {0xa0, 0xca, ZC3XX_R127_GAMMA07},
4029 {0xa0, 0xd7, ZC3XX_R128_GAMMA08},
4030 {0xa0, 0xe1, ZC3XX_R129_GAMMA09},
4031 {0xa0, 0xea, ZC3XX_R12A_GAMMA0A},
4032 {0xa0, 0xf1, ZC3XX_R12B_GAMMA0B},
4033 {0xa0, 0xf7, ZC3XX_R12C_GAMMA0C},
4034 {0xa0, 0xfc, ZC3XX_R12D_GAMMA0D},
4035 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
4036 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
4037 {0xa0, 0x20, ZC3XX_R130_GAMMA10},
4038 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
4039 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
4040 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
4041 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
4042 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
4043 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
4044 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
4045 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
4046 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
4047 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
4048 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
4049 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
4050 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
4051 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
4052 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
4053 {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
4054 {0xa0, 0xfe, ZC3XX_R10B_RGB01},
4055 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
4056 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
4057 {0xa0, 0x4d, ZC3XX_R10E_RGB11},
4058 {0xa0, 0xfc, ZC3XX_R10F_RGB12},
4059 {0xa0, 0x00, ZC3XX_R110_RGB20},
4060 {0xa0, 0xf6, ZC3XX_R111_RGB21},
4061 {0xa0, 0x4a, ZC3XX_R112_RGB22},
4062
4063 {0xa1, 0x01, 0x0180},
4064 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4065 {0xaa, 0x10, 0x000d},
4066 {0xaa, 0x76, 0x0002},
4067 {0xaa, 0x2a, 0x0081},
4068 {0xaa, 0x2b, 0x0000},
4069 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4070 {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
4071 {0xa0, 0xd8, ZC3XX_R192_EXPOSURELIMITLOW},
4072 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4073 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4074 {0xa0, 0x1b, ZC3XX_R197_ANTIFLICKERLOW},
4075 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
4076 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
4077 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
4078 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
4079 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
4080 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
4081 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
4082 {0xaa, 0x13, 0x00c3},
4083
4084 {0xa1, 0x01, 0x0180},
4085 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4086 {}
4087};
4088
4089static const struct usb_action pas106b_Initial_com[] = {
4090/* Sream and Sensor specific */
4091 {0xa1, 0x01, 0x0010}, /* CMOSSensorSelect */
4092/* System */
4093 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
4094 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
4095/* Picture size */
4096 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* ClockSelect */
4097 {0xa0, 0x03, 0x003a},
4098 {0xa0, 0x0c, 0x003b},
4099 {0xa0, 0x04, 0x0038},
4100 {}
4101};
4102
4103static const struct usb_action pas106b_Initial[] = { /* 176x144 */
4104/* JPEG control */
4105 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4106/* Sream and Sensor specific */
4107 {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT}, /* CMOSSensorSelect */
4108/* Picture size */
4109 {0xa0, 0x00, ZC3XX_R003_FRAMEWIDTHHIGH}, /* FrameWidthHigh 00 */
4110 {0xa0, 0xb0, ZC3XX_R004_FRAMEWIDTHLOW}, /* FrameWidthLow B0 */
4111 {0xa0, 0x00, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* FrameHeightHigh 00 */
4112 {0xa0, 0x90, ZC3XX_R006_FRAMEHEIGHTLOW}, /* FrameHightLow 90 */
4113/* System */
4114 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* SystemOperating */
4115/* Sream and Sensor specific */
4116 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
4117 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
4118/* Sensor Interface */
4119 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* Compatibily Mode */
4120/* Window inside sensor array */
4121 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, /* WinXStartLow */
4122 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* FirstYLow */
4123 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, /* FirstxLow */
4124 {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW}, /* WinHeightLow */
4125 {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW}, /* WinWidthLow */
4126/* Init the sensor */
4127 {0xaa, 0x02, 0x0004},
4128 {0xaa, 0x08, 0x0000},
4129 {0xaa, 0x09, 0x0005},
4130 {0xaa, 0x0a, 0x0002},
4131 {0xaa, 0x0b, 0x0002},
4132 {0xaa, 0x0c, 0x0005},
4133 {0xaa, 0x0d, 0x0000},
4134 {0xaa, 0x0e, 0x0002},
4135 {0xaa, 0x14, 0x0081},
4136
4137/* Other registors */
4138 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* SensorCorrection */
4139/* Frame retreiving */
4140 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* AutoAdjustFPS */
4141/* Gains */
4142 {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN}, /* DigitalGain */
4143/* Unknown */
4144 {0xa0, 0x00, 0x01ad},
4145/* Sharpness */
4146 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* SharpnessMode */
4147 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* Sharpness05 */
4148/* Other registors */
4149 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
4150/* Auto exposure and white balance */
4151 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* AWBStatus */
4152/*Dead pixels */
4153 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
4154/* EEPROM */
4155 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* EEPROMAccess */
4156/* JPEG control */
4157 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4158 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4159 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4160/* Other registers */
4161 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
4162/* Auto exposure and white balance */
4163 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* AWBStatus */
4164/*Dead pixels */
4165 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
4166/* EEPROM */
4167 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* EEPROMAccess */
4168/* JPEG control */
4169 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4170 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4171 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4172
4173 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
4174 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
4175 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
4176 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
4177 {0xa0, 0x58, ZC3XX_R10E_RGB11},
4178 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
4179 {0xa0, 0xf4, ZC3XX_R110_RGB20},
4180 {0xa0, 0xf4, ZC3XX_R111_RGB21},
4181 {0xa0, 0x58, ZC3XX_R112_RGB22},
4182/* Auto correction */
4183 {0xa0, 0x03, ZC3XX_R181_WINXSTART}, /* WinXstart */
4184 {0xa0, 0x08, ZC3XX_R182_WINXWIDTH}, /* WinXWidth */
4185 {0xa0, 0x16, ZC3XX_R183_WINXCENTER}, /* WinXCenter */
4186 {0xa0, 0x03, ZC3XX_R184_WINYSTART}, /* WinYStart */
4187 {0xa0, 0x05, ZC3XX_R185_WINYWIDTH}, /* WinYWidth */
4188 {0xa0, 0x14, ZC3XX_R186_WINYCENTER}, /* WinYCenter */
4189 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4190
4191/* Auto exposure and white balance */
4192 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* ExposureLimitHigh */
4193 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* ExposureLimitMid */
4194 {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW}, /* ExposureLimitLow */
4195 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* AntiFlickerHigh */
4196 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* AntiFlickerLow */
4197 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* AntiFlickerLow */
4198 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* AEBFreeze */
4199 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* AEBUnfreeze */
4200/* sensor on */
4201 {0xaa, 0x07, 0x00b1},
4202 {0xaa, 0x05, 0x0003},
4203 {0xaa, 0x04, 0x0001},
4204 {0xaa, 0x03, 0x003b},
4205/* Gains */
4206 {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* DigitalLimitDiff */
4207 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* DigitalGainStep */
4208 {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, /* GlobalGain */
4209 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* GlobalGain */
4210/* Auto correction */
4211 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4212 {0xa1, 0x01, 0x0180}, /* AutoCorrectEnable */
4213 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4214/* Gains */
4215 {0xa0, 0x40, ZC3XX_R116_RGAIN}, /* RGain */
4216 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* GGain */
4217 {0xa0, 0x40, ZC3XX_R118_BGAIN}, /* BGain */
4218 {}
4219};
4220
4221static const struct usb_action pas106b_InitialScale[] = { /* 352x288 */
4222/* JPEG control */
4223 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4224/* Sream and Sensor specific */
4225 {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT}, /* CMOSSensorSelect */
4226/* Picture size */
4227 {0xa0, 0x01, ZC3XX_R003_FRAMEWIDTHHIGH}, /* FrameWidthHigh */
4228 {0xa0, 0x60, ZC3XX_R004_FRAMEWIDTHLOW}, /* FrameWidthLow */
4229 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* FrameHeightHigh */
4230 {0xa0, 0x20, ZC3XX_R006_FRAMEHEIGHTLOW}, /* FrameHightLow */
4231/* System */
4232 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* SystemOperating */
4233/* Sream and Sensor specific */
4234 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
4235 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
4236/* Sensor Interface */
4237 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* Compatibily Mode */
4238/* Window inside sensor array */
4239 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, /* WinXStartLow */
4240 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* FirstYLow */
4241 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, /* FirstxLow */
4242 {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW}, /* WinHeightLow */
4243 {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW}, /* WinWidthLow */
4244/* Init the sensor */
4245 {0xaa, 0x02, 0x0004},
4246 {0xaa, 0x08, 0x0000},
4247 {0xaa, 0x09, 0x0005},
4248 {0xaa, 0x0a, 0x0002},
4249 {0xaa, 0x0b, 0x0002},
4250 {0xaa, 0x0c, 0x0005},
4251 {0xaa, 0x0d, 0x0000},
4252 {0xaa, 0x0e, 0x0002},
4253 {0xaa, 0x14, 0x0081},
4254
4255/* Other registors */
4256 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* SensorCorrection */
4257/* Frame retreiving */
4258 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* AutoAdjustFPS */
4259/* Gains */
4260 {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN}, /* DigitalGain */
4261/* Unknown */
4262 {0xa0, 0x00, 0x01ad},
4263/* Sharpness */
4264 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* SharpnessMode */
4265 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* Sharpness05 */
4266/* Other registors */
4267 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
4268/* Auto exposure and white balance */
4269 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* AWBStatus */
4270 {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* ????????? */
4271/*Dead pixels */
4272 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
4273/* EEPROM */
4274 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* EEPROMAccess */
4275/* JPEG control */
4276 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4277 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4278 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4279/* Other registers */
4280 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
4281/* Auto exposure and white balance */
4282 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* AWBStatus */
4283/*Dead pixels */
4284 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
4285/* EEPROM */
4286 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* EEPROMAccess */
4287/* JPEG control */
4288 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4289 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4290 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4291
4292 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
4293 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
4294 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
4295 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
4296 {0xa0, 0x58, ZC3XX_R10E_RGB11},
4297 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
4298 {0xa0, 0xf4, ZC3XX_R110_RGB20},
4299 {0xa0, 0xf4, ZC3XX_R111_RGB21},
4300 {0xa0, 0x58, ZC3XX_R112_RGB22},
4301/* Auto correction */
4302 {0xa0, 0x03, ZC3XX_R181_WINXSTART}, /* WinXstart */
4303 {0xa0, 0x08, ZC3XX_R182_WINXWIDTH}, /* WinXWidth */
4304 {0xa0, 0x16, ZC3XX_R183_WINXCENTER}, /* WinXCenter */
4305 {0xa0, 0x03, ZC3XX_R184_WINYSTART}, /* WinYStart */
4306 {0xa0, 0x05, ZC3XX_R185_WINYWIDTH}, /* WinYWidth */
4307 {0xa0, 0x14, ZC3XX_R186_WINYCENTER}, /* WinYCenter */
4308 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4309
4310/* Auto exposure and white balance */
4311 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* ExposureLimitHigh 0 */
4312 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* ExposureLimitMid */
4313 {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW}, /* ExposureLimitLow 0xb1 */
4314
4315 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* AntiFlickerHigh 0x00 */
4316 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* AntiFlickerLow 0x00 */
4317 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* AntiFlickerLow 0x87 */
4318
4319 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* AEBFreeze 0x10 0x0c */
4320 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* AEBUnfreeze 0x30 0x18 */
4321/* sensor on */
4322 {0xaa, 0x07, 0x00b1},
4323 {0xaa, 0x05, 0x0003},
4324 {0xaa, 0x04, 0x0001},
4325 {0xaa, 0x03, 0x003b},
4326/* Gains */
4327 {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* DigitalLimitDiff */
4328 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* DigitalGainStep */
4329 {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, /* GlobalGain */
4330 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* GlobalGain */
4331/* Auto correction */
4332 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4333 {0xa1, 0x01, 0x0180}, /* AutoCorrectEnable */
4334 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4335/* Gains */
4336 {0xa0, 0x40, ZC3XX_R116_RGAIN}, /* RGain */
4337 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* GGain */
4338 {0xa0, 0x40, ZC3XX_R118_BGAIN}, /* BGain */
4339
4340 {0xa0, 0x00, 0x0007}, /* AutoCorrectEnable */
4341 {0xa0, 0xff, ZC3XX_R018_FRAMELOST}, /* Frame adjust */
4342 {}
4343};
4344static const struct usb_action pas106b_50HZ[] = {
4345 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4346 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
4347 {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,54,cc */
4348 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4349 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4350 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,87,cc */
4351 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4352 {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,30,cc */
4353 {0xaa, 0x03, 0x0021}, /* 00,03,21,aa */
4354 {0xaa, 0x04, 0x000c}, /* 00,04,0c,aa */
4355 {0xaa, 0x05, 0x0002}, /* 00,05,02,aa */
4356 {0xaa, 0x07, 0x001c}, /* 00,07,1c,aa */
4357 {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
4358 {}
4359};
4360static const struct usb_action pas106b_60HZ[] = {
4361 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4362 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
4363 {0xa0, 0x2e, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,2e,cc */
4364 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4365 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4366 {0xa0, 0x71, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,71,cc */
4367 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4368 {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,30,cc */
4369 {0xaa, 0x03, 0x001c}, /* 00,03,1c,aa */
4370 {0xaa, 0x04, 0x0004}, /* 00,04,04,aa */
4371 {0xaa, 0x05, 0x0001}, /* 00,05,01,aa */
4372 {0xaa, 0x07, 0x00c4}, /* 00,07,c4,aa */
4373 {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
4374 {}
4375};
4376static const struct usb_action pas106b_NoFliker[] = {
4377 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4378 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
4379 {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc */
4380 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4381 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4382 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
4383 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4384 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4385 {0xaa, 0x03, 0x0013}, /* 00,03,13,aa */
4386 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
4387 {0xaa, 0x05, 0x0001}, /* 00,05,01,aa */
4388 {0xaa, 0x07, 0x0030}, /* 00,07,30,aa */
4389 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
4390 {}
4391};
4392
4393static const struct usb_action pb03303x_Initial[] = {
4394 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4395 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4396 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4397 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4398 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4399 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4400 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4401 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4402 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, /* 8b -> dc */
4403 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4404 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
4405 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
4406 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4407 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4408 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4409 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4410 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4411 {0xaa, 0x01, 0x0001},
4412 {0xaa, 0x06, 0x0000},
4413 {0xaa, 0x08, 0x0483},
4414 {0xaa, 0x01, 0x0004},
4415 {0xaa, 0x08, 0x0006},
4416 {0xaa, 0x02, 0x0011},
4417 {0xaa, 0x03, 0x01e7},
4418 {0xaa, 0x04, 0x0287},
4419 {0xaa, 0x07, 0x3002},
4420 {0xaa, 0x20, 0x1100},
4421 {0xaa, 0x35, 0x0050},
4422 {0xaa, 0x30, 0x0005},
4423 {0xaa, 0x31, 0x0000},
4424 {0xaa, 0x58, 0x0078},
4425 {0xaa, 0x62, 0x0411},
4426 {0xaa, 0x2b, 0x0028},
4427 {0xaa, 0x2c, 0x0030},
4428 {0xaa, 0x2d, 0x0030},
4429 {0xaa, 0x2e, 0x0028},
4430 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4431 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4432 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4433 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4434 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4435 {0xa0, 0x00, 0x01ad},
4436 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4437 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4438 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4439 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4440 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4441 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
4442 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4443 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4444
4445 {0xa1, 0x01, 0x0002},
4446 {0xa0, 0x09, 0x01ad},
4447 {0xa0, 0x15, 0x01ae},
4448 {0xa0, 0x0d, 0x003a},
4449 {0xa0, 0x02, 0x003b},
4450 {0xa0, 0x00, 0x0038},
4451 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4452 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4453 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4454 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4455 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4456 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4457 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4458 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4459 {0xa0, 0x50, ZC3XX_R112_RGB22},
4460
4461 {0xa1, 0x01, 0x0008},
4462 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
4463 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4464 {0xa1, 0x01, 0x01c8},
4465 {0xa1, 0x01, 0x01c9},
4466 {0xa1, 0x01, 0x01ca},
4467 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4468 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
4469 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
4470 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
4471 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
4472 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
4473 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
4474 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
4475 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
4476 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
4477 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
4478 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
4479 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
4480 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
4481 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
4482 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
4483 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
4484 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
4485 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
4486 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
4487 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
4488 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
4489 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
4490 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
4491 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
4492 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
4493 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
4494 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
4495 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
4496 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
4497 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
4498 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
4499 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
4500 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4501 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4502 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4503 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4504 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4505 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4506 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4507 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4508 {0xa0, 0x50, ZC3XX_R112_RGB22},
4509
4510 {0xa1, 0x01, 0x0180},
4511 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4512 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4513 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4514 {0xaa, 0x05, 0x0009},
4515 {0xaa, 0x09, 0x0134},
4516 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4517 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4518 {0xa0, 0xec, ZC3XX_R192_EXPOSURELIMITLOW},
4519 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4520 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4521 {0xa0, 0x9c, ZC3XX_R197_ANTIFLICKERLOW},
4522 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4523 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4524 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4525 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4526 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4527 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4528 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4529 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4530 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4531 {0xa0, 0x09, 0x01ad},
4532 {0xa0, 0x15, 0x01ae},
4533 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
4534 {0xa1, 0x01, 0x0180},
4535 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4536 {}
4537};
4538
4539static const struct usb_action pb03303x_InitialScale[] = {
4540 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4541 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4542 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4543 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
4544 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4545 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4546 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4547 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4548 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, /* 8b -> dc */
4549 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4550 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
4551 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
4552 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4553 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4554 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4555 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4556 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4557 {0xaa, 0x01, 0x0001},
4558 {0xaa, 0x06, 0x0000},
4559 {0xaa, 0x08, 0x0483},
4560 {0xaa, 0x01, 0x0004},
4561 {0xaa, 0x08, 0x0006},
4562 {0xaa, 0x02, 0x0011},
4563 {0xaa, 0x03, 0x01e7},
4564 {0xaa, 0x04, 0x0287},
4565 {0xaa, 0x07, 0x3002},
4566 {0xaa, 0x20, 0x1100},
4567 {0xaa, 0x35, 0x0050},
4568 {0xaa, 0x30, 0x0005},
4569 {0xaa, 0x31, 0x0000},
4570 {0xaa, 0x58, 0x0078},
4571 {0xaa, 0x62, 0x0411},
4572 {0xaa, 0x2b, 0x0028},
4573 {0xaa, 0x2c, 0x0030},
4574 {0xaa, 0x2d, 0x0030},
4575 {0xaa, 0x2e, 0x0028},
4576 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4577 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4578 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4579 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4580 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4581 {0xa0, 0x00, 0x01ad},
4582 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4583 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4584 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4585 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4586 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4587 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
4588 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4589 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4590
4591 {0xa1, 0x01, 0x0002},
4592
4593 {0xa0, 0x09, 0x01ad},
4594 {0xa0, 0x15, 0x01ae},
4595
4596 {0xa0, 0x0d, 0x003a},
4597 {0xa0, 0x02, 0x003b},
4598 {0xa0, 0x00, 0x0038},
4599 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4600 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4601 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4602 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4603 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4604 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4605 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4606 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4607 {0xa0, 0x50, ZC3XX_R112_RGB22},
4608
4609 {0xa1, 0x01, 0x0008},
4610 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
4611 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4612 {0xa1, 0x01, 0x01c8},
4613 {0xa1, 0x01, 0x01c9},
4614 {0xa1, 0x01, 0x01ca},
4615 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4616
4617 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
4618 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
4619 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
4620 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
4621 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
4622 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
4623 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
4624 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
4625 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
4626 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
4627 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
4628 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
4629 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
4630 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
4631 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
4632 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
4633 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
4634 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
4635 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
4636 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
4637 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
4638 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
4639 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
4640 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
4641 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
4642 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
4643 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
4644 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
4645 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
4646 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
4647 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
4648 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
4649 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4650 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4651 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4652 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4653 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4654 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4655 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4656 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4657 {0xa0, 0x50, ZC3XX_R112_RGB22},
4658
4659 {0xa1, 0x01, 0x0180},
4660 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4661 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4662 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4663 {0xaa, 0x05, 0x0009},
4664 {0xaa, 0x09, 0x0134},
4665 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4666 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4667 {0xa0, 0xec, ZC3XX_R192_EXPOSURELIMITLOW},
4668 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4669 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4670 {0xa0, 0x9c, ZC3XX_R197_ANTIFLICKERLOW},
4671 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4672 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4673 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4674 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4675 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4676 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4677 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4678 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4679 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4680 {0xa0, 0x09, 0x01ad},
4681 {0xa0, 0x15, 0x01ae},
4682 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
4683 {0xa1, 0x01, 0x0180},
4684 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4685 {}
4686};
4687static const struct usb_action pb0330xx_Initial[] = {
4688 {0xa1, 0x01, 0x0008},
4689 {0xa1, 0x01, 0x0008},
4690 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4691 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
4692 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4693 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4694 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4695 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4696 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4697 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4698 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4699 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4700 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4701 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4702 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4703 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4704 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4705 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4706 {0xaa, 0x01, 0x0006},
4707 {0xaa, 0x02, 0x0011},
4708 {0xaa, 0x03, 0x01e7},
4709 {0xaa, 0x04, 0x0287},
4710 {0xaa, 0x06, 0x0003},
4711 {0xaa, 0x07, 0x3002},
4712 {0xaa, 0x20, 0x1100},
4713 {0xaa, 0x2f, 0xf7b0},
4714 {0xaa, 0x30, 0x0005},
4715 {0xaa, 0x31, 0x0000},
4716 {0xaa, 0x34, 0x0100},
4717 {0xaa, 0x35, 0x0060},
4718 {0xaa, 0x3d, 0x068f},
4719 {0xaa, 0x40, 0x01e0},
4720 {0xaa, 0x58, 0x0078},
4721 {0xaa, 0x62, 0x0411},
4722 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4723 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4724 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4725 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4726 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4727 {0xa0, 0x00, 0x01ad},
4728 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4729 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4730 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4731 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4732 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4733 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
4734 {0xa1, 0x01, 0x0002},
4735 {0xa0, 0x09, 0x01ad},
4736 {0xa0, 0x15, 0x01ae},
4737 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
4738 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
4739 {0xa1, 0x01, 0x0091},
4740 {0xa1, 0x01, 0x0095},
4741 {0xa1, 0x01, 0x0096},
4742 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4743 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4744 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4745 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4746 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4747 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4748 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4749 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4750 {0xa0, 0x50, ZC3XX_R112_RGB22},
4751 {0xa1, 0x01, 0x0008},
4752 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
4753 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4754 {0xa1, 0x01, 0x01c8},
4755 {0xa1, 0x01, 0x01c9},
4756 {0xa1, 0x01, 0x01ca},
4757 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4758
4759 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4760 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4761 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4762 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4763 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4764 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4765 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4766 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4767 {0xa0, 0x50, ZC3XX_R112_RGB22},
4768 {0xa1, 0x01, 0x0180},
4769 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4770 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4771 {0xaa, 0x05, 0x0066},
4772 {0xaa, 0x09, 0x02b2},
4773 {0xaa, 0x10, 0x0002},
4774
4775 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4776 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4777 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4778 {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW},
4779 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4780 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4781 {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW},
4782 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
4783 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
4784 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4785 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4786 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4787 {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1},
4788 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2},
4789 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4790 {0xa0, 0x09, 0x01ad},
4791 {0xa0, 0x15, 0x01ae},
4792 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
4793 {0xa1, 0x01, 0x0180},
4794 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4795 {0xa1, 0x01, 0x0008},
4796 {0xa1, 0x01, 0x0007},
4797/* {0xa0, 0x30, 0x0007}, */
4798/* {0xa0, 0x00, 0x0007}, */
4799 {}
4800};
4801
4802static const struct usb_action pb0330xx_InitialScale[] = {
4803 {0xa1, 0x01, 0x0008},
4804 {0xa1, 0x01, 0x0008},
4805 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4806 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
4807 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4808 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 10 */
4809 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4810 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4811 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4812 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4813 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4814 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4815 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4816 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4817 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4818 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4819 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4820 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4821 {0xaa, 0x01, 0x0006},
4822 {0xaa, 0x02, 0x0011},
4823 {0xaa, 0x03, 0x01e7},
4824 {0xaa, 0x04, 0x0287},
4825 {0xaa, 0x06, 0x0003},
4826 {0xaa, 0x07, 0x3002},
4827 {0xaa, 0x20, 0x1100},
4828 {0xaa, 0x2f, 0xf7b0},
4829 {0xaa, 0x30, 0x0005},
4830 {0xaa, 0x31, 0x0000},
4831 {0xaa, 0x34, 0x0100},
4832 {0xaa, 0x35, 0x0060},
4833 {0xaa, 0x3d, 0x068f},
4834 {0xaa, 0x40, 0x01e0},
4835 {0xaa, 0x58, 0x0078},
4836 {0xaa, 0x62, 0x0411},
4837 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4838 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4839 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4840 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4841 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4842 {0xa0, 0x00, 0x01ad},
4843 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4844 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4845 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4846 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4847 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4848 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
4849 {0xa1, 0x01, 0x0002},
4850 {0xa0, 0x09, 0x01ad},
4851 {0xa0, 0x15, 0x01ae},
4852 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
4853 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
4854 {0xa1, 0x01, 0x0091},
4855 {0xa1, 0x01, 0x0095},
4856 {0xa1, 0x01, 0x0096},
4857 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4858 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4859 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4860 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4861 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4862 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4863 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4864 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4865 {0xa0, 0x50, ZC3XX_R112_RGB22},
4866 {0xa1, 0x01, 0x0008},
4867 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
4868 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4869 {0xa1, 0x01, 0x01c8},
4870 {0xa1, 0x01, 0x01c9},
4871 {0xa1, 0x01, 0x01ca},
4872 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4873
4874 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4875 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4876 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4877 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4878 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4879 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4880 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4881 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4882 {0xa0, 0x50, ZC3XX_R112_RGB22},
4883 {0xa1, 0x01, 0x0180},
4884 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4885 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4886 {0xaa, 0x05, 0x0066},
4887 {0xaa, 0x09, 0x02b2},
4888 {0xaa, 0x10, 0x0002},
4889 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4890 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4891 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4892 {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW},
4893 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4894 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4895 {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW},
4896 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
4897 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
4898 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4899 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4900 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4901 {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1},
4902 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2},
4903 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4904 {0xa0, 0x09, 0x01ad},
4905 {0xa0, 0x15, 0x01ae},
4906 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
4907 {0xa1, 0x01, 0x0180},
4908 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4909 {0xa1, 0x01, 0x0008},
4910 {0xa1, 0x01, 0x0007},
4911/* {0xa0, 0x30, 0x0007}, */
4912/* {0xa0, 0x00, 0x0007}, */
4913 {}
4914};
4915static const struct usb_action pb0330_50HZ[] = {
4916 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4917 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
4918 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,ee,cc */
4919 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4920 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4921 {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */
4922 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4923 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4924 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
4925 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
4926 {0xa0, 0x68, ZC3XX_R01D_HSYNC_0}, /* 00,1d,68,cc */
4927 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
4928 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
4929 {}
4930};
4931static const struct usb_action pb0330_50HZScale[] = {
4932 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4933 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4934 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
4935 {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,a0,cc */
4936 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4937 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4938 {0xa0, 0x7a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7a,cc */
4939 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4940 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4941 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
4942 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
4943 {0xa0, 0xe5, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e5,cc */
4944 {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f0,cc */
4945 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */
4946 {}
4947};
4948static const struct usb_action pb0330_60HZ[] = {
4949 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4950 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4951 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
4952 {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,dd,cc */
4953 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4954 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4955 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */
4956 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4957 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4958 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
4959 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
4960 {0xa0, 0x43, ZC3XX_R01D_HSYNC_0}, /* 00,1d,43,cc */
4961 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */
4962 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
4963 {}
4964};
4965static const struct usb_action pb0330_60HZScale[] = {
4966 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4967 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4968 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
4969 {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,a0,cc */
4970 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4971 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4972 {0xa0, 0x7a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7a,cc */
4973 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4974 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4975 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
4976 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
4977 {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */
4978 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */
4979 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
4980 {}
4981};
4982static const struct usb_action pb0330_NoFliker[] = {
4983 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4984 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4985 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
4986 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
4987 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4988 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4989 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
4990 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4991 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4992 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
4993 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
4994 {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, /* 00,1d,09,cc */
4995 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */
4996 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
4997 {}
4998};
4999static const struct usb_action pb0330_NoFlikerScale[] = {
5000 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5001 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5002 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
5003 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
5004 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5005 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5006 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
5007 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
5008 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5009 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
5010 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
5011 {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, /* 00,1d,09,cc */
5012 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */
5013 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
5014 {}
5015};
5016
5017/* from oem9.inf - HKR,%PO2030%,Initial - 640x480 - (close to CS2102) */
5018static const struct usb_action PO2030_mode0[] = {
5019 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
5020 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
5021 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
5022 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
5023 {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
5024 {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
5025 {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
5026 {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
5027 {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
5028 {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
5029 {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
5030 {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
5031 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
5032 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
5033 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
5034 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
5035 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
5036 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
5037 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
5038 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5039 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5040 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
5041 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
5042 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
5043 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
5044 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */
5045 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
5046 {0xaa, 0x09, 0x00ce}, /* 00,09,ce,aa */
5047 {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
5048 {0xaa, 0x0d, 0x0054}, /* 00,0d,54,aa */
5049 {0xaa, 0x0f, 0x00eb}, /* 00,0f,eb,aa */
5050 {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
5051 {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
5052 {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
5053 {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
5054 {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
5055 {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
5056 {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
5057 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
5058 {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
5059 {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
5060 {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
5061 {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
5062 {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
5063 {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
5064 {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
5065 {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
5066 {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
5067 {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
5068 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
5069 {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
5070 {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
5071 {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
5072 {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
5073 {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
5074 {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
5075 {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
5076 {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
5077 {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
5078 {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
5079 {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
5080 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
5081 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
5082 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
5083 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
5084 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
5085 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
5086 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
5087 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
5088 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
5089 {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
5090 {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
5091 {}
5092};
5093
5094/* from oem9.inf - HKR,%PO2030%,InitialScale - 320x240 */
5095static const struct usb_action PO2030_mode1[] = {
5096 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
5097 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
5098 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
5099 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
5100 {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
5101 {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
5102 {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
5103 {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
5104 {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
5105 {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
5106 {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
5107 {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
5108 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
5109 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
5110 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
5111 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
5112 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
5113 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
5114 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
5115 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5116 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5117 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
5118 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
5119 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
5120 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
5121 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */
5122 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
5123 {0xaa, 0x09, 0x00cc}, /* 00,09,cc,aa */
5124 {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
5125 {0xaa, 0x0d, 0x0058}, /* 00,0d,58,aa */
5126 {0xaa, 0x0f, 0x00ed}, /* 00,0f,ed,aa */
5127 {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
5128 {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
5129 {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
5130 {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
5131 {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
5132 {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
5133 {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
5134 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
5135 {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
5136 {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
5137 {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
5138 {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
5139 {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
5140 {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
5141 {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
5142 {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
5143 {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
5144 {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
5145 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
5146 {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
5147 {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
5148 {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
5149 {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
5150 {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
5151 {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
5152 {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
5153 {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
5154 {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
5155 {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
5156 {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
5157 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
5158 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
5159 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
5160 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
5161 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
5162 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
5163 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
5164 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
5165 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
5166 {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
5167 {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
5168 {}
5169};
5170
5171static const struct usb_action PO2030_50HZ[] = {
5172 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5173 {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */
5174 {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */
5175 {0xaa, 0x1c, 0x00b0}, /* 00,1c,b0,aa */
5176 {0xa0, 0x05, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,05,cc */
5177 {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,35,cc */
5178 {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
5179 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5180 {0xa0, 0x85, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,85,cc */
5181 {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,58,cc */
5182 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
5183 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
5184 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
5185 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
5186 {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */
5187 {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */
5188 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */
5189 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5190 {}
5191};
5192
5193static const struct usb_action PO2030_60HZ[] = {
5194 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5195 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
5196 {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */
5197 {0xaa, 0x1c, 0x0040}, /* 00,1c,40,aa */
5198 {0xa0, 0x08, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,08,cc */
5199 {0xa0, 0xae, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,ae,cc */
5200 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */
5201 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5202 {0xa0, 0x6f, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,6f,cc */
5203 {0xa0, 0x20, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,20,cc */
5204 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
5205 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
5206 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
5207 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
5208 {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */
5209 {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */
5210 /* win: 01,8d,80 */
5211 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */
5212 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5213 {}
5214};
5215
5216static const struct usb_action PO2030_NoFliker[] = {
5217 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
5218 {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */
5219 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
5220 {0xaa, 0x1b, 0x0002}, /* 00,1b,02,aa */
5221 {0xaa, 0x1c, 0x0078}, /* 00,1c,78,aa */
5222 {0xaa, 0x46, 0x0000}, /* 00,46,00,aa */
5223 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
5224 {}
5225};
5226
5227/* TEST */
5228static const struct usb_action tas5130CK_Initial[] = {
5229 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5230 {0xa0, 0x01, 0x003b},
5231 {0xa0, 0x0e, 0x003a},
5232 {0xa0, 0x01, 0x0038},
5233 {0xa0, 0x0b, 0x0039},
5234 {0xa0, 0x00, 0x0038},
5235 {0xa0, 0x0b, 0x0039},
5236 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5237 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5238 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
5239 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
5240 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5241 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5242 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5243 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5244 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
5245 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5246 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
5247 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
5248 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
5249 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
5250 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
5251 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
5252 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5253 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
5254 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
5255 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5256 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5257 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
5258 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5259 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5260 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5261 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
5262 {0xa0, 0x83, ZC3XX_R093_I2CSETVALUE},
5263 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5264 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5265 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
5266 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
5267 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5268 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5269 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
5270 {0xa0, 0x06, ZC3XX_R093_I2CSETVALUE},
5271 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5272 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5273 {0xa0, 0x02, ZC3XX_R092_I2CADDRESSSELECT},
5274 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5275 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5276 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5277 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
5278 {0xa0, 0xE7, ZC3XX_R093_I2CSETVALUE},
5279 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5280 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5281 {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
5282 {0xa0, 0x87, ZC3XX_R093_I2CSETVALUE},
5283 {0xa0, 0x02, ZC3XX_R094_I2CWRITEACK},
5284 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5285 {0xa0, 0x07, ZC3XX_R092_I2CADDRESSSELECT},
5286 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
5287 {0xa0, 0x30, ZC3XX_R094_I2CWRITEACK},
5288 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5289 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
5290 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5291 {0xa0, 0x51, ZC3XX_R094_I2CWRITEACK},
5292 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5293 {0xa0, 0x35, ZC3XX_R092_I2CADDRESSSELECT},
5294 {0xa0, 0x7F, ZC3XX_R093_I2CSETVALUE},
5295 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5296 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5297 {0xa0, 0x30, ZC3XX_R092_I2CADDRESSSELECT},
5298 {0xa0, 0x05, ZC3XX_R093_I2CSETVALUE},
5299 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5300 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5301 {0xa0, 0x31, ZC3XX_R092_I2CADDRESSSELECT},
5302 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5303 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5304 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5305 {0xa0, 0x58, ZC3XX_R092_I2CADDRESSSELECT},
5306 {0xa0, 0x78, ZC3XX_R093_I2CSETVALUE},
5307 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5308 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5309 {0xa0, 0x62, ZC3XX_R092_I2CADDRESSSELECT},
5310 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5311 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5312 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5313 {0xa0, 0x2B, ZC3XX_R092_I2CADDRESSSELECT},
5314 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5315 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5316 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5317 {0xa0, 0x2c, ZC3XX_R092_I2CADDRESSSELECT},
5318 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5319 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5320 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5321 {0xa0, 0x2D, ZC3XX_R092_I2CADDRESSSELECT},
5322 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5323 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5324 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5325 {0xa0, 0x2e, ZC3XX_R092_I2CADDRESSSELECT},
5326 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5327 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5328 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5329 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
5330 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
5331 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5332 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5333 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5334 {0xa0, 0x09, 0x01ad},
5335 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5336 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5337 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5338 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5339 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
5340 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
5341 {0xa0, 0x61, ZC3XX_R116_RGAIN},
5342 {0xa0, 0x65, ZC3XX_R118_BGAIN},
5343 {0xa0, 0x09, 0x01ad},
5344 {0xa0, 0x15, 0x01ae},
5345 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5346 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5347 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5348 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5349 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5350 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5351 {0xa0, 0xec, ZC3XX_R110_RGB20},
5352 {0xa0, 0x03, ZC3XX_R111_RGB21},
5353 {0xa0, 0x51, ZC3XX_R112_RGB22},
5354 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5355 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
5356 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
5357 {0xa0, 0x38, ZC3XX_R120_GAMMA00}, /* gamma > 5 */
5358 {0xa0, 0x51, ZC3XX_R121_GAMMA01},
5359 {0xa0, 0x6e, ZC3XX_R122_GAMMA02},
5360 {0xa0, 0x8c, ZC3XX_R123_GAMMA03},
5361 {0xa0, 0xa2, ZC3XX_R124_GAMMA04},
5362 {0xa0, 0xb6, ZC3XX_R125_GAMMA05},
5363 {0xa0, 0xc8, ZC3XX_R126_GAMMA06},
5364 {0xa0, 0xd6, ZC3XX_R127_GAMMA07},
5365 {0xa0, 0xe2, ZC3XX_R128_GAMMA08},
5366 {0xa0, 0xed, ZC3XX_R129_GAMMA09},
5367 {0xa0, 0xf5, ZC3XX_R12A_GAMMA0A},
5368 {0xa0, 0xfc, ZC3XX_R12B_GAMMA0B},
5369 {0xa0, 0xff, ZC3XX_R12C_GAMMA0C},
5370 {0xa0, 0xff, ZC3XX_R12D_GAMMA0D},
5371 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
5372 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
5373 {0xa0, 0x12, ZC3XX_R130_GAMMA10},
5374 {0xa0, 0x1b, ZC3XX_R131_GAMMA11},
5375 {0xa0, 0x1d, ZC3XX_R132_GAMMA12},
5376 {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
5377 {0xa0, 0x15, ZC3XX_R134_GAMMA14},
5378 {0xa0, 0x12, ZC3XX_R135_GAMMA15},
5379 {0xa0, 0x0f, ZC3XX_R136_GAMMA16},
5380 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
5381 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
5382 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
5383 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
5384 {0xa0, 0x05, ZC3XX_R13B_GAMMA1B},
5385 {0xa0, 0x00, ZC3XX_R13C_GAMMA1C},
5386 {0xa0, 0x00, ZC3XX_R13D_GAMMA1D},
5387 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
5388 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
5389 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5390 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5391 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5392 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5393 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5394 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5395 {0xa0, 0xec, ZC3XX_R110_RGB20},
5396 {0xa0, 0x03, ZC3XX_R111_RGB21},
5397 {0xa0, 0x51, ZC3XX_R112_RGB22},
5398 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
5399 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
5400 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
5401 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
5402 {0xa0, 0x09, ZC3XX_R093_I2CSETVALUE},
5403 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5404 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5405 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
5406 {0xa0, 0x34, ZC3XX_R093_I2CSETVALUE},
5407 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5408 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5409 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
5410 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
5411 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
5412 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5413 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5414 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
5415 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
5416 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
5417 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
5418 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
5419 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
5420 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
5421 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
5422 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
5423 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5424 {0xa0, 0x09, 0x01ad},
5425 {0xa0, 0x15, 0x01ae},
5426 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
5427 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5428 {}
5429};
5430
5431static const struct usb_action tas5130CK_InitialScale[] = {
5432 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5433 {0xa0, 0x01, 0x003b},
5434 {0xa0, 0x0e, 0x003a},
5435 {0xa0, 0x01, 0x0038},
5436 {0xa0, 0x0b, 0x0039},
5437 {0xa0, 0x00, 0x0038},
5438 {0xa0, 0x0b, 0x0039},
5439 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5440 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5441 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
5442 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
5443 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5444 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5445 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5446 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5447 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
5448 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5449 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
5450 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
5451 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
5452 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
5453 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
5454 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
5455 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5456 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
5457 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
5458 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5459 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5460 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
5461 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5462 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5463 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5464 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
5465 {0xa0, 0x83, ZC3XX_R093_I2CSETVALUE},
5466 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5467 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5468 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
5469 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
5470 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5471 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5472 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
5473 {0xa0, 0x06, ZC3XX_R093_I2CSETVALUE},
5474 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5475 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5476 {0xa0, 0x02, ZC3XX_R092_I2CADDRESSSELECT},
5477 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5478 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5479 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5480 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
5481 {0xa0, 0xe5, ZC3XX_R093_I2CSETVALUE},
5482 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5483 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5484 {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
5485 {0xa0, 0x85, ZC3XX_R093_I2CSETVALUE},
5486 {0xa0, 0x02, ZC3XX_R094_I2CWRITEACK},
5487 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5488 {0xa0, 0x07, ZC3XX_R092_I2CADDRESSSELECT},
5489 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
5490 {0xa0, 0x30, ZC3XX_R094_I2CWRITEACK},
5491 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5492 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
5493 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5494 {0xa0, 0x51, ZC3XX_R094_I2CWRITEACK},
5495 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5496 {0xa0, 0x35, ZC3XX_R092_I2CADDRESSSELECT},
5497 {0xa0, 0x7F, ZC3XX_R093_I2CSETVALUE},
5498 {0xa0, 0x50, ZC3XX_R094_I2CWRITEACK},
5499 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5500 {0xa0, 0x30, ZC3XX_R092_I2CADDRESSSELECT},
5501 {0xa0, 0x05, ZC3XX_R093_I2CSETVALUE},
5502 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5503 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5504 {0xa0, 0x31, ZC3XX_R092_I2CADDRESSSELECT},
5505 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5506 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5507 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5508 {0xa0, 0x58, ZC3XX_R092_I2CADDRESSSELECT},
5509 {0xa0, 0x78, ZC3XX_R093_I2CSETVALUE},
5510 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5511 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5512 {0xa0, 0x62, ZC3XX_R092_I2CADDRESSSELECT},
5513 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5514 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5515 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5516 {0xa0, 0x2B, ZC3XX_R092_I2CADDRESSSELECT},
5517 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5518 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5519 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5520 {0xa0, 0x2C, ZC3XX_R092_I2CADDRESSSELECT},
5521 {0xa0, 0x7F, ZC3XX_R093_I2CSETVALUE},
5522 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5523 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5524 {0xa0, 0x2D, ZC3XX_R092_I2CADDRESSSELECT},
5525 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5526 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5527 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5528 {0xa0, 0x2e, ZC3XX_R092_I2CADDRESSSELECT},
5529 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5530 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5531 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5532 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
5533 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
5534 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5535 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5536 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5537 {0xa0, 0x09, 0x01ad},
5538 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5539 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5540 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5541 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5542 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
5543 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
5544 {0xa0, 0x61, ZC3XX_R116_RGAIN},
5545 {0xa0, 0x65, ZC3XX_R118_BGAIN},
5546 {0xa0, 0x09, 0x01ad},
5547 {0xa0, 0x15, 0x01ae},
5548 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5549 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5550 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5551 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5552 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5553 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5554 {0xa0, 0xec, ZC3XX_R110_RGB20},
5555 {0xa0, 0x03, ZC3XX_R111_RGB21},
5556 {0xa0, 0x51, ZC3XX_R112_RGB22},
5557 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5558 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
5559 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
5560 {0xa0, 0x38, ZC3XX_R120_GAMMA00}, /* gamma > 5 */
5561 {0xa0, 0x51, ZC3XX_R121_GAMMA01},
5562 {0xa0, 0x6e, ZC3XX_R122_GAMMA02},
5563 {0xa0, 0x8c, ZC3XX_R123_GAMMA03},
5564 {0xa0, 0xa2, ZC3XX_R124_GAMMA04},
5565 {0xa0, 0xb6, ZC3XX_R125_GAMMA05},
5566 {0xa0, 0xc8, ZC3XX_R126_GAMMA06},
5567 {0xa0, 0xd6, ZC3XX_R127_GAMMA07},
5568 {0xa0, 0xe2, ZC3XX_R128_GAMMA08},
5569 {0xa0, 0xed, ZC3XX_R129_GAMMA09},
5570 {0xa0, 0xf5, ZC3XX_R12A_GAMMA0A},
5571 {0xa0, 0xfc, ZC3XX_R12B_GAMMA0B},
5572 {0xa0, 0xff, ZC3XX_R12C_GAMMA0C},
5573 {0xa0, 0xff, ZC3XX_R12D_GAMMA0D},
5574 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
5575 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
5576 {0xa0, 0x12, ZC3XX_R130_GAMMA10},
5577 {0xa0, 0x1b, ZC3XX_R131_GAMMA11},
5578 {0xa0, 0x1d, ZC3XX_R132_GAMMA12},
5579 {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
5580 {0xa0, 0x15, ZC3XX_R134_GAMMA14},
5581 {0xa0, 0x12, ZC3XX_R135_GAMMA15},
5582 {0xa0, 0x0f, ZC3XX_R136_GAMMA16},
5583 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
5584 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
5585 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
5586 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
5587 {0xa0, 0x05, ZC3XX_R13B_GAMMA1B},
5588 {0xa0, 0x00, ZC3XX_R13C_GAMMA1C},
5589 {0xa0, 0x00, ZC3XX_R13D_GAMMA1D},
5590 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
5591 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
5592 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5593 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5594 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5595 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5596 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5597 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5598 {0xa0, 0xec, ZC3XX_R110_RGB20},
5599 {0xa0, 0x03, ZC3XX_R111_RGB21},
5600 {0xa0, 0x51, ZC3XX_R112_RGB22},
5601 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
5602 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
5603 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
5604 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
5605 {0xa0, 0x62, ZC3XX_R093_I2CSETVALUE},
5606 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5607 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5608 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
5609 {0xa0, 0xaa, ZC3XX_R093_I2CSETVALUE},
5610 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5611 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5612 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
5613 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
5614 {0xa0, 0x9b, ZC3XX_R192_EXPOSURELIMITLOW},
5615 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5616 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5617 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
5618 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
5619 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
5620 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
5621 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
5622 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
5623 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
5624 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
5625 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
5626 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
5627 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5628 {0xa0, 0x09, 0x01ad},
5629 {0xa0, 0x15, 0x01ae},
5630 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
5631 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5632 {0xa0, 0x30, 0x0007},
5633 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},
5634 {0xa0, 0x00, 0x0007},
5635 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5636 {}
5637};
5638
5639static const struct usb_action tas5130cxx_Initial[] = {
5640 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5641 {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT},
5642 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5643 {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
5644 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5645 {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
5646 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
5647 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5648 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5649 {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
5650 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
5651
5652 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5653 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5654 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5655 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5656
5657 {0xa0, 0x04, ZC3XX_R098_WINYSTARTLOW},
5658 {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
5659 {0xa0, 0x04, ZC3XX_R11A_FIRSTYLOW},
5660 {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
5661 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
5662 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
5663 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
5664 {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
5665 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
5666 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5667 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5668 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
5669 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
5670 {0xa0, 0x00, 0x01ad},
5671 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5672 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5673 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5674 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5675 {0xa1, 0x01, 0x0002},
5676 {0xa1, 0x01, 0x0008},
5677 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
5678 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
5679 {0xa1, 0x01, 0x01c8},
5680 {0xa1, 0x01, 0x01c9},
5681 {0xa1, 0x01, 0x01ca},
5682 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
5683
5684 {0xa0, 0x68, ZC3XX_R10A_RGB00}, /* matrix */
5685 {0xa0, 0xec, ZC3XX_R10B_RGB01},
5686 {0xa0, 0xec, ZC3XX_R10C_RGB02},
5687 {0xa0, 0xec, ZC3XX_R10D_RGB10},
5688 {0xa0, 0x68, ZC3XX_R10E_RGB11},
5689 {0xa0, 0xec, ZC3XX_R10F_RGB12},
5690 {0xa0, 0xec, ZC3XX_R110_RGB20},
5691 {0xa0, 0xec, ZC3XX_R111_RGB21},
5692 {0xa0, 0x68, ZC3XX_R112_RGB22},
5693
5694 {0xa1, 0x01, 0x018d},
5695 {0xa0, 0x90, ZC3XX_R18D_YTARGET}, /* 90 */
5696 {0xa1, 0x01, 0x0180},
5697 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
5698 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
5699
5700 {0xaa, 0xa3, 0x0001},
5701 {0xaa, 0xa4, 0x0077},
5702 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
5703 {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW},
5704
5705 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 00 */
5706 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 03 */
5707 {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* e8 */
5708 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 0 */
5709 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 0 */
5710 {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 7d */
5711
5712 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5713 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5714 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 08 */
5715 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 24 */
5716 {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0},
5717 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
5718 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2},
5719 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
5720 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH},
5721 {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW},
5722 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, /* 50 */
5723 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
5724 {0xa1, 0x01, 0x0180},
5725 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5726 {}
5727};
5728static const struct usb_action tas5130cxx_InitialScale[] = {
5729 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5730 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5731 {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},
5732
5733 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5734 {0xa1, 0x01, 0x0008},
5735
5736 {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
5737 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5738 {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
5739 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
5740 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5741 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5742 {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
5743 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
5744 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5745 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5746 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5747 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5748 {0xa0, 0x05, ZC3XX_R098_WINYSTARTLOW},
5749 {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
5750 {0xa0, 0x05, ZC3XX_R11A_FIRSTYLOW},
5751 {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
5752 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
5753 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
5754 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
5755 {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
5756 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
5757 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5758 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5759 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
5760 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
5761 {0xa0, 0x00, 0x01ad},
5762 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5763 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5764 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5765 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5766 {0xa1, 0x01, 0x0002},
5767 {0xa1, 0x01, 0x0008},
5768
5769 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5770 {0xa1, 0x01, 0x0008}, /* clock ? */
5771 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
5772 {0xa1, 0x01, 0x01c8},
5773 {0xa1, 0x01, 0x01c9},
5774 {0xa1, 0x01, 0x01ca},
5775 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
5776
5777 {0xa0, 0x68, ZC3XX_R10A_RGB00}, /* matrix */
5778 {0xa0, 0xec, ZC3XX_R10B_RGB01},
5779 {0xa0, 0xec, ZC3XX_R10C_RGB02},
5780 {0xa0, 0xec, ZC3XX_R10D_RGB10},
5781 {0xa0, 0x68, ZC3XX_R10E_RGB11},
5782 {0xa0, 0xec, ZC3XX_R10F_RGB12},
5783 {0xa0, 0xec, ZC3XX_R110_RGB20},
5784 {0xa0, 0xec, ZC3XX_R111_RGB21},
5785 {0xa0, 0x68, ZC3XX_R112_RGB22},
5786
5787 {0xa1, 0x01, 0x018d},
5788 {0xa0, 0x90, ZC3XX_R18D_YTARGET},
5789 {0xa1, 0x01, 0x0180},
5790 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
5791 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
5792 {0xaa, 0xa3, 0x0001},
5793 {0xaa, 0xa4, 0x0063},
5794 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
5795 {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW},
5796 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
5797 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
5798 {0xa0, 0x38, ZC3XX_R192_EXPOSURELIMITLOW},
5799 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5800 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5801 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
5802 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5803 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5804 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
5805 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
5806 {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0},
5807 {0xa0, 0xda, ZC3XX_R01E_HSYNC_1},
5808 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2},
5809 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
5810 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH},
5811 {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW},
5812 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5813 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
5814 {0xa1, 0x01, 0x0180},
5815 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5816 {}
5817};
5818static const struct usb_action tas5130cxx_50HZ[] = {
5819 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5820 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5821 {0xaa, 0xa4, 0x0063}, /* 00,a4,63,aa */
5822 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5823 {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,63,cc */
5824 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5825 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
5826 {0xa0, 0x38, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,38,cc */
5827 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5828 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5829 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc */
5830 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
5831 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5832 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
5833 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
5834 {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,d3,cc */
5835 {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, /* 00,1e,da,cc */
5836 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
5837 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5838 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5839 {}
5840};
5841static const struct usb_action tas5130cxx_50HZScale[] = {
5842 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5843 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5844 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
5845 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5846 {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
5847 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5848 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */
5849 {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e8,cc */
5850 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5851 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5852 {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
5853 {0xa0, 0x14, ZC3XX_R18C_AEFREEZE}, /* 01,8c,14,cc */
5854 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5855 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
5856 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
5857 {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, /* 00,1d,f0,cc */
5858 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f4,cc */
5859 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */
5860 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5861 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5862 {}
5863};
5864static const struct usb_action tas5130cxx_60HZ[] = {
5865 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5866 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5867 {0xaa, 0xa4, 0x0036}, /* 00,a4,36,aa */
5868 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5869 {0xa0, 0x36, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,36,cc */
5870 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5871 {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,01,cc */
5872 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
5873 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5874 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5875 {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3e,cc */
5876 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
5877 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5878 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
5879 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
5880 {0xa0, 0xca, ZC3XX_R01D_HSYNC_0}, /* 00,1d,ca,cc */
5881 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5882 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5883 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5884 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5885 {}
5886};
5887static const struct usb_action tas5130cxx_60HZScale[] = {
5888 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5889 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5890 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
5891 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5892 {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
5893 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5894 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */
5895 {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e8,cc */
5896 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5897 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5898 {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
5899 {0xa0, 0x14, ZC3XX_R18C_AEFREEZE}, /* 01,8c,14,cc */
5900 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5901 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
5902 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
5903 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
5904 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5905 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5906 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5907 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5908 {}
5909};
5910static const struct usb_action tas5130cxx_NoFliker[] = {
5911 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5912 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5913 {0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */
5914 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5915 {0xa0, 0x40, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,40,cc */
5916 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5917 {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,01,cc */
5918 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
5919 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5920 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5921 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
5922 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
5923 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5924 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
5925 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
5926 {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
5927 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5928 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5929 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5930 {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
5931 {}
5932};
5933
5934static const struct usb_action tas5130cxx_NoFlikerScale[] = {
5935 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5936 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5937 {0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */
5938 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5939 {0xa0, 0x90, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,90,cc */
5940 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5941 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */
5942 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
5943 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5944 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5945 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
5946 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
5947 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5948 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
5949 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
5950 {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
5951 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5952 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5953 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5954 {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
5955 {}
5956};
5957
5958static const struct usb_action tas5130c_vf0250_Initial[] = {
5959 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
5960 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
5961 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
5962 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc,
5963 * 0<->10 */
5964 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */
5965 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */
5966 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */
5967 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc, */
5968 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5969 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc, */
5970 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc, */
5971 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc, */
5972 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc, */
5973 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc, */
5974 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc, */
5975 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc, */
5976 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc,
5977 * 6<->8 */
5978 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc,
5979 * 6<->8 */
5980 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */
5981 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5982 {0xaa, 0x1b, 0x0024}, /* 00,1b,24,aa, */
5983 {0xdd, 0x00, 0x0080}, /* 00,00,80,dd, */
5984 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */
5985 {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */
5986 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
5987 {0xaa, 0x01, 0x0000},
5988 {0xaa, 0x01, 0x0000},
5989 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */
5990 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */
5991 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */
5992 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */
5993 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */
5994 {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */
5995 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa, */
5996 {0xaa, 0x0b, 0x00a0}, /* 00,0b,a0,aa, */
5997 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa, */
5998 {0xaa, 0x0d, 0x00a0}, /* 00,0d,a0,aa, */
5999 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa, */
6000 {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */
6001 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */
6002 {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */
6003 {0xa0, 0x00, 0x0039},
6004 {0xa1, 0x01, 0x0037},
6005 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */
6006 {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa, (e6 -> e8) */
6007 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */
6008 {0xaa, 0x19, 0x0088}, /* 00,19,86,aa, */
6009 {0xaa, 0x20, 0x0020}, /* 00,20,20,aa, */
6010 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */
6011 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */
6012 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */
6013 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc, */
6014 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc, */
6015 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc, */
6016 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */
6017 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */
6018 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */
6019 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc, */
6020 {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */
6021 {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
6022 {}
6023};
6024
6025static const struct usb_action tas5130c_vf0250_InitialScale[] = {
6026 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
6027 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
6028 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
6029 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc, */
6030 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */
6031 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */
6032 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */
6033 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc, */
6034 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
6035 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc, */
6036 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc, */
6037 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc, */
6038 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc, */
6039 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc, */
6040 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc, */
6041 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc, */
6042 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc,
6043 * 8<->6 */
6044 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc,
6045 * 8<->6 */
6046 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */
6047 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
6048 {0xaa, 0x1b, 0x0024}, /* 00,1b,24,aa, */
6049 {0xdd, 0x00, 0x0080}, /* 00,00,80,dd, */
6050 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */
6051 {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */
6052 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
6053 {0xaa, 0x01, 0x0000},
6054 {0xaa, 0x01, 0x0000},
6055 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */
6056 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */
6057 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */
6058 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */
6059 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */
6060 {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */
6061 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa, */
6062 {0xaa, 0x0b, 0x00a0}, /* 00,0b,a0,aa, */
6063 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa, */
6064 {0xaa, 0x0d, 0x00a0}, /* 00,0d,a0,aa, */
6065 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa, */
6066 {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */
6067 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */
6068 {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */
6069 {0xa0, 0x00, 0x0039},
6070 {0xa1, 0x01, 0x0037},
6071 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */
6072 {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa (e6 -> e8) */
6073 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */
6074 {0xaa, 0x19, 0x0088}, /* 00,19,88,aa, */
6075 {0xaa, 0x20, 0x0020}, /* 00,20,20,aa, */
6076 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */
6077 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */
6078 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */
6079 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc, */
6080 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc, */
6081 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc, */
6082 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */
6083 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */
6084 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */
6085 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc, */
6086 {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */
6087 {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
6088 {}
6089};
6090/* "50HZ" light frequency banding filter */
6091static const struct usb_action tas5130c_vf0250_50HZ[] = {
6092 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6093 {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
6094 {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */
6095 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
6096 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */
6097 {0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */
6098 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
6099 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
6100 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc, */
6101 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
6102 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
6103 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
6104 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
6105 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
6106 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
6107 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
6108 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
6109 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
6110 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
6111 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
6112 {}
6113};
6114
6115/* "50HZScale" light frequency banding filter */
6116static const struct usb_action tas5130c_vf0250_50HZScale[] = {
6117 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6118 {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */
6119 {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */
6120 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
6121 {0xa0, 0x0d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */
6122 {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */
6123 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
6124 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
6125 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,8e,cc, */
6126 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
6127 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
6128 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
6129 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
6130 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
6131 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
6132 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
6133 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
6134 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
6135 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
6136 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
6137 {}
6138};
6139
6140/* "60HZ" light frequency banding filter */
6141static const struct usb_action tas5130c_vf0250_60HZ[] = {
6142 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6143 {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
6144 {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */
6145 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
6146 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */
6147 {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */
6148 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
6149 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
6150 {0xa0, 0x3b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3b,cc, */
6151 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
6152 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
6153 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
6154 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
6155 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
6156 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
6157 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
6158 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
6159 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
6160 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
6161 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
6162 {}
6163};
6164
6165/* "60HZScale" light frequency banding ilter */
6166static const struct usb_action tas5130c_vf0250_60HZScale[] = {
6167 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6168 {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */
6169 {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */
6170 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
6171 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,1,0b,cc, */
6172 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,2,10,cc, */
6173 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,5,00,cc, */
6174 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,6,00,cc, */
6175 {0xa0, 0x76, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,7,76,cc, */
6176 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,c,0e,cc, */
6177 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,f,15,cc, */
6178 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,9,10,cc, */
6179 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,a,24,cc, */
6180 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,d,62,cc, */
6181 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,e,90,cc, */
6182 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,f,c8,cc, */
6183 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,0,ff,cc, */
6184 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,d,58,cc, */
6185 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
6186 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,d,78,cc */
6187 {}
6188};
6189
6190/* "NoFliker" light frequency banding flter */
6191static const struct usb_action tas5130c_vf0250_NoFliker[] = {
6192 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
6193 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6194 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
6195 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
6196 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,0,00,cc, */
6197 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */
6198 {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */
6199 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
6200 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
6201 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */
6202 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
6203 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
6204 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
6205 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
6206 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
6207 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
6208 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
6209 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
6210 {}
6211};
6212
6213/* "NoFlikerScale" light frequency banding filter */
6214static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = {
6215 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
6216 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6217 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
6218 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
6219 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
6220 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc, */
6221 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc, */
6222 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
6223 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
6224 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */
6225 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
6226 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
6227 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
6228 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
6229 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
6230 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
6231 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
6232 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
6233 {}
6234};
6235
6236static int reg_r_i(struct gspca_dev *gspca_dev,
6237 __u16 index)
6238{
6239 usb_control_msg(gspca_dev->dev,
6240 usb_rcvctrlpipe(gspca_dev->dev, 0),
6241 0xa1,
6242 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
6243 0x01, /* value */
6244 index, gspca_dev->usb_buf, 1,
6245 500);
6246 return gspca_dev->usb_buf[0];
6247}
6248
6249static int reg_r(struct gspca_dev *gspca_dev,
6250 __u16 index)
6251{
6252 int ret;
6253
6254 ret = reg_r_i(gspca_dev, index);
6255 PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret);
6256 return ret;
6257}
6258
6259static void reg_w_i(struct usb_device *dev,
6260 __u8 value,
6261 __u16 index)
6262{
6263 usb_control_msg(dev,
6264 usb_sndctrlpipe(dev, 0),
6265 0xa0,
6266 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
6267 value, index, NULL, 0,
6268 500);
6269}
6270
6271static void reg_w(struct usb_device *dev,
6272 __u8 value,
6273 __u16 index)
6274{
6275 PDEBUG(D_USBO, "reg w %02x -> [%04x]", value, index);
6276 reg_w_i(dev, value, index);
6277}
6278
6279static __u16 i2c_read(struct gspca_dev *gspca_dev,
6280 __u8 reg)
6281{
6282 __u8 retbyte;
6283 __u8 retval[2];
6284
6285 reg_w_i(gspca_dev->dev, reg, 0x92);
6286 reg_w_i(gspca_dev->dev, 0x02, 0x90); /* <- read command */
6287 msleep(25);
6288 retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
6289 retval[0] = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */
6290 retval[1] = reg_r_i(gspca_dev, 0x0096); /* read Hightbyte */
6291 PDEBUG(D_USBO, "i2c r [%02x] -> (%02x) %02x%02x",
6292 reg, retbyte, retval[1], retval[0]);
6293 return (retval[1] << 8) | retval[0];
6294}
6295
6296static __u8 i2c_write(struct gspca_dev *gspca_dev,
6297 __u8 reg,
6298 __u8 valL,
6299 __u8 valH)
6300{
6301 __u8 retbyte;
6302
6303 reg_w_i(gspca_dev->dev, reg, 0x92);
6304 reg_w_i(gspca_dev->dev, valL, 0x93);
6305 reg_w_i(gspca_dev->dev, valH, 0x94);
6306 reg_w_i(gspca_dev->dev, 0x01, 0x90); /* <- write command */
6307 msleep(5);
6308 retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
6309 PDEBUG(D_USBO, "i2c w [%02x] %02x%02x (%02x)",
6310 reg, valH, valL, retbyte);
6311 return retbyte;
6312}
6313
6314static void usb_exchange(struct gspca_dev *gspca_dev,
6315 const struct usb_action *action)
6316{
6317 while (action->req) {
6318 switch (action->req) {
6319 case 0xa0: /* write register */
6320 reg_w(gspca_dev->dev, action->val, action->idx);
6321 break;
6322 case 0xa1: /* read status */
6323 reg_r(gspca_dev, action->idx);
6324 break;
6325 case 0xaa:
6326 i2c_write(gspca_dev,
6327 action->val, /* reg */
6328 action->idx & 0xff, /* valL */
6329 action->idx >> 8); /* valH */
6330 break;
6331 default:
6332/* case 0xdd: * delay */
6333 msleep(action->val / 64 + 10);
6334 break;
6335 }
6336 action++;
6337/* msleep(1); */
6338 }
6339}
6340
6341static void setmatrix(struct gspca_dev *gspca_dev)
6342{
6343 struct sd *sd = (struct sd *) gspca_dev;
6344 int i;
6345 const __u8 *matrix;
6346 static const __u8 gc0305_matrix[9] =
6347 {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50};
6348 static const __u8 ov7620_matrix[9] =
6349 {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58};
6350 static const __u8 po2030_matrix[9] =
6351 {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60};
6352
6353 switch (sd->sensor) {
6354 case SENSOR_GC0305:
6355 matrix = gc0305_matrix;
6356 break;
6357 case SENSOR_MC501CB:
6358 return; /* no matrix? */
6359 case SENSOR_OV7620:
6360/* case SENSOR_OV7648: */
6361 matrix = ov7620_matrix;
6362 break;
6363 case SENSOR_PO2030:
6364 matrix = po2030_matrix;
6365 break;
6366 case SENSOR_TAS5130C_VF0250: /* no matrix? */
6367 return;
6368 default: /* matrix already loaded */
6369 return;
6370 }
6371 for (i = 0; i < ARRAY_SIZE(ov7620_matrix); i++)
6372 reg_w(gspca_dev->dev, matrix[i], 0x010a + i);
6373}
6374
6375static void setbrightness(struct gspca_dev *gspca_dev)
6376{
6377 struct sd *sd = (struct sd *) gspca_dev;
6378 __u8 brightness;
6379
6380 switch (sd->sensor) {
6381 case SENSOR_GC0305:
6382 case SENSOR_OV7620:
6383 case SENSOR_PO2030:
6384 return;
6385 }
6386/*fixme: is it really write to 011d and 018d for all other sensors? */
6387 brightness = sd->brightness;
6388 reg_w(gspca_dev->dev, brightness, 0x011d);
6389 if (brightness < 0x70)
6390 brightness += 0x10;
6391 else
6392 brightness = 0x80;
6393 reg_w(gspca_dev->dev, brightness, 0x018d);
6394}
6395
6396static void setsharpness(struct gspca_dev *gspca_dev)
6397{
6398 struct sd *sd = (struct sd *) gspca_dev;
6399 struct usb_device *dev = gspca_dev->dev;
6400 int sharpness;
6401 static const __u8 sharpness_tb[][2] = {
6402 {0x02, 0x03},
6403 {0x04, 0x07},
6404 {0x08, 0x0f},
6405 {0x10, 0x1e}
6406 };
6407
6408 sharpness = sd->sharpness;
6409 reg_w(dev, sharpness_tb[sharpness][0], 0x01c6);
6410 reg_r(gspca_dev, 0x01c8);
6411 reg_r(gspca_dev, 0x01c9);
6412 reg_r(gspca_dev, 0x01ca);
6413 reg_w(dev, sharpness_tb[sharpness][1], 0x01cb);
6414}
6415
6416static void setcontrast(struct gspca_dev *gspca_dev)
6417{
6418 struct sd *sd = (struct sd *) gspca_dev;
6419 struct usb_device *dev = gspca_dev->dev;
6420 const __u8 *Tgamma, *Tgradient;
6421 int g, i, k;
6422 static const __u8 kgamma_tb[16] = /* delta for contrast */
6423 {0x15, 0x0d, 0x0a, 0x09, 0x08, 0x08, 0x08, 0x08,
6424 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
6425 static const __u8 kgrad_tb[16] =
6426 {0x1b, 0x06, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00,
6427 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x04};
6428 static const __u8 Tgamma_1[16] =
6429 {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f,
6430 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff};
6431 static const __u8 Tgradient_1[16] =
6432 {0x00, 0x01, 0x05, 0x0b, 0x10, 0x15, 0x18, 0x1a,
6433 0x1a, 0x18, 0x16, 0x14, 0x12, 0x0f, 0x0d, 0x06};
6434 static const __u8 Tgamma_2[16] =
6435 {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c,
6436 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff};
6437 static const __u8 Tgradient_2[16] =
6438 {0x05, 0x0f, 0x16, 0x1a, 0x19, 0x19, 0x17, 0x15,
6439 0x12, 0x10, 0x0e, 0x0b, 0x09, 0x08, 0x06, 0x03};
6440 static const __u8 Tgamma_3[16] =
6441 {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac,
6442 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff};
6443 static const __u8 Tgradient_3[16] =
6444 {0x0c, 0x16, 0x1b, 0x1c, 0x19, 0x18, 0x15, 0x12,
6445 0x10, 0x0d, 0x0b, 0x09, 0x08, 0x06, 0x05, 0x03};
6446 static const __u8 Tgamma_4[16] =
6447 {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
6448 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff};
6449 static const __u8 Tgradient_4[16] =
6450 {0x26, 0x22, 0x20, 0x1c, 0x16, 0x13, 0x10, 0x0d,
6451 0x0b, 0x09, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02};
6452 static const __u8 Tgamma_5[16] =
6453 {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2,
6454 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff};
6455 static const __u8 Tgradient_5[16] =
6456 {0x37, 0x26, 0x20, 0x1a, 0x14, 0x10, 0x0e, 0x0b,
6457 0x09, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02};
6458 static const __u8 Tgamma_6[16] = /* ?? was gamma 5 */
6459 {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3,
6460 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff};
6461 static const __u8 Tgradient_6[16] =
6462 {0x18, 0x20, 0x20, 0x1c, 0x16, 0x13, 0x10, 0x0e,
6463 0x0b, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01};
6464 static const __u8 *gamma_tb[] = {
6465 NULL, Tgamma_1, Tgamma_2,
6466 Tgamma_3, Tgamma_4, Tgamma_5, Tgamma_6
6467 };
6468 static const __u8 *gradient_tb[] = {
6469 NULL, Tgradient_1, Tgradient_2,
6470 Tgradient_3, Tgradient_4, Tgradient_5, Tgradient_6
6471 };
6472#ifdef CONFIG_VIDEO_ADV_DEBUG
6473 __u8 v[16];
6474#endif
6475
6476 Tgamma = gamma_tb[sd->gamma];
6477 Tgradient = gradient_tb[sd->gamma];
6478
6479 k = (sd->contrast - 128) /* -128 / 128 */
6480 * Tgamma[0];
6481 PDEBUG(D_CONF, "gamma:%d contrast:%d gamma coeff: %d/128",
6482 sd->gamma, sd->contrast, k);
6483 for (i = 0; i < 16; i++) {
6484 g = Tgamma[i] + kgamma_tb[i] * k / 128;
6485 if (g > 0xff)
6486 g = 0xff;
6487 else if (g <= 0)
6488 g = 1;
6489 reg_w(dev, g, 0x0120 + i); /* gamma */
6490#ifdef CONFIG_VIDEO_ADV_DEBUG
6491 if (gspca_debug & D_CONF)
6492 v[i] = g;
6493#endif
6494 }
6495 PDEBUG(D_CONF, "tb: %02x %02x %02x %02x %02x %02x %02x %02x",
6496 v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
6497 PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x",
6498 v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]);
6499 for (i = 0; i < 16; i++) {
6500 g = Tgradient[i] - kgrad_tb[i] * k / 128;
6501 if (g > 0xff)
6502 g = 0xff;
6503 else if (g <= 0) {
6504 if (i != 15)
6505 g = 0;
6506 else
6507 g = 1;
6508 }
6509 reg_w(dev, g, 0x0130 + i); /* gradient */
6510#ifdef CONFIG_VIDEO_ADV_DEBUG
6511 if (gspca_debug & D_CONF)
6512 v[i] = g;
6513#endif
6514 }
6515 PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x",
6516 v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
6517 PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x",
6518 v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]);
6519}
6520
6521static void setquality(struct gspca_dev *gspca_dev)
6522{
6523 struct sd *sd = (struct sd *) gspca_dev;
6524 struct usb_device *dev = gspca_dev->dev;
6525 __u8 quality;
6526 __u8 frxt;
6527
6528 switch (sd->sensor) {
6529 case SENSOR_GC0305:
6530 case SENSOR_OV7620:
6531 case SENSOR_PO2030:
6532 return;
6533 }
6534/*fixme: is it really 0008 0007 0018 for all other sensors? */
6535 quality = sd->qindex;
6536 reg_w(dev, quality, 0x0008);
6537 frxt = 0x30;
6538 reg_w(dev, frxt, 0x0007);
6539 switch (quality) {
6540 case 0:
6541 case 1:
6542 case 2:
6543 frxt = 0xff;
6544 break;
6545 case 3:
6546 frxt = 0xf0;
6547 break;
6548 case 4:
6549 frxt = 0xe0;
6550 break;
6551 case 5:
6552 frxt = 0x20;
6553 break;
6554 }
6555 reg_w(dev, frxt, 0x0018);
6556}
6557
6558/* Matches the sensor's internal frame rate to the lighting frequency.
6559 * Valid frequencies are:
6560 * 50Hz, for European and Asian lighting (default)
6561 * 60Hz, for American lighting
6562 * 0 = No Fliker (for outdoore usage)
6563 * Returns: 0 for success
6564 */
6565static int setlightfreq(struct gspca_dev *gspca_dev)
6566{
6567 struct sd *sd = (struct sd *) gspca_dev;
6568 int i, mode;
6569 const struct usb_action *zc3_freq;
6570 static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
6571/* SENSOR_CS2102 0 */
6572 {cs2102_NoFliker, cs2102_NoFlikerScale,
6573 cs2102_50HZ, cs2102_50HZScale,
6574 cs2102_60HZ, cs2102_60HZScale},
6575/* SENSOR_CS2102K 1 */
6576 {cs2102_NoFliker, cs2102_NoFlikerScale,
6577 cs2102_50HZ, cs2102_50HZScale,
6578 cs2102_60HZ, cs2102_60HZScale},
6579/* SENSOR_GC0305 2 */
6580 {gc0305_NoFliker, gc0305_NoFliker,
6581 gc0305_50HZ, gc0305_50HZ,
6582 gc0305_60HZ, gc0305_60HZ},
6583/* SENSOR_HDCS2020 3 */
6584 {NULL, NULL,
6585 NULL, NULL,
6586 NULL, NULL},
6587/* SENSOR_HDCS2020b 4 */
6588 {hdcs2020b_NoFliker, hdcs2020b_NoFliker,
6589 hdcs2020b_50HZ, hdcs2020b_50HZ,
6590 hdcs2020b_60HZ, hdcs2020b_60HZ},
6591/* SENSOR_HV7131B 5 */
6592 {NULL, NULL,
6593 NULL, NULL,
6594 NULL, NULL},
6595/* SENSOR_HV7131C 6 */
6596 {NULL, NULL,
6597 NULL, NULL,
6598 NULL, NULL},
6599/* SENSOR_ICM105A 7 */
6600 {icm105a_NoFliker, icm105a_NoFlikerScale,
6601 icm105a_50HZ, icm105a_50HZScale,
6602 icm105a_60HZ, icm105a_60HZScale},
6603/* SENSOR_MC501CB 8 */
6604 {MC501CB_NoFliker, MC501CB_NoFlikerScale,
6605 MC501CB_50HZ, MC501CB_50HZScale,
6606 MC501CB_60HZ, MC501CB_60HZScale},
6607/* SENSOR_OV7620 9 */
6608 {OV7620_NoFliker, OV7620_NoFliker,
6609 OV7620_50HZ, OV7620_50HZ,
6610 OV7620_60HZ, OV7620_60HZ},
6611/* SENSOR_OV7630C 10 */
6612 {NULL, NULL,
6613 NULL, NULL,
6614 NULL, NULL},
6615/* SENSOR_PAS106 11 */
6616 {pas106b_NoFliker, pas106b_NoFliker,
6617 pas106b_50HZ, pas106b_50HZ,
6618 pas106b_60HZ, pas106b_60HZ},
6619/* SENSOR_PB0330 12 */
6620 {pb0330_NoFliker, pb0330_NoFlikerScale,
6621 pb0330_50HZ, pb0330_50HZScale,
6622 pb0330_60HZ, pb0330_60HZScale},
6623/* SENSOR_PO2030 13 */
6624 {PO2030_NoFliker, PO2030_NoFliker,
6625 PO2030_50HZ, PO2030_50HZ,
6626 PO2030_60HZ, PO2030_60HZ},
6627/* SENSOR_TAS5130CK 14 */
6628 {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale,
6629 tas5130cxx_50HZ, tas5130cxx_50HZScale,
6630 tas5130cxx_60HZ, tas5130cxx_60HZScale},
6631/* SENSOR_TAS5130CXX 15 */
6632 {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale,
6633 tas5130cxx_50HZ, tas5130cxx_50HZScale,
6634 tas5130cxx_60HZ, tas5130cxx_60HZScale},
6635/* SENSOR_TAS5130C_VF0250 16 */
6636 {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale,
6637 tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale,
6638 tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale},
6639 };
6640
6641 i = sd->lightfreq * 2;
6642 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
6643 if (!mode)
6644 i++; /* 640x480 */
6645 zc3_freq = freq_tb[(int) sd->sensor][i];
6646 if (zc3_freq != NULL) {
6647 usb_exchange(gspca_dev, zc3_freq);
6648 switch (sd->sensor) {
6649 case SENSOR_GC0305:
6650 if (mode /* if 320x240 */
6651 && sd->lightfreq == 1) /* and 50Hz */
6652 reg_w(gspca_dev->dev, 0x85, 0x018d);
6653 /* win: 0x80, 0x018d */
6654 break;
6655 case SENSOR_OV7620:
6656 if (!mode) { /* if 640x480 */
6657 if (sd->lightfreq != 0) /* and 50 or 60 Hz */
6658 reg_w(gspca_dev->dev, 0x40, 0x0002);
6659 else
6660 reg_w(gspca_dev->dev, 0x44, 0x0002);
6661 }
6662 break;
6663 }
6664 }
6665 return 0;
6666}
6667
6668static void setautogain(struct gspca_dev *gspca_dev)
6669{
6670 struct sd *sd = (struct sd *) gspca_dev;
6671 __u8 autoval;
6672
6673 if (sd->autogain)
6674 autoval = 0x42;
6675 else
6676 autoval = 0x02;
6677 reg_w(gspca_dev->dev, autoval, 0x0180);
6678}
6679
6680static void send_unknown(struct usb_device *dev, int sensor)
6681{
6682 reg_w(dev, 0x01, 0x0000); /* led off */
6683 switch (sensor) {
6684 case SENSOR_PAS106:
6685 reg_w(dev, 0x03, 0x003a);
6686 reg_w(dev, 0x0c, 0x003b);
6687 reg_w(dev, 0x08, 0x0038);
6688 break;
6689 case SENSOR_GC0305:
6690 case SENSOR_OV7620:
6691 case SENSOR_PB0330:
6692 case SENSOR_PO2030:
6693 reg_w(dev, 0x0d, 0x003a);
6694 reg_w(dev, 0x02, 0x003b);
6695 reg_w(dev, 0x00, 0x0038);
6696 break;
6697 }
6698}
6699
6700/* start probe 2 wires */
6701static void start_2wr_probe(struct usb_device *dev, int sensor)
6702{
6703 reg_w(dev, 0x01, 0x0000);
6704 reg_w(dev, sensor, 0x0010);
6705 reg_w(dev, 0x01, 0x0001);
6706 reg_w(dev, 0x03, 0x0012);
6707 reg_w(dev, 0x01, 0x0012);
6708/* msleep(2); */
6709}
6710
6711static int sif_probe(struct gspca_dev *gspca_dev)
6712{
6713 __u16 checkword;
6714
6715 start_2wr_probe(gspca_dev->dev, 0x0f); /* PAS106 */
6716 reg_w(gspca_dev->dev, 0x08, 0x008d);
6717 msleep(150);
6718 checkword = ((i2c_read(gspca_dev, 0x00) & 0x0f) << 4)
6719 | ((i2c_read(gspca_dev, 0x01) & 0xf0) >> 4);
6720 PDEBUG(D_PROBE, "probe sif 0x%04x", checkword);
6721 if (checkword == 0x0007) {
6722 send_unknown(gspca_dev->dev, SENSOR_PAS106);
6723 return 0x0f; /* PAS106 */
6724 }
6725 return -1;
6726}
6727
6728static int vga_2wr_probe(struct gspca_dev *gspca_dev)
6729{
6730 struct usb_device *dev = gspca_dev->dev;
6731 __u8 retbyte;
6732 __u16 checkword;
6733
6734 start_2wr_probe(dev, 0x00); /* HV7131B */
6735 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6736 retbyte = i2c_read(gspca_dev, 0x01);
6737 if (retbyte != 0)
6738 return 0x00; /* HV7131B */
6739
6740 start_2wr_probe(dev, 0x04); /* CS2102 */
6741 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6742 retbyte = i2c_read(gspca_dev, 0x01);
6743 if (retbyte != 0)
6744 return 0x04; /* CS2102 */
6745
6746 start_2wr_probe(dev, 0x06); /* OmniVision */
6747 reg_w(dev, 0x08, 0x8d);
6748 i2c_write(gspca_dev, 0x11, 0xaa, 0x00);
6749 retbyte = i2c_read(gspca_dev, 0x11);
6750 if (retbyte != 0) {
6751 /* (should have returned 0xaa) --> Omnivision? */
6752 /* reg_r 0x10 -> 0x06 --> */
6753 goto ov_check;
6754 }
6755
6756 start_2wr_probe(dev, 0x08); /* HDCS2020 */
6757 i2c_write(gspca_dev, 0x15, 0xaa, 0x00);
6758 retbyte = i2c_read(gspca_dev, 0x15);
6759 if (retbyte != 0)
6760 return 0x08; /* HDCS2020 */
6761
6762 start_2wr_probe(dev, 0x0a); /* PB0330 */
6763 i2c_write(gspca_dev, 0x07, 0xaa, 0xaa);
6764 retbyte = i2c_read(gspca_dev, 0x07);
6765 if (retbyte != 0)
6766 return 0x0a; /* PB0330 */
6767 retbyte = i2c_read(gspca_dev, 0x03);
6768 if (retbyte != 0)
6769 return 0x0a; /* PB0330 ?? */
6770 retbyte = i2c_read(gspca_dev, 0x04);
6771 if (retbyte != 0)
6772 return 0x0a; /* PB0330 ?? */
6773
6774 start_2wr_probe(dev, 0x0c); /* ICM105A */
6775 i2c_write(gspca_dev, 0x01, 0x11, 0x00);
6776 retbyte = i2c_read(gspca_dev, 0x01);
6777 if (retbyte != 0)
6778 return 0x0c; /* ICM105A */
6779
6780 start_2wr_probe(dev, 0x0e); /* PAS202BCB */
6781 reg_w(dev, 0x08, 0x8d);
6782 i2c_write(gspca_dev, 0x03, 0xaa, 0x00);
6783 msleep(500);
6784 retbyte = i2c_read(gspca_dev, 0x03);
6785 if (retbyte != 0)
6786 return 0x0e; /* PAS202BCB */
6787
6788 start_2wr_probe(dev, 0x02); /* ?? */
6789 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6790 retbyte = i2c_read(gspca_dev, 0x01);
6791 if (retbyte != 0)
6792 return 0x02; /* ?? */
6793ov_check:
6794 reg_r(gspca_dev, 0x0010); /* ?? */
6795 reg_r(gspca_dev, 0x0010);
6796
6797 reg_w(dev, 0x01, 0x0000);
6798 reg_w(dev, 0x01, 0x0001);
6799 reg_w(dev, 0x06, 0x0010); /* OmniVision */
6800 reg_w(dev, 0xa1, 0x008b);
6801 reg_w(dev, 0x08, 0x008d);
6802 msleep(500);
6803 reg_w(dev, 0x01, 0x0012);
6804 i2c_write(gspca_dev, 0x12, 0x80, 0x00); /* sensor reset */
6805 retbyte = i2c_read(gspca_dev, 0x0a);
6806 checkword = retbyte << 8;
6807 retbyte = i2c_read(gspca_dev, 0x0b);
6808 checkword |= retbyte;
6809 PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", checkword);
6810 switch (checkword) {
6811 case 0x7631: /* OV7630C */
6812 reg_w(dev, 0x06, 0x0010);
6813 break;
6814 case 0x7620: /* OV7620 */
6815 case 0x7648: /* OV7648 */
6816 break;
6817 default:
6818 return -1; /* not OmniVision */
6819 }
6820 return checkword;
6821}
6822
6823struct sensor_by_chipset_revision {
6824 __u16 revision;
6825 __u8 internal_sensor_id;
6826};
6827static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
6828 {0xc001, 0x13}, /* MI0360 */
6829 {0xe001, 0x13},
6830 {0x8001, 0x13},
6831 {0x8000, 0x14}, /* CS2102K */
6832 {0x8400, 0x15}, /* TAS5130K */
6833 {0, 0}
6834};
6835
6836static int vga_3wr_probe(struct gspca_dev *gspca_dev)
6837{
6838 struct sd *sd = (struct sd *) gspca_dev;
6839 struct usb_device *dev = gspca_dev->dev;
6840 int i;
6841 __u8 retbyte;
6842 __u16 checkword;
6843
6844/*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/
6845 reg_w(dev, 0x02, 0x0010);
6846 reg_r(gspca_dev, 0x10);
6847 reg_w(dev, 0x01, 0x0000);
6848 reg_w(dev, 0x00, 0x0010);
6849 reg_w(dev, 0x01, 0x0001);
6850 reg_w(dev, 0x91, 0x008b);
6851 reg_w(dev, 0x03, 0x0012);
6852 reg_w(dev, 0x01, 0x0012);
6853 reg_w(dev, 0x05, 0x0012);
6854 retbyte = i2c_read(gspca_dev, 0x14);
6855 if (retbyte != 0)
6856 return 0x11; /* HV7131R */
6857 retbyte = i2c_read(gspca_dev, 0x15);
6858 if (retbyte != 0)
6859 return 0x11; /* HV7131R */
6860 retbyte = i2c_read(gspca_dev, 0x16);
6861 if (retbyte != 0)
6862 return 0x11; /* HV7131R */
6863
6864 reg_w(dev, 0x02, 0x0010);
6865 retbyte = reg_r(gspca_dev, 0x000b);
6866 checkword = retbyte << 8;
6867 retbyte = reg_r(gspca_dev, 0x000a);
6868 checkword |= retbyte;
6869 PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", checkword);
6870 reg_r(gspca_dev, 0x0010);
6871 /* this is tested only once anyway */
6872 i = 0;
6873 while (chipset_revision_sensor[i].revision) {
6874 if (chipset_revision_sensor[i].revision == checkword) {
6875 sd->chip_revision = checkword;
6876 send_unknown(dev, SENSOR_PB0330);
6877 return chipset_revision_sensor[i].internal_sensor_id;
6878 }
6879 i++;
6880 }
6881
6882 reg_w(dev, 0x01, 0x0000);
6883 reg_w(dev, 0x01, 0x0001);
6884 reg_w(dev, 0xdd, 0x008b);
6885 reg_w(dev, 0x0a, 0x0010);
6886 reg_w(dev, 0x03, 0x0012);
6887 reg_w(dev, 0x01, 0x0012);
6888 retbyte = i2c_read(gspca_dev, 0x00);
6889 if (retbyte != 0) {
6890 PDEBUG(D_PROBE, "probe 3wr vga type 0a ?");
6891 return 0x0a; /* ?? */
6892 }
6893
6894 reg_w(dev, 0x01, 0x0000);
6895 reg_w(dev, 0x01, 0x0001);
6896 reg_w(dev, 0x98, 0x008b);
6897 reg_w(dev, 0x01, 0x0010);
6898 reg_w(dev, 0x03, 0x0012);
6899 msleep(2);
6900 reg_w(dev, 0x01, 0x0012);
6901 retbyte = i2c_read(gspca_dev, 0x00);
6902 if (retbyte != 0) {
6903 PDEBUG(D_PROBE, "probe 3wr vga type %02x", retbyte);
6904 send_unknown(dev, SENSOR_GC0305);
6905 return retbyte; /* 0x29 = gc0305 - should continue? */
6906 }
6907
6908 reg_w(dev, 0x01, 0x0000); /* check OmniVision */
6909 reg_w(dev, 0x01, 0x0001);
6910 reg_w(dev, 0xa1, 0x008b);
6911 reg_w(dev, 0x08, 0x008d);
6912 reg_w(dev, 0x06, 0x0010);
6913 reg_w(dev, 0x01, 0x0012);
6914 reg_w(dev, 0x05, 0x0012);
6915 if (i2c_read(gspca_dev, 0x1c) == 0x7f /* OV7610 - manufacturer ID */
6916 && i2c_read(gspca_dev, 0x1d) == 0xa2) {
6917 send_unknown(dev, SENSOR_OV7620);
6918 return 0x06; /* OmniVision confirm ? */
6919 }
6920
6921 reg_w(dev, 0x01, 0x00);
6922 reg_w(dev, 0x00, 0x02);
6923 reg_w(dev, 0x01, 0x10);
6924 reg_w(dev, 0x01, 0x01);
6925 reg_w(dev, 0xee, 0x8b);
6926 reg_w(dev, 0x03, 0x12);
6927/* msleep(150); */
6928 reg_w(dev, 0x01, 0x12);
6929 reg_w(dev, 0x05, 0x12);
6930 retbyte = i2c_read(gspca_dev, 0x00); /* ID 0 */
6931 checkword = retbyte << 8;
6932 retbyte = i2c_read(gspca_dev, 0x01); /* ID 1 */
6933 checkword |= retbyte;
6934 PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", checkword);
6935 if (checkword == 0x2030) {
6936 retbyte = i2c_read(gspca_dev, 0x02); /* revision number */
6937 PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte);
6938 send_unknown(dev, SENSOR_PO2030);
6939 return checkword;
6940 }
6941
6942 reg_w(dev, 0x01, 0x00);
6943 reg_w(dev, 0x0a, 0x10);
6944 reg_w(dev, 0xd3, 0x8b);
6945 reg_w(dev, 0x01, 0x01);
6946 reg_w(dev, 0x03, 0x12);
6947 reg_w(dev, 0x01, 0x12);
6948 reg_w(dev, 0x05, 0x01);
6949 reg_w(dev, 0xd3, 0x8b);
6950 retbyte = i2c_read(gspca_dev, 0x01);
6951 if (retbyte != 0) {
6952 PDEBUG(D_PROBE, "probe 3wr vga type 0a ?");
6953 return 0x0a; /* ?? */
6954 }
6955 return -1;
6956}
6957
6958static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
6959{
6960 struct sd *sd = (struct sd *) gspca_dev;
6961 int sensor, sensor2;
6962
6963 switch (sd->sensor) {
6964 case SENSOR_MC501CB:
6965 case SENSOR_TAS5130C_VF0250:
6966 return -1; /* don't probe */
6967 }
6968 sensor = vga_2wr_probe(gspca_dev);
6969 if (sensor >= 0) {
6970 if (sensor < 0x7600)
6971 return sensor;
6972 /* next probe is needed for OmniVision ? */
6973 }
6974 sensor2 = vga_3wr_probe(gspca_dev);
6975 if (sensor2 >= 0) {
6976 if (sensor >= 0)
6977 return sensor;
6978 return sensor2;
6979 }
6980 return sif_probe(gspca_dev);
6981}
6982
6983/* this function is called at probe time */
6984static int sd_config(struct gspca_dev *gspca_dev,
6985 const struct usb_device_id *id)
6986{
6987 struct sd *sd = (struct sd *) gspca_dev;
6988 struct cam *cam;
6989 int sensor;
6990 int vga = 1; /* 1: vga, 0: sif */
6991 static const __u8 gamma[SENSOR_MAX] = {
6992 5, /* SENSOR_CS2102 0 */
6993 5, /* SENSOR_CS2102K 1 */
6994 4, /* SENSOR_GC0305 2 */
6995 4, /* SENSOR_HDCS2020 3 */
6996 4, /* SENSOR_HDCS2020b 4 */
6997 4, /* SENSOR_HV7131B 5 */
6998 4, /* SENSOR_HV7131C 6 */
6999 4, /* SENSOR_ICM105A 7 */
7000 4, /* SENSOR_MC501CB 8 */
7001 3, /* SENSOR_OV7620 9 */
7002 4, /* SENSOR_OV7630C 10 */
7003 4, /* SENSOR_PAS106 11 */
7004 4, /* SENSOR_PB0330 12 */
7005 4, /* SENSOR_PO2030 13 */
7006 4, /* SENSOR_TAS5130CK 14 */
7007 4, /* SENSOR_TAS5130CXX 15 */
7008 3, /* SENSOR_TAS5130C_VF0250 16 */
7009 };
7010
7011 /* define some sensors from the vendor/product */
7012 sd->sharpness = 2;
7013 switch (id->idVendor) {
7014 case 0x041e: /* Creative */
7015 switch (id->idProduct) {
7016 case 0x4051: /* zc301 chips */
7017 case 0x4053:
7018 sd->sensor = SENSOR_TAS5130C_VF0250;
7019 break;
7020 }
7021 break;
7022 case 0x046d: /* Logitech Labtec */
7023 switch (id->idProduct) {
7024 case 0x08dd:
7025 sd->sensor = SENSOR_MC501CB;
7026 break;
7027 }
7028 break;
7029 case 0x0ac8: /* Vimicro z-star */
7030 switch (id->idProduct) {
7031 case 0x305b:
7032 sd->sensor = SENSOR_TAS5130C_VF0250;
7033 break;
7034 }
7035 break;
7036 }
7037 sensor = zcxx_probeSensor(gspca_dev);
7038 if (sensor >= 0)
7039 PDEBUG(D_PROBE, "probe sensor -> %02x", sensor);
7040 if ((unsigned) force_sensor < SENSOR_MAX) {
7041 sd->sensor = force_sensor;
7042 PDEBUG(D_PROBE, "sensor forced to %d", force_sensor);
7043 } else {
7044 switch (sensor) {
7045 case -1:
7046 switch (sd->sensor) {
7047 case SENSOR_MC501CB:
7048 PDEBUG(D_PROBE, "Sensor MC501CB");
7049 break;
7050 case SENSOR_TAS5130C_VF0250:
7051 PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)");
7052 break;
7053 default:
7054 PDEBUG(D_PROBE,
7055 "Sensor UNKNOW_0 force Tas5130");
7056 sd->sensor = SENSOR_TAS5130CXX;
7057 }
7058 break;
7059 case 0:
7060 PDEBUG(D_PROBE, "Find Sensor HV7131B");
7061 sd->sensor = SENSOR_HV7131B;
7062 break;
7063 case 0x04:
7064 PDEBUG(D_PROBE, "Find Sensor CS2102");
7065 sd->sensor = SENSOR_CS2102;
7066 break;
7067 case 0x08:
7068 PDEBUG(D_PROBE, "Find Sensor HDCS2020(b)");
7069 sd->sensor = SENSOR_HDCS2020b;
7070 break;
7071 case 0x0a:
7072 PDEBUG(D_PROBE,
7073 "Find Sensor PB0330. Chip revision %x",
7074 sd->chip_revision);
7075 sd->sensor = SENSOR_PB0330;
7076 break;
7077 case 0x0c:
7078 PDEBUG(D_PROBE, "Find Sensor ICM105A");
7079 sd->sensor = SENSOR_ICM105A;
7080 break;
7081 case 0x0e:
7082 PDEBUG(D_PROBE, "Find Sensor HDCS2020");
7083 sd->sensor = SENSOR_HDCS2020;
7084 sd->sharpness = 1;
7085 break;
7086 case 0x0f:
7087 PDEBUG(D_PROBE, "Find Sensor PAS106");
7088 sd->sensor = SENSOR_PAS106;
7089 vga = 0; /* SIF */
7090 break;
7091 case 0x10:
7092 case 0x12:
7093 PDEBUG(D_PROBE, "Find Sensor TAS5130");
7094 sd->sensor = SENSOR_TAS5130CXX;
7095 break;
7096 case 0x11:
7097 PDEBUG(D_PROBE, "Find Sensor HV7131R(c)");
7098 sd->sensor = SENSOR_HV7131C;
7099 break;
7100 case 0x13:
7101 PDEBUG(D_PROBE,
7102 "Find Sensor MI0360. Chip revision %x",
7103 sd->chip_revision);
7104 sd->sensor = SENSOR_PB0330;
7105 break;
7106 case 0x14:
7107 PDEBUG(D_PROBE,
7108 "Find Sensor CS2102K?. Chip revision %x",
7109 sd->chip_revision);
7110 sd->sensor = SENSOR_CS2102K;
7111 break;
7112 case 0x15:
7113 PDEBUG(D_PROBE,
7114 "Find Sensor TAS5130CK?. Chip revision %x",
7115 sd->chip_revision);
7116 sd->sensor = SENSOR_TAS5130CK;
7117 break;
7118 case 0x29:
7119 PDEBUG(D_PROBE, "Find Sensor GC0305");
7120 sd->sensor = SENSOR_GC0305;
7121 break;
7122 case 0x2030:
7123 PDEBUG(D_PROBE, "Find Sensor PO2030");
7124 sd->sensor = SENSOR_PO2030;
7125 sd->sharpness = 0; /* from win traces */
7126 break;
7127 case 0x7620:
7128 PDEBUG(D_PROBE, "Find Sensor OV7620");
7129 sd->sensor = SENSOR_OV7620;
7130 break;
7131 case 0x7648:
7132 PDEBUG(D_PROBE, "Find Sensor OV7648");
7133 sd->sensor = SENSOR_OV7620; /* same sensor (?) */
7134 break;
7135 default:
7136 PDEBUG(D_ERR|D_PROBE, "Unknown sensor %02x", sensor);
7137 return -EINVAL;
7138 }
7139 }
7140 if (sensor < 0x20) {
7141 if (sensor == -1 || sensor == 0x10 || sensor == 0x12)
7142 reg_w(gspca_dev->dev, 0x02, 0x0010);
7143 else
7144 reg_w(gspca_dev->dev, sensor & 0x0f, 0x0010);
7145 reg_r(gspca_dev, 0x0010);
7146 }
7147
7148 cam = &gspca_dev->cam;
7149 cam->dev_name = (char *) id->driver_info;
7150 cam->epaddr = 0x01;
7151/*fixme:test*/
7152 gspca_dev->nbalt--;
7153 if (vga) {
7154 cam->cam_mode = vga_mode;
7155 cam->nmodes = ARRAY_SIZE(vga_mode);
7156 } else {
7157 cam->cam_mode = sif_mode;
7158 cam->nmodes = ARRAY_SIZE(sif_mode);
7159 }
7160 sd->qindex = 1;
7161 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
7162 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
7163 sd->gamma = gamma[(int) sd->sensor];
7164 sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
7165 sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value;
7166 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
7167
7168 /* switch the led off */
7169 reg_w(gspca_dev->dev, 0x01, 0x0000);
7170 return 0;
7171}
7172
7173/* this function is called at open time */
7174static int sd_open(struct gspca_dev *gspca_dev)
7175{
7176 reg_w(gspca_dev->dev, 0x01, 0x0000);
7177 return 0;
7178}
7179
7180static void sd_start(struct gspca_dev *gspca_dev)
7181{
7182 struct sd *sd = (struct sd *) gspca_dev;
7183 struct usb_device *dev = gspca_dev->dev;
7184 const struct usb_action *zc3_init;
7185 int mode;
7186 static const struct usb_action *init_tb[SENSOR_MAX][2] = {
7187 {cs2102_InitialScale, cs2102_Initial}, /* 0 */
7188 {cs2102K_InitialScale, cs2102K_Initial}, /* 1 */
7189 {gc0305_Initial, gc0305_InitialScale}, /* 2 */
7190 {hdcs2020xx_InitialScale, hdcs2020xx_Initial}, /* 3 */
7191 {hdcs2020xb_InitialScale, hdcs2020xb_Initial}, /* 4 */
7192 {hv7131bxx_InitialScale, hv7131bxx_Initial}, /* 5 */
7193 {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 6 */
7194 {icm105axx_InitialScale, icm105axx_Initial}, /* 7 */
7195 {MC501CB_InitialScale, MC501CB_Initial}, /* 9 */
7196 {OV7620_mode0, OV7620_mode1}, /* 9 */
7197 {ov7630c_InitialScale, ov7630c_Initial}, /* 10 */
7198 {pas106b_InitialScale, pas106b_Initial}, /* 11 */
7199 {pb0330xx_InitialScale, pb0330xx_Initial}, /* 12 */
7200/* or {pb03303x_InitialScale, pb03303x_Initial}, */
7201 {PO2030_mode0, PO2030_mode1}, /* 13 */
7202 {tas5130CK_InitialScale, tas5130CK_Initial}, /* 14 */
7203 {tas5130cxx_InitialScale, tas5130cxx_Initial}, /* 15 */
7204 {tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial},
7205 /* 16 */
7206 };
7207
7208 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
7209 zc3_init = init_tb[(int) sd->sensor][mode];
7210 switch (sd->sensor) {
7211 case SENSOR_HV7131B:
7212 case SENSOR_HV7131C:
7213 zcxx_probeSensor(gspca_dev);
7214 break;
7215 case SENSOR_PAS106:
7216 usb_exchange(gspca_dev, pas106b_Initial_com);
7217 break;
7218 case SENSOR_PB0330:
7219 if (mode) {
7220 if (sd->chip_revision == 0xc001
7221 || sd->chip_revision == 0xe001
7222 || sd->chip_revision == 0x8001)
7223 zc3_init = pb03303x_Initial;
7224 } else {
7225 if (sd->chip_revision == 0xc001
7226 || sd->chip_revision == 0xe001
7227 || sd->chip_revision == 0x8001)
7228 zc3_init = pb03303x_InitialScale;
7229 }
7230 break;
7231 }
7232 usb_exchange(gspca_dev, zc3_init);
7233
7234 switch (sd->sensor) {
7235 case SENSOR_GC0305:
7236 case SENSOR_OV7620:
7237 case SENSOR_PO2030:
7238 msleep(100); /* ?? */
7239 reg_r(gspca_dev, 0x0002); /* --> 0x40 */
7240 reg_w(dev, 0x09, 0x01ad); /* (from win traces) */
7241 reg_w(dev, 0x15, 0x01ae);
7242 reg_w(dev, 0x0d, 0x003a);
7243 reg_w(dev, 0x02, 0x003b);
7244 reg_w(dev, 0x00, 0x0038);
7245 break;
7246 }
7247
7248 setmatrix(gspca_dev);
7249 setbrightness(gspca_dev);
7250 switch (sd->sensor) {
7251 case SENSOR_OV7620:
7252 reg_r(gspca_dev, 0x0008);
7253 reg_w(dev, 0x00, 0x0008);
7254 break;
7255 case SENSOR_GC0305:
7256 reg_r(gspca_dev, 0x0008);
7257 /* fall thru */
7258 case SENSOR_PO2030:
7259 reg_w(dev, 0x03, 0x0008);
7260 break;
7261 }
7262 setsharpness(gspca_dev);
7263
7264 /* set the gamma tables when not set */
7265 switch (sd->sensor) {
7266 case SENSOR_CS2102: /* gamma set in xxx_Initial */
7267 case SENSOR_CS2102K:
7268 case SENSOR_HDCS2020:
7269 case SENSOR_HDCS2020b:
7270 case SENSOR_PB0330: /* pb with chip_revision - see above */
7271 case SENSOR_OV7630C:
7272 case SENSOR_TAS5130CK:
7273 break;
7274 default:
7275 setcontrast(gspca_dev);
7276 break;
7277 }
7278 setmatrix(gspca_dev); /* one more time? */
7279 switch (sd->sensor) {
7280 case SENSOR_OV7620:
7281 reg_r(gspca_dev, 0x0180); /* from win */
7282 reg_w(dev, 0x00, 0x0180);
7283 break;
7284 default:
7285 setquality(gspca_dev);
7286 break;
7287 }
7288 setlightfreq(gspca_dev);
7289
7290 switch (sd->sensor) {
7291 case SENSOR_GC0305:
7292 case SENSOR_OV7620:
7293 reg_w(dev, 0x09, 0x01ad); /* (from win traces) */
7294 reg_w(dev, 0x15, 0x01ae);
7295 sd->autogain = 0;
7296 break;
7297 case SENSOR_PO2030:
7298 reg_w(dev, 0x40, 0x0117); /* (from win traces) */
7299 reg_r(gspca_dev, 0x0180);
7300 break;
7301 }
7302
7303 setautogain(gspca_dev);
7304 switch (sd->sensor) {
7305 case SENSOR_GC0305:
7306/* setlightfreq(gspca_dev); ?? (end: 80 -> [18d]) */
7307 reg_w(dev, 0x09, 0x01ad); /* (from win traces) */
7308 reg_w(dev, 0x15, 0x01ae);
7309 reg_w(dev, 0x40, 0x0180);
7310 reg_w(dev, 0x40, 0x0117);
7311 reg_r(gspca_dev, 0x0180);
7312 sd->autogain = 1;
7313 setautogain(gspca_dev);
7314 break;
7315 case SENSOR_OV7620:
7316 i2c_read(gspca_dev, 0x13); /*fixme: returns 0xa3 */
7317 i2c_write(gspca_dev, 0x13, 0xa3, 0x00);
7318 /*fixme: returned value to send? */
7319 reg_w(dev, 0x40, 0x0117); /* (from win traces) */
7320 reg_r(gspca_dev, 0x0180);
7321 setautogain(gspca_dev);
7322 msleep(500);
7323 break;
7324 case SENSOR_PO2030:
7325 msleep(500);
7326 reg_r(gspca_dev, 0x0008);
7327 reg_r(gspca_dev, 0x0007);
7328 reg_w(dev, 0x00, 0x0007); /* (from win traces) */
7329 reg_w(dev, 0x02, 0x0008);
7330 break;
7331 }
7332}
7333
7334static void sd_stopN(struct gspca_dev *gspca_dev)
7335{
7336}
7337
7338static void sd_stop0(struct gspca_dev *gspca_dev)
7339{
7340 struct sd *sd = (struct sd *) gspca_dev;
7341
7342 send_unknown(gspca_dev->dev, sd->sensor);
7343}
7344
7345/* this function is called at close time */
7346static void sd_close(struct gspca_dev *gspca_dev)
7347{
7348}
7349
7350static void sd_pkt_scan(struct gspca_dev *gspca_dev,
7351 struct gspca_frame *frame,
7352 __u8 *data,
7353 int len)
7354{
7355
7356 if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */
7357 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
7358 data, 0);
7359 /* put the JPEG header in the new frame */
7360 jpeg_put_header(gspca_dev, frame,
7361 ((struct sd *) gspca_dev)->qindex,
7362 0x21);
7363 /* remove the webcam's header:
7364 * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp
7365 * - 'ss ss' is the frame sequence number (BE)
7366 * - 'ww ww' and 'hh hh' are the window dimensions (BE)
7367 * - 'pp pp' is the packet sequence number (BE)
7368 */
7369 data += 18;
7370 len -= 18;
7371 }
7372 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
7373}
7374
7375static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
7376{
7377 struct sd *sd = (struct sd *) gspca_dev;
7378
7379 sd->brightness = val;
7380 if (gspca_dev->streaming)
7381 setbrightness(gspca_dev);
7382 return 0;
7383}
7384
7385static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
7386{
7387 struct sd *sd = (struct sd *) gspca_dev;
7388
7389 *val = sd->brightness;
7390 return 0;
7391}
7392
7393static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
7394{
7395 struct sd *sd = (struct sd *) gspca_dev;
7396
7397 sd->contrast = val;
7398 if (gspca_dev->streaming)
7399 setcontrast(gspca_dev);
7400 return 0;
7401}
7402
7403static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
7404{
7405 struct sd *sd = (struct sd *) gspca_dev;
7406
7407 *val = sd->contrast;
7408 return 0;
7409}
7410
7411static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
7412{
7413 struct sd *sd = (struct sd *) gspca_dev;
7414
7415 sd->autogain = val;
7416 if (gspca_dev->streaming)
7417 setautogain(gspca_dev);
7418 return 0;
7419}
7420
7421static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
7422{
7423 struct sd *sd = (struct sd *) gspca_dev;
7424
7425 *val = sd->autogain;
7426 return 0;
7427}
7428
7429static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
7430{
7431 struct sd *sd = (struct sd *) gspca_dev;
7432
7433 sd->gamma = val;
7434 if (gspca_dev->streaming)
7435 setcontrast(gspca_dev);
7436 return 0;
7437}
7438
7439static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
7440{
7441 struct sd *sd = (struct sd *) gspca_dev;
7442
7443 *val = sd->gamma;
7444 return 0;
7445}
7446
7447static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
7448{
7449 struct sd *sd = (struct sd *) gspca_dev;
7450
7451 sd->lightfreq = val;
7452 if (gspca_dev->streaming)
7453 setlightfreq(gspca_dev);
7454 return 0;
7455}
7456
7457static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
7458{
7459 struct sd *sd = (struct sd *) gspca_dev;
7460
7461 *val = sd->lightfreq;
7462 return 0;
7463}
7464
7465static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
7466{
7467 struct sd *sd = (struct sd *) gspca_dev;
7468
7469 sd->sharpness = val;
7470 if (gspca_dev->streaming)
7471 setsharpness(gspca_dev);
7472 return 0;
7473}
7474
7475static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
7476{
7477 struct sd *sd = (struct sd *) gspca_dev;
7478
7479 *val = sd->sharpness;
7480 return 0;
7481}
7482
7483static int sd_querymenu(struct gspca_dev *gspca_dev,
7484 struct v4l2_querymenu *menu)
7485{
7486 switch (menu->id) {
7487 case V4L2_CID_POWER_LINE_FREQUENCY:
7488 switch (menu->index) {
7489 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
7490 strcpy((char *) menu->name, "NoFliker");
7491 return 0;
7492 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
7493 strcpy((char *) menu->name, "50 Hz");
7494 return 0;
7495 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
7496 strcpy((char *) menu->name, "60 Hz");
7497 return 0;
7498 }
7499 break;
7500 }
7501 return -EINVAL;
7502}
7503
7504static const struct sd_desc sd_desc = {
7505 .name = MODULE_NAME,
7506 .ctrls = sd_ctrls,
7507 .nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0],
7508 .config = sd_config,
7509 .open = sd_open,
7510 .start = sd_start,
7511 .stopN = sd_stopN,
7512 .stop0 = sd_stop0,
7513 .close = sd_close,
7514 .pkt_scan = sd_pkt_scan,
7515 .querymenu = sd_querymenu,
7516};
7517
7518#define DVNM(name) .driver_info = (kernel_ulong_t) name
7519static const __devinitdata struct usb_device_id device_table[] = {
7520 {USB_DEVICE(0x041e, 0x041e), DVNM("Creative WebCam Live!")},
7521#ifndef CONFIG_USB_ZC0301
7522 {USB_DEVICE(0x041e, 0x4017), DVNM("Creative Webcam Mobile PD1090")},
7523 {USB_DEVICE(0x041e, 0x401c), DVNM("Creative NX")},
7524 {USB_DEVICE(0x041e, 0x401e), DVNM("Creative Nx Pro")},
7525 {USB_DEVICE(0x041e, 0x401f), DVNM("Creative Webcam Notebook PD1171")},
7526#endif
7527 {USB_DEVICE(0x041e, 0x4029), DVNM("Creative WebCam Vista Pro")},
7528#ifndef CONFIG_USB_ZC0301
7529 {USB_DEVICE(0x041e, 0x4034), DVNM("Creative Instant P0620")},
7530 {USB_DEVICE(0x041e, 0x4035), DVNM("Creative Instant P0620D")},
7531 {USB_DEVICE(0x041e, 0x4036), DVNM("Creative Live !")},
7532 {USB_DEVICE(0x041e, 0x403a), DVNM("Creative Nx Pro 2")},
7533#endif
7534 {USB_DEVICE(0x041e, 0x4051), DVNM("Creative Notebook Pro (VF0250)")},
7535 {USB_DEVICE(0x041e, 0x4053), DVNM("Creative Live!Cam Video IM")},
7536#ifndef CONFIG_USB_ZC0301
7537 {USB_DEVICE(0x0458, 0x7007), DVNM("Genius VideoCam V2")},
7538 {USB_DEVICE(0x0458, 0x700c), DVNM("Genius VideoCam V3")},
7539 {USB_DEVICE(0x0458, 0x700f), DVNM("Genius VideoCam Web V2")},
7540#endif
7541 {USB_DEVICE(0x0461, 0x0a00), DVNM("MicroInnovation WebCam320")},
7542 {USB_DEVICE(0x046d, 0x08a0), DVNM("Logitech QC IM")},
7543 {USB_DEVICE(0x046d, 0x08a1), DVNM("Logitech QC IM 0x08A1 +sound")},
7544 {USB_DEVICE(0x046d, 0x08a2), DVNM("Labtec Webcam Pro")},
7545 {USB_DEVICE(0x046d, 0x08a3), DVNM("Logitech QC Chat")},
7546 {USB_DEVICE(0x046d, 0x08a6), DVNM("Logitech QCim")},
7547 {USB_DEVICE(0x046d, 0x08a7), DVNM("Logitech QuickCam Image")},
7548 {USB_DEVICE(0x046d, 0x08a9), DVNM("Logitech Notebook Deluxe")},
7549 {USB_DEVICE(0x046d, 0x08aa), DVNM("Labtec Webcam Notebook")},
7550 {USB_DEVICE(0x046d, 0x08ac), DVNM("Logitech QuickCam Cool")},
7551 {USB_DEVICE(0x046d, 0x08ad), DVNM("Logitech QCCommunicate STX")},
7552#ifndef CONFIG_USB_ZC0301
7553 {USB_DEVICE(0x046d, 0x08ae), DVNM("Logitech QuickCam for Notebooks")},
7554#endif
7555 {USB_DEVICE(0x046d, 0x08af), DVNM("Logitech QuickCam Cool")},
7556 {USB_DEVICE(0x046d, 0x08b9), DVNM("Logitech QC IM ???")},
7557 {USB_DEVICE(0x046d, 0x08d7), DVNM("Logitech QCam STX")},
7558 {USB_DEVICE(0x046d, 0x08d9), DVNM("Logitech QuickCam IM/Connect")},
7559 {USB_DEVICE(0x046d, 0x08d8), DVNM("Logitech Notebook Deluxe")},
7560 {USB_DEVICE(0x046d, 0x08da), DVNM("Logitech QuickCam Messenger")},
7561 {USB_DEVICE(0x046d, 0x08dd), DVNM("Logitech QuickCam for Notebooks")},
7562 {USB_DEVICE(0x0471, 0x0325), DVNM("Philips SPC 200 NC")},
7563 {USB_DEVICE(0x0471, 0x0326), DVNM("Philips SPC 300 NC")},
7564 {USB_DEVICE(0x0471, 0x032d), DVNM("Philips spc210nc")},
7565 {USB_DEVICE(0x0471, 0x032e), DVNM("Philips spc315nc")},
7566 {USB_DEVICE(0x055f, 0xc005), DVNM("Mustek Wcam300A")},
7567#ifndef CONFIG_USB_ZC0301
7568 {USB_DEVICE(0x055f, 0xd003), DVNM("Mustek WCam300A")},
7569 {USB_DEVICE(0x055f, 0xd004), DVNM("Mustek WCam300 AN")},
7570#endif
7571 {USB_DEVICE(0x0698, 0x2003), DVNM("CTX M730V built in")},
7572 {USB_DEVICE(0x0ac8, 0x0302), DVNM("Z-star Vimicro zc0302")},
7573#ifndef CONFIG_USB_ZC0301
7574 {USB_DEVICE(0x0ac8, 0x301b), DVNM("Z-Star zc301b")},
7575 {USB_DEVICE(0x0ac8, 0x303b), DVNM("Vimicro 0x303b")},
7576#endif
7577 {USB_DEVICE(0x0ac8, 0x305b), DVNM("Z-star Vimicro zc0305b")},
7578#ifndef CONFIG_USB_ZC0301
7579 {USB_DEVICE(0x0ac8, 0x307b), DVNM("Z-Star 307b")},
7580 {USB_DEVICE(0x10fd, 0x0128), DVNM("Typhoon Webshot II 300k 0x0128")},
7581 {USB_DEVICE(0x10fd, 0x8050), DVNM("Typhoon Webshot II USB 300k")},
7582#endif
7583 {} /* end of entry */
7584};
7585#undef DVNAME
7586MODULE_DEVICE_TABLE(usb, device_table);
7587
7588/* -- device connect -- */
7589static int sd_probe(struct usb_interface *intf,
7590 const struct usb_device_id *id)
7591{
7592 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
7593 THIS_MODULE);
7594}
7595
7596/* USB driver */
7597static struct usb_driver sd_driver = {
7598 .name = MODULE_NAME,
7599 .id_table = device_table,
7600 .probe = sd_probe,
7601 .disconnect = gspca_disconnect,
7602};
7603
7604static int __init sd_mod_init(void)
7605{
7606 if (usb_register(&sd_driver) < 0)
7607 return -1;
7608 PDEBUG(D_PROBE, "v%s registered", version);
7609 return 0;
7610}
7611
7612static void __exit sd_mod_exit(void)
7613{
7614 usb_deregister(&sd_driver);
7615 PDEBUG(D_PROBE, "deregistered");
7616}
7617
7618module_init(sd_mod_init);
7619module_exit(sd_mod_exit);
7620
7621module_param(force_sensor, int, 0644);
7622MODULE_PARM_DESC(force_sensor,
7623 "Force sensor. Only for experts!!!");
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 7b65f5e537f8..a30254bed311 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -194,88 +194,6 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
194 return 1; 194 return 1;
195} 195}
196 196
197/* Common (grey or coloured) pinnacle PCTV remote handling
198 *
199 */
200static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
201 int parity_offset, int marker, int code_modulo)
202{
203 unsigned char b[4];
204 unsigned int start = 0,parity = 0,code = 0;
205
206 /* poll IR chip */
207 if (4 != i2c_master_recv(&ir->c,b,4)) {
208 dprintk(2,"read error\n");
209 return -EIO;
210 }
211
212 for (start = 0; start < ARRAY_SIZE(b); start++) {
213 if (b[start] == marker) {
214 code=b[(start+parity_offset+1)%4];
215 parity=b[(start+parity_offset)%4];
216 }
217 }
218
219 /* Empty Request */
220 if (parity==0)
221 return 0;
222
223 /* Repeating... */
224 if (ir->old == parity)
225 return 0;
226
227 ir->old = parity;
228
229 /* drop special codes when a key is held down a long time for the grey controller
230 In this case, the second bit of the code is asserted */
231 if (marker == 0xfe && (code & 0x40))
232 return 0;
233
234 code %= code_modulo;
235
236 *ir_raw = code;
237 *ir_key = code;
238
239 dprintk(1,"Pinnacle PCTV key %02x\n", code);
240
241 return 1;
242}
243
244/* The grey pinnacle PCTV remote
245 *
246 * There are one issue with this remote:
247 * - I2c packet does not change when the same key is pressed quickly. The workaround
248 * is to hold down each key for about half a second, so that another code is generated
249 * in the i2c packet, and the function can distinguish key presses.
250 *
251 * Sylvain Pasche <sylvain.pasche@gmail.com>
252 */
253int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
254{
255
256 return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
257}
258
259EXPORT_SYMBOL_GPL(get_key_pinnacle_grey);
260
261
262/* The new pinnacle PCTV remote (with the colored buttons)
263 *
264 * Ricardo Cerqueira <v4l@cerqueira.org>
265 */
266int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
267{
268 /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
269 *
270 * this is the only value that results in 42 unique
271 * codes < 128
272 */
273
274 return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
275}
276
277EXPORT_SYMBOL_GPL(get_key_pinnacle_color);
278
279/* ----------------------------------------------------------------------- */ 197/* ----------------------------------------------------------------------- */
280 198
281static void ir_key_poll(struct IR_i2c *ir) 199static void ir_key_poll(struct IR_i2c *ir)
diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c
index 4fb8faefe2ce..4e05f91a9100 100644
--- a/drivers/media/video/ivtv/ivtv-cards.c
+++ b/drivers/media/video/ivtv/ivtv-cards.c
@@ -40,7 +40,7 @@
40#define MSP_MONO MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \ 40#define MSP_MONO MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \
41 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART) 41 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
42 42
43#define V4L2_STD_NOT_MN (V4L2_STD_PAL|V4L2_STD_SECAM) 43#define V4L2_STD_PAL_SECAM (V4L2_STD_PAL|V4L2_STD_SECAM)
44 44
45/* usual i2c tuner addresses to probe */ 45/* usual i2c tuner addresses to probe */
46static struct ivtv_card_tuner_i2c ivtv_i2c_std = { 46static struct ivtv_card_tuner_i2c ivtv_i2c_std = {
@@ -300,7 +300,7 @@ static const struct ivtv_card ivtv_card_mpg600 = {
300 .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 }, 300 .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
301 .tuners = { 301 .tuners = {
302 /* The PAL tuner is confirmed */ 302 /* The PAL tuner is confirmed */
303 { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME }, 303 { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
304 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 }, 304 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
305 }, 305 },
306 .pci_list = ivtv_pci_mpg600, 306 .pci_list = ivtv_pci_mpg600,
@@ -341,7 +341,7 @@ static const struct ivtv_card ivtv_card_mpg160 = {
341 .lang1 = 0x0004, .lang2 = 0x0000, .both = 0x0008 }, 341 .lang1 = 0x0004, .lang2 = 0x0000, .both = 0x0008 },
342 .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 }, 342 .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
343 .tuners = { 343 .tuners = {
344 { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME }, 344 { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
345 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 }, 345 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
346 }, 346 },
347 .pci_list = ivtv_pci_mpg160, 347 .pci_list = ivtv_pci_mpg160,
@@ -377,7 +377,7 @@ static const struct ivtv_card ivtv_card_pg600 = {
377 { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, 377 { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
378 }, 378 },
379 .tuners = { 379 .tuners = {
380 { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME }, 380 { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
381 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 }, 381 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
382 }, 382 },
383 .pci_list = ivtv_pci_pg600, 383 .pci_list = ivtv_pci_pg600,
@@ -418,7 +418,7 @@ static const struct ivtv_card ivtv_card_avc2410 = {
418 on the country/region setting of the user to decide which tuner 418 on the country/region setting of the user to decide which tuner
419 is available. */ 419 is available. */
420 .tuners = { 420 .tuners = {
421 { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, 421 { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
422 { .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP, 422 { .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP,
423 .tuner = TUNER_PHILIPS_FM1236_MK3 }, 423 .tuner = TUNER_PHILIPS_FM1236_MK3 },
424 { .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 }, 424 { .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 },
@@ -492,7 +492,7 @@ static const struct ivtv_card ivtv_card_tg5000tv = {
492 .gpio_video_input = { .mask = 0x0030, .tuner = 0x0000, 492 .gpio_video_input = { .mask = 0x0030, .tuner = 0x0000,
493 .composite = 0x0010, .svideo = 0x0020 }, 493 .composite = 0x0010, .svideo = 0x0020 },
494 .tuners = { 494 .tuners = {
495 { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 }, 495 { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
496 }, 496 },
497 .pci_list = ivtv_pci_tg5000tv, 497 .pci_list = ivtv_pci_tg5000tv,
498 .i2c = &ivtv_i2c_std, 498 .i2c = &ivtv_i2c_std,
@@ -523,7 +523,7 @@ static const struct ivtv_card ivtv_card_va2000 = {
523 { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER }, 523 { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER },
524 }, 524 },
525 .tuners = { 525 .tuners = {
526 { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 }, 526 { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
527 }, 527 },
528 .pci_list = ivtv_pci_va2000, 528 .pci_list = ivtv_pci_va2000,
529 .i2c = &ivtv_i2c_std, 529 .i2c = &ivtv_i2c_std,
@@ -567,7 +567,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc = {
567 .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000, 567 .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
568 .f44100 = 0x4000, .f48000 = 0x8000 }, 568 .f44100 = 0x4000, .f48000 = 0x8000 },
569 .tuners = { 569 .tuners = {
570 { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, 570 { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
571 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, 571 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
572 }, 572 },
573 .pci_list = ivtv_pci_cx23416gyc, 573 .pci_list = ivtv_pci_cx23416gyc,
@@ -599,7 +599,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc_nogr = {
599 .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000, 599 .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
600 .f44100 = 0x4000, .f48000 = 0x8000 }, 600 .f44100 = 0x4000, .f48000 = 0x8000 },
601 .tuners = { 601 .tuners = {
602 { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, 602 { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
603 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, 603 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
604 }, 604 },
605 .i2c = &ivtv_i2c_std, 605 .i2c = &ivtv_i2c_std,
@@ -629,7 +629,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc_nogrycs = {
629 .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000, 629 .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000,
630 .f44100 = 0x4000, .f48000 = 0x8000 }, 630 .f44100 = 0x4000, .f48000 = 0x8000 },
631 .tuners = { 631 .tuners = {
632 { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, 632 { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
633 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, 633 { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
634 }, 634 },
635 .i2c = &ivtv_i2c_std, 635 .i2c = &ivtv_i2c_std,
@@ -669,7 +669,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx = {
669 .gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 }, 669 .gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 },
670 .tuners = { 670 .tuners = {
671 /* This card has the Panasonic VP27 tuner */ 671 /* This card has the Panasonic VP27 tuner */
672 { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 }, 672 { .std = V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
673 }, 673 },
674 .pci_list = ivtv_pci_gv_mvprx, 674 .pci_list = ivtv_pci_gv_mvprx,
675 .i2c = &ivtv_i2c_std, 675 .i2c = &ivtv_i2c_std,
@@ -706,7 +706,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx2e = {
706 .gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 }, 706 .gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 },
707 .tuners = { 707 .tuners = {
708 /* This card has the Panasonic VP27 tuner */ 708 /* This card has the Panasonic VP27 tuner */
709 { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 }, 709 { .std = V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
710 }, 710 },
711 .pci_list = ivtv_pci_gv_mvprx2e, 711 .pci_list = ivtv_pci_gv_mvprx2e,
712 .i2c = &ivtv_i2c_std, 712 .i2c = &ivtv_i2c_std,
@@ -741,7 +741,7 @@ static const struct ivtv_card ivtv_card_gotview_pci_dvd = {
741 .gpio_init = { .direction = 0xf000, .initial_value = 0xA000 }, 741 .gpio_init = { .direction = 0xf000, .initial_value = 0xA000 },
742 .tuners = { 742 .tuners = {
743 /* This card has a Philips FQ1216ME MK3 tuner */ 743 /* This card has a Philips FQ1216ME MK3 tuner */
744 { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, 744 { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
745 }, 745 },
746 .pci_list = ivtv_pci_gotview_pci_dvd, 746 .pci_list = ivtv_pci_gotview_pci_dvd,
747 .i2c = &ivtv_i2c_std, 747 .i2c = &ivtv_i2c_std,
@@ -780,7 +780,7 @@ static const struct ivtv_card ivtv_card_gotview_pci_dvd2 = {
780 .gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 }, 780 .gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
781 .tuners = { 781 .tuners = {
782 /* This card has a Philips FQ1216ME MK5 tuner */ 782 /* This card has a Philips FQ1216ME MK5 tuner */
783 { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, 783 { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
784 }, 784 },
785 .pci_list = ivtv_pci_gotview_pci_dvd2, 785 .pci_list = ivtv_pci_gotview_pci_dvd2,
786 .i2c = &ivtv_i2c_std, 786 .i2c = &ivtv_i2c_std,
@@ -858,7 +858,7 @@ static const struct ivtv_card ivtv_card_dctmvtvp1 = {
858 .gpio_video_input = { .mask = 0x0030, .tuner = 0x0000, 858 .gpio_video_input = { .mask = 0x0030, .tuner = 0x0000,
859 .composite = 0x0010, .svideo = 0x0020}, 859 .composite = 0x0010, .svideo = 0x0020},
860 .tuners = { 860 .tuners = {
861 { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 }, 861 { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
862 }, 862 },
863 .pci_list = ivtv_pci_dctmvtvp1, 863 .pci_list = ivtv_pci_dctmvtvp1,
864 .i2c = &ivtv_i2c_std, 864 .i2c = &ivtv_i2c_std,
@@ -923,7 +923,6 @@ static const struct ivtv_card ivtv_card_club3d = {
923 { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, 923 { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
924 }, 924 },
925 .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, 925 .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
926 .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, /* tuner reset */
927 .xceive_pin = 12, 926 .xceive_pin = 12,
928 .tuners = { 927 .tuners = {
929 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, 928 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
@@ -959,7 +958,7 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = {
959 { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, 958 { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 },
960 }, 959 },
961 /* enable line-in */ 960 /* enable line-in */
962 .gpio_init = { .direction = 0xe400, .initial_value = 0x4400 }, 961 .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 },
963 .xceive_pin = 10, 962 .xceive_pin = 10,
964 .tuners = { 963 .tuners = {
965 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, 964 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
@@ -1001,7 +1000,7 @@ static const struct ivtv_card ivtv_card_aver_pvr150 = {
1001 .gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 }, 1000 .gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
1002 .tuners = { 1001 .tuners = {
1003 /* This card has a Partsnic PTI-5NF05 tuner */ 1002 /* This card has a Partsnic PTI-5NF05 tuner */
1004 { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_TCL_2002N }, 1003 { .std = V4L2_STD_MN, .tuner = TUNER_TCL_2002N },
1005 }, 1004 },
1006 .pci_list = ivtv_pci_aver_pvr150, 1005 .pci_list = ivtv_pci_aver_pvr150,
1007 .i2c = &ivtv_i2c_radio, 1006 .i2c = &ivtv_i2c_radio,
@@ -1069,7 +1068,7 @@ static const struct ivtv_card ivtv_card_asus_falcon2 = {
1069 }, 1068 },
1070 .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, M52790_IN_TUNER }, 1069 .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, M52790_IN_TUNER },
1071 .tuners = { 1070 .tuners = {
1072 { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 }, 1071 { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
1073 }, 1072 },
1074 .pci_list = ivtv_pci_asus_falcon2, 1073 .pci_list = ivtv_pci_asus_falcon2,
1075 .i2c = &ivtv_i2c_std, 1074 .i2c = &ivtv_i2c_std,
@@ -1102,7 +1101,7 @@ static const struct ivtv_card ivtv_card_aver_m104 = {
1102 }, 1101 },
1103 .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 }, 1102 .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
1104 /* enable line-in + reset tuner */ 1103 /* enable line-in + reset tuner */
1105 .gpio_init = { .direction = 0xe400, .initial_value = 0x4000 }, 1104 .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 },
1106 .xceive_pin = 10, 1105 .xceive_pin = 10,
1107 .tuners = { 1106 .tuners = {
1108 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, 1107 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
@@ -1111,6 +1110,41 @@ static const struct ivtv_card ivtv_card_aver_m104 = {
1111 .i2c = &ivtv_i2c_std, 1110 .i2c = &ivtv_i2c_std,
1112}; 1111};
1113 1112
1113/* ------------------------------------------------------------------------- */
1114
1115/* Buffalo PC-MV5L/PCI cards */
1116
1117static const struct ivtv_card_pci_info ivtv_pci_buffalo[] = {
1118 { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x052b },
1119 { 0, 0, 0 }
1120};
1121
1122static const struct ivtv_card ivtv_card_buffalo = {
1123 .type = IVTV_CARD_BUFFALO_MV5L,
1124 .name = "Buffalo PC-MV5L/PCI",
1125 .v4l2_capabilities = IVTV_CAP_ENCODER,
1126 .hw_video = IVTV_HW_CX25840,
1127 .hw_audio = IVTV_HW_CX25840,
1128 .hw_audio_ctrl = IVTV_HW_CX25840,
1129 .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
1130 .video_inputs = {
1131 { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 },
1132 { IVTV_CARD_INPUT_SVIDEO1, 1,
1133 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
1134 { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
1135 },
1136 .audio_inputs = {
1137 { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
1138 { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL },
1139 },
1140 .xceive_pin = 12,
1141 .tuners = {
1142 { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
1143 },
1144 .pci_list = ivtv_pci_buffalo,
1145 .i2c = &ivtv_i2c_std,
1146};
1147
1114static const struct ivtv_card *ivtv_card_list[] = { 1148static const struct ivtv_card *ivtv_card_list[] = {
1115 &ivtv_card_pvr250, 1149 &ivtv_card_pvr250,
1116 &ivtv_card_pvr350, 1150 &ivtv_card_pvr350,
@@ -1137,6 +1171,7 @@ static const struct ivtv_card *ivtv_card_list[] = {
1137 &ivtv_card_aver_pvr150, 1171 &ivtv_card_aver_pvr150,
1138 &ivtv_card_aver_ezmaker, 1172 &ivtv_card_aver_ezmaker,
1139 &ivtv_card_aver_m104, 1173 &ivtv_card_aver_m104,
1174 &ivtv_card_buffalo,
1140 1175
1141 /* Variations of standard cards but with the same PCI IDs. 1176 /* Variations of standard cards but with the same PCI IDs.
1142 These cards must come last in this list. */ 1177 These cards must come last in this list. */
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
index 748485dcebbd..381af1bceef8 100644
--- a/drivers/media/video/ivtv/ivtv-cards.h
+++ b/drivers/media/video/ivtv/ivtv-cards.h
@@ -49,7 +49,8 @@
49#define IVTV_CARD_AVER_PVR150PLUS 22 /* AVerMedia PVR-150 Plus */ 49#define IVTV_CARD_AVER_PVR150PLUS 22 /* AVerMedia PVR-150 Plus */
50#define IVTV_CARD_AVER_EZMAKER 23 /* AVerMedia EZMaker PCI Deluxe */ 50#define IVTV_CARD_AVER_EZMAKER 23 /* AVerMedia EZMaker PCI Deluxe */
51#define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */ 51#define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */
52#define IVTV_CARD_LAST 24 52#define IVTV_CARD_BUFFALO_MV5L 25 /* Buffalo PC-MV5L/PCI card */
53#define IVTV_CARD_LAST 25
53 54
54/* Variants of existing cards but with the same PCI IDs. The driver 55/* Variants of existing cards but with the same PCI IDs. The driver
55 detects these based on other device information. 56 detects these based on other device information.
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c
index c7e449f6397b..48e103be7183 100644
--- a/drivers/media/video/ivtv/ivtv-controls.c
+++ b/drivers/media/video/ivtv/ivtv-controls.c
@@ -47,12 +47,12 @@ static const u32 *ctrl_classes[] = {
47 NULL 47 NULL
48}; 48};
49 49
50static int ivtv_queryctrl(struct ivtv *itv, struct v4l2_queryctrl *qctrl) 50
51int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl)
51{ 52{
53 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
52 const char *name; 54 const char *name;
53 55
54 IVTV_DEBUG_IOCTL("VIDIOC_QUERYCTRL(%08x)\n", qctrl->id);
55
56 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id); 56 qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
57 if (qctrl->id == 0) 57 if (qctrl->id == 0)
58 return -EINVAL; 58 return -EINVAL;
@@ -87,21 +87,35 @@ static int ivtv_queryctrl(struct ivtv *itv, struct v4l2_queryctrl *qctrl)
87 return 0; 87 return 0;
88} 88}
89 89
90static int ivtv_querymenu(struct ivtv *itv, struct v4l2_querymenu *qmenu) 90int ivtv_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qmenu)
91{ 91{
92 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
92 struct v4l2_queryctrl qctrl; 93 struct v4l2_queryctrl qctrl;
93 94
94 qctrl.id = qmenu->id; 95 qctrl.id = qmenu->id;
95 ivtv_queryctrl(itv, &qctrl); 96 ivtv_queryctrl(file, fh, &qctrl);
96 return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id)); 97 return v4l2_ctrl_query_menu(qmenu, &qctrl,
98 cx2341x_ctrl_get_menu(&itv->params, qmenu->id));
97} 99}
98 100
99static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) 101static int ivtv_try_ctrl(struct file *file, void *fh,
102 struct v4l2_ext_control *vctrl)
100{ 103{
101 s32 v = vctrl->value; 104 struct v4l2_queryctrl qctrl;
102 105 const char **menu_items = NULL;
103 IVTV_DEBUG_IOCTL("VIDIOC_S_CTRL(%08x, %x)\n", vctrl->id, v); 106 int err;
107
108 qctrl.id = vctrl->id;
109 err = ivtv_queryctrl(file, fh, &qctrl);
110 if (err)
111 return err;
112 if (qctrl.type == V4L2_CTRL_TYPE_MENU)
113 menu_items = v4l2_ctrl_get_menu(qctrl.id);
114 return v4l2_ctrl_check(vctrl, &qctrl, menu_items);
115}
104 116
117static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
118{
105 switch (vctrl->id) { 119 switch (vctrl->id) {
106 /* Standard V4L2 controls */ 120 /* Standard V4L2 controls */
107 case V4L2_CID_BRIGHTNESS: 121 case V4L2_CID_BRIGHTNESS:
@@ -119,7 +133,7 @@ static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
119 return ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl); 133 return ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl);
120 134
121 default: 135 default:
122 IVTV_DEBUG_IOCTL("invalid control %x\n", vctrl->id); 136 IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
123 return -EINVAL; 137 return -EINVAL;
124 } 138 }
125 return 0; 139 return 0;
@@ -127,8 +141,6 @@ static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
127 141
128static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) 142static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
129{ 143{
130 IVTV_DEBUG_IOCTL("VIDIOC_G_CTRL(%08x)\n", vctrl->id);
131
132 switch (vctrl->id) { 144 switch (vctrl->id) {
133 /* Standard V4L2 controls */ 145 /* Standard V4L2 controls */
134 case V4L2_CID_BRIGHTNESS: 146 case V4L2_CID_BRIGHTNESS:
@@ -145,7 +157,7 @@ static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
145 case V4L2_CID_AUDIO_LOUDNESS: 157 case V4L2_CID_AUDIO_LOUDNESS:
146 return ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl); 158 return ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl);
147 default: 159 default:
148 IVTV_DEBUG_IOCTL("invalid control %x\n", vctrl->id); 160 IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
149 return -EINVAL; 161 return -EINVAL;
150 } 162 }
151 return 0; 163 return 0;
@@ -191,119 +203,106 @@ static int ivtv_setup_vbi_fmt(struct ivtv *itv, enum v4l2_mpeg_stream_vbi_fmt fm
191 return 0; 203 return 0;
192} 204}
193 205
194int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg) 206int ivtv_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
195{ 207{
208 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
196 struct v4l2_control ctrl; 209 struct v4l2_control ctrl;
197 210
198 switch (cmd) { 211 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
199 case VIDIOC_QUERYMENU: 212 int i;
200 IVTV_DEBUG_IOCTL("VIDIOC_QUERYMENU\n"); 213 int err = 0;
201 return ivtv_querymenu(itv, arg); 214
202 215 for (i = 0; i < c->count; i++) {
203 case VIDIOC_QUERYCTRL: 216 ctrl.id = c->controls[i].id;
204 return ivtv_queryctrl(itv, arg); 217 ctrl.value = c->controls[i].value;
205 218 err = ivtv_g_ctrl(itv, &ctrl);
206 case VIDIOC_S_CTRL: 219 c->controls[i].value = ctrl.value;
207 return ivtv_s_ctrl(itv, arg); 220 if (err) {
208 221 c->error_idx = i;
209 case VIDIOC_G_CTRL: 222 break;
210 return ivtv_g_ctrl(itv, arg);
211
212 case VIDIOC_S_EXT_CTRLS:
213 {
214 struct v4l2_ext_controls *c = arg;
215
216 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
217 int i;
218 int err = 0;
219
220 for (i = 0; i < c->count; i++) {
221 ctrl.id = c->controls[i].id;
222 ctrl.value = c->controls[i].value;
223 err = ivtv_s_ctrl(itv, &ctrl);
224 c->controls[i].value = ctrl.value;
225 if (err) {
226 c->error_idx = i;
227 break;
228 }
229 } 223 }
230 return err;
231 } 224 }
232 IVTV_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); 225 return err;
233 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { 226 }
234 static u32 freqs[3] = { 44100, 48000, 32000 }; 227 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
235 struct cx2341x_mpeg_params p = itv->params; 228 return cx2341x_ext_ctrls(&itv->params, 0, c, VIDIOC_G_EXT_CTRLS);
236 int err = cx2341x_ext_ctrls(&p, atomic_read(&itv->capturing), arg, cmd); 229 return -EINVAL;
237 unsigned idx; 230}
238 231
239 if (err) 232int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
240 return err; 233{
241 234 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
242 if (p.video_encoding != itv->params.video_encoding) { 235 struct v4l2_control ctrl;
243 int is_mpeg1 = p.video_encoding == 236
244 V4L2_MPEG_VIDEO_ENCODING_MPEG_1; 237 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
245 struct v4l2_format fmt; 238 int i;
246 239 int err = 0;
247 /* fix videodecoder resolution */ 240
248 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 241 for (i = 0; i < c->count; i++) {
249 fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1); 242 ctrl.id = c->controls[i].id;
250 fmt.fmt.pix.height = itv->params.height; 243 ctrl.value = c->controls[i].value;
251 itv->video_dec_func(itv, VIDIOC_S_FMT, &fmt); 244 err = ivtv_s_ctrl(itv, &ctrl);
252 } 245 c->controls[i].value = ctrl.value;
253 err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p); 246 if (err) {
254 if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt) { 247 c->error_idx = i;
255 err = ivtv_setup_vbi_fmt(itv, p.stream_vbi_fmt); 248 break;
256 } 249 }
257 itv->params = p;
258 itv->dualwatch_stereo_mode = p.audio_properties & 0x0300;
259 idx = p.audio_properties & 0x03;
260 /* The audio clock of the digitizer must match the codec sample
261 rate otherwise you get some very strange effects. */
262 if (idx < sizeof(freqs))
263 ivtv_call_i2c_clients(itv, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[idx]);
264 return err;
265 } 250 }
266 return -EINVAL; 251 return err;
267 } 252 }
253 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
254 static u32 freqs[3] = { 44100, 48000, 32000 };
255 struct cx2341x_mpeg_params p = itv->params;
256 int err = cx2341x_ext_ctrls(&p, atomic_read(&itv->capturing), c, VIDIOC_S_EXT_CTRLS);
257 unsigned idx;
268 258
269 case VIDIOC_G_EXT_CTRLS: 259 if (err)
270 {
271 struct v4l2_ext_controls *c = arg;
272
273 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
274 int i;
275 int err = 0;
276
277 for (i = 0; i < c->count; i++) {
278 ctrl.id = c->controls[i].id;
279 ctrl.value = c->controls[i].value;
280 err = ivtv_g_ctrl(itv, &ctrl);
281 c->controls[i].value = ctrl.value;
282 if (err) {
283 c->error_idx = i;
284 break;
285 }
286 }
287 return err; 260 return err;
261
262 if (p.video_encoding != itv->params.video_encoding) {
263 int is_mpeg1 = p.video_encoding ==
264 V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
265 struct v4l2_format fmt;
266
267 /* fix videodecoder resolution */
268 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
269 fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1);
270 fmt.fmt.pix.height = itv->params.height;
271 itv->video_dec_func(itv, VIDIOC_S_FMT, &fmt);
288 } 272 }
289 IVTV_DEBUG_IOCTL("VIDIOC_G_EXT_CTRLS\n"); 273 err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p);
290 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) 274 if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt)
291 return cx2341x_ext_ctrls(&itv->params, 0, arg, cmd); 275 err = ivtv_setup_vbi_fmt(itv, p.stream_vbi_fmt);
292 return -EINVAL; 276 itv->params = p;
277 itv->dualwatch_stereo_mode = p.audio_properties & 0x0300;
278 idx = p.audio_properties & 0x03;
279 /* The audio clock of the digitizer must match the codec sample
280 rate otherwise you get some very strange effects. */
281 if (idx < sizeof(freqs))
282 ivtv_call_i2c_clients(itv, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[idx]);
283 return err;
293 } 284 }
285 return -EINVAL;
286}
294 287
295 case VIDIOC_TRY_EXT_CTRLS: 288int ivtv_try_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
296 { 289{
297 struct v4l2_ext_controls *c = arg; 290 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
298 291
299 IVTV_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); 292 if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
300 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) 293 int i;
301 return cx2341x_ext_ctrls(&itv->params, atomic_read(&itv->capturing), arg, cmd); 294 int err = 0;
302 return -EINVAL;
303 }
304 295
305 default: 296 for (i = 0; i < c->count; i++) {
306 return -EINVAL; 297 err = ivtv_try_ctrl(file, fh, &c->controls[i]);
298 if (err) {
299 c->error_idx = i;
300 break;
301 }
302 }
303 return err;
307 } 304 }
308 return 0; 305 if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
306 return cx2341x_ext_ctrls(&itv->params, atomic_read(&itv->capturing), c, VIDIOC_TRY_EXT_CTRLS);
307 return -EINVAL;
309} 308}
diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/video/ivtv/ivtv-controls.h
index bb8a6a5ed2bc..1c7721e23c9b 100644
--- a/drivers/media/video/ivtv/ivtv-controls.h
+++ b/drivers/media/video/ivtv/ivtv-controls.h
@@ -21,6 +21,10 @@
21#ifndef IVTV_CONTROLS_H 21#ifndef IVTV_CONTROLS_H
22#define IVTV_CONTROLS_H 22#define IVTV_CONTROLS_H
23 23
24int ivtv_control_ioctls(struct ivtv *itv, unsigned int cmd, void *arg); 24int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *a);
25int ivtv_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
26int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
27int ivtv_try_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
28int ivtv_querymenu(struct file *file, void *fh, struct v4l2_querymenu *a);
25 29
26#endif 30#endif
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index 797e636771da..41fd79279bb5 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -191,6 +191,7 @@ MODULE_PARM_DESC(cardtype,
191 "\t\t\t23 = AverMedia PVR-150 Plus\n" 191 "\t\t\t23 = AverMedia PVR-150 Plus\n"
192 "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n" 192 "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
193 "\t\t\t25 = AverMedia M104 (not yet working)\n" 193 "\t\t\t25 = AverMedia M104 (not yet working)\n"
194 "\t\t\t26 = Buffalo PC-MV5L/PCI\n"
194 "\t\t\t 0 = Autodetect (default)\n" 195 "\t\t\t 0 = Autodetect (default)\n"
195 "\t\t\t-1 = Ignore this card\n\t\t"); 196 "\t\t\t-1 = Ignore this card\n\t\t");
196MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60"); 197MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60");
@@ -1019,7 +1020,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
1019 ivtv_cards[ivtv_cards_active] = itv; 1020 ivtv_cards[ivtv_cards_active] = itv;
1020 itv->dev = dev; 1021 itv->dev = dev;
1021 itv->num = ivtv_cards_active++; 1022 itv->num = ivtv_cards_active++;
1022 snprintf(itv->name, sizeof(itv->name) - 1, "ivtv%d", itv->num); 1023 snprintf(itv->name, sizeof(itv->name), "ivtv%d", itv->num);
1023 IVTV_INFO("Initializing card #%d\n", itv->num); 1024 IVTV_INFO("Initializing card #%d\n", itv->num);
1024 1025
1025 spin_unlock(&ivtv_cards_lock); 1026 spin_unlock(&ivtv_cards_lock);
@@ -1127,6 +1128,12 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
1127 /* if no tuner was found, then pick the first tuner in the card list */ 1128 /* if no tuner was found, then pick the first tuner in the card list */
1128 if (itv->options.tuner == -1 && itv->card->tuners[0].std) { 1129 if (itv->options.tuner == -1 && itv->card->tuners[0].std) {
1129 itv->std = itv->card->tuners[0].std; 1130 itv->std = itv->card->tuners[0].std;
1131 if (itv->std & V4L2_STD_PAL)
1132 itv->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
1133 else if (itv->std & V4L2_STD_NTSC)
1134 itv->std = V4L2_STD_NTSC_M;
1135 else if (itv->std & V4L2_STD_SECAM)
1136 itv->std = V4L2_STD_SECAM_L;
1130 itv->options.tuner = itv->card->tuners[0].tuner; 1137 itv->options.tuner = itv->card->tuners[0].tuner;
1131 } 1138 }
1132 if (itv->options.radio == -1) 1139 if (itv->options.radio == -1)
@@ -1261,9 +1268,13 @@ err:
1261int ivtv_init_on_first_open(struct ivtv *itv) 1268int ivtv_init_on_first_open(struct ivtv *itv)
1262{ 1269{
1263 struct v4l2_frequency vf; 1270 struct v4l2_frequency vf;
1271 /* Needed to call ioctls later */
1272 struct ivtv_open_id fh;
1264 int fw_retry_count = 3; 1273 int fw_retry_count = 3;
1265 int video_input; 1274 int video_input;
1266 1275
1276 fh.itv = itv;
1277
1267 if (test_bit(IVTV_F_I_FAILED, &itv->i_flags)) 1278 if (test_bit(IVTV_F_I_FAILED, &itv->i_flags))
1268 return -ENXIO; 1279 return -ENXIO;
1269 1280
@@ -1311,18 +1322,18 @@ int ivtv_init_on_first_open(struct ivtv *itv)
1311 1322
1312 video_input = itv->active_input; 1323 video_input = itv->active_input;
1313 itv->active_input++; /* Force update of input */ 1324 itv->active_input++; /* Force update of input */
1314 ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_INPUT, &video_input); 1325 ivtv_s_input(NULL, &fh, video_input);
1315 1326
1316 /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code 1327 /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
1317 in one place. */ 1328 in one place. */
1318 itv->std++; /* Force full standard initialization */ 1329 itv->std++; /* Force full standard initialization */
1319 itv->std_out = itv->std; 1330 itv->std_out = itv->std;
1320 ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_FREQUENCY, &vf); 1331 ivtv_s_frequency(NULL, &fh, &vf);
1321 1332
1322 if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) { 1333 if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
1323 ivtv_init_mpeg_decoder(itv); 1334 ivtv_init_mpeg_decoder(itv);
1324 } 1335 }
1325 ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_STD, &itv->tuner_std); 1336 ivtv_s_std(NULL, &fh, &itv->tuner_std);
1326 1337
1327 /* On a cx23416 this seems to be able to enable DMA to the chip? */ 1338 /* On a cx23416 this seems to be able to enable DMA to the chip? */
1328 if (!itv->has_cx23415) 1339 if (!itv->has_cx23415)
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 9d23b1efd36d..a08bb3331cfb 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -635,7 +635,6 @@ struct ivtv {
635 spinlock_t lock; /* lock access to this struct */ 635 spinlock_t lock; /* lock access to this struct */
636 struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ 636 struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */
637 637
638
639 /* Streams */ 638 /* Streams */
640 int stream_buf_size[IVTV_MAX_STREAMS]; /* stream buffer size */ 639 int stream_buf_size[IVTV_MAX_STREAMS]; /* stream buffer size */
641 struct ivtv_stream streams[IVTV_MAX_STREAMS]; /* stream data */ 640 struct ivtv_stream streams[IVTV_MAX_STREAMS]; /* stream data */
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index db813e071ce6..7ec5c99f9ad1 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -582,6 +582,19 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
582 ivtv_queue_init(&q); 582 ivtv_queue_init(&q);
583 set_bit(IVTV_F_S_APPL_IO, &s->s_flags); 583 set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
584 584
585 /* Start decoder (returns 0 if already started) */
586 mutex_lock(&itv->serialize_lock);
587 rc = ivtv_start_decoding(id, itv->speed);
588 mutex_unlock(&itv->serialize_lock);
589 if (rc) {
590 IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
591
592 /* failure, clean up */
593 clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
594 clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
595 return rc;
596 }
597
585retry: 598retry:
586 /* If possible, just DMA the entire frame - Check the data transfer size 599 /* If possible, just DMA the entire frame - Check the data transfer size
587 since we may get here before the stream has been fully set-up */ 600 since we may get here before the stream has been fully set-up */
@@ -664,18 +677,6 @@ retry:
664 ivtv_enqueue(s, buf, &s->q_full); 677 ivtv_enqueue(s, buf, &s->q_full);
665 } 678 }
666 679
667 /* Start decoder (returns 0 if already started) */
668 mutex_lock(&itv->serialize_lock);
669 rc = ivtv_start_decoding(id, itv->speed);
670 mutex_unlock(&itv->serialize_lock);
671 if (rc) {
672 IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
673
674 /* failure, clean up */
675 clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
676 clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
677 return rc;
678 }
679 if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) { 680 if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) {
680 if (s->q_full.length >= itv->dma_data_req_size) { 681 if (s->q_full.length >= itv->dma_data_req_size) {
681 int got_sig; 682 int got_sig;
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c
index d8ac09f3cce6..bc22905ea20f 100644
--- a/drivers/media/video/ivtv/ivtv-gpio.c
+++ b/drivers/media/video/ivtv/ivtv-gpio.c
@@ -146,15 +146,20 @@ int ivtv_reset_tuner_gpio(void *dev, int cmd, int value)
146 146
147void ivtv_gpio_init(struct ivtv *itv) 147void ivtv_gpio_init(struct ivtv *itv)
148{ 148{
149 if (itv->card->gpio_init.direction == 0) 149 u16 pin = 0;
150
151 if (itv->card->xceive_pin)
152 pin = 1 << itv->card->xceive_pin;
153
154 if ((itv->card->gpio_init.direction | pin) == 0)
150 return; 155 return;
151 156
152 IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n", 157 IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
153 read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT)); 158 read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
154 159
155 /* init output data then direction */ 160 /* init output data then direction */
156 write_reg(itv->card->gpio_init.initial_value, IVTV_REG_GPIO_OUT); 161 write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
157 write_reg(itv->card->gpio_init.direction, IVTV_REG_GPIO_DIR); 162 write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
158} 163}
159 164
160static struct v4l2_queryctrl gpio_ctrl_mute = { 165static struct v4l2_queryctrl gpio_ctrl_mute = {
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
index 32129f3ea836..af154238fb9a 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/drivers/media/video/ivtv/ivtv-i2c.c
@@ -75,10 +75,6 @@
75#define IVTV_REG_I2C_GETSCL_OFFSET 0x7008 75#define IVTV_REG_I2C_GETSCL_OFFSET 0x7008
76#define IVTV_REG_I2C_GETSDA_OFFSET 0x700c 76#define IVTV_REG_I2C_GETSDA_OFFSET 0x700c
77 77
78#ifndef I2C_ADAP_CLASS_TV_ANALOG
79#define I2C_ADAP_CLASS_TV_ANALOG I2C_CLASS_TV_ANALOG
80#endif /* I2C_ADAP_CLASS_TV_ANALOG */
81
82#define IVTV_CS53L32A_I2C_ADDR 0x11 78#define IVTV_CS53L32A_I2C_ADDR 0x11
83#define IVTV_M52790_I2C_ADDR 0x48 79#define IVTV_M52790_I2C_ADDR 0x48
84#define IVTV_CX25840_I2C_ADDR 0x44 80#define IVTV_CX25840_I2C_ADDR 0x44
@@ -139,7 +135,7 @@ static const u8 hw_addrs[] = {
139static const char * const hw_devicenames[] = { 135static const char * const hw_devicenames[] = {
140 "cx25840", 136 "cx25840",
141 "saa7115", 137 "saa7115",
142 "saa7127", 138 "saa7127_auto", /* saa7127 or saa7129 */
143 "msp3400", 139 "msp3400",
144 "tuner", 140 "tuner",
145 "wm8775", 141 "wm8775",
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 26cc0f6699fd..52e00a7f3110 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -128,37 +128,6 @@ u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)
128 return set; 128 return set;
129} 129}
130 130
131static const struct {
132 v4l2_std_id std;
133 char *name;
134} enum_stds[] = {
135 { V4L2_STD_PAL_BG | V4L2_STD_PAL_H, "PAL-BGH" },
136 { V4L2_STD_PAL_DK, "PAL-DK" },
137 { V4L2_STD_PAL_I, "PAL-I" },
138 { V4L2_STD_PAL_M, "PAL-M" },
139 { V4L2_STD_PAL_N, "PAL-N" },
140 { V4L2_STD_PAL_Nc, "PAL-Nc" },
141 { V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H, "SECAM-BGH" },
142 { V4L2_STD_SECAM_DK, "SECAM-DK" },
143 { V4L2_STD_SECAM_L, "SECAM-L" },
144 { V4L2_STD_SECAM_LC, "SECAM-L'" },
145 { V4L2_STD_NTSC_M, "NTSC-M" },
146 { V4L2_STD_NTSC_M_JP, "NTSC-J" },
147 { V4L2_STD_NTSC_M_KR, "NTSC-K" },
148};
149
150static const struct v4l2_standard ivtv_std_60hz =
151{
152 .frameperiod = {.numerator = 1001, .denominator = 30000},
153 .framelines = 525,
154};
155
156static const struct v4l2_standard ivtv_std_50hz =
157{
158 .frameperiod = {.numerator = 1, .denominator = 25},
159 .framelines = 625,
160};
161
162void ivtv_set_osd_alpha(struct ivtv *itv) 131void ivtv_set_osd_alpha(struct ivtv *itv)
163{ 132{
164 ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3, 133 ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3,
@@ -345,1073 +314,1219 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
345 return 0; 314 return 0;
346} 315}
347 316
348static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) 317static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
349{ 318{
350 struct v4l2_register *regs = arg; 319 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
351 unsigned long flags; 320 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
352 volatile u8 __iomem *reg_start;
353 321
354 if (!capable(CAP_SYS_ADMIN)) 322 vbifmt->reserved[0] = 0;
355 return -EPERM; 323 vbifmt->reserved[1] = 0;
356 if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE) 324 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
357 reg_start = itv->reg_mem - IVTV_REG_OFFSET;
358 else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
359 regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
360 reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
361 else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE)
362 reg_start = itv->enc_mem;
363 else
364 return -EINVAL; 325 return -EINVAL;
365 326 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
366 spin_lock_irqsave(&ivtv_cards_lock, flags); 327 if (itv->is_60hz) {
367 if (cmd == VIDIOC_DBG_G_REGISTER) { 328 vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
368 regs->val = readl(regs->reg + reg_start); 329 vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
369 } else { 330 } else {
370 writel(regs->val, regs->reg + reg_start); 331 vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
332 vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
371 } 333 }
372 spin_unlock_irqrestore(&ivtv_cards_lock, flags); 334 vbifmt->service_set = ivtv_get_service_set(vbifmt);
373 return 0; 335 return 0;
374} 336}
375 337
376static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fmt) 338static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
377{ 339{
378 switch (fmt->type) { 340 struct ivtv_open_id *id = fh;
379 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 341 struct ivtv *itv = id->itv;
380 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) 342 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
381 return -EINVAL; 343
382 fmt->fmt.pix.width = itv->main_rect.width; 344 pixfmt->width = itv->params.width;
383 fmt->fmt.pix.height = itv->main_rect.height; 345 pixfmt->height = itv->params.height;
384 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 346 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
385 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; 347 pixfmt->field = V4L2_FIELD_INTERLACED;
386 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { 348 pixfmt->priv = 0;
387 switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) { 349 if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
388 case IVTV_YUV_MODE_INTERLACED: 350 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
389 fmt->fmt.pix.field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ? 351 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
390 V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB; 352 pixfmt->sizeimage =
391 break; 353 pixfmt->height * pixfmt->width +
392 case IVTV_YUV_MODE_PROGRESSIVE: 354 pixfmt->height * (pixfmt->width / 2);
393 fmt->fmt.pix.field = V4L2_FIELD_NONE; 355 pixfmt->bytesperline = 720;
394 break; 356 } else {
395 default: 357 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
396 fmt->fmt.pix.field = V4L2_FIELD_ANY; 358 pixfmt->sizeimage = 128 * 1024;
397 break; 359 pixfmt->bytesperline = 0;
398 } 360 }
399 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; 361 return 0;
400 fmt->fmt.pix.bytesperline = 720; 362}
401 fmt->fmt.pix.width = itv->yuv_info.v4l2_src_w;
402 fmt->fmt.pix.height = itv->yuv_info.v4l2_src_h;
403 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
404 fmt->fmt.pix.sizeimage =
405 1080 * ((fmt->fmt.pix.height + 31) & ~31);
406 } else if (streamtype == IVTV_ENC_STREAM_TYPE_YUV) {
407 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
408 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
409 fmt->fmt.pix.sizeimage =
410 fmt->fmt.pix.height * fmt->fmt.pix.width +
411 fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
412 } else {
413 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
414 fmt->fmt.pix.sizeimage = 128 * 1024;
415 }
416 break;
417
418 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
419 fmt->fmt.pix.width = itv->params.width;
420 fmt->fmt.pix.height = itv->params.height;
421 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
422 fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
423 if (streamtype == IVTV_ENC_STREAM_TYPE_YUV ||
424 streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
425 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
426 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
427 fmt->fmt.pix.sizeimage =
428 fmt->fmt.pix.height * fmt->fmt.pix.width +
429 fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
430 } else {
431 fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
432 fmt->fmt.pix.sizeimage = 128 * 1024;
433 }
434 break;
435 363
436 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 364static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
437 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) 365{
438 return -EINVAL; 366 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
439 fmt->fmt.win.chromakey = itv->osd_chroma_key; 367 struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
440 fmt->fmt.win.global_alpha = itv->osd_global_alpha; 368
441 break; 369 vbifmt->sampling_rate = 27000000;
370 vbifmt->offset = 248;
371 vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4;
372 vbifmt->sample_format = V4L2_PIX_FMT_GREY;
373 vbifmt->start[0] = itv->vbi.start[0];
374 vbifmt->start[1] = itv->vbi.start[1];
375 vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count;
376 vbifmt->flags = 0;
377 vbifmt->reserved[0] = 0;
378 vbifmt->reserved[1] = 0;
379 return 0;
380}
442 381
443 case V4L2_BUF_TYPE_VBI_CAPTURE: 382static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
444 fmt->fmt.vbi.sampling_rate = 27000000; 383{
445 fmt->fmt.vbi.offset = 248; 384 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
446 fmt->fmt.vbi.samples_per_line = itv->vbi.raw_decoder_line_size - 4; 385 struct ivtv_open_id *id = fh;
447 fmt->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; 386 struct ivtv *itv = id->itv;
448 fmt->fmt.vbi.start[0] = itv->vbi.start[0];
449 fmt->fmt.vbi.start[1] = itv->vbi.start[1];
450 fmt->fmt.vbi.count[0] = fmt->fmt.vbi.count[1] = itv->vbi.count;
451 break;
452 387
453 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 388 vbifmt->reserved[0] = 0;
454 { 389 vbifmt->reserved[1] = 0;
455 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; 390 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
456 391
457 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) 392 if (id->type == IVTV_DEC_STREAM_TYPE_VBI) {
458 return -EINVAL; 393 vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
459 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; 394 V4L2_SLICED_VBI_525;
460 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); 395 ivtv_expand_service_set(vbifmt, itv->is_50hz);
461 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); 396 return 0;
462 if (itv->is_60hz) {
463 vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
464 vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
465 } else {
466 vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
467 vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
468 }
469 vbifmt->service_set = ivtv_get_service_set(vbifmt);
470 break;
471 } 397 }
472 398
473 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 399 itv->video_dec_func(itv, VIDIOC_G_FMT, fmt);
474 { 400 vbifmt->service_set = ivtv_get_service_set(vbifmt);
475 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; 401 return 0;
402}
476 403
477 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; 404static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
478 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); 405{
479 memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines)); 406 struct ivtv_open_id *id = fh;
407 struct ivtv *itv = id->itv;
408 struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
480 409
481 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) { 410 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
482 vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 : 411 return -EINVAL;
483 V4L2_SLICED_VBI_525; 412 pixfmt->width = itv->main_rect.width;
484 ivtv_expand_service_set(vbifmt, itv->is_50hz); 413 pixfmt->height = itv->main_rect.height;
414 pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
415 pixfmt->field = V4L2_FIELD_INTERLACED;
416 pixfmt->priv = 0;
417 if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
418 switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
419 case IVTV_YUV_MODE_INTERLACED:
420 pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
421 V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
422 break;
423 case IVTV_YUV_MODE_PROGRESSIVE:
424 pixfmt->field = V4L2_FIELD_NONE;
425 break;
426 default:
427 pixfmt->field = V4L2_FIELD_ANY;
485 break; 428 break;
486 } 429 }
487 430 pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
488 itv->video_dec_func(itv, VIDIOC_G_FMT, fmt); 431 pixfmt->bytesperline = 720;
489 vbifmt->service_set = ivtv_get_service_set(vbifmt); 432 pixfmt->width = itv->yuv_info.v4l2_src_w;
490 break; 433 pixfmt->height = itv->yuv_info.v4l2_src_h;
491 } 434 /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
492 case V4L2_BUF_TYPE_VBI_OUTPUT: 435 pixfmt->sizeimage =
493 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 436 1080 * ((pixfmt->height + 31) & ~31);
494 default: 437 } else {
495 return -EINVAL; 438 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
439 pixfmt->sizeimage = 128 * 1024;
440 pixfmt->bytesperline = 0;
496 } 441 }
497 return 0; 442 return 0;
498} 443}
499 444
500static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, 445static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
501 struct v4l2_format *fmt, int set_fmt)
502{ 446{
503 struct yuv_playback_info *yi = &itv->yuv_info; 447 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
504 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; 448 struct v4l2_window *winfmt = &fmt->fmt.win;
505 u16 set;
506 449
507 if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { 450 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
508 struct v4l2_rect r; 451 return -EINVAL;
509 int field; 452 winfmt->chromakey = itv->osd_chroma_key;
453 winfmt->global_alpha = itv->osd_global_alpha;
454 winfmt->field = V4L2_FIELD_INTERLACED;
455 winfmt->clips = NULL;
456 winfmt->clipcount = 0;
457 winfmt->bitmap = NULL;
458 winfmt->w.top = winfmt->w.left = 0;
459 winfmt->w.width = itv->osd_rect.width;
460 winfmt->w.height = itv->osd_rect.height;
461 return 0;
462}
510 463
511 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) 464static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
512 return -EINVAL; 465{
513 field = fmt->fmt.pix.field; 466 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
514 r.top = 0; 467}
515 r.left = 0;
516 r.width = fmt->fmt.pix.width;
517 r.height = fmt->fmt.pix.height;
518 ivtv_get_fmt(itv, streamtype, fmt);
519 fmt->fmt.pix.width = r.width;
520 fmt->fmt.pix.height = r.height;
521 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
522 fmt->fmt.pix.field = field;
523 if (fmt->fmt.pix.width < 2)
524 fmt->fmt.pix.width = 2;
525 if (fmt->fmt.pix.width > 720)
526 fmt->fmt.pix.width = 720;
527 if (fmt->fmt.pix.height < 2)
528 fmt->fmt.pix.height = 2;
529 if (fmt->fmt.pix.height > 576)
530 fmt->fmt.pix.height = 576;
531 }
532 if (set_fmt && streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
533 /* Return now if we already have some frame data */
534 if (yi->stream_size)
535 return -EBUSY;
536 468
537 yi->v4l2_src_w = r.width; 469static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
538 yi->v4l2_src_h = r.height; 470{
471 struct ivtv_open_id *id = fh;
472 struct ivtv *itv = id->itv;
473 int w = fmt->fmt.pix.width;
474 int h = fmt->fmt.pix.height;
475
476 w = min(w, 720);
477 w = max(w, 1);
478 h = min(h, itv->is_50hz ? 576 : 480);
479 h = max(h, 2);
480 ivtv_g_fmt_vid_cap(file, fh, fmt);
481 fmt->fmt.pix.width = w;
482 fmt->fmt.pix.height = h;
483 return 0;
484}
539 485
540 switch (field) { 486static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
541 case V4L2_FIELD_NONE: 487{
542 yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE; 488 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
543 break; 489}
544 case V4L2_FIELD_ANY:
545 yi->lace_mode = IVTV_YUV_MODE_AUTO;
546 break;
547 case V4L2_FIELD_INTERLACED_BT:
548 yi->lace_mode =
549 IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
550 break;
551 case V4L2_FIELD_INTERLACED_TB:
552 default:
553 yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
554 break;
555 }
556 yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
557 490
558 if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) 491static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
559 itv->dma_data_req_size = 492{
560 1080 * ((yi->v4l2_src_h + 31) & ~31); 493 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
494 struct ivtv_open_id *id = fh;
495 struct ivtv *itv = id->itv;
561 496
562 /* Force update of yuv registers */ 497 if (id->type == IVTV_DEC_STREAM_TYPE_VBI)
563 yi->yuv_forced_update = 1; 498 return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt);
564 return 0;
565 }
566 return 0;
567 }
568 499
569 if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) { 500 /* set sliced VBI capture format */
570 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) 501 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
571 return -EINVAL; 502 vbifmt->reserved[0] = 0;
572 if (set_fmt) { 503 vbifmt->reserved[1] = 0;
573 itv->osd_chroma_key = fmt->fmt.win.chromakey;
574 itv->osd_global_alpha = fmt->fmt.win.global_alpha;
575 ivtv_set_osd_alpha(itv);
576 }
577 return 0;
578 }
579 504
580 /* set window size */ 505 if (vbifmt->service_set)
581 if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 506 ivtv_expand_service_set(vbifmt, itv->is_50hz);
582 struct cx2341x_mpeg_params *p = &itv->params; 507 check_service_set(vbifmt, itv->is_50hz);
583 int w = fmt->fmt.pix.width; 508 vbifmt->service_set = ivtv_get_service_set(vbifmt);
584 int h = fmt->fmt.pix.height; 509 return 0;
585 510}
586 if (w > 720) w = 720;
587 else if (w < 1) w = 1;
588 if (h > (itv->is_50hz ? 576 : 480)) h = (itv->is_50hz ? 576 : 480);
589 else if (h < 2) h = 2;
590 ivtv_get_fmt(itv, streamtype, fmt);
591 fmt->fmt.pix.width = w;
592 fmt->fmt.pix.height = h;
593
594 if (!set_fmt || (p->width == w && p->height == h))
595 return 0;
596 if (atomic_read(&itv->capturing) > 0)
597 return -EBUSY;
598 511
599 p->width = w; 512static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
600 p->height = h; 513{
601 if (w != 720 || h != (itv->is_50hz ? 576 : 480)) 514 struct ivtv_open_id *id = fh;
602 p->video_temporal_filter = 0; 515 s32 w, h;
603 else 516 int field;
604 p->video_temporal_filter = 8; 517 int ret;
605 if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
606 fmt->fmt.pix.width /= 2;
607 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
608 return ivtv_get_fmt(itv, streamtype, fmt);
609 }
610 518
611 /* set raw VBI format */ 519 w = fmt->fmt.pix.width;
612 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 520 h = fmt->fmt.pix.height;
613 if (set_fmt && atomic_read(&itv->capturing) > 0) { 521 field = fmt->fmt.pix.field;
614 return -EBUSY; 522 ret = ivtv_g_fmt_vid_out(file, fh, fmt);
615 } 523 fmt->fmt.pix.width = w;
616 if (set_fmt) { 524 fmt->fmt.pix.height = h;
617 itv->vbi.sliced_in->service_set = 0; 525 if (!ret && id->type == IVTV_DEC_STREAM_TYPE_YUV) {
618 itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in); 526 fmt->fmt.pix.field = field;
619 } 527 if (fmt->fmt.pix.width < 2)
620 return ivtv_get_fmt(itv, streamtype, fmt); 528 fmt->fmt.pix.width = 2;
621 } 529 if (fmt->fmt.pix.width > 720)
530 fmt->fmt.pix.width = 720;
531 if (fmt->fmt.pix.height < 2)
532 fmt->fmt.pix.height = 2;
533 if (fmt->fmt.pix.height > 576)
534 fmt->fmt.pix.height = 576;
535 }
536 return ret;
537}
622 538
623 /* set sliced VBI output 539static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
624 In principle the user could request that only certain 540{
625 VBI types are output and that the others are ignored. 541 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
626 I.e., suppress CC in the even fields or only output 542 u32 chromakey = fmt->fmt.win.chromakey;
627 WSS and no VPS. Currently though there is no choice. */ 543 u8 global_alpha = fmt->fmt.win.global_alpha;
628 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
629 return ivtv_get_fmt(itv, streamtype, fmt);
630 544
631 /* any else but sliced VBI capture is an error */ 545 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
632 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
633 return -EINVAL; 546 return -EINVAL;
547 ivtv_g_fmt_vid_out_overlay(file, fh, fmt);
548 fmt->fmt.win.chromakey = chromakey;
549 fmt->fmt.win.global_alpha = global_alpha;
550 return 0;
551}
634 552
635 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) 553static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
636 return ivtv_get_fmt(itv, streamtype, fmt); 554{
555 return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
556}
637 557
638 /* set sliced VBI capture format */ 558static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
639 vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; 559{
640 memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); 560 struct ivtv_open_id *id = fh;
561 struct ivtv *itv = id->itv;
562 struct cx2341x_mpeg_params *p = &itv->params;
563 int w = fmt->fmt.pix.width;
564 int h = fmt->fmt.pix.height;
565 int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
641 566
642 if (vbifmt->service_set) 567 if (ret)
643 ivtv_expand_service_set(vbifmt, itv->is_50hz); 568 return ret;
644 set = check_service_set(vbifmt, itv->is_50hz);
645 vbifmt->service_set = ivtv_get_service_set(vbifmt);
646 569
647 if (!set_fmt) 570 if (p->width == w && p->height == h)
648 return 0; 571 return 0;
649 if (set == 0) 572
573 if (atomic_read(&itv->capturing) > 0)
574 return -EBUSY;
575
576 p->width = w;
577 p->height = h;
578 if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
579 fmt->fmt.pix.width /= 2;
580 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
581 return ivtv_g_fmt_vid_cap(file, fh, fmt);
582}
583
584static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
585{
586 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
587
588 itv->vbi.sliced_in->service_set = 0;
589 itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in);
590 return ivtv_g_fmt_vbi_cap(file, fh, fmt);
591}
592
593static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
594{
595 struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
596 struct ivtv_open_id *id = fh;
597 struct ivtv *itv = id->itv;
598 int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);
599
600 if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
601 return ret;
602
603 if (check_service_set(vbifmt, itv->is_50hz) == 0)
650 return -EINVAL; 604 return -EINVAL;
651 if (atomic_read(&itv->capturing) > 0) { 605 if (atomic_read(&itv->capturing) > 0)
652 return -EBUSY; 606 return -EBUSY;
653 }
654 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); 607 itv->video_dec_func(itv, VIDIOC_S_FMT, fmt);
655 memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); 608 memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
656 return 0; 609 return 0;
657} 610}
658 611
659static int ivtv_debug_ioctls(struct file *filp, unsigned int cmd, void *arg) 612static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
660{ 613{
661 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; 614 struct ivtv_open_id *id = fh;
662 struct ivtv *itv = id->itv; 615 struct ivtv *itv = id->itv;
663 struct v4l2_register *reg = arg; 616 struct yuv_playback_info *yi = &itv->yuv_info;
617 int ret = ivtv_try_fmt_vid_out(file, fh, fmt);
664 618
665 switch (cmd) { 619 if (ret)
666 /* ioctls to allow direct access to the encoder registers for testing */ 620 return ret;
667 case VIDIOC_DBG_G_REGISTER:
668 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
669 return ivtv_itvc(itv, cmd, arg);
670 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
671 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
672 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
673
674 case VIDIOC_DBG_S_REGISTER:
675 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
676 return ivtv_itvc(itv, cmd, arg);
677 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
678 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
679 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
680
681 case VIDIOC_G_CHIP_IDENT: {
682 struct v4l2_chip_ident *chip = arg;
683
684 chip->ident = V4L2_IDENT_NONE;
685 chip->revision = 0;
686 if (reg->match_type == V4L2_CHIP_MATCH_HOST) {
687 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
688 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
689 return 0;
690 }
691 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
692 return ivtv_i2c_id(itv, reg->match_chip, cmd, arg);
693 if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
694 return ivtv_call_i2c_client(itv, reg->match_chip, cmd, arg);
695 return -EINVAL;
696 }
697 621
698 case VIDIOC_INT_S_AUDIO_ROUTING: { 622 if (id->type != IVTV_DEC_STREAM_TYPE_YUV)
699 struct v4l2_routing *route = arg; 623 return 0;
700 624
701 ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route); 625 /* Return now if we already have some frame data */
702 break; 626 if (yi->stream_size)
703 } 627 return -EBUSY;
704 628
705 case VIDIOC_INT_RESET: { 629 yi->v4l2_src_w = fmt->fmt.pix.width;
706 u32 val = *(u32 *)arg; 630 yi->v4l2_src_h = fmt->fmt.pix.height;
707 631
708 if ((val == 0 && itv->options.newi2c) || (val & 0x01)) { 632 switch (fmt->fmt.pix.field) {
709 ivtv_reset_ir_gpio(itv); 633 case V4L2_FIELD_NONE:
710 } 634 yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
711 if (val & 0x02) {
712 itv->video_dec_func(itv, cmd, NULL);
713 }
714 break; 635 break;
715 } 636 case V4L2_FIELD_ANY:
716 637 yi->lace_mode = IVTV_YUV_MODE_AUTO;
638 break;
639 case V4L2_FIELD_INTERLACED_BT:
640 yi->lace_mode =
641 IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
642 break;
643 case V4L2_FIELD_INTERLACED_TB:
717 default: 644 default:
718 return -EINVAL; 645 yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
646 break;
719 } 647 }
648 yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
649
650 if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
651 itv->dma_data_req_size =
652 1080 * ((yi->v4l2_src_h + 31) & ~31);
653
654 /* Force update of yuv registers */
655 yi->yuv_forced_update = 1;
720 return 0; 656 return 0;
721} 657}
722 658
723int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg) 659static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
724{ 660{
725 struct ivtv_open_id *id = NULL; 661 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
726 struct yuv_playback_info *yi = &itv->yuv_info; 662 int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);
727 u32 data[CX2341X_MBOX_MAX_DATA];
728 int streamtype = 0;
729 663
730 if (filp) { 664 if (ret == 0) {
731 id = (struct ivtv_open_id *)filp->private_data; 665 itv->osd_chroma_key = fmt->fmt.win.chromakey;
732 streamtype = id->type; 666 itv->osd_global_alpha = fmt->fmt.win.global_alpha;
667 ivtv_set_osd_alpha(itv);
733 } 668 }
669 return ret;
670}
734 671
735 switch (cmd) { 672static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident *chip)
736 case VIDIOC_G_PRIORITY: 673{
737 { 674 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
738 enum v4l2_priority *p = arg;
739 675
740 *p = v4l2_prio_max(&itv->prio); 676 chip->ident = V4L2_IDENT_NONE;
741 break; 677 chip->revision = 0;
678 if (chip->match_type == V4L2_CHIP_MATCH_HOST) {
679 if (v4l2_chip_match_host(chip->match_type, chip->match_chip))
680 chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
681 return 0;
742 } 682 }
683 if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
684 return ivtv_i2c_id(itv, chip->match_chip, VIDIOC_G_CHIP_IDENT, chip);
685 if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
686 return ivtv_call_i2c_client(itv, chip->match_chip, VIDIOC_G_CHIP_IDENT, chip);
687 return -EINVAL;
688}
743 689
744 case VIDIOC_S_PRIORITY: 690#ifdef CONFIG_VIDEO_ADV_DEBUG
745 { 691static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
746 enum v4l2_priority *prio = arg; 692{
693 struct v4l2_register *regs = arg;
694 unsigned long flags;
695 volatile u8 __iomem *reg_start;
747 696
748 return v4l2_prio_change(&itv->prio, &id->prio, *prio); 697 if (!capable(CAP_SYS_ADMIN))
749 } 698 return -EPERM;
699 if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
700 reg_start = itv->reg_mem - IVTV_REG_OFFSET;
701 else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
702 regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
703 reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
704 else if (regs->reg >= 0 && regs->reg < IVTV_ENCODER_SIZE)
705 reg_start = itv->enc_mem;
706 else
707 return -EINVAL;
750 708
751 case VIDIOC_QUERYCAP:{ 709 spin_lock_irqsave(&ivtv_cards_lock, flags);
752 struct v4l2_capability *vcap = arg; 710 if (cmd == VIDIOC_DBG_G_REGISTER)
711 regs->val = readl(regs->reg + reg_start);
712 else
713 writel(regs->val, regs->reg + reg_start);
714 spin_unlock_irqrestore(&ivtv_cards_lock, flags);
715 return 0;
716}
753 717
754 memset(vcap, 0, sizeof(*vcap)); 718static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *reg)
755 strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); 719{
756 strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); 720 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
757 strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->bus_info));
758 vcap->version = IVTV_DRIVER_VERSION; /* version */
759 vcap->capabilities = itv->v4l2_cap; /* capabilities */
760 721
761 /* reserved.. must set to 0! */ 722 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
762 vcap->reserved[0] = vcap->reserved[1] = 723 return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
763 vcap->reserved[2] = vcap->reserved[3] = 0; 724 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
764 break; 725 return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_G_REGISTER, reg);
765 } 726 return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_G_REGISTER, reg);
727}
766 728
767 case VIDIOC_ENUMAUDIO:{ 729static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *reg)
768 struct v4l2_audio *vin = arg; 730{
731 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
769 732
770 return ivtv_get_audio_input(itv, vin->index, vin); 733 if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
771 } 734 return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
735 if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
736 return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg);
737 return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg);
738}
739#endif
772 740
773 case VIDIOC_G_AUDIO:{ 741static int ivtv_g_priority(struct file *file, void *fh, enum v4l2_priority *p)
774 struct v4l2_audio *vin = arg; 742{
743 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
775 744
776 vin->index = itv->audio_input; 745 *p = v4l2_prio_max(&itv->prio);
777 return ivtv_get_audio_input(itv, vin->index, vin);
778 }
779 746
780 case VIDIOC_S_AUDIO:{ 747 return 0;
781 struct v4l2_audio *vout = arg; 748}
782 749
783 if (vout->index >= itv->nof_audio_inputs) 750static int ivtv_s_priority(struct file *file, void *fh, enum v4l2_priority prio)
784 return -EINVAL; 751{
785 itv->audio_input = vout->index; 752 struct ivtv_open_id *id = fh;
786 ivtv_audio_set_io(itv); 753 struct ivtv *itv = id->itv;
787 break;
788 }
789 754
790 case VIDIOC_ENUMAUDOUT:{ 755 return v4l2_prio_change(&itv->prio, &id->prio, prio);
791 struct v4l2_audioout *vin = arg; 756}
792 757
793 /* set it to defaults from our table */ 758static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
794 return ivtv_get_audio_output(itv, vin->index, vin); 759{
795 } 760 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
796 761
797 case VIDIOC_G_AUDOUT:{ 762 strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
798 struct v4l2_audioout *vin = arg; 763 strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
764 strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->bus_info));
765 vcap->version = IVTV_DRIVER_VERSION; /* version */
766 vcap->capabilities = itv->v4l2_cap; /* capabilities */
767 return 0;
768}
799 769
800 vin->index = 0; 770static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
801 return ivtv_get_audio_output(itv, vin->index, vin); 771{
802 } 772 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
803 773
804 case VIDIOC_S_AUDOUT:{ 774 return ivtv_get_audio_input(itv, vin->index, vin);
805 struct v4l2_audioout *vout = arg; 775}
806 776
807 return ivtv_get_audio_output(itv, vout->index, vout); 777static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
808 } 778{
779 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
809 780
810 case VIDIOC_ENUMINPUT:{ 781 vin->index = itv->audio_input;
811 struct v4l2_input *vin = arg; 782 return ivtv_get_audio_input(itv, vin->index, vin);
783}
812 784
813 /* set it to defaults from our table */ 785static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
814 return ivtv_get_input(itv, vin->index, vin); 786{
815 } 787 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
816 788
817 case VIDIOC_ENUMOUTPUT:{ 789 if (vout->index >= itv->nof_audio_inputs)
818 struct v4l2_output *vout = arg; 790 return -EINVAL;
819 791
820 return ivtv_get_output(itv, vout->index, vout); 792 itv->audio_input = vout->index;
821 } 793 ivtv_audio_set_io(itv);
822 794
823 case VIDIOC_TRY_FMT: 795 return 0;
824 case VIDIOC_S_FMT: { 796}
825 struct v4l2_format *fmt = arg;
826 797
827 return ivtv_try_or_set_fmt(itv, id->type, fmt, cmd == VIDIOC_S_FMT); 798static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
828 } 799{
800 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
829 801
830 case VIDIOC_G_FMT: { 802 /* set it to defaults from our table */
831 struct v4l2_format *fmt = arg; 803 return ivtv_get_audio_output(itv, vin->index, vin);
832 int type = fmt->type; 804}
833 805
834 memset(fmt, 0, sizeof(*fmt)); 806static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
835 fmt->type = type; 807{
836 return ivtv_get_fmt(itv, id->type, fmt); 808 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
837 }
838 809
839 case VIDIOC_CROPCAP: { 810 vin->index = 0;
840 struct v4l2_cropcap *cropcap = arg; 811 return ivtv_get_audio_output(itv, vin->index, vin);
812}
841 813
842 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 814static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout)
843 return -EINVAL; 815{
844 cropcap->bounds.top = cropcap->bounds.left = 0; 816 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
845 cropcap->bounds.width = 720; 817
846 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 818 return ivtv_get_audio_output(itv, vout->index, vout);
847 cropcap->bounds.height = itv->is_50hz ? 576 : 480; 819}
848 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; 820
849 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; 821static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
850 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { 822{
851 if (yi->track_osd) { 823 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
852 cropcap->bounds.width = yi->osd_full_w; 824
853 cropcap->bounds.height = yi->osd_full_h; 825 /* set it to defaults from our table */
854 } else { 826 return ivtv_get_input(itv, vin->index, vin);
855 cropcap->bounds.width = 720; 827}
856 cropcap->bounds.height = 828
857 itv->is_out_50hz ? 576 : 480; 829static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
858 } 830{
859 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; 831 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
860 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; 832
833 return ivtv_get_output(itv, vout->index, vout);
834}
835
836static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
837{
838 struct ivtv_open_id *id = fh;
839 struct ivtv *itv = id->itv;
840 struct yuv_playback_info *yi = &itv->yuv_info;
841 int streamtype;
842
843 streamtype = id->type;
844
845 if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
846 return -EINVAL;
847 cropcap->bounds.top = cropcap->bounds.left = 0;
848 cropcap->bounds.width = 720;
849 if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
850 cropcap->bounds.height = itv->is_50hz ? 576 : 480;
851 cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
852 cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
853 } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
854 if (yi->track_osd) {
855 cropcap->bounds.width = yi->osd_full_w;
856 cropcap->bounds.height = yi->osd_full_h;
861 } else { 857 } else {
862 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480; 858 cropcap->bounds.width = 720;
863 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; 859 cropcap->bounds.height =
864 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; 860 itv->is_out_50hz ? 576 : 480;
865 } 861 }
866 cropcap->defrect = cropcap->bounds; 862 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
867 return 0; 863 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
864 } else {
865 cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
866 cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
867 cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
868 } 868 }
869 cropcap->defrect = cropcap->bounds;
870 return 0;
871}
872
873static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
874{
875 struct ivtv_open_id *id = fh;
876 struct ivtv *itv = id->itv;
877 struct yuv_playback_info *yi = &itv->yuv_info;
878 int streamtype;
869 879
870 case VIDIOC_S_CROP: { 880 streamtype = id->type;
871 struct v4l2_crop *crop = arg;
872 881
873 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && 882 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
874 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { 883 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
875 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { 884 /* Should be replaced */
876 yi->main_rect = crop->c; 885 /* v4l_printk_ioctl(VIDIOC_S_CROP); */
886 }
887
888 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
889 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
890 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
891 yi->main_rect = crop->c;
892 return 0;
893 } else {
894 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
895 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
896 itv->main_rect = crop->c;
877 return 0; 897 return 0;
878 } else {
879 if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
880 crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
881 itv->main_rect = crop->c;
882 return 0;
883 }
884 } 898 }
885 return -EINVAL;
886 } 899 }
887 return -EINVAL; 900 return -EINVAL;
888 } 901 }
902 return -EINVAL;
903}
889 904
890 case VIDIOC_G_CROP: { 905static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
891 struct v4l2_crop *crop = arg; 906{
907 struct ivtv_open_id *id = fh;
908 struct ivtv *itv = id->itv;
909 struct yuv_playback_info *yi = &itv->yuv_info;
910 int streamtype;
892 911
893 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && 912 streamtype = id->type;
894 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { 913
895 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) 914 if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
896 crop->c = yi->main_rect; 915 (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
897 else 916 if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
898 crop->c = itv->main_rect; 917 crop->c = yi->main_rect;
899 return 0; 918 else
919 crop->c = itv->main_rect;
920 return 0;
921 }
922 return -EINVAL;
923}
924
925static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
926{
927 static struct v4l2_fmtdesc formats[] = {
928 { 0, 0, 0,
929 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
930 { 0, 0, 0, 0 }
931 },
932 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
933 "MPEG", V4L2_PIX_FMT_MPEG,
934 { 0, 0, 0, 0 }
900 } 935 }
936 };
937 enum v4l2_buf_type type = fmt->type;
938
939 if (fmt->index > 1)
901 return -EINVAL; 940 return -EINVAL;
902 }
903 941
904 case VIDIOC_ENUM_FMT: { 942 *fmt = formats[fmt->index];
905 static struct v4l2_fmtdesc formats[] = { 943 fmt->type = type;
906 { 0, 0, 0, 944 return 0;
907 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, 945}
908 { 0, 0, 0, 0 }
909 },
910 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
911 "MPEG", V4L2_PIX_FMT_MPEG,
912 { 0, 0, 0, 0 }
913 }
914 };
915 struct v4l2_fmtdesc *fmt = arg;
916 enum v4l2_buf_type type = fmt->type;
917 946
918 switch (type) { 947static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
919 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 948{
920 break; 949 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
921 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 950
922 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) 951 static struct v4l2_fmtdesc formats[] = {
923 return -EINVAL; 952 { 0, 0, 0,
924 break; 953 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
925 default: 954 { 0, 0, 0, 0 }
926 return -EINVAL; 955 },
956 { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
957 "MPEG", V4L2_PIX_FMT_MPEG,
958 { 0, 0, 0, 0 }
927 } 959 }
928 if (fmt->index > 1) 960 };
929 return -EINVAL; 961 enum v4l2_buf_type type = fmt->type;
930 *fmt = formats[fmt->index]; 962
931 fmt->type = type; 963 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
964 return -EINVAL;
965
966 if (fmt->index > 1)
967 return -EINVAL;
968
969 *fmt = formats[fmt->index];
970 fmt->type = type;
971
972 return 0;
973}
974
975static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
976{
977 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
978
979 *i = itv->active_input;
980
981 return 0;
982}
983
984int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
985{
986 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
987
988 if (inp < 0 || inp >= itv->nof_inputs)
989 return -EINVAL;
990
991 if (inp == itv->active_input) {
992 IVTV_DEBUG_INFO("Input unchanged\n");
932 return 0; 993 return 0;
933 } 994 }
934 995
935 case VIDIOC_G_INPUT:{ 996 if (atomic_read(&itv->capturing) > 0) {
936 *(int *)arg = itv->active_input; 997 return -EBUSY;
937 break;
938 } 998 }
939 999
940 case VIDIOC_S_INPUT:{ 1000 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
941 int inp = *(int *)arg; 1001 itv->active_input, inp);
942 1002
943 if (inp < 0 || inp >= itv->nof_inputs) 1003 itv->active_input = inp;
944 return -EINVAL; 1004 /* Set the audio input to whatever is appropriate for the
1005 input type. */
1006 itv->audio_input = itv->card->video_inputs[inp].audio_index;
945 1007
946 if (inp == itv->active_input) { 1008 /* prevent others from messing with the streams until
947 IVTV_DEBUG_INFO("Input unchanged\n"); 1009 we're finished changing inputs. */
948 break; 1010 ivtv_mute(itv);
949 } 1011 ivtv_video_set_io(itv);
950 if (atomic_read(&itv->capturing) > 0) { 1012 ivtv_audio_set_io(itv);
951 return -EBUSY; 1013 ivtv_unmute(itv);
952 }
953 IVTV_DEBUG_INFO("Changing input from %d to %d\n",
954 itv->active_input, inp);
955 1014
956 itv->active_input = inp; 1015 return 0;
957 /* Set the audio input to whatever is appropriate for the 1016}
958 input type. */
959 itv->audio_input = itv->card->video_inputs[inp].audio_index;
960 1017
961 /* prevent others from messing with the streams until 1018static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
962 we're finished changing inputs. */ 1019{
963 ivtv_mute(itv); 1020 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
964 ivtv_video_set_io(itv);
965 ivtv_audio_set_io(itv);
966 ivtv_unmute(itv);
967 break;
968 }
969 1021
970 case VIDIOC_G_OUTPUT:{ 1022 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
971 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) 1023 return -EINVAL;
972 return -EINVAL;
973 *(int *)arg = itv->active_output;
974 break;
975 }
976 1024
977 case VIDIOC_S_OUTPUT:{ 1025 *i = itv->active_output;
978 int outp = *(int *)arg;
979 struct v4l2_routing route;
980 1026
981 if (outp >= itv->card->nof_outputs) 1027 return 0;
982 return -EINVAL; 1028}
983 1029
984 if (outp == itv->active_output) { 1030static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
985 IVTV_DEBUG_INFO("Output unchanged\n"); 1031{
986 break; 1032 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
987 } 1033 struct v4l2_routing route;
988 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
989 itv->active_output, outp);
990 1034
991 itv->active_output = outp; 1035 if (outp >= itv->card->nof_outputs)
992 route.input = SAA7127_INPUT_TYPE_NORMAL; 1036 return -EINVAL;
993 route.output = itv->card->video_outputs[outp].video_output; 1037
994 ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); 1038 if (outp == itv->active_output) {
995 break; 1039 IVTV_DEBUG_INFO("Output unchanged\n");
1040 return 0;
996 } 1041 }
1042 IVTV_DEBUG_INFO("Changing output from %d to %d\n",
1043 itv->active_output, outp);
997 1044
998 case VIDIOC_G_FREQUENCY:{ 1045 itv->active_output = outp;
999 struct v4l2_frequency *vf = arg; 1046 route.input = SAA7127_INPUT_TYPE_NORMAL;
1047 route.output = itv->card->video_outputs[outp].video_output;
1048 ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route);
1000 1049
1001 if (vf->tuner != 0) 1050 return 0;
1002 return -EINVAL; 1051}
1003 ivtv_call_i2c_clients(itv, cmd, arg);
1004 break;
1005 }
1006 1052
1007 case VIDIOC_S_FREQUENCY:{ 1053static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1008 struct v4l2_frequency vf = *(struct v4l2_frequency *)arg; 1054{
1055 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1009 1056
1010 if (vf.tuner != 0) 1057 if (vf->tuner != 0)
1011 return -EINVAL; 1058 return -EINVAL;
1012 1059
1013 ivtv_mute(itv); 1060 ivtv_call_i2c_clients(itv, VIDIOC_G_FREQUENCY, vf);
1014 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency); 1061 return 0;
1015 ivtv_call_i2c_clients(itv, cmd, &vf); 1062}
1016 ivtv_unmute(itv);
1017 break;
1018 }
1019 1063
1020 case VIDIOC_ENUMSTD:{ 1064int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
1021 struct v4l2_standard *vs = arg; 1065{
1022 int idx = vs->index; 1066 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1023 1067
1024 if (idx < 0 || idx >= ARRAY_SIZE(enum_stds)) 1068 if (vf->tuner != 0)
1025 return -EINVAL; 1069 return -EINVAL;
1026 1070
1027 *vs = (enum_stds[idx].std & V4L2_STD_525_60) ? 1071 ivtv_mute(itv);
1028 ivtv_std_60hz : ivtv_std_50hz; 1072 IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
1029 vs->index = idx; 1073 ivtv_call_i2c_clients(itv, VIDIOC_S_FREQUENCY, vf);
1030 vs->id = enum_stds[idx].std; 1074 ivtv_unmute(itv);
1031 strlcpy(vs->name, enum_stds[idx].name, sizeof(vs->name)); 1075 return 0;
1032 break; 1076}
1033 }
1034 1077
1035 case VIDIOC_G_STD:{ 1078static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
1036 *(v4l2_std_id *) arg = itv->std; 1079{
1037 break; 1080 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1038 }
1039 1081
1040 case VIDIOC_S_STD: { 1082 *std = itv->std;
1041 v4l2_std_id std = *(v4l2_std_id *) arg; 1083 return 0;
1084}
1042 1085
1043 if ((std & V4L2_STD_ALL) == 0) 1086int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
1044 return -EINVAL; 1087{
1088 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1089 struct yuv_playback_info *yi = &itv->yuv_info;
1045 1090
1046 if (std == itv->std) 1091 if ((*std & V4L2_STD_ALL) == 0)
1047 break; 1092 return -EINVAL;
1048 1093
1049 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) || 1094 if (*std == itv->std)
1050 atomic_read(&itv->capturing) > 0 || 1095 return 0;
1051 atomic_read(&itv->decoding) > 0) {
1052 /* Switching standard would turn off the radio or mess
1053 with already running streams, prevent that by
1054 returning EBUSY. */
1055 return -EBUSY;
1056 }
1057 1096
1058 itv->std = std; 1097 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
1059 itv->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0; 1098 atomic_read(&itv->capturing) > 0 ||
1060 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz; 1099 atomic_read(&itv->decoding) > 0) {
1061 itv->params.width = 720; 1100 /* Switching standard would turn off the radio or mess
1062 itv->params.height = itv->is_50hz ? 576 : 480; 1101 with already running streams, prevent that by
1063 itv->vbi.count = itv->is_50hz ? 18 : 12; 1102 returning EBUSY. */
1064 itv->vbi.start[0] = itv->is_50hz ? 6 : 10; 1103 return -EBUSY;
1065 itv->vbi.start[1] = itv->is_50hz ? 318 : 273; 1104 }
1066 if (itv->hw_flags & IVTV_HW_CX25840) { 1105
1067 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; 1106 itv->std = *std;
1068 } 1107 itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
1069 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std); 1108 itv->params.is_50hz = itv->is_50hz = !itv->is_60hz;
1070 1109 itv->params.width = 720;
1071 /* Tuner */ 1110 itv->params.height = itv->is_50hz ? 576 : 480;
1072 ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); 1111 itv->vbi.count = itv->is_50hz ? 18 : 12;
1073 1112 itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
1074 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { 1113 itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
1075 /* set display standard */ 1114
1076 itv->std_out = std; 1115 if (itv->hw_flags & IVTV_HW_CX25840)
1077 itv->is_out_60hz = itv->is_60hz; 1116 itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
1078 itv->is_out_50hz = itv->is_50hz; 1117
1079 ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out); 1118 IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
1080 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); 1119
1081 itv->main_rect.left = itv->main_rect.top = 0; 1120 /* Tuner */
1082 itv->main_rect.width = 720; 1121 ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
1083 itv->main_rect.height = itv->params.height; 1122
1084 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, 1123 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
1085 720, itv->main_rect.height, 0, 0); 1124 /* set display standard */
1086 yi->main_rect = itv->main_rect; 1125 itv->std_out = *std;
1087 if (!itv->osd_info) { 1126 itv->is_out_60hz = itv->is_60hz;
1088 yi->osd_full_w = 720; 1127 itv->is_out_50hz = itv->is_50hz;
1089 yi->osd_full_h = itv->is_out_50hz ? 576 : 480; 1128 ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out);
1090 } 1129 ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
1130 itv->main_rect.left = itv->main_rect.top = 0;
1131 itv->main_rect.width = 720;
1132 itv->main_rect.height = itv->params.height;
1133 ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
1134 720, itv->main_rect.height, 0, 0);
1135 yi->main_rect = itv->main_rect;
1136 if (!itv->osd_info) {
1137 yi->osd_full_w = 720;
1138 yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
1091 } 1139 }
1092 break;
1093 } 1140 }
1141 return 0;
1142}
1094 1143
1095 case VIDIOC_S_TUNER: { /* Setting tuner can only set audio mode */ 1144static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1096 struct v4l2_tuner *vt = arg; 1145{
1146 struct ivtv_open_id *id = fh;
1147 struct ivtv *itv = id->itv;
1097 1148
1098 if (vt->index != 0) 1149 if (vt->index != 0)
1099 return -EINVAL; 1150 return -EINVAL;
1100 1151
1101 ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt); 1152 ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt);
1102 break;
1103 }
1104 1153
1105 case VIDIOC_G_TUNER: { 1154 return 0;
1106 struct v4l2_tuner *vt = arg; 1155}
1107 1156
1108 if (vt->index != 0) 1157static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
1109 return -EINVAL; 1158{
1159 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1110 1160
1111 memset(vt, 0, sizeof(*vt)); 1161 if (vt->index != 0)
1112 ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt); 1162 return -EINVAL;
1113 1163
1114 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { 1164 ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
1115 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name)); 1165
1116 vt->type = V4L2_TUNER_RADIO; 1166 if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
1117 } else { 1167 strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
1118 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name)); 1168 vt->type = V4L2_TUNER_RADIO;
1119 vt->type = V4L2_TUNER_ANALOG_TV; 1169 } else {
1120 } 1170 strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
1121 break; 1171 vt->type = V4L2_TUNER_ANALOG_TV;
1122 } 1172 }
1123 1173
1124 case VIDIOC_G_SLICED_VBI_CAP: { 1174 return 0;
1125 struct v4l2_sliced_vbi_cap *cap = arg; 1175}
1126 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; 1176
1127 int f, l; 1177static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
1128 enum v4l2_buf_type type = cap->type; 1178{
1129 1179 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1130 memset(cap, 0, sizeof(*cap)); 1180 int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
1131 cap->type = type; 1181 int f, l;
1132 if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { 1182
1133 for (f = 0; f < 2; f++) { 1183 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
1134 for (l = 0; l < 24; l++) { 1184 for (f = 0; f < 2; f++) {
1135 if (valid_service_line(f, l, itv->is_50hz)) { 1185 for (l = 0; l < 24; l++) {
1136 cap->service_lines[f][l] = set; 1186 if (valid_service_line(f, l, itv->is_50hz))
1137 } 1187 cap->service_lines[f][l] = set;
1138 }
1139 } 1188 }
1140 return 0;
1141 } 1189 }
1142 if (type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { 1190 return 0;
1143 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) 1191 }
1144 return -EINVAL; 1192 if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
1145 if (itv->is_60hz) { 1193 if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
1146 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525; 1194 return -EINVAL;
1147 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525; 1195 if (itv->is_60hz) {
1148 } else { 1196 cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
1149 cap->service_lines[0][23] = V4L2_SLICED_WSS_625; 1197 cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
1150 cap->service_lines[0][16] = V4L2_SLICED_VPS; 1198 } else {
1151 } 1199 cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
1152 return 0; 1200 cap->service_lines[0][16] = V4L2_SLICED_VPS;
1153 } 1201 }
1154 return -EINVAL; 1202 return 0;
1155 } 1203 }
1204 return -EINVAL;
1205}
1156 1206
1157 case VIDIOC_G_ENC_INDEX: { 1207static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
1158 struct v4l2_enc_idx *idx = arg; 1208{
1159 struct v4l2_enc_idx_entry *e = idx->entry; 1209 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1160 int entries; 1210 struct v4l2_enc_idx_entry *e = idx->entry;
1161 int i; 1211 int entries;
1162 1212 int i;
1163 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) % 1213
1164 IVTV_MAX_PGM_INDEX; 1214 entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
1165 if (entries > V4L2_ENC_IDX_ENTRIES) 1215 IVTV_MAX_PGM_INDEX;
1166 entries = V4L2_ENC_IDX_ENTRIES; 1216 if (entries > V4L2_ENC_IDX_ENTRIES)
1167 idx->entries = 0; 1217 entries = V4L2_ENC_IDX_ENTRIES;
1168 for (i = 0; i < entries; i++) { 1218 idx->entries = 0;
1169 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX]; 1219 for (i = 0; i < entries; i++) {
1170 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) { 1220 *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
1171 idx->entries++; 1221 if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
1172 e++; 1222 idx->entries++;
1173 } 1223 e++;
1174 } 1224 }
1175 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1176 break;
1177 } 1225 }
1226 itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
1227 return 0;
1228}
1178 1229
1179 case VIDIOC_ENCODER_CMD: 1230static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1180 case VIDIOC_TRY_ENCODER_CMD: { 1231{
1181 struct v4l2_encoder_cmd *enc = arg; 1232 struct ivtv_open_id *id = fh;
1182 int try = cmd == VIDIOC_TRY_ENCODER_CMD; 1233 struct ivtv *itv = id->itv;
1183
1184 memset(&enc->raw, 0, sizeof(enc->raw));
1185 switch (enc->cmd) {
1186 case V4L2_ENC_CMD_START:
1187 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1188 enc->flags = 0;
1189 if (try)
1190 return 0;
1191 return ivtv_start_capture(id);
1192 1234
1193 case V4L2_ENC_CMD_STOP: 1235
1194 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n"); 1236 switch (enc->cmd) {
1195 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; 1237 case V4L2_ENC_CMD_START:
1196 if (try) 1238 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1197 return 0; 1239 enc->flags = 0;
1198 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END); 1240 return ivtv_start_capture(id);
1241
1242 case V4L2_ENC_CMD_STOP:
1243 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1244 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1245 ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
1246 return 0;
1247
1248 case V4L2_ENC_CMD_PAUSE:
1249 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1250 enc->flags = 0;
1251
1252 if (!atomic_read(&itv->capturing))
1253 return -EPERM;
1254 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1199 return 0; 1255 return 0;
1200 1256
1201 case V4L2_ENC_CMD_PAUSE: 1257 ivtv_mute(itv);
1202 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n"); 1258 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1203 enc->flags = 0; 1259 break;
1204 if (try)
1205 return 0;
1206 if (!atomic_read(&itv->capturing))
1207 return -EPERM;
1208 if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1209 return 0;
1210 ivtv_mute(itv);
1211 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
1212 break;
1213 1260
1214 case V4L2_ENC_CMD_RESUME: 1261 case V4L2_ENC_CMD_RESUME:
1215 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n"); 1262 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1216 enc->flags = 0; 1263 enc->flags = 0;
1217 if (try) 1264
1218 return 0; 1265 if (!atomic_read(&itv->capturing))
1219 if (!atomic_read(&itv->capturing)) 1266 return -EPERM;
1220 return -EPERM; 1267
1221 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags)) 1268 if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
1222 return 0; 1269 return 0;
1223 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1); 1270
1224 ivtv_unmute(itv); 1271 ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
1225 break; 1272 ivtv_unmute(itv);
1226 default:
1227 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1228 return -EINVAL;
1229 }
1230 break; 1273 break;
1274 default:
1275 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1276 return -EINVAL;
1231 } 1277 }
1232 1278
1233 case VIDIOC_G_FBUF: { 1279 return 0;
1234 struct v4l2_framebuffer *fb = arg; 1280}
1235 int pixfmt;
1236 static u32 pixel_format[16] = {
1237 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
1238 V4L2_PIX_FMT_RGB565,
1239 V4L2_PIX_FMT_RGB555,
1240 V4L2_PIX_FMT_RGB444,
1241 V4L2_PIX_FMT_RGB32,
1242 0,
1243 0,
1244 0,
1245 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1246 V4L2_PIX_FMT_YUV565,
1247 V4L2_PIX_FMT_YUV555,
1248 V4L2_PIX_FMT_YUV444,
1249 V4L2_PIX_FMT_YUV32,
1250 0,
1251 0,
1252 0,
1253 };
1254 1281
1255 memset(fb, 0, sizeof(*fb)); 1282static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
1256 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) 1283{
1257 return -EINVAL; 1284 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1258 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY | 1285
1259 V4L2_FBUF_CAP_GLOBAL_ALPHA; 1286 switch (enc->cmd) {
1260 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0); 1287 case V4L2_ENC_CMD_START:
1261 data[0] |= (read_reg(0x2a00) >> 7) & 0x40; 1288 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
1262 pixfmt = (data[0] >> 3) & 0xf; 1289 enc->flags = 0;
1263 fb->fmt.pixelformat = pixel_format[pixfmt]; 1290 return 0;
1264 fb->fmt.width = itv->osd_rect.width; 1291
1265 fb->fmt.height = itv->osd_rect.height; 1292 case V4L2_ENC_CMD_STOP:
1266 fb->base = (void *)itv->osd_video_pbase; 1293 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
1267 if (itv->osd_chroma_key_state) 1294 enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
1268 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY; 1295 return 0;
1269 if (itv->osd_global_alpha_state) 1296
1270 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; 1297 case V4L2_ENC_CMD_PAUSE:
1271 pixfmt &= 7; 1298 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
1272 /* no local alpha for RGB565 or unknown formats */ 1299 enc->flags = 0;
1273 if (pixfmt == 1 || pixfmt > 4) 1300 return 0;
1274 break; 1301
1302 case V4L2_ENC_CMD_RESUME:
1303 IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
1304 enc->flags = 0;
1305 return 0;
1306 default:
1307 IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
1308 return -EINVAL;
1309 }
1310}
1311
1312static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1313{
1314 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1315 u32 data[CX2341X_MBOX_MAX_DATA];
1316 struct yuv_playback_info *yi = &itv->yuv_info;
1317
1318 int pixfmt;
1319 static u32 pixel_format[16] = {
1320 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
1321 V4L2_PIX_FMT_RGB565,
1322 V4L2_PIX_FMT_RGB555,
1323 V4L2_PIX_FMT_RGB444,
1324 V4L2_PIX_FMT_RGB32,
1325 0,
1326 0,
1327 0,
1328 V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
1329 V4L2_PIX_FMT_YUV565,
1330 V4L2_PIX_FMT_YUV555,
1331 V4L2_PIX_FMT_YUV444,
1332 V4L2_PIX_FMT_YUV32,
1333 0,
1334 0,
1335 0,
1336 };
1337
1338 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1339 return -EINVAL;
1340 if (!itv->osd_video_pbase)
1341 return -EINVAL;
1342
1343 fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
1344 V4L2_FBUF_CAP_GLOBAL_ALPHA;
1345
1346 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1347 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1348 pixfmt = (data[0] >> 3) & 0xf;
1349
1350 fb->fmt.pixelformat = pixel_format[pixfmt];
1351 fb->fmt.width = itv->osd_rect.width;
1352 fb->fmt.height = itv->osd_rect.height;
1353 fb->fmt.field = V4L2_FIELD_INTERLACED;
1354 fb->fmt.bytesperline = fb->fmt.width;
1355 fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
1356 fb->fmt.field = V4L2_FIELD_INTERLACED;
1357 fb->fmt.priv = 0;
1358 if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
1359 fb->fmt.bytesperline *= 2;
1360 if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
1361 fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
1362 fb->fmt.bytesperline *= 2;
1363 fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
1364 fb->base = (void *)itv->osd_video_pbase;
1365 fb->flags = 0;
1366
1367 if (itv->osd_chroma_key_state)
1368 fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
1369
1370 if (itv->osd_global_alpha_state)
1371 fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
1372
1373 pixfmt &= 7;
1374
1375 /* no local alpha for RGB565 or unknown formats */
1376 if (pixfmt == 1 || pixfmt > 4)
1377 return 0;
1378
1379 /* 16-bit formats have inverted local alpha */
1380 if (pixfmt == 2 || pixfmt == 3)
1381 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
1382 else
1383 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
1384
1385 if (itv->osd_local_alpha_state) {
1275 /* 16-bit formats have inverted local alpha */ 1386 /* 16-bit formats have inverted local alpha */
1276 if (pixfmt == 2 || pixfmt == 3) 1387 if (pixfmt == 2 || pixfmt == 3)
1277 fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA; 1388 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
1278 else 1389 else
1279 fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA; 1390 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
1280 if (itv->osd_local_alpha_state) {
1281 /* 16-bit formats have inverted local alpha */
1282 if (pixfmt == 2 || pixfmt == 3)
1283 fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
1284 else
1285 fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
1286 }
1287 if (yi->track_osd)
1288 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
1289 break;
1290 } 1391 }
1392 if (yi->track_osd)
1393 fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
1291 1394
1292 case VIDIOC_S_FBUF: { 1395 return 0;
1293 struct v4l2_framebuffer *fb = arg; 1396}
1294 1397
1295 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) 1398static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
1296 return -EINVAL; 1399{
1297 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; 1400 struct ivtv_open_id *id = fh;
1298 itv->osd_local_alpha_state = 1401 struct ivtv *itv = id->itv;
1299 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0; 1402 struct yuv_playback_info *yi = &itv->yuv_info;
1300 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
1301 ivtv_set_osd_alpha(itv);
1302 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
1303 break;
1304 }
1305 1403
1306 case VIDIOC_OVERLAY: { 1404 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1307 int *on = arg; 1405 return -EINVAL;
1406 if (!itv->osd_video_pbase)
1407 return -EINVAL;
1308 1408
1309 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) 1409 itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
1310 return -EINVAL; 1410 itv->osd_local_alpha_state =
1311 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, *on != 0); 1411 (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
1312 break; 1412 itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
1313 } 1413 ivtv_set_osd_alpha(itv);
1414 yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
1415 return ivtv_g_fbuf(file, fh, fb);
1416}
1314 1417
1315 case VIDIOC_LOG_STATUS: 1418static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
1316 { 1419{
1317 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT; 1420 struct ivtv_open_id *id = fh;
1318 struct v4l2_input vidin; 1421 struct ivtv *itv = id->itv;
1319 struct v4l2_audio audin;
1320 int i;
1321 1422
1322 IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num); 1423 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
1323 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); 1424 return -EINVAL;
1324 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1325 struct tveeprom tv;
1326 1425
1327 ivtv_read_eeprom(itv, &tv); 1426 ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
1328 } 1427
1329 ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL); 1428 return 0;
1330 ivtv_get_input(itv, itv->active_input, &vidin); 1429}
1331 ivtv_get_audio_input(itv, itv->audio_input, &audin); 1430
1332 IVTV_INFO("Video Input: %s\n", vidin.name); 1431static int ivtv_log_status(struct file *file, void *fh)
1333 IVTV_INFO("Audio Input: %s%s\n", audin.name, 1432{
1334 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : ""); 1433 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1335 if (has_output) { 1434 u32 data[CX2341X_MBOX_MAX_DATA];
1336 struct v4l2_output vidout; 1435
1337 struct v4l2_audioout audout; 1436 int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
1338 int mode = itv->output_mode; 1437 struct v4l2_input vidin;
1339 static const char * const output_modes[5] = { 1438 struct v4l2_audio audin;
1340 "None", 1439 int i;
1341 "MPEG Streaming", 1440
1342 "YUV Streaming", 1441 IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num);
1343 "YUV Frames", 1442 IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
1344 "Passthrough", 1443 if (itv->hw_flags & IVTV_HW_TVEEPROM) {
1345 }; 1444 struct tveeprom tv;
1346 static const char * const audio_modes[5] = { 1445
1347 "Stereo", 1446 ivtv_read_eeprom(itv, &tv);
1348 "Left", 1447 }
1349 "Right", 1448 ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL);
1350 "Mono", 1449 ivtv_get_input(itv, itv->active_input, &vidin);
1351 "Swapped" 1450 ivtv_get_audio_input(itv, itv->audio_input, &audin);
1352 }; 1451 IVTV_INFO("Video Input: %s\n", vidin.name);
1353 static const char * const alpha_mode[4] = { 1452 IVTV_INFO("Audio Input: %s%s\n", audin.name,
1354 "None", 1453 (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
1355 "Global", 1454 if (has_output) {
1356 "Local", 1455 struct v4l2_output vidout;
1357 "Global and Local" 1456 struct v4l2_audioout audout;
1358 }; 1457 int mode = itv->output_mode;
1359 static const char * const pixel_format[16] = { 1458 static const char * const output_modes[5] = {
1360 "ARGB Indexed", 1459 "None",
1361 "RGB 5:6:5", 1460 "MPEG Streaming",
1362 "ARGB 1:5:5:5", 1461 "YUV Streaming",
1363 "ARGB 1:4:4:4", 1462 "YUV Frames",
1364 "ARGB 8:8:8:8", 1463 "Passthrough",
1365 "5", 1464 };
1366 "6", 1465 static const char * const audio_modes[5] = {
1367 "7", 1466 "Stereo",
1368 "AYUV Indexed", 1467 "Left",
1369 "YUV 5:6:5", 1468 "Right",
1370 "AYUV 1:5:5:5", 1469 "Mono",
1371 "AYUV 1:4:4:4", 1470 "Swapped"
1372 "AYUV 8:8:8:8", 1471 };
1373 "13", 1472 static const char * const alpha_mode[4] = {
1374 "14", 1473 "None",
1375 "15", 1474 "Global",
1376 }; 1475 "Local",
1377 1476 "Global and Local"
1378 ivtv_get_output(itv, itv->active_output, &vidout); 1477 };
1379 ivtv_get_audio_output(itv, 0, &audout); 1478 static const char * const pixel_format[16] = {
1380 IVTV_INFO("Video Output: %s\n", vidout.name); 1479 "ARGB Indexed",
1381 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name, 1480 "RGB 5:6:5",
1382 audio_modes[itv->audio_stereo_mode], 1481 "ARGB 1:5:5:5",
1383 audio_modes[itv->audio_bilingual_mode]); 1482 "ARGB 1:4:4:4",
1384 if (mode < 0 || mode > OUT_PASSTHROUGH) 1483 "ARGB 8:8:8:8",
1385 mode = OUT_NONE; 1484 "5",
1386 IVTV_INFO("Output Mode: %s\n", output_modes[mode]); 1485 "6",
1387 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0); 1486 "7",
1388 data[0] |= (read_reg(0x2a00) >> 7) & 0x40; 1487 "AYUV Indexed",
1389 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n", 1488 "YUV 5:6:5",
1390 data[0] & 1 ? "On" : "Off", 1489 "AYUV 1:5:5:5",
1391 alpha_mode[(data[0] >> 1) & 0x3], 1490 "AYUV 1:4:4:4",
1392 pixel_format[(data[0] >> 3) & 0xf]); 1491 "AYUV 8:8:8:8",
1393 } 1492 "13",
1394 IVTV_INFO("Tuner: %s\n", 1493 "14",
1395 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); 1494 "15",
1396 cx2341x_log_status(&itv->params, itv->name); 1495 };
1397 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); 1496
1398 for (i = 0; i < IVTV_MAX_STREAMS; i++) { 1497 ivtv_get_output(itv, itv->active_output, &vidout);
1399 struct ivtv_stream *s = &itv->streams[i]; 1498 ivtv_get_audio_output(itv, 0, &audout);
1400 1499 IVTV_INFO("Video Output: %s\n", vidout.name);
1401 if (s->v4l2dev == NULL || s->buffers == 0) 1500 IVTV_INFO("Audio Output: %s (Stereo/Bilingual: %s/%s)\n", audout.name,
1402 continue; 1501 audio_modes[itv->audio_stereo_mode],
1403 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, 1502 audio_modes[itv->audio_bilingual_mode]);
1404 (s->buffers - s->q_free.buffers) * 100 / s->buffers, 1503 if (mode < 0 || mode > OUT_PASSTHROUGH)
1405 (s->buffers * s->buf_size) / 1024, s->buffers); 1504 mode = OUT_NONE;
1406 } 1505 IVTV_INFO("Output Mode: %s\n", output_modes[mode]);
1407 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted); 1506 ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
1408 IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num); 1507 data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
1409 break; 1508 IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n",
1509 data[0] & 1 ? "On" : "Off",
1510 alpha_mode[(data[0] >> 1) & 0x3],
1511 pixel_format[(data[0] >> 3) & 0xf]);
1410 } 1512 }
1513 IVTV_INFO("Tuner: %s\n",
1514 test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
1515 cx2341x_log_status(&itv->params, itv->name);
1516 IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
1517 for (i = 0; i < IVTV_MAX_STREAMS; i++) {
1518 struct ivtv_stream *s = &itv->streams[i];
1411 1519
1412 default: 1520 if (s->v4l2dev == NULL || s->buffers == 0)
1413 return -EINVAL; 1521 continue;
1522 IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
1523 (s->buffers - s->q_free.buffers) * 100 / s->buffers,
1524 (s->buffers * s->buf_size) / 1024, s->buffers);
1414 } 1525 }
1526
1527 IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted);
1528 IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
1529
1415 return 0; 1530 return 0;
1416} 1531}
1417 1532
@@ -1433,7 +1548,7 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
1433 return -EINVAL; 1548 return -EINVAL;
1434 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL) 1549 if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
1435 return 0; 1550 return 0;
1436 if (ivtv_claim_stream(id, id->type)) { 1551 if (ivtv_start_decoding(id, id->type)) {
1437 return -EBUSY; 1552 return -EBUSY;
1438 } 1553 }
1439 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) { 1554 if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
@@ -1607,121 +1722,30 @@ static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
1607 return 0; 1722 return 0;
1608} 1723}
1609 1724
1610static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, 1725static int ivtv_default(struct file *file, void *fh, int cmd, void *arg)
1611 unsigned int cmd, void *arg)
1612{ 1726{
1613 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data; 1727 struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
1614 struct ivtv *itv = id->itv;
1615 int ret;
1616
1617 /* check priority */
1618 switch (cmd) {
1619 case VIDIOC_S_CTRL:
1620 case VIDIOC_S_STD:
1621 case VIDIOC_S_INPUT:
1622 case VIDIOC_S_OUTPUT:
1623 case VIDIOC_S_TUNER:
1624 case VIDIOC_S_FREQUENCY:
1625 case VIDIOC_S_FMT:
1626 case VIDIOC_S_CROP:
1627 case VIDIOC_S_AUDIO:
1628 case VIDIOC_S_AUDOUT:
1629 case VIDIOC_S_EXT_CTRLS:
1630 case VIDIOC_S_FBUF:
1631 case VIDIOC_OVERLAY:
1632 ret = v4l2_prio_check(&itv->prio, &id->prio);
1633 if (ret)
1634 return ret;
1635 }
1636 1728
1637 switch (cmd) { 1729 switch (cmd) {
1638 case VIDIOC_DBG_G_REGISTER: 1730 case VIDIOC_INT_S_AUDIO_ROUTING: {
1639 case VIDIOC_DBG_S_REGISTER: 1731 struct v4l2_routing *route = arg;
1640 case VIDIOC_G_CHIP_IDENT:
1641 case VIDIOC_INT_S_AUDIO_ROUTING:
1642 case VIDIOC_INT_RESET:
1643 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1644 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1645 v4l_printk_ioctl(cmd);
1646 printk("\n");
1647 }
1648 return ivtv_debug_ioctls(filp, cmd, arg);
1649 1732
1650 case VIDIOC_G_PRIORITY: 1733 ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route);
1651 case VIDIOC_S_PRIORITY: 1734 break;
1652 case VIDIOC_QUERYCAP: 1735 }
1653 case VIDIOC_ENUMINPUT:
1654 case VIDIOC_G_INPUT:
1655 case VIDIOC_S_INPUT:
1656 case VIDIOC_ENUMOUTPUT:
1657 case VIDIOC_G_OUTPUT:
1658 case VIDIOC_S_OUTPUT:
1659 case VIDIOC_G_FMT:
1660 case VIDIOC_S_FMT:
1661 case VIDIOC_TRY_FMT:
1662 case VIDIOC_ENUM_FMT:
1663 case VIDIOC_CROPCAP:
1664 case VIDIOC_G_CROP:
1665 case VIDIOC_S_CROP:
1666 case VIDIOC_G_FREQUENCY:
1667 case VIDIOC_S_FREQUENCY:
1668 case VIDIOC_ENUMSTD:
1669 case VIDIOC_G_STD:
1670 case VIDIOC_S_STD:
1671 case VIDIOC_S_TUNER:
1672 case VIDIOC_G_TUNER:
1673 case VIDIOC_ENUMAUDIO:
1674 case VIDIOC_S_AUDIO:
1675 case VIDIOC_G_AUDIO:
1676 case VIDIOC_ENUMAUDOUT:
1677 case VIDIOC_S_AUDOUT:
1678 case VIDIOC_G_AUDOUT:
1679 case VIDIOC_G_SLICED_VBI_CAP:
1680 case VIDIOC_LOG_STATUS:
1681 case VIDIOC_G_ENC_INDEX:
1682 case VIDIOC_ENCODER_CMD:
1683 case VIDIOC_TRY_ENCODER_CMD:
1684 case VIDIOC_G_FBUF:
1685 case VIDIOC_S_FBUF:
1686 case VIDIOC_OVERLAY:
1687 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1688 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1689 v4l_printk_ioctl(cmd);
1690 printk("\n");
1691 }
1692 return ivtv_v4l2_ioctls(itv, filp, cmd, arg);
1693 1736
1694 case VIDIOC_QUERYMENU: 1737 case VIDIOC_INT_RESET: {
1695 case VIDIOC_QUERYCTRL: 1738 u32 val = *(u32 *)arg;
1696 case VIDIOC_S_CTRL:
1697 case VIDIOC_G_CTRL:
1698 case VIDIOC_S_EXT_CTRLS:
1699 case VIDIOC_G_EXT_CTRLS:
1700 case VIDIOC_TRY_EXT_CTRLS:
1701 if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
1702 printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
1703 v4l_printk_ioctl(cmd);
1704 printk("\n");
1705 }
1706 return ivtv_control_ioctls(itv, cmd, arg);
1707 1739
1708 case IVTV_IOC_DMA_FRAME: 1740 if ((val == 0 && itv->options.newi2c) || (val & 0x01))
1709 case VIDEO_GET_PTS: 1741 ivtv_reset_ir_gpio(itv);
1710 case VIDEO_GET_FRAME_COUNT: 1742 if (val & 0x02)
1711 case VIDEO_GET_EVENT: 1743 itv->video_dec_func(itv, cmd, NULL);
1712 case VIDEO_PLAY: 1744 break;
1713 case VIDEO_STOP: 1745 }
1714 case VIDEO_FREEZE:
1715 case VIDEO_CONTINUE:
1716 case VIDEO_COMMAND:
1717 case VIDEO_TRY_COMMAND:
1718 return ivtv_decoder_ioctls(filp, cmd, arg);
1719 1746
1720 case 0x00005401: /* Handle isatty() calls */
1721 return -EINVAL;
1722 default: 1747 default:
1723 return v4l_compat_translate_ioctl(inode, filp, cmd, arg, 1748 return -EINVAL;
1724 ivtv_v4l2_do_ioctl);
1725 } 1749 }
1726 return 0; 1750 return 0;
1727} 1751}
@@ -1729,7 +1753,11 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
1729static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp, 1753static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct file *filp,
1730 unsigned int cmd, unsigned long arg) 1754 unsigned int cmd, unsigned long arg)
1731{ 1755{
1732 /* Filter dvb ioctls that cannot be handled by video_usercopy */ 1756 struct video_device *vfd = video_devdata(filp);
1757 struct ivtv_open_id *id = (struct ivtv_open_id *)filp->private_data;
1758 int ret;
1759
1760 /* Filter dvb ioctls that cannot be handled by the v4l ioctl framework */
1733 switch (cmd) { 1761 switch (cmd) {
1734 case VIDEO_SELECT_SOURCE: 1762 case VIDEO_SELECT_SOURCE:
1735 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n"); 1763 IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
@@ -1758,10 +1786,47 @@ static int ivtv_serialized_ioctl(struct ivtv *itv, struct inode *inode, struct f
1758 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); 1786 ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
1759 return 0; 1787 return 0;
1760 1788
1789 case IVTV_IOC_DMA_FRAME:
1790 case VIDEO_GET_PTS:
1791 case VIDEO_GET_FRAME_COUNT:
1792 case VIDEO_GET_EVENT:
1793 case VIDEO_PLAY:
1794 case VIDEO_STOP:
1795 case VIDEO_FREEZE:
1796 case VIDEO_CONTINUE:
1797 case VIDEO_COMMAND:
1798 case VIDEO_TRY_COMMAND:
1799 return ivtv_decoder_ioctls(filp, cmd, (void *)arg);
1800
1761 default: 1801 default:
1762 break; 1802 break;
1763 } 1803 }
1764 return video_usercopy(inode, filp, cmd, arg, ivtv_v4l2_do_ioctl); 1804
1805 /* check priority */
1806 switch (cmd) {
1807 case VIDIOC_S_CTRL:
1808 case VIDIOC_S_STD:
1809 case VIDIOC_S_INPUT:
1810 case VIDIOC_S_OUTPUT:
1811 case VIDIOC_S_TUNER:
1812 case VIDIOC_S_FREQUENCY:
1813 case VIDIOC_S_FMT:
1814 case VIDIOC_S_CROP:
1815 case VIDIOC_S_AUDIO:
1816 case VIDIOC_S_AUDOUT:
1817 case VIDIOC_S_EXT_CTRLS:
1818 case VIDIOC_S_FBUF:
1819 case VIDIOC_OVERLAY:
1820 ret = v4l2_prio_check(&itv->prio, &id->prio);
1821 if (ret)
1822 return ret;
1823 }
1824
1825 if (ivtv_debug & IVTV_DBGFLG_IOCTL)
1826 vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
1827 ret = video_ioctl2(inode, filp, cmd, arg);
1828 vfd->debug = 0;
1829 return ret;
1765} 1830}
1766 1831
1767int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 1832int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
@@ -1776,3 +1841,70 @@ int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
1776 mutex_unlock(&itv->serialize_lock); 1841 mutex_unlock(&itv->serialize_lock);
1777 return res; 1842 return res;
1778} 1843}
1844
1845void ivtv_set_funcs(struct video_device *vdev)
1846{
1847 vdev->vidioc_querycap = ivtv_querycap;
1848 vdev->vidioc_g_priority = ivtv_g_priority;
1849 vdev->vidioc_s_priority = ivtv_s_priority;
1850 vdev->vidioc_s_audio = ivtv_s_audio;
1851 vdev->vidioc_g_audio = ivtv_g_audio;
1852 vdev->vidioc_enumaudio = ivtv_enumaudio;
1853 vdev->vidioc_s_audout = ivtv_s_audout;
1854 vdev->vidioc_g_audout = ivtv_g_audout;
1855 vdev->vidioc_enum_input = ivtv_enum_input;
1856 vdev->vidioc_enum_output = ivtv_enum_output;
1857 vdev->vidioc_enumaudout = ivtv_enumaudout;
1858 vdev->vidioc_cropcap = ivtv_cropcap;
1859 vdev->vidioc_s_crop = ivtv_s_crop;
1860 vdev->vidioc_g_crop = ivtv_g_crop;
1861 vdev->vidioc_g_input = ivtv_g_input;
1862 vdev->vidioc_s_input = ivtv_s_input;
1863 vdev->vidioc_g_output = ivtv_g_output;
1864 vdev->vidioc_s_output = ivtv_s_output;
1865 vdev->vidioc_g_frequency = ivtv_g_frequency;
1866 vdev->vidioc_s_frequency = ivtv_s_frequency;
1867 vdev->vidioc_s_tuner = ivtv_s_tuner;
1868 vdev->vidioc_g_tuner = ivtv_g_tuner;
1869 vdev->vidioc_g_enc_index = ivtv_g_enc_index;
1870 vdev->vidioc_g_fbuf = ivtv_g_fbuf;
1871 vdev->vidioc_s_fbuf = ivtv_s_fbuf;
1872 vdev->vidioc_g_std = ivtv_g_std;
1873 vdev->vidioc_s_std = ivtv_s_std;
1874 vdev->vidioc_overlay = ivtv_overlay;
1875 vdev->vidioc_log_status = ivtv_log_status;
1876 vdev->vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap;
1877 vdev->vidioc_encoder_cmd = ivtv_encoder_cmd;
1878 vdev->vidioc_try_encoder_cmd = ivtv_try_encoder_cmd;
1879 vdev->vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out;
1880 vdev->vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap;
1881 vdev->vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap;
1882 vdev->vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap;
1883 vdev->vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out;
1884 vdev->vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay;
1885 vdev->vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out;
1886 vdev->vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap;
1887 vdev->vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap;
1888 vdev->vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap;
1889 vdev->vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out;
1890 vdev->vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay;
1891 vdev->vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out;
1892 vdev->vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap;
1893 vdev->vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap;
1894 vdev->vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap;
1895 vdev->vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out;
1896 vdev->vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay;
1897 vdev->vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out;
1898 vdev->vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap;
1899 vdev->vidioc_g_chip_ident = ivtv_g_chip_ident;
1900#ifdef CONFIG_VIDEO_ADV_DEBUG
1901 vdev->vidioc_g_register = ivtv_g_register;
1902 vdev->vidioc_s_register = ivtv_s_register;
1903#endif
1904 vdev->vidioc_default = ivtv_default;
1905 vdev->vidioc_queryctrl = ivtv_queryctrl;
1906 vdev->vidioc_querymenu = ivtv_querymenu;
1907 vdev->vidioc_g_ext_ctrls = ivtv_g_ext_ctrls;
1908 vdev->vidioc_s_ext_ctrls = ivtv_s_ext_ctrls;
1909 vdev->vidioc_try_ext_ctrls = ivtv_try_ext_ctrls;
1910}
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h
index 4e67f0ed1fc0..70188588b4f4 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.h
+++ b/drivers/media/video/ivtv/ivtv-ioctl.h
@@ -24,10 +24,13 @@
24u16 ivtv_service2vbi(int type); 24u16 ivtv_service2vbi(int type);
25void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal); 25void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
26u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt); 26u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt);
27int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
28 unsigned long arg);
29int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg);
30void ivtv_set_osd_alpha(struct ivtv *itv); 27void ivtv_set_osd_alpha(struct ivtv *itv);
31int ivtv_set_speed(struct ivtv *itv, int speed); 28int ivtv_set_speed(struct ivtv *itv, int speed);
29void ivtv_set_funcs(struct video_device *vdev);
30int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std);
31int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
32int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
33int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
34 unsigned long arg);
32 35
33#endif 36#endif
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index c854285a4371..f8883b487f4a 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -220,7 +220,8 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
220 s->v4l2dev->dev = &itv->dev->dev; 220 s->v4l2dev->dev = &itv->dev->dev;
221 s->v4l2dev->fops = ivtv_stream_info[type].fops; 221 s->v4l2dev->fops = ivtv_stream_info[type].fops;
222 s->v4l2dev->release = video_device_release; 222 s->v4l2dev->release = video_device_release;
223 223 s->v4l2dev->tvnorms = V4L2_STD_ALL;
224 ivtv_set_funcs(s->v4l2dev);
224 return 0; 225 return 0;
225} 226}
226 227
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
index 73be154f7f05..bdfda48e56bf 100644
--- a/drivers/media/video/ivtv/ivtvfb.c
+++ b/drivers/media/video/ivtv/ivtvfb.c
@@ -367,6 +367,88 @@ static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
367 return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count); 367 return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
368} 368}
369 369
370static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
371 size_t count, loff_t *ppos)
372{
373 unsigned long p = *ppos;
374 void *dst;
375 int err = 0;
376 unsigned long total_size;
377 struct ivtv *itv = (struct ivtv *) info->par;
378 unsigned long dma_offset =
379 IVTV_DECODER_OFFSET + itv->osd_info->video_rbase;
380 unsigned long dma_size;
381 u16 lead = 0, tail = 0;
382
383 if (info->state != FBINFO_STATE_RUNNING)
384 return -EPERM;
385
386 total_size = info->screen_size;
387
388 if (total_size == 0)
389 total_size = info->fix.smem_len;
390
391 if (p > total_size)
392 return -EFBIG;
393
394 if (count > total_size) {
395 err = -EFBIG;
396 count = total_size;
397 }
398
399 if (count + p > total_size) {
400 if (!err)
401 err = -ENOSPC;
402
403 count = total_size - p;
404 }
405
406 dst = (void __force *) (info->screen_base + p);
407
408 if (info->fbops->fb_sync)
409 info->fbops->fb_sync(info);
410
411 if (!access_ok(VERIFY_READ, buf, count)) {
412 IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
413 (unsigned long)buf);
414 err = -EFAULT;
415 }
416
417 if (!err) {
418 /* If transfer size > threshold and both src/dst
419 addresses are aligned, use DMA */
420 if (count >= 4096 &&
421 ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
422 /* Odd address = can't DMA. Align */
423 if ((unsigned long)dst & 3) {
424 lead = 4 - ((unsigned long)dst & 3);
425 memcpy(dst, buf, lead);
426 buf += lead;
427 dst += lead;
428 }
429 /* DMA resolution is 32 bits */
430 if ((count - lead) & 3)
431 tail = (count - lead) & 3;
432 /* DMA the data */
433 dma_size = count - lead - tail;
434 err = ivtvfb_prep_dec_dma_to_device(itv,
435 p + lead + dma_offset, (void *)buf, dma_size);
436 dst += dma_size;
437 buf += dma_size;
438 /* Copy any leftover data */
439 if (tail)
440 memcpy(dst, buf, tail);
441 } else {
442 memcpy(dst, buf, count);
443 }
444 }
445
446 if (!err)
447 *ppos += count;
448
449 return (err) ? err : count;
450}
451
370static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) 452static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
371{ 453{
372 DEFINE_WAIT(wait); 454 DEFINE_WAIT(wait);
@@ -708,6 +790,9 @@ static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
708 else 790 else
709 var->pixclock = pixclock; 791 var->pixclock = pixclock;
710 792
793 itv->osd_rect.width = var->xres;
794 itv->osd_rect.height = var->yres;
795
711 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", 796 IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
712 var->xres, var->yres, 797 var->xres, var->yres,
713 var->xres_virtual, var->yres_virtual, 798 var->xres_virtual, var->yres_virtual,
@@ -824,6 +909,7 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info)
824 909
825static struct fb_ops ivtvfb_ops = { 910static struct fb_ops ivtvfb_ops = {
826 .owner = THIS_MODULE, 911 .owner = THIS_MODULE,
912 .fb_write = ivtvfb_write,
827 .fb_check_var = ivtvfb_check_var, 913 .fb_check_var = ivtvfb_check_var,
828 .fb_set_par = ivtvfb_set_par, 914 .fb_set_par = ivtvfb_set_par,
829 .fb_setcolreg = ivtvfb_setcolreg, 915 .fb_setcolreg = ivtvfb_setcolreg,
diff --git a/drivers/media/video/m52790.c b/drivers/media/video/m52790.c
index 8e0160d275ca..39bf6b114d50 100644
--- a/drivers/media/video/m52790.c
+++ b/drivers/media/video/m52790.c
@@ -171,4 +171,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
171 .remove = m52790_remove, 171 .remove = m52790_remove,
172 .id_table = m52790_id, 172 .id_table = m52790_id,
173}; 173};
174
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index e7ccbc895d7a..2fb5854cf6f0 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -1253,7 +1253,7 @@ static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
1253 return 0; 1253 return 0;
1254} 1254}
1255 1255
1256static int vidioc_enum_fmt_cap(struct file *file, void *fh, 1256static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
1257 struct v4l2_fmtdesc *f) 1257 struct v4l2_fmtdesc *f)
1258{ 1258{
1259 if (f->index > 1) 1259 if (f->index > 1)
@@ -1283,7 +1283,7 @@ static int vidioc_enum_fmt_cap(struct file *file, void *fh,
1283 return 0; 1283 return 0;
1284} 1284}
1285 1285
1286static int vidioc_try_fmt_cap(struct file *file, void *fh, 1286static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
1287 struct v4l2_format *f) 1287 struct v4l2_format *f)
1288{ 1288{
1289 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1289 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
@@ -1316,7 +1316,8 @@ static int vidioc_try_fmt_cap(struct file *file, void *fh,
1316 return 0; 1316 return 0;
1317} 1317}
1318 1318
1319static int vidioc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) 1319static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
1320 struct v4l2_format *f)
1320{ 1321{
1321 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1322 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1322 return -EINVAL; 1323 return -EINVAL;
@@ -1346,7 +1347,8 @@ static int vidioc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
1346 return 0; 1347 return 0;
1347} 1348}
1348 1349
1349static int vidioc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f) 1350static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
1351 struct v4l2_format *f)
1350{ 1352{
1351 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1353 if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1352 return -EINVAL; 1354 return -EINVAL;
@@ -1709,10 +1711,10 @@ static struct video_device meye_template = {
1709 .vidioc_queryctrl = vidioc_queryctrl, 1711 .vidioc_queryctrl = vidioc_queryctrl,
1710 .vidioc_s_ctrl = vidioc_s_ctrl, 1712 .vidioc_s_ctrl = vidioc_s_ctrl,
1711 .vidioc_g_ctrl = vidioc_g_ctrl, 1713 .vidioc_g_ctrl = vidioc_g_ctrl,
1712 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, 1714 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1713 .vidioc_try_fmt_cap = vidioc_try_fmt_cap, 1715 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1714 .vidioc_g_fmt_cap = vidioc_g_fmt_cap, 1716 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1715 .vidioc_s_fmt_cap = vidioc_s_fmt_cap, 1717 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1716 .vidioc_reqbufs = vidioc_reqbufs, 1718 .vidioc_reqbufs = vidioc_reqbufs,
1717 .vidioc_querybuf = vidioc_querybuf, 1719 .vidioc_querybuf = vidioc_querybuf,
1718 .vidioc_qbuf = vidioc_qbuf, 1720 .vidioc_qbuf = vidioc_qbuf,
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index 310dbaba55ff..5691e019d195 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -110,6 +110,7 @@ MODULE_PARM_DESC(dolby, "Activates Dolby processsing");
110 110
111/* Addresses to scan */ 111/* Addresses to scan */
112static unsigned short normal_i2c[] = { 0x80 >> 1, 0x88 >> 1, I2C_CLIENT_END }; 112static unsigned short normal_i2c[] = { 0x80 >> 1, 0x88 >> 1, I2C_CLIENT_END };
113
113I2C_CLIENT_INSMOD; 114I2C_CLIENT_INSMOD;
114 115
115/* ----------------------------------------------------------------------- */ 116/* ----------------------------------------------------------------------- */
@@ -333,7 +334,6 @@ void msp_set_audio(struct i2c_client *client)
333 334
334/* ------------------------------------------------------------------------ */ 335/* ------------------------------------------------------------------------ */
335 336
336
337static void msp_wake_thread(struct i2c_client *client) 337static void msp_wake_thread(struct i2c_client *client)
338{ 338{
339 struct msp_state *state = i2c_get_clientdata(client); 339 struct msp_state *state = i2c_get_clientdata(client);
@@ -1004,7 +1004,6 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1004 .id_table = msp_id, 1004 .id_table = msp_id,
1005}; 1005};
1006 1006
1007
1008/* 1007/*
1009 * Overrides for Emacs so that we follow Linus's tabbing style. 1008 * Overrides for Emacs so that we follow Linus's tabbing style.
1010 * --------------------------------------------------------------------------- 1009 * ---------------------------------------------------------------------------
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index 7f5568592793..1622f70e4dd0 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -480,7 +480,6 @@ int msp3400c_thread(void *data)
480 struct msp3400c_carrier_detect *cd; 480 struct msp3400c_carrier_detect *cd;
481 int count, max1, max2, val1, val2, val, i; 481 int count, max1, max2, val1, val2, val, i;
482 482
483
484 v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n"); 483 v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
485 set_freezable(); 484 set_freezable();
486 for (;;) { 485 for (;;) {
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 1658fe590392..b31ba4e09327 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -815,7 +815,6 @@ static int mt9v022_remove(struct i2c_client *client)
815 815
816 return 0; 816 return 0;
817} 817}
818
819static const struct i2c_device_id mt9v022_id[] = { 818static const struct i2c_device_id mt9v022_id[] = {
820 { "mt9v022", 0 }, 819 { "mt9v022", 0 },
821 { } 820 { }
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index d7bfd30f74a9..ea032f5f2f41 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -682,17 +682,17 @@ static int ov7670_try_fmt(struct i2c_client *c, struct v4l2_format *fmt,
682 for (index = 0; index < N_OV7670_FMTS; index++) 682 for (index = 0; index < N_OV7670_FMTS; index++)
683 if (ov7670_formats[index].pixelformat == pix->pixelformat) 683 if (ov7670_formats[index].pixelformat == pix->pixelformat)
684 break; 684 break;
685 if (index >= N_OV7670_FMTS) 685 if (index >= N_OV7670_FMTS) {
686 return -EINVAL; 686 /* default to first format */
687 index = 0;
688 pix->pixelformat = ov7670_formats[0].pixelformat;
689 }
687 if (ret_fmt != NULL) 690 if (ret_fmt != NULL)
688 *ret_fmt = ov7670_formats + index; 691 *ret_fmt = ov7670_formats + index;
689 /* 692 /*
690 * Fields: the OV devices claim to be progressive. 693 * Fields: the OV devices claim to be progressive.
691 */ 694 */
692 if (pix->field == V4L2_FIELD_ANY) 695 pix->field = V4L2_FIELD_NONE;
693 pix->field = V4L2_FIELD_NONE;
694 else if (pix->field != V4L2_FIELD_NONE)
695 return -EINVAL;
696 /* 696 /*
697 * Round requested image size down to the nearest 697 * Round requested image size down to the nearest
698 * we support, but not below the smallest. 698 * we support, but not below the smallest.
@@ -833,7 +833,7 @@ static int ov7670_store_cmatrix(struct i2c_client *client,
833 int matrix[CMATRIX_LEN]) 833 int matrix[CMATRIX_LEN])
834{ 834{
835 int i, ret; 835 int i, ret;
836 unsigned char signbits; 836 unsigned char signbits = 0;
837 837
838 /* 838 /*
839 * Weird crap seems to exist in the upper part of 839 * Weird crap seems to exist in the upper part of
@@ -1009,7 +1009,7 @@ static unsigned char ov7670_abs_to_sm(unsigned char v)
1009 1009
1010static int ov7670_t_brightness(struct i2c_client *client, int value) 1010static int ov7670_t_brightness(struct i2c_client *client, int value)
1011{ 1011{
1012 unsigned char com8, v; 1012 unsigned char com8 = 0, v;
1013 int ret; 1013 int ret;
1014 1014
1015 ov7670_read(client, REG_COM8, &com8); 1015 ov7670_read(client, REG_COM8, &com8);
@@ -1022,7 +1022,7 @@ static int ov7670_t_brightness(struct i2c_client *client, int value)
1022 1022
1023static int ov7670_q_brightness(struct i2c_client *client, __s32 *value) 1023static int ov7670_q_brightness(struct i2c_client *client, __s32 *value)
1024{ 1024{
1025 unsigned char v; 1025 unsigned char v = 0;
1026 int ret = ov7670_read(client, REG_BRIGHT, &v); 1026 int ret = ov7670_read(client, REG_BRIGHT, &v);
1027 1027
1028 *value = ov7670_sm_to_abs(v); 1028 *value = ov7670_sm_to_abs(v);
@@ -1036,7 +1036,7 @@ static int ov7670_t_contrast(struct i2c_client *client, int value)
1036 1036
1037static int ov7670_q_contrast(struct i2c_client *client, __s32 *value) 1037static int ov7670_q_contrast(struct i2c_client *client, __s32 *value)
1038{ 1038{
1039 unsigned char v; 1039 unsigned char v = 0;
1040 int ret = ov7670_read(client, REG_CONTRAS, &v); 1040 int ret = ov7670_read(client, REG_CONTRAS, &v);
1041 1041
1042 *value = v; 1042 *value = v;
@@ -1046,7 +1046,7 @@ static int ov7670_q_contrast(struct i2c_client *client, __s32 *value)
1046static int ov7670_q_hflip(struct i2c_client *client, __s32 *value) 1046static int ov7670_q_hflip(struct i2c_client *client, __s32 *value)
1047{ 1047{
1048 int ret; 1048 int ret;
1049 unsigned char v; 1049 unsigned char v = 0;
1050 1050
1051 ret = ov7670_read(client, REG_MVFP, &v); 1051 ret = ov7670_read(client, REG_MVFP, &v);
1052 *value = (v & MVFP_MIRROR) == MVFP_MIRROR; 1052 *value = (v & MVFP_MIRROR) == MVFP_MIRROR;
@@ -1056,7 +1056,7 @@ static int ov7670_q_hflip(struct i2c_client *client, __s32 *value)
1056 1056
1057static int ov7670_t_hflip(struct i2c_client *client, int value) 1057static int ov7670_t_hflip(struct i2c_client *client, int value)
1058{ 1058{
1059 unsigned char v; 1059 unsigned char v = 0;
1060 int ret; 1060 int ret;
1061 1061
1062 ret = ov7670_read(client, REG_MVFP, &v); 1062 ret = ov7670_read(client, REG_MVFP, &v);
@@ -1074,7 +1074,7 @@ static int ov7670_t_hflip(struct i2c_client *client, int value)
1074static int ov7670_q_vflip(struct i2c_client *client, __s32 *value) 1074static int ov7670_q_vflip(struct i2c_client *client, __s32 *value)
1075{ 1075{
1076 int ret; 1076 int ret;
1077 unsigned char v; 1077 unsigned char v = 0;
1078 1078
1079 ret = ov7670_read(client, REG_MVFP, &v); 1079 ret = ov7670_read(client, REG_MVFP, &v);
1080 *value = (v & MVFP_FLIP) == MVFP_FLIP; 1080 *value = (v & MVFP_FLIP) == MVFP_FLIP;
@@ -1084,7 +1084,7 @@ static int ov7670_q_vflip(struct i2c_client *client, __s32 *value)
1084 1084
1085static int ov7670_t_vflip(struct i2c_client *client, int value) 1085static int ov7670_t_vflip(struct i2c_client *client, int value)
1086{ 1086{
1087 unsigned char v; 1087 unsigned char v = 0;
1088 int ret; 1088 int ret;
1089 1089
1090 ret = ov7670_read(client, REG_MVFP, &v); 1090 ret = ov7670_read(client, REG_MVFP, &v);
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index 8063e33f1c85..065c2454113e 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -297,7 +297,6 @@ static int ovcamchip_attach(struct i2c_adapter *adap)
297 switch (adap->id) { 297 switch (adap->id) {
298 case I2C_HW_SMBUS_OV511: 298 case I2C_HW_SMBUS_OV511:
299 case I2C_HW_SMBUS_OV518: 299 case I2C_HW_SMBUS_OV518:
300 case I2C_HW_SMBUS_OVFX2:
301 case I2C_HW_SMBUS_W9968CF: 300 case I2C_HW_SMBUS_W9968CF:
302 PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id); 301 PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id);
303 break; 302 break;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c
index 8d859ccd48ec..cdedaa55f152 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-audio.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h
index 536339b68843..ac54eed3721b 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-audio.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-audio.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
index 73dcb1c57ae6..7c19ff72e6b3 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-context.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-context.c
@@ -1,5 +1,4 @@
1/* 1/*
2 * $Id$
3 * 2 *
4 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 3 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
5 * 4 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h
index 745e270233c2..61801291c2af 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-context.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-context.h
@@ -1,5 +1,4 @@
1/* 1/*
2 * $Id$
3 * 2 *
4 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 3 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
5 * 4 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
index 91a42f2473a7..0764fbfffb73 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
index c1680053cd64..0371ae6e6e4e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
index 29d50597c88a..895859ec495a 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
index 54b2844e7a71..66abf77f51fd 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h
index 707d2d9635d7..be79249f8628 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-debug.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-debug.h
@@ -1,5 +1,4 @@
1/* 1/*
2 * $Id$
3 * 2 *
4 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 3 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
5 * 4 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
index b53121c78ff9..ca892fb78a5b 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
index 990b02d35d36..e24ff59f8605 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index 5bf6d8fda1f9..5d036e7e3f07 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2007 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2007 Mike Isely <isely@pobox.com>
6 * 5 *
@@ -182,7 +181,7 @@ static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
182 return 0; 181 return 0;
183} 182}
184 183
185struct pvr2_dvb_props pvr2_onair_creator_fe_props = { 184static struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
186 .frontend_attach = pvr2_lgdt3303_attach, 185 .frontend_attach = pvr2_lgdt3303_attach,
187 .tuner_attach = pvr2_lgh06xf_attach, 186 .tuner_attach = pvr2_lgh06xf_attach,
188}; 187};
@@ -242,7 +241,7 @@ static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
242 return 0; 241 return 0;
243} 242}
244 243
245struct pvr2_dvb_props pvr2_onair_usb2_fe_props = { 244static struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
246 .frontend_attach = pvr2_lgdt3302_attach, 245 .frontend_attach = pvr2_lgdt3302_attach,
247 .tuner_attach = pvr2_fcv1236d_attach, 246 .tuner_attach = pvr2_fcv1236d_attach,
248}; 247};
@@ -315,7 +314,7 @@ static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
315 return 0; 314 return 0;
316} 315}
317 316
318struct pvr2_dvb_props pvr2_73xxx_dvb_props = { 317static struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
319 .frontend_attach = pvr2_tda10048_attach, 318 .frontend_attach = pvr2_tda10048_attach,
320 .tuner_attach = pvr2_73xxx_tda18271_8295_attach, 319 .tuner_attach = pvr2_73xxx_tda18271_8295_attach,
321}; 320};
@@ -418,12 +417,12 @@ static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
418 return 0; 417 return 0;
419} 418}
420 419
421struct pvr2_dvb_props pvr2_750xx_dvb_props = { 420static struct pvr2_dvb_props pvr2_750xx_dvb_props = {
422 .frontend_attach = pvr2_s5h1409_attach, 421 .frontend_attach = pvr2_s5h1409_attach,
423 .tuner_attach = pvr2_tda18271_8295_attach, 422 .tuner_attach = pvr2_tda18271_8295_attach,
424}; 423};
425 424
426struct pvr2_dvb_props pvr2_751xx_dvb_props = { 425static struct pvr2_dvb_props pvr2_751xx_dvb_props = {
427 .frontend_attach = pvr2_s5h1411_attach, 426 .frontend_attach = pvr2_s5h1411_attach,
428 .tuner_attach = pvr2_tda18271_8295_attach, 427 .tuner_attach = pvr2_tda18271_8295_attach,
429}; 428};
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
index d016f8b6c70b..e23ce1d2edd7 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
index 5ef005947b04..299afa4fa969 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.h b/drivers/media/video/pvrusb2/pvrusb2-eeprom.h
index 84242975dea7..cca3216f94cc 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-eeprom.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-eeprom.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
index c46d367f7472..a1252d673b41 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.h b/drivers/media/video/pvrusb2/pvrusb2-encoder.h
index 54caf2e3c428..232fefbcd1ac 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
index abaada31e66e..b58369e7f30b 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2007 Michael Krufky <mkrufky@linuxtv.org> 4 * Copyright (C) 2007 Michael Krufky <mkrufky@linuxtv.org>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index a3fe251d6fd9..657f861593b3 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 0a868888f389..a5217a2cf4c0 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
@@ -40,6 +39,23 @@
40#define TV_MIN_FREQ 55250000L 39#define TV_MIN_FREQ 55250000L
41#define TV_MAX_FREQ 850000000L 40#define TV_MAX_FREQ 850000000L
42 41
42/* This defines a minimum interval that the decoder must remain quiet
43 before we are allowed to start it running. */
44#define TIME_MSEC_DECODER_WAIT 50
45
46/* This defines a minimum interval that the encoder must remain quiet
47 before we are allowed to configure it. I had this originally set to
48 50msec, but Martin Dauskardt <martin.dauskardt@gmx.de> reports that
49 things work better when it's set to 100msec. */
50#define TIME_MSEC_ENCODER_WAIT 100
51
52/* This defines the minimum interval that the encoder must successfully run
53 before we consider that the encoder has run at least once since its
54 firmware has been loaded. This measurement is in important for cases
55 where we can't do something until we know that the encoder has been run
56 at least once. */
57#define TIME_MSEC_ENCODER_OK 250
58
43static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; 59static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
44static DEFINE_MUTEX(pvr2_unit_mtx); 60static DEFINE_MUTEX(pvr2_unit_mtx);
45 61
@@ -67,6 +83,16 @@ MODULE_PARM_DESC(video_std,"specify initial video standard");
67module_param_array(tolerance, int, NULL, 0444); 83module_param_array(tolerance, int, NULL, 0444);
68MODULE_PARM_DESC(tolerance,"specify stream error tolerance"); 84MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
69 85
86/* US Broadcast channel 7 (175.25 MHz) */
87static int default_tv_freq = 175250000L;
88/* 104.3 MHz, a usable FM station for my area */
89static int default_radio_freq = 104300000L;
90
91module_param_named(tv_freq, default_tv_freq, int, 0444);
92MODULE_PARM_DESC(tv_freq, "specify initial television frequency");
93module_param_named(radio_freq, default_radio_freq, int, 0444);
94MODULE_PARM_DESC(radio_freq, "specify initial radio frequency");
95
70#define PVR2_CTL_WRITE_ENDPOINT 0x01 96#define PVR2_CTL_WRITE_ENDPOINT 0x01
71#define PVR2_CTL_READ_ENDPOINT 0x81 97#define PVR2_CTL_READ_ENDPOINT 0x81
72 98
@@ -1701,10 +1727,8 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
1701 are, but I set them to something usable in the Chicago area just 1727 are, but I set them to something usable in the Chicago area just
1702 to make driver testing a little easier. */ 1728 to make driver testing a little easier. */
1703 1729
1704 /* US Broadcast channel 7 (175.25 MHz) */ 1730 hdw->freqValTelevision = default_tv_freq;
1705 hdw->freqValTelevision = 175250000L; 1731 hdw->freqValRadio = default_radio_freq;
1706 /* 104.3 MHz, a usable FM station for my area */
1707 hdw->freqValRadio = 104300000L;
1708 1732
1709 // Do not use pvr2_reset_ctl_endpoints() here. It is not 1733 // Do not use pvr2_reset_ctl_endpoints() here. It is not
1710 // thread-safe against the normal pvr2_send_request() mechanism. 1734 // thread-safe against the normal pvr2_send_request() mechanism.
@@ -1989,7 +2013,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
1989 case V4L2_CTRL_TYPE_MENU: 2013 case V4L2_CTRL_TYPE_MENU:
1990 ciptr->type = pvr2_ctl_enum; 2014 ciptr->type = pvr2_ctl_enum;
1991 ciptr->def.type_enum.value_names = 2015 ciptr->def.type_enum.value_names =
1992 cx2341x_ctrl_get_menu(ciptr->v4l_id); 2016 cx2341x_ctrl_get_menu(&hdw->enc_ctl_state,
2017 ciptr->v4l_id);
1993 for (cnt1 = 0; 2018 for (cnt1 = 0;
1994 ciptr->def.type_enum.value_names[cnt1] != NULL; 2019 ciptr->def.type_enum.value_names[cnt1] != NULL;
1995 cnt1++) { } 2020 cnt1++) { }
@@ -2428,22 +2453,38 @@ static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
2428 struct pvr2_ctrl *cptr; 2453 struct pvr2_ctrl *cptr;
2429 int disruptive_change; 2454 int disruptive_change;
2430 2455
2431 /* When video standard changes, reset the hres and vres values - 2456 /* Handle some required side effects when the video standard is
2432 but if the user has pending changes there, then let the changes 2457 changed.... */
2433 take priority. */
2434 if (hdw->std_dirty) { 2458 if (hdw->std_dirty) {
2435 /* Rewrite the vertical resolution to be appropriate to the
2436 video standard that has been selected. */
2437 int nvres; 2459 int nvres;
2460 int gop_size;
2438 if (hdw->std_mask_cur & V4L2_STD_525_60) { 2461 if (hdw->std_mask_cur & V4L2_STD_525_60) {
2439 nvres = 480; 2462 nvres = 480;
2463 gop_size = 15;
2440 } else { 2464 } else {
2441 nvres = 576; 2465 nvres = 576;
2466 gop_size = 12;
2442 } 2467 }
2468 /* Rewrite the vertical resolution to be appropriate to the
2469 video standard that has been selected. */
2443 if (nvres != hdw->res_ver_val) { 2470 if (nvres != hdw->res_ver_val) {
2444 hdw->res_ver_val = nvres; 2471 hdw->res_ver_val = nvres;
2445 hdw->res_ver_dirty = !0; 2472 hdw->res_ver_dirty = !0;
2446 } 2473 }
2474 /* Rewrite the GOP size to be appropriate to the video
2475 standard that has been selected. */
2476 if (gop_size != hdw->enc_ctl_state.video_gop_size) {
2477 struct v4l2_ext_controls cs;
2478 struct v4l2_ext_control c1;
2479 memset(&cs, 0, sizeof(cs));
2480 memset(&c1, 0, sizeof(c1));
2481 cs.controls = &c1;
2482 cs.count = 1;
2483 c1.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
2484 c1.value = gop_size;
2485 cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,
2486 VIDIOC_S_EXT_CTRLS);
2487 }
2447 } 2488 }
2448 2489
2449 if (hdw->input_dirty && hdw->state_pathway_ok && 2490 if (hdw->input_dirty && hdw->state_pathway_ok &&
@@ -3421,7 +3462,7 @@ static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl)
3421} 3462}
3422 3463
3423 3464
3424void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff) 3465static void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff)
3425{ 3466{
3426 /* change some GPIO data 3467 /* change some GPIO data
3427 * 3468 *
@@ -3601,7 +3642,9 @@ static int state_eval_encoder_config(struct pvr2_hdw *hdw)
3601 the encoder. */ 3642 the encoder. */
3602 if (!hdw->state_encoder_waitok) { 3643 if (!hdw->state_encoder_waitok) {
3603 hdw->encoder_wait_timer.expires = 3644 hdw->encoder_wait_timer.expires =
3604 jiffies + (HZ*50/1000); 3645 jiffies +
3646 (HZ * TIME_MSEC_ENCODER_WAIT
3647 / 1000);
3605 add_timer(&hdw->encoder_wait_timer); 3648 add_timer(&hdw->encoder_wait_timer);
3606 } 3649 }
3607 } 3650 }
@@ -3725,7 +3768,7 @@ static int state_eval_encoder_run(struct pvr2_hdw *hdw)
3725 hdw->state_encoder_run = !0; 3768 hdw->state_encoder_run = !0;
3726 if (!hdw->state_encoder_runok) { 3769 if (!hdw->state_encoder_runok) {
3727 hdw->encoder_run_timer.expires = 3770 hdw->encoder_run_timer.expires =
3728 jiffies + (HZ*250/1000); 3771 jiffies + (HZ * TIME_MSEC_ENCODER_OK / 1000);
3729 add_timer(&hdw->encoder_run_timer); 3772 add_timer(&hdw->encoder_run_timer);
3730 } 3773 }
3731 } 3774 }
@@ -3800,7 +3843,9 @@ static int state_eval_decoder_run(struct pvr2_hdw *hdw)
3800 but before we did the pending check. */ 3843 but before we did the pending check. */
3801 if (!hdw->state_decoder_quiescent) { 3844 if (!hdw->state_decoder_quiescent) {
3802 hdw->quiescent_timer.expires = 3845 hdw->quiescent_timer.expires =
3803 jiffies + (HZ*50/1000); 3846 jiffies +
3847 (HZ * TIME_MSEC_DECODER_WAIT
3848 / 1000);
3804 add_timer(&hdw->quiescent_timer); 3849 add_timer(&hdw->quiescent_timer);
3805 } 3850 }
3806 } 3851 }
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index 20295e0c1995..c04956d304a7 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
index 49773764383b..ccdb429fc7af 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
index c650e02ccd00..55f04a0b2047 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
index c838df6167f9..7fa38683b3b1 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index 793c89a8d672..9d3c18b24744 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
index bd0807b905bb..6ef7a1c0e935 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
index 7aff8b720064..20b6ae0bb40d 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h
index 42fcf8281a87..afb7e87c0394 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
index c572212c9f15..05a1376405e7 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.h b/drivers/media/video/pvrusb2/pvrusb2-ioread.h
index 1d362f833588..100e0780e1aa 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ioread.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
index 332aced8a5a1..ad0d98c2ebb4 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-main.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c
index fdc5a2b49ca8..ca9f83a85ca5 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-std.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-std.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.h b/drivers/media/video/pvrusb2/pvrusb2-std.h
index 07c399375341..a35c53d0b320 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-std.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-std.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 0ff7a836a8a2..46a8c39ba030 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
@@ -71,6 +70,7 @@ struct pvr2_sysfs_ctl_item {
71 struct device_attribute attr_val; 70 struct device_attribute attr_val;
72 struct device_attribute attr_custom; 71 struct device_attribute attr_custom;
73 struct pvr2_ctrl *cptr; 72 struct pvr2_ctrl *cptr;
73 int ctl_id;
74 struct pvr2_sysfs *chptr; 74 struct pvr2_sysfs *chptr;
75 struct pvr2_sysfs_ctl_item *item_next; 75 struct pvr2_sysfs_ctl_item *item_next;
76 struct attribute *attr_gen[7]; 76 struct attribute *attr_gen[7];
@@ -83,38 +83,29 @@ struct pvr2_sysfs_class {
83 struct class class; 83 struct class class;
84}; 84};
85 85
86static ssize_t show_name(int id,struct device *class_dev,char *buf) 86static ssize_t show_name(struct device *class_dev,
87 struct device_attribute *attr,
88 char *buf)
87{ 89{
88 struct pvr2_ctrl *cptr; 90 struct pvr2_sysfs_ctl_item *cip;
89 struct pvr2_sysfs *sfp;
90 const char *name; 91 const char *name;
91 92 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name);
92 sfp = (struct pvr2_sysfs *)class_dev->driver_data; 93 name = pvr2_ctrl_get_desc(cip->cptr);
93 if (!sfp) return -EINVAL; 94 pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",
94 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 95 cip->chptr, cip->ctl_id, name);
95 if (!cptr) return -EINVAL;
96
97 name = pvr2_ctrl_get_desc(cptr);
98 pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp,id,name);
99
100 if (!name) return -EINVAL; 96 if (!name) return -EINVAL;
101 97 return scnprintf(buf, PAGE_SIZE, "%s\n", name);
102 return scnprintf(buf,PAGE_SIZE,"%s\n",name);
103} 98}
104 99
105static ssize_t show_type(int id,struct device *class_dev,char *buf) 100static ssize_t show_type(struct device *class_dev,
101 struct device_attribute *attr,
102 char *buf)
106{ 103{
107 struct pvr2_ctrl *cptr; 104 struct pvr2_sysfs_ctl_item *cip;
108 struct pvr2_sysfs *sfp;
109 const char *name; 105 const char *name;
110 enum pvr2_ctl_type tp; 106 enum pvr2_ctl_type tp;
111 107 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type);
112 sfp = (struct pvr2_sysfs *)class_dev->driver_data; 108 tp = pvr2_ctrl_get_type(cip->cptr);
113 if (!sfp) return -EINVAL;
114 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
115 if (!cptr) return -EINVAL;
116
117 tp = pvr2_ctrl_get_type(cptr);
118 switch (tp) { 109 switch (tp) {
119 case pvr2_ctl_int: name = "integer"; break; 110 case pvr2_ctl_int: name = "integer"; break;
120 case pvr2_ctl_enum: name = "enum"; break; 111 case pvr2_ctl_enum: name = "enum"; break;
@@ -122,403 +113,178 @@ static ssize_t show_type(int id,struct device *class_dev,char *buf)
122 case pvr2_ctl_bool: name = "boolean"; break; 113 case pvr2_ctl_bool: name = "boolean"; break;
123 default: name = "?"; break; 114 default: name = "?"; break;
124 } 115 }
125 pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp,id,name); 116 pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",
126 117 cip->chptr, cip->ctl_id, name);
127 if (!name) return -EINVAL; 118 if (!name) return -EINVAL;
128 119 return scnprintf(buf, PAGE_SIZE, "%s\n", name);
129 return scnprintf(buf,PAGE_SIZE,"%s\n",name);
130} 120}
131 121
132static ssize_t show_min(int id,struct device *class_dev,char *buf) 122static ssize_t show_min(struct device *class_dev,
123 struct device_attribute *attr,
124 char *buf)
133{ 125{
134 struct pvr2_ctrl *cptr; 126 struct pvr2_sysfs_ctl_item *cip;
135 struct pvr2_sysfs *sfp;
136 long val; 127 long val;
137 128 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min);
138 sfp = (struct pvr2_sysfs *)class_dev->driver_data; 129 val = pvr2_ctrl_get_min(cip->cptr);
139 if (!sfp) return -EINVAL; 130 pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",
140 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 131 cip->chptr, cip->ctl_id, val);
141 if (!cptr) return -EINVAL; 132 return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
142 val = pvr2_ctrl_get_min(cptr);
143
144 pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp,id,val);
145
146 return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
147} 133}
148 134
149static ssize_t show_max(int id,struct device *class_dev,char *buf) 135static ssize_t show_max(struct device *class_dev,
136 struct device_attribute *attr,
137 char *buf)
150{ 138{
151 struct pvr2_ctrl *cptr; 139 struct pvr2_sysfs_ctl_item *cip;
152 struct pvr2_sysfs *sfp;
153 long val; 140 long val;
154 141 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max);
155 sfp = (struct pvr2_sysfs *)class_dev->driver_data; 142 val = pvr2_ctrl_get_max(cip->cptr);
156 if (!sfp) return -EINVAL; 143 pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",
157 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); 144 cip->chptr, cip->ctl_id, val);
158 if (!cptr) return -EINVAL; 145 return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
159 val = pvr2_ctrl_get_max(cptr);
160
161 pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp,id,val);
162
163 return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
164} 146}
165 147
166static ssize_t show_val_norm(int id,struct device *class_dev,char *buf) 148static ssize_t show_val_norm(struct device *class_dev,
149 struct device_attribute *attr,
150 char *buf)
167{ 151{
168 struct pvr2_ctrl *cptr; 152 struct pvr2_sysfs_ctl_item *cip;
169 struct pvr2_sysfs *sfp; 153 int val;
170 int val,ret; 154 int ret;
171 unsigned int cnt = 0; 155 unsigned int cnt = 0;
172 156 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
173 sfp = (struct pvr2_sysfs *)class_dev->driver_data; 157 ret = pvr2_ctrl_get_value(cip->cptr, &val);
174 if (!sfp) return -EINVAL;
175 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
176 if (!cptr) return -EINVAL;
177
178 ret = pvr2_ctrl_get_value(cptr,&val);
179 if (ret < 0) return ret; 158 if (ret < 0) return ret;
180 159 ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
181 ret = pvr2_ctrl_value_to_sym(cptr,~0,val, 160 buf, PAGE_SIZE - 1, &cnt);
182 buf,PAGE_SIZE-1,&cnt);
183
184 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)", 161 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
185 sfp,id,cnt,buf,val); 162 cip->chptr, cip->ctl_id, cnt, buf, val);
186 buf[cnt] = '\n'; 163 buf[cnt] = '\n';
187 return cnt+1; 164 return cnt+1;
188} 165}
189 166
190static ssize_t show_val_custom(int id,struct device *class_dev,char *buf) 167static ssize_t show_val_custom(struct device *class_dev,
168 struct device_attribute *attr,
169 char *buf)
191{ 170{
192 struct pvr2_ctrl *cptr; 171 struct pvr2_sysfs_ctl_item *cip;
193 struct pvr2_sysfs *sfp; 172 int val;
194 int val,ret; 173 int ret;
195 unsigned int cnt = 0; 174 unsigned int cnt = 0;
196 175 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
197 sfp = (struct pvr2_sysfs *)class_dev->driver_data; 176 ret = pvr2_ctrl_get_value(cip->cptr, &val);
198 if (!sfp) return -EINVAL;
199 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
200 if (!cptr) return -EINVAL;
201
202 ret = pvr2_ctrl_get_value(cptr,&val);
203 if (ret < 0) return ret; 177 if (ret < 0) return ret;
204 178 ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val,
205 ret = pvr2_ctrl_custom_value_to_sym(cptr,~0,val, 179 buf, PAGE_SIZE - 1, &cnt);
206 buf,PAGE_SIZE-1,&cnt);
207
208 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)", 180 pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
209 sfp,id,cnt,buf,val); 181 cip->chptr, cip->ctl_id, cnt, buf, val);
210 buf[cnt] = '\n'; 182 buf[cnt] = '\n';
211 return cnt+1; 183 return cnt+1;
212} 184}
213 185
214static ssize_t show_enum(int id,struct device *class_dev,char *buf) 186static ssize_t show_enum(struct device *class_dev,
187 struct device_attribute *attr,
188 char *buf)
215{ 189{
216 struct pvr2_ctrl *cptr; 190 struct pvr2_sysfs_ctl_item *cip;
217 struct pvr2_sysfs *sfp;
218 long val; 191 long val;
219 unsigned int bcnt,ccnt,ecnt; 192 unsigned int bcnt, ccnt, ecnt;
220 193 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum);
221 sfp = (struct pvr2_sysfs *)class_dev->driver_data; 194 ecnt = pvr2_ctrl_get_cnt(cip->cptr);
222 if (!sfp) return -EINVAL;
223 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
224 if (!cptr) return -EINVAL;
225 ecnt = pvr2_ctrl_get_cnt(cptr);
226 bcnt = 0; 195 bcnt = 0;
227 for (val = 0; val < ecnt; val++) { 196 for (val = 0; val < ecnt; val++) {
228 pvr2_ctrl_get_valname(cptr,val,buf+bcnt,PAGE_SIZE-bcnt,&ccnt); 197 pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt,
198 PAGE_SIZE - bcnt, &ccnt);
229 if (!ccnt) continue; 199 if (!ccnt) continue;
230 bcnt += ccnt; 200 bcnt += ccnt;
231 if (bcnt >= PAGE_SIZE) break; 201 if (bcnt >= PAGE_SIZE) break;
232 buf[bcnt] = '\n'; 202 buf[bcnt] = '\n';
233 bcnt++; 203 bcnt++;
234 } 204 }
235 pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id); 205 pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",
206 cip->chptr, cip->ctl_id);
236 return bcnt; 207 return bcnt;
237} 208}
238 209
239static ssize_t show_bits(int id,struct device *class_dev,char *buf) 210static ssize_t show_bits(struct device *class_dev,
211 struct device_attribute *attr,
212 char *buf)
240{ 213{
241 struct pvr2_ctrl *cptr; 214 struct pvr2_sysfs_ctl_item *cip;
242 struct pvr2_sysfs *sfp; 215 int valid_bits, msk;
243 int valid_bits,msk; 216 unsigned int bcnt, ccnt;
244 unsigned int bcnt,ccnt; 217 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits);
245 218 valid_bits = pvr2_ctrl_get_mask(cip->cptr);
246 sfp = (struct pvr2_sysfs *)class_dev->driver_data;
247 if (!sfp) return -EINVAL;
248 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
249 if (!cptr) return -EINVAL;
250 valid_bits = pvr2_ctrl_get_mask(cptr);
251 bcnt = 0; 219 bcnt = 0;
252 for (msk = 1; valid_bits; msk <<= 1) { 220 for (msk = 1; valid_bits; msk <<= 1) {
253 if (!(msk & valid_bits)) continue; 221 if (!(msk & valid_bits)) continue;
254 valid_bits &= ~msk; 222 valid_bits &= ~msk;
255 pvr2_ctrl_get_valname(cptr,msk,buf+bcnt,PAGE_SIZE-bcnt,&ccnt); 223 pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt,
224 PAGE_SIZE - bcnt, &ccnt);
256 bcnt += ccnt; 225 bcnt += ccnt;
257 if (bcnt >= PAGE_SIZE) break; 226 if (bcnt >= PAGE_SIZE) break;
258 buf[bcnt] = '\n'; 227 buf[bcnt] = '\n';
259 bcnt++; 228 bcnt++;
260 } 229 }
261 pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp,id); 230 pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",
231 cip->chptr, cip->ctl_id);
262 return bcnt; 232 return bcnt;
263} 233}
264 234
265static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp, 235static int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl,
266 const char *buf,unsigned int count) 236 const char *buf,unsigned int count)
267{ 237{
268 struct pvr2_ctrl *cptr;
269 int ret; 238 int ret;
270 int mask,val; 239 int mask,val;
271
272 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
273 if (customfl) { 240 if (customfl) {
274 ret = pvr2_ctrl_custom_sym_to_value(cptr,buf,count,&mask,&val); 241 ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count,
242 &mask, &val);
275 } else { 243 } else {
276 ret = pvr2_ctrl_sym_to_value(cptr,buf,count,&mask,&val); 244 ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count,
245 &mask, &val);
277 } 246 }
278 if (ret < 0) return ret; 247 if (ret < 0) return ret;
279 ret = pvr2_ctrl_set_mask_value(cptr,mask,val); 248 ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val);
280 pvr2_hdw_commit_ctl(sfp->channel.hdw); 249 pvr2_hdw_commit_ctl(cip->chptr->channel.hdw);
281 return ret; 250 return ret;
282} 251}
283 252
284static ssize_t store_val_norm(int id,struct device *class_dev, 253static ssize_t store_val_norm(struct device *class_dev,
285 const char *buf,size_t count) 254 struct device_attribute *attr,
255 const char *buf, size_t count)
286{ 256{
287 struct pvr2_sysfs *sfp; 257 struct pvr2_sysfs_ctl_item *cip;
288 int ret; 258 int ret;
289 sfp = (struct pvr2_sysfs *)class_dev->driver_data; 259 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
290 pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"", 260 pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
291 sfp,id,(int)count,buf); 261 cip->chptr, cip->ctl_id, (int)count, buf);
292 ret = store_val_any(id,0,sfp,buf,count); 262 ret = store_val_any(cip, 0, buf, count);
293 if (!ret) ret = count; 263 if (!ret) ret = count;
294 return ret; 264 return ret;
295} 265}
296 266
297static ssize_t store_val_custom(int id,struct device *class_dev, 267static ssize_t store_val_custom(struct device *class_dev,
298 const char *buf,size_t count) 268 struct device_attribute *attr,
269 const char *buf, size_t count)
299{ 270{
300 struct pvr2_sysfs *sfp; 271 struct pvr2_sysfs_ctl_item *cip;
301 int ret; 272 int ret;
302 sfp = (struct pvr2_sysfs *)class_dev->driver_data; 273 cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
303 pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"", 274 pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
304 sfp,id,(int)count,buf); 275 cip->chptr, cip->ctl_id, (int)count, buf);
305 ret = store_val_any(id,1,sfp,buf,count); 276 ret = store_val_any(cip, 1, buf, count);
306 if (!ret) ret = count; 277 if (!ret) ret = count;
307 return ret; 278 return ret;
308} 279}
309 280
310/*
311 Mike Isely <isely@pobox.com> 30-April-2005
312
313 This next batch of horrible preprocessor hackery is needed because the
314 kernel's device_attribute mechanism fails to pass the actual
315 attribute through to the show / store functions, which means we have no
316 way to package up any attribute-specific parameters, like for example the
317 control id. So we work around this brain-damage by encoding the control
318 id into the show / store functions themselves and pick the function based
319 on the control id we're setting up. These macros try to ease the pain.
320 Yuck.
321*/
322
323#define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \
324static ssize_t sf_name##_##ctl_id(struct device *class_dev, \
325struct device_attribute *attr, char *buf) \
326{ return sf_name(ctl_id,class_dev,buf); }
327
328#define CREATE_STORE_INSTANCE(sf_name,ctl_id) \
329static ssize_t sf_name##_##ctl_id(struct device *class_dev, \
330struct device_attribute *attr, const char *buf, size_t count) \
331{ return sf_name(ctl_id,class_dev,buf,count); }
332
333#define CREATE_BATCH(ctl_id) \
334CREATE_SHOW_INSTANCE(show_name,ctl_id) \
335CREATE_SHOW_INSTANCE(show_type,ctl_id) \
336CREATE_SHOW_INSTANCE(show_min,ctl_id) \
337CREATE_SHOW_INSTANCE(show_max,ctl_id) \
338CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \
339CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \
340CREATE_SHOW_INSTANCE(show_enum,ctl_id) \
341CREATE_SHOW_INSTANCE(show_bits,ctl_id) \
342CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \
343CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \
344
345CREATE_BATCH(0)
346CREATE_BATCH(1)
347CREATE_BATCH(2)
348CREATE_BATCH(3)
349CREATE_BATCH(4)
350CREATE_BATCH(5)
351CREATE_BATCH(6)
352CREATE_BATCH(7)
353CREATE_BATCH(8)
354CREATE_BATCH(9)
355CREATE_BATCH(10)
356CREATE_BATCH(11)
357CREATE_BATCH(12)
358CREATE_BATCH(13)
359CREATE_BATCH(14)
360CREATE_BATCH(15)
361CREATE_BATCH(16)
362CREATE_BATCH(17)
363CREATE_BATCH(18)
364CREATE_BATCH(19)
365CREATE_BATCH(20)
366CREATE_BATCH(21)
367CREATE_BATCH(22)
368CREATE_BATCH(23)
369CREATE_BATCH(24)
370CREATE_BATCH(25)
371CREATE_BATCH(26)
372CREATE_BATCH(27)
373CREATE_BATCH(28)
374CREATE_BATCH(29)
375CREATE_BATCH(30)
376CREATE_BATCH(31)
377CREATE_BATCH(32)
378CREATE_BATCH(33)
379CREATE_BATCH(34)
380CREATE_BATCH(35)
381CREATE_BATCH(36)
382CREATE_BATCH(37)
383CREATE_BATCH(38)
384CREATE_BATCH(39)
385CREATE_BATCH(40)
386CREATE_BATCH(41)
387CREATE_BATCH(42)
388CREATE_BATCH(43)
389CREATE_BATCH(44)
390CREATE_BATCH(45)
391CREATE_BATCH(46)
392CREATE_BATCH(47)
393CREATE_BATCH(48)
394CREATE_BATCH(49)
395CREATE_BATCH(50)
396CREATE_BATCH(51)
397CREATE_BATCH(52)
398CREATE_BATCH(53)
399CREATE_BATCH(54)
400CREATE_BATCH(55)
401CREATE_BATCH(56)
402CREATE_BATCH(57)
403CREATE_BATCH(58)
404CREATE_BATCH(59)
405
406struct pvr2_sysfs_func_set {
407 ssize_t (*show_name)(struct device *,
408 struct device_attribute *attr, char *);
409 ssize_t (*show_type)(struct device *,
410 struct device_attribute *attr, char *);
411 ssize_t (*show_min)(struct device *,
412 struct device_attribute *attr, char *);
413 ssize_t (*show_max)(struct device *,
414 struct device_attribute *attr, char *);
415 ssize_t (*show_enum)(struct device *,
416 struct device_attribute *attr, char *);
417 ssize_t (*show_bits)(struct device *,
418 struct device_attribute *attr, char *);
419 ssize_t (*show_val_norm)(struct device *,
420 struct device_attribute *attr, char *);
421 ssize_t (*store_val_norm)(struct device *,
422 struct device_attribute *attr,
423 const char *,size_t);
424 ssize_t (*show_val_custom)(struct device *,
425 struct device_attribute *attr, char *);
426 ssize_t (*store_val_custom)(struct device *,
427 struct device_attribute *attr,
428 const char *,size_t);
429};
430
431#define INIT_BATCH(ctl_id) \
432[ctl_id] = { \
433 .show_name = show_name_##ctl_id, \
434 .show_type = show_type_##ctl_id, \
435 .show_min = show_min_##ctl_id, \
436 .show_max = show_max_##ctl_id, \
437 .show_enum = show_enum_##ctl_id, \
438 .show_bits = show_bits_##ctl_id, \
439 .show_val_norm = show_val_norm_##ctl_id, \
440 .store_val_norm = store_val_norm_##ctl_id, \
441 .show_val_custom = show_val_custom_##ctl_id, \
442 .store_val_custom = store_val_custom_##ctl_id, \
443} \
444
445static struct pvr2_sysfs_func_set funcs[] = {
446 INIT_BATCH(0),
447 INIT_BATCH(1),
448 INIT_BATCH(2),
449 INIT_BATCH(3),
450 INIT_BATCH(4),
451 INIT_BATCH(5),
452 INIT_BATCH(6),
453 INIT_BATCH(7),
454 INIT_BATCH(8),
455 INIT_BATCH(9),
456 INIT_BATCH(10),
457 INIT_BATCH(11),
458 INIT_BATCH(12),
459 INIT_BATCH(13),
460 INIT_BATCH(14),
461 INIT_BATCH(15),
462 INIT_BATCH(16),
463 INIT_BATCH(17),
464 INIT_BATCH(18),
465 INIT_BATCH(19),
466 INIT_BATCH(20),
467 INIT_BATCH(21),
468 INIT_BATCH(22),
469 INIT_BATCH(23),
470 INIT_BATCH(24),
471 INIT_BATCH(25),
472 INIT_BATCH(26),
473 INIT_BATCH(27),
474 INIT_BATCH(28),
475 INIT_BATCH(29),
476 INIT_BATCH(30),
477 INIT_BATCH(31),
478 INIT_BATCH(32),
479 INIT_BATCH(33),
480 INIT_BATCH(34),
481 INIT_BATCH(35),
482 INIT_BATCH(36),
483 INIT_BATCH(37),
484 INIT_BATCH(38),
485 INIT_BATCH(39),
486 INIT_BATCH(40),
487 INIT_BATCH(41),
488 INIT_BATCH(42),
489 INIT_BATCH(43),
490 INIT_BATCH(44),
491 INIT_BATCH(45),
492 INIT_BATCH(46),
493 INIT_BATCH(47),
494 INIT_BATCH(48),
495 INIT_BATCH(49),
496 INIT_BATCH(50),
497 INIT_BATCH(51),
498 INIT_BATCH(52),
499 INIT_BATCH(53),
500 INIT_BATCH(54),
501 INIT_BATCH(55),
502 INIT_BATCH(56),
503 INIT_BATCH(57),
504 INIT_BATCH(58),
505 INIT_BATCH(59),
506};
507
508
509static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) 281static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
510{ 282{
511 struct pvr2_sysfs_ctl_item *cip; 283 struct pvr2_sysfs_ctl_item *cip;
512 struct pvr2_sysfs_func_set *fp;
513 struct pvr2_ctrl *cptr; 284 struct pvr2_ctrl *cptr;
514 unsigned int cnt,acnt; 285 unsigned int cnt,acnt;
515 int ret; 286 int ret;
516 287
517 if ((ctl_id < 0) || (ctl_id >= ARRAY_SIZE(funcs))) {
518 return;
519 }
520
521 fp = funcs + ctl_id;
522 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id); 288 cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
523 if (!cptr) return; 289 if (!cptr) return;
524 290
@@ -527,6 +293,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
527 pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip); 293 pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
528 294
529 cip->cptr = cptr; 295 cip->cptr = cptr;
296 cip->ctl_id = ctl_id;
530 297
531 cip->chptr = sfp; 298 cip->chptr = sfp;
532 cip->item_next = NULL; 299 cip->item_next = NULL;
@@ -539,19 +306,19 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
539 306
540 cip->attr_name.attr.name = "name"; 307 cip->attr_name.attr.name = "name";
541 cip->attr_name.attr.mode = S_IRUGO; 308 cip->attr_name.attr.mode = S_IRUGO;
542 cip->attr_name.show = fp->show_name; 309 cip->attr_name.show = show_name;
543 310
544 cip->attr_type.attr.name = "type"; 311 cip->attr_type.attr.name = "type";
545 cip->attr_type.attr.mode = S_IRUGO; 312 cip->attr_type.attr.mode = S_IRUGO;
546 cip->attr_type.show = fp->show_type; 313 cip->attr_type.show = show_type;
547 314
548 cip->attr_min.attr.name = "min_val"; 315 cip->attr_min.attr.name = "min_val";
549 cip->attr_min.attr.mode = S_IRUGO; 316 cip->attr_min.attr.mode = S_IRUGO;
550 cip->attr_min.show = fp->show_min; 317 cip->attr_min.show = show_min;
551 318
552 cip->attr_max.attr.name = "max_val"; 319 cip->attr_max.attr.name = "max_val";
553 cip->attr_max.attr.mode = S_IRUGO; 320 cip->attr_max.attr.mode = S_IRUGO;
554 cip->attr_max.show = fp->show_max; 321 cip->attr_max.show = show_max;
555 322
556 cip->attr_val.attr.name = "cur_val"; 323 cip->attr_val.attr.name = "cur_val";
557 cip->attr_val.attr.mode = S_IRUGO; 324 cip->attr_val.attr.mode = S_IRUGO;
@@ -561,11 +328,11 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
561 328
562 cip->attr_enum.attr.name = "enum_val"; 329 cip->attr_enum.attr.name = "enum_val";
563 cip->attr_enum.attr.mode = S_IRUGO; 330 cip->attr_enum.attr.mode = S_IRUGO;
564 cip->attr_enum.show = fp->show_enum; 331 cip->attr_enum.show = show_enum;
565 332
566 cip->attr_bits.attr.name = "bit_val"; 333 cip->attr_bits.attr.name = "bit_val";
567 cip->attr_bits.attr.mode = S_IRUGO; 334 cip->attr_bits.attr.mode = S_IRUGO;
568 cip->attr_bits.show = fp->show_bits; 335 cip->attr_bits.show = show_bits;
569 336
570 if (pvr2_ctrl_is_writable(cptr)) { 337 if (pvr2_ctrl_is_writable(cptr)) {
571 cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP; 338 cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
@@ -576,12 +343,12 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
576 cip->attr_gen[acnt++] = &cip->attr_name.attr; 343 cip->attr_gen[acnt++] = &cip->attr_name.attr;
577 cip->attr_gen[acnt++] = &cip->attr_type.attr; 344 cip->attr_gen[acnt++] = &cip->attr_type.attr;
578 cip->attr_gen[acnt++] = &cip->attr_val.attr; 345 cip->attr_gen[acnt++] = &cip->attr_val.attr;
579 cip->attr_val.show = fp->show_val_norm; 346 cip->attr_val.show = show_val_norm;
580 cip->attr_val.store = fp->store_val_norm; 347 cip->attr_val.store = store_val_norm;
581 if (pvr2_ctrl_has_custom_symbols(cptr)) { 348 if (pvr2_ctrl_has_custom_symbols(cptr)) {
582 cip->attr_gen[acnt++] = &cip->attr_custom.attr; 349 cip->attr_gen[acnt++] = &cip->attr_custom.attr;
583 cip->attr_custom.show = fp->show_val_custom; 350 cip->attr_custom.show = show_val_custom;
584 cip->attr_custom.store = fp->store_val_custom; 351 cip->attr_custom.store = store_val_custom;
585 } 352 }
586 switch (pvr2_ctrl_get_type(cptr)) { 353 switch (pvr2_ctrl_get_type(cptr)) {
587 case pvr2_ctl_enum: 354 case pvr2_ctl_enum:
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.h b/drivers/media/video/pvrusb2/pvrusb2-sysfs.h
index ff9373b47f8f..6d875bfe7991 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/drivers/media/video/pvrusb2/pvrusb2-tuner.c
index 05e65ce2e3a9..07775d1aad4e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-tuner.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-tuner.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/drivers/media/video/pvrusb2/pvrusb2-tuner.h
index 556f12aa9160..ef4afaf37b0a 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-tuner.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-tuner.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-util.h b/drivers/media/video/pvrusb2/pvrusb2-util.h
index e53aee416f56..92b75544ee2e 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-util.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-util.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index e9b5d4e91327..0d72dc470fef 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-v4l2.h
index 9a995e2d2256..34c011a7b107 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * 5 *
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
index 2433a3160041..4059648c7056 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
index 2b917fda02e4..4ff5b892b303 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
index 66b4d36ef765..f6fcf0ac6118 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
index 8aaeff4e1e20..807090961255 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pvrusb2/pvrusb2.h b/drivers/media/video/pvrusb2/pvrusb2.h
index 1a9a4baf12b8..240de9b35661 100644
--- a/drivers/media/video/pvrusb2/pvrusb2.h
+++ b/drivers/media/video/pvrusb2/pvrusb2.h
@@ -1,6 +1,5 @@
1/* 1/*
2 * 2 *
3 * $Id$
4 * 3 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index ea53316d2111..1cccd5c77048 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -1255,7 +1255,6 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
1255 exactly the same otherwise. 1255 exactly the same otherwise.
1256 */ 1256 */
1257 1257
1258
1259/* define local variable for arg */ 1258/* define local variable for arg */
1260#define ARG_DEF(ARG_type, ARG_name)\ 1259#define ARG_DEF(ARG_type, ARG_name)\
1261 ARG_type *ARG_name = arg; 1260 ARG_type *ARG_name = arg;
@@ -1268,7 +1267,6 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
1268/* copy local variable to arg */ 1267/* copy local variable to arg */
1269#define ARG_OUT(ARG_name) /* nothing */ 1268#define ARG_OUT(ARG_name) /* nothing */
1270 1269
1271
1272int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) 1270int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1273{ 1271{
1274 int ret = 0; 1272 int ret = 0;
diff --git a/drivers/media/video/pwc/pwc-ioctl.h b/drivers/media/video/pwc/pwc-ioctl.h
index cec660299768..8c0cae7b3daf 100644
--- a/drivers/media/video/pwc/pwc-ioctl.h
+++ b/drivers/media/video/pwc/pwc-ioctl.h
@@ -54,7 +54,6 @@
54#include <linux/types.h> 54#include <linux/types.h>
55#include <linux/version.h> 55#include <linux/version.h>
56 56
57
58 /* Enumeration of image sizes */ 57 /* Enumeration of image sizes */
59#define PSZ_SQCIF 0x00 58#define PSZ_SQCIF 0x00
60#define PSZ_QSIF 0x01 59#define PSZ_QSIF 0x01
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 5ec5bb9a94d2..b15f82c49766 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -30,6 +30,7 @@
30 30
31#include <media/v4l2-common.h> 31#include <media/v4l2-common.h>
32#include <media/v4l2-dev.h> 32#include <media/v4l2-dev.h>
33#include <media/videobuf-dma-sg.h>
33#include <media/soc_camera.h> 34#include <media/soc_camera.h>
34 35
35#include <linux/videodev2.h> 36#include <linux/videodev2.h>
@@ -582,6 +583,19 @@ static struct videobuf_queue_ops pxa_videobuf_ops = {
582 .buf_release = pxa_videobuf_release, 583 .buf_release = pxa_videobuf_release,
583}; 584};
584 585
586static void pxa_camera_init_videobuf(struct videobuf_queue *q,
587 struct soc_camera_device *icd)
588{
589 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
590 struct pxa_camera_dev *pcdev = ici->priv;
591
592 /* We must pass NULL as dev pointer, then all pci_* dma operations
593 * transform to normal dma_* ones. */
594 videobuf_queue_sg_init(q, &pxa_videobuf_ops, NULL, &pcdev->lock,
595 V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
596 sizeof(struct pxa_buffer), icd);
597}
598
585static int mclk_get_divisor(struct pxa_camera_dev *pcdev) 599static int mclk_get_divisor(struct pxa_camera_dev *pcdev)
586{ 600{
587 unsigned int mclk_10khz = pcdev->platform_mclk_10khz; 601 unsigned int mclk_10khz = pcdev->platform_mclk_10khz;
@@ -983,34 +997,23 @@ static int pxa_camera_querycap(struct soc_camera_host *ici,
983 return 0; 997 return 0;
984} 998}
985 999
986static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf)
987{
988 struct soc_camera_host *ici =
989 to_soc_camera_host(icf->icd->dev.parent);
990 struct pxa_camera_dev *pcdev = ici->priv;
991
992 return &pcdev->lock;
993}
994
995static struct soc_camera_host_ops pxa_soc_camera_host_ops = { 1000static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
996 .owner = THIS_MODULE, 1001 .owner = THIS_MODULE,
997 .add = pxa_camera_add_device, 1002 .add = pxa_camera_add_device,
998 .remove = pxa_camera_remove_device, 1003 .remove = pxa_camera_remove_device,
999 .set_fmt_cap = pxa_camera_set_fmt_cap, 1004 .set_fmt_cap = pxa_camera_set_fmt_cap,
1000 .try_fmt_cap = pxa_camera_try_fmt_cap, 1005 .try_fmt_cap = pxa_camera_try_fmt_cap,
1006 .init_videobuf = pxa_camera_init_videobuf,
1001 .reqbufs = pxa_camera_reqbufs, 1007 .reqbufs = pxa_camera_reqbufs,
1002 .poll = pxa_camera_poll, 1008 .poll = pxa_camera_poll,
1003 .querycap = pxa_camera_querycap, 1009 .querycap = pxa_camera_querycap,
1004 .try_bus_param = pxa_camera_try_bus_param, 1010 .try_bus_param = pxa_camera_try_bus_param,
1005 .set_bus_param = pxa_camera_set_bus_param, 1011 .set_bus_param = pxa_camera_set_bus_param,
1006 .spinlock_alloc = pxa_camera_spinlock_alloc,
1007}; 1012};
1008 1013
1009/* Should be allocated dynamically too, but we have only one. */ 1014/* Should be allocated dynamically too, but we have only one. */
1010static struct soc_camera_host pxa_soc_camera_host = { 1015static struct soc_camera_host pxa_soc_camera_host = {
1011 .drv_name = PXA_CAM_DRV_NAME, 1016 .drv_name = PXA_CAM_DRV_NAME,
1012 .vbq_ops = &pxa_videobuf_ops,
1013 .msize = sizeof(struct pxa_buffer),
1014 .ops = &pxa_soc_camera_host_ops, 1017 .ops = &pxa_soc_camera_host_ops,
1015}; 1018};
1016 1019
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
new file mode 100644
index 000000000000..04eb2c3fabd8
--- /dev/null
+++ b/drivers/media/video/s2255drv.c
@@ -0,0 +1,2495 @@
1/*
2 * s2255drv.c - a driver for the Sensoray 2255 USB video capture device
3 *
4 * Copyright (C) 2007-2008 by Sensoray Company Inc.
5 * Dean Anderson
6 *
7 * Some video buffer code based on vivi driver:
8 *
9 * Sensoray 2255 device supports 4 simultaneous channels.
10 * The channels are not "crossbar" inputs, they are physically
11 * attached to separate video decoders.
12 *
13 * Because of USB2.0 bandwidth limitations. There is only a
14 * certain amount of data which may be transferred at one time.
15 *
16 * Example maximum bandwidth utilization:
17 *
18 * -full size, color mode YUYV or YUV422P: 2 channels at once
19 *
20 * -full or half size Grey scale: all 4 channels at once
21 *
22 * -half size, color mode YUYV or YUV422P: all 4 channels at once
23 *
24 * -full size, color mode YUYV or YUV422P 1/2 frame rate: all 4 channels
25 * at once.
26 * (TODO: Incorporate videodev2 frame rate(FR) enumeration,
27 * which is currently experimental.)
28 *
29 * This program is free software; you can redistribute it and/or modify
30 * it under the terms of the GNU General Public License as published by
31 * the Free Software Foundation; either version 2 of the License, or
32 * (at your option) any later version.
33 *
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
42 */
43
44#include <linux/module.h>
45#include <linux/firmware.h>
46#include <linux/kernel.h>
47#include <linux/mutex.h>
48#include <linux/videodev2.h>
49#include <linux/version.h>
50#include <media/videobuf-vmalloc.h>
51#include <media/v4l2-common.h>
52#include <linux/vmalloc.h>
53#include <linux/usb.h>
54
55#define FIRMWARE_FILE_NAME "f2255usb.bin"
56
57
58
59/* vendor request in */
60#define S2255_VR_IN 0
61/* vendor request out */
62#define S2255_VR_OUT 1
63/* firmware query */
64#define S2255_VR_FW 0x30
65/* USB endpoint number for configuring the device */
66#define S2255_CONFIG_EP 2
67/* maximum time for DSP to start responding after last FW word loaded(ms) */
68#define S2255_DSP_BOOTTIME 400
69/* maximum time to wait for firmware to load (ms) */
70#define S2255_LOAD_TIMEOUT (5000 + S2255_DSP_BOOTTIME)
71#define S2255_DEF_BUFS 16
72#define MAX_CHANNELS 4
73#define FRAME_MARKER 0x2255DA4AL
74#define MAX_PIPE_USBBLOCK (40 * 1024)
75#define DEFAULT_PIPE_USBBLOCK (16 * 1024)
76#define MAX_CHANNELS 4
77#define MAX_PIPE_BUFFERS 1
78#define SYS_FRAMES 4
79/* maximum size is PAL full size plus room for the marker header(s) */
80#define SYS_FRAMES_MAXSIZE (720 * 288 * 2 * 2 + 4096)
81#define DEF_USB_BLOCK (4096)
82#define LINE_SZ_4CIFS_NTSC 640
83#define LINE_SZ_2CIFS_NTSC 640
84#define LINE_SZ_1CIFS_NTSC 320
85#define LINE_SZ_4CIFS_PAL 704
86#define LINE_SZ_2CIFS_PAL 704
87#define LINE_SZ_1CIFS_PAL 352
88#define NUM_LINES_4CIFS_NTSC 240
89#define NUM_LINES_2CIFS_NTSC 240
90#define NUM_LINES_1CIFS_NTSC 240
91#define NUM_LINES_4CIFS_PAL 288
92#define NUM_LINES_2CIFS_PAL 288
93#define NUM_LINES_1CIFS_PAL 288
94#define LINE_SZ_DEF 640
95#define NUM_LINES_DEF 240
96
97
98/* predefined settings */
99#define FORMAT_NTSC 1
100#define FORMAT_PAL 2
101
102#define SCALE_4CIFS 1 /* 640x480(NTSC) or 704x576(PAL) */
103#define SCALE_2CIFS 2 /* 640x240(NTSC) or 704x288(PAL) */
104#define SCALE_1CIFS 3 /* 320x240(NTSC) or 352x288(PAL) */
105
106#define COLOR_YUVPL 1 /* YUV planar */
107#define COLOR_YUVPK 2 /* YUV packed */
108#define COLOR_Y8 4 /* monochrome */
109
110/* frame decimation. Not implemented by V4L yet(experimental in V4L) */
111#define FDEC_1 1 /* capture every frame. default */
112#define FDEC_2 2 /* capture every 2nd frame */
113#define FDEC_3 3 /* capture every 3rd frame */
114#define FDEC_5 5 /* capture every 5th frame */
115
116/*-------------------------------------------------------
117 * Default mode parameters.
118 *-------------------------------------------------------*/
119#define DEF_SCALE SCALE_4CIFS
120#define DEF_COLOR COLOR_YUVPL
121#define DEF_FDEC FDEC_1
122#define DEF_BRIGHT 0
123#define DEF_CONTRAST 0x5c
124#define DEF_SATURATION 0x80
125#define DEF_HUE 0
126
127/* usb config commands */
128#define IN_DATA_TOKEN 0x2255c0de
129#define CMD_2255 0xc2255000
130#define CMD_SET_MODE (CMD_2255 | 0x10)
131#define CMD_START (CMD_2255 | 0x20)
132#define CMD_STOP (CMD_2255 | 0x30)
133#define CMD_STATUS (CMD_2255 | 0x40)
134
135struct s2255_mode {
136 u32 format; /* input video format (NTSC, PAL) */
137 u32 scale; /* output video scale */
138 u32 color; /* output video color format */
139 u32 fdec; /* frame decimation */
140 u32 bright; /* brightness */
141 u32 contrast; /* contrast */
142 u32 saturation; /* saturation */
143 u32 hue; /* hue (NTSC only)*/
144 u32 single; /* capture 1 frame at a time (!=0), continuously (==0)*/
145 u32 usb_block; /* block size. should be 4096 of DEF_USB_BLOCK */
146 u32 restart; /* if DSP requires restart */
147};
148
149/* frame structure */
150#define FRAME_STATE_UNUSED 0
151#define FRAME_STATE_FILLING 1
152#define FRAME_STATE_FULL 2
153
154
155struct s2255_framei {
156 unsigned long size;
157
158 unsigned long ulState; /* ulState ==0 unused, 1 being filled, 2 full */
159 void *lpvbits; /* image data */
160 unsigned long cur_size; /* current data copied to it */
161};
162
163/* image buffer structure */
164struct s2255_bufferi {
165 unsigned long dwFrames; /* number of frames in buffer */
166 struct s2255_framei frame[SYS_FRAMES]; /* array of FRAME structures */
167};
168
169#define DEF_MODEI_NTSC_CONT {FORMAT_NTSC, DEF_SCALE, DEF_COLOR, \
170 DEF_FDEC, DEF_BRIGHT, DEF_CONTRAST, DEF_SATURATION, \
171 DEF_HUE, 0, DEF_USB_BLOCK, 0}
172
173struct s2255_dmaqueue {
174 struct list_head active;
175 /* thread for acquisition */
176 struct task_struct *kthread;
177 int frame;
178 struct s2255_dev *dev;
179 int channel;
180};
181
182/* for firmware loading, fw_state */
183#define S2255_FW_NOTLOADED 0
184#define S2255_FW_LOADED_DSPWAIT 1
185#define S2255_FW_SUCCESS 2
186#define S2255_FW_FAILED 3
187
188struct s2255_fw {
189 int fw_loaded;
190 int fw_size;
191 struct urb *fw_urb;
192 atomic_t fw_state;
193 void *pfw_data;
194 wait_queue_head_t wait_fw;
195 struct timer_list dsp_wait;
196 const struct firmware *fw;
197};
198
199struct s2255_pipeinfo {
200 u32 max_transfer_size;
201 u32 cur_transfer_size;
202 u8 *transfer_buffer;
203 u32 transfer_flags;;
204 u32 state;
205 u32 prev_state;
206 u32 urb_size;
207 void *stream_urb;
208 void *dev; /* back pointer to s2255_dev struct*/
209 u32 err_count;
210 u32 buf_index;
211 u32 idx;
212 u32 priority_set;
213};
214
215struct s2255_fmt; /*forward declaration */
216
217struct s2255_dev {
218 int frames;
219 int users[MAX_CHANNELS];
220 struct mutex lock;
221 struct mutex open_lock;
222 int resources[MAX_CHANNELS];
223 struct usb_device *udev;
224 struct usb_interface *interface;
225 u8 read_endpoint;
226
227 struct s2255_dmaqueue vidq[MAX_CHANNELS];
228 struct video_device *vdev[MAX_CHANNELS];
229 struct list_head s2255_devlist;
230 struct timer_list timer;
231 struct s2255_fw *fw_data;
232 int board_num;
233 int is_open;
234 struct s2255_pipeinfo pipes[MAX_PIPE_BUFFERS];
235 struct s2255_bufferi buffer[MAX_CHANNELS];
236 struct s2255_mode mode[MAX_CHANNELS];
237 const struct s2255_fmt *cur_fmt[MAX_CHANNELS];
238 int cur_frame[MAX_CHANNELS];
239 int last_frame[MAX_CHANNELS];
240 u32 cc; /* current channel */
241 int b_acquire[MAX_CHANNELS];
242 unsigned long req_image_size[MAX_CHANNELS];
243 int bad_payload[MAX_CHANNELS];
244 unsigned long frame_count[MAX_CHANNELS];
245 int frame_ready;
246 struct kref kref;
247 spinlock_t slock;
248};
249#define to_s2255_dev(d) container_of(d, struct s2255_dev, kref)
250
251struct s2255_fmt {
252 char *name;
253 u32 fourcc;
254 int depth;
255};
256
257/* buffer for one video frame */
258struct s2255_buffer {
259 /* common v4l buffer stuff -- must be first */
260 struct videobuf_buffer vb;
261 const struct s2255_fmt *fmt;
262};
263
264struct s2255_fh {
265 struct s2255_dev *dev;
266 unsigned int resources;
267 const struct s2255_fmt *fmt;
268 unsigned int width;
269 unsigned int height;
270 struct videobuf_queue vb_vidq;
271 enum v4l2_buf_type type;
272 int channel;
273 /* mode below is the desired mode.
274 mode in s2255_dev is the current mode that was last set */
275 struct s2255_mode mode;
276};
277
278/*
279 * TODO: fixme S2255_MAX_USERS. Do not limit open driver handles.
280 * Limit V4L to one stream at a time.
281 */
282#define S2255_MAX_USERS 1
283
284#define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */
285#define S2255_MAJOR_VERSION 1
286#define S2255_MINOR_VERSION 13
287#define S2255_RELEASE 0
288#define S2255_VERSION KERNEL_VERSION(S2255_MAJOR_VERSION, \
289 S2255_MINOR_VERSION, \
290 S2255_RELEASE)
291
292/* vendor ids */
293#define USB_S2255_VENDOR_ID 0x1943
294#define USB_S2255_PRODUCT_ID 0x2255
295#define S2255_NORMS (V4L2_STD_PAL | V4L2_STD_NTSC)
296/* frame prefix size (sent once every frame) */
297#define PREFIX_SIZE 512
298
299/* Channels on box are in reverse order */
300static unsigned long G_chnmap[MAX_CHANNELS] = {3, 2, 1, 0};
301
302static LIST_HEAD(s2255_devlist);
303
304static int debug;
305static int *s2255_debug = &debug;
306
307static int s2255_start_readpipe(struct s2255_dev *dev);
308static void s2255_stop_readpipe(struct s2255_dev *dev);
309static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn);
310static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn);
311static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
312 int chn);
313static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
314 struct s2255_mode *mode);
315static int s2255_board_shutdown(struct s2255_dev *dev);
316static void s2255_exit_v4l(struct s2255_dev *dev);
317static void s2255_fwload_start(struct s2255_dev *dev);
318
319#define dprintk(level, fmt, arg...) \
320 do { \
321 if (*s2255_debug >= (level)) { \
322 printk(KERN_DEBUG "s2255: " fmt, ##arg); \
323 } \
324 } while (0)
325
326
327static struct usb_driver s2255_driver;
328
329
330/* Declare static vars that will be used as parameters */
331static unsigned int vid_limit = 16; /* Video memory limit, in Mb */
332
333/* start video number */
334static int video_nr = -1; /* /dev/videoN, -1 for autodetect */
335
336module_param(debug, int, 0644);
337MODULE_PARM_DESC(debug, "Debug level(0-100) default 0");
338module_param(vid_limit, int, 0644);
339MODULE_PARM_DESC(vid_limit, "video memory limit(Mb)");
340module_param(video_nr, int, 0644);
341MODULE_PARM_DESC(video_nr, "start video minor(-1 default autodetect)");
342
343/* USB device table */
344static struct usb_device_id s2255_table[] = {
345 {USB_DEVICE(USB_S2255_VENDOR_ID, USB_S2255_PRODUCT_ID)},
346 { } /* Terminating entry */
347};
348MODULE_DEVICE_TABLE(usb, s2255_table);
349
350
351#define BUFFER_TIMEOUT msecs_to_jiffies(400)
352
353/* supported controls */
354static struct v4l2_queryctrl s2255_qctrl[] = {
355 {
356 .id = V4L2_CID_BRIGHTNESS,
357 .type = V4L2_CTRL_TYPE_INTEGER,
358 .name = "Brightness",
359 .minimum = -127,
360 .maximum = 128,
361 .step = 1,
362 .default_value = 0,
363 .flags = 0,
364 }, {
365 .id = V4L2_CID_CONTRAST,
366 .type = V4L2_CTRL_TYPE_INTEGER,
367 .name = "Contrast",
368 .minimum = 0,
369 .maximum = 255,
370 .step = 0x1,
371 .default_value = DEF_CONTRAST,
372 .flags = 0,
373 }, {
374 .id = V4L2_CID_SATURATION,
375 .type = V4L2_CTRL_TYPE_INTEGER,
376 .name = "Saturation",
377 .minimum = 0,
378 .maximum = 255,
379 .step = 0x1,
380 .default_value = DEF_SATURATION,
381 .flags = 0,
382 }, {
383 .id = V4L2_CID_HUE,
384 .type = V4L2_CTRL_TYPE_INTEGER,
385 .name = "Hue",
386 .minimum = 0,
387 .maximum = 255,
388 .step = 0x1,
389 .default_value = DEF_HUE,
390 .flags = 0,
391 }
392};
393
394static int qctl_regs[ARRAY_SIZE(s2255_qctrl)];
395
396/* image formats. */
397static const struct s2255_fmt formats[] = {
398 {
399 .name = "4:2:2, planar, YUV422P",
400 .fourcc = V4L2_PIX_FMT_YUV422P,
401 .depth = 16
402
403 }, {
404 .name = "4:2:2, packed, YUYV",
405 .fourcc = V4L2_PIX_FMT_YUYV,
406 .depth = 16
407
408 }, {
409 .name = "4:2:2, packed, UYVY",
410 .fourcc = V4L2_PIX_FMT_UYVY,
411 .depth = 16
412 }, {
413 .name = "8bpp GREY",
414 .fourcc = V4L2_PIX_FMT_GREY,
415 .depth = 8
416 }
417};
418
419static int norm_maxw(struct video_device *vdev)
420{
421 return (vdev->current_norm & V4L2_STD_NTSC) ?
422 LINE_SZ_4CIFS_NTSC : LINE_SZ_4CIFS_PAL;
423}
424
425static int norm_maxh(struct video_device *vdev)
426{
427 return (vdev->current_norm & V4L2_STD_NTSC) ?
428 (NUM_LINES_1CIFS_NTSC * 2) : (NUM_LINES_1CIFS_PAL * 2);
429}
430
431static int norm_minw(struct video_device *vdev)
432{
433 return (vdev->current_norm & V4L2_STD_NTSC) ?
434 LINE_SZ_1CIFS_NTSC : LINE_SZ_1CIFS_PAL;
435}
436
437static int norm_minh(struct video_device *vdev)
438{
439 return (vdev->current_norm & V4L2_STD_NTSC) ?
440 (NUM_LINES_1CIFS_NTSC) : (NUM_LINES_1CIFS_PAL);
441}
442
443
444/*
445 * TODO: fixme: move YUV reordering to hardware
446 * converts 2255 planar format to yuyv or uyvy
447 */
448static void planar422p_to_yuv_packed(const unsigned char *in,
449 unsigned char *out,
450 int width, int height,
451 int fmt)
452{
453 unsigned char *pY;
454 unsigned char *pCb;
455 unsigned char *pCr;
456 unsigned long size = height * width;
457 unsigned int i;
458 pY = (unsigned char *)in;
459 pCr = (unsigned char *)in + height * width;
460 pCb = (unsigned char *)in + height * width + (height * width / 2);
461 for (i = 0; i < size * 2; i += 4) {
462 out[i] = (fmt == V4L2_PIX_FMT_YUYV) ? *pY++ : *pCr++;
463 out[i + 1] = (fmt == V4L2_PIX_FMT_YUYV) ? *pCr++ : *pY++;
464 out[i + 2] = (fmt == V4L2_PIX_FMT_YUYV) ? *pY++ : *pCb++;
465 out[i + 3] = (fmt == V4L2_PIX_FMT_YUYV) ? *pCb++ : *pY++;
466 }
467 return;
468}
469
470
471/* kickstarts the firmware loading. from probe
472 */
473static void s2255_timer(unsigned long user_data)
474{
475 struct s2255_fw *data = (struct s2255_fw *)user_data;
476 dprintk(100, "s2255 timer\n");
477 if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) {
478 printk(KERN_ERR "s2255: can't submit urb\n");
479 if (data->fw) {
480 release_firmware(data->fw);
481 data->fw = NULL;
482 }
483 return;
484 }
485}
486
487/* called when DSP is up and running. DSP is guaranteed to
488 be running after S2255_DSP_BOOTTIME */
489static void s2255_dsp_running(unsigned long user_data)
490{
491 struct s2255_fw *data = (struct s2255_fw *)user_data;
492 dprintk(1, "dsp running\n");
493 atomic_set(&data->fw_state, S2255_FW_SUCCESS);
494 wake_up(&data->wait_fw);
495 printk(KERN_INFO "s2255: firmware loaded successfully\n");
496 return;
497}
498
499
500/* this loads the firmware asynchronously.
501 Originally this was done synchroously in probe.
502 But it is better to load it asynchronously here than block
503 inside the probe function. Blocking inside probe affects boot time.
504 FW loading is triggered by the timer in the probe function
505*/
506static void s2255_fwchunk_complete(struct urb *urb)
507{
508 struct s2255_fw *data = urb->context;
509 struct usb_device *udev = urb->dev;
510 int len;
511 dprintk(100, "udev %p urb %p", udev, urb);
512 /* TODO: fixme. reflect change in status */
513 if (urb->status) {
514 dev_err(&udev->dev, "URB failed with status %d", urb->status);
515 return;
516 }
517 if (data->fw_urb == NULL) {
518 dev_err(&udev->dev, "early disconncect\n");
519 return;
520 }
521#define CHUNK_SIZE 512
522 /* all USB transfers must be done with continuous kernel memory.
523 can't allocate more than 128k in current linux kernel, so
524 upload the firmware in chunks
525 */
526 if (data->fw_loaded < data->fw_size) {
527 len = (data->fw_loaded + CHUNK_SIZE) > data->fw_size ?
528 data->fw_size % CHUNK_SIZE : CHUNK_SIZE;
529
530 if (len < CHUNK_SIZE)
531 memset(data->pfw_data, 0, CHUNK_SIZE);
532
533 dprintk(100, "completed len %d, loaded %d \n", len,
534 data->fw_loaded);
535
536 memcpy(data->pfw_data,
537 (char *) data->fw->data + data->fw_loaded, len);
538
539 usb_fill_bulk_urb(data->fw_urb, udev, usb_sndbulkpipe(udev, 2),
540 data->pfw_data, CHUNK_SIZE,
541 s2255_fwchunk_complete, data);
542 if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) {
543 dev_err(&udev->dev, "failed submit URB\n");
544 atomic_set(&data->fw_state, S2255_FW_FAILED);
545 /* wake up anything waiting for the firmware */
546 wake_up(&data->wait_fw);
547 return;
548 }
549 data->fw_loaded += len;
550 } else {
551 init_timer(&data->dsp_wait);
552 data->dsp_wait.function = s2255_dsp_running;
553 data->dsp_wait.data = (unsigned long)data;
554 atomic_set(&data->fw_state, S2255_FW_LOADED_DSPWAIT);
555 mod_timer(&data->dsp_wait, msecs_to_jiffies(S2255_DSP_BOOTTIME)
556 + jiffies);
557 }
558 dprintk(100, "2255 complete done\n");
559 return;
560
561}
562
563static int s2255_got_frame(struct s2255_dev *dev, int chn)
564{
565 struct s2255_dmaqueue *dma_q = &dev->vidq[chn];
566 struct s2255_buffer *buf;
567 unsigned long flags = 0;
568 int rc = 0;
569 dprintk(2, "wakeup: %p channel: %d\n", &dma_q, chn);
570 spin_lock_irqsave(&dev->slock, flags);
571
572 if (list_empty(&dma_q->active)) {
573 dprintk(1, "No active queue to serve\n");
574 rc = -1;
575 goto unlock;
576 }
577 buf = list_entry(dma_q->active.next,
578 struct s2255_buffer, vb.queue);
579
580 if (!waitqueue_active(&buf->vb.done)) {
581 /* no one active */
582 rc = -1;
583 goto unlock;
584 }
585 list_del(&buf->vb.queue);
586 do_gettimeofday(&buf->vb.ts);
587 dprintk(100, "[%p/%d] wakeup\n", buf, buf->vb.i);
588
589 s2255_fillbuff(dev, buf, dma_q->channel);
590 wake_up(&buf->vb.done);
591 dprintk(2, "wakeup [buf/i] [%p/%d]\n", buf, buf->vb.i);
592unlock:
593 spin_unlock_irqrestore(&dev->slock, flags);
594 return 0;
595}
596
597
598static const struct s2255_fmt *format_by_fourcc(int fourcc)
599{
600 unsigned int i;
601
602 for (i = 0; i < ARRAY_SIZE(formats); i++) {
603 if (-1 == formats[i].fourcc)
604 continue;
605 if (formats[i].fourcc == fourcc)
606 return formats + i;
607 }
608 return NULL;
609}
610
611
612
613
614/* video buffer vmalloc implementation based partly on VIVI driver which is
615 * Copyright (c) 2006 by
616 * Mauro Carvalho Chehab <mchehab--a.t--infradead.org>
617 * Ted Walther <ted--a.t--enumera.com>
618 * John Sokol <sokol--a.t--videotechnology.com>
619 * http://v4l.videotechnology.com/
620 *
621 */
622static void s2255_fillbuff(struct s2255_dev *dev, struct s2255_buffer *buf,
623 int chn)
624{
625 int pos = 0;
626 struct timeval ts;
627 const char *tmpbuf;
628 char *vbuf = videobuf_to_vmalloc(&buf->vb);
629 unsigned long last_frame;
630 struct s2255_framei *frm;
631
632 if (!vbuf)
633 return;
634
635 last_frame = dev->last_frame[chn];
636 if (last_frame != -1) {
637 frm = &dev->buffer[chn].frame[last_frame];
638 tmpbuf =
639 (const char *)dev->buffer[chn].frame[last_frame].lpvbits;
640 switch (buf->fmt->fourcc) {
641 case V4L2_PIX_FMT_YUYV:
642 case V4L2_PIX_FMT_UYVY:
643 planar422p_to_yuv_packed((const unsigned char *)tmpbuf,
644 vbuf, buf->vb.width,
645 buf->vb.height,
646 buf->fmt->fourcc);
647 break;
648 case V4L2_PIX_FMT_GREY:
649 memcpy(vbuf, tmpbuf, buf->vb.width * buf->vb.height);
650 break;
651 case V4L2_PIX_FMT_YUV422P:
652 memcpy(vbuf, tmpbuf,
653 buf->vb.width * buf->vb.height * 2);
654 break;
655 default:
656 printk(KERN_DEBUG "s2255: unknown format?\n");
657 }
658 dev->last_frame[chn] = -1;
659 /* done with the frame, free it */
660 frm->ulState = 0;
661 dprintk(4, "freeing buffer\n");
662 } else {
663 printk(KERN_ERR "s2255: =======no frame\n");
664 return;
665
666 }
667 dprintk(2, "s2255fill at : Buffer 0x%08lx size= %d\n",
668 (unsigned long)vbuf, pos);
669 /* tell v4l buffer was filled */
670
671 buf->vb.field_count++;
672 do_gettimeofday(&ts);
673 buf->vb.ts = ts;
674 buf->vb.state = VIDEOBUF_DONE;
675}
676
677
678/* ------------------------------------------------------------------
679 Videobuf operations
680 ------------------------------------------------------------------*/
681
682static int buffer_setup(struct videobuf_queue *vq, unsigned int *count,
683 unsigned int *size)
684{
685 struct s2255_fh *fh = vq->priv_data;
686
687 *size = fh->width * fh->height * (fh->fmt->depth >> 3);
688
689 if (0 == *count)
690 *count = S2255_DEF_BUFS;
691
692 while (*size * (*count) > vid_limit * 1024 * 1024)
693 (*count)--;
694
695 return 0;
696}
697
698static void free_buffer(struct videobuf_queue *vq, struct s2255_buffer *buf)
699{
700 dprintk(4, "%s\n", __func__);
701
702 videobuf_waiton(&buf->vb, 0, 0);
703 videobuf_vmalloc_free(&buf->vb);
704 buf->vb.state = VIDEOBUF_NEEDS_INIT;
705}
706
707static int buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
708 enum v4l2_field field)
709{
710 struct s2255_fh *fh = vq->priv_data;
711 struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
712 int rc;
713 dprintk(4, "%s, field=%d\n", __func__, field);
714 if (fh->fmt == NULL)
715 return -EINVAL;
716
717 if ((fh->width < norm_minw(fh->dev->vdev[fh->channel])) ||
718 (fh->width > norm_maxw(fh->dev->vdev[fh->channel])) ||
719 (fh->height < norm_minh(fh->dev->vdev[fh->channel])) ||
720 (fh->height > norm_maxh(fh->dev->vdev[fh->channel]))) {
721 dprintk(4, "invalid buffer prepare\n");
722 return -EINVAL;
723 }
724
725 buf->vb.size = fh->width * fh->height * (fh->fmt->depth >> 3);
726
727 if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) {
728 dprintk(4, "invalid buffer prepare\n");
729 return -EINVAL;
730 }
731
732 buf->fmt = fh->fmt;
733 buf->vb.width = fh->width;
734 buf->vb.height = fh->height;
735 buf->vb.field = field;
736
737
738 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
739 rc = videobuf_iolock(vq, &buf->vb, NULL);
740 if (rc < 0)
741 goto fail;
742 }
743
744 buf->vb.state = VIDEOBUF_PREPARED;
745 return 0;
746fail:
747 free_buffer(vq, buf);
748 return rc;
749}
750
751static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
752{
753 struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
754 struct s2255_fh *fh = vq->priv_data;
755 struct s2255_dev *dev = fh->dev;
756 struct s2255_dmaqueue *vidq = &dev->vidq[fh->channel];
757
758 dprintk(1, "%s\n", __func__);
759
760 buf->vb.state = VIDEOBUF_QUEUED;
761 list_add_tail(&buf->vb.queue, &vidq->active);
762}
763
764static void buffer_release(struct videobuf_queue *vq,
765 struct videobuf_buffer *vb)
766{
767 struct s2255_buffer *buf = container_of(vb, struct s2255_buffer, vb);
768 struct s2255_fh *fh = vq->priv_data;
769 dprintk(4, "%s %d\n", __func__, fh->channel);
770 free_buffer(vq, buf);
771}
772
773static struct videobuf_queue_ops s2255_video_qops = {
774 .buf_setup = buffer_setup,
775 .buf_prepare = buffer_prepare,
776 .buf_queue = buffer_queue,
777 .buf_release = buffer_release,
778};
779
780
781static int res_get(struct s2255_dev *dev, struct s2255_fh *fh)
782{
783 /* is it free? */
784 mutex_lock(&dev->lock);
785 if (dev->resources[fh->channel]) {
786 /* no, someone else uses it */
787 mutex_unlock(&dev->lock);
788 return 0;
789 }
790 /* it's free, grab it */
791 dev->resources[fh->channel] = 1;
792 dprintk(1, "res: get\n");
793 mutex_unlock(&dev->lock);
794 return 1;
795}
796
797static int res_locked(struct s2255_dev *dev, struct s2255_fh *fh)
798{
799 return dev->resources[fh->channel];
800}
801
802static void res_free(struct s2255_dev *dev, struct s2255_fh *fh)
803{
804 dev->resources[fh->channel] = 0;
805 dprintk(1, "res: put\n");
806}
807
808
809static int vidioc_querycap(struct file *file, void *priv,
810 struct v4l2_capability *cap)
811{
812 struct s2255_fh *fh = file->private_data;
813 struct s2255_dev *dev = fh->dev;
814 strlcpy(cap->driver, "s2255", sizeof(cap->driver));
815 strlcpy(cap->card, "s2255", sizeof(cap->card));
816 strlcpy(cap->bus_info, dev_name(&dev->udev->dev),
817 sizeof(cap->bus_info));
818 cap->version = S2255_VERSION;
819 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
820 return 0;
821}
822
823static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
824 struct v4l2_fmtdesc *f)
825{
826 int index = 0;
827 if (f)
828 index = f->index;
829
830 if (index >= ARRAY_SIZE(formats))
831 return -EINVAL;
832
833 dprintk(4, "name %s\n", formats[index].name);
834 strlcpy(f->description, formats[index].name, sizeof(f->description));
835 f->pixelformat = formats[index].fourcc;
836 return 0;
837}
838
839static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
840 struct v4l2_format *f)
841{
842 struct s2255_fh *fh = priv;
843
844 f->fmt.pix.width = fh->width;
845 f->fmt.pix.height = fh->height;
846 f->fmt.pix.field = fh->vb_vidq.field;
847 f->fmt.pix.pixelformat = fh->fmt->fourcc;
848 f->fmt.pix.bytesperline = f->fmt.pix.width * (fh->fmt->depth >> 3);
849 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
850 return 0;
851}
852
853static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
854 struct v4l2_format *f)
855{
856 const struct s2255_fmt *fmt;
857 enum v4l2_field field;
858 int b_any_field = 0;
859 struct s2255_fh *fh = priv;
860 struct s2255_dev *dev = fh->dev;
861 int is_ntsc;
862
863 is_ntsc =
864 (dev->vdev[fh->channel]->current_norm & V4L2_STD_NTSC) ? 1 : 0;
865
866 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
867
868 if (fmt == NULL)
869 return -EINVAL;
870
871 field = f->fmt.pix.field;
872 if (field == V4L2_FIELD_ANY)
873 b_any_field = 1;
874
875 dprintk(4, "try format %d \n", is_ntsc);
876 /* supports 3 sizes. see s2255drv.h */
877 dprintk(50, "width test %d, height %d\n",
878 f->fmt.pix.width, f->fmt.pix.height);
879 if (is_ntsc) {
880 /* NTSC */
881 if (f->fmt.pix.height >= NUM_LINES_1CIFS_NTSC * 2) {
882 f->fmt.pix.height = NUM_LINES_1CIFS_NTSC * 2;
883 if (b_any_field) {
884 field = V4L2_FIELD_SEQ_TB;
885 } else if (!((field == V4L2_FIELD_INTERLACED) ||
886 (field == V4L2_FIELD_SEQ_TB) ||
887 (field == V4L2_FIELD_INTERLACED_TB))) {
888 dprintk(1, "unsupported field setting\n");
889 return -EINVAL;
890 }
891 } else {
892 f->fmt.pix.height = NUM_LINES_1CIFS_NTSC;
893 if (b_any_field) {
894 field = V4L2_FIELD_TOP;
895 } else if (!((field == V4L2_FIELD_TOP) ||
896 (field == V4L2_FIELD_BOTTOM))) {
897 dprintk(1, "unsupported field setting\n");
898 return -EINVAL;
899 }
900
901 }
902 if (f->fmt.pix.width >= LINE_SZ_4CIFS_NTSC)
903 f->fmt.pix.width = LINE_SZ_4CIFS_NTSC;
904 else if (f->fmt.pix.width >= LINE_SZ_2CIFS_NTSC)
905 f->fmt.pix.width = LINE_SZ_2CIFS_NTSC;
906 else if (f->fmt.pix.width >= LINE_SZ_1CIFS_NTSC)
907 f->fmt.pix.width = LINE_SZ_1CIFS_NTSC;
908 else
909 f->fmt.pix.width = LINE_SZ_1CIFS_NTSC;
910 } else {
911 /* PAL */
912 if (f->fmt.pix.height >= NUM_LINES_1CIFS_PAL * 2) {
913 f->fmt.pix.height = NUM_LINES_1CIFS_PAL * 2;
914 if (b_any_field) {
915 field = V4L2_FIELD_SEQ_TB;
916 } else if (!((field == V4L2_FIELD_INTERLACED) ||
917 (field == V4L2_FIELD_SEQ_TB) ||
918 (field == V4L2_FIELD_INTERLACED_TB))) {
919 dprintk(1, "unsupported field setting\n");
920 return -EINVAL;
921 }
922 } else {
923 f->fmt.pix.height = NUM_LINES_1CIFS_PAL;
924 if (b_any_field) {
925 field = V4L2_FIELD_TOP;
926 } else if (!((field == V4L2_FIELD_TOP) ||
927 (field == V4L2_FIELD_BOTTOM))) {
928 dprintk(1, "unsupported field setting\n");
929 return -EINVAL;
930 }
931 }
932 if (f->fmt.pix.width >= LINE_SZ_4CIFS_PAL) {
933 dprintk(50, "pal 704\n");
934 f->fmt.pix.width = LINE_SZ_4CIFS_PAL;
935 field = V4L2_FIELD_SEQ_TB;
936 } else if (f->fmt.pix.width >= LINE_SZ_2CIFS_PAL) {
937 dprintk(50, "pal 352A\n");
938 f->fmt.pix.width = LINE_SZ_2CIFS_PAL;
939 field = V4L2_FIELD_TOP;
940 } else if (f->fmt.pix.width >= LINE_SZ_1CIFS_PAL) {
941 dprintk(50, "pal 352B\n");
942 f->fmt.pix.width = LINE_SZ_1CIFS_PAL;
943 field = V4L2_FIELD_TOP;
944 } else {
945 dprintk(50, "pal 352C\n");
946 f->fmt.pix.width = LINE_SZ_1CIFS_PAL;
947 field = V4L2_FIELD_TOP;
948 }
949 }
950
951 dprintk(50, "width %d height %d field %d \n", f->fmt.pix.width,
952 f->fmt.pix.height, f->fmt.pix.field);
953 f->fmt.pix.field = field;
954 f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
955 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
956 return 0;
957}
958
959static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
960 struct v4l2_format *f)
961{
962 struct s2255_fh *fh = priv;
963 const struct s2255_fmt *fmt;
964 struct videobuf_queue *q = &fh->vb_vidq;
965 int ret;
966 int norm;
967
968 ret = vidioc_try_fmt_vid_cap(file, fh, f);
969
970 if (ret < 0)
971 return ret;
972
973 fmt = format_by_fourcc(f->fmt.pix.pixelformat);
974
975 if (fmt == NULL)
976 return -EINVAL;
977
978 mutex_lock(&q->vb_lock);
979
980 if (videobuf_queue_is_busy(&fh->vb_vidq)) {
981 dprintk(1, "queue busy\n");
982 ret = -EBUSY;
983 goto out_s_fmt;
984 }
985
986 if (res_locked(fh->dev, fh)) {
987 dprintk(1, "can't change format after started\n");
988 ret = -EBUSY;
989 goto out_s_fmt;
990 }
991
992 fh->fmt = fmt;
993 fh->width = f->fmt.pix.width;
994 fh->height = f->fmt.pix.height;
995 fh->vb_vidq.field = f->fmt.pix.field;
996 fh->type = f->type;
997 norm = norm_minw(fh->dev->vdev[fh->channel]);
998 if (fh->width > norm_minw(fh->dev->vdev[fh->channel])) {
999 if (fh->height > norm_minh(fh->dev->vdev[fh->channel]))
1000 fh->mode.scale = SCALE_4CIFS;
1001 else
1002 fh->mode.scale = SCALE_2CIFS;
1003
1004 } else {
1005 fh->mode.scale = SCALE_1CIFS;
1006 }
1007
1008 /* color mode */
1009 switch (fh->fmt->fourcc) {
1010 case V4L2_PIX_FMT_GREY:
1011 fh->mode.color = COLOR_Y8;
1012 break;
1013 case V4L2_PIX_FMT_YUV422P:
1014 fh->mode.color = COLOR_YUVPL;
1015 break;
1016 case V4L2_PIX_FMT_YUYV:
1017 case V4L2_PIX_FMT_UYVY:
1018 default:
1019 fh->mode.color = COLOR_YUVPK;
1020 break;
1021 }
1022 ret = 0;
1023out_s_fmt:
1024 mutex_unlock(&q->vb_lock);
1025 return ret;
1026}
1027
1028static int vidioc_reqbufs(struct file *file, void *priv,
1029 struct v4l2_requestbuffers *p)
1030{
1031 int rc;
1032 struct s2255_fh *fh = priv;
1033 rc = videobuf_reqbufs(&fh->vb_vidq, p);
1034 return rc;
1035}
1036
1037static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
1038{
1039 int rc;
1040 struct s2255_fh *fh = priv;
1041 rc = videobuf_querybuf(&fh->vb_vidq, p);
1042 return rc;
1043}
1044
1045static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
1046{
1047 int rc;
1048 struct s2255_fh *fh = priv;
1049 rc = videobuf_qbuf(&fh->vb_vidq, p);
1050 return rc;
1051}
1052
1053static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
1054{
1055 int rc;
1056 struct s2255_fh *fh = priv;
1057 rc = videobuf_dqbuf(&fh->vb_vidq, p, file->f_flags & O_NONBLOCK);
1058 return rc;
1059}
1060
1061#ifdef CONFIG_VIDEO_V4L1_COMPAT
1062static int vidioc_cgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
1063{
1064 struct s2255_fh *fh = priv;
1065
1066 return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
1067}
1068#endif
1069
1070/* write to the configuration pipe, synchronously */
1071static int s2255_write_config(struct usb_device *udev, unsigned char *pbuf,
1072 int size)
1073{
1074 int pipe;
1075 int done;
1076 long retval = -1;
1077 if (udev) {
1078 pipe = usb_sndbulkpipe(udev, S2255_CONFIG_EP);
1079 retval = usb_bulk_msg(udev, pipe, pbuf, size, &done, 500);
1080 }
1081 return retval;
1082}
1083
1084static u32 get_transfer_size(struct s2255_mode *mode)
1085{
1086 int linesPerFrame = LINE_SZ_DEF;
1087 int pixelsPerLine = NUM_LINES_DEF;
1088 u32 outImageSize;
1089 u32 usbInSize;
1090 unsigned int mask_mult;
1091
1092 if (mode == NULL)
1093 return 0;
1094
1095 if (mode->format == FORMAT_NTSC) {
1096 switch (mode->scale) {
1097 case SCALE_4CIFS:
1098 linesPerFrame = NUM_LINES_4CIFS_NTSC * 2;
1099 pixelsPerLine = LINE_SZ_4CIFS_NTSC;
1100 break;
1101 case SCALE_2CIFS:
1102 linesPerFrame = NUM_LINES_2CIFS_NTSC;
1103 pixelsPerLine = LINE_SZ_2CIFS_NTSC;
1104 break;
1105 case SCALE_1CIFS:
1106 linesPerFrame = NUM_LINES_1CIFS_NTSC;
1107 pixelsPerLine = LINE_SZ_1CIFS_NTSC;
1108 break;
1109 default:
1110 break;
1111 }
1112 } else if (mode->format == FORMAT_PAL) {
1113 switch (mode->scale) {
1114 case SCALE_4CIFS:
1115 linesPerFrame = NUM_LINES_4CIFS_PAL * 2;
1116 pixelsPerLine = LINE_SZ_4CIFS_PAL;
1117 break;
1118 case SCALE_2CIFS:
1119 linesPerFrame = NUM_LINES_2CIFS_PAL;
1120 pixelsPerLine = LINE_SZ_2CIFS_PAL;
1121 break;
1122 case SCALE_1CIFS:
1123 linesPerFrame = NUM_LINES_1CIFS_PAL;
1124 pixelsPerLine = LINE_SZ_1CIFS_PAL;
1125 break;
1126 default:
1127 break;
1128 }
1129 }
1130 outImageSize = linesPerFrame * pixelsPerLine;
1131 if (mode->color != COLOR_Y8) {
1132 /* 2 bytes/pixel if not monochrome */
1133 outImageSize *= 2;
1134 }
1135
1136 /* total bytes to send including prefix and 4K padding;
1137 must be a multiple of USB_READ_SIZE */
1138 usbInSize = outImageSize + PREFIX_SIZE; /* always send prefix */
1139 mask_mult = 0xffffffffUL - DEF_USB_BLOCK + 1;
1140 /* if size not a multiple of USB_READ_SIZE */
1141 if (usbInSize & ~mask_mult)
1142 usbInSize = (usbInSize & mask_mult) + (DEF_USB_BLOCK);
1143 return usbInSize;
1144}
1145
1146static void dump_verify_mode(struct s2255_dev *sdev, struct s2255_mode *mode)
1147{
1148 struct device *dev = &sdev->udev->dev;
1149 dev_info(dev, "------------------------------------------------\n");
1150 dev_info(dev, "verify mode\n");
1151 dev_info(dev, "format: %d\n", mode->format);
1152 dev_info(dev, "scale: %d\n", mode->scale);
1153 dev_info(dev, "fdec: %d\n", mode->fdec);
1154 dev_info(dev, "color: %d\n", mode->color);
1155 dev_info(dev, "bright: 0x%x\n", mode->bright);
1156 dev_info(dev, "restart: 0x%x\n", mode->restart);
1157 dev_info(dev, "usb_block: 0x%x\n", mode->usb_block);
1158 dev_info(dev, "single: 0x%x\n", mode->single);
1159 dev_info(dev, "------------------------------------------------\n");
1160}
1161
1162/*
1163 * set mode is the function which controls the DSP.
1164 * the restart parameter in struct s2255_mode should be set whenever
1165 * the image size could change via color format, video system or image
1166 * size.
1167 * When the restart parameter is set, we sleep for ONE frame to allow the
1168 * DSP time to get the new frame
1169 */
1170static int s2255_set_mode(struct s2255_dev *dev, unsigned long chn,
1171 struct s2255_mode *mode)
1172{
1173 int res;
1174 u32 *buffer;
1175 unsigned long chn_rev;
1176
1177 chn_rev = G_chnmap[chn];
1178 dprintk(3, "mode scale [%ld] %p %d\n", chn, mode, mode->scale);
1179 dprintk(3, "mode scale [%ld] %p %d\n", chn, &dev->mode[chn],
1180 dev->mode[chn].scale);
1181 dprintk(2, "mode contrast %x\n", mode->contrast);
1182
1183 /* save the mode */
1184 dev->mode[chn] = *mode;
1185 dev->req_image_size[chn] = get_transfer_size(mode);
1186 dprintk(1, "transfer size %ld\n", dev->req_image_size[chn]);
1187
1188 buffer = kzalloc(512, GFP_KERNEL);
1189 if (buffer == NULL) {
1190 dev_err(&dev->udev->dev, "out of mem\n");
1191 return -ENOMEM;
1192 }
1193
1194 /* set the mode */
1195 buffer[0] = IN_DATA_TOKEN;
1196 buffer[1] = (u32) chn_rev;
1197 buffer[2] = CMD_SET_MODE;
1198 memcpy(&buffer[3], &dev->mode[chn], sizeof(struct s2255_mode));
1199 res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
1200 if (debug)
1201 dump_verify_mode(dev, mode);
1202 kfree(buffer);
1203 dprintk(1, "set mode done chn %lu, %d\n", chn, res);
1204
1205 /* wait at least 3 frames before continuing */
1206 if (mode->restart)
1207 msleep(125);
1208
1209 /* clear the restart flag */
1210 dev->mode[chn].restart = 0;
1211
1212 return res;
1213}
1214
1215static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
1216{
1217 int res;
1218 struct s2255_fh *fh = priv;
1219 struct s2255_dev *dev = fh->dev;
1220 struct s2255_mode *new_mode;
1221 struct s2255_mode *old_mode;
1222 int chn;
1223 int j;
1224 dprintk(4, "%s\n", __func__);
1225 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1226 dev_err(&dev->udev->dev, "invalid fh type0\n");
1227 return -EINVAL;
1228 }
1229 if (i != fh->type) {
1230 dev_err(&dev->udev->dev, "invalid fh type1\n");
1231 return -EINVAL;
1232 }
1233
1234 if (!res_get(dev, fh)) {
1235 dev_err(&dev->udev->dev, "res get busy\n");
1236 return -EBUSY;
1237 }
1238
1239 /* send a set mode command everytime with restart.
1240 in case we switch resolutions or other parameters */
1241 chn = fh->channel;
1242 new_mode = &fh->mode;
1243 old_mode = &fh->dev->mode[chn];
1244
1245 if (new_mode->color != old_mode->color)
1246 new_mode->restart = 1;
1247 else if (new_mode->scale != old_mode->scale)
1248 new_mode->restart = 1;
1249 else if (new_mode->format != old_mode->format)
1250 new_mode->restart = 1;
1251
1252 s2255_set_mode(dev, chn, new_mode);
1253 new_mode->restart = 0;
1254 *old_mode = *new_mode;
1255 dev->cur_fmt[chn] = fh->fmt;
1256 dprintk(1, "%s[%d]\n", __func__, chn);
1257 dev->last_frame[chn] = -1;
1258 dev->bad_payload[chn] = 0;
1259 dev->cur_frame[chn] = 0;
1260 for (j = 0; j < SYS_FRAMES; j++) {
1261 dev->buffer[chn].frame[j].ulState = 0;
1262 dev->buffer[chn].frame[j].cur_size = 0;
1263 }
1264 res = videobuf_streamon(&fh->vb_vidq);
1265 if (res == 0) {
1266 s2255_start_acquire(dev, chn);
1267 dev->b_acquire[chn] = 1;
1268 } else {
1269 res_free(dev, fh);
1270 }
1271 return res;
1272}
1273
1274static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
1275{
1276 int res;
1277 struct s2255_fh *fh = priv;
1278 struct s2255_dev *dev = fh->dev;
1279
1280 dprintk(4, "%s\n, channel: %d", __func__, fh->channel);
1281 if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1282 printk(KERN_ERR "invalid fh type0\n");
1283 return -EINVAL;
1284 }
1285 if (i != fh->type) {
1286 printk(KERN_ERR "invalid type i\n");
1287 return -EINVAL;
1288 }
1289 s2255_stop_acquire(dev, fh->channel);
1290 res = videobuf_streamoff(&fh->vb_vidq);
1291 res_free(dev, fh);
1292 return res;
1293}
1294
1295static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
1296{
1297 struct s2255_fh *fh = priv;
1298 struct s2255_mode *mode;
1299 struct videobuf_queue *q = &fh->vb_vidq;
1300 int ret = 0;
1301
1302 mutex_lock(&q->vb_lock);
1303 if (videobuf_queue_is_busy(q)) {
1304 dprintk(1, "queue busy\n");
1305 ret = -EBUSY;
1306 goto out_s_std;
1307 }
1308
1309 if (res_locked(fh->dev, fh)) {
1310 dprintk(1, "can't change standard after started\n");
1311 ret = -EBUSY;
1312 goto out_s_std;
1313 }
1314 mode = &fh->mode;
1315
1316 if (*i & V4L2_STD_NTSC) {
1317 dprintk(4, "vidioc_s_std NTSC\n");
1318 mode->format = FORMAT_NTSC;
1319 } else if (*i & V4L2_STD_PAL) {
1320 dprintk(4, "vidioc_s_std PAL\n");
1321 mode->format = FORMAT_PAL;
1322 } else {
1323 ret = -EINVAL;
1324 }
1325out_s_std:
1326 mutex_unlock(&q->vb_lock);
1327 return ret;
1328}
1329
1330/* Sensoray 2255 is a multiple channel capture device.
1331 It does not have a "crossbar" of inputs.
1332 We use one V4L device per channel. The user must
1333 be aware that certain combinations are not allowed.
1334 For instance, you cannot do full FPS on more than 2 channels(2 videodevs)
1335 at once in color(you can do full fps on 4 channels with greyscale.
1336*/
1337static int vidioc_enum_input(struct file *file, void *priv,
1338 struct v4l2_input *inp)
1339{
1340 if (inp->index != 0)
1341 return -EINVAL;
1342
1343 inp->type = V4L2_INPUT_TYPE_CAMERA;
1344 inp->std = S2255_NORMS;
1345 strlcpy(inp->name, "Camera", sizeof(inp->name));
1346 return 0;
1347}
1348
1349static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
1350{
1351 *i = 0;
1352 return 0;
1353}
1354static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
1355{
1356 if (i > 0)
1357 return -EINVAL;
1358 return 0;
1359}
1360
1361/* --- controls ---------------------------------------------- */
1362static int vidioc_queryctrl(struct file *file, void *priv,
1363 struct v4l2_queryctrl *qc)
1364{
1365 int i;
1366
1367 for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++)
1368 if (qc->id && qc->id == s2255_qctrl[i].id) {
1369 memcpy(qc, &(s2255_qctrl[i]), sizeof(*qc));
1370 return 0;
1371 }
1372
1373 dprintk(4, "query_ctrl -EINVAL %d\n", qc->id);
1374 return -EINVAL;
1375}
1376
1377static int vidioc_g_ctrl(struct file *file, void *priv,
1378 struct v4l2_control *ctrl)
1379{
1380 int i;
1381
1382 for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++)
1383 if (ctrl->id == s2255_qctrl[i].id) {
1384 ctrl->value = qctl_regs[i];
1385 return 0;
1386 }
1387 dprintk(4, "g_ctrl -EINVAL\n");
1388
1389 return -EINVAL;
1390}
1391
1392static int vidioc_s_ctrl(struct file *file, void *priv,
1393 struct v4l2_control *ctrl)
1394{
1395 int i;
1396 struct s2255_fh *fh = priv;
1397 struct s2255_dev *dev = fh->dev;
1398 struct s2255_mode *mode;
1399 mode = &fh->mode;
1400 dprintk(4, "vidioc_s_ctrl\n");
1401 for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++) {
1402 if (ctrl->id == s2255_qctrl[i].id) {
1403 if (ctrl->value < s2255_qctrl[i].minimum ||
1404 ctrl->value > s2255_qctrl[i].maximum)
1405 return -ERANGE;
1406
1407 qctl_regs[i] = ctrl->value;
1408 /* update the mode to the corresponding value */
1409 switch (ctrl->id) {
1410 case V4L2_CID_BRIGHTNESS:
1411 mode->bright = ctrl->value;
1412 break;
1413 case V4L2_CID_CONTRAST:
1414 mode->contrast = ctrl->value;
1415 break;
1416 case V4L2_CID_HUE:
1417 mode->hue = ctrl->value;
1418 break;
1419 case V4L2_CID_SATURATION:
1420 mode->saturation = ctrl->value;
1421 break;
1422 }
1423 mode->restart = 0;
1424 /* set mode here. Note: stream does not need restarted.
1425 some V4L programs restart stream unnecessarily
1426 after a s_crtl.
1427 */
1428 s2255_set_mode(dev, fh->channel, mode);
1429 return 0;
1430 }
1431 }
1432 return -EINVAL;
1433}
1434
1435static int s2255_open(struct inode *inode, struct file *file)
1436{
1437 int minor = iminor(inode);
1438 struct s2255_dev *h, *dev = NULL;
1439 struct s2255_fh *fh;
1440 struct list_head *list;
1441 enum v4l2_buf_type type = 0;
1442 int i = 0;
1443 int cur_channel = -1;
1444 dprintk(1, "s2255: open called (minor=%d)\n", minor);
1445
1446 list_for_each(list, &s2255_devlist) {
1447 h = list_entry(list, struct s2255_dev, s2255_devlist);
1448 for (i = 0; i < MAX_CHANNELS; i++) {
1449 if (h->vdev[i]->minor == minor) {
1450 cur_channel = i;
1451 dev = h;
1452 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1453 }
1454 }
1455 }
1456
1457 if ((NULL == dev) || (cur_channel == -1)) {
1458 dprintk(1, "s2255: openv4l no dev\n");
1459 return -ENODEV;
1460 }
1461
1462 mutex_lock(&dev->open_lock);
1463
1464 dev->users[cur_channel]++;
1465 if (dev->users[cur_channel] > S2255_MAX_USERS) {
1466 dev->users[cur_channel]--;
1467 mutex_unlock(&dev->open_lock);
1468 printk(KERN_INFO "s2255drv: too many open handles!\n");
1469 return -EBUSY;
1470 }
1471
1472 if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) {
1473 err("2255 firmware load failed. retrying.\n");
1474 s2255_fwload_start(dev);
1475 wait_event_timeout(dev->fw_data->wait_fw,
1476 (atomic_read(&dev->fw_data->fw_state)
1477 != S2255_FW_NOTLOADED),
1478 msecs_to_jiffies(S2255_LOAD_TIMEOUT));
1479 if (atomic_read(&dev->fw_data->fw_state)
1480 != S2255_FW_SUCCESS) {
1481 printk(KERN_INFO "2255 FW load failed after 2 tries\n");
1482 mutex_unlock(&dev->open_lock);
1483 return -EFAULT;
1484 }
1485 } else if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_NOTLOADED) {
1486 /* give S2255_LOAD_TIMEOUT time for firmware to load in case
1487 driver loaded and then device immediately opened */
1488 printk(KERN_INFO "%s waiting for firmware load\n", __func__);
1489 wait_event_timeout(dev->fw_data->wait_fw,
1490 (atomic_read(&dev->fw_data->fw_state)
1491 != S2255_FW_NOTLOADED),
1492 msecs_to_jiffies(S2255_LOAD_TIMEOUT));
1493 if (atomic_read(&dev->fw_data->fw_state)
1494 != S2255_FW_SUCCESS) {
1495 printk(KERN_INFO "2255 firmware not loaded"
1496 "try again\n");
1497 mutex_unlock(&dev->open_lock);
1498 return -EBUSY;
1499 }
1500 }
1501
1502 /* allocate + initialize per filehandle data */
1503 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
1504 if (NULL == fh) {
1505 mutex_unlock(&dev->open_lock);
1506 return -ENOMEM;
1507 }
1508
1509 file->private_data = fh;
1510 fh->dev = dev;
1511 fh->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1512 fh->mode = dev->mode[cur_channel];
1513 fh->fmt = dev->cur_fmt[cur_channel];
1514 /* default 4CIF NTSC */
1515 fh->width = LINE_SZ_4CIFS_NTSC;
1516 fh->height = NUM_LINES_4CIFS_NTSC * 2;
1517 fh->channel = cur_channel;
1518
1519 /* Put all controls at a sane state */
1520 for (i = 0; i < ARRAY_SIZE(s2255_qctrl); i++)
1521 qctl_regs[i] = s2255_qctrl[i].default_value;
1522
1523 dprintk(1, "s2255drv: open minor=%d type=%s users=%d\n",
1524 minor, v4l2_type_names[type], dev->users[cur_channel]);
1525 dprintk(2, "s2255drv: open: fh=0x%08lx, dev=0x%08lx, vidq=0x%08lx\n",
1526 (unsigned long)fh, (unsigned long)dev,
1527 (unsigned long)&dev->vidq[cur_channel]);
1528 dprintk(4, "s2255drv: open: list_empty active=%d\n",
1529 list_empty(&dev->vidq[cur_channel].active));
1530
1531 videobuf_queue_vmalloc_init(&fh->vb_vidq, &s2255_video_qops,
1532 NULL, &dev->slock,
1533 fh->type,
1534 V4L2_FIELD_INTERLACED,
1535 sizeof(struct s2255_buffer), fh);
1536
1537 kref_get(&dev->kref);
1538 mutex_unlock(&dev->open_lock);
1539 return 0;
1540}
1541
1542
1543static unsigned int s2255_poll(struct file *file,
1544 struct poll_table_struct *wait)
1545{
1546 struct s2255_fh *fh = file->private_data;
1547 int rc;
1548 dprintk(100, "%s\n", __func__);
1549
1550 if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
1551 return POLLERR;
1552
1553 rc = videobuf_poll_stream(file, &fh->vb_vidq, wait);
1554 return rc;
1555}
1556
1557static void s2255_destroy(struct kref *kref)
1558{
1559 struct s2255_dev *dev = to_s2255_dev(kref);
1560 if (!dev) {
1561 printk(KERN_ERR "s2255drv: kref problem\n");
1562 return;
1563 }
1564 /* prevent s2255_disconnect from racing s2255_open */
1565 mutex_lock(&dev->open_lock);
1566 s2255_exit_v4l(dev);
1567 /* device unregistered so no longer possible to open. open_mutex
1568 can be unlocked */
1569 mutex_unlock(&dev->open_lock);
1570
1571 /* board shutdown stops the read pipe if it is running */
1572 s2255_board_shutdown(dev);
1573
1574 /* make sure firmware still not trying to load */
1575 if (dev->fw_data->fw_urb) {
1576 dprintk(2, "kill fw_urb\n");
1577 usb_kill_urb(dev->fw_data->fw_urb);
1578 usb_free_urb(dev->fw_data->fw_urb);
1579 dev->fw_data->fw_urb = NULL;
1580 }
1581 /*
1582 * TODO: fixme(above, below): potentially leaving timers alive.
1583 * do not ignore timeout below if
1584 * it occurs.
1585 */
1586
1587 /* make sure we aren't waiting for the DSP */
1588 if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_LOADED_DSPWAIT) {
1589 /* if we are, wait for the wakeup for fw_success or timeout */
1590 wait_event_timeout(dev->fw_data->wait_fw,
1591 (atomic_read(&dev->fw_data->fw_state)
1592 == S2255_FW_SUCCESS),
1593 msecs_to_jiffies(S2255_LOAD_TIMEOUT));
1594 }
1595
1596 if (dev->fw_data) {
1597 if (dev->fw_data->fw)
1598 release_firmware(dev->fw_data->fw);
1599 kfree(dev->fw_data->pfw_data);
1600 kfree(dev->fw_data);
1601 }
1602
1603 usb_put_dev(dev->udev);
1604 dprintk(1, "%s", __func__);
1605 kfree(dev);
1606}
1607
1608static int s2255_close(struct inode *inode, struct file *file)
1609{
1610 struct s2255_fh *fh = file->private_data;
1611 struct s2255_dev *dev = fh->dev;
1612 int minor = iminor(inode);
1613 if (!dev)
1614 return -ENODEV;
1615
1616 mutex_lock(&dev->open_lock);
1617
1618 if (dev->b_acquire[fh->channel])
1619 s2255_stop_acquire(dev, fh->channel);
1620 res_free(dev, fh);
1621 videobuf_mmap_free(&fh->vb_vidq);
1622 kfree(fh);
1623 dev->users[fh->channel]--;
1624 mutex_unlock(&dev->open_lock);
1625
1626 kref_put(&dev->kref, s2255_destroy);
1627 dprintk(1, "s2255: close called (minor=%d, users=%d)\n",
1628 minor, dev->users[fh->channel]);
1629 return 0;
1630}
1631
1632static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma)
1633{
1634 struct s2255_fh *fh = file->private_data;
1635 int ret;
1636
1637 if (!fh)
1638 return -ENODEV;
1639 dprintk(4, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
1640
1641 ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
1642
1643 dprintk(4, "vma start=0x%08lx, size=%ld, ret=%d\n",
1644 (unsigned long)vma->vm_start,
1645 (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
1646
1647 return ret;
1648}
1649
1650static const struct file_operations s2255_fops_v4l = {
1651 .owner = THIS_MODULE,
1652 .open = s2255_open,
1653 .release = s2255_close,
1654 .poll = s2255_poll,
1655 .ioctl = video_ioctl2, /* V4L2 ioctl handler */
1656 .compat_ioctl = v4l_compat_ioctl32,
1657 .mmap = s2255_mmap_v4l,
1658 .llseek = no_llseek,
1659};
1660
1661static struct video_device template = {
1662 .name = "s2255v",
1663 .type = VID_TYPE_CAPTURE,
1664 .fops = &s2255_fops_v4l,
1665 .minor = -1,
1666 .release = video_device_release,
1667 .vidioc_querycap = vidioc_querycap,
1668 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1669 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1670 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1671 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1672 .vidioc_reqbufs = vidioc_reqbufs,
1673 .vidioc_querybuf = vidioc_querybuf,
1674 .vidioc_qbuf = vidioc_qbuf,
1675 .vidioc_dqbuf = vidioc_dqbuf,
1676 .vidioc_s_std = vidioc_s_std,
1677 .vidioc_enum_input = vidioc_enum_input,
1678 .vidioc_g_input = vidioc_g_input,
1679 .vidioc_s_input = vidioc_s_input,
1680 .vidioc_queryctrl = vidioc_queryctrl,
1681 .vidioc_g_ctrl = vidioc_g_ctrl,
1682 .vidioc_s_ctrl = vidioc_s_ctrl,
1683 .vidioc_streamon = vidioc_streamon,
1684 .vidioc_streamoff = vidioc_streamoff,
1685#ifdef CONFIG_VIDEO_V4L1_COMPAT
1686 .vidiocgmbuf = vidioc_cgmbuf,
1687#endif
1688 .tvnorms = S2255_NORMS,
1689 .current_norm = V4L2_STD_NTSC_M,
1690};
1691
1692static int s2255_probe_v4l(struct s2255_dev *dev)
1693{
1694 int ret;
1695 int i;
1696 int cur_nr = video_nr;
1697
1698 /* initialize all video 4 linux */
1699 list_add_tail(&dev->s2255_devlist, &s2255_devlist);
1700 /* register 4 video devices */
1701 for (i = 0; i < MAX_CHANNELS; i++) {
1702 INIT_LIST_HEAD(&dev->vidq[i].active);
1703 dev->vidq[i].dev = dev;
1704 dev->vidq[i].channel = i;
1705 dev->vidq[i].kthread = NULL;
1706 /* register 4 video devices */
1707 dev->vdev[i] = video_device_alloc();
1708 memcpy(dev->vdev[i], &template, sizeof(struct video_device));
1709 dev->vdev[i]->dev = &dev->interface->dev;
1710 if (video_nr == -1)
1711 ret = video_register_device(dev->vdev[i],
1712 VFL_TYPE_GRABBER,
1713 video_nr);
1714 else
1715 ret = video_register_device(dev->vdev[i],
1716 VFL_TYPE_GRABBER,
1717 cur_nr + i);
1718 dev->vdev[i]->priv = dev;
1719
1720 if (ret != 0) {
1721 dev_err(&dev->udev->dev,
1722 "failed to register video device!\n");
1723 return ret;
1724 }
1725 }
1726 printk(KERN_INFO "Sensoray 2255 V4L driver\n");
1727 return ret;
1728}
1729
1730static void s2255_exit_v4l(struct s2255_dev *dev)
1731{
1732 struct list_head *list;
1733 int i;
1734 /* unregister the video devices */
1735 while (!list_empty(&s2255_devlist)) {
1736 list = s2255_devlist.next;
1737 list_del(list);
1738 }
1739 for (i = 0; i < MAX_CHANNELS; i++) {
1740 if (-1 != dev->vdev[i]->minor)
1741 video_unregister_device(dev->vdev[i]);
1742 else
1743 video_device_release(dev->vdev[i]);
1744 }
1745}
1746
1747/* this function moves the usb stream read pipe data
1748 * into the system buffers.
1749 * returns 0 on success, EAGAIN if more data to process( call this
1750 * function again).
1751 *
1752 * Received frame structure:
1753 * bytes 0-3: marker : 0x2255DA4AL (FRAME_MARKER)
1754 * bytes 4-7: channel: 0-3
1755 * bytes 8-11: payload size: size of the frame
1756 * bytes 12-payloadsize+12: frame data
1757 */
1758static int save_frame(struct s2255_dev *dev, struct s2255_pipeinfo *pipe_info)
1759{
1760 static int dbgsync; /* = 0; */
1761 char *pdest;
1762 u32 offset = 0;
1763 int bsync = 0;
1764 int btrunc = 0;
1765 char *psrc;
1766 unsigned long copy_size;
1767 unsigned long size;
1768 s32 idx = -1;
1769 struct s2255_framei *frm;
1770 unsigned char *pdata;
1771 unsigned long cur_size;
1772 int bsearch = 0;
1773 struct s2255_bufferi *buf;
1774 dprintk(100, "buffer to user\n");
1775
1776 idx = dev->cur_frame[dev->cc];
1777 buf = &dev->buffer[dev->cc];
1778 frm = &buf->frame[idx];
1779
1780 if (frm->ulState == 0) {
1781 frm->ulState = 1;
1782 frm->cur_size = 0;
1783 bsearch = 1;
1784 } else if (frm->ulState == 2) {
1785 /* system frame was not freed */
1786 dprintk(2, "sys frame not free. overrun ringbuf\n");
1787 bsearch = 1;
1788 frm->ulState = 1;
1789 frm->cur_size = 0;
1790 }
1791
1792 if (bsearch) {
1793 if (*(s32 *) pipe_info->transfer_buffer != FRAME_MARKER) {
1794 u32 jj;
1795 if (dbgsync == 0) {
1796 dprintk(3, "not synched, discarding all packets"
1797 "until marker\n");
1798
1799 dbgsync++;
1800 }
1801 pdata = (unsigned char *)pipe_info->transfer_buffer;
1802 for (jj = 0; jj < (pipe_info->cur_transfer_size - 12);
1803 jj++) {
1804 if (*(s32 *) pdata == FRAME_MARKER) {
1805 int cc;
1806 dprintk(3,
1807 "found frame marker at offset:"
1808 " %d [%x %x]\n", jj, pdata[0],
1809 pdata[1]);
1810 offset = jj;
1811 bsync = 1;
1812 cc = *(u32 *) (pdata + sizeof(u32));
1813 if (cc >= MAX_CHANNELS) {
1814 printk(KERN_ERR
1815 "bad channel\n");
1816 return -EINVAL;
1817 }
1818 /* reverse it */
1819 dev->cc = G_chnmap[cc];
1820 break;
1821 }
1822 pdata++;
1823 }
1824 if (bsync == 0)
1825 return -EINVAL;
1826 } else {
1827 u32 *pword;
1828 u32 payload;
1829 int cc;
1830 dbgsync = 0;
1831 bsync = 1;
1832 pword = (u32 *) pipe_info->transfer_buffer;
1833 cc = pword[1];
1834
1835 if (cc >= MAX_CHANNELS) {
1836 printk("invalid channel found. "
1837 "throwing out data!\n");
1838 return -EINVAL;
1839 }
1840 dev->cc = G_chnmap[cc];
1841 payload = pword[2];
1842 if (payload != dev->req_image_size[dev->cc]) {
1843 dprintk(1, "[%d][%d]unexpected payload: %d"
1844 "required: %lu \n", cc, dev->cc,
1845 payload, dev->req_image_size[dev->cc]);
1846 dev->bad_payload[dev->cc]++;
1847 /* discard the bad frame */
1848 return -EINVAL;
1849 }
1850
1851 }
1852 }
1853 /* search done. now find out if should be acquiring
1854 on this channel */
1855 if (!dev->b_acquire[dev->cc]) {
1856 frm->ulState = 0;
1857 return -EINVAL;
1858 }
1859
1860 idx = dev->cur_frame[dev->cc];
1861 frm = &dev->buffer[dev->cc].frame[idx];
1862
1863 if (frm->ulState == 0) {
1864 frm->ulState = 1;
1865 frm->cur_size = 0;
1866 } else if (frm->ulState == 2) {
1867 /* system frame ring buffer overrun */
1868 dprintk(2, "sys frame overrun. overwriting frame %d %d\n",
1869 dev->cc, idx);
1870 frm->ulState = 1;
1871 frm->cur_size = 0;
1872 }
1873
1874 if (bsync) {
1875 /* skip the marker 512 bytes (and offset if out of sync) */
1876 psrc = (u8 *)pipe_info->transfer_buffer + offset + PREFIX_SIZE;
1877 } else {
1878 psrc = (u8 *)pipe_info->transfer_buffer;
1879 }
1880
1881 if (frm->lpvbits == NULL) {
1882 dprintk(1, "s2255 frame buffer == NULL.%p %p %d %d",
1883 frm, dev, dev->cc, idx);
1884 return -ENOMEM;
1885 }
1886
1887 pdest = frm->lpvbits + frm->cur_size;
1888
1889 if (bsync) {
1890 copy_size =
1891 (pipe_info->cur_transfer_size - offset) - PREFIX_SIZE;
1892 if (copy_size > pipe_info->cur_transfer_size) {
1893 printk("invalid copy size, overflow!\n");
1894 return -ENOMEM;
1895 }
1896 } else {
1897 copy_size = pipe_info->cur_transfer_size;
1898 }
1899
1900 cur_size = frm->cur_size;
1901 size = dev->req_image_size[dev->cc];
1902
1903 if ((copy_size + cur_size) > size) {
1904 copy_size = size - cur_size;
1905 btrunc = 1;
1906 }
1907
1908 memcpy(pdest, psrc, copy_size);
1909 cur_size += copy_size;
1910 frm->cur_size += copy_size;
1911 dprintk(50, "cur_size size %lu size %lu \n", cur_size, size);
1912
1913 if (cur_size >= (size - PREFIX_SIZE)) {
1914 u32 cc = dev->cc;
1915 frm->ulState = 2;
1916 dprintk(2, "****************[%d]Buffer[%d]full*************\n",
1917 cc, idx);
1918 dev->last_frame[cc] = dev->cur_frame[cc];
1919 dev->cur_frame[cc]++;
1920 /* end of system frame ring buffer, start at zero */
1921 if ((dev->cur_frame[cc] == SYS_FRAMES) ||
1922 (dev->cur_frame[cc] == dev->buffer[cc].dwFrames))
1923 dev->cur_frame[cc] = 0;
1924
1925 /* signal the semaphore for this channel */
1926 if (dev->b_acquire[cc])
1927 s2255_got_frame(dev, cc);
1928 dev->frame_count[cc]++;
1929 }
1930 /* frame was truncated */
1931 if (btrunc) {
1932 /* return more data to process */
1933 return EAGAIN;
1934 }
1935 /* done successfully */
1936 return 0;
1937}
1938
1939static void s2255_read_video_callback(struct s2255_dev *dev,
1940 struct s2255_pipeinfo *pipe_info)
1941{
1942 int res;
1943 dprintk(50, "callback read video \n");
1944
1945 if (dev->cc >= MAX_CHANNELS) {
1946 dev->cc = 0;
1947 dev_err(&dev->udev->dev, "invalid channel\n");
1948 return;
1949 }
1950 /* otherwise copy to the system buffers */
1951 res = save_frame(dev, pipe_info);
1952 if (res == EAGAIN)
1953 save_frame(dev, pipe_info);
1954
1955 dprintk(50, "callback read video done\n");
1956 return;
1957}
1958
1959static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request,
1960 u16 Index, u16 Value, void *TransferBuffer,
1961 s32 TransferBufferLength, int bOut)
1962{
1963 int r;
1964 if (!bOut) {
1965 r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
1966 Request,
1967 USB_TYPE_VENDOR | USB_RECIP_DEVICE |
1968 USB_DIR_IN,
1969 Value, Index, TransferBuffer,
1970 TransferBufferLength, HZ * 5);
1971 } else {
1972 r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
1973 Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1974 Value, Index, TransferBuffer,
1975 TransferBufferLength, HZ * 5);
1976 }
1977 return r;
1978}
1979
1980/*
1981 * retrieve FX2 firmware version. future use.
1982 * @param dev pointer to device extension
1983 * @return -1 for fail, else returns firmware version as an int(16 bits)
1984 */
1985static int s2255_get_fx2fw(struct s2255_dev *dev)
1986{
1987 int fw;
1988 int ret;
1989 unsigned char transBuffer[64];
1990 ret = s2255_vendor_req(dev, S2255_VR_FW, 0, 0, transBuffer, 2,
1991 S2255_VR_IN);
1992 if (ret < 0)
1993 dprintk(2, "get fw error: %x\n", ret);
1994 fw = transBuffer[0] + (transBuffer[1] << 8);
1995 dprintk(2, "Get FW %x %x\n", transBuffer[0], transBuffer[1]);
1996 return fw;
1997}
1998
1999/*
2000 * Create the system ring buffer to copy frames into from the
2001 * usb read pipe.
2002 */
2003static int s2255_create_sys_buffers(struct s2255_dev *dev, unsigned long chn)
2004{
2005 unsigned long i;
2006 unsigned long reqsize;
2007 dprintk(1, "create sys buffers\n");
2008 if (chn >= MAX_CHANNELS)
2009 return -1;
2010
2011 dev->buffer[chn].dwFrames = SYS_FRAMES;
2012
2013 /* always allocate maximum size(PAL) for system buffers */
2014 reqsize = SYS_FRAMES_MAXSIZE;
2015
2016 if (reqsize > SYS_FRAMES_MAXSIZE)
2017 reqsize = SYS_FRAMES_MAXSIZE;
2018
2019 for (i = 0; i < SYS_FRAMES; i++) {
2020 /* allocate the frames */
2021 dev->buffer[chn].frame[i].lpvbits = vmalloc(reqsize);
2022
2023 dprintk(1, "valloc %p chan %lu, idx %lu, pdata %p\n",
2024 &dev->buffer[chn].frame[i], chn, i,
2025 dev->buffer[chn].frame[i].lpvbits);
2026 dev->buffer[chn].frame[i].size = reqsize;
2027 if (dev->buffer[chn].frame[i].lpvbits == NULL) {
2028 printk(KERN_INFO "out of memory. using less frames\n");
2029 dev->buffer[chn].dwFrames = i;
2030 break;
2031 }
2032 }
2033
2034 /* make sure internal states are set */
2035 for (i = 0; i < SYS_FRAMES; i++) {
2036 dev->buffer[chn].frame[i].ulState = 0;
2037 dev->buffer[chn].frame[i].cur_size = 0;
2038 }
2039
2040 dev->cur_frame[chn] = 0;
2041 dev->last_frame[chn] = -1;
2042 return 0;
2043}
2044
2045static int s2255_release_sys_buffers(struct s2255_dev *dev,
2046 unsigned long channel)
2047{
2048 unsigned long i;
2049 dprintk(1, "release sys buffers\n");
2050 for (i = 0; i < SYS_FRAMES; i++) {
2051 if (dev->buffer[channel].frame[i].lpvbits) {
2052 dprintk(1, "vfree %p\n",
2053 dev->buffer[channel].frame[i].lpvbits);
2054 vfree(dev->buffer[channel].frame[i].lpvbits);
2055 }
2056 dev->buffer[channel].frame[i].lpvbits = NULL;
2057 }
2058 return 0;
2059}
2060
2061static int s2255_board_init(struct s2255_dev *dev)
2062{
2063 int j;
2064 struct s2255_mode mode_def = DEF_MODEI_NTSC_CONT;
2065 int fw_ver;
2066 dprintk(4, "board init: %p", dev);
2067
2068 for (j = 0; j < MAX_PIPE_BUFFERS; j++) {
2069 struct s2255_pipeinfo *pipe = &dev->pipes[j];
2070
2071 memset(pipe, 0, sizeof(*pipe));
2072 pipe->dev = dev;
2073 pipe->cur_transfer_size = DEFAULT_PIPE_USBBLOCK;
2074 pipe->max_transfer_size = MAX_PIPE_USBBLOCK;
2075
2076 if (pipe->cur_transfer_size > pipe->max_transfer_size)
2077 pipe->cur_transfer_size = pipe->max_transfer_size;
2078 pipe->transfer_buffer = kzalloc(pipe->max_transfer_size,
2079 GFP_KERNEL);
2080 if (pipe->transfer_buffer == NULL) {
2081 dprintk(1, "out of memory!\n");
2082 return -ENOMEM;
2083 }
2084
2085 }
2086
2087 /* query the firmware */
2088 fw_ver = s2255_get_fx2fw(dev);
2089
2090 printk(KERN_INFO "2255 usb firmware version %d \n", fw_ver);
2091 if (fw_ver < CUR_USB_FWVER)
2092 err("usb firmware not up to date %d\n", fw_ver);
2093
2094 for (j = 0; j < MAX_CHANNELS; j++) {
2095 dev->b_acquire[j] = 0;
2096 dev->mode[j] = mode_def;
2097 dev->cur_fmt[j] = &formats[0];
2098 dev->mode[j].restart = 1;
2099 dev->req_image_size[j] = get_transfer_size(&mode_def);
2100 dev->frame_count[j] = 0;
2101 /* create the system buffers */
2102 s2255_create_sys_buffers(dev, j);
2103 }
2104 /* start read pipe */
2105 s2255_start_readpipe(dev);
2106
2107 dprintk(1, "S2255: board initialized\n");
2108 return 0;
2109}
2110
2111static int s2255_board_shutdown(struct s2255_dev *dev)
2112{
2113 u32 i;
2114
2115 dprintk(1, "S2255: board shutdown: %p", dev);
2116
2117 for (i = 0; i < MAX_CHANNELS; i++) {
2118 if (dev->b_acquire[i])
2119 s2255_stop_acquire(dev, i);
2120 }
2121
2122 s2255_stop_readpipe(dev);
2123
2124 for (i = 0; i < MAX_CHANNELS; i++)
2125 s2255_release_sys_buffers(dev, i);
2126
2127 /* release transfer buffers */
2128 for (i = 0; i < MAX_PIPE_BUFFERS; i++) {
2129 struct s2255_pipeinfo *pipe = &dev->pipes[i];
2130 kfree(pipe->transfer_buffer);
2131 }
2132 return 0;
2133}
2134
2135static void read_pipe_completion(struct urb *purb)
2136{
2137 struct s2255_pipeinfo *pipe_info;
2138 struct s2255_dev *dev;
2139 int status;
2140 int pipe;
2141
2142 pipe_info = purb->context;
2143 dprintk(100, "read pipe completion %p, status %d\n", purb,
2144 purb->status);
2145 if (pipe_info == NULL) {
2146 err("no context !");
2147 return;
2148 }
2149
2150 dev = pipe_info->dev;
2151 if (dev == NULL) {
2152 err("no context !");
2153 return;
2154 }
2155 status = purb->status;
2156 if (status != 0) {
2157 dprintk(2, "read_pipe_completion: err\n");
2158 return;
2159 }
2160
2161 if (pipe_info->state == 0) {
2162 dprintk(2, "exiting USB pipe");
2163 return;
2164 }
2165
2166 s2255_read_video_callback(dev, pipe_info);
2167
2168 pipe_info->err_count = 0;
2169 pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint);
2170 /* reuse urb */
2171 usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev,
2172 pipe,
2173 pipe_info->transfer_buffer,
2174 pipe_info->cur_transfer_size,
2175 read_pipe_completion, pipe_info);
2176
2177 if (pipe_info->state != 0) {
2178 if (usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL)) {
2179 dev_err(&dev->udev->dev, "error submitting urb\n");
2180 usb_free_urb(pipe_info->stream_urb);
2181 }
2182 } else {
2183 dprintk(2, "read pipe complete state 0\n");
2184 }
2185 return;
2186}
2187
2188static int s2255_start_readpipe(struct s2255_dev *dev)
2189{
2190 int pipe;
2191 int retval;
2192 int i;
2193 struct s2255_pipeinfo *pipe_info = dev->pipes;
2194 pipe = usb_rcvbulkpipe(dev->udev, dev->read_endpoint);
2195 dprintk(2, "start pipe IN %d\n", dev->read_endpoint);
2196
2197 for (i = 0; i < MAX_PIPE_BUFFERS; i++) {
2198 pipe_info->state = 1;
2199 pipe_info->buf_index = (u32) i;
2200 pipe_info->priority_set = 0;
2201 pipe_info->stream_urb = usb_alloc_urb(0, GFP_KERNEL);
2202 if (!pipe_info->stream_urb) {
2203 dev_err(&dev->udev->dev,
2204 "ReadStream: Unable to alloc URB");
2205 return -ENOMEM;
2206 }
2207 /* transfer buffer allocated in board_init */
2208 usb_fill_bulk_urb(pipe_info->stream_urb, dev->udev,
2209 pipe,
2210 pipe_info->transfer_buffer,
2211 pipe_info->cur_transfer_size,
2212 read_pipe_completion, pipe_info);
2213
2214 pipe_info->urb_size = sizeof(pipe_info->stream_urb);
2215 dprintk(4, "submitting URB %p\n", pipe_info->stream_urb);
2216 retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
2217 if (retval) {
2218 printk(KERN_ERR "s2255: start read pipe failed\n");
2219 return retval;
2220 }
2221 }
2222
2223 return 0;
2224}
2225
2226/* starts acquisition process */
2227static int s2255_start_acquire(struct s2255_dev *dev, unsigned long chn)
2228{
2229 unsigned char *buffer;
2230 int res;
2231 unsigned long chn_rev;
2232 int j;
2233 if (chn >= MAX_CHANNELS) {
2234 dprintk(2, "start acquire failed, bad channel %lu\n", chn);
2235 return -1;
2236 }
2237
2238 chn_rev = G_chnmap[chn];
2239 dprintk(1, "S2255: start acquire %lu \n", chn);
2240
2241 buffer = kzalloc(512, GFP_KERNEL);
2242 if (buffer == NULL) {
2243 dev_err(&dev->udev->dev, "out of mem\n");
2244 return -ENOMEM;
2245 }
2246
2247 dev->last_frame[chn] = -1;
2248 dev->bad_payload[chn] = 0;
2249 dev->cur_frame[chn] = 0;
2250 for (j = 0; j < SYS_FRAMES; j++) {
2251 dev->buffer[chn].frame[j].ulState = 0;
2252 dev->buffer[chn].frame[j].cur_size = 0;
2253 }
2254
2255 /* send the start command */
2256 *(u32 *) buffer = IN_DATA_TOKEN;
2257 *((u32 *) buffer + 1) = (u32) chn_rev;
2258 *((u32 *) buffer + 2) = (u32) CMD_START;
2259 res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
2260 if (res != 0)
2261 dev_err(&dev->udev->dev, "CMD_START error\n");
2262
2263 dprintk(2, "start acquire exit[%lu] %d \n", chn, res);
2264 kfree(buffer);
2265 return 0;
2266}
2267
2268static int s2255_stop_acquire(struct s2255_dev *dev, unsigned long chn)
2269{
2270 unsigned char *buffer;
2271 int res;
2272 unsigned long chn_rev;
2273
2274 if (chn >= MAX_CHANNELS) {
2275 dprintk(2, "stop acquire failed, bad channel %lu\n", chn);
2276 return -1;
2277 }
2278 chn_rev = G_chnmap[chn];
2279
2280 buffer = kzalloc(512, GFP_KERNEL);
2281 if (buffer == NULL) {
2282 dev_err(&dev->udev->dev, "out of mem\n");
2283 return -ENOMEM;
2284 }
2285
2286 /* send the stop command */
2287 dprintk(4, "stop acquire %lu\n", chn);
2288 *(u32 *) buffer = IN_DATA_TOKEN;
2289 *((u32 *) buffer + 1) = (u32) chn_rev;
2290 *((u32 *) buffer + 2) = CMD_STOP;
2291 res = s2255_write_config(dev->udev, (unsigned char *)buffer, 512);
2292
2293 if (res != 0)
2294 dev_err(&dev->udev->dev, "CMD_STOP error\n");
2295
2296 dprintk(4, "stop acquire: releasing states \n");
2297
2298 kfree(buffer);
2299 dev->b_acquire[chn] = 0;
2300
2301 return 0;
2302}
2303
2304static void s2255_stop_readpipe(struct s2255_dev *dev)
2305{
2306 int j;
2307
2308 if (dev == NULL) {
2309 err("s2255: invalid device");
2310 return;
2311 }
2312 dprintk(4, "stop read pipe\n");
2313 for (j = 0; j < MAX_PIPE_BUFFERS; j++) {
2314 struct s2255_pipeinfo *pipe_info = &dev->pipes[j];
2315 if (pipe_info) {
2316 if (pipe_info->state == 0)
2317 continue;
2318 pipe_info->state = 0;
2319 pipe_info->prev_state = 1;
2320
2321 }
2322 }
2323
2324 for (j = 0; j < MAX_PIPE_BUFFERS; j++) {
2325 struct s2255_pipeinfo *pipe_info = &dev->pipes[j];
2326 if (pipe_info->stream_urb) {
2327 /* cancel urb */
2328 usb_kill_urb(pipe_info->stream_urb);
2329 usb_free_urb(pipe_info->stream_urb);
2330 pipe_info->stream_urb = NULL;
2331 }
2332 }
2333 dprintk(2, "s2255 stop read pipe: %d\n", j);
2334 return;
2335}
2336
2337static void s2255_fwload_start(struct s2255_dev *dev)
2338{
2339 dev->fw_data->fw_size = dev->fw_data->fw->size;
2340 atomic_set(&dev->fw_data->fw_state, S2255_FW_NOTLOADED);
2341 memcpy(dev->fw_data->pfw_data,
2342 dev->fw_data->fw->data, CHUNK_SIZE);
2343 dev->fw_data->fw_loaded = CHUNK_SIZE;
2344 usb_fill_bulk_urb(dev->fw_data->fw_urb, dev->udev,
2345 usb_sndbulkpipe(dev->udev, 2),
2346 dev->fw_data->pfw_data,
2347 CHUNK_SIZE, s2255_fwchunk_complete,
2348 dev->fw_data);
2349 mod_timer(&dev->timer, jiffies + HZ);
2350}
2351
2352/* standard usb probe function */
2353static int s2255_probe(struct usb_interface *interface,
2354 const struct usb_device_id *id)
2355{
2356 struct s2255_dev *dev = NULL;
2357 struct usb_host_interface *iface_desc;
2358 struct usb_endpoint_descriptor *endpoint;
2359 int i;
2360 int retval = -ENOMEM;
2361
2362 dprintk(2, "s2255: probe\n");
2363
2364 /* allocate memory for our device state and initialize it to zero */
2365 dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL);
2366 if (dev == NULL) {
2367 err("s2255: out of memory");
2368 goto error;
2369 }
2370
2371 dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL);
2372 if (!dev->fw_data)
2373 goto error;
2374
2375 mutex_init(&dev->lock);
2376 mutex_init(&dev->open_lock);
2377
2378 /* grab usb_device and save it */
2379 dev->udev = usb_get_dev(interface_to_usbdev(interface));
2380 if (dev->udev == NULL) {
2381 dev_err(&interface->dev, "null usb device\n");
2382 retval = -ENODEV;
2383 goto error;
2384 }
2385 kref_init(&dev->kref);
2386 dprintk(1, "dev: %p, kref: %p udev %p interface %p\n", dev, &dev->kref,
2387 dev->udev, interface);
2388 dev->interface = interface;
2389 /* set up the endpoint information */
2390 iface_desc = interface->cur_altsetting;
2391 dprintk(1, "num endpoints %d\n", iface_desc->desc.bNumEndpoints);
2392 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
2393 endpoint = &iface_desc->endpoint[i].desc;
2394 if (!dev->read_endpoint && usb_endpoint_is_bulk_in(endpoint)) {
2395 /* we found the bulk in endpoint */
2396 dev->read_endpoint = endpoint->bEndpointAddress;
2397 }
2398 }
2399
2400 if (!dev->read_endpoint) {
2401 dev_err(&interface->dev, "Could not find bulk-in endpoint");
2402 goto error;
2403 }
2404
2405 /* set intfdata */
2406 usb_set_intfdata(interface, dev);
2407
2408 dprintk(100, "after intfdata %p\n", dev);
2409
2410 init_timer(&dev->timer);
2411 dev->timer.function = s2255_timer;
2412 dev->timer.data = (unsigned long)dev->fw_data;
2413
2414 init_waitqueue_head(&dev->fw_data->wait_fw);
2415
2416
2417 dev->fw_data->fw_urb = usb_alloc_urb(0, GFP_KERNEL);
2418
2419 if (!dev->fw_data->fw_urb) {
2420 dev_err(&interface->dev, "out of memory!\n");
2421 goto error;
2422 }
2423 dev->fw_data->pfw_data = kzalloc(CHUNK_SIZE, GFP_KERNEL);
2424 if (!dev->fw_data->pfw_data) {
2425 dev_err(&interface->dev, "out of memory!\n");
2426 goto error;
2427 }
2428 /* load the first chunk */
2429 if (request_firmware(&dev->fw_data->fw,
2430 FIRMWARE_FILE_NAME, &dev->udev->dev)) {
2431 printk(KERN_ERR "sensoray 2255 failed to get firmware\n");
2432 goto error;
2433 }
2434
2435 /* loads v4l specific */
2436 s2255_probe_v4l(dev);
2437 /* load 2255 board specific */
2438 s2255_board_init(dev);
2439
2440 dprintk(4, "before probe done %p\n", dev);
2441 spin_lock_init(&dev->slock);
2442
2443 s2255_fwload_start(dev);
2444 dev_info(&interface->dev, "Sensoray 2255 detected\n");
2445 return 0;
2446error:
2447 return retval;
2448}
2449
2450/* disconnect routine. when board is removed physically or with rmmod */
2451static void s2255_disconnect(struct usb_interface *interface)
2452{
2453 struct s2255_dev *dev = NULL;
2454 dprintk(1, "s2255: disconnect interface %p\n", interface);
2455 dev = usb_get_intfdata(interface);
2456 if (dev) {
2457 kref_put(&dev->kref, s2255_destroy);
2458 dprintk(1, "s2255drv: disconnect\n");
2459 dev_info(&interface->dev, "s2255usb now disconnected\n");
2460 }
2461 usb_set_intfdata(interface, NULL);
2462}
2463
2464static struct usb_driver s2255_driver = {
2465 .name = "s2255",
2466 .probe = s2255_probe,
2467 .disconnect = s2255_disconnect,
2468 .id_table = s2255_table,
2469};
2470
2471static int __init usb_s2255_init(void)
2472{
2473 int result;
2474
2475 /* register this driver with the USB subsystem */
2476 result = usb_register(&s2255_driver);
2477
2478 if (result)
2479 err("usb_register failed. Error number %d", result);
2480
2481 dprintk(2, "s2255_init: done\n");
2482 return result;
2483}
2484
2485static void __exit usb_s2255_exit(void)
2486{
2487 usb_deregister(&s2255_driver);
2488}
2489
2490module_init(usb_s2255_init);
2491module_exit(usb_s2255_exit);
2492
2493MODULE_DESCRIPTION("Sensoray 2255 Video for Linux driver");
2494MODULE_AUTHOR("Dean Anderson (Sensoray Company Inc.)");
2495MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index 996b49491f5a..03e772130b55 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -66,6 +66,7 @@ static struct video_device saa_template; /* Declared near bottom */
66 66
67/* Addresses to scan */ 67/* Addresses to scan */
68static unsigned short normal_i2c[] = { I2C_ADDRESS, I2C_CLIENT_END }; 68static unsigned short normal_i2c[] = { I2C_ADDRESS, I2C_CLIENT_END };
69
69I2C_CLIENT_INSMOD; 70I2C_CLIENT_INSMOD;
70 71
71static struct i2c_client client_template; 72static struct i2c_client client_template;
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index ec8c65dc8408..fde99d9ee71f 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -130,6 +130,7 @@ static struct video_device saa_template; /* Declared near bottom */
130 130
131/* Addresses to scan */ 131/* Addresses to scan */
132static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END}; 132static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END};
133
133I2C_CLIENT_INSMOD; 134I2C_CLIENT_INSMOD;
134 135
135static struct i2c_client client_template; 136static struct i2c_client client_template;
diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c
index 716ee7f64df3..f05024259f01 100644
--- a/drivers/media/video/saa6588.c
+++ b/drivers/media/video/saa6588.c
@@ -31,7 +31,6 @@
31#include <linux/wait.h> 31#include <linux/wait.h>
32#include <asm/uaccess.h> 32#include <asm/uaccess.h>
33 33
34
35#include <media/rds.h> 34#include <media/rds.h>
36 35
37/* Addresses to scan */ 36/* Addresses to scan */
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index 435c083cc542..bcd1c8f6cf6b 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -67,7 +67,6 @@ static unsigned short normal_i2c[] = {
67 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */ 67 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
68 I2C_CLIENT_END }; 68 I2C_CLIENT_END };
69 69
70
71I2C_CLIENT_INSMOD; 70I2C_CLIENT_INSMOD;
72 71
73struct saa711x_state { 72struct saa711x_state {
@@ -1558,7 +1557,7 @@ static int saa7115_remove(struct i2c_client *client)
1558} 1557}
1559 1558
1560static const struct i2c_device_id saa7115_id[] = { 1559static const struct i2c_device_id saa7115_id[] = {
1561 { "saa711x", 1 }, /* autodetect */ 1560 { "saa7115_auto", 1 }, /* autodetect */
1562 { "saa7111", 0 }, 1561 { "saa7111", 0 },
1563 { "saa7113", 0 }, 1562 { "saa7113", 0 },
1564 { "saa7114", 0 }, 1563 { "saa7114", 0 },
@@ -1577,4 +1576,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1577 .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, 1576 .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
1578 .id_table = saa7115_id, 1577 .id_table = saa7115_id,
1579}; 1578};
1580
diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c
deleted file mode 100644
index cedb988574bd..000000000000
--- a/drivers/media/video/saa711x.c
+++ /dev/null
@@ -1,584 +0,0 @@
1/*
2 * saa711x - Philips SAA711x video decoder driver version 0.0.1
3 *
4 * To do: Now, it handles only saa7113/7114. Should be improved to
5 * handle all Philips saa711x devices.
6 *
7 * Based on saa7113 driver from Dave Perks <dperks@ibm.net>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/errno.h>
28#include <linux/fs.h>
29#include <linux/kernel.h>
30#include <linux/major.h>
31#include <linux/slab.h>
32#include <linux/mm.h>
33#include <linux/signal.h>
34#include <asm/io.h>
35#include <asm/pgtable.h>
36#include <asm/page.h>
37#include <linux/types.h>
38#include <asm/uaccess.h>
39#include <linux/videodev.h>
40
41MODULE_DESCRIPTION("Philips SAA711x video decoder driver");
42MODULE_AUTHOR("Dave Perks, Jose Ignacio Gijon, Joerg Heckenbach, Mark McClelland, Dwaine Garden");
43MODULE_LICENSE("GPL");
44
45#include <linux/i2c.h>
46
47#define I2C_NAME(s) (s)->name
48
49#include <linux/video_decoder.h>
50
51static int debug;
52module_param(debug, int, 0644);
53MODULE_PARM_DESC(debug, " Set the default Debug level. Default: 0 (Off) - (0-1)");
54
55
56#define dprintk(num, format, args...) \
57 do { \
58 if (debug >= num) \
59 printk(format, ##args); \
60 } while (0)
61
62/* ----------------------------------------------------------------------- */
63
64struct saa711x {
65 unsigned char reg[32];
66
67 int norm;
68 int input;
69 int enable;
70 int bright;
71 int contrast;
72 int hue;
73 int sat;
74};
75
76#define I2C_SAA7113 0x4A
77#define I2C_SAA7114 0x42
78
79/* ----------------------------------------------------------------------- */
80
81static inline int
82saa711x_write (struct i2c_client *client,
83 u8 reg,
84 u8 value)
85{
86 struct saa711x *decoder = i2c_get_clientdata(client);
87
88 decoder->reg[reg] = value;
89 return i2c_smbus_write_byte_data(client, reg, value);
90}
91
92static int
93saa711x_write_block (struct i2c_client *client,
94 const u8 *data,
95 unsigned int len)
96{
97 int ret = -1;
98 u8 reg;
99
100 /* the saa711x has an autoincrement function, use it if
101 * the adapter understands raw I2C */
102 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
103 /* do raw I2C, not smbus compatible */
104 struct saa711x *decoder = i2c_get_clientdata(client);
105 struct i2c_msg msg;
106 u8 block_data[32];
107
108 msg.addr = client->addr;
109 msg.flags = 0;
110 while (len >= 2) {
111 msg.buf = (char *) block_data;
112 msg.len = 0;
113 block_data[msg.len++] = reg = data[0];
114 do {
115 block_data[msg.len++] =
116 decoder->reg[reg++] = data[1];
117 len -= 2;
118 data += 2;
119 } while (len >= 2 && data[0] == reg &&
120 msg.len < 32);
121 if ((ret = i2c_transfer(client->adapter,
122 &msg, 1)) < 0)
123 break;
124 }
125 } else {
126 /* do some slow I2C emulation kind of thing */
127 while (len >= 2) {
128 reg = *data++;
129 if ((ret = saa711x_write(client, reg,
130 *data++)) < 0)
131 break;
132 len -= 2;
133 }
134 }
135
136 return ret;
137}
138
139static int
140saa711x_init_decoder (struct i2c_client *client,
141 struct video_decoder_init *init)
142{
143 return saa711x_write_block(client, init->data, init->len);
144}
145
146static inline int
147saa711x_read (struct i2c_client *client,
148 u8 reg)
149{
150 return i2c_smbus_read_byte_data(client, reg);
151}
152
153/* ----------------------------------------------------------------------- */
154
155static const unsigned char saa711x_i2c_init[] = {
156 0x00, 0x00, /* PH711x_CHIP_VERSION 00 - ID byte */
157 0x01, 0x08, /* PH711x_INCREMENT_DELAY - (1) (1) (1) (1) IDEL3 IDEL2 IDELL1 IDEL0 */
158 0x02, 0xc0, /* PH711x_ANALOG_INPUT_CONTR_1 - FUSE1 FUSE0 GUDL1 GUDL0 MODE3 MODE2 MODE1 MODE0 */
159 0x03, 0x23, /* PH711x_ANALOG_INPUT_CONTR_2 - (1) HLNRS VBSL WPOFF HOLDG GAFIX GAI28 GAI18 */
160 0x04, 0x00, /* PH711x_ANALOG_INPUT_CONTR_3 - GAI17 GAI16 GAI15 GAI14 GAI13 GAI12 GAI11 GAI10 */
161 0x05, 0x00, /* PH711x_ANALOG_INPUT_CONTR_4 - GAI27 GAI26 GAI25 GAI24 GAI23 GAI22 GAI21 GAI20 */
162 0x06, 0xeb, /* PH711x_HORIZONTAL_SYNC_START - HSB7 HSB6 HSB5 HSB4 HSB3 HSB2 HSB1 HSB0 */
163 0x07, 0xe0, /* PH711x_HORIZONTAL_SYNC_STOP - HSS7 HSS6 HSS5 HSS4 HSS3 HSS2 HSS1 HSS0 */
164 0x08, 0x88, /* PH711x_SYNC_CONTROL - AUFD FSEL FOET HTC1 HTC0 HPLL VNOI1 VNOI0 */
165 0x09, 0x00, /* PH711x_LUMINANCE_CONTROL - BYPS PREF BPSS1 BPSS0 VBLB UPTCV APER1 APER0 */
166 0x0a, 0x80, /* PH711x_LUMINANCE_BRIGHTNESS - BRIG7 BRIG6 BRIG5 BRIG4 BRIG3 BRIG2 BRIG1 BRIG0 */
167 0x0b, 0x47, /* PH711x_LUMINANCE_CONTRAST - CONT7 CONT6 CONT5 CONT4 CONT3 CONT2 CONT1 CONT0 */
168 0x0c, 0x40, /* PH711x_CHROMA_SATURATION - SATN7 SATN6 SATN5 SATN4 SATN3 SATN2 SATN1 SATN0 */
169 0x0d, 0x00, /* PH711x_CHROMA_HUE_CONTROL - HUEC7 HUEC6 HUEC5 HUEC4 HUEC3 HUEC2 HUEC1 HUEC0 */
170 0x0e, 0x01, /* PH711x_CHROMA_CONTROL - CDTO CSTD2 CSTD1 CSTD0 DCCF FCTC CHBW1 CHBW0 */
171 0x0f, 0xaa, /* PH711x_CHROMA_GAIN_CONTROL - ACGC CGAIN6 CGAIN5 CGAIN4 CGAIN3 CGAIN2 CGAIN1 CGAIN0 */
172 0x10, 0x00, /* PH711x_FORMAT_DELAY_CONTROL - OFTS1 OFTS0 HDEL1 HDEL0 VRLN YDEL2 YDEL1 YDEL0 */
173 0x11, 0x1C, /* PH711x_OUTPUT_CONTROL_1 - GPSW1 CM99 GPSW0 HLSEL OEYC OERT VIPB COLO */
174 0x12, 0x01, /* PH711x_OUTPUT_CONTROL_2 - RTSE13 RTSE12 RTSE11 RTSE10 RTSE03 RTSE02 RTSE01 RTSE00 */
175 0x13, 0x00, /* PH711x_OUTPUT_CONTROL_3 - ADLSB (1) (1) OLDSB FIDP (1) AOSL1 AOSL0 */
176 0x14, 0x00, /* RESERVED 14 - (1) (1) (1) (1) (1) (1) (1) (1) */
177 0x15, 0x00, /* PH711x_V_GATE1_START - VSTA7 VSTA6 VSTA5 VSTA4 VSTA3 VSTA2 VSTA1 VSTA0 */
178 0x16, 0x00, /* PH711x_V_GATE1_STOP - VSTO7 VSTO6 VSTO5 VSTO4 VSTO3 VSTO2 VSTO1 VSTO0 */
179 0x17, 0x00, /* PH711x_V_GATE1_MSB - (1) (1) (1) (1) (1) (1) VSTO8 VSTA8 */
180};
181
182static int
183saa711x_command (struct i2c_client *client,
184 unsigned int cmd,
185 void *arg)
186{
187 struct saa711x *decoder = i2c_get_clientdata(client);
188
189 switch (cmd) {
190
191 case 0:
192 case DECODER_INIT:
193 {
194 struct video_decoder_init *init = arg;
195 if (NULL != init)
196 return saa711x_init_decoder(client, init);
197 else {
198 struct video_decoder_init vdi;
199 vdi.data = saa711x_i2c_init;
200 vdi.len = sizeof(saa711x_i2c_init);
201 return saa711x_init_decoder(client, &vdi);
202 }
203 }
204
205 case DECODER_DUMP:
206 {
207 int i;
208
209 for (i = 0; i < 32; i += 16) {
210 int j;
211
212 printk(KERN_DEBUG "%s: %03x", I2C_NAME(client), i);
213 for (j = 0; j < 16; ++j) {
214 printk(" %02x",
215 saa711x_read(client, i + j));
216 }
217 printk("\n");
218 }
219 }
220 break;
221
222 case DECODER_GET_CAPABILITIES:
223 {
224 struct video_decoder_capability *cap = arg;
225
226 cap->flags = VIDEO_DECODER_PAL |
227 VIDEO_DECODER_NTSC |
228 VIDEO_DECODER_SECAM |
229 VIDEO_DECODER_AUTO |
230 VIDEO_DECODER_CCIR;
231 cap->inputs = 8;
232 cap->outputs = 1;
233 }
234 break;
235
236 case DECODER_GET_STATUS:
237 {
238 int *iarg = arg;
239 int status;
240 int res;
241
242 status = saa711x_read(client, 0x1f);
243 dprintk(1, KERN_DEBUG "%s status: 0x%02x\n", I2C_NAME(client),
244 status);
245 res = 0;
246 if ((status & (1 << 6)) == 0) {
247 res |= DECODER_STATUS_GOOD;
248 }
249 switch (decoder->norm) {
250 case VIDEO_MODE_NTSC:
251 res |= DECODER_STATUS_NTSC;
252 break;
253 case VIDEO_MODE_PAL:
254 res |= DECODER_STATUS_PAL;
255 break;
256 case VIDEO_MODE_SECAM:
257 res |= DECODER_STATUS_SECAM;
258 break;
259 default:
260 case VIDEO_MODE_AUTO:
261 if ((status & (1 << 5)) != 0) {
262 res |= DECODER_STATUS_NTSC;
263 } else {
264 res |= DECODER_STATUS_PAL;
265 }
266 break;
267 }
268 if ((status & (1 << 0)) != 0) {
269 res |= DECODER_STATUS_COLOR;
270 }
271 *iarg = res;
272 }
273 break;
274
275 case DECODER_SET_GPIO:
276 {
277 int *iarg = arg;
278 if (0 != *iarg) {
279 saa711x_write(client, 0x11,
280 (decoder->reg[0x11] | 0x80));
281 } else {
282 saa711x_write(client, 0x11,
283 (decoder->reg[0x11] & 0x7f));
284 }
285 break;
286 }
287
288 case DECODER_SET_VBI_BYPASS:
289 {
290 int *iarg = arg;
291 if (0 != *iarg) {
292 saa711x_write(client, 0x13,
293 (decoder->reg[0x13] & 0xf0) | 0x0a);
294 } else {
295 saa711x_write(client, 0x13,
296 (decoder->reg[0x13] & 0xf0));
297 }
298 break;
299 }
300
301 case DECODER_SET_NORM:
302 {
303 int *iarg = arg;
304
305 switch (*iarg) {
306
307 case VIDEO_MODE_NTSC:
308 saa711x_write(client, 0x08,
309 (decoder->reg[0x08] & 0x3f) | 0x40);
310 saa711x_write(client, 0x0e,
311 (decoder->reg[0x0e] & 0x8f));
312 break;
313
314 case VIDEO_MODE_PAL:
315 saa711x_write(client, 0x08,
316 (decoder->reg[0x08] & 0x3f) | 0x00);
317 saa711x_write(client, 0x0e,
318 (decoder->reg[0x0e] & 0x8f));
319 break;
320
321 case VIDEO_MODE_SECAM:
322 saa711x_write(client, 0x08,
323 (decoder->reg[0x08] & 0x3f) | 0x00);
324 saa711x_write(client, 0x0e,
325 (decoder->reg[0x0e] & 0x8f) | 0x50);
326 break;
327
328 case VIDEO_MODE_AUTO:
329 saa711x_write(client, 0x08,
330 (decoder->reg[0x08] & 0x3f) | 0x80);
331 saa711x_write(client, 0x0e,
332 (decoder->reg[0x0e] & 0x8f));
333 break;
334
335 default:
336 return -EINVAL;
337
338 }
339 decoder->norm = *iarg;
340 }
341 break;
342
343 case DECODER_SET_INPUT:
344 {
345 int *iarg = arg;
346 if (*iarg < 0 || *iarg > 9) {
347 return -EINVAL;
348 }
349 if (decoder->input != *iarg) {
350 decoder->input = *iarg;
351 /* select mode */
352 saa711x_write(client, 0x02,
353 (decoder->reg[0x02] & 0xf0) | decoder->input);
354 /* bypass chrominance trap for modes 4..7 */
355 saa711x_write(client, 0x09,
356 (decoder->reg[0x09] & 0x7f) | ((decoder->input > 3) ? 0x80 : 0));
357 }
358 }
359 break;
360
361 case DECODER_SET_OUTPUT:
362 {
363 int *iarg = arg;
364
365 /* not much choice of outputs */
366 if (*iarg != 0) {
367 return -EINVAL;
368 }
369 }
370 break;
371
372 case DECODER_ENABLE_OUTPUT:
373 {
374 int *iarg = arg;
375 int enable = (*iarg != 0);
376
377 if (decoder->enable != enable) {
378 decoder->enable = enable;
379
380 /* RJ: If output should be disabled (for
381 * playing videos), we also need a open PLL.
382 * The input is set to 0 (where no input
383 * source is connected), although this
384 * is not necessary.
385 *
386 * If output should be enabled, we have to
387 * reverse the above.
388 */
389
390 if (decoder->enable) {
391 saa711x_write(client, 0x02,
392 (decoder->
393 reg[0x02] & 0xf8) |
394 decoder->input);
395 saa711x_write(client, 0x08,
396 (decoder->reg[0x08] & 0xfb));
397 saa711x_write(client, 0x11,
398 (decoder->
399 reg[0x11] & 0xf3) | 0x0c);
400 } else {
401 saa711x_write(client, 0x02,
402 (decoder->reg[0x02] & 0xf8));
403 saa711x_write(client, 0x08,
404 (decoder->
405 reg[0x08] & 0xfb) | 0x04);
406 saa711x_write(client, 0x11,
407 (decoder->reg[0x11] & 0xf3));
408 }
409 }
410 }
411 break;
412
413 case DECODER_SET_PICTURE:
414 {
415 struct video_picture *pic = arg;
416
417 if (decoder->bright != pic->brightness) {
418 /* We want 0 to 255 we get 0-65535 */
419 decoder->bright = pic->brightness;
420 saa711x_write(client, 0x0a, decoder->bright >> 8);
421 }
422 if (decoder->contrast != pic->contrast) {
423 /* We want 0 to 127 we get 0-65535 */
424 decoder->contrast = pic->contrast;
425 saa711x_write(client, 0x0b,
426 decoder->contrast >> 9);
427 }
428 if (decoder->sat != pic->colour) {
429 /* We want 0 to 127 we get 0-65535 */
430 decoder->sat = pic->colour;
431 saa711x_write(client, 0x0c, decoder->sat >> 9);
432 }
433 if (decoder->hue != pic->hue) {
434 /* We want -128 to 127 we get 0-65535 */
435 decoder->hue = pic->hue;
436 saa711x_write(client, 0x0d,
437 (decoder->hue - 32768) >> 8);
438 }
439 }
440 break;
441
442 default:
443 return -EINVAL;
444 }
445
446 return 0;
447}
448
449/* ----------------------------------------------------------------------- */
450
451/*
452 * Generic i2c probe
453 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
454 */
455
456/* standard i2c insmod options */
457static unsigned short normal_i2c[] = {
458 I2C_SAA7113>>1, /* saa7113 */
459 I2C_SAA7114>>1, /* saa7114 */
460 I2C_CLIENT_END
461};
462
463I2C_CLIENT_INSMOD;
464
465
466static struct i2c_driver i2c_driver_saa711x;
467
468static int
469saa711x_detect_client (struct i2c_adapter *adapter,
470 int address,
471 int kind)
472{
473 int i;
474 struct i2c_client *client;
475 struct saa711x *decoder;
476 struct video_decoder_init vdi;
477
478 dprintk(1,
479 KERN_INFO
480 "saa711x.c: detecting saa711x client on address 0x%x\n",
481 address << 1);
482
483 /* Check if the adapter supports the needed features */
484 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
485 return 0;
486
487 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
488 if (client == 0)
489 return -ENOMEM;
490 client->addr = address;
491 client->adapter = adapter;
492 client->driver = &i2c_driver_saa711x;
493 strlcpy(I2C_NAME(client), "saa711x", sizeof(I2C_NAME(client)));
494 decoder = kzalloc(sizeof(struct saa711x), GFP_KERNEL);
495 if (decoder == NULL) {
496 kfree(client);
497 return -ENOMEM;
498 }
499 decoder->norm = VIDEO_MODE_NTSC;
500 decoder->input = 0;
501 decoder->enable = 1;
502 decoder->bright = 32768;
503 decoder->contrast = 32768;
504 decoder->hue = 32768;
505 decoder->sat = 32768;
506 i2c_set_clientdata(client, decoder);
507
508 i = i2c_attach_client(client);
509 if (i) {
510 kfree(client);
511 kfree(decoder);
512 return i;
513 }
514
515 vdi.data = saa711x_i2c_init;
516 vdi.len = sizeof(saa711x_i2c_init);
517 i = saa711x_init_decoder(client, &vdi);
518 if (i < 0) {
519 dprintk(1, KERN_ERR "%s_attach error: init status %d\n",
520 I2C_NAME(client), i);
521 } else {
522 dprintk(1,
523 KERN_INFO
524 "%s_attach: chip version %x at address 0x%x\n",
525 I2C_NAME(client), saa711x_read(client, 0x00) >> 4,
526 client->addr << 1);
527 }
528
529 return 0;
530}
531
532static int
533saa711x_attach_adapter (struct i2c_adapter *adapter)
534{
535 dprintk(1,
536 KERN_INFO
537 "saa711x.c: starting probe for adapter %s (0x%x)\n",
538 I2C_NAME(adapter), adapter->id);
539 return i2c_probe(adapter, &addr_data, &saa711x_detect_client);
540}
541
542static int
543saa711x_detach_client (struct i2c_client *client)
544{
545 struct saa711x *decoder = i2c_get_clientdata(client);
546 int err;
547
548 err = i2c_detach_client(client);
549 if (err) {
550 return err;
551 }
552
553 kfree(decoder);
554 kfree(client);
555
556 return 0;
557}
558
559/* ----------------------------------------------------------------------- */
560
561static struct i2c_driver i2c_driver_saa711x = {
562 .driver = {
563 .name = "saa711x",
564 },
565 .id = I2C_DRIVERID_SAA711X,
566 .attach_adapter = saa711x_attach_adapter,
567 .detach_client = saa711x_detach_client,
568 .command = saa711x_command,
569};
570
571static int __init
572saa711x_init (void)
573{
574 return i2c_add_driver(&i2c_driver_saa711x);
575}
576
577static void __exit
578saa711x_exit (void)
579{
580 i2c_del_driver(&i2c_driver_saa711x);
581}
582
583module_init(saa711x_init);
584module_exit(saa711x_exit);
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index 79d11a658bdf..d0e83fe0ff51 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -666,7 +666,6 @@ static int saa7127_probe(struct i2c_client *client,
666{ 666{
667 struct saa7127_state *state; 667 struct saa7127_state *state;
668 struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */ 668 struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */
669 int read_result = 0;
670 669
671 /* Check if the adapter supports the needed features */ 670 /* Check if the adapter supports the needed features */
672 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 671 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -710,20 +709,29 @@ static int saa7127_probe(struct i2c_client *client,
710 saa7127_set_input_type(client, SAA7127_INPUT_TYPE_NORMAL); 709 saa7127_set_input_type(client, SAA7127_INPUT_TYPE_NORMAL);
711 saa7127_set_video_enable(client, 1); 710 saa7127_set_video_enable(client, 1);
712 711
713 /* Detect if it's an saa7129 */ 712 if (id->driver_data) { /* Chip type is already known */
714 read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2); 713 state->ident = id->driver_data;
715 saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa); 714 } else { /* Needs detection */
716 if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { 715 int read_result;
717 v4l_info(client, "saa7129 found @ 0x%x (%s)\n", 716
718 client->addr << 1, client->adapter->name); 717 /* Detect if it's an saa7129 */
719 saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, read_result); 718 read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2);
720 saa7127_write_inittab(client, saa7129_init_config_extra); 719 saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa);
721 state->ident = V4L2_IDENT_SAA7129; 720 if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
722 } else { 721 saa7127_write(client, SAA7129_REG_FADE_KEY_COL2,
723 v4l_info(client, "saa7127 found @ 0x%x (%s)\n", 722 read_result);
724 client->addr << 1, client->adapter->name); 723 state->ident = V4L2_IDENT_SAA7129;
725 state->ident = V4L2_IDENT_SAA7127; 724 strlcpy(client->name, "saa7129", I2C_NAME_SIZE);
725 } else {
726 state->ident = V4L2_IDENT_SAA7127;
727 strlcpy(client->name, "saa7127", I2C_NAME_SIZE);
728 }
726 } 729 }
730
731 v4l_info(client, "%s found @ 0x%x (%s)\n", client->name,
732 client->addr << 1, client->adapter->name);
733 if (state->ident == V4L2_IDENT_SAA7129)
734 saa7127_write_inittab(client, saa7129_init_config_extra);
727 return 0; 735 return 0;
728} 736}
729 737
@@ -740,7 +748,11 @@ static int saa7127_remove(struct i2c_client *client)
740/* ----------------------------------------------------------------------- */ 748/* ----------------------------------------------------------------------- */
741 749
742static struct i2c_device_id saa7127_id[] = { 750static struct i2c_device_id saa7127_id[] = {
743 { "saa7127", 0 }, 751 { "saa7127_auto", 0 }, /* auto-detection */
752 { "saa7126", V4L2_IDENT_SAA7127 },
753 { "saa7127", V4L2_IDENT_SAA7127 },
754 { "saa7128", V4L2_IDENT_SAA7129 },
755 { "saa7129", V4L2_IDENT_SAA7129 },
744 { } 756 { }
745}; 757};
746MODULE_DEVICE_TABLE(i2c, saa7127_id); 758MODULE_DEVICE_TABLE(i2c, saa7127_id);
@@ -753,4 +765,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
753 .remove = saa7127_remove, 765 .remove = saa7127_remove,
754 .id_table = saa7127_id, 766 .id_table = saa7127_id,
755}; 767};
756
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 002e70a33a4f..707be175509d 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -13,7 +13,6 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/crc32.h> 14#include <linux/crc32.h>
15 15
16
17#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000 16#define MPEG_VIDEO_TARGET_BITRATE_MAX 27000
18#define MPEG_VIDEO_MAX_BITRATE_MAX 27000 17#define MPEG_VIDEO_MAX_BITRATE_MAX 27000
19#define MPEG_TOTAL_TARGET_BITRATE_MAX 27000 18#define MPEG_TOTAL_TARGET_BITRATE_MAX 27000
@@ -21,6 +20,7 @@
21 20
22/* Addresses to scan */ 21/* Addresses to scan */
23static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END}; 22static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END};
23
24I2C_CLIENT_INSMOD; 24I2C_CLIENT_INSMOD;
25 25
26MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder"); 26MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
@@ -448,6 +448,104 @@ static int handle_ctrl(struct saa6752hs_mpeg_params *params,
448 return 0; 448 return 0;
449} 449}
450 450
451static int saa6752hs_qctrl(struct saa6752hs_mpeg_params *params,
452 struct v4l2_queryctrl *qctrl)
453{
454 int err;
455
456 switch (qctrl->id) {
457 case V4L2_CID_MPEG_AUDIO_ENCODING:
458 return v4l2_ctrl_query_fill(qctrl,
459 V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
460 V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
461 V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
462
463 case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
464 return v4l2_ctrl_query_fill(qctrl,
465 V4L2_MPEG_AUDIO_L2_BITRATE_256K,
466 V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
467 V4L2_MPEG_AUDIO_L2_BITRATE_256K);
468
469 case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
470 return v4l2_ctrl_query_fill(qctrl,
471 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
472 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1,
473 V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
474
475 case V4L2_CID_MPEG_VIDEO_ENCODING:
476 return v4l2_ctrl_query_fill(qctrl,
477 V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
478 V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
479 V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
480
481 case V4L2_CID_MPEG_VIDEO_ASPECT:
482 return v4l2_ctrl_query_fill(qctrl,
483 V4L2_MPEG_VIDEO_ASPECT_4x3,
484 V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
485 V4L2_MPEG_VIDEO_ASPECT_4x3);
486
487 case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
488 err = v4l2_ctrl_query_fill_std(qctrl);
489 if (err == 0 &&
490 params->vi_bitrate_mode ==
491 V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
492 qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
493 return err;
494
495 case V4L2_CID_MPEG_STREAM_TYPE:
496 return v4l2_ctrl_query_fill(qctrl,
497 V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
498 V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1,
499 V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
500
501 case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
502 case V4L2_CID_MPEG_VIDEO_BITRATE:
503 case V4L2_CID_MPEG_STREAM_PID_PMT:
504 case V4L2_CID_MPEG_STREAM_PID_AUDIO:
505 case V4L2_CID_MPEG_STREAM_PID_VIDEO:
506 case V4L2_CID_MPEG_STREAM_PID_PCR:
507 return v4l2_ctrl_query_fill_std(qctrl);
508
509 default:
510 break;
511 }
512 return -EINVAL;
513}
514
515static int saa6752hs_qmenu(struct saa6752hs_mpeg_params *params,
516 struct v4l2_querymenu *qmenu)
517{
518 static const char *mpeg_audio_l2_bitrate[] = {
519 "",
520 "",
521 "",
522 "",
523 "",
524 "",
525 "",
526 "",
527 "",
528 "",
529 "",
530 "256 kbps",
531 "",
532 "384 kbps",
533 NULL
534 };
535 struct v4l2_queryctrl qctrl;
536 int err;
537
538 qctrl.id = qmenu->id;
539 err = saa6752hs_qctrl(params, &qctrl);
540 if (err)
541 return err;
542 if (qmenu->id == V4L2_CID_MPEG_AUDIO_L2_BITRATE)
543 return v4l2_ctrl_query_menu(qmenu, &qctrl,
544 mpeg_audio_l2_bitrate);
545 return v4l2_ctrl_query_menu(qmenu, &qctrl,
546 v4l2_ctrl_get_menu(qmenu->id));
547}
548
451static int saa6752hs_init(struct i2c_client* client) 549static int saa6752hs_init(struct i2c_client* client)
452{ 550{
453 unsigned char buf[9], buf2[4]; 551 unsigned char buf[9], buf2[4];
@@ -609,7 +707,6 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
609 i2c_attach_client(&h->client); 707 i2c_attach_client(&h->client);
610 708
611 v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1); 709 v4l_info(&h->client,"saa6752hs: chip found @ 0x%x\n", addr<<1);
612
613 return 0; 710 return 0;
614} 711}
615 712
@@ -662,6 +759,10 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
662 } 759 }
663 h->params = params; 760 h->params = params;
664 break; 761 break;
762 case VIDIOC_QUERYCTRL:
763 return saa6752hs_qctrl(&h->params, arg);
764 case VIDIOC_QUERYMENU:
765 return saa6752hs_qmenu(&h->params, arg);
665 case VIDIOC_G_FMT: 766 case VIDIOC_G_FMT:
666 { 767 {
667 struct v4l2_format *f = arg; 768 struct v4l2_format *f = arg;
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index f118de6e3672..9929d20320b4 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -80,7 +80,6 @@ typedef struct snd_card_saa7134 {
80} snd_card_saa7134_t; 80} snd_card_saa7134_t;
81 81
82 82
83
84/* 83/*
85 * PCM structure 84 * PCM structure
86 */ 85 */
@@ -1121,6 +1120,3 @@ late_initcall(saa7134_alsa_init);
1121module_exit(saa7134_alsa_exit); 1120module_exit(saa7134_alsa_exit);
1122MODULE_LICENSE("GPL"); 1121MODULE_LICENSE("GPL");
1123MODULE_AUTHOR("Ricardo Cerqueira"); 1122MODULE_AUTHOR("Ricardo Cerqueira");
1124
1125
1126
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 2618cfa592e7..6893f998d292 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -1287,6 +1287,22 @@ struct saa7134_board saa7134_boards[] = {
1287 .vmux = 8, 1287 .vmux = 8,
1288 }}, 1288 }},
1289 }, 1289 },
1290 [SAA7134_BOARD_AVERMEDIA_M103] = {
1291 /* Massimo Piccioni <dafastidio@libero.it> */
1292 .name = "AVerMedia MiniPCI DVB-T Hybrid M103",
1293 .audio_clock = 0x187de7,
1294 .tuner_type = TUNER_XC2028,
1295 .radio_type = UNSET,
1296 .tuner_addr = ADDR_UNSET,
1297 .radio_addr = ADDR_UNSET,
1298 .mpeg = SAA7134_MPEG_DVB,
1299 .inputs = {{
1300 .name = name_tv,
1301 .vmux = 1,
1302 .amux = TV,
1303 .tv = 1,
1304 } },
1305 },
1290 [SAA7134_BOARD_NOVAC_PRIMETV7133] = { 1306 [SAA7134_BOARD_NOVAC_PRIMETV7133] = {
1291 /* toshii@netbsd.org */ 1307 /* toshii@netbsd.org */
1292 .name = "Noval Prime TV 7133", 1308 .name = "Noval Prime TV 7133",
@@ -3503,6 +3519,39 @@ struct saa7134_board saa7134_boards[] = {
3503 .amux = TV, 3519 .amux = TV,
3504 .gpio = 0x0200000, 3520 .gpio = 0x0200000,
3505 }, 3521 },
3522 },
3523 [SAA7134_BOARD_ASUSTeK_P7131_ANALOG] = {
3524 .name = "ASUSTeK P7131 Analog",
3525 .audio_clock = 0x00187de7,
3526 .tuner_type = TUNER_PHILIPS_TDA8290,
3527 .radio_type = UNSET,
3528 .tuner_addr = ADDR_UNSET,
3529 .radio_addr = ADDR_UNSET,
3530 .gpiomask = 1 << 21,
3531 .inputs = {{
3532 .name = name_tv,
3533 .vmux = 1,
3534 .amux = TV,
3535 .tv = 1,
3536 .gpio = 0x0000000,
3537 }, {
3538 .name = name_comp1,
3539 .vmux = 3,
3540 .amux = LINE2,
3541 }, {
3542 .name = name_comp2,
3543 .vmux = 0,
3544 .amux = LINE2,
3545 }, {
3546 .name = name_svideo,
3547 .vmux = 8,
3548 .amux = LINE2,
3549 } },
3550 .radio = {
3551 .name = name_radio,
3552 .amux = TV,
3553 .gpio = 0x0200000,
3554 },
3506 }, 3555 },
3507 [SAA7134_BOARD_SABRENT_TV_PCB05] = { 3556 [SAA7134_BOARD_SABRENT_TV_PCB05] = {
3508 .name = "Sabrent PCMCIA TV-PCB05", 3557 .name = "Sabrent PCMCIA TV-PCB05",
@@ -3940,32 +3989,111 @@ struct saa7134_board saa7134_boards[] = {
3940 [SAA7134_BOARD_BEHOLD_M6] = { 3989 [SAA7134_BOARD_BEHOLD_M6] = {
3941 /* Igor Kuznetsov <igk@igk.ru> */ 3990 /* Igor Kuznetsov <igk@igk.ru> */
3942 /* Andrey Melnikoff <temnota@kmv.ru> */ 3991 /* Andrey Melnikoff <temnota@kmv.ru> */
3943 .name = "Beholder BeholdTV M6 / BeholdTV M6 Extra", 3992 /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
3993 .name = "Beholder BeholdTV M6",
3944 .audio_clock = 0x00187de7, 3994 .audio_clock = 0x00187de7,
3945 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, 3995 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
3946 .radio_type = UNSET, 3996 .radio_type = UNSET,
3947 .tuner_addr = ADDR_UNSET, 3997 .tuner_addr = ADDR_UNSET,
3948 .radio_addr = ADDR_UNSET, 3998 .radio_addr = ADDR_UNSET,
3949 .tda9887_conf = TDA9887_PRESENT, 3999 .tda9887_conf = TDA9887_PRESENT,
3950 .inputs = {{ 4000 .inputs = { {
3951 .name = name_tv, 4001 .name = name_tv,
3952 .vmux = 3, 4002 .vmux = 3,
3953 .amux = TV, 4003 .amux = TV,
3954 .tv = 1, 4004 .tv = 1,
3955 },{ 4005 }, {
3956 .name = name_comp1, 4006 .name = name_comp1,
3957 .vmux = 1, 4007 .vmux = 1,
3958 .amux = LINE1, 4008 .amux = LINE1,
3959 },{ 4009 }, {
3960 .name = name_svideo, 4010 .name = name_svideo,
3961 .vmux = 8, 4011 .vmux = 8,
3962 .amux = LINE1, 4012 .amux = LINE1,
3963 }}, 4013 } },
3964 .radio = { 4014 .radio = {
3965 .name = name_radio, 4015 .name = name_radio,
3966 .amux = LINE2, 4016 .amux = LINE2,
3967 }, 4017 },
3968 .mpeg = SAA7134_MPEG_EMPRESS, 4018 .mpeg = SAA7134_MPEG_EMPRESS,
4019 .video_out = CCIR656,
4020 .vid_port_opts = (SET_T_CODE_POLARITY_NON_INVERTED |
4021 SET_CLOCK_NOT_DELAYED |
4022 SET_CLOCK_INVERTED |
4023 SET_VSYNC_OFF),
4024 },
4025 [SAA7134_BOARD_BEHOLD_M63] = {
4026 /* Igor Kuznetsov <igk@igk.ru> */
4027 /* Andrey Melnikoff <temnota@kmv.ru> */
4028 /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
4029 .name = "Beholder BeholdTV M63",
4030 .audio_clock = 0x00187de7,
4031 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
4032 .radio_type = UNSET,
4033 .tuner_addr = ADDR_UNSET,
4034 .radio_addr = ADDR_UNSET,
4035 .tda9887_conf = TDA9887_PRESENT,
4036 .inputs = { {
4037 .name = name_tv,
4038 .vmux = 3,
4039 .amux = TV,
4040 .tv = 1,
4041 }, {
4042 .name = name_comp1,
4043 .vmux = 1,
4044 .amux = LINE1,
4045 }, {
4046 .name = name_svideo,
4047 .vmux = 8,
4048 .amux = LINE1,
4049 } },
4050 .radio = {
4051 .name = name_radio,
4052 .amux = LINE2,
4053 },
4054 .mpeg = SAA7134_MPEG_EMPRESS,
4055 .video_out = CCIR656,
4056 .vid_port_opts = (SET_T_CODE_POLARITY_NON_INVERTED |
4057 SET_CLOCK_NOT_DELAYED |
4058 SET_CLOCK_INVERTED |
4059 SET_VSYNC_OFF),
4060 },
4061 [SAA7134_BOARD_BEHOLD_M6_EXTRA] = {
4062 /* Igor Kuznetsov <igk@igk.ru> */
4063 /* Andrey Melnikoff <temnota@kmv.ru> */
4064 /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
4065 .name = "Beholder BeholdTV M6 Extra",
4066 .audio_clock = 0x00187de7,
4067 /* FIXME: Must be PHILIPS_FM1216ME_MK5*/
4068 .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
4069 .radio_type = UNSET,
4070 .tuner_addr = ADDR_UNSET,
4071 .radio_addr = ADDR_UNSET,
4072 .tda9887_conf = TDA9887_PRESENT,
4073 .inputs = { {
4074 .name = name_tv,
4075 .vmux = 3,
4076 .amux = TV,
4077 .tv = 1,
4078 }, {
4079 .name = name_comp1,
4080 .vmux = 1,
4081 .amux = LINE1,
4082 }, {
4083 .name = name_svideo,
4084 .vmux = 8,
4085 .amux = LINE1,
4086 } },
4087 .radio = {
4088 .name = name_radio,
4089 .amux = LINE2,
4090 },
4091 .mpeg = SAA7134_MPEG_EMPRESS,
4092 .video_out = CCIR656,
4093 .vid_port_opts = (SET_T_CODE_POLARITY_NON_INVERTED |
4094 SET_CLOCK_NOT_DELAYED |
4095 SET_CLOCK_INVERTED |
4096 SET_VSYNC_OFF),
3969 }, 4097 },
3970 [SAA7134_BOARD_TWINHAN_DTV_DVB_3056] = { 4098 [SAA7134_BOARD_TWINHAN_DTV_DVB_3056] = {
3971 .name = "Twinhan Hybrid DTV-DVB 3056 PCI", 4099 .name = "Twinhan Hybrid DTV-DVB 3056 PCI",
@@ -4121,9 +4249,9 @@ struct saa7134_board saa7134_boards[] = {
4121 .amux = TV, 4249 .amux = TV,
4122 .tv = 1, 4250 .tv = 1,
4123 }, { 4251 }, {
4124 .name = name_comp1, 4252 .name = name_comp,
4125 .vmux = 3, 4253 .vmux = 0,
4126 .amux = LINE2, 4254 .amux = LINE1,
4127 }, { 4255 }, {
4128 .name = name_svideo, 4256 .name = name_svideo,
4129 .vmux = 8, 4257 .vmux = 8,
@@ -4141,6 +4269,7 @@ struct saa7134_board saa7134_boards[] = {
4141 .radio_type = UNSET, 4269 .radio_type = UNSET,
4142 .tuner_addr = ADDR_UNSET, 4270 .tuner_addr = ADDR_UNSET,
4143 .radio_addr = ADDR_UNSET, 4271 .radio_addr = ADDR_UNSET,
4272 .mpeg = SAA7134_MPEG_DVB,
4144 .inputs = {{ 4273 .inputs = {{
4145 .name = name_tv, 4274 .name = name_tv,
4146 .vmux = 1, 4275 .vmux = 1,
@@ -4150,6 +4279,10 @@ struct saa7134_board saa7134_boards[] = {
4150 .name = name_svideo, 4279 .name = name_svideo,
4151 .vmux = 8, 4280 .vmux = 8,
4152 .amux = LINE1, 4281 .amux = LINE1,
4282 }, {
4283 .name = name_comp,
4284 .vmux = 0,
4285 .amux = LINE1,
4153 } }, 4286 } },
4154 .radio = { 4287 .radio = {
4155 .name = name_radio, 4288 .name = name_radio,
@@ -4163,7 +4296,6 @@ struct saa7134_board saa7134_boards[] = {
4163 .radio_type = UNSET, 4296 .radio_type = UNSET,
4164 .tuner_addr = ADDR_UNSET, 4297 .tuner_addr = ADDR_UNSET,
4165 .radio_addr = ADDR_UNSET, 4298 .radio_addr = ADDR_UNSET,
4166 .mpeg = SAA7134_MPEG_DVB,
4167 .inputs = {{ 4299 .inputs = {{
4168 .name = name_tv, 4300 .name = name_tv,
4169 .vmux = 1, 4301 .vmux = 1,
@@ -5226,13 +5358,13 @@ struct pci_device_id saa7134_pci_tbl[] = {
5226 .device = PCI_DEVICE_ID_PHILIPS_SAA7133, 5358 .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
5227 .subvendor = 0x5ace, 5359 .subvendor = 0x5ace,
5228 .subdevice = 0x6193, 5360 .subdevice = 0x6193,
5229 .driver_data = SAA7134_BOARD_BEHOLD_M6, 5361 .driver_data = SAA7134_BOARD_BEHOLD_M6_EXTRA,
5230 }, { 5362 }, {
5231 .vendor = PCI_VENDOR_ID_PHILIPS, 5363 .vendor = PCI_VENDOR_ID_PHILIPS,
5232 .device = PCI_DEVICE_ID_PHILIPS_SAA7133, 5364 .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
5233 .subvendor = 0x5ace, 5365 .subvendor = 0x5ace,
5234 .subdevice = 0x6191, 5366 .subdevice = 0x6191,
5235 .driver_data = SAA7134_BOARD_BEHOLD_M6, 5367 .driver_data = SAA7134_BOARD_BEHOLD_M63,
5236 },{ 5368 },{
5237 .vendor = PCI_VENDOR_ID_PHILIPS, 5369 .vendor = PCI_VENDOR_ID_PHILIPS,
5238 .device = PCI_DEVICE_ID_PHILIPS_SAA7133, 5370 .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -5284,10 +5416,22 @@ struct pci_device_id saa7134_pci_tbl[] = {
5284 }, { 5416 }, {
5285 .vendor = PCI_VENDOR_ID_PHILIPS, 5417 .vendor = PCI_VENDOR_ID_PHILIPS,
5286 .device = PCI_DEVICE_ID_PHILIPS_SAA7133, 5418 .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
5419 .subvendor = 0x5169,
5420 .subdevice = 0x1502,
5421 .driver_data = SAA7134_BOARD_FLYTVPLATINUM_MINI,
5422 }, {
5423 .vendor = PCI_VENDOR_ID_PHILIPS,
5424 .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
5287 .subvendor = 0x5ace, 5425 .subvendor = 0x5ace,
5288 .subdevice = 0x6290, 5426 .subdevice = 0x6290,
5289 .driver_data = SAA7134_BOARD_BEHOLD_H6, 5427 .driver_data = SAA7134_BOARD_BEHOLD_H6,
5290 }, { 5428 }, {
5429 .vendor = PCI_VENDOR_ID_PHILIPS,
5430 .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
5431 .subvendor = 0x1461, /* Avermedia Technologies Inc */
5432 .subdevice = 0xf636,
5433 .driver_data = SAA7134_BOARD_AVERMEDIA_M103,
5434 }, {
5291 /* --- boards without eeprom + subsystem ID --- */ 5435 /* --- boards without eeprom + subsystem ID --- */
5292 .vendor = PCI_VENDOR_ID_PHILIPS, 5436 .vendor = PCI_VENDOR_ID_PHILIPS,
5293 .device = PCI_DEVICE_ID_PHILIPS_SAA7134, 5437 .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -5352,6 +5496,7 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev,
5352 saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000); 5496 saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
5353 switch (dev->board) { 5497 switch (dev->board) {
5354 case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: 5498 case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
5499 case SAA7134_BOARD_AVERMEDIA_M103:
5355 saa7134_set_gpio(dev, 23, 0); 5500 saa7134_set_gpio(dev, 23, 0);
5356 msleep(10); 5501 msleep(10);
5357 saa7134_set_gpio(dev, 23, 1); 5502 saa7134_set_gpio(dev, 23, 1);
@@ -5493,6 +5638,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
5493 case SAA7134_BOARD_FLYDVBT_LR301: 5638 case SAA7134_BOARD_FLYDVBT_LR301:
5494 case SAA7134_BOARD_ASUSTeK_P7131_DUAL: 5639 case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
5495 case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: 5640 case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
5641 case SAA7134_BOARD_ASUSTeK_P7131_ANALOG:
5496 case SAA7134_BOARD_FLYDVBTDUO: 5642 case SAA7134_BOARD_FLYDVBTDUO:
5497 case SAA7134_BOARD_PROTEUS_2309: 5643 case SAA7134_BOARD_PROTEUS_2309:
5498 case SAA7134_BOARD_AVERMEDIA_A16AR: 5644 case SAA7134_BOARD_AVERMEDIA_A16AR:
@@ -5560,6 +5706,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
5560 msleep(10); 5706 msleep(10);
5561 break; 5707 break;
5562 case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: 5708 case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
5709 case SAA7134_BOARD_AVERMEDIA_M103:
5563 saa7134_set_gpio(dev, 23, 0); 5710 saa7134_set_gpio(dev, 23, 0);
5564 msleep(10); 5711 msleep(10);
5565 saa7134_set_gpio(dev, 23, 1); 5712 saa7134_set_gpio(dev, 23, 1);
@@ -5601,6 +5748,8 @@ int saa7134_board_init1(struct saa7134_dev *dev)
5601 case SAA7134_BOARD_HAUPPAUGE_HVR1110: 5748 case SAA7134_BOARD_HAUPPAUGE_HVR1110:
5602 case SAA7134_BOARD_BEHOLD_607_9FM: 5749 case SAA7134_BOARD_BEHOLD_607_9FM:
5603 case SAA7134_BOARD_BEHOLD_M6: 5750 case SAA7134_BOARD_BEHOLD_M6:
5751 case SAA7134_BOARD_BEHOLD_M63:
5752 case SAA7134_BOARD_BEHOLD_M6_EXTRA:
5604 dev->has_remote = SAA7134_REMOTE_I2C; 5753 dev->has_remote = SAA7134_REMOTE_I2C;
5605 break; 5754 break;
5606 case SAA7134_BOARD_AVERMEDIA_A169_B: 5755 case SAA7134_BOARD_AVERMEDIA_A169_B:
@@ -5683,6 +5832,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev)
5683 switch (dev->board) { 5832 switch (dev->board) {
5684 case SAA7134_BOARD_AVERMEDIA_A16D: 5833 case SAA7134_BOARD_AVERMEDIA_A16D:
5685 case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: 5834 case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
5835 case SAA7134_BOARD_AVERMEDIA_M103:
5686 ctl.demod = XC3028_FE_ZARLINK456; 5836 ctl.demod = XC3028_FE_ZARLINK456;
5687 break; 5837 break;
5688 default: 5838 default:
@@ -5825,6 +5975,15 @@ int saa7134_board_init2(struct saa7134_dev *dev)
5825 i2c_transfer(&dev->i2c_adap, &msg, 1); 5975 i2c_transfer(&dev->i2c_adap, &msg, 1);
5826 break; 5976 break;
5827 } 5977 }
5978 case SAA7134_BOARD_ASUSTeK_TVFM7135:
5979 /* The card below is detected as card=53, but is different */
5980 if (dev->autodetected && (dev->eedata[0x27] == 0x03)) {
5981 dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG;
5982 printk(KERN_INFO "%s: P7131 analog only, using "
5983 "entry of %s\n",
5984 dev->name, saa7134_boards[dev->board].name);
5985 }
5986 break;
5828 case SAA7134_BOARD_HAUPPAUGE_HVR1110: 5987 case SAA7134_BOARD_HAUPPAUGE_HVR1110:
5829 hauppauge_eeprom(dev, dev->eedata+0x80); 5988 hauppauge_eeprom(dev, dev->eedata+0x80);
5830 /* break intentionally omitted */ 5989 /* break intentionally omitted */
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 2c19cd0113c8..cfee84ee7a88 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -150,7 +150,6 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
150 150
151#if defined(CONFIG_MODULES) && defined(MODULE) 151#if defined(CONFIG_MODULES) && defined(MODULE)
152 152
153
154static void request_module_async(struct work_struct *work){ 153static void request_module_async(struct work_struct *work){
155 struct saa7134_dev* dev = container_of(work, struct saa7134_dev, request_module_wk); 154 struct saa7134_dev* dev = container_of(work, struct saa7134_dev, request_module_wk);
156 if (card_is_empress(dev)) 155 if (card_is_empress(dev))
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 341b101b0357..be48b9b66a67 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1263,6 +1263,7 @@ static int dvb_init(struct saa7134_dev *dev)
1263 &avermedia_xc3028_mt352_dev, 1263 &avermedia_xc3028_mt352_dev,
1264 &dev->i2c_adap); 1264 &dev->i2c_adap);
1265 attach_xc3028 = 1; 1265 attach_xc3028 = 1;
1266 break;
1266 case SAA7134_BOARD_MD7134_BRIDGE_2: 1267 case SAA7134_BOARD_MD7134_BRIDGE_2:
1267 dev->dvb.frontend = dvb_attach(tda10086_attach, 1268 dev->dvb.frontend = dvb_attach(tda10086_attach,
1268 &sd1878_4m, &dev->i2c_adap); 1269 &sd1878_4m, &dev->i2c_adap);
@@ -1290,6 +1291,15 @@ static int dvb_init(struct saa7134_dev *dev)
1290 fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage; 1291 fe->ops.enable_high_lnb_voltage = md8800_set_high_voltage;
1291 } 1292 }
1292 break; 1293 break;
1294 case SAA7134_BOARD_AVERMEDIA_M103:
1295 saa7134_set_gpio(dev, 25, 0);
1296 msleep(10);
1297 saa7134_set_gpio(dev, 25, 1);
1298 dev->dvb.frontend = dvb_attach(mt352_attach,
1299 &avermedia_xc3028_mt352_dev,
1300 &dev->i2c_adap);
1301 attach_xc3028 = 1;
1302 break;
1293 default: 1303 default:
1294 wprintk("Huh? unknown DVB card?\n"); 1304 wprintk("Huh? unknown DVB card?\n");
1295 break; 1305 break;
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 3ae71a340822..2a5ab957542d 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -208,7 +208,7 @@ static int empress_s_input(struct file *file, void *priv, unsigned int i)
208 return 0; 208 return 0;
209} 209}
210 210
211static int empress_enum_fmt_cap(struct file *file, void *priv, 211static int empress_enum_fmt_vid_cap(struct file *file, void *priv,
212 struct v4l2_fmtdesc *f) 212 struct v4l2_fmtdesc *f)
213{ 213{
214 if (f->index != 0) 214 if (f->index != 0)
@@ -220,7 +220,7 @@ static int empress_enum_fmt_cap(struct file *file, void *priv,
220 return 0; 220 return 0;
221} 221}
222 222
223static int empress_g_fmt_cap(struct file *file, void *priv, 223static int empress_g_fmt_vid_cap(struct file *file, void *priv,
224 struct v4l2_format *f) 224 struct v4l2_format *f)
225{ 225{
226 struct saa7134_dev *dev = file->private_data; 226 struct saa7134_dev *dev = file->private_data;
@@ -233,7 +233,7 @@ static int empress_g_fmt_cap(struct file *file, void *priv,
233 return 0; 233 return 0;
234} 234}
235 235
236static int empress_s_fmt_cap(struct file *file, void *priv, 236static int empress_s_fmt_vid_cap(struct file *file, void *priv,
237 struct v4l2_format *f) 237 struct v4l2_format *f)
238{ 238{
239 struct saa7134_dev *dev = file->private_data; 239 struct saa7134_dev *dev = file->private_data;
@@ -294,10 +294,20 @@ static int empress_streamoff(struct file *file, void *priv,
294 return videobuf_streamoff(&dev->empress_tsq); 294 return videobuf_streamoff(&dev->empress_tsq);
295} 295}
296 296
297static int saa7134_i2c_call_saa6752(struct saa7134_dev *dev,
298 unsigned int cmd, void *arg)
299{
300 if (dev->mpeg_i2c_client == NULL)
301 return -EINVAL;
302 return dev->mpeg_i2c_client->driver->command(dev->mpeg_i2c_client,
303 cmd, arg);
304}
305
297static int empress_s_ext_ctrls(struct file *file, void *priv, 306static int empress_s_ext_ctrls(struct file *file, void *priv,
298 struct v4l2_ext_controls *ctrls) 307 struct v4l2_ext_controls *ctrls)
299{ 308{
300 struct saa7134_dev *dev = file->private_data; 309 struct saa7134_dev *dev = file->private_data;
310 int err;
301 311
302 /* count == 0 is abused in saa6752hs.c, so that special 312 /* count == 0 is abused in saa6752hs.c, so that special
303 case is handled here explicitly. */ 313 case is handled here explicitly. */
@@ -307,10 +317,10 @@ static int empress_s_ext_ctrls(struct file *file, void *priv,
307 if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) 317 if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
308 return -EINVAL; 318 return -EINVAL;
309 319
310 saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, ctrls); 320 err = saa7134_i2c_call_saa6752(dev, VIDIOC_S_EXT_CTRLS, ctrls);
311 ts_init_encoder(dev); 321 ts_init_encoder(dev);
312 322
313 return 0; 323 return err;
314} 324}
315 325
316static int empress_g_ext_ctrls(struct file *file, void *priv, 326static int empress_g_ext_ctrls(struct file *file, void *priv,
@@ -320,9 +330,62 @@ static int empress_g_ext_ctrls(struct file *file, void *priv,
320 330
321 if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) 331 if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
322 return -EINVAL; 332 return -EINVAL;
323 saa7134_i2c_call_clients(dev, VIDIOC_G_EXT_CTRLS, ctrls); 333 return saa7134_i2c_call_saa6752(dev, VIDIOC_G_EXT_CTRLS, ctrls);
334}
324 335
325 return 0; 336static int empress_queryctrl(struct file *file, void *priv,
337 struct v4l2_queryctrl *c)
338{
339 static const u32 user_ctrls[] = {
340 V4L2_CID_USER_CLASS,
341 V4L2_CID_BRIGHTNESS,
342 V4L2_CID_CONTRAST,
343 V4L2_CID_SATURATION,
344 V4L2_CID_HUE,
345 V4L2_CID_AUDIO_VOLUME,
346 V4L2_CID_AUDIO_MUTE,
347 V4L2_CID_HFLIP,
348 0
349 };
350
351 static const u32 mpeg_ctrls[] = {
352 V4L2_CID_MPEG_CLASS,
353 V4L2_CID_MPEG_STREAM_TYPE,
354 V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
355 V4L2_CID_MPEG_AUDIO_ENCODING,
356 V4L2_CID_MPEG_AUDIO_L2_BITRATE,
357 V4L2_CID_MPEG_VIDEO_ENCODING,
358 V4L2_CID_MPEG_VIDEO_ASPECT,
359 V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
360 V4L2_CID_MPEG_VIDEO_BITRATE,
361 V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
362 0
363 };
364 static const u32 *ctrl_classes[] = {
365 user_ctrls,
366 mpeg_ctrls,
367 NULL
368 };
369 struct saa7134_dev *dev = file->private_data;
370
371 c->id = v4l2_ctrl_next(ctrl_classes, c->id);
372 if (c->id == 0)
373 return -EINVAL;
374 if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS)
375 return v4l2_ctrl_query_fill_std(c);
376 if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
377 return saa7134_queryctrl(file, priv, c);
378 return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYCTRL, c);
379}
380
381static int empress_querymenu(struct file *file, void *priv,
382 struct v4l2_querymenu *c)
383{
384 struct saa7134_dev *dev = file->private_data;
385
386 if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
387 return -EINVAL;
388 return saa7134_i2c_call_saa6752(dev, VIDIOC_QUERYMENU, c);
326} 389}
327 390
328static const struct file_operations ts_fops = 391static const struct file_operations ts_fops =
@@ -348,9 +411,9 @@ static struct video_device saa7134_empress_template =
348 .minor = -1, 411 .minor = -1,
349 412
350 .vidioc_querycap = empress_querycap, 413 .vidioc_querycap = empress_querycap,
351 .vidioc_enum_fmt_cap = empress_enum_fmt_cap, 414 .vidioc_enum_fmt_vid_cap = empress_enum_fmt_vid_cap,
352 .vidioc_s_fmt_cap = empress_s_fmt_cap, 415 .vidioc_s_fmt_vid_cap = empress_s_fmt_vid_cap,
353 .vidioc_g_fmt_cap = empress_g_fmt_cap, 416 .vidioc_g_fmt_vid_cap = empress_g_fmt_vid_cap,
354 .vidioc_reqbufs = empress_reqbufs, 417 .vidioc_reqbufs = empress_reqbufs,
355 .vidioc_querybuf = empress_querybuf, 418 .vidioc_querybuf = empress_querybuf,
356 .vidioc_qbuf = empress_qbuf, 419 .vidioc_qbuf = empress_qbuf,
@@ -363,7 +426,8 @@ static struct video_device saa7134_empress_template =
363 .vidioc_g_input = empress_g_input, 426 .vidioc_g_input = empress_g_input,
364 .vidioc_s_input = empress_s_input, 427 .vidioc_s_input = empress_s_input,
365 428
366 .vidioc_queryctrl = saa7134_queryctrl, 429 .vidioc_queryctrl = empress_queryctrl,
430 .vidioc_querymenu = empress_querymenu,
367 .vidioc_g_ctrl = saa7134_g_ctrl, 431 .vidioc_g_ctrl = saa7134_g_ctrl,
368 .vidioc_s_ctrl = saa7134_s_ctrl, 432 .vidioc_s_ctrl = saa7134_s_ctrl,
369 433
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index d8af3863f2d3..5f713e637683 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -327,6 +327,8 @@ static int attach_inform(struct i2c_client *client)
327 327
328 d1printk( "%s i2c attach [addr=0x%x,client=%s]\n", 328 d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
329 client->driver->driver.name, client->addr, client->name); 329 client->driver->driver.name, client->addr, client->name);
330 if (client->addr == 0x20 && client->driver && client->driver->command)
331 dev->mpeg_i2c_client = client;
330 332
331 /* Am I an i2c remote control? */ 333 /* Am I an i2c remote control? */
332 334
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 76e6501d238d..ad08d13dffdd 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -198,6 +198,84 @@ static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
198 return 1; 198 return 1;
199} 199}
200 200
201/* Common (grey or coloured) pinnacle PCTV remote handling
202 *
203 */
204static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
205 int parity_offset, int marker, int code_modulo)
206{
207 unsigned char b[4];
208 unsigned int start = 0,parity = 0,code = 0;
209
210 /* poll IR chip */
211 if (4 != i2c_master_recv(&ir->c, b, 4)) {
212 i2cdprintk("read error\n");
213 return -EIO;
214 }
215
216 for (start = 0; start < ARRAY_SIZE(b); start++) {
217 if (b[start] == marker) {
218 code=b[(start+parity_offset + 1) % 4];
219 parity=b[(start+parity_offset) % 4];
220 }
221 }
222
223 /* Empty Request */
224 if (parity == 0)
225 return 0;
226
227 /* Repeating... */
228 if (ir->old == parity)
229 return 0;
230
231 ir->old = parity;
232
233 /* drop special codes when a key is held down a long time for the grey controller
234 In this case, the second bit of the code is asserted */
235 if (marker == 0xfe && (code & 0x40))
236 return 0;
237
238 code %= code_modulo;
239
240 *ir_raw = code;
241 *ir_key = code;
242
243 i2cdprintk("Pinnacle PCTV key %02x\n", code);
244
245 return 1;
246}
247
248/* The grey pinnacle PCTV remote
249 *
250 * There are one issue with this remote:
251 * - I2c packet does not change when the same key is pressed quickly. The workaround
252 * is to hold down each key for about half a second, so that another code is generated
253 * in the i2c packet, and the function can distinguish key presses.
254 *
255 * Sylvain Pasche <sylvain.pasche@gmail.com>
256 */
257static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
258{
259
260 return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
261}
262
263
264/* The new pinnacle PCTV remote (with the colored buttons)
265 *
266 * Ricardo Cerqueira <v4l@cerqueira.org>
267 */
268static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
269{
270 /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
271 *
272 * this is the only value that results in 42 unique
273 * codes < 128
274 */
275
276 return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
277}
278
201void saa7134_input_irq(struct saa7134_dev *dev) 279void saa7134_input_irq(struct saa7134_dev *dev)
202{ 280{
203 struct card_ir *ir = dev->remote; 281 struct card_ir *ir = dev->remote;
@@ -409,6 +487,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
409 break; 487 break;
410 case SAA7134_BOARD_ASUSTeK_P7131_DUAL: 488 case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
411 case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: 489 case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
490 case SAA7134_BOARD_ASUSTeK_P7131_ANALOG:
412 ir_codes = ir_codes_asus_pc39; 491 ir_codes = ir_codes_asus_pc39;
413 mask_keydown = 0x0040000; 492 mask_keydown = 0x0040000;
414 rc5_gpio = 1; 493 rc5_gpio = 1;
@@ -540,6 +619,8 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
540 break; 619 break;
541 case SAA7134_BOARD_BEHOLD_607_9FM: 620 case SAA7134_BOARD_BEHOLD_607_9FM:
542 case SAA7134_BOARD_BEHOLD_M6: 621 case SAA7134_BOARD_BEHOLD_M6:
622 case SAA7134_BOARD_BEHOLD_M63:
623 case SAA7134_BOARD_BEHOLD_M6_EXTRA:
543 case SAA7134_BOARD_BEHOLD_H6: 624 case SAA7134_BOARD_BEHOLD_H6:
544 snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV"); 625 snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV");
545 ir->get_key = get_key_beholdm6xx; 626 ir->get_key = get_key_beholdm6xx;
diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h
index 86f5eefdb0f6..cf89d96d7295 100644
--- a/drivers/media/video/saa7134/saa7134-reg.h
+++ b/drivers/media/video/saa7134/saa7134-reg.h
@@ -368,6 +368,7 @@
368#define SAA7135_DSP_RWCLEAR 0x586 368#define SAA7135_DSP_RWCLEAR 0x586
369#define SAA7135_DSP_RWCLEAR_RERR 1 369#define SAA7135_DSP_RWCLEAR_RERR 1
370 370
371#define SAA7133_I2S_AUDIO_CONTROL 0x591
371/* ------------------------------------------------------------------ */ 372/* ------------------------------------------------------------------ */
372/* 373/*
373 * Local variables: 374 * Local variables:
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 232af598d947..c5d0b44c179e 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -477,7 +477,6 @@ static int tvaudio_thread(void *data)
477 unsigned int i, audio, nscan; 477 unsigned int i, audio, nscan;
478 int max1,max2,carrier,rx,mode,lastmode,default_carrier; 478 int max1,max2,carrier,rx,mode,lastmode,default_carrier;
479 479
480
481 set_freezable(); 480 set_freezable();
482 481
483 for (;;) { 482 for (;;) {
@@ -775,7 +774,6 @@ static int tvaudio_thread_ddep(void *data)
775 struct saa7134_dev *dev = data; 774 struct saa7134_dev *dev = data;
776 u32 value, norms; 775 u32 value, norms;
777 776
778
779 set_freezable(); 777 set_freezable();
780 for (;;) { 778 for (;;) {
781 tvaudio_sleep(dev,-1); 779 tvaudio_sleep(dev,-1);
@@ -873,13 +871,34 @@ void saa7134_enable_i2s(struct saa7134_dev *dev)
873 871
874 if (!card_is_empress(dev)) 872 if (!card_is_empress(dev))
875 return; 873 return;
876 i2s_format = (dev->input->amux == TV) ? 0x00 : 0x01;
877 874
878 /* enable I2S audio output for the mpeg encoder */ 875 if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
879 saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80); 876 return;
880 saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2s_format); 877
881 saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F); 878 /* configure GPIO for out */
882 saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01); 879 saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0E000000, 0x00000000);
880
881 switch (dev->pci->device) {
882 case PCI_DEVICE_ID_PHILIPS_SAA7133:
883 case PCI_DEVICE_ID_PHILIPS_SAA7135:
884 /* Set I2S format (SONY)  */
885 saa_writeb(SAA7133_I2S_AUDIO_CONTROL, 0x00);
886 /* Start I2S */
887 saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x11);
888 break;
889
890 case PCI_DEVICE_ID_PHILIPS_SAA7134:
891 i2s_format = (dev->input->amux == TV) ? 0x00 : 0x01;
892
893 /* enable I2S audio output for the mpeg encoder */
894 saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80);
895 saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2s_format);
896 saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F);
897 saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01);
898
899 default:
900 break;
901 }
883} 902}
884 903
885int saa7134_tvaudio_rx2mode(u32 rx) 904int saa7134_tvaudio_rx2mode(u32 rx)
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 48e1a01718ec..1a5137550e7a 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1496,7 +1496,7 @@ static int video_mmap(struct file *file, struct vm_area_struct * vma)
1496 1496
1497/* ------------------------------------------------------------------ */ 1497/* ------------------------------------------------------------------ */
1498 1498
1499static int saa7134_try_get_set_fmt_vbi(struct file *file, void *priv, 1499static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,
1500 struct v4l2_format *f) 1500 struct v4l2_format *f)
1501{ 1501{
1502 struct saa7134_fh *fh = priv; 1502 struct saa7134_fh *fh = priv;
@@ -1516,7 +1516,7 @@ static int saa7134_try_get_set_fmt_vbi(struct file *file, void *priv,
1516 return 0; 1516 return 0;
1517} 1517}
1518 1518
1519static int saa7134_g_fmt_cap(struct file *file, void *priv, 1519static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
1520 struct v4l2_format *f) 1520 struct v4l2_format *f)
1521{ 1521{
1522 struct saa7134_fh *fh = priv; 1522 struct saa7134_fh *fh = priv;
@@ -1532,7 +1532,7 @@ static int saa7134_g_fmt_cap(struct file *file, void *priv,
1532 return 0; 1532 return 0;
1533} 1533}
1534 1534
1535static int saa7134_g_fmt_overlay(struct file *file, void *priv, 1535static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
1536 struct v4l2_format *f) 1536 struct v4l2_format *f)
1537{ 1537{
1538 struct saa7134_fh *fh = priv; 1538 struct saa7134_fh *fh = priv;
@@ -1546,7 +1546,7 @@ static int saa7134_g_fmt_overlay(struct file *file, void *priv,
1546 return 0; 1546 return 0;
1547} 1547}
1548 1548
1549static int saa7134_try_fmt_cap(struct file *file, void *priv, 1549static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
1550 struct v4l2_format *f) 1550 struct v4l2_format *f)
1551{ 1551{
1552 struct saa7134_fh *fh = priv; 1552 struct saa7134_fh *fh = priv;
@@ -1597,7 +1597,7 @@ static int saa7134_try_fmt_cap(struct file *file, void *priv,
1597 return 0; 1597 return 0;
1598} 1598}
1599 1599
1600static int saa7134_try_fmt_overlay(struct file *file, void *priv, 1600static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
1601 struct v4l2_format *f) 1601 struct v4l2_format *f)
1602{ 1602{
1603 struct saa7134_fh *fh = priv; 1603 struct saa7134_fh *fh = priv;
@@ -1611,13 +1611,13 @@ static int saa7134_try_fmt_overlay(struct file *file, void *priv,
1611 return verify_preview(dev, &f->fmt.win); 1611 return verify_preview(dev, &f->fmt.win);
1612} 1612}
1613 1613
1614static int saa7134_s_fmt_cap(struct file *file, void *priv, 1614static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
1615 struct v4l2_format *f) 1615 struct v4l2_format *f)
1616{ 1616{
1617 struct saa7134_fh *fh = priv; 1617 struct saa7134_fh *fh = priv;
1618 int err; 1618 int err;
1619 1619
1620 err = saa7134_try_fmt_cap(file, priv, f); 1620 err = saa7134_try_fmt_vid_cap(file, priv, f);
1621 if (0 != err) 1621 if (0 != err)
1622 return err; 1622 return err;
1623 1623
@@ -1628,7 +1628,7 @@ static int saa7134_s_fmt_cap(struct file *file, void *priv,
1628 return 0; 1628 return 0;
1629} 1629}
1630 1630
1631static int saa7134_s_fmt_overlay(struct file *file, void *priv, 1631static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
1632 struct v4l2_format *f) 1632 struct v4l2_format *f)
1633{ 1633{
1634 struct saa7134_fh *fh = priv; 1634 struct saa7134_fh *fh = priv;
@@ -2028,7 +2028,7 @@ static int saa7134_s_priority(struct file *file, void *f,
2028 return v4l2_prio_change(&dev->prio, &fh->prio, prio); 2028 return v4l2_prio_change(&dev->prio, &fh->prio, prio);
2029} 2029}
2030 2030
2031static int saa7134_enum_fmt_cap(struct file *file, void *priv, 2031static int saa7134_enum_fmt_vid_cap(struct file *file, void *priv,
2032 struct v4l2_fmtdesc *f) 2032 struct v4l2_fmtdesc *f)
2033{ 2033{
2034 if (f->index >= FORMATS) 2034 if (f->index >= FORMATS)
@@ -2042,7 +2042,7 @@ static int saa7134_enum_fmt_cap(struct file *file, void *priv,
2042 return 0; 2042 return 0;
2043} 2043}
2044 2044
2045static int saa7134_enum_fmt_overlay(struct file *file, void *priv, 2045static int saa7134_enum_fmt_vid_overlay(struct file *file, void *priv,
2046 struct v4l2_fmtdesc *f) 2046 struct v4l2_fmtdesc *f)
2047{ 2047{
2048 if (saa7134_no_overlay > 0) { 2048 if (saa7134_no_overlay > 0) {
@@ -2061,7 +2061,7 @@ static int saa7134_enum_fmt_overlay(struct file *file, void *priv,
2061 return 0; 2061 return 0;
2062} 2062}
2063 2063
2064static int saa7134_enum_fmt_vbi(struct file *file, void *priv, 2064static int saa7134_enum_fmt_vbi_cap(struct file *file, void *priv,
2065 struct v4l2_fmtdesc *f) 2065 struct v4l2_fmtdesc *f)
2066{ 2066{
2067 if (0 != f->index) 2067 if (0 != f->index)
@@ -2208,6 +2208,32 @@ static int saa7134_g_parm(struct file *file, void *fh,
2208 return 0; 2208 return 0;
2209} 2209}
2210 2210
2211#ifdef CONFIG_VIDEO_ADV_DEBUG
2212static int vidioc_g_register (struct file *file, void *priv,
2213 struct v4l2_register *reg)
2214{
2215 struct saa7134_fh *fh = priv;
2216 struct saa7134_dev *dev = fh->dev;
2217
2218 if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
2219 return -EINVAL;
2220 reg->val = saa_readb(reg->reg);
2221 return 0;
2222}
2223
2224static int vidioc_s_register (struct file *file, void *priv,
2225 struct v4l2_register *reg)
2226{
2227 struct saa7134_fh *fh = priv;
2228 struct saa7134_dev *dev = fh->dev;
2229
2230 if (!v4l2_chip_match_host(reg->match_type, reg->match_chip))
2231 return -EINVAL;
2232 saa_writeb(reg->reg&0xffffff, reg->val);
2233 return 0;
2234}
2235#endif
2236
2211static int radio_querycap(struct file *file, void *priv, 2237static int radio_querycap(struct file *file, void *priv,
2212 struct v4l2_capability *cap) 2238 struct v4l2_capability *cap)
2213{ 2239{
@@ -2348,18 +2374,18 @@ struct video_device saa7134_video_template =
2348 .fops = &video_fops, 2374 .fops = &video_fops,
2349 .minor = -1, 2375 .minor = -1,
2350 .vidioc_querycap = saa7134_querycap, 2376 .vidioc_querycap = saa7134_querycap,
2351 .vidioc_enum_fmt_cap = saa7134_enum_fmt_cap, 2377 .vidioc_enum_fmt_vid_cap = saa7134_enum_fmt_vid_cap,
2352 .vidioc_g_fmt_cap = saa7134_g_fmt_cap, 2378 .vidioc_g_fmt_vid_cap = saa7134_g_fmt_vid_cap,
2353 .vidioc_try_fmt_cap = saa7134_try_fmt_cap, 2379 .vidioc_try_fmt_vid_cap = saa7134_try_fmt_vid_cap,
2354 .vidioc_s_fmt_cap = saa7134_s_fmt_cap, 2380 .vidioc_s_fmt_vid_cap = saa7134_s_fmt_vid_cap,
2355 .vidioc_enum_fmt_overlay = saa7134_enum_fmt_overlay, 2381 .vidioc_enum_fmt_vid_overlay = saa7134_enum_fmt_vid_overlay,
2356 .vidioc_g_fmt_overlay = saa7134_g_fmt_overlay, 2382 .vidioc_g_fmt_vid_overlay = saa7134_g_fmt_vid_overlay,
2357 .vidioc_try_fmt_overlay = saa7134_try_fmt_overlay, 2383 .vidioc_try_fmt_vid_overlay = saa7134_try_fmt_vid_overlay,
2358 .vidioc_s_fmt_overlay = saa7134_s_fmt_overlay, 2384 .vidioc_s_fmt_vid_overlay = saa7134_s_fmt_vid_overlay,
2359 .vidioc_enum_fmt_vbi = saa7134_enum_fmt_vbi, 2385 .vidioc_enum_fmt_vbi_cap = saa7134_enum_fmt_vbi_cap,
2360 .vidioc_g_fmt_vbi = saa7134_try_get_set_fmt_vbi, 2386 .vidioc_g_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
2361 .vidioc_try_fmt_vbi = saa7134_try_get_set_fmt_vbi, 2387 .vidioc_try_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
2362 .vidioc_s_fmt_vbi = saa7134_try_get_set_fmt_vbi, 2388 .vidioc_s_fmt_vbi_cap = saa7134_try_get_set_fmt_vbi_cap,
2363 .vidioc_g_audio = saa7134_g_audio, 2389 .vidioc_g_audio = saa7134_g_audio,
2364 .vidioc_s_audio = saa7134_s_audio, 2390 .vidioc_s_audio = saa7134_s_audio,
2365 .vidioc_cropcap = saa7134_cropcap, 2391 .vidioc_cropcap = saa7134_cropcap,
@@ -2391,6 +2417,10 @@ struct video_device saa7134_video_template =
2391 .vidioc_g_parm = saa7134_g_parm, 2417 .vidioc_g_parm = saa7134_g_parm,
2392 .vidioc_g_frequency = saa7134_g_frequency, 2418 .vidioc_g_frequency = saa7134_g_frequency,
2393 .vidioc_s_frequency = saa7134_s_frequency, 2419 .vidioc_s_frequency = saa7134_s_frequency,
2420#ifdef CONFIG_VIDEO_ADV_DEBUG
2421 .vidioc_g_register = vidioc_g_register,
2422 .vidioc_s_register = vidioc_s_register,
2423#endif
2394 .tvnorms = SAA7134_NORMS, 2424 .tvnorms = SAA7134_NORMS,
2395 .current_norm = V4L2_STD_PAL, 2425 .current_norm = V4L2_STD_PAL,
2396}; 2426};
@@ -2458,13 +2488,14 @@ int saa7134_videoport_init(struct saa7134_dev *dev)
2458 int vo = saa7134_boards[dev->board].video_out; 2488 int vo = saa7134_boards[dev->board].video_out;
2459 int video_reg; 2489 int video_reg;
2460 unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts; 2490 unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts;
2491
2492 /* Configure videoport */
2461 saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]); 2493 saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]);
2462 video_reg = video_out[vo][1]; 2494 video_reg = video_out[vo][1];
2463 if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED) 2495 if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED)
2464 video_reg &= ~VP_T_CODE_P_INVERTED; 2496 video_reg &= ~VP_T_CODE_P_INVERTED;
2465 saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg); 2497 saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg);
2466 saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]); 2498 saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]);
2467 saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]);
2468 saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]); 2499 saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]);
2469 video_reg = video_out[vo][5]; 2500 video_reg = video_out[vo][5];
2470 if (vid_port_opts & SET_CLOCK_NOT_DELAYED) 2501 if (vid_port_opts & SET_CLOCK_NOT_DELAYED)
@@ -2481,6 +2512,9 @@ int saa7134_videoport_init(struct saa7134_dev *dev)
2481 saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]); 2512 saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]);
2482 saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]); 2513 saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]);
2483 2514
2515 /* Start videoport */
2516 saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]);
2517
2484 return 0; 2518 return 0;
2485} 2519}
2486 2520
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 34ff0d4998f3..6927cbea8624 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -264,7 +264,10 @@ struct saa7134_format {
264#define SAA7134_BOARD_AVERMEDIA_A700_PRO 140 264#define SAA7134_BOARD_AVERMEDIA_A700_PRO 140
265#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141 265#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141
266#define SAA7134_BOARD_BEHOLD_H6 142 266#define SAA7134_BOARD_BEHOLD_H6 142
267 267#define SAA7134_BOARD_BEHOLD_M63 143
268#define SAA7134_BOARD_BEHOLD_M6_EXTRA 144
269#define SAA7134_BOARD_AVERMEDIA_M103 145
270#define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146
268 271
269#define SAA7134_MAXBOARDS 8 272#define SAA7134_MAXBOARDS 8
270#define SAA7134_INPUT_MAX 8 273#define SAA7134_INPUT_MAX 8
@@ -552,6 +555,7 @@ struct saa7134_dev {
552 struct saa7134_ts ts; 555 struct saa7134_ts ts;
553 struct saa7134_dmaqueue ts_q; 556 struct saa7134_dmaqueue ts_q;
554 struct saa7134_mpeg_ops *mops; 557 struct saa7134_mpeg_ops *mops;
558 struct i2c_client *mpeg_i2c_client;
555 559
556 /* SAA7134_MPEG_EMPRESS only */ 560 /* SAA7134_MPEG_EMPRESS only */
557 struct video_device *empress_dev; 561 struct video_device *empress_dev;
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
new file mode 100644
index 000000000000..012005e1a77b
--- /dev/null
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -0,0 +1,657 @@
1/*
2 * V4L2 Driver for SuperH Mobile CEU interface
3 *
4 * Copyright (C) 2008 Magnus Damm
5 *
6 * Based on V4L2 Driver for PXA camera host - "pxa_camera.c",
7 *
8 * Copyright (C) 2006, Sascha Hauer, Pengutronix
9 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/io.h>
20#include <linux/delay.h>
21#include <linux/dma-mapping.h>
22#include <linux/errno.h>
23#include <linux/fs.h>
24#include <linux/interrupt.h>
25#include <linux/kernel.h>
26#include <linux/mm.h>
27#include <linux/moduleparam.h>
28#include <linux/time.h>
29#include <linux/version.h>
30#include <linux/device.h>
31#include <linux/platform_device.h>
32#include <linux/mutex.h>
33#include <linux/videodev2.h>
34
35#include <media/v4l2-common.h>
36#include <media/v4l2-dev.h>
37#include <media/soc_camera.h>
38#include <media/sh_mobile_ceu.h>
39#include <media/videobuf-dma-contig.h>
40
41/* register offsets for sh7722 / sh7723 */
42
43#define CAPSR 0x00
44#define CAPCR 0x04
45#define CAMCR 0x08
46#define CMCYR 0x0c
47#define CAMOR 0x10
48#define CAPWR 0x14
49#define CAIFR 0x18
50#define CSTCR 0x20 /* not on sh7723 */
51#define CSECR 0x24 /* not on sh7723 */
52#define CRCNTR 0x28
53#define CRCMPR 0x2c
54#define CFLCR 0x30
55#define CFSZR 0x34
56#define CDWDR 0x38
57#define CDAYR 0x3c
58#define CDACR 0x40
59#define CDBYR 0x44
60#define CDBCR 0x48
61#define CBDSR 0x4c
62#define CFWCR 0x5c
63#define CLFCR 0x60
64#define CDOCR 0x64
65#define CDDCR 0x68
66#define CDDAR 0x6c
67#define CEIER 0x70
68#define CETCR 0x74
69#define CSTSR 0x7c
70#define CSRTR 0x80
71#define CDSSR 0x84
72#define CDAYR2 0x90
73#define CDACR2 0x94
74#define CDBYR2 0x98
75#define CDBCR2 0x9c
76
77static DEFINE_MUTEX(camera_lock);
78
79/* per video frame buffer */
80struct sh_mobile_ceu_buffer {
81 struct videobuf_buffer vb; /* v4l buffer must be first */
82 const struct soc_camera_data_format *fmt;
83};
84
85struct sh_mobile_ceu_dev {
86 struct device *dev;
87 struct soc_camera_host ici;
88 struct soc_camera_device *icd;
89
90 unsigned int irq;
91 void __iomem *base;
92 unsigned long video_limit;
93
94 spinlock_t lock;
95 struct list_head capture;
96 struct videobuf_buffer *active;
97
98 struct sh_mobile_ceu_info *pdata;
99};
100
101static void ceu_write(struct sh_mobile_ceu_dev *priv,
102 unsigned long reg_offs, unsigned long data)
103{
104 iowrite32(data, priv->base + reg_offs);
105}
106
107static unsigned long ceu_read(struct sh_mobile_ceu_dev *priv,
108 unsigned long reg_offs)
109{
110 return ioread32(priv->base + reg_offs);
111}
112
113/*
114 * Videobuf operations
115 */
116static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq,
117 unsigned int *count,
118 unsigned int *size)
119{
120 struct soc_camera_device *icd = vq->priv_data;
121 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
122 struct sh_mobile_ceu_dev *pcdev = ici->priv;
123 int bytes_per_pixel = (icd->current_fmt->depth + 7) >> 3;
124
125 *size = PAGE_ALIGN(icd->width * icd->height * bytes_per_pixel);
126
127 if (0 == *count)
128 *count = 2;
129
130 if (pcdev->video_limit) {
131 while (*size * *count > pcdev->video_limit)
132 (*count)--;
133 }
134
135 dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
136
137 return 0;
138}
139
140static void free_buffer(struct videobuf_queue *vq,
141 struct sh_mobile_ceu_buffer *buf)
142{
143 struct soc_camera_device *icd = vq->priv_data;
144
145 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
146 &buf->vb, buf->vb.baddr, buf->vb.bsize);
147
148 if (in_interrupt())
149 BUG();
150
151 videobuf_dma_contig_free(vq, &buf->vb);
152 dev_dbg(&icd->dev, "%s freed\n", __func__);
153 buf->vb.state = VIDEOBUF_NEEDS_INIT;
154}
155
156static void sh_mobile_ceu_capture(struct sh_mobile_ceu_dev *pcdev)
157{
158 ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) & ~1);
159 ceu_write(pcdev, CETCR, ~ceu_read(pcdev, CETCR) & 0x0317f313);
160 ceu_write(pcdev, CEIER, ceu_read(pcdev, CEIER) | 1);
161
162 ceu_write(pcdev, CAPCR, ceu_read(pcdev, CAPCR) & ~0x10000);
163
164 ceu_write(pcdev, CETCR, 0x0317f313 ^ 0x10);
165
166 if (pcdev->active) {
167 ceu_write(pcdev, CDAYR, videobuf_to_dma_contig(pcdev->active));
168 ceu_write(pcdev, CAPSR, 0x1); /* start capture */
169 }
170}
171
172static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq,
173 struct videobuf_buffer *vb,
174 enum v4l2_field field)
175{
176 struct soc_camera_device *icd = vq->priv_data;
177 struct sh_mobile_ceu_buffer *buf;
178 int ret;
179
180 buf = container_of(vb, struct sh_mobile_ceu_buffer, vb);
181
182 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
183 vb, vb->baddr, vb->bsize);
184
185 /* Added list head initialization on alloc */
186 WARN_ON(!list_empty(&vb->queue));
187
188#ifdef DEBUG
189 /* This can be useful if you want to see if we actually fill
190 * the buffer with something */
191 memset((void *)vb->baddr, 0xaa, vb->bsize);
192#endif
193
194 BUG_ON(NULL == icd->current_fmt);
195
196 if (buf->fmt != icd->current_fmt ||
197 vb->width != icd->width ||
198 vb->height != icd->height ||
199 vb->field != field) {
200 buf->fmt = icd->current_fmt;
201 vb->width = icd->width;
202 vb->height = icd->height;
203 vb->field = field;
204 vb->state = VIDEOBUF_NEEDS_INIT;
205 }
206
207 vb->size = vb->width * vb->height * ((buf->fmt->depth + 7) >> 3);
208 if (0 != vb->baddr && vb->bsize < vb->size) {
209 ret = -EINVAL;
210 goto out;
211 }
212
213 if (vb->state == VIDEOBUF_NEEDS_INIT) {
214 ret = videobuf_iolock(vq, vb, NULL);
215 if (ret)
216 goto fail;
217 vb->state = VIDEOBUF_PREPARED;
218 }
219
220 return 0;
221fail:
222 free_buffer(vq, buf);
223out:
224 return ret;
225}
226
227static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq,
228 struct videobuf_buffer *vb)
229{
230 struct soc_camera_device *icd = vq->priv_data;
231 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
232 struct sh_mobile_ceu_dev *pcdev = ici->priv;
233 unsigned long flags;
234
235 dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
236 vb, vb->baddr, vb->bsize);
237
238 vb->state = VIDEOBUF_ACTIVE;
239 spin_lock_irqsave(&pcdev->lock, flags);
240 list_add_tail(&vb->queue, &pcdev->capture);
241
242 if (!pcdev->active) {
243 pcdev->active = vb;
244 sh_mobile_ceu_capture(pcdev);
245 }
246
247 spin_unlock_irqrestore(&pcdev->lock, flags);
248}
249
250static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq,
251 struct videobuf_buffer *vb)
252{
253 free_buffer(vq, container_of(vb, struct sh_mobile_ceu_buffer, vb));
254}
255
256static struct videobuf_queue_ops sh_mobile_ceu_videobuf_ops = {
257 .buf_setup = sh_mobile_ceu_videobuf_setup,
258 .buf_prepare = sh_mobile_ceu_videobuf_prepare,
259 .buf_queue = sh_mobile_ceu_videobuf_queue,
260 .buf_release = sh_mobile_ceu_videobuf_release,
261};
262
263static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
264{
265 struct sh_mobile_ceu_dev *pcdev = data;
266 struct videobuf_buffer *vb;
267 unsigned long flags;
268
269 spin_lock_irqsave(&pcdev->lock, flags);
270
271 vb = pcdev->active;
272 list_del_init(&vb->queue);
273
274 if (!list_empty(&pcdev->capture))
275 pcdev->active = list_entry(pcdev->capture.next,
276 struct videobuf_buffer, queue);
277 else
278 pcdev->active = NULL;
279
280 sh_mobile_ceu_capture(pcdev);
281
282 vb->state = VIDEOBUF_DONE;
283 do_gettimeofday(&vb->ts);
284 vb->field_count++;
285 wake_up(&vb->done);
286 spin_unlock_irqrestore(&pcdev->lock, flags);
287
288 return IRQ_HANDLED;
289}
290
291static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
292{
293 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
294 struct sh_mobile_ceu_dev *pcdev = ici->priv;
295 int ret = -EBUSY;
296
297 mutex_lock(&camera_lock);
298
299 if (pcdev->icd)
300 goto err;
301
302 dev_info(&icd->dev,
303 "SuperH Mobile CEU driver attached to camera %d\n",
304 icd->devnum);
305
306 if (pcdev->pdata->enable_camera)
307 pcdev->pdata->enable_camera();
308
309 ret = icd->ops->init(icd);
310 if (ret)
311 goto err;
312
313 ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
314 while (ceu_read(pcdev, CSTSR) & 1)
315 msleep(1);
316
317 pcdev->icd = icd;
318err:
319 mutex_unlock(&camera_lock);
320
321 return ret;
322}
323
324static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
325{
326 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
327 struct sh_mobile_ceu_dev *pcdev = ici->priv;
328
329 BUG_ON(icd != pcdev->icd);
330
331 /* disable capture, disable interrupts */
332 ceu_write(pcdev, CEIER, 0);
333 ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
334 icd->ops->release(icd);
335 if (pcdev->pdata->disable_camera)
336 pcdev->pdata->disable_camera();
337
338 dev_info(&icd->dev,
339 "SuperH Mobile CEU driver detached from camera %d\n",
340 icd->devnum);
341
342 pcdev->icd = NULL;
343}
344
345static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
346 __u32 pixfmt)
347{
348 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
349 struct sh_mobile_ceu_dev *pcdev = ici->priv;
350 int ret, buswidth, width, cfszr_width, cdwdr_width;
351 unsigned long camera_flags, common_flags, value;
352
353 camera_flags = icd->ops->query_bus_param(icd);
354 common_flags = soc_camera_bus_param_compatible(camera_flags,
355 pcdev->pdata->flags);
356 if (!common_flags)
357 return -EINVAL;
358
359 ret = icd->ops->set_bus_param(icd, common_flags);
360 if (ret < 0)
361 return ret;
362
363 switch (common_flags & SOCAM_DATAWIDTH_MASK) {
364 case SOCAM_DATAWIDTH_8:
365 buswidth = 8;
366 break;
367 case SOCAM_DATAWIDTH_16:
368 buswidth = 16;
369 break;
370 default:
371 return -EINVAL;
372 }
373
374 ceu_write(pcdev, CRCNTR, 0);
375 ceu_write(pcdev, CRCMPR, 0);
376
377 value = 0x00000010;
378 value |= (common_flags & SOCAM_VSYNC_ACTIVE_LOW) ? (1 << 1) : 0;
379 value |= (common_flags & SOCAM_HSYNC_ACTIVE_LOW) ? (1 << 0) : 0;
380 value |= (buswidth == 16) ? (1 << 12) : 0;
381 ceu_write(pcdev, CAMCR, value);
382
383 ceu_write(pcdev, CAPCR, 0x00300000);
384 ceu_write(pcdev, CAIFR, 0);
385
386 mdelay(1);
387
388 width = icd->width * (icd->current_fmt->depth / 8);
389 width = (buswidth == 16) ? width / 2 : width;
390 cfszr_width = (buswidth == 8) ? width / 2 : width;
391 cdwdr_width = (buswidth == 16) ? width * 2 : width;
392
393 ceu_write(pcdev, CAMOR, 0);
394 ceu_write(pcdev, CAPWR, (icd->height << 16) | width);
395 ceu_write(pcdev, CFLCR, 0); /* data fetch mode - no scaling */
396 ceu_write(pcdev, CFSZR, (icd->height << 16) | cfszr_width);
397 ceu_write(pcdev, CLFCR, 0); /* data fetch mode - no lowpass filter */
398 ceu_write(pcdev, CDOCR, 0x00000016);
399
400 ceu_write(pcdev, CDWDR, cdwdr_width);
401 ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */
402
403 /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */
404 /* in data fetch mode: no need for CDACR, CDBYR, CDBCR */
405
406 return 0;
407}
408
409static int sh_mobile_ceu_try_bus_param(struct soc_camera_device *icd,
410 __u32 pixfmt)
411{
412 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
413 struct sh_mobile_ceu_dev *pcdev = ici->priv;
414 unsigned long camera_flags, common_flags;
415
416 camera_flags = icd->ops->query_bus_param(icd);
417 common_flags = soc_camera_bus_param_compatible(camera_flags,
418 pcdev->pdata->flags);
419 if (!common_flags)
420 return -EINVAL;
421
422 return 0;
423}
424
425static int sh_mobile_ceu_set_fmt_cap(struct soc_camera_device *icd,
426 __u32 pixfmt, struct v4l2_rect *rect)
427{
428 return icd->ops->set_fmt_cap(icd, pixfmt, rect);
429}
430
431static int sh_mobile_ceu_try_fmt_cap(struct soc_camera_device *icd,
432 struct v4l2_format *f)
433{
434 /* FIXME: calculate using depth and bus width */
435
436 if (f->fmt.pix.height < 4)
437 f->fmt.pix.height = 4;
438 if (f->fmt.pix.height > 1920)
439 f->fmt.pix.height = 1920;
440 if (f->fmt.pix.width < 2)
441 f->fmt.pix.width = 2;
442 if (f->fmt.pix.width > 2560)
443 f->fmt.pix.width = 2560;
444 f->fmt.pix.width &= ~0x01;
445 f->fmt.pix.height &= ~0x03;
446
447 /* limit to sensor capabilities */
448 return icd->ops->try_fmt_cap(icd, f);
449}
450
451static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf,
452 struct v4l2_requestbuffers *p)
453{
454 int i;
455
456 /* This is for locking debugging only. I removed spinlocks and now I
457 * check whether .prepare is ever called on a linked buffer, or whether
458 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
459 * it hadn't triggered */
460 for (i = 0; i < p->count; i++) {
461 struct sh_mobile_ceu_buffer *buf;
462
463 buf = container_of(icf->vb_vidq.bufs[i],
464 struct sh_mobile_ceu_buffer, vb);
465 INIT_LIST_HEAD(&buf->vb.queue);
466 }
467
468 return 0;
469}
470
471static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt)
472{
473 struct soc_camera_file *icf = file->private_data;
474 struct sh_mobile_ceu_buffer *buf;
475
476 buf = list_entry(icf->vb_vidq.stream.next,
477 struct sh_mobile_ceu_buffer, vb.stream);
478
479 poll_wait(file, &buf->vb.done, pt);
480
481 if (buf->vb.state == VIDEOBUF_DONE ||
482 buf->vb.state == VIDEOBUF_ERROR)
483 return POLLIN|POLLRDNORM;
484
485 return 0;
486}
487
488static int sh_mobile_ceu_querycap(struct soc_camera_host *ici,
489 struct v4l2_capability *cap)
490{
491 strlcpy(cap->card, "SuperH_Mobile_CEU", sizeof(cap->card));
492 cap->version = KERNEL_VERSION(0, 0, 5);
493 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
494 return 0;
495}
496
497static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q,
498 struct soc_camera_device *icd)
499{
500 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
501 struct sh_mobile_ceu_dev *pcdev = ici->priv;
502
503 videobuf_queue_dma_contig_init(q,
504 &sh_mobile_ceu_videobuf_ops,
505 &ici->dev, &pcdev->lock,
506 V4L2_BUF_TYPE_VIDEO_CAPTURE,
507 V4L2_FIELD_NONE,
508 sizeof(struct sh_mobile_ceu_buffer),
509 icd);
510}
511
512static struct soc_camera_host_ops sh_mobile_ceu_host_ops = {
513 .owner = THIS_MODULE,
514 .add = sh_mobile_ceu_add_device,
515 .remove = sh_mobile_ceu_remove_device,
516 .set_fmt_cap = sh_mobile_ceu_set_fmt_cap,
517 .try_fmt_cap = sh_mobile_ceu_try_fmt_cap,
518 .reqbufs = sh_mobile_ceu_reqbufs,
519 .poll = sh_mobile_ceu_poll,
520 .querycap = sh_mobile_ceu_querycap,
521 .try_bus_param = sh_mobile_ceu_try_bus_param,
522 .set_bus_param = sh_mobile_ceu_set_bus_param,
523 .init_videobuf = sh_mobile_ceu_init_videobuf,
524};
525
526static int sh_mobile_ceu_probe(struct platform_device *pdev)
527{
528 struct sh_mobile_ceu_dev *pcdev;
529 struct resource *res;
530 void __iomem *base;
531 unsigned int irq;
532 int err = 0;
533
534 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
535 irq = platform_get_irq(pdev, 0);
536 if (!res || !irq) {
537 dev_err(&pdev->dev, "Not enough CEU platform resources.\n");
538 err = -ENODEV;
539 goto exit;
540 }
541
542 pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
543 if (!pcdev) {
544 dev_err(&pdev->dev, "Could not allocate pcdev\n");
545 err = -ENOMEM;
546 goto exit;
547 }
548
549 platform_set_drvdata(pdev, pcdev);
550 INIT_LIST_HEAD(&pcdev->capture);
551 spin_lock_init(&pcdev->lock);
552
553 pcdev->pdata = pdev->dev.platform_data;
554 if (!pcdev->pdata) {
555 err = -EINVAL;
556 dev_err(&pdev->dev, "CEU platform data not set.\n");
557 goto exit_kfree;
558 }
559
560 base = ioremap_nocache(res->start, res->end - res->start + 1);
561 if (!base) {
562 err = -ENXIO;
563 dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n");
564 goto exit_kfree;
565 }
566
567 pcdev->irq = irq;
568 pcdev->base = base;
569 pcdev->video_limit = 0; /* only enabled if second resource exists */
570 pcdev->dev = &pdev->dev;
571
572 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
573 if (res) {
574 err = dma_declare_coherent_memory(&pdev->dev, res->start,
575 res->start,
576 (res->end - res->start) + 1,
577 DMA_MEMORY_MAP |
578 DMA_MEMORY_EXCLUSIVE);
579 if (!err) {
580 dev_err(&pdev->dev, "Unable to declare CEU memory.\n");
581 err = -ENXIO;
582 goto exit_iounmap;
583 }
584
585 pcdev->video_limit = (res->end - res->start) + 1;
586 }
587
588 /* request irq */
589 err = request_irq(pcdev->irq, sh_mobile_ceu_irq, IRQF_DISABLED,
590 pdev->dev.bus_id, pcdev);
591 if (err) {
592 dev_err(&pdev->dev, "Unable to register CEU interrupt.\n");
593 goto exit_release_mem;
594 }
595
596 pcdev->ici.priv = pcdev;
597 pcdev->ici.dev.parent = &pdev->dev;
598 pcdev->ici.nr = pdev->id;
599 pcdev->ici.drv_name = pdev->dev.bus_id,
600 pcdev->ici.ops = &sh_mobile_ceu_host_ops,
601
602 err = soc_camera_host_register(&pcdev->ici);
603 if (err)
604 goto exit_free_irq;
605
606 return 0;
607
608exit_free_irq:
609 free_irq(pcdev->irq, pcdev);
610exit_release_mem:
611 if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
612 dma_release_declared_memory(&pdev->dev);
613exit_iounmap:
614 iounmap(base);
615exit_kfree:
616 kfree(pcdev);
617exit:
618 return err;
619}
620
621static int sh_mobile_ceu_remove(struct platform_device *pdev)
622{
623 struct sh_mobile_ceu_dev *pcdev = platform_get_drvdata(pdev);
624
625 soc_camera_host_unregister(&pcdev->ici);
626 free_irq(pcdev->irq, pcdev);
627 if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
628 dma_release_declared_memory(&pdev->dev);
629 iounmap(pcdev->base);
630 kfree(pcdev);
631 return 0;
632}
633
634static struct platform_driver sh_mobile_ceu_driver = {
635 .driver = {
636 .name = "sh_mobile_ceu",
637 },
638 .probe = sh_mobile_ceu_probe,
639 .remove = sh_mobile_ceu_remove,
640};
641
642static int __init sh_mobile_ceu_init(void)
643{
644 return platform_driver_register(&sh_mobile_ceu_driver);
645}
646
647static void __exit sh_mobile_ceu_exit(void)
648{
649 return platform_driver_unregister(&sh_mobile_ceu_driver);
650}
651
652module_init(sh_mobile_ceu_init);
653module_exit(sh_mobile_ceu_exit);
654
655MODULE_DESCRIPTION("SuperH Mobile CEU driver");
656MODULE_AUTHOR("Magnus Damm");
657MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
index 35223e0d7e49..6ff489baacf3 100644
--- a/drivers/media/video/sn9c102/sn9c102_devtable.h
+++ b/drivers/media/video/sn9c102/sn9c102_devtable.h
@@ -44,7 +44,6 @@ static const struct usb_device_id sn9c102_id_table[] = {
44 { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), }, 44 { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
45 { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), }, 45 { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
46 { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), }, 46 { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
47 { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), },
48 { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), }, 47 { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
49 { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), }, 48 { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
50 { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), }, 49 { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
@@ -57,7 +56,6 @@ static const struct usb_device_id sn9c102_id_table[] = {
57 { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, 56 { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), },
58 { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), }, 57 { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
59 { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, 58 { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), },
60 { SN9C102_USB_DEVICE(0x0c45, 0x603f, BRIDGE_SN9C102), },
61 /* SN9C103 */ 59 /* SN9C103 */
62 { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, 60 { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), },
63 { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, 61 { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), },
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index d015bfe00950..e39b98f1eca4 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -26,6 +26,7 @@
26 26
27#include <media/v4l2-common.h> 27#include <media/v4l2-common.h>
28#include <media/v4l2-dev.h> 28#include <media/v4l2-dev.h>
29#include <media/videobuf-core.h>
29#include <media/soc_camera.h> 30#include <media/soc_camera.h>
30 31
31static LIST_HEAD(hosts); 32static LIST_HEAD(hosts);
@@ -44,7 +45,7 @@ format_by_fourcc(struct soc_camera_device *icd, unsigned int fourcc)
44 return NULL; 45 return NULL;
45} 46}
46 47
47static int soc_camera_try_fmt_cap(struct file *file, void *priv, 48static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
48 struct v4l2_format *f) 49 struct v4l2_format *f)
49{ 50{
50 struct soc_camera_file *icf = file->private_data; 51 struct soc_camera_file *icf = file->private_data;
@@ -182,7 +183,6 @@ static int soc_camera_open(struct inode *inode, struct file *file)
182 struct soc_camera_device *icd; 183 struct soc_camera_device *icd;
183 struct soc_camera_host *ici; 184 struct soc_camera_host *ici;
184 struct soc_camera_file *icf; 185 struct soc_camera_file *icf;
185 spinlock_t *lock;
186 int ret; 186 int ret;
187 187
188 icf = vmalloc(sizeof(*icf)); 188 icf = vmalloc(sizeof(*icf));
@@ -209,13 +209,6 @@ static int soc_camera_open(struct inode *inode, struct file *file)
209 } 209 }
210 210
211 icf->icd = icd; 211 icf->icd = icd;
212
213 icf->lock = ici->ops->spinlock_alloc(icf);
214 if (!icf->lock) {
215 ret = -ENOMEM;
216 goto esla;
217 }
218
219 icd->use_count++; 212 icd->use_count++;
220 213
221 /* Now we really have to activate the camera */ 214 /* Now we really have to activate the camera */
@@ -233,21 +226,12 @@ static int soc_camera_open(struct inode *inode, struct file *file)
233 file->private_data = icf; 226 file->private_data = icf;
234 dev_dbg(&icd->dev, "camera device open\n"); 227 dev_dbg(&icd->dev, "camera device open\n");
235 228
236 /* We must pass NULL as dev pointer, then all pci_* dma operations 229 ici->ops->init_videobuf(&icf->vb_vidq, icd);
237 * transform to normal dma_* ones. */
238 videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock,
239 V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
240 ici->msize, icd);
241 230
242 return 0; 231 return 0;
243 232
244 /* All errors are entered with the video_lock held */ 233 /* All errors are entered with the video_lock held */
245eiciadd: 234eiciadd:
246 lock = icf->lock;
247 icf->lock = NULL;
248 if (ici->ops->spinlock_free)
249 ici->ops->spinlock_free(lock);
250esla:
251 module_put(ici->ops->owner); 235 module_put(ici->ops->owner);
252emgi: 236emgi:
253 module_put(icd->ops->owner); 237 module_put(icd->ops->owner);
@@ -263,15 +247,11 @@ static int soc_camera_close(struct inode *inode, struct file *file)
263 struct soc_camera_device *icd = icf->icd; 247 struct soc_camera_device *icd = icf->icd;
264 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 248 struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
265 struct video_device *vdev = icd->vdev; 249 struct video_device *vdev = icd->vdev;
266 spinlock_t *lock = icf->lock;
267 250
268 mutex_lock(&video_lock); 251 mutex_lock(&video_lock);
269 icd->use_count--; 252 icd->use_count--;
270 if (!icd->use_count) 253 if (!icd->use_count)
271 ici->ops->remove(icd); 254 ici->ops->remove(icd);
272 icf->lock = NULL;
273 if (ici->ops->spinlock_free)
274 ici->ops->spinlock_free(lock);
275 module_put(icd->ops->owner); 255 module_put(icd->ops->owner);
276 module_put(ici->ops->owner); 256 module_put(ici->ops->owner);
277 mutex_unlock(&video_lock); 257 mutex_unlock(&video_lock);
@@ -342,7 +322,7 @@ static struct file_operations soc_camera_fops = {
342}; 322};
343 323
344 324
345static int soc_camera_s_fmt_cap(struct file *file, void *priv, 325static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
346 struct v4l2_format *f) 326 struct v4l2_format *f)
347{ 327{
348 struct soc_camera_file *icf = file->private_data; 328 struct soc_camera_file *icf = file->private_data;
@@ -362,7 +342,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv,
362 /* buswidth may be further adjusted by the ici */ 342 /* buswidth may be further adjusted by the ici */
363 icd->buswidth = data_fmt->depth; 343 icd->buswidth = data_fmt->depth;
364 344
365 ret = soc_camera_try_fmt_cap(file, icf, f); 345 ret = soc_camera_try_fmt_vid_cap(file, icf, f);
366 if (ret < 0) 346 if (ret < 0)
367 return ret; 347 return ret;
368 348
@@ -389,7 +369,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv,
389 return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat); 369 return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat);
390} 370}
391 371
392static int soc_camera_enum_fmt_cap(struct file *file, void *priv, 372static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
393 struct v4l2_fmtdesc *f) 373 struct v4l2_fmtdesc *f)
394{ 374{
395 struct soc_camera_file *icf = file->private_data; 375 struct soc_camera_file *icf = file->private_data;
@@ -408,7 +388,7 @@ static int soc_camera_enum_fmt_cap(struct file *file, void *priv,
408 return 0; 388 return 0;
409} 389}
410 390
411static int soc_camera_g_fmt_cap(struct file *file, void *priv, 391static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv,
412 struct v4l2_format *f) 392 struct v4l2_format *f)
413{ 393{
414 struct soc_camera_file *icf = file->private_data; 394 struct soc_camera_file *icf = file->private_data;
@@ -767,27 +747,12 @@ static void dummy_release(struct device *dev)
767{ 747{
768} 748}
769 749
770static spinlock_t *spinlock_alloc(struct soc_camera_file *icf)
771{
772 spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
773
774 if (lock)
775 spin_lock_init(lock);
776
777 return lock;
778}
779
780static void spinlock_free(spinlock_t *lock)
781{
782 kfree(lock);
783}
784
785int soc_camera_host_register(struct soc_camera_host *ici) 750int soc_camera_host_register(struct soc_camera_host *ici)
786{ 751{
787 int ret; 752 int ret;
788 struct soc_camera_host *ix; 753 struct soc_camera_host *ix;
789 754
790 if (!ici->vbq_ops || !ici->ops->add || !ici->ops->remove) 755 if (!ici->ops->init_videobuf || !ici->ops->add || !ici->ops->remove)
791 return -EINVAL; 756 return -EINVAL;
792 757
793 /* Number might be equal to the platform device ID */ 758 /* Number might be equal to the platform device ID */
@@ -811,11 +776,6 @@ int soc_camera_host_register(struct soc_camera_host *ici)
811 if (ret) 776 if (ret)
812 goto edevr; 777 goto edevr;
813 778
814 if (!ici->ops->spinlock_alloc) {
815 ici->ops->spinlock_alloc = spinlock_alloc;
816 ici->ops->spinlock_free = spinlock_free;
817 }
818
819 scan_add_host(ici); 779 scan_add_host(ici);
820 780
821 return 0; 781 return 0;
@@ -925,15 +885,15 @@ int soc_camera_video_start(struct soc_camera_device *icd)
925 vdev->minor = -1; 885 vdev->minor = -1;
926 vdev->tvnorms = V4L2_STD_UNKNOWN, 886 vdev->tvnorms = V4L2_STD_UNKNOWN,
927 vdev->vidioc_querycap = soc_camera_querycap; 887 vdev->vidioc_querycap = soc_camera_querycap;
928 vdev->vidioc_g_fmt_cap = soc_camera_g_fmt_cap; 888 vdev->vidioc_g_fmt_vid_cap = soc_camera_g_fmt_vid_cap;
929 vdev->vidioc_enum_fmt_cap = soc_camera_enum_fmt_cap; 889 vdev->vidioc_enum_fmt_vid_cap = soc_camera_enum_fmt_vid_cap;
930 vdev->vidioc_s_fmt_cap = soc_camera_s_fmt_cap; 890 vdev->vidioc_s_fmt_vid_cap = soc_camera_s_fmt_vid_cap;
931 vdev->vidioc_enum_input = soc_camera_enum_input; 891 vdev->vidioc_enum_input = soc_camera_enum_input;
932 vdev->vidioc_g_input = soc_camera_g_input; 892 vdev->vidioc_g_input = soc_camera_g_input;
933 vdev->vidioc_s_input = soc_camera_s_input; 893 vdev->vidioc_s_input = soc_camera_s_input;
934 vdev->vidioc_s_std = soc_camera_s_std; 894 vdev->vidioc_s_std = soc_camera_s_std;
935 vdev->vidioc_reqbufs = soc_camera_reqbufs; 895 vdev->vidioc_reqbufs = soc_camera_reqbufs;
936 vdev->vidioc_try_fmt_cap = soc_camera_try_fmt_cap; 896 vdev->vidioc_try_fmt_vid_cap = soc_camera_try_fmt_vid_cap;
937 vdev->vidioc_querybuf = soc_camera_querybuf; 897 vdev->vidioc_querybuf = soc_camera_querybuf;
938 vdev->vidioc_qbuf = soc_camera_qbuf; 898 vdev->vidioc_qbuf = soc_camera_qbuf;
939 vdev->vidioc_dqbuf = soc_camera_dqbuf; 899 vdev->vidioc_dqbuf = soc_camera_dqbuf;
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
new file mode 100644
index 000000000000..eefb0327ebb6
--- /dev/null
+++ b/drivers/media/video/soc_camera_platform.c
@@ -0,0 +1,198 @@
1/*
2 * Generic Platform Camera Driver
3 *
4 * Copyright (C) 2008 Magnus Damm
5 * Based on mt9m001 driver,
6 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/slab.h>
16#include <linux/delay.h>
17#include <linux/platform_device.h>
18#include <linux/videodev2.h>
19#include <media/v4l2-common.h>
20#include <media/soc_camera.h>
21
22struct soc_camera_platform_info {
23 int iface;
24 char *format_name;
25 unsigned long format_depth;
26 struct v4l2_pix_format format;
27 unsigned long bus_param;
28 int (*set_capture)(struct soc_camera_platform_info *info, int enable);
29};
30
31struct soc_camera_platform_priv {
32 struct soc_camera_platform_info *info;
33 struct soc_camera_device icd;
34 struct soc_camera_data_format format;
35};
36
37static struct soc_camera_platform_info *
38soc_camera_platform_get_info(struct soc_camera_device *icd)
39{
40 struct soc_camera_platform_priv *priv;
41 priv = container_of(icd, struct soc_camera_platform_priv, icd);
42 return priv->info;
43}
44
45static int soc_camera_platform_init(struct soc_camera_device *icd)
46{
47 return 0;
48}
49
50static int soc_camera_platform_release(struct soc_camera_device *icd)
51{
52 return 0;
53}
54
55static int soc_camera_platform_start_capture(struct soc_camera_device *icd)
56{
57 struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
58 return p->set_capture(p, 1);
59}
60
61static int soc_camera_platform_stop_capture(struct soc_camera_device *icd)
62{
63 struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
64 return p->set_capture(p, 0);
65}
66
67static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd,
68 unsigned long flags)
69{
70 return 0;
71}
72
73static unsigned long
74soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
75{
76 struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
77 return p->bus_param;
78}
79
80static int soc_camera_platform_set_fmt_cap(struct soc_camera_device *icd,
81 __u32 pixfmt, struct v4l2_rect *rect)
82{
83 return 0;
84}
85
86static int soc_camera_platform_try_fmt_cap(struct soc_camera_device *icd,
87 struct v4l2_format *f)
88{
89 struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
90
91 f->fmt.pix.width = p->format.width;
92 f->fmt.pix.height = p->format.height;
93 return 0;
94}
95
96static int soc_camera_platform_video_probe(struct soc_camera_device *icd)
97{
98 struct soc_camera_platform_priv *priv;
99 priv = container_of(icd, struct soc_camera_platform_priv, icd);
100
101 priv->format.name = priv->info->format_name;
102 priv->format.depth = priv->info->format_depth;
103 priv->format.fourcc = priv->info->format.pixelformat;
104 priv->format.colorspace = priv->info->format.colorspace;
105
106 icd->formats = &priv->format;
107 icd->num_formats = 1;
108
109 return soc_camera_video_start(icd);
110}
111
112static void soc_camera_platform_video_remove(struct soc_camera_device *icd)
113{
114 soc_camera_video_stop(icd);
115}
116
117static struct soc_camera_ops soc_camera_platform_ops = {
118 .owner = THIS_MODULE,
119 .probe = soc_camera_platform_video_probe,
120 .remove = soc_camera_platform_video_remove,
121 .init = soc_camera_platform_init,
122 .release = soc_camera_platform_release,
123 .start_capture = soc_camera_platform_start_capture,
124 .stop_capture = soc_camera_platform_stop_capture,
125 .set_fmt_cap = soc_camera_platform_set_fmt_cap,
126 .try_fmt_cap = soc_camera_platform_try_fmt_cap,
127 .set_bus_param = soc_camera_platform_set_bus_param,
128 .query_bus_param = soc_camera_platform_query_bus_param,
129};
130
131static int soc_camera_platform_probe(struct platform_device *pdev)
132{
133 struct soc_camera_platform_priv *priv;
134 struct soc_camera_platform_info *p;
135 struct soc_camera_device *icd;
136 int ret;
137
138 p = pdev->dev.platform_data;
139 if (!p)
140 return -EINVAL;
141
142 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
143 if (!priv)
144 return -ENOMEM;
145
146 priv->info = p;
147 platform_set_drvdata(pdev, priv);
148
149 icd = &priv->icd;
150 icd->ops = &soc_camera_platform_ops;
151 icd->control = &pdev->dev;
152 icd->width_min = 0;
153 icd->width_max = priv->info->format.width;
154 icd->height_min = 0;
155 icd->height_max = priv->info->format.height;
156 icd->y_skip_top = 0;
157 icd->iface = priv->info->iface;
158
159 ret = soc_camera_device_register(icd);
160 if (ret)
161 kfree(priv);
162
163 return ret;
164}
165
166static int soc_camera_platform_remove(struct platform_device *pdev)
167{
168 struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev);
169
170 soc_camera_device_unregister(&priv->icd);
171 kfree(priv);
172 return 0;
173}
174
175static struct platform_driver soc_camera_platform_driver = {
176 .driver = {
177 .name = "soc_camera_platform",
178 },
179 .probe = soc_camera_platform_probe,
180 .remove = soc_camera_platform_remove,
181};
182
183static int __init soc_camera_platform_module_init(void)
184{
185 return platform_driver_register(&soc_camera_platform_driver);
186}
187
188static void __exit soc_camera_platform_module_exit(void)
189{
190 return platform_driver_unregister(&soc_camera_platform_driver);
191}
192
193module_init(soc_camera_platform_module_init);
194module_exit(soc_camera_platform_module_exit);
195
196MODULE_DESCRIPTION("SoC Camera Platform driver");
197MODULE_AUTHOR("Magnus Damm");
198MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c
index b12c60cf5a09..f308c38d744f 100644
--- a/drivers/media/video/stk-webcam.c
+++ b/drivers/media/video/stk-webcam.c
@@ -981,7 +981,7 @@ static int stk_vidioc_s_ctrl(struct file *filp,
981} 981}
982 982
983 983
984static int stk_vidioc_enum_fmt_cap(struct file *filp, 984static int stk_vidioc_enum_fmt_vid_cap(struct file *filp,
985 void *priv, struct v4l2_fmtdesc *fmtd) 985 void *priv, struct v4l2_fmtdesc *fmtd)
986{ 986{
987 fmtd->flags = 0; 987 fmtd->flags = 0;
@@ -1025,7 +1025,7 @@ static struct stk_size {
1025 { .w = 176, .h = 144, .m = MODE_QCIF, }, 1025 { .w = 176, .h = 144, .m = MODE_QCIF, },
1026}; 1026};
1027 1027
1028static int stk_vidioc_g_fmt_cap(struct file *filp, 1028static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
1029 void *priv, struct v4l2_format *f) 1029 void *priv, struct v4l2_format *f)
1030{ 1030{
1031 struct v4l2_pix_format *pix_format = &f->fmt.pix; 1031 struct v4l2_pix_format *pix_format = &f->fmt.pix;
@@ -1054,7 +1054,7 @@ static int stk_vidioc_g_fmt_cap(struct file *filp,
1054 return 0; 1054 return 0;
1055} 1055}
1056 1056
1057static int stk_vidioc_try_fmt_cap(struct file *filp, 1057static int stk_vidioc_try_fmt_vid_cap(struct file *filp,
1058 void *priv, struct v4l2_format *fmtd) 1058 void *priv, struct v4l2_format *fmtd)
1059{ 1059{
1060 int i; 1060 int i;
@@ -1131,7 +1131,7 @@ static int stk_setup_format(struct stk_camera *dev)
1131 return stk_sensor_configure(dev); 1131 return stk_sensor_configure(dev);
1132} 1132}
1133 1133
1134static int stk_vidioc_s_fmt_cap(struct file *filp, 1134static int stk_vidioc_s_fmt_vid_cap(struct file *filp,
1135 void *priv, struct v4l2_format *fmtd) 1135 void *priv, struct v4l2_format *fmtd)
1136{ 1136{
1137 int ret; 1137 int ret;
@@ -1145,7 +1145,7 @@ static int stk_vidioc_s_fmt_cap(struct file *filp,
1145 return -EBUSY; 1145 return -EBUSY;
1146 if (dev->owner && dev->owner != filp) 1146 if (dev->owner && dev->owner != filp)
1147 return -EBUSY; 1147 return -EBUSY;
1148 ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd); 1148 ret = stk_vidioc_try_fmt_vid_cap(filp, priv, fmtd);
1149 if (ret) 1149 if (ret)
1150 return ret; 1150 return ret;
1151 dev->owner = filp; 1151 dev->owner = filp;
@@ -1342,10 +1342,10 @@ static struct video_device stk_v4l_data = {
1342 .release = stk_v4l_dev_release, 1342 .release = stk_v4l_dev_release,
1343 1343
1344 .vidioc_querycap = stk_vidioc_querycap, 1344 .vidioc_querycap = stk_vidioc_querycap,
1345 .vidioc_enum_fmt_cap = stk_vidioc_enum_fmt_cap, 1345 .vidioc_enum_fmt_vid_cap = stk_vidioc_enum_fmt_vid_cap,
1346 .vidioc_try_fmt_cap = stk_vidioc_try_fmt_cap, 1346 .vidioc_try_fmt_vid_cap = stk_vidioc_try_fmt_vid_cap,
1347 .vidioc_s_fmt_cap = stk_vidioc_s_fmt_cap, 1347 .vidioc_s_fmt_vid_cap = stk_vidioc_s_fmt_vid_cap,
1348 .vidioc_g_fmt_cap = stk_vidioc_g_fmt_cap, 1348 .vidioc_g_fmt_vid_cap = stk_vidioc_g_fmt_vid_cap,
1349 .vidioc_enum_input = stk_vidioc_enum_input, 1349 .vidioc_enum_input = stk_vidioc_enum_input,
1350 .vidioc_s_input = stk_vidioc_s_input, 1350 .vidioc_s_input = stk_vidioc_s_input,
1351 .vidioc_g_input = stk_vidioc_g_input, 1351 .vidioc_g_input = stk_vidioc_g_input,
diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c
index 8f0100f67a91..29991d1cf13e 100644
--- a/drivers/media/video/tcm825x.c
+++ b/drivers/media/video/tcm825x.c
@@ -523,6 +523,9 @@ static int ioctl_g_ctrl(struct v4l2_int_device *s,
523 if (val < 0) 523 if (val < 0)
524 return val; 524 return val;
525 525
526 if (vc->id == V4L2_CID_HFLIP || vc->id == V4L2_CID_VFLIP)
527 val ^= sensor->platform_data->is_upside_down();
528
526 vc->value = val; 529 vc->value = val;
527 return 0; 530 return 0;
528} 531}
@@ -556,6 +559,9 @@ static int ioctl_s_ctrl(struct v4l2_int_device *s,
556 if (lvc == NULL) 559 if (lvc == NULL)
557 return -EINVAL; 560 return -EINVAL;
558 561
562 if (vc->id == V4L2_CID_HFLIP || vc->id == V4L2_CID_VFLIP)
563 val ^= sensor->platform_data->is_upside_down();
564
559 val = val << lvc->start_bit; 565 val = val << lvc->start_bit;
560 if (tcm825x_write_reg_mask(client, lvc->reg, val)) 566 if (tcm825x_write_reg_mask(client, lvc->reg, val))
561 return -EIO; 567 return -EIO;
diff --git a/drivers/media/video/tcm825x.h b/drivers/media/video/tcm825x.h
index 966765b66b3a..770ebacfa344 100644
--- a/drivers/media/video/tcm825x.h
+++ b/drivers/media/video/tcm825x.h
@@ -182,6 +182,7 @@ struct tcm825x_platform_data {
182 int (*needs_reset)(struct v4l2_int_device *s, void *buf, 182 int (*needs_reset)(struct v4l2_int_device *s, void *buf,
183 struct v4l2_pix_format *fmt); 183 struct v4l2_pix_format *fmt);
184 int (*ifparm)(struct v4l2_ifparm *p); 184 int (*ifparm)(struct v4l2_ifparm *p);
185 int (*is_upside_down)(void);
185}; 186};
186 187
187/* Array of image sizes supported by TCM825X. These must be ordered from 188/* Array of image sizes supported by TCM825X. These must be ordered from
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index b4d10f7a4e57..ae75c187da79 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -72,6 +72,7 @@ static unsigned short normal_i2c[] = {
72 I2C_ADDR_TDA7432 >> 1, 72 I2C_ADDR_TDA7432 >> 1,
73 I2C_CLIENT_END, 73 I2C_CLIENT_END,
74}; 74};
75
75I2C_CLIENT_INSMOD; 76I2C_CLIENT_INSMOD;
76 77
77/* Structure of address and subaddresses for the tda7432 */ 78/* Structure of address and subaddresses for the tda7432 */
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index 0cee00242782..2437c1a269c5 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -34,6 +34,7 @@
34static int debug; /* insmod parameter */ 34static int debug; /* insmod parameter */
35module_param(debug, int, 0644); 35module_param(debug, int, 0644);
36MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); 36MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
37
37#define dprintk(args...) \ 38#define dprintk(args...) \
38 do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) 39 do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
39 40
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 3c0557130a70..7a8ce8fb46dc 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -30,7 +30,6 @@
30#include <linux/i2c.h> 30#include <linux/i2c.h>
31#include <linux/init.h> 31#include <linux/init.h>
32 32
33
34#include <media/i2c-addr.h> 33#include <media/i2c-addr.h>
35 34
36static int debug; /* insmod parameter */ 35static int debug; /* insmod parameter */
@@ -42,6 +41,7 @@ static unsigned short normal_i2c[] = {
42 I2C_ADDR_TDA9875 >> 1, 41 I2C_ADDR_TDA9875 >> 1,
43 I2C_CLIENT_END 42 I2C_CLIENT_END
44}; 43};
44
45I2C_CLIENT_INSMOD; 45I2C_CLIENT_INSMOD;
46 46
47/* This is a superset of the TDA9875 */ 47/* This is a superset of the TDA9875 */
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index 9513d8611e87..421c1445e96c 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -36,6 +36,7 @@
36static int debug; /* insmod parameter */ 36static int debug; /* insmod parameter */
37module_param(debug, int, 0644); 37module_param(debug, int, 0644);
38MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); 38MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
39
39#define dprintk(args...) \ 40#define dprintk(args...) \
40 do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) 41 do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
41 42
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index 7fd53367c07c..b5c8957d130e 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -36,6 +36,7 @@
36static int debug; /* insmod parameter */ 36static int debug; /* insmod parameter */
37module_param(debug, int, 0644); 37module_param(debug, int, 0644);
38MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off)."); 38MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
39
39#define dprintk(args...) \ 40#define dprintk(args...) \
40 do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0) 41 do { if (debug) { printk("%s: %s()[%d]: ", KBUILD_MODNAME, __func__, __LINE__); printk(args); } } while (0)
41 42
diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c
index 28ab9f9d760a..9220378a5637 100644
--- a/drivers/media/video/tlv320aic23b.c
+++ b/drivers/media/video/tlv320aic23b.c
@@ -39,7 +39,6 @@ MODULE_LICENSE("GPL");
39 39
40static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END }; 40static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END };
41 41
42
43I2C_CLIENT_INSMOD; 42I2C_CLIENT_INSMOD;
44 43
45/* ----------------------------------------------------------------------- */ 44/* ----------------------------------------------------------------------- */
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 0d12ace61665..93d879dc510f 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -1298,7 +1298,6 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1298 .id_table = tuner_id, 1298 .id_table = tuner_id,
1299}; 1299};
1300 1300
1301
1302/* 1301/*
1303 * Overrides for Emacs so that we follow Linus's tabbing style. 1302 * Overrides for Emacs so that we follow Linus's tabbing style.
1304 * --------------------------------------------------------------------------- 1303 * ---------------------------------------------------------------------------
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index c77914d99d15..463680b13289 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -69,7 +69,6 @@ typedef struct AUDIOCMD {
69/* chip description */ 69/* chip description */
70struct CHIPDESC { 70struct CHIPDESC {
71 char *name; /* chip name */ 71 char *name; /* chip name */
72 int id; /* ID */
73 int addr_lo, addr_hi; /* i2c address range */ 72 int addr_lo, addr_hi; /* i2c address range */
74 int registers; /* # of registers */ 73 int registers; /* # of registers */
75 74
@@ -1256,7 +1255,6 @@ module_param(ta8874z, int, 0444);
1256static struct CHIPDESC chiplist[] = { 1255static struct CHIPDESC chiplist[] = {
1257 { 1256 {
1258 .name = "tda9840", 1257 .name = "tda9840",
1259 .id = I2C_DRIVERID_TDA9840,
1260 .insmodopt = &tda9840, 1258 .insmodopt = &tda9840,
1261 .addr_lo = I2C_ADDR_TDA9840 >> 1, 1259 .addr_lo = I2C_ADDR_TDA9840 >> 1,
1262 .addr_hi = I2C_ADDR_TDA9840 >> 1, 1260 .addr_hi = I2C_ADDR_TDA9840 >> 1,
@@ -1272,7 +1270,6 @@ static struct CHIPDESC chiplist[] = {
1272 }, 1270 },
1273 { 1271 {
1274 .name = "tda9873h", 1272 .name = "tda9873h",
1275 .id = I2C_DRIVERID_TDA9873,
1276 .checkit = tda9873_checkit, 1273 .checkit = tda9873_checkit,
1277 .insmodopt = &tda9873, 1274 .insmodopt = &tda9873,
1278 .addr_lo = I2C_ADDR_TDA985x_L >> 1, 1275 .addr_lo = I2C_ADDR_TDA985x_L >> 1,
@@ -1293,7 +1290,6 @@ static struct CHIPDESC chiplist[] = {
1293 }, 1290 },
1294 { 1291 {
1295 .name = "tda9874h/a", 1292 .name = "tda9874h/a",
1296 .id = I2C_DRIVERID_TDA9874,
1297 .checkit = tda9874a_checkit, 1293 .checkit = tda9874a_checkit,
1298 .initialize = tda9874a_initialize, 1294 .initialize = tda9874a_initialize,
1299 .insmodopt = &tda9874a, 1295 .insmodopt = &tda9874a,
@@ -1306,7 +1302,6 @@ static struct CHIPDESC chiplist[] = {
1306 }, 1302 },
1307 { 1303 {
1308 .name = "tda9850", 1304 .name = "tda9850",
1309 .id = I2C_DRIVERID_TDA9850,
1310 .insmodopt = &tda9850, 1305 .insmodopt = &tda9850,
1311 .addr_lo = I2C_ADDR_TDA985x_L >> 1, 1306 .addr_lo = I2C_ADDR_TDA985x_L >> 1,
1312 .addr_hi = I2C_ADDR_TDA985x_H >> 1, 1307 .addr_hi = I2C_ADDR_TDA985x_H >> 1,
@@ -1319,7 +1314,6 @@ static struct CHIPDESC chiplist[] = {
1319 }, 1314 },
1320 { 1315 {
1321 .name = "tda9855", 1316 .name = "tda9855",
1322 .id = I2C_DRIVERID_TDA9855,
1323 .insmodopt = &tda9855, 1317 .insmodopt = &tda9855,
1324 .addr_lo = I2C_ADDR_TDA985x_L >> 1, 1318 .addr_lo = I2C_ADDR_TDA985x_L >> 1,
1325 .addr_hi = I2C_ADDR_TDA985x_H >> 1, 1319 .addr_hi = I2C_ADDR_TDA985x_H >> 1,
@@ -1344,7 +1338,6 @@ static struct CHIPDESC chiplist[] = {
1344 }, 1338 },
1345 { 1339 {
1346 .name = "tea6300", 1340 .name = "tea6300",
1347 .id = I2C_DRIVERID_TEA6300,
1348 .insmodopt = &tea6300, 1341 .insmodopt = &tea6300,
1349 .addr_lo = I2C_ADDR_TEA6300 >> 1, 1342 .addr_lo = I2C_ADDR_TEA6300 >> 1,
1350 .addr_hi = I2C_ADDR_TEA6300 >> 1, 1343 .addr_hi = I2C_ADDR_TEA6300 >> 1,
@@ -1365,7 +1358,6 @@ static struct CHIPDESC chiplist[] = {
1365 }, 1358 },
1366 { 1359 {
1367 .name = "tea6320", 1360 .name = "tea6320",
1368 .id = I2C_DRIVERID_TEA6300,
1369 .initialize = tea6320_initialize, 1361 .initialize = tea6320_initialize,
1370 .insmodopt = &tea6320, 1362 .insmodopt = &tea6320,
1371 .addr_lo = I2C_ADDR_TEA6300 >> 1, 1363 .addr_lo = I2C_ADDR_TEA6300 >> 1,
@@ -1387,7 +1379,6 @@ static struct CHIPDESC chiplist[] = {
1387 }, 1379 },
1388 { 1380 {
1389 .name = "tea6420", 1381 .name = "tea6420",
1390 .id = I2C_DRIVERID_TEA6420,
1391 .insmodopt = &tea6420, 1382 .insmodopt = &tea6420,
1392 .addr_lo = I2C_ADDR_TEA6420 >> 1, 1383 .addr_lo = I2C_ADDR_TEA6420 >> 1,
1393 .addr_hi = I2C_ADDR_TEA6420 >> 1, 1384 .addr_hi = I2C_ADDR_TEA6420 >> 1,
@@ -1400,7 +1391,6 @@ static struct CHIPDESC chiplist[] = {
1400 }, 1391 },
1401 { 1392 {
1402 .name = "tda8425", 1393 .name = "tda8425",
1403 .id = I2C_DRIVERID_TDA8425,
1404 .insmodopt = &tda8425, 1394 .insmodopt = &tda8425,
1405 .addr_lo = I2C_ADDR_TDA8425 >> 1, 1395 .addr_lo = I2C_ADDR_TDA8425 >> 1,
1406 .addr_hi = I2C_ADDR_TDA8425 >> 1, 1396 .addr_hi = I2C_ADDR_TDA8425 >> 1,
@@ -1424,7 +1414,6 @@ static struct CHIPDESC chiplist[] = {
1424 }, 1414 },
1425 { 1415 {
1426 .name = "pic16c54 (PV951)", 1416 .name = "pic16c54 (PV951)",
1427 .id = I2C_DRIVERID_PIC16C54_PV9,
1428 .insmodopt = &pic16c54, 1417 .insmodopt = &pic16c54,
1429 .addr_lo = I2C_ADDR_PIC16C54 >> 1, 1418 .addr_lo = I2C_ADDR_PIC16C54 >> 1,
1430 .addr_hi = I2C_ADDR_PIC16C54>> 1, 1419 .addr_hi = I2C_ADDR_PIC16C54>> 1,
@@ -1440,8 +1429,6 @@ static struct CHIPDESC chiplist[] = {
1440 }, 1429 },
1441 { 1430 {
1442 .name = "ta8874z", 1431 .name = "ta8874z",
1443 .id = -1,
1444 /*.id = I2C_DRIVERID_TA8874Z, */
1445 .checkit = ta8874z_checkit, 1432 .checkit = ta8874z_checkit,
1446 .insmodopt = &ta8874z, 1433 .insmodopt = &ta8874z,
1447 .addr_lo = I2C_ADDR_TDA9840 >> 1, 1434 .addr_lo = I2C_ADDR_TDA9840 >> 1,
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index a9c5e5adba3a..abf685464b7c 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -169,7 +169,6 @@ static void usbvision_rvfree(void *mem, unsigned long size)
169} 169}
170 170
171 171
172
173#if ENABLE_HEXDUMP 172#if ENABLE_HEXDUMP
174static void usbvision_hexdump(const unsigned char *data, int len) 173static void usbvision_hexdump(const unsigned char *data, int len)
175{ 174{
@@ -2317,7 +2316,6 @@ static void usbvision_powerOffTimer(unsigned long data)
2317 del_timer(&usbvision->powerOffTimer); 2316 del_timer(&usbvision->powerOffTimer);
2318 INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off); 2317 INIT_WORK(&usbvision->powerOffWork, call_usbvision_power_off);
2319 (void) schedule_work(&usbvision->powerOffWork); 2318 (void) schedule_work(&usbvision->powerOffWork);
2320
2321} 2319}
2322 2320
2323void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision) 2321void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision)
@@ -2518,7 +2516,6 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
2518 } 2516 }
2519 } 2517 }
2520 2518
2521
2522 /* Submit all URBs */ 2519 /* Submit all URBs */
2523 for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { 2520 for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
2524 errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, 2521 errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb,
@@ -2564,7 +2561,6 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
2564 usbvision->sbuf[bufIdx].urb = NULL; 2561 usbvision->sbuf[bufIdx].urb = NULL;
2565 } 2562 }
2566 2563
2567
2568 PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __func__); 2564 PDEBUG(DBG_ISOC, "%s: streaming=Stream_Off\n", __func__);
2569 usbvision->streaming = Stream_Off; 2565 usbvision->streaming = Stream_Off;
2570 2566
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index e2274d77ea29..a6d00858b07e 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -190,7 +190,6 @@ static u32 functionality(struct i2c_adapter *adap)
190 return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; 190 return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
191} 191}
192 192
193
194/* -----exported algorithm data: ------------------------------------- */ 193/* -----exported algorithm data: ------------------------------------- */
195 194
196static struct i2c_algorithm usbvision_algo = { 195static struct i2c_algorithm usbvision_algo = {
@@ -514,11 +513,7 @@ static struct i2c_adapter i2c_adap_template = {
514 .id = I2C_HW_B_BT848, /* FIXME */ 513 .id = I2C_HW_B_BT848, /* FIXME */
515 .client_register = attach_inform, 514 .client_register = attach_inform,
516 .client_unregister = detach_inform, 515 .client_unregister = detach_inform,
517#ifdef I2C_ADAP_CLASS_TV_ANALOG
518 .class = I2C_ADAP_CLASS_TV_ANALOG,
519#else
520 .class = I2C_CLASS_TV_ANALOG, 516 .class = I2C_CLASS_TV_ANALOG,
521#endif
522}; 517};
523 518
524static struct i2c_client i2c_client_template = { 519static struct i2c_client i2c_client_template = {
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index d97261ab430f..cd6c41d67899 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -179,7 +179,6 @@ MODULE_ALIAS(DRIVER_ALIAS);
179/* /sys/bus/usb/drivers/USBVision Video Grabber */ 179/* /sys/bus/usb/drivers/USBVision Video Grabber */
180/*****************************************************************************/ 180/*****************************************************************************/
181 181
182
183#define YES_NO(x) ((x) ? "Yes" : "No") 182#define YES_NO(x) ((x) ? "Yes" : "No")
184 183
185static inline struct usb_usbvision *cd_to_usbvision(struct device *cd) 184static inline struct usb_usbvision *cd_to_usbvision(struct device *cd)
@@ -370,7 +369,6 @@ static void usbvision_remove_sysfs(struct video_device *vdev)
370 } 369 }
371} 370}
372 371
373
374/* 372/*
375 * usbvision_open() 373 * usbvision_open()
376 * 374 *
@@ -388,7 +386,6 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
388 386
389 PDEBUG(DBG_IO, "open"); 387 PDEBUG(DBG_IO, "open");
390 388
391
392 usbvision_reset_powerOffTimer(usbvision); 389 usbvision_reset_powerOffTimer(usbvision);
393 390
394 if (usbvision->user) 391 if (usbvision->user)
@@ -442,9 +439,6 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
442 mutex_unlock(&usbvision->lock); 439 mutex_unlock(&usbvision->lock);
443 } 440 }
444 441
445 if (errCode) {
446 }
447
448 /* prepare queues */ 442 /* prepare queues */
449 usbvision_empty_framequeues(usbvision); 443 usbvision_empty_framequeues(usbvision);
450 444
@@ -495,8 +489,6 @@ static int usbvision_v4l2_close(struct inode *inode, struct file *file)
495 } 489 }
496 490
497 PDEBUG(DBG_IO, "success"); 491 PDEBUG(DBG_IO, "success");
498
499
500 return 0; 492 return 0;
501} 493}
502 494
@@ -998,7 +990,7 @@ static int vidioc_streamoff(struct file *file,
998 return 0; 990 return 0;
999} 991}
1000 992
1001static int vidioc_enum_fmt_cap (struct file *file, void *priv, 993static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv,
1002 struct v4l2_fmtdesc *vfd) 994 struct v4l2_fmtdesc *vfd)
1003{ 995{
1004 if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) { 996 if(vfd->index>=USBVISION_SUPPORTED_PALETTES-1) {
@@ -1012,7 +1004,7 @@ static int vidioc_enum_fmt_cap (struct file *file, void *priv,
1012 return 0; 1004 return 0;
1013} 1005}
1014 1006
1015static int vidioc_g_fmt_cap (struct file *file, void *priv, 1007static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
1016 struct v4l2_format *vf) 1008 struct v4l2_format *vf)
1017{ 1009{
1018 struct video_device *dev = video_devdata(file); 1010 struct video_device *dev = video_devdata(file);
@@ -1030,7 +1022,7 @@ static int vidioc_g_fmt_cap (struct file *file, void *priv,
1030 return 0; 1022 return 0;
1031} 1023}
1032 1024
1033static int vidioc_try_fmt_cap (struct file *file, void *priv, 1025static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
1034 struct v4l2_format *vf) 1026 struct v4l2_format *vf)
1035{ 1027{
1036 struct video_device *dev = video_devdata(file); 1028 struct video_device *dev = video_devdata(file);
@@ -1060,7 +1052,7 @@ static int vidioc_try_fmt_cap (struct file *file, void *priv,
1060 return 0; 1052 return 0;
1061} 1053}
1062 1054
1063static int vidioc_s_fmt_cap(struct file *file, void *priv, 1055static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1064 struct v4l2_format *vf) 1056 struct v4l2_format *vf)
1065{ 1057{
1066 struct video_device *dev = video_devdata(file); 1058 struct video_device *dev = video_devdata(file);
@@ -1068,7 +1060,7 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv,
1068 (struct usb_usbvision *) video_get_drvdata(dev); 1060 (struct usb_usbvision *) video_get_drvdata(dev);
1069 int ret; 1061 int ret;
1070 1062
1071 if( 0 != (ret=vidioc_try_fmt_cap (file, priv, vf)) ) { 1063 if( 0 != (ret=vidioc_try_fmt_vid_cap (file, priv, vf)) ) {
1072 return ret; 1064 return ret;
1073 } 1065 }
1074 1066
@@ -1346,9 +1338,7 @@ static int usbvision_radio_close(struct inode *inode, struct file *file)
1346 usbvision_release(usbvision); 1338 usbvision_release(usbvision);
1347 } 1339 }
1348 1340
1349
1350 PDEBUG(DBG_IO, "success"); 1341 PDEBUG(DBG_IO, "success");
1351
1352 return errCode; 1342 return errCode;
1353} 1343}
1354 1344
@@ -1360,7 +1350,6 @@ static int usbvision_vbi_open(struct inode *inode, struct file *file)
1360{ 1350{
1361 /* TODO */ 1351 /* TODO */
1362 return -ENODEV; 1352 return -ENODEV;
1363
1364} 1353}
1365 1354
1366static int usbvision_vbi_close(struct inode *inode, struct file *file) 1355static int usbvision_vbi_close(struct inode *inode, struct file *file)
@@ -1407,10 +1396,10 @@ static struct video_device usbvision_video_template = {
1407 .release = video_device_release, 1396 .release = video_device_release,
1408 .minor = -1, 1397 .minor = -1,
1409 .vidioc_querycap = vidioc_querycap, 1398 .vidioc_querycap = vidioc_querycap,
1410 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, 1399 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1411 .vidioc_g_fmt_cap = vidioc_g_fmt_cap, 1400 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1412 .vidioc_try_fmt_cap = vidioc_try_fmt_cap, 1401 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1413 .vidioc_s_fmt_cap = vidioc_s_fmt_cap, 1402 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1414 .vidioc_reqbufs = vidioc_reqbufs, 1403 .vidioc_reqbufs = vidioc_reqbufs,
1415 .vidioc_querybuf = vidioc_querybuf, 1404 .vidioc_querybuf = vidioc_querybuf,
1416 .vidioc_qbuf = vidioc_qbuf, 1405 .vidioc_qbuf = vidioc_qbuf,
@@ -1899,7 +1888,6 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
1899 } 1888 }
1900 1889
1901 PDEBUG(DBG_PROBE, "success"); 1890 PDEBUG(DBG_PROBE, "success");
1902
1903} 1891}
1904 1892
1905static struct usb_driver usbvision_driver = { 1893static struct usb_driver usbvision_driver = {
diff --git a/drivers/media/video/uvc/Kconfig b/drivers/media/video/uvc/Kconfig
new file mode 100644
index 000000000000..c2d9760de832
--- /dev/null
+++ b/drivers/media/video/uvc/Kconfig
@@ -0,0 +1,17 @@
1config USB_VIDEO_CLASS
2 tristate "USB Video Class (UVC)"
3 ---help---
4 Support for the USB Video Class (UVC). Currently only video
5 input devices, such as webcams, are supported.
6
7 For more information see: <http://linux-uvc.berlios.de/>
8
9config USB_VIDEO_CLASS_INPUT_EVDEV
10 bool "UVC input events device support"
11 default y
12 depends on USB_VIDEO_CLASS && INPUT
13 ---help---
14 This option makes USB Video Class devices register an input device
15 to report button events.
16
17 If you are in doubt, say Y.
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
index f0ee46d15540..3ae95512666f 100644
--- a/drivers/media/video/uvc/uvc_ctrl.c
+++ b/drivers/media/video/uvc/uvc_ctrl.c
@@ -1254,3 +1254,4 @@ void uvc_ctrl_init(void)
1254 for (; mapping < mend; ++mapping) 1254 for (; mapping < mend; ++mapping)
1255 uvc_ctrl_add_mapping(mapping); 1255 uvc_ctrl_add_mapping(mapping);
1256} 1256}
1257
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index 60ced589f898..f2b2983fe062 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -298,7 +298,8 @@ static int uvc_parse_format(struct uvc_device *dev,
298 switch (buffer[2]) { 298 switch (buffer[2]) {
299 case VS_FORMAT_UNCOMPRESSED: 299 case VS_FORMAT_UNCOMPRESSED:
300 case VS_FORMAT_FRAME_BASED: 300 case VS_FORMAT_FRAME_BASED:
301 if (buflen < 27) { 301 n = buffer[2] == VS_FORMAT_UNCOMPRESSED ? 27 : 28;
302 if (buflen < n) {
302 uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" 303 uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming"
303 "interface %d FORMAT error\n", 304 "interface %d FORMAT error\n",
304 dev->udev->devnum, 305 dev->udev->devnum,
@@ -1632,13 +1633,16 @@ static void uvc_disconnect(struct usb_interface *intf)
1632 * reference to the uvc_device instance after uvc_v4l2_open() received 1633 * reference to the uvc_device instance after uvc_v4l2_open() received
1633 * the pointer to the device (video_devdata) but before it got the 1634 * the pointer to the device (video_devdata) but before it got the
1634 * chance to increase the reference count (kref_get). 1635 * chance to increase the reference count (kref_get).
1636 *
1637 * Note that the reference can't be released with the lock held,
1638 * otherwise a AB-BA deadlock can occur with videodev_lock that
1639 * videodev acquires in videodev_open() and video_unregister_device().
1635 */ 1640 */
1636 mutex_lock(&uvc_driver.open_mutex); 1641 mutex_lock(&uvc_driver.open_mutex);
1637
1638 dev->state |= UVC_DEV_DISCONNECTED; 1642 dev->state |= UVC_DEV_DISCONNECTED;
1639 kref_put(&dev->kref, uvc_delete);
1640
1641 mutex_unlock(&uvc_driver.open_mutex); 1643 mutex_unlock(&uvc_driver.open_mutex);
1644
1645 kref_put(&dev->kref, uvc_delete);
1642} 1646}
1643 1647
1644static int uvc_suspend(struct usb_interface *intf, pm_message_t message) 1648static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
@@ -1825,6 +1829,15 @@ static struct usb_device_id uvc_ids[] = {
1825 .bInterfaceSubClass = 1, 1829 .bInterfaceSubClass = 1,
1826 .bInterfaceProtocol = 0, 1830 .bInterfaceProtocol = 0,
1827 .driver_info = UVC_QUIRK_STREAM_NO_FID }, 1831 .driver_info = UVC_QUIRK_STREAM_NO_FID },
1832 /* Asus F9SG */
1833 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1834 | USB_DEVICE_ID_MATCH_INT_INFO,
1835 .idVendor = 0x174f,
1836 .idProduct = 0x8a31,
1837 .bInterfaceClass = USB_CLASS_VIDEO,
1838 .bInterfaceSubClass = 1,
1839 .bInterfaceProtocol = 0,
1840 .driver_info = UVC_QUIRK_STREAM_NO_FID },
1828 /* Syntek (Asus U3S) */ 1841 /* Syntek (Asus U3S) */
1829 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE 1842 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1830 | USB_DEVICE_ID_MATCH_INT_INFO, 1843 | USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1891,6 +1904,15 @@ static struct usb_device_id uvc_ids[] = {
1891 .bInterfaceSubClass = 1, 1904 .bInterfaceSubClass = 1,
1892 .bInterfaceProtocol = 0, 1905 .bInterfaceProtocol = 0,
1893 .driver_info = UVC_QUIRK_PROBE_MINMAX }, 1906 .driver_info = UVC_QUIRK_PROBE_MINMAX },
1907 /* Medion Akoya Mini E1210 */
1908 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1909 | USB_DEVICE_ID_MATCH_INT_INFO,
1910 .idVendor = 0x5986,
1911 .idProduct = 0x0141,
1912 .bInterfaceClass = USB_CLASS_VIDEO,
1913 .bInterfaceSubClass = 1,
1914 .bInterfaceProtocol = 0,
1915 .driver_info = UVC_QUIRK_PROBE_MINMAX },
1894 /* Acer OrbiCam - Unknown vendor */ 1916 /* Acer OrbiCam - Unknown vendor */
1895 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE 1917 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1896 | USB_DEVICE_ID_MATCH_INT_INFO, 1918 | USB_DEVICE_ID_MATCH_INT_INFO,
@@ -1953,3 +1975,4 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
1953MODULE_DESCRIPTION(DRIVER_DESC); 1975MODULE_DESCRIPTION(DRIVER_DESC);
1954MODULE_LICENSE("GPL"); 1976MODULE_LICENSE("GPL");
1955MODULE_VERSION(DRIVER_VERSION); 1977MODULE_VERSION(DRIVER_VERSION);
1978
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index 0923f0e3b3d4..7388d0cee3d4 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -475,3 +475,4 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
475 wake_up(&buf->wait); 475 wake_up(&buf->wait);
476 return nextbuf; 476 return nextbuf;
477} 477}
478
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c
index be9084e5eace..75e678ac54eb 100644
--- a/drivers/media/video/uvc/uvc_status.c
+++ b/drivers/media/video/uvc/uvc_status.c
@@ -22,6 +22,7 @@
22/* -------------------------------------------------------------------------- 22/* --------------------------------------------------------------------------
23 * Input device 23 * Input device
24 */ 24 */
25#ifdef CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV
25static int uvc_input_init(struct uvc_device *dev) 26static int uvc_input_init(struct uvc_device *dev)
26{ 27{
27 struct usb_device *udev = dev->udev; 28 struct usb_device *udev = dev->udev;
@@ -67,6 +68,19 @@ static void uvc_input_cleanup(struct uvc_device *dev)
67 input_unregister_device(dev->input); 68 input_unregister_device(dev->input);
68} 69}
69 70
71static void uvc_input_report_key(struct uvc_device *dev, unsigned int code,
72 int value)
73{
74 if (dev->input)
75 input_report_key(dev->input, code, value);
76}
77
78#else
79#define uvc_input_init(dev)
80#define uvc_input_cleanup(dev)
81#define uvc_input_report_key(dev, code, value)
82#endif /* CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV */
83
70/* -------------------------------------------------------------------------- 84/* --------------------------------------------------------------------------
71 * Status interrupt endpoint 85 * Status interrupt endpoint
72 */ 86 */
@@ -83,8 +97,7 @@ static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len)
83 return; 97 return;
84 uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", 98 uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n",
85 data[1], data[3] ? "pressed" : "released", len); 99 data[1], data[3] ? "pressed" : "released", len);
86 if (dev->input) 100 uvc_input_report_key(dev, BTN_0, data[3]);
87 input_report_key(dev->input, BTN_0, data[3]);
88 } else { 101 } else {
89 uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " 102 uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x "
90 "len %d.\n", data[1], data[2], data[3], len); 103 "len %d.\n", data[1], data[2], data[3], len);
@@ -203,5 +216,6 @@ int uvc_status_resume(struct uvc_device *dev)
203 if (dev->int_urb == NULL) 216 if (dev->int_urb == NULL)
204 return 0; 217 return 0;
205 218
206 return usb_submit_urb(dev->int_urb, GFP_KERNEL); 219 return usb_submit_urb(dev->int_urb, GFP_NOIO);
207} 220}
221
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 2e0a66575bb4..b5a11eb8f9fa 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -1032,7 +1032,7 @@ static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
1032{ 1032{
1033 struct video_device *vdev = video_devdata(file); 1033 struct video_device *vdev = video_devdata(file);
1034 struct uvc_video_device *video = video_get_drvdata(vdev); 1034 struct uvc_video_device *video = video_get_drvdata(vdev);
1035 struct uvc_buffer *buffer; 1035 struct uvc_buffer *uninitialized_var(buffer);
1036 struct page *page; 1036 struct page *page;
1037 unsigned long addr, start, size; 1037 unsigned long addr, start, size;
1038 unsigned int i; 1038 unsigned int i;
@@ -1103,3 +1103,4 @@ struct file_operations uvc_fops = {
1103 .mmap = uvc_v4l2_mmap, 1103 .mmap = uvc_v4l2_mmap,
1104 .poll = uvc_v4l2_poll, 1104 .poll = uvc_v4l2_poll,
1105}; 1105};
1106
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 6faf1fb21614..ad63794fda77 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -554,9 +554,56 @@ static void uvc_video_complete(struct urb *urb)
554} 554}
555 555
556/* 556/*
557 * Free transfer buffers.
558 */
559static void uvc_free_urb_buffers(struct uvc_video_device *video)
560{
561 unsigned int i;
562
563 for (i = 0; i < UVC_URBS; ++i) {
564 if (video->urb_buffer[i]) {
565 usb_buffer_free(video->dev->udev, video->urb_size,
566 video->urb_buffer[i], video->urb_dma[i]);
567 video->urb_buffer[i] = NULL;
568 }
569 }
570
571 video->urb_size = 0;
572}
573
574/*
575 * Allocate transfer buffers. This function can be called with buffers
576 * already allocated when resuming from suspend, in which case it will
577 * return without touching the buffers.
578 *
579 * Return 0 on success or -ENOMEM when out of memory.
580 */
581static int uvc_alloc_urb_buffers(struct uvc_video_device *video,
582 unsigned int size)
583{
584 unsigned int i;
585
586 /* Buffers are already allocated, bail out. */
587 if (video->urb_size)
588 return 0;
589
590 for (i = 0; i < UVC_URBS; ++i) {
591 video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,
592 size, GFP_KERNEL, &video->urb_dma[i]);
593 if (video->urb_buffer[i] == NULL) {
594 uvc_free_urb_buffers(video);
595 return -ENOMEM;
596 }
597 }
598
599 video->urb_size = size;
600 return 0;
601}
602
603/*
557 * Uninitialize isochronous/bulk URBs and free transfer buffers. 604 * Uninitialize isochronous/bulk URBs and free transfer buffers.
558 */ 605 */
559static void uvc_uninit_video(struct uvc_video_device *video) 606static void uvc_uninit_video(struct uvc_video_device *video, int free_buffers)
560{ 607{
561 struct urb *urb; 608 struct urb *urb;
562 unsigned int i; 609 unsigned int i;
@@ -566,19 +613,12 @@ static void uvc_uninit_video(struct uvc_video_device *video)
566 continue; 613 continue;
567 614
568 usb_kill_urb(urb); 615 usb_kill_urb(urb);
569 /* urb->transfer_buffer_length is not touched by USB core, so
570 * we can use it here as the buffer length.
571 */
572 if (video->urb_buffer[i]) {
573 usb_buffer_free(video->dev->udev,
574 urb->transfer_buffer_length,
575 video->urb_buffer[i], urb->transfer_dma);
576 video->urb_buffer[i] = NULL;
577 }
578
579 usb_free_urb(urb); 616 usb_free_urb(urb);
580 video->urb[i] = NULL; 617 video->urb[i] = NULL;
581 } 618 }
619
620 if (free_buffers)
621 uvc_free_urb_buffers(video);
582} 622}
583 623
584/* 624/*
@@ -586,7 +626,7 @@ static void uvc_uninit_video(struct uvc_video_device *video)
586 * is given by the endpoint. 626 * is given by the endpoint.
587 */ 627 */
588static int uvc_init_video_isoc(struct uvc_video_device *video, 628static int uvc_init_video_isoc(struct uvc_video_device *video,
589 struct usb_host_endpoint *ep) 629 struct usb_host_endpoint *ep, gfp_t gfp_flags)
590{ 630{
591 struct urb *urb; 631 struct urb *urb;
592 unsigned int npackets, i, j; 632 unsigned int npackets, i, j;
@@ -610,18 +650,13 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
610 650
611 size = npackets * psize; 651 size = npackets * psize;
612 652
653 if (uvc_alloc_urb_buffers(video, size) < 0)
654 return -ENOMEM;
655
613 for (i = 0; i < UVC_URBS; ++i) { 656 for (i = 0; i < UVC_URBS; ++i) {
614 urb = usb_alloc_urb(npackets, GFP_KERNEL); 657 urb = usb_alloc_urb(npackets, gfp_flags);
615 if (urb == NULL) { 658 if (urb == NULL) {
616 uvc_uninit_video(video); 659 uvc_uninit_video(video, 1);
617 return -ENOMEM;
618 }
619
620 video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,
621 size, GFP_KERNEL, &urb->transfer_dma);
622 if (video->urb_buffer[i] == NULL) {
623 usb_free_urb(urb);
624 uvc_uninit_video(video);
625 return -ENOMEM; 660 return -ENOMEM;
626 } 661 }
627 662
@@ -632,6 +667,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
632 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; 667 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
633 urb->interval = ep->desc.bInterval; 668 urb->interval = ep->desc.bInterval;
634 urb->transfer_buffer = video->urb_buffer[i]; 669 urb->transfer_buffer = video->urb_buffer[i];
670 urb->transfer_dma = video->urb_dma[i];
635 urb->complete = uvc_video_complete; 671 urb->complete = uvc_video_complete;
636 urb->number_of_packets = npackets; 672 urb->number_of_packets = npackets;
637 urb->transfer_buffer_length = size; 673 urb->transfer_buffer_length = size;
@@ -652,7 +688,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
652 * given by the endpoint. 688 * given by the endpoint.
653 */ 689 */
654static int uvc_init_video_bulk(struct uvc_video_device *video, 690static int uvc_init_video_bulk(struct uvc_video_device *video,
655 struct usb_host_endpoint *ep) 691 struct usb_host_endpoint *ep, gfp_t gfp_flags)
656{ 692{
657 struct urb *urb; 693 struct urb *urb;
658 unsigned int pipe, i; 694 unsigned int pipe, i;
@@ -671,20 +707,15 @@ static int uvc_init_video_bulk(struct uvc_video_device *video,
671 if (size > psize * UVC_MAX_ISO_PACKETS) 707 if (size > psize * UVC_MAX_ISO_PACKETS)
672 size = psize * UVC_MAX_ISO_PACKETS; 708 size = psize * UVC_MAX_ISO_PACKETS;
673 709
710 if (uvc_alloc_urb_buffers(video, size) < 0)
711 return -ENOMEM;
712
674 pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress); 713 pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress);
675 714
676 for (i = 0; i < UVC_URBS; ++i) { 715 for (i = 0; i < UVC_URBS; ++i) {
677 urb = usb_alloc_urb(0, GFP_KERNEL); 716 urb = usb_alloc_urb(0, gfp_flags);
678 if (urb == NULL) { 717 if (urb == NULL) {
679 uvc_uninit_video(video); 718 uvc_uninit_video(video, 1);
680 return -ENOMEM;
681 }
682
683 video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,
684 size, GFP_KERNEL, &urb->transfer_dma);
685 if (video->urb_buffer[i] == NULL) {
686 usb_free_urb(urb);
687 uvc_uninit_video(video);
688 return -ENOMEM; 719 return -ENOMEM;
689 } 720 }
690 721
@@ -692,6 +723,7 @@ static int uvc_init_video_bulk(struct uvc_video_device *video,
692 video->urb_buffer[i], size, uvc_video_complete, 723 video->urb_buffer[i], size, uvc_video_complete,
693 video); 724 video);
694 urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; 725 urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
726 urb->transfer_dma = video->urb_dma[i];
695 727
696 video->urb[i] = urb; 728 video->urb[i] = urb;
697 } 729 }
@@ -702,7 +734,7 @@ static int uvc_init_video_bulk(struct uvc_video_device *video,
702/* 734/*
703 * Initialize isochronous/bulk URBs and allocate transfer buffers. 735 * Initialize isochronous/bulk URBs and allocate transfer buffers.
704 */ 736 */
705static int uvc_init_video(struct uvc_video_device *video) 737static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags)
706{ 738{
707 struct usb_interface *intf = video->streaming->intf; 739 struct usb_interface *intf = video->streaming->intf;
708 struct usb_host_interface *alts; 740 struct usb_host_interface *alts;
@@ -747,7 +779,7 @@ static int uvc_init_video(struct uvc_video_device *video)
747 if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0) 779 if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0)
748 return ret; 780 return ret;
749 781
750 ret = uvc_init_video_isoc(video, ep); 782 ret = uvc_init_video_isoc(video, ep, gfp_flags);
751 } else { 783 } else {
752 /* Bulk endpoint, proceed to URB initialization. */ 784 /* Bulk endpoint, proceed to URB initialization. */
753 ep = uvc_find_endpoint(&intf->altsetting[0], 785 ep = uvc_find_endpoint(&intf->altsetting[0],
@@ -755,7 +787,7 @@ static int uvc_init_video(struct uvc_video_device *video)
755 if (ep == NULL) 787 if (ep == NULL)
756 return -EIO; 788 return -EIO;
757 789
758 ret = uvc_init_video_bulk(video, ep); 790 ret = uvc_init_video_bulk(video, ep, gfp_flags);
759 } 791 }
760 792
761 if (ret < 0) 793 if (ret < 0)
@@ -763,10 +795,10 @@ static int uvc_init_video(struct uvc_video_device *video)
763 795
764 /* Submit the URBs. */ 796 /* Submit the URBs. */
765 for (i = 0; i < UVC_URBS; ++i) { 797 for (i = 0; i < UVC_URBS; ++i) {
766 if ((ret = usb_submit_urb(video->urb[i], GFP_KERNEL)) < 0) { 798 if ((ret = usb_submit_urb(video->urb[i], gfp_flags)) < 0) {
767 uvc_printk(KERN_ERR, "Failed to submit URB %u " 799 uvc_printk(KERN_ERR, "Failed to submit URB %u "
768 "(%d).\n", i, ret); 800 "(%d).\n", i, ret);
769 uvc_uninit_video(video); 801 uvc_uninit_video(video, 1);
770 return ret; 802 return ret;
771 } 803 }
772 } 804 }
@@ -791,7 +823,7 @@ int uvc_video_suspend(struct uvc_video_device *video)
791 return 0; 823 return 0;
792 824
793 video->frozen = 1; 825 video->frozen = 1;
794 uvc_uninit_video(video); 826 uvc_uninit_video(video, 0);
795 usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); 827 usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);
796 return 0; 828 return 0;
797} 829}
@@ -818,7 +850,7 @@ int uvc_video_resume(struct uvc_video_device *video)
818 if (!uvc_queue_streaming(&video->queue)) 850 if (!uvc_queue_streaming(&video->queue))
819 return 0; 851 return 0;
820 852
821 if ((ret = uvc_init_video(video)) < 0) 853 if ((ret = uvc_init_video(video, GFP_NOIO)) < 0)
822 uvc_queue_enable(&video->queue, 0); 854 uvc_queue_enable(&video->queue, 0);
823 855
824 return ret; 856 return ret;
@@ -920,7 +952,7 @@ int uvc_video_enable(struct uvc_video_device *video, int enable)
920 int ret; 952 int ret;
921 953
922 if (!enable) { 954 if (!enable) {
923 uvc_uninit_video(video); 955 uvc_uninit_video(video, 1);
924 usb_set_interface(video->dev->udev, 956 usb_set_interface(video->dev->udev,
925 video->streaming->intfnum, 0); 957 video->streaming->intfnum, 0);
926 uvc_queue_enable(&video->queue, 0); 958 uvc_queue_enable(&video->queue, 0);
@@ -930,5 +962,6 @@ int uvc_video_enable(struct uvc_video_device *video, int enable)
930 if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) 962 if ((ret = uvc_queue_enable(&video->queue, 1)) < 0)
931 return ret; 963 return ret;
932 964
933 return uvc_init_video(video); 965 return uvc_init_video(video, GFP_KERNEL);
934} 966}
967
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index a995a780db1c..bafe3406e305 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -602,6 +602,8 @@ struct uvc_video_device {
602 602
603 struct urb *urb[UVC_URBS]; 603 struct urb *urb[UVC_URBS];
604 char *urb_buffer[UVC_URBS]; 604 char *urb_buffer[UVC_URBS];
605 dma_addr_t urb_dma[UVC_URBS];
606 unsigned int urb_size;
605 607
606 __u8 last_fid; 608 __u8 last_fid;
607}; 609};
@@ -794,3 +796,4 @@ void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video,
794#endif /* __KERNEL__ */ 796#endif /* __KERNEL__ */
795 797
796#endif 798#endif
799
diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c
new file mode 100644
index 000000000000..03f20acb668c
--- /dev/null
+++ b/drivers/media/video/videobuf-dma-contig.c
@@ -0,0 +1,418 @@
1/*
2 * helper functions for physically contiguous capture buffers
3 *
4 * The functions support hardware lacking scatter gather support
5 * (i.e. the buffers must be linear in physical memory)
6 *
7 * Copyright (c) 2008 Magnus Damm
8 *
9 * Based on videobuf-vmalloc.c,
10 * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2
15 */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/mm.h>
20#include <linux/dma-mapping.h>
21#include <media/videobuf-dma-contig.h>
22
23struct videobuf_dma_contig_memory {
24 u32 magic;
25 void *vaddr;
26 dma_addr_t dma_handle;
27 unsigned long size;
28};
29
30#define MAGIC_DC_MEM 0x0733ac61
31#define MAGIC_CHECK(is, should) \
32 if (unlikely((is) != (should))) { \
33 pr_err("magic mismatch: %x expected %x\n", is, should); \
34 BUG(); \
35 }
36
37static void
38videobuf_vm_open(struct vm_area_struct *vma)
39{
40 struct videobuf_mapping *map = vma->vm_private_data;
41
42 dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
43 map, map->count, vma->vm_start, vma->vm_end);
44
45 map->count++;
46}
47
48static void videobuf_vm_close(struct vm_area_struct *vma)
49{
50 struct videobuf_mapping *map = vma->vm_private_data;
51 struct videobuf_queue *q = map->q;
52 int i;
53
54 dev_dbg(map->q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n",
55 map, map->count, vma->vm_start, vma->vm_end);
56
57 map->count--;
58 if (0 == map->count) {
59 struct videobuf_dma_contig_memory *mem;
60
61 dev_dbg(map->q->dev, "munmap %p q=%p\n", map, q);
62 mutex_lock(&q->vb_lock);
63
64 /* We need first to cancel streams, before unmapping */
65 if (q->streaming)
66 videobuf_queue_cancel(q);
67
68 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
69 if (NULL == q->bufs[i])
70 continue;
71
72 if (q->bufs[i]->map != map)
73 continue;
74
75 mem = q->bufs[i]->priv;
76 if (mem) {
77 /* This callback is called only if kernel has
78 allocated memory and this memory is mmapped.
79 In this case, memory should be freed,
80 in order to do memory unmap.
81 */
82
83 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
84
85 /* vfree is not atomic - can't be
86 called with IRQ's disabled
87 */
88 dev_dbg(map->q->dev, "buf[%d] freeing %p\n",
89 i, mem->vaddr);
90
91 dma_free_coherent(q->dev, mem->size,
92 mem->vaddr, mem->dma_handle);
93 mem->vaddr = NULL;
94 }
95
96 q->bufs[i]->map = NULL;
97 q->bufs[i]->baddr = 0;
98 }
99
100 kfree(map);
101
102 mutex_unlock(&q->vb_lock);
103 }
104}
105
106static struct vm_operations_struct videobuf_vm_ops = {
107 .open = videobuf_vm_open,
108 .close = videobuf_vm_close,
109};
110
111static void *__videobuf_alloc(size_t size)
112{
113 struct videobuf_dma_contig_memory *mem;
114 struct videobuf_buffer *vb;
115
116 vb = kzalloc(size + sizeof(*mem), GFP_KERNEL);
117 if (vb) {
118 mem = vb->priv = ((char *)vb) + size;
119 mem->magic = MAGIC_DC_MEM;
120 }
121
122 return vb;
123}
124
125static void *__videobuf_to_vmalloc(struct videobuf_buffer *buf)
126{
127 struct videobuf_dma_contig_memory *mem = buf->priv;
128
129 BUG_ON(!mem);
130 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
131
132 return mem->vaddr;
133}
134
135static int __videobuf_iolock(struct videobuf_queue *q,
136 struct videobuf_buffer *vb,
137 struct v4l2_framebuffer *fbuf)
138{
139 struct videobuf_dma_contig_memory *mem = vb->priv;
140
141 BUG_ON(!mem);
142 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
143
144 switch (vb->memory) {
145 case V4L2_MEMORY_MMAP:
146 dev_dbg(q->dev, "%s memory method MMAP\n", __func__);
147
148 /* All handling should be done by __videobuf_mmap_mapper() */
149 if (!mem->vaddr) {
150 dev_err(q->dev, "memory is not alloced/mmapped.\n");
151 return -EINVAL;
152 }
153 break;
154 case V4L2_MEMORY_USERPTR:
155 dev_dbg(q->dev, "%s memory method USERPTR\n", __func__);
156
157 /* The only USERPTR currently supported is the one needed for
158 read() method.
159 */
160 if (vb->baddr)
161 return -EINVAL;
162
163 mem->size = PAGE_ALIGN(vb->size);
164 mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
165 &mem->dma_handle, GFP_KERNEL);
166 if (!mem->vaddr) {
167 dev_err(q->dev, "dma_alloc_coherent %ld failed\n",
168 mem->size);
169 return -ENOMEM;
170 }
171
172 dev_dbg(q->dev, "dma_alloc_coherent data is at %p (%ld)\n",
173 mem->vaddr, mem->size);
174 break;
175 case V4L2_MEMORY_OVERLAY:
176 default:
177 dev_dbg(q->dev, "%s memory method OVERLAY/unknown\n",
178 __func__);
179 return -EINVAL;
180 }
181
182 return 0;
183}
184
185static int __videobuf_sync(struct videobuf_queue *q,
186 struct videobuf_buffer *buf)
187{
188 struct videobuf_dma_contig_memory *mem = buf->priv;
189
190 BUG_ON(!mem);
191 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
192
193 dma_sync_single_for_cpu(q->dev, mem->dma_handle, mem->size,
194 DMA_FROM_DEVICE);
195 return 0;
196}
197
198static int __videobuf_mmap_free(struct videobuf_queue *q)
199{
200 unsigned int i;
201
202 dev_dbg(q->dev, "%s\n", __func__);
203 for (i = 0; i < VIDEO_MAX_FRAME; i++) {
204 if (q->bufs[i] && q->bufs[i]->map)
205 return -EBUSY;
206 }
207
208 return 0;
209}
210
211static int __videobuf_mmap_mapper(struct videobuf_queue *q,
212 struct vm_area_struct *vma)
213{
214 struct videobuf_dma_contig_memory *mem;
215 struct videobuf_mapping *map;
216 unsigned int first;
217 int retval;
218 unsigned long size, offset = vma->vm_pgoff << PAGE_SHIFT;
219
220 dev_dbg(q->dev, "%s\n", __func__);
221 if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED))
222 return -EINVAL;
223
224 /* look for first buffer to map */
225 for (first = 0; first < VIDEO_MAX_FRAME; first++) {
226 if (!q->bufs[first])
227 continue;
228
229 if (V4L2_MEMORY_MMAP != q->bufs[first]->memory)
230 continue;
231 if (q->bufs[first]->boff == offset)
232 break;
233 }
234 if (VIDEO_MAX_FRAME == first) {
235 dev_dbg(q->dev, "invalid user space offset [offset=0x%lx]\n",
236 offset);
237 return -EINVAL;
238 }
239
240 /* create mapping + update buffer list */
241 map = kzalloc(sizeof(struct videobuf_mapping), GFP_KERNEL);
242 if (!map)
243 return -ENOMEM;
244
245 q->bufs[first]->map = map;
246 map->start = vma->vm_start;
247 map->end = vma->vm_end;
248 map->q = q;
249
250 q->bufs[first]->baddr = vma->vm_start;
251
252 mem = q->bufs[first]->priv;
253 BUG_ON(!mem);
254 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
255
256 mem->size = PAGE_ALIGN(q->bufs[first]->bsize);
257 mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
258 &mem->dma_handle, GFP_KERNEL);
259 if (!mem->vaddr) {
260 dev_err(q->dev, "dma_alloc_coherent size %ld failed\n",
261 mem->size);
262 goto error;
263 }
264 dev_dbg(q->dev, "dma_alloc_coherent data is at addr %p (size %ld)\n",
265 mem->vaddr, mem->size);
266
267 /* Try to remap memory */
268
269 size = vma->vm_end - vma->vm_start;
270 size = (size < mem->size) ? size : mem->size;
271
272 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
273 retval = remap_pfn_range(vma, vma->vm_start,
274 mem->dma_handle >> PAGE_SHIFT,
275 size, vma->vm_page_prot);
276 if (retval) {
277 dev_err(q->dev, "mmap: remap failed with error %d. ", retval);
278 dma_free_coherent(q->dev, mem->size,
279 mem->vaddr, mem->dma_handle);
280 goto error;
281 }
282
283 vma->vm_ops = &videobuf_vm_ops;
284 vma->vm_flags |= VM_DONTEXPAND;
285 vma->vm_private_data = map;
286
287 dev_dbg(q->dev, "mmap %p: q=%p %08lx-%08lx (%lx) pgoff %08lx buf %d\n",
288 map, q, vma->vm_start, vma->vm_end,
289 (long int) q->bufs[first]->bsize,
290 vma->vm_pgoff, first);
291
292 videobuf_vm_open(vma);
293
294 return 0;
295
296error:
297 kfree(map);
298 return -ENOMEM;
299}
300
301static int __videobuf_copy_to_user(struct videobuf_queue *q,
302 char __user *data, size_t count,
303 int nonblocking)
304{
305 struct videobuf_dma_contig_memory *mem = q->read_buf->priv;
306 void *vaddr;
307
308 BUG_ON(!mem);
309 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
310 BUG_ON(!mem->vaddr);
311
312 /* copy to userspace */
313 if (count > q->read_buf->size - q->read_off)
314 count = q->read_buf->size - q->read_off;
315
316 vaddr = mem->vaddr;
317
318 if (copy_to_user(data, vaddr + q->read_off, count))
319 return -EFAULT;
320
321 return count;
322}
323
324static int __videobuf_copy_stream(struct videobuf_queue *q,
325 char __user *data, size_t count, size_t pos,
326 int vbihack, int nonblocking)
327{
328 unsigned int *fc;
329 struct videobuf_dma_contig_memory *mem = q->read_buf->priv;
330
331 BUG_ON(!mem);
332 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
333
334 if (vbihack) {
335 /* dirty, undocumented hack -- pass the frame counter
336 * within the last four bytes of each vbi data block.
337 * We need that one to maintain backward compatibility
338 * to all vbi decoding software out there ... */
339 fc = (unsigned int *)mem->vaddr;
340 fc += (q->read_buf->size >> 2) - 1;
341 *fc = q->read_buf->field_count >> 1;
342 dev_dbg(q->dev, "vbihack: %d\n", *fc);
343 }
344
345 /* copy stuff using the common method */
346 count = __videobuf_copy_to_user(q, data, count, nonblocking);
347
348 if ((count == -EFAULT) && (pos == 0))
349 return -EFAULT;
350
351 return count;
352}
353
354static struct videobuf_qtype_ops qops = {
355 .magic = MAGIC_QTYPE_OPS,
356
357 .alloc = __videobuf_alloc,
358 .iolock = __videobuf_iolock,
359 .sync = __videobuf_sync,
360 .mmap_free = __videobuf_mmap_free,
361 .mmap_mapper = __videobuf_mmap_mapper,
362 .video_copy_to_user = __videobuf_copy_to_user,
363 .copy_stream = __videobuf_copy_stream,
364 .vmalloc = __videobuf_to_vmalloc,
365};
366
367void videobuf_queue_dma_contig_init(struct videobuf_queue *q,
368 struct videobuf_queue_ops *ops,
369 struct device *dev,
370 spinlock_t *irqlock,
371 enum v4l2_buf_type type,
372 enum v4l2_field field,
373 unsigned int msize,
374 void *priv)
375{
376 videobuf_queue_core_init(q, ops, dev, irqlock, type, field, msize,
377 priv, &qops);
378}
379EXPORT_SYMBOL_GPL(videobuf_queue_dma_contig_init);
380
381dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf)
382{
383 struct videobuf_dma_contig_memory *mem = buf->priv;
384
385 BUG_ON(!mem);
386 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
387
388 return mem->dma_handle;
389}
390EXPORT_SYMBOL_GPL(videobuf_to_dma_contig);
391
392void videobuf_dma_contig_free(struct videobuf_queue *q,
393 struct videobuf_buffer *buf)
394{
395 struct videobuf_dma_contig_memory *mem = buf->priv;
396
397 /* mmapped memory can't be freed here, otherwise mmapped region
398 would be released, while still needed. In this case, the memory
399 release should happen inside videobuf_vm_close().
400 So, it should free memory only if the memory were allocated for
401 read() operation.
402 */
403 if ((buf->memory != V4L2_MEMORY_USERPTR) || !buf->baddr)
404 return;
405
406 if (!mem)
407 return;
408
409 MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
410
411 dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
412 mem->vaddr = NULL;
413}
414EXPORT_SYMBOL_GPL(videobuf_dma_contig_free);
415
416MODULE_DESCRIPTION("helper module to manage video4linux dma contig buffers");
417MODULE_AUTHOR("Magnus Damm");
418MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c
index 03a7b946bd54..bc6d5aba0fe6 100644
--- a/drivers/media/video/videobuf-dma-sg.c
+++ b/drivers/media/video/videobuf-dma-sg.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * helper functions for SG DMA video4linux capture buffers 2 * helper functions for SG DMA video4linux capture buffers
3 * 3 *
4 * The functions expect the hardware being able to scatter gatter 4 * The functions expect the hardware being able to scatter gather
5 * (i.e. the buffers are not linear in physical memory, but fragmented 5 * (i.e. the buffers are not linear in physical memory, but fragmented
6 * into PAGE_SIZE chunks). They also assume the driver does not need 6 * into PAGE_SIZE chunks). They also assume the driver does not need
7 * to touch the video data. 7 * to touch the video data.
@@ -80,17 +80,15 @@ struct scatterlist*
80videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) 80videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset)
81{ 81{
82 struct scatterlist *sglist; 82 struct scatterlist *sglist;
83 int i = 0; 83 int i;
84 84
85 if (NULL == pages[0]) 85 if (NULL == pages[0])
86 return NULL; 86 return NULL;
87 sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL); 87 sglist = kmalloc(nr_pages * sizeof(*sglist), GFP_KERNEL);
88 if (NULL == sglist) 88 if (NULL == sglist)
89 return NULL; 89 return NULL;
90 sg_init_table(sglist, nr_pages); 90 sg_init_table(sglist, nr_pages);
91 91
92 if (NULL == pages[0])
93 goto nopage;
94 if (PageHighMem(pages[0])) 92 if (PageHighMem(pages[0]))
95 /* DMA to highmem pages might not work */ 93 /* DMA to highmem pages might not work */
96 goto highmem; 94 goto highmem;
diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c
index 6e4d73ec6855..b56cffcbfd45 100644
--- a/drivers/media/video/videobuf-dvb.c
+++ b/drivers/media/video/videobuf-dvb.c
@@ -13,7 +13,6 @@
13 * (at your option) any later version. 13 * (at your option) any later version.
14 */ 14 */
15 15
16
17#include <linux/module.h> 16#include <linux/module.h>
18#include <linux/init.h> 17#include <linux/init.h>
19#include <linux/device.h> 18#include <linux/device.h>
@@ -257,4 +256,3 @@ EXPORT_SYMBOL(videobuf_dvb_unregister);
257 * compile-command: "make DVB=1" 256 * compile-command: "make DVB=1"
258 * End: 257 * End:
259 */ 258 */
260
diff --git a/drivers/media/video/videobuf-vmalloc.c b/drivers/media/video/videobuf-vmalloc.c
index c91e1d8e3802..a868b7ed75ff 100644
--- a/drivers/media/video/videobuf-vmalloc.c
+++ b/drivers/media/video/videobuf-vmalloc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * helper functions for vmalloc video4linux capture buffers 2 * helper functions for vmalloc video4linux capture buffers
3 * 3 *
4 * The functions expect the hardware being able to scatter gatter 4 * The functions expect the hardware being able to scatter gather
5 * (i.e. the buffers are not linear in physical memory, but fragmented 5 * (i.e. the buffers are not linear in physical memory, but fragmented
6 * into PAGE_SIZE chunks). They also assume the driver does not need 6 * into PAGE_SIZE chunks). They also assume the driver does not need
7 * to touch the video data. 7 * to touch the video data.
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 7649860a388d..6616e6570557 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -17,15 +17,19 @@
17 */ 17 */
18 18
19#define dbgarg(cmd, fmt, arg...) \ 19#define dbgarg(cmd, fmt, arg...) \
20 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { \ 20 do { \
21 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { \
21 printk(KERN_DEBUG "%s: ", vfd->name); \ 22 printk(KERN_DEBUG "%s: ", vfd->name); \
22 v4l_printk_ioctl(cmd); \ 23 v4l_printk_ioctl(cmd); \
23 printk(" " fmt, ## arg); \ 24 printk(" " fmt, ## arg); \
24 } 25 } \
26 } while (0)
25 27
26#define dbgarg2(fmt, arg...) \ 28#define dbgarg2(fmt, arg...) \
27 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \ 29 do { \
28 printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg); 30 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
31 printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\
32 } while (0)
29 33
30#include <linux/module.h> 34#include <linux/module.h>
31#include <linux/types.h> 35#include <linux/types.h>
@@ -138,7 +142,7 @@ EXPORT_SYMBOL(v4l2_video_std_construct);
138/* ----------------------------------------------------------------- */ 142/* ----------------------------------------------------------------- */
139/* some arrays for pretty-printing debug messages of enum types */ 143/* some arrays for pretty-printing debug messages of enum types */
140 144
141char *v4l2_field_names[] = { 145const char *v4l2_field_names[] = {
142 [V4L2_FIELD_ANY] = "any", 146 [V4L2_FIELD_ANY] = "any",
143 [V4L2_FIELD_NONE] = "none", 147 [V4L2_FIELD_NONE] = "none",
144 [V4L2_FIELD_TOP] = "top", 148 [V4L2_FIELD_TOP] = "top",
@@ -152,19 +156,19 @@ char *v4l2_field_names[] = {
152}; 156};
153EXPORT_SYMBOL(v4l2_field_names); 157EXPORT_SYMBOL(v4l2_field_names);
154 158
155char *v4l2_type_names[] = { 159const char *v4l2_type_names[] = {
156 [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", 160 [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "vid-cap",
157 [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", 161 [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "vid-overlay",
158 [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", 162 [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "vid-out",
159 [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", 163 [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
160 [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", 164 [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
161 [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap", 165 [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
162 [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out", 166 [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out",
163 [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "video-out-over", 167 [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
164}; 168};
165EXPORT_SYMBOL(v4l2_type_names); 169EXPORT_SYMBOL(v4l2_type_names);
166 170
167static char *v4l2_memory_names[] = { 171static const char *v4l2_memory_names[] = {
168 [V4L2_MEMORY_MMAP] = "mmap", 172 [V4L2_MEMORY_MMAP] = "mmap",
169 [V4L2_MEMORY_USERPTR] = "userptr", 173 [V4L2_MEMORY_USERPTR] = "userptr",
170 [V4L2_MEMORY_OVERLAY] = "overlay", 174 [V4L2_MEMORY_OVERLAY] = "overlay",
@@ -278,6 +282,7 @@ static const char *v4l2_ioctls[] = {
278 [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", 282 [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
279 283
280 [_IOC_NR(VIDIOC_G_CHIP_IDENT)] = "VIDIOC_G_CHIP_IDENT", 284 [_IOC_NR(VIDIOC_G_CHIP_IDENT)] = "VIDIOC_G_CHIP_IDENT",
285 [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
281#endif 286#endif
282}; 287};
283#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) 288#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
@@ -371,6 +376,14 @@ EXPORT_SYMBOL(v4l_printk_ioctl);
371 * sysfs stuff 376 * sysfs stuff
372 */ 377 */
373 378
379static ssize_t show_index(struct device *cd,
380 struct device_attribute *attr, char *buf)
381{
382 struct video_device *vfd = container_of(cd, struct video_device,
383 class_dev);
384 return sprintf(buf, "%i\n", vfd->index);
385}
386
374static ssize_t show_name(struct device *cd, 387static ssize_t show_name(struct device *cd,
375 struct device_attribute *attr, char *buf) 388 struct device_attribute *attr, char *buf)
376{ 389{
@@ -379,6 +392,12 @@ static ssize_t show_name(struct device *cd,
379 return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name); 392 return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name);
380} 393}
381 394
395static struct device_attribute video_device_attrs[] = {
396 __ATTR(name, S_IRUGO, show_name, NULL),
397 __ATTR(index, S_IRUGO, show_index, NULL),
398 __ATTR_NULL
399};
400
382struct video_device *video_device_alloc(void) 401struct video_device *video_device_alloc(void)
383{ 402{
384 struct video_device *vfd; 403 struct video_device *vfd;
@@ -407,11 +426,6 @@ static void video_release(struct device *cd)
407 vfd->release(vfd); 426 vfd->release(vfd);
408} 427}
409 428
410static struct device_attribute video_device_attrs[] = {
411 __ATTR(name, S_IRUGO, show_name, NULL),
412 __ATTR_NULL
413};
414
415static struct class video_class = { 429static struct class video_class = {
416 .name = VIDEO_NAME, 430 .name = VIDEO_NAME,
417 .dev_attrs = video_device_attrs, 431 .dev_attrs = video_device_attrs,
@@ -650,7 +664,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
650 p->field, p->sequence, 664 p->field, p->sequence,
651 prt_names(p->memory, v4l2_memory_names), 665 prt_names(p->memory, v4l2_memory_names),
652 p->m.userptr, p->length); 666 p->m.userptr, p->length);
653 dbgarg2 ("timecode= %02d:%02d:%02d type=%d, " 667 dbgarg2("timecode=%02d:%02d:%02d type=%d, "
654 "flags=0x%08d, frames=%d, userbits=0x%08x\n", 668 "flags=0x%08d, frames=%d, userbits=0x%08x\n",
655 tc->hours,tc->minutes,tc->seconds, 669 tc->hours,tc->minutes,tc->seconds,
656 tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits); 670 tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits);
@@ -659,7 +673,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
659static inline void dbgrect(struct video_device *vfd, char *s, 673static inline void dbgrect(struct video_device *vfd, char *s,
660 struct v4l2_rect *r) 674 struct v4l2_rect *r)
661{ 675{
662 dbgarg2 ("%sRect start at %dx%d, size= %dx%d\n", s, r->left, r->top, 676 dbgarg2("%sRect start at %dx%d, size=%dx%d\n", s, r->left, r->top,
663 r->width, r->height); 677 r->width, r->height);
664}; 678};
665 679
@@ -677,40 +691,85 @@ static inline void v4l_print_pix_fmt (struct video_device *vfd,
677 fmt->bytesperline, fmt->sizeimage, fmt->colorspace); 691 fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
678}; 692};
679 693
694static inline void v4l_print_ext_ctrls(unsigned int cmd,
695 struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals)
696{
697 __u32 i;
698
699 if (!(vfd->debug & V4L2_DEBUG_IOCTL_ARG))
700 return;
701 dbgarg(cmd, "");
702 printk(KERN_CONT "class=0x%x", c->ctrl_class);
703 for (i = 0; i < c->count; i++) {
704 if (show_vals)
705 printk(KERN_CONT " id/val=0x%x/0x%x",
706 c->controls[i].id, c->controls[i].value);
707 else
708 printk(KERN_CONT " id=0x%x", c->controls[i].id);
709 }
710 printk(KERN_CONT "\n");
711};
712
713static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
714{
715 __u32 i;
716
717 /* zero the reserved fields */
718 c->reserved[0] = c->reserved[1] = 0;
719 for (i = 0; i < c->count; i++) {
720 c->controls[i].reserved2[0] = 0;
721 c->controls[i].reserved2[1] = 0;
722 }
723 /* V4L2_CID_PRIVATE_BASE cannot be used as control class
724 when using extended controls.
725 Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
726 is it allowed for backwards compatibility.
727 */
728 if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
729 return 0;
730 /* Check that all controls are from the same control class. */
731 for (i = 0; i < c->count; i++) {
732 if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
733 c->error_idx = i;
734 return 0;
735 }
736 }
737 return 1;
738}
680 739
681static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type) 740static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type)
682{ 741{
683 switch (type) { 742 switch (type) {
684 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 743 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
685 if (vfd->vidioc_try_fmt_cap) 744 if (vfd->vidioc_try_fmt_vid_cap)
686 return (0); 745 return (0);
687 break; 746 break;
688 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 747 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
689 if (vfd->vidioc_try_fmt_overlay) 748 if (vfd->vidioc_try_fmt_vid_overlay)
690 return (0); 749 return (0);
691 break; 750 break;
692 case V4L2_BUF_TYPE_VBI_CAPTURE: 751 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
693 if (vfd->vidioc_try_fmt_vbi) 752 if (vfd->vidioc_try_fmt_vid_out)
694 return (0); 753 return (0);
695 break; 754 break;
696 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 755 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
697 if (vfd->vidioc_try_fmt_vbi_output) 756 if (vfd->vidioc_try_fmt_vid_out_overlay)
698 return (0); 757 return (0);
699 break; 758 break;
700 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 759 case V4L2_BUF_TYPE_VBI_CAPTURE:
701 if (vfd->vidioc_try_fmt_vbi_capture) 760 if (vfd->vidioc_try_fmt_vbi_cap)
702 return (0); 761 return (0);
703 break; 762 break;
704 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 763 case V4L2_BUF_TYPE_VBI_OUTPUT:
705 if (vfd->vidioc_try_fmt_video_output) 764 if (vfd->vidioc_try_fmt_vbi_out)
706 return (0); 765 return (0);
707 break; 766 break;
708 case V4L2_BUF_TYPE_VBI_OUTPUT: 767 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
709 if (vfd->vidioc_try_fmt_vbi_output) 768 if (vfd->vidioc_try_fmt_sliced_vbi_cap)
710 return (0); 769 return (0);
711 break; 770 break;
712 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 771 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
713 if (vfd->vidioc_try_fmt_output_overlay) 772 if (vfd->vidioc_try_fmt_sliced_vbi_out)
714 return (0); 773 return (0);
715 break; 774 break;
716 case V4L2_BUF_TYPE_PRIVATE: 775 case V4L2_BUF_TYPE_PRIVATE:
@@ -827,46 +886,37 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
827 886
828 switch (type) { 887 switch (type) {
829 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 888 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
830 if (vfd->vidioc_enum_fmt_cap) 889 if (vfd->vidioc_enum_fmt_vid_cap)
831 ret=vfd->vidioc_enum_fmt_cap(file, fh, f); 890 ret = vfd->vidioc_enum_fmt_vid_cap(file, fh, f);
832 break; 891 break;
833 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 892 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
834 if (vfd->vidioc_enum_fmt_overlay) 893 if (vfd->vidioc_enum_fmt_vid_overlay)
835 ret=vfd->vidioc_enum_fmt_overlay(file, fh, f); 894 ret = vfd->vidioc_enum_fmt_vid_overlay(file,
895 fh, f);
836 break; 896 break;
897#if 1
898 /* V4L2_BUF_TYPE_VBI_CAPTURE should not support VIDIOC_ENUM_FMT
899 * according to the spec. The bttv and saa7134 drivers support
900 * it though, so just warn that this is deprecated and will be
901 * removed in the near future. */
837 case V4L2_BUF_TYPE_VBI_CAPTURE: 902 case V4L2_BUF_TYPE_VBI_CAPTURE:
838 if (vfd->vidioc_enum_fmt_vbi) 903 if (vfd->vidioc_enum_fmt_vbi_cap) {
839 ret=vfd->vidioc_enum_fmt_vbi(file, fh, f); 904 printk(KERN_WARNING "vidioc_enum_fmt_vbi_cap will be removed in 2.6.28!\n");
840 break; 905 ret = vfd->vidioc_enum_fmt_vbi_cap(file, fh, f);
841 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 906 }
842 if (vfd->vidioc_enum_fmt_vbi_output)
843 ret=vfd->vidioc_enum_fmt_vbi_output(file,
844 fh, f);
845 break;
846 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
847 if (vfd->vidioc_enum_fmt_vbi_capture)
848 ret=vfd->vidioc_enum_fmt_vbi_capture(file,
849 fh, f);
850 break; 907 break;
908#endif
851 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 909 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
852 if (vfd->vidioc_enum_fmt_video_output) 910 if (vfd->vidioc_enum_fmt_vid_out)
853 ret=vfd->vidioc_enum_fmt_video_output(file, 911 ret = vfd->vidioc_enum_fmt_vid_out(file, fh, f);
854 fh, f);
855 break;
856 case V4L2_BUF_TYPE_VBI_OUTPUT:
857 if (vfd->vidioc_enum_fmt_vbi_output)
858 ret=vfd->vidioc_enum_fmt_vbi_output(file,
859 fh, f);
860 break;
861 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
862 if (vfd->vidioc_enum_fmt_output_overlay)
863 ret=vfd->vidioc_enum_fmt_output_overlay(file, fh, f);
864 break; 912 break;
865 case V4L2_BUF_TYPE_PRIVATE: 913 case V4L2_BUF_TYPE_PRIVATE:
866 if (vfd->vidioc_enum_fmt_type_private) 914 if (vfd->vidioc_enum_fmt_type_private)
867 ret=vfd->vidioc_enum_fmt_type_private(file, 915 ret = vfd->vidioc_enum_fmt_type_private(file,
868 fh, f); 916 fh, f);
869 break; 917 break;
918 default:
919 break;
870 } 920 }
871 if (!ret) 921 if (!ret)
872 dbgarg (cmd, "index=%d, type=%d, flags=%d, " 922 dbgarg (cmd, "index=%d, type=%d, flags=%d, "
@@ -882,54 +932,56 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
882 case VIDIOC_G_FMT: 932 case VIDIOC_G_FMT:
883 { 933 {
884 struct v4l2_format *f = (struct v4l2_format *)arg; 934 struct v4l2_format *f = (struct v4l2_format *)arg;
885 enum v4l2_buf_type type=f->type;
886 935
887 memset(&f->fmt.pix,0,sizeof(f->fmt.pix)); 936 memset(f->fmt.raw_data, 0, sizeof(f->fmt.raw_data));
888 f->type=type;
889 937
890 /* FIXME: Should be one dump per type */ 938 /* FIXME: Should be one dump per type */
891 dbgarg (cmd, "type=%s\n", prt_names(type, 939 dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
892 v4l2_type_names));
893 940
894 switch (type) { 941 switch (f->type) {
895 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 942 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
896 if (vfd->vidioc_g_fmt_cap) 943 if (vfd->vidioc_g_fmt_vid_cap)
897 ret=vfd->vidioc_g_fmt_cap(file, fh, f); 944 ret = vfd->vidioc_g_fmt_vid_cap(file, fh, f);
898 if (!ret) 945 if (!ret)
899 v4l_print_pix_fmt(vfd,&f->fmt.pix); 946 v4l_print_pix_fmt(vfd, &f->fmt.pix);
900 break; 947 break;
901 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 948 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
902 if (vfd->vidioc_g_fmt_overlay) 949 if (vfd->vidioc_g_fmt_vid_overlay)
903 ret=vfd->vidioc_g_fmt_overlay(file, fh, f); 950 ret = vfd->vidioc_g_fmt_vid_overlay(file,
904 break; 951 fh, f);
905 case V4L2_BUF_TYPE_VBI_CAPTURE:
906 if (vfd->vidioc_g_fmt_vbi)
907 ret=vfd->vidioc_g_fmt_vbi(file, fh, f);
908 break;
909 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
910 if (vfd->vidioc_g_fmt_vbi_output)
911 ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
912 break;
913 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
914 if (vfd->vidioc_g_fmt_vbi_capture)
915 ret=vfd->vidioc_g_fmt_vbi_capture(file, fh, f);
916 break; 952 break;
917 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 953 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
918 if (vfd->vidioc_g_fmt_video_output) 954 if (vfd->vidioc_g_fmt_vid_out)
919 ret=vfd->vidioc_g_fmt_video_output(file, 955 ret = vfd->vidioc_g_fmt_vid_out(file, fh, f);
920 fh, f); 956 if (!ret)
957 v4l_print_pix_fmt(vfd, &f->fmt.pix);
921 break; 958 break;
922 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 959 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
923 if (vfd->vidioc_g_fmt_output_overlay) 960 if (vfd->vidioc_g_fmt_vid_out_overlay)
924 ret=vfd->vidioc_g_fmt_output_overlay(file, fh, f); 961 ret = vfd->vidioc_g_fmt_vid_out_overlay(file,
962 fh, f);
963 break;
964 case V4L2_BUF_TYPE_VBI_CAPTURE:
965 if (vfd->vidioc_g_fmt_vbi_cap)
966 ret = vfd->vidioc_g_fmt_vbi_cap(file, fh, f);
925 break; 967 break;
926 case V4L2_BUF_TYPE_VBI_OUTPUT: 968 case V4L2_BUF_TYPE_VBI_OUTPUT:
927 if (vfd->vidioc_g_fmt_vbi_output) 969 if (vfd->vidioc_g_fmt_vbi_out)
928 ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f); 970 ret = vfd->vidioc_g_fmt_vbi_out(file, fh, f);
971 break;
972 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
973 if (vfd->vidioc_g_fmt_sliced_vbi_cap)
974 ret = vfd->vidioc_g_fmt_sliced_vbi_cap(file,
975 fh, f);
976 break;
977 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
978 if (vfd->vidioc_g_fmt_sliced_vbi_out)
979 ret = vfd->vidioc_g_fmt_sliced_vbi_out(file,
980 fh, f);
929 break; 981 break;
930 case V4L2_BUF_TYPE_PRIVATE: 982 case V4L2_BUF_TYPE_PRIVATE:
931 if (vfd->vidioc_g_fmt_type_private) 983 if (vfd->vidioc_g_fmt_type_private)
932 ret=vfd->vidioc_g_fmt_type_private(file, 984 ret = vfd->vidioc_g_fmt_type_private(file,
933 fh, f); 985 fh, f);
934 break; 986 break;
935 } 987 }
@@ -941,48 +993,50 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
941 struct v4l2_format *f = (struct v4l2_format *)arg; 993 struct v4l2_format *f = (struct v4l2_format *)arg;
942 994
943 /* FIXME: Should be one dump per type */ 995 /* FIXME: Should be one dump per type */
944 dbgarg (cmd, "type=%s\n", prt_names(f->type, 996 dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
945 v4l2_type_names));
946 997
947 switch (f->type) { 998 switch (f->type) {
948 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 999 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
949 v4l_print_pix_fmt(vfd,&f->fmt.pix); 1000 v4l_print_pix_fmt(vfd, &f->fmt.pix);
950 if (vfd->vidioc_s_fmt_cap) 1001 if (vfd->vidioc_s_fmt_vid_cap)
951 ret=vfd->vidioc_s_fmt_cap(file, fh, f); 1002 ret = vfd->vidioc_s_fmt_vid_cap(file, fh, f);
952 break; 1003 break;
953 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 1004 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
954 if (vfd->vidioc_s_fmt_overlay) 1005 if (vfd->vidioc_s_fmt_vid_overlay)
955 ret=vfd->vidioc_s_fmt_overlay(file, fh, f); 1006 ret = vfd->vidioc_s_fmt_vid_overlay(file,
956 break; 1007 fh, f);
957 case V4L2_BUF_TYPE_VBI_CAPTURE:
958 if (vfd->vidioc_s_fmt_vbi)
959 ret=vfd->vidioc_s_fmt_vbi(file, fh, f);
960 break;
961 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
962 if (vfd->vidioc_s_fmt_vbi_output)
963 ret=vfd->vidioc_s_fmt_vbi_output(file, fh, f);
964 break;
965 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
966 if (vfd->vidioc_s_fmt_vbi_capture)
967 ret=vfd->vidioc_s_fmt_vbi_capture(file, fh, f);
968 break; 1008 break;
969 case V4L2_BUF_TYPE_VIDEO_OUTPUT: 1009 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
970 if (vfd->vidioc_s_fmt_video_output) 1010 v4l_print_pix_fmt(vfd, &f->fmt.pix);
971 ret=vfd->vidioc_s_fmt_video_output(file, 1011 if (vfd->vidioc_s_fmt_vid_out)
972 fh, f); 1012 ret = vfd->vidioc_s_fmt_vid_out(file, fh, f);
973 break; 1013 break;
974 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 1014 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
975 if (vfd->vidioc_s_fmt_output_overlay) 1015 if (vfd->vidioc_s_fmt_vid_out_overlay)
976 ret=vfd->vidioc_s_fmt_output_overlay(file, fh, f); 1016 ret = vfd->vidioc_s_fmt_vid_out_overlay(file,
1017 fh, f);
1018 break;
1019 case V4L2_BUF_TYPE_VBI_CAPTURE:
1020 if (vfd->vidioc_s_fmt_vbi_cap)
1021 ret = vfd->vidioc_s_fmt_vbi_cap(file, fh, f);
977 break; 1022 break;
978 case V4L2_BUF_TYPE_VBI_OUTPUT: 1023 case V4L2_BUF_TYPE_VBI_OUTPUT:
979 if (vfd->vidioc_s_fmt_vbi_output) 1024 if (vfd->vidioc_s_fmt_vbi_out)
980 ret=vfd->vidioc_s_fmt_vbi_output(file, 1025 ret = vfd->vidioc_s_fmt_vbi_out(file, fh, f);
981 fh, f); 1026 break;
1027 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
1028 if (vfd->vidioc_s_fmt_sliced_vbi_cap)
1029 ret = vfd->vidioc_s_fmt_sliced_vbi_cap(file,
1030 fh, f);
1031 break;
1032 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
1033 if (vfd->vidioc_s_fmt_sliced_vbi_out)
1034 ret = vfd->vidioc_s_fmt_sliced_vbi_out(file,
1035 fh, f);
982 break; 1036 break;
983 case V4L2_BUF_TYPE_PRIVATE: 1037 case V4L2_BUF_TYPE_PRIVATE:
984 if (vfd->vidioc_s_fmt_type_private) 1038 if (vfd->vidioc_s_fmt_type_private)
985 ret=vfd->vidioc_s_fmt_type_private(file, 1039 ret = vfd->vidioc_s_fmt_type_private(file,
986 fh, f); 1040 fh, f);
987 break; 1041 break;
988 } 1042 }
@@ -997,46 +1051,48 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
997 v4l2_type_names)); 1051 v4l2_type_names));
998 switch (f->type) { 1052 switch (f->type) {
999 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1053 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1000 if (vfd->vidioc_try_fmt_cap) 1054 if (vfd->vidioc_try_fmt_vid_cap)
1001 ret=vfd->vidioc_try_fmt_cap(file, fh, f); 1055 ret = vfd->vidioc_try_fmt_vid_cap(file, fh, f);
1002 if (!ret) 1056 if (!ret)
1003 v4l_print_pix_fmt(vfd,&f->fmt.pix); 1057 v4l_print_pix_fmt(vfd, &f->fmt.pix);
1004 break; 1058 break;
1005 case V4L2_BUF_TYPE_VIDEO_OVERLAY: 1059 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
1006 if (vfd->vidioc_try_fmt_overlay) 1060 if (vfd->vidioc_try_fmt_vid_overlay)
1007 ret=vfd->vidioc_try_fmt_overlay(file, fh, f); 1061 ret = vfd->vidioc_try_fmt_vid_overlay(file,
1062 fh, f);
1063 break;
1064 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1065 if (vfd->vidioc_try_fmt_vid_out)
1066 ret = vfd->vidioc_try_fmt_vid_out(file, fh, f);
1067 if (!ret)
1068 v4l_print_pix_fmt(vfd, &f->fmt.pix);
1069 break;
1070 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
1071 if (vfd->vidioc_try_fmt_vid_out_overlay)
1072 ret = vfd->vidioc_try_fmt_vid_out_overlay(file,
1073 fh, f);
1008 break; 1074 break;
1009 case V4L2_BUF_TYPE_VBI_CAPTURE: 1075 case V4L2_BUF_TYPE_VBI_CAPTURE:
1010 if (vfd->vidioc_try_fmt_vbi) 1076 if (vfd->vidioc_try_fmt_vbi_cap)
1011 ret=vfd->vidioc_try_fmt_vbi(file, fh, f); 1077 ret = vfd->vidioc_try_fmt_vbi_cap(file, fh, f);
1012 break; 1078 break;
1013 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 1079 case V4L2_BUF_TYPE_VBI_OUTPUT:
1014 if (vfd->vidioc_try_fmt_vbi_output) 1080 if (vfd->vidioc_try_fmt_vbi_out)
1015 ret=vfd->vidioc_try_fmt_vbi_output(file, 1081 ret = vfd->vidioc_try_fmt_vbi_out(file, fh, f);
1016 fh, f);
1017 break; 1082 break;
1018 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 1083 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
1019 if (vfd->vidioc_try_fmt_vbi_capture) 1084 if (vfd->vidioc_try_fmt_sliced_vbi_cap)
1020 ret=vfd->vidioc_try_fmt_vbi_capture(file, 1085 ret = vfd->vidioc_try_fmt_sliced_vbi_cap(file,
1021 fh, f);
1022 break;
1023 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1024 if (vfd->vidioc_try_fmt_video_output)
1025 ret=vfd->vidioc_try_fmt_video_output(file,
1026 fh, f); 1086 fh, f);
1027 break; 1087 break;
1028 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 1088 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
1029 if (vfd->vidioc_try_fmt_output_overlay) 1089 if (vfd->vidioc_try_fmt_sliced_vbi_out)
1030 ret=vfd->vidioc_try_fmt_output_overlay(file, fh, f); 1090 ret = vfd->vidioc_try_fmt_sliced_vbi_out(file,
1031 break;
1032 case V4L2_BUF_TYPE_VBI_OUTPUT:
1033 if (vfd->vidioc_try_fmt_vbi_output)
1034 ret=vfd->vidioc_try_fmt_vbi_output(file,
1035 fh, f); 1091 fh, f);
1036 break; 1092 break;
1037 case V4L2_BUF_TYPE_PRIVATE: 1093 case V4L2_BUF_TYPE_PRIVATE:
1038 if (vfd->vidioc_try_fmt_type_private) 1094 if (vfd->vidioc_try_fmt_type_private)
1039 ret=vfd->vidioc_try_fmt_type_private(file, 1095 ret = vfd->vidioc_try_fmt_type_private(file,
1040 fh, f); 1096 fh, f);
1041 break; 1097 break;
1042 } 1098 }
@@ -1120,29 +1176,29 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1120 } 1176 }
1121 case VIDIOC_G_FBUF: 1177 case VIDIOC_G_FBUF:
1122 { 1178 {
1123 struct v4l2_framebuffer *p=arg; 1179 struct v4l2_framebuffer *p = arg;
1180
1124 if (!vfd->vidioc_g_fbuf) 1181 if (!vfd->vidioc_g_fbuf)
1125 break; 1182 break;
1126 ret=vfd->vidioc_g_fbuf(file, fh, arg); 1183 ret = vfd->vidioc_g_fbuf(file, fh, arg);
1127 if (!ret) { 1184 if (!ret) {
1128 dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n", 1185 dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
1129 p->capability,p->flags, 1186 p->capability, p->flags,
1130 (unsigned long)p->base); 1187 (unsigned long)p->base);
1131 v4l_print_pix_fmt (vfd, &p->fmt); 1188 v4l_print_pix_fmt(vfd, &p->fmt);
1132 } 1189 }
1133 break; 1190 break;
1134 } 1191 }
1135 case VIDIOC_S_FBUF: 1192 case VIDIOC_S_FBUF:
1136 { 1193 {
1137 struct v4l2_framebuffer *p=arg; 1194 struct v4l2_framebuffer *p = arg;
1195
1138 if (!vfd->vidioc_s_fbuf) 1196 if (!vfd->vidioc_s_fbuf)
1139 break; 1197 break;
1140 1198 dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
1141 dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n", 1199 p->capability, p->flags, (unsigned long)p->base);
1142 p->capability,p->flags,(unsigned long)p->base); 1200 v4l_print_pix_fmt(vfd, &p->fmt);
1143 v4l_print_pix_fmt (vfd, &p->fmt); 1201 ret = vfd->vidioc_s_fbuf(file, fh, arg);
1144 ret=vfd->vidioc_s_fbuf(file, fh, arg);
1145
1146 break; 1202 break;
1147 } 1203 }
1148 case VIDIOC_STREAMON: 1204 case VIDIOC_STREAMON:
@@ -1194,7 +1250,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1194 v4l2_video_std_construct(p, curr_id, descr); 1250 v4l2_video_std_construct(p, curr_id, descr);
1195 p->index = index; 1251 p->index = index;
1196 1252
1197 dbgarg(cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " 1253 dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, "
1198 "framelines=%d\n", p->index, 1254 "framelines=%d\n", p->index,
1199 (unsigned long long)p->id, p->name, 1255 (unsigned long long)p->id, p->name,
1200 p->frameperiod.numerator, 1256 p->frameperiod.numerator,
@@ -1208,18 +1264,22 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1208 { 1264 {
1209 v4l2_std_id *id = arg; 1265 v4l2_std_id *id = arg;
1210 1266
1211 *id = vfd->current_norm; 1267 ret = 0;
1212 1268 /* Calls the specific handler */
1213 dbgarg (cmd, "value=%08Lx\n", (long long unsigned) *id); 1269 if (vfd->vidioc_g_std)
1270 ret = vfd->vidioc_g_std(file, fh, id);
1271 else
1272 *id = vfd->current_norm;
1214 1273
1215 ret=0; 1274 if (!ret)
1275 dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
1216 break; 1276 break;
1217 } 1277 }
1218 case VIDIOC_S_STD: 1278 case VIDIOC_S_STD:
1219 { 1279 {
1220 v4l2_std_id *id = arg,norm; 1280 v4l2_std_id *id = arg,norm;
1221 1281
1222 dbgarg (cmd, "value=%08Lx\n", (long long unsigned) *id); 1282 dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
1223 1283
1224 norm = (*id) & vfd->tvnorms; 1284 norm = (*id) & vfd->tvnorms;
1225 if ( vfd->tvnorms && !norm) /* Check if std is supported */ 1285 if ( vfd->tvnorms && !norm) /* Check if std is supported */
@@ -1295,6 +1355,25 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1295 } 1355 }
1296 1356
1297 /* ------ output switching ---------- */ 1357 /* ------ output switching ---------- */
1358 case VIDIOC_ENUMOUTPUT:
1359 {
1360 struct v4l2_output *p = arg;
1361 int i = p->index;
1362
1363 if (!vfd->vidioc_enum_output)
1364 break;
1365 memset(p, 0, sizeof(*p));
1366 p->index = i;
1367
1368 ret = vfd->vidioc_enum_output(file, fh, p);
1369 if (!ret)
1370 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1371 "audioset=0x%x, "
1372 "modulator=%d, std=0x%08Lx\n",
1373 p->index, p->name, p->type, p->audioset,
1374 p->modulator, (unsigned long long)p->std);
1375 break;
1376 }
1298 case VIDIOC_G_OUTPUT: 1377 case VIDIOC_G_OUTPUT:
1299 { 1378 {
1300 unsigned int *i = arg; 1379 unsigned int *i = arg;
@@ -1320,132 +1399,172 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1320 /* --- controls ---------------------------------------------- */ 1399 /* --- controls ---------------------------------------------- */
1321 case VIDIOC_QUERYCTRL: 1400 case VIDIOC_QUERYCTRL:
1322 { 1401 {
1323 struct v4l2_queryctrl *p=arg; 1402 struct v4l2_queryctrl *p = arg;
1324 1403
1325 if (!vfd->vidioc_queryctrl) 1404 if (!vfd->vidioc_queryctrl)
1326 break; 1405 break;
1327 ret=vfd->vidioc_queryctrl(file, fh, p); 1406 ret = vfd->vidioc_queryctrl(file, fh, p);
1328
1329 if (!ret) 1407 if (!ret)
1330 dbgarg (cmd, "id=%d, type=%d, name=%s, " 1408 dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, "
1331 "min/max=%d/%d," 1409 "step=%d, default=%d, flags=0x%08x\n",
1332 " step=%d, default=%d, flags=0x%08x\n", 1410 p->id, p->type, p->name,
1333 p->id,p->type,p->name,p->minimum, 1411 p->minimum, p->maximum,
1334 p->maximum,p->step,p->default_value, 1412 p->step, p->default_value, p->flags);
1335 p->flags); 1413 else
1414 dbgarg(cmd, "id=0x%x\n", p->id);
1336 break; 1415 break;
1337 } 1416 }
1338 case VIDIOC_G_CTRL: 1417 case VIDIOC_G_CTRL:
1339 { 1418 {
1340 struct v4l2_control *p = arg; 1419 struct v4l2_control *p = arg;
1341 1420
1342 if (!vfd->vidioc_g_ctrl) 1421 if (vfd->vidioc_g_ctrl)
1422 ret = vfd->vidioc_g_ctrl(file, fh, p);
1423 else if (vfd->vidioc_g_ext_ctrls) {
1424 struct v4l2_ext_controls ctrls;
1425 struct v4l2_ext_control ctrl;
1426
1427 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
1428 ctrls.count = 1;
1429 ctrls.controls = &ctrl;
1430 ctrl.id = p->id;
1431 ctrl.value = p->value;
1432 if (check_ext_ctrls(&ctrls, 1)) {
1433 ret = vfd->vidioc_g_ext_ctrls(file, fh, &ctrls);
1434 if (ret == 0)
1435 p->value = ctrl.value;
1436 }
1437 } else
1343 break; 1438 break;
1344 dbgarg(cmd, "Enum for index=%d\n", p->id);
1345
1346 ret=vfd->vidioc_g_ctrl(file, fh, p);
1347 if (!ret) 1439 if (!ret)
1348 dbgarg2 ( "id=%d, value=%d\n", p->id, p->value); 1440 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1441 else
1442 dbgarg(cmd, "id=0x%x\n", p->id);
1349 break; 1443 break;
1350 } 1444 }
1351 case VIDIOC_S_CTRL: 1445 case VIDIOC_S_CTRL:
1352 { 1446 {
1353 struct v4l2_control *p = arg; 1447 struct v4l2_control *p = arg;
1448 struct v4l2_ext_controls ctrls;
1449 struct v4l2_ext_control ctrl;
1450
1451 if (!vfd->vidioc_s_ctrl && !vfd->vidioc_s_ext_ctrls)
1452 break;
1354 1453
1355 if (!vfd->vidioc_s_ctrl) 1454 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1455
1456 if (vfd->vidioc_s_ctrl) {
1457 ret = vfd->vidioc_s_ctrl(file, fh, p);
1458 break;
1459 }
1460 if (!vfd->vidioc_s_ext_ctrls)
1356 break; 1461 break;
1357 dbgarg (cmd, "id=%d, value=%d\n", p->id, p->value);
1358 1462
1359 ret=vfd->vidioc_s_ctrl(file, fh, p); 1463 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
1464 ctrls.count = 1;
1465 ctrls.controls = &ctrl;
1466 ctrl.id = p->id;
1467 ctrl.value = p->value;
1468 if (check_ext_ctrls(&ctrls, 1))
1469 ret = vfd->vidioc_s_ext_ctrls(file, fh, &ctrls);
1360 break; 1470 break;
1361 } 1471 }
1362 case VIDIOC_G_EXT_CTRLS: 1472 case VIDIOC_G_EXT_CTRLS:
1363 { 1473 {
1364 struct v4l2_ext_controls *p = arg; 1474 struct v4l2_ext_controls *p = arg;
1365 1475
1366 if (vfd->vidioc_g_ext_ctrls) { 1476 p->error_idx = p->count;
1367 dbgarg(cmd, "count=%d\n", p->count); 1477 if (!vfd->vidioc_g_ext_ctrls)
1368 1478 break;
1369 ret=vfd->vidioc_g_ext_ctrls(file, fh, p); 1479 if (check_ext_ctrls(p, 0))
1370 } 1480 ret = vfd->vidioc_g_ext_ctrls(file, fh, p);
1481 v4l_print_ext_ctrls(cmd, vfd, p, !ret);
1371 break; 1482 break;
1372 } 1483 }
1373 case VIDIOC_S_EXT_CTRLS: 1484 case VIDIOC_S_EXT_CTRLS:
1374 { 1485 {
1375 struct v4l2_ext_controls *p = arg; 1486 struct v4l2_ext_controls *p = arg;
1376 1487
1377 if (vfd->vidioc_s_ext_ctrls) { 1488 p->error_idx = p->count;
1378 dbgarg(cmd, "count=%d\n", p->count); 1489 if (!vfd->vidioc_s_ext_ctrls)
1379 1490 break;
1380 ret=vfd->vidioc_s_ext_ctrls(file, fh, p); 1491 v4l_print_ext_ctrls(cmd, vfd, p, 1);
1381 } 1492 if (check_ext_ctrls(p, 0))
1493 ret = vfd->vidioc_s_ext_ctrls(file, fh, p);
1382 break; 1494 break;
1383 } 1495 }
1384 case VIDIOC_TRY_EXT_CTRLS: 1496 case VIDIOC_TRY_EXT_CTRLS:
1385 { 1497 {
1386 struct v4l2_ext_controls *p = arg; 1498 struct v4l2_ext_controls *p = arg;
1387 1499
1388 if (vfd->vidioc_try_ext_ctrls) { 1500 p->error_idx = p->count;
1389 dbgarg(cmd, "count=%d\n", p->count); 1501 if (!vfd->vidioc_try_ext_ctrls)
1390 1502 break;
1391 ret=vfd->vidioc_try_ext_ctrls(file, fh, p); 1503 v4l_print_ext_ctrls(cmd, vfd, p, 1);
1392 } 1504 if (check_ext_ctrls(p, 0))
1505 ret = vfd->vidioc_try_ext_ctrls(file, fh, p);
1393 break; 1506 break;
1394 } 1507 }
1395 case VIDIOC_QUERYMENU: 1508 case VIDIOC_QUERYMENU:
1396 { 1509 {
1397 struct v4l2_querymenu *p=arg; 1510 struct v4l2_querymenu *p = arg;
1511
1398 if (!vfd->vidioc_querymenu) 1512 if (!vfd->vidioc_querymenu)
1399 break; 1513 break;
1400 ret=vfd->vidioc_querymenu(file, fh, p); 1514 ret = vfd->vidioc_querymenu(file, fh, p);
1401 if (!ret) 1515 if (!ret)
1402 dbgarg (cmd, "id=%d, index=%d, name=%s\n", 1516 dbgarg(cmd, "id=0x%x, index=%d, name=%s\n",
1403 p->id,p->index,p->name); 1517 p->id, p->index, p->name);
1518 else
1519 dbgarg(cmd, "id=0x%x, index=%d\n",
1520 p->id, p->index);
1404 break; 1521 break;
1405 } 1522 }
1406 /* --- audio ---------------------------------------------- */ 1523 /* --- audio ---------------------------------------------- */
1407 case VIDIOC_ENUMAUDIO: 1524 case VIDIOC_ENUMAUDIO:
1408 { 1525 {
1409 struct v4l2_audio *p=arg; 1526 struct v4l2_audio *p = arg;
1410 1527
1411 if (!vfd->vidioc_enumaudio) 1528 if (!vfd->vidioc_enumaudio)
1412 break; 1529 break;
1413 dbgarg(cmd, "Enum for index=%d\n", p->index); 1530 ret = vfd->vidioc_enumaudio(file, fh, p);
1414 ret=vfd->vidioc_enumaudio(file, fh, p);
1415 if (!ret) 1531 if (!ret)
1416 dbgarg2("index=%d, name=%s, capability=%d, " 1532 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1417 "mode=%d\n",p->index,p->name, 1533 "mode=0x%x\n", p->index, p->name,
1418 p->capability, p->mode); 1534 p->capability, p->mode);
1535 else
1536 dbgarg(cmd, "index=%d\n", p->index);
1419 break; 1537 break;
1420 } 1538 }
1421 case VIDIOC_G_AUDIO: 1539 case VIDIOC_G_AUDIO:
1422 { 1540 {
1423 struct v4l2_audio *p=arg; 1541 struct v4l2_audio *p = arg;
1424 __u32 index=p->index; 1542 __u32 index = p->index;
1425 1543
1426 if (!vfd->vidioc_g_audio) 1544 if (!vfd->vidioc_g_audio)
1427 break; 1545 break;
1428 1546
1429 memset(p,0,sizeof(*p)); 1547 memset(p, 0, sizeof(*p));
1430 p->index=index; 1548 p->index = index;
1431 dbgarg(cmd, "Get for index=%d\n", p->index); 1549 ret = vfd->vidioc_g_audio(file, fh, p);
1432 ret=vfd->vidioc_g_audio(file, fh, p);
1433 if (!ret) 1550 if (!ret)
1434 dbgarg2("index=%d, name=%s, capability=%d, " 1551 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1435 "mode=%d\n",p->index, 1552 "mode=0x%x\n", p->index,
1436 p->name,p->capability, p->mode); 1553 p->name, p->capability, p->mode);
1554 else
1555 dbgarg(cmd, "index=%d\n", p->index);
1437 break; 1556 break;
1438 } 1557 }
1439 case VIDIOC_S_AUDIO: 1558 case VIDIOC_S_AUDIO:
1440 { 1559 {
1441 struct v4l2_audio *p=arg; 1560 struct v4l2_audio *p = arg;
1442 1561
1443 if (!vfd->vidioc_s_audio) 1562 if (!vfd->vidioc_s_audio)
1444 break; 1563 break;
1445 dbgarg(cmd, "index=%d, name=%s, capability=%d, " 1564 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1446 "mode=%d\n", p->index, p->name, 1565 "mode=0x%x\n", p->index, p->name,
1447 p->capability, p->mode); 1566 p->capability, p->mode);
1448 ret=vfd->vidioc_s_audio(file, fh, p); 1567 ret = vfd->vidioc_s_audio(file, fh, p);
1449 break; 1568 break;
1450 } 1569 }
1451 case VIDIOC_ENUMAUDOUT: 1570 case VIDIOC_ENUMAUDOUT:
@@ -1521,9 +1640,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1521 struct v4l2_crop *p=arg; 1640 struct v4l2_crop *p=arg;
1522 if (!vfd->vidioc_g_crop) 1641 if (!vfd->vidioc_g_crop)
1523 break; 1642 break;
1643 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
1524 ret=vfd->vidioc_g_crop(file, fh, p); 1644 ret=vfd->vidioc_g_crop(file, fh, p);
1525 if (!ret) { 1645 if (!ret) {
1526 dbgarg(cmd, "type=%d\n", p->type);
1527 dbgrect(vfd, "", &p->c); 1646 dbgrect(vfd, "", &p->c);
1528 } 1647 }
1529 break; 1648 break;
@@ -1533,21 +1652,24 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1533 struct v4l2_crop *p=arg; 1652 struct v4l2_crop *p=arg;
1534 if (!vfd->vidioc_s_crop) 1653 if (!vfd->vidioc_s_crop)
1535 break; 1654 break;
1536 dbgarg(cmd, "type=%d\n", p->type); 1655 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
1537 dbgrect(vfd, "", &p->c); 1656 dbgrect(vfd, "", &p->c);
1538 ret=vfd->vidioc_s_crop(file, fh, p); 1657 ret=vfd->vidioc_s_crop(file, fh, p);
1539 break; 1658 break;
1540 } 1659 }
1541 case VIDIOC_CROPCAP: 1660 case VIDIOC_CROPCAP:
1542 { 1661 {
1543 struct v4l2_cropcap *p=arg; 1662 struct v4l2_cropcap *p = arg;
1663
1544 /*FIXME: Should also show v4l2_fract pixelaspect */ 1664 /*FIXME: Should also show v4l2_fract pixelaspect */
1545 if (!vfd->vidioc_cropcap) 1665 if (!vfd->vidioc_cropcap)
1546 break; 1666 break;
1547 dbgarg(cmd, "type=%d\n", p->type); 1667 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
1548 dbgrect(vfd, "bounds ", &p->bounds); 1668 ret = vfd->vidioc_cropcap(file, fh, p);
1549 dbgrect(vfd, "defrect ", &p->defrect); 1669 if (!ret) {
1550 ret=vfd->vidioc_cropcap(file, fh, p); 1670 dbgrect(vfd, "bounds ", &p->bounds);
1671 dbgrect(vfd, "defrect ", &p->defrect);
1672 }
1551 break; 1673 break;
1552 } 1674 }
1553 case VIDIOC_G_JPEGCOMP: 1675 case VIDIOC_G_JPEGCOMP:
@@ -1590,26 +1712,26 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1590 } 1712 }
1591 case VIDIOC_ENCODER_CMD: 1713 case VIDIOC_ENCODER_CMD:
1592 { 1714 {
1593 struct v4l2_encoder_cmd *p=arg; 1715 struct v4l2_encoder_cmd *p = arg;
1594 1716
1595 if (!vfd->vidioc_encoder_cmd) 1717 if (!vfd->vidioc_encoder_cmd)
1596 break; 1718 break;
1597 ret=vfd->vidioc_encoder_cmd(file, fh, p); 1719 memset(&p->raw, 0, sizeof(p->raw));
1720 ret = vfd->vidioc_encoder_cmd(file, fh, p);
1598 if (!ret) 1721 if (!ret)
1599 dbgarg (cmd, "cmd=%d, flags=%d\n", 1722 dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
1600 p->cmd,p->flags);
1601 break; 1723 break;
1602 } 1724 }
1603 case VIDIOC_TRY_ENCODER_CMD: 1725 case VIDIOC_TRY_ENCODER_CMD:
1604 { 1726 {
1605 struct v4l2_encoder_cmd *p=arg; 1727 struct v4l2_encoder_cmd *p = arg;
1606 1728
1607 if (!vfd->vidioc_try_encoder_cmd) 1729 if (!vfd->vidioc_try_encoder_cmd)
1608 break; 1730 break;
1609 ret=vfd->vidioc_try_encoder_cmd(file, fh, p); 1731 memset(&p->raw, 0, sizeof(p->raw));
1732 ret = vfd->vidioc_try_encoder_cmd(file, fh, p);
1610 if (!ret) 1733 if (!ret)
1611 dbgarg (cmd, "cmd=%d, flags=%d\n", 1734 dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
1612 p->cmd,p->flags);
1613 break; 1735 break;
1614 } 1736 }
1615 case VIDIOC_G_PARM: 1737 case VIDIOC_G_PARM:
@@ -1649,54 +1771,57 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1649 } 1771 }
1650 case VIDIOC_G_TUNER: 1772 case VIDIOC_G_TUNER:
1651 { 1773 {
1652 struct v4l2_tuner *p=arg; 1774 struct v4l2_tuner *p = arg;
1653 __u32 index=p->index; 1775 __u32 index = p->index;
1654 1776
1655 if (!vfd->vidioc_g_tuner) 1777 if (!vfd->vidioc_g_tuner)
1656 break; 1778 break;
1657 1779
1658 memset(p,0,sizeof(*p)); 1780 memset(p, 0, sizeof(*p));
1659 p->index=index; 1781 p->index = index;
1660 1782
1661 ret=vfd->vidioc_g_tuner(file, fh, p); 1783 ret = vfd->vidioc_g_tuner(file, fh, p);
1662 if (!ret) 1784 if (!ret)
1663 dbgarg (cmd, "index=%d, name=%s, type=%d, " 1785 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1664 "capability=%d, rangelow=%d, " 1786 "capability=0x%x, rangelow=%d, "
1665 "rangehigh=%d, signal=%d, afc=%d, " 1787 "rangehigh=%d, signal=%d, afc=%d, "
1666 "rxsubchans=%d, audmode=%d\n", 1788 "rxsubchans=0x%x, audmode=%d\n",
1667 p->index, p->name, p->type, 1789 p->index, p->name, p->type,
1668 p->capability, p->rangelow, 1790 p->capability, p->rangelow,
1669 p->rangehigh, p->rxsubchans, 1791 p->rangehigh, p->signal, p->afc,
1670 p->audmode, p->signal, p->afc); 1792 p->rxsubchans, p->audmode);
1671 break; 1793 break;
1672 } 1794 }
1673 case VIDIOC_S_TUNER: 1795 case VIDIOC_S_TUNER:
1674 { 1796 {
1675 struct v4l2_tuner *p=arg; 1797 struct v4l2_tuner *p = arg;
1798
1676 if (!vfd->vidioc_s_tuner) 1799 if (!vfd->vidioc_s_tuner)
1677 break; 1800 break;
1678 dbgarg (cmd, "index=%d, name=%s, type=%d, " 1801 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1679 "capability=%d, rangelow=%d, rangehigh=%d, " 1802 "capability=0x%x, rangelow=%d, "
1680 "signal=%d, afc=%d, rxsubchans=%d, " 1803 "rangehigh=%d, signal=%d, afc=%d, "
1681 "audmode=%d\n",p->index, p->name, p->type, 1804 "rxsubchans=0x%x, audmode=%d\n",
1682 p->capability, p->rangelow,p->rangehigh, 1805 p->index, p->name, p->type,
1683 p->rxsubchans, p->audmode, p->signal, 1806 p->capability, p->rangelow,
1684 p->afc); 1807 p->rangehigh, p->signal, p->afc,
1685 ret=vfd->vidioc_s_tuner(file, fh, p); 1808 p->rxsubchans, p->audmode);
1809 ret = vfd->vidioc_s_tuner(file, fh, p);
1686 break; 1810 break;
1687 } 1811 }
1688 case VIDIOC_G_FREQUENCY: 1812 case VIDIOC_G_FREQUENCY:
1689 { 1813 {
1690 struct v4l2_frequency *p=arg; 1814 struct v4l2_frequency *p = arg;
1815
1691 if (!vfd->vidioc_g_frequency) 1816 if (!vfd->vidioc_g_frequency)
1692 break; 1817 break;
1693 1818
1694 memset(p,0,sizeof(*p)); 1819 memset(p->reserved, 0, sizeof(p->reserved));
1695 1820
1696 ret=vfd->vidioc_g_frequency(file, fh, p); 1821 ret = vfd->vidioc_g_frequency(file, fh, p);
1697 if (!ret) 1822 if (!ret)
1698 dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n", 1823 dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
1699 p->tuner,p->type,p->frequency); 1824 p->tuner, p->type, p->frequency);
1700 break; 1825 break;
1701 } 1826 }
1702 case VIDIOC_S_FREQUENCY: 1827 case VIDIOC_S_FREQUENCY:
@@ -1711,12 +1836,17 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1711 } 1836 }
1712 case VIDIOC_G_SLICED_VBI_CAP: 1837 case VIDIOC_G_SLICED_VBI_CAP:
1713 { 1838 {
1714 struct v4l2_sliced_vbi_cap *p=arg; 1839 struct v4l2_sliced_vbi_cap *p = arg;
1840 __u32 type = p->type;
1841
1715 if (!vfd->vidioc_g_sliced_vbi_cap) 1842 if (!vfd->vidioc_g_sliced_vbi_cap)
1716 break; 1843 break;
1717 ret=vfd->vidioc_g_sliced_vbi_cap(file, fh, p); 1844 memset(p, 0, sizeof(*p));
1845 p->type = type;
1846 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
1847 ret = vfd->vidioc_g_sliced_vbi_cap(file, fh, p);
1718 if (!ret) 1848 if (!ret)
1719 dbgarg (cmd, "service_set=%d\n", p->service_set); 1849 dbgarg2("service_set=%d\n", p->service_set);
1720 break; 1850 break;
1721 } 1851 }
1722 case VIDIOC_LOG_STATUS: 1852 case VIDIOC_LOG_STATUS:
@@ -1763,13 +1893,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
1763 ret = vfd->vidioc_default(file, fh, cmd, arg); 1893 ret = vfd->vidioc_default(file, fh, cmd, arg);
1764 break; 1894 break;
1765 } 1895 }
1896 case VIDIOC_S_HW_FREQ_SEEK:
1897 {
1898 struct v4l2_hw_freq_seek *p = arg;
1899 if (!vfd->vidioc_s_hw_freq_seek)
1900 break;
1901 dbgarg(cmd,
1902 "tuner=%d, type=%d, seek_upward=%d, wrap_around=%d\n",
1903 p->tuner, p->type, p->seek_upward, p->wrap_around);
1904 ret = vfd->vidioc_s_hw_freq_seek(file, fh, p);
1905 break;
1906 }
1766 } /* switch */ 1907 } /* switch */
1767 1908
1768 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { 1909 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
1769 if (ret<0) { 1910 if (ret < 0) {
1770 printk("%s: err: on ", vfd->name);
1771 v4l_print_ioctl(vfd->name, cmd); 1911 v4l_print_ioctl(vfd->name, cmd);
1772 printk("\n"); 1912 printk(KERN_CONT " error %d\n", ret);
1773 } 1913 }
1774 } 1914 }
1775 1915
@@ -1871,8 +2011,55 @@ out:
1871} 2011}
1872EXPORT_SYMBOL(video_ioctl2); 2012EXPORT_SYMBOL(video_ioctl2);
1873 2013
2014/**
2015 * get_index - assign stream number based on parent device
2016 * @vdev: video_device to assign index number to, vdev->dev should be assigned
2017 * @num: -1 if auto assign, requested number otherwise
2018 *
2019 *
2020 * returns -ENFILE if num is already in use, a free index number if
2021 * successful.
2022 */
2023static int get_index(struct video_device *vdev, int num)
2024{
2025 u32 used = 0;
2026 const int max_index = sizeof(used) * 8 - 1;
2027 int i;
2028
2029 /* Currently a single v4l driver instance cannot create more than
2030 32 devices.
2031 Increase to u64 or an array of u32 if more are needed. */
2032 if (num > max_index) {
2033 printk(KERN_ERR "videodev: %s num is too large\n", __func__);
2034 return -EINVAL;
2035 }
2036
2037 for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
2038 if (video_device[i] != NULL &&
2039 video_device[i] != vdev &&
2040 video_device[i]->dev == vdev->dev) {
2041 used |= 1 << video_device[i]->index;
2042 }
2043 }
2044
2045 if (num >= 0) {
2046 if (used & (1 << num))
2047 return -ENFILE;
2048 return num;
2049 }
2050
2051 i = ffz(used);
2052 return i > max_index ? -ENFILE : i;
2053}
2054
1874static const struct file_operations video_fops; 2055static const struct file_operations video_fops;
1875 2056
2057int video_register_device(struct video_device *vfd, int type, int nr)
2058{
2059 return video_register_device_index(vfd, type, nr, -1);
2060}
2061EXPORT_SYMBOL(video_register_device);
2062
1876/** 2063/**
1877 * video_register_device - register video4linux devices 2064 * video_register_device - register video4linux devices
1878 * @vfd: video device structure we want to register 2065 * @vfd: video device structure we want to register
@@ -1898,7 +2085,8 @@ static const struct file_operations video_fops;
1898 * %VFL_TYPE_RADIO - A radio card 2085 * %VFL_TYPE_RADIO - A radio card
1899 */ 2086 */
1900 2087
1901int video_register_device(struct video_device *vfd, int type, int nr) 2088int video_register_device_index(struct video_device *vfd, int type, int nr,
2089 int index)
1902{ 2090{
1903 int i=0; 2091 int i=0;
1904 int base; 2092 int base;
@@ -1955,20 +2143,29 @@ int video_register_device(struct video_device *vfd, int type, int nr)
1955 } 2143 }
1956 video_device[i]=vfd; 2144 video_device[i]=vfd;
1957 vfd->minor=i; 2145 vfd->minor=i;
2146
2147 ret = get_index(vfd, index);
2148 vfd->index = ret;
2149
1958 mutex_unlock(&videodev_lock); 2150 mutex_unlock(&videodev_lock);
2151
2152 if (ret < 0) {
2153 printk(KERN_ERR "%s: get_index failed\n", __func__);
2154 goto fail_minor;
2155 }
2156
1959 mutex_init(&vfd->lock); 2157 mutex_init(&vfd->lock);
1960 2158
1961 /* sysfs class */ 2159 /* sysfs class */
1962 memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev)); 2160 memset(&vfd->class_dev, 0x00, sizeof(vfd->class_dev));
1963 if (vfd->dev)
1964 vfd->class_dev.parent = vfd->dev;
1965 vfd->class_dev.class = &video_class; 2161 vfd->class_dev.class = &video_class;
1966 vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); 2162 vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor);
2163 if (vfd->dev)
2164 vfd->class_dev.parent = vfd->dev;
1967 sprintf(vfd->class_dev.bus_id, "%s%d", name_base, i - base); 2165 sprintf(vfd->class_dev.bus_id, "%s%d", name_base, i - base);
1968 ret = device_register(&vfd->class_dev); 2166 ret = device_register(&vfd->class_dev);
1969 if (ret < 0) { 2167 if (ret < 0) {
1970 printk(KERN_ERR "%s: device_register failed\n", 2168 printk(KERN_ERR "%s: device_register failed\n", __func__);
1971 __func__);
1972 goto fail_minor; 2169 goto fail_minor;
1973 } 2170 }
1974 2171
@@ -1988,7 +2185,7 @@ fail_minor:
1988 mutex_unlock(&videodev_lock); 2185 mutex_unlock(&videodev_lock);
1989 return ret; 2186 return ret;
1990} 2187}
1991EXPORT_SYMBOL(video_register_device); 2188EXPORT_SYMBOL(video_register_device_index);
1992 2189
1993/** 2190/**
1994 * video_unregister_device - unregister a video4linux device 2191 * video_unregister_device - unregister a video4linux device
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 5ff9a58b6135..059b01c11dc1 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -39,6 +39,8 @@
39#include <linux/highmem.h> 39#include <linux/highmem.h>
40#include <linux/freezer.h> 40#include <linux/freezer.h>
41 41
42#define VIVI_MODULE_NAME "vivi"
43
42/* Wake up at about 30 fps */ 44/* Wake up at about 30 fps */
43#define WAKE_NUMERATOR 30 45#define WAKE_NUMERATOR 30
44#define WAKE_DENOMINATOR 1001 46#define WAKE_DENOMINATOR 1001
@@ -47,7 +49,7 @@
47#include "font.h" 49#include "font.h"
48 50
49#define VIVI_MAJOR_VERSION 0 51#define VIVI_MAJOR_VERSION 0
50#define VIVI_MINOR_VERSION 4 52#define VIVI_MINOR_VERSION 5
51#define VIVI_RELEASE 0 53#define VIVI_RELEASE 0
52#define VIVI_VERSION \ 54#define VIVI_VERSION \
53 KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE) 55 KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
@@ -630,7 +632,7 @@ static int vidioc_querycap(struct file *file, void *priv,
630 return 0; 632 return 0;
631} 633}
632 634
633static int vidioc_enum_fmt_cap(struct file *file, void *priv, 635static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
634 struct v4l2_fmtdesc *f) 636 struct v4l2_fmtdesc *f)
635{ 637{
636 if (f->index > 0) 638 if (f->index > 0)
@@ -641,7 +643,7 @@ static int vidioc_enum_fmt_cap(struct file *file, void *priv,
641 return 0; 643 return 0;
642} 644}
643 645
644static int vidioc_g_fmt_cap(struct file *file, void *priv, 646static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
645 struct v4l2_format *f) 647 struct v4l2_format *f)
646{ 648{
647 struct vivi_fh *fh = priv; 649 struct vivi_fh *fh = priv;
@@ -658,7 +660,7 @@ static int vidioc_g_fmt_cap(struct file *file, void *priv,
658 return (0); 660 return (0);
659} 661}
660 662
661static int vidioc_try_fmt_cap(struct file *file, void *priv, 663static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
662 struct v4l2_format *f) 664 struct v4l2_format *f)
663{ 665{
664 struct vivi_fh *fh = priv; 666 struct vivi_fh *fh = priv;
@@ -706,13 +708,13 @@ static int vidioc_try_fmt_cap(struct file *file, void *priv,
706} 708}
707 709
708/*FIXME: This seems to be generic enough to be at videodev2 */ 710/*FIXME: This seems to be generic enough to be at videodev2 */
709static int vidioc_s_fmt_cap(struct file *file, void *priv, 711static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
710 struct v4l2_format *f) 712 struct v4l2_format *f)
711{ 713{
712 struct vivi_fh *fh = priv; 714 struct vivi_fh *fh = priv;
713 struct videobuf_queue *q = &fh->vb_vidq; 715 struct videobuf_queue *q = &fh->vb_vidq;
714 716
715 int ret = vidioc_try_fmt_cap(file, fh, f); 717 int ret = vidioc_try_fmt_vid_cap(file, fh, f);
716 if (ret < 0) 718 if (ret < 0)
717 return (ret); 719 return (ret);
718 720
@@ -1017,10 +1019,15 @@ static int vivi_release(void)
1017 list_del(list); 1019 list_del(list);
1018 dev = list_entry(list, struct vivi_dev, vivi_devlist); 1020 dev = list_entry(list, struct vivi_dev, vivi_devlist);
1019 1021
1020 if (-1 != dev->vfd->minor) 1022 if (-1 != dev->vfd->minor) {
1021 video_unregister_device(dev->vfd); 1023 video_unregister_device(dev->vfd);
1022 else 1024 printk(KERN_INFO "%s: /dev/video%d unregistered.\n",
1025 VIVI_MODULE_NAME, dev->vfd->minor);
1026 } else {
1023 video_device_release(dev->vfd); 1027 video_device_release(dev->vfd);
1028 printk(KERN_INFO "%s: /dev/video%d released.\n",
1029 VIVI_MODULE_NAME, dev->vfd->minor);
1030 }
1024 1031
1025 kfree(dev); 1032 kfree(dev);
1026 } 1033 }
@@ -1066,10 +1073,10 @@ static struct video_device vivi_template = {
1066 .release = video_device_release, 1073 .release = video_device_release,
1067 1074
1068 .vidioc_querycap = vidioc_querycap, 1075 .vidioc_querycap = vidioc_querycap,
1069 .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, 1076 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1070 .vidioc_g_fmt_cap = vidioc_g_fmt_cap, 1077 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1071 .vidioc_try_fmt_cap = vidioc_try_fmt_cap, 1078 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1072 .vidioc_s_fmt_cap = vidioc_s_fmt_cap, 1079 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1073 .vidioc_reqbufs = vidioc_reqbufs, 1080 .vidioc_reqbufs = vidioc_reqbufs,
1074 .vidioc_querybuf = vidioc_querybuf, 1081 .vidioc_querybuf = vidioc_querybuf,
1075 .vidioc_qbuf = vidioc_qbuf, 1082 .vidioc_qbuf = vidioc_qbuf,
@@ -1131,6 +1138,8 @@ static int __init vivi_init(void)
1131 video_nr++; 1138 video_nr++;
1132 1139
1133 dev->vfd = vfd; 1140 dev->vfd = vfd;
1141 printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n",
1142 VIVI_MODULE_NAME, vfd->minor);
1134 } 1143 }
1135 1144
1136 if (ret < 0) { 1145 if (ret < 0) {
@@ -1138,7 +1147,9 @@ static int __init vivi_init(void)
1138 printk(KERN_INFO "Error %d while loading vivi driver\n", ret); 1147 printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
1139 } else 1148 } else
1140 printk(KERN_INFO "Video Technology Magazine Virtual Video " 1149 printk(KERN_INFO "Video Technology Magazine Virtual Video "
1141 "Capture Board successfully loaded.\n"); 1150 "Capture Board ver %u.%u.%u successfully loaded.\n",
1151 (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
1152 VIVI_VERSION & 0xFF);
1142 return ret; 1153 return ret;
1143} 1154}
1144 1155
diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c
index a1f76ee032e7..cbecb3cbbbaa 100644
--- a/drivers/media/video/vp27smpx.c
+++ b/drivers/media/video/vp27smpx.c
@@ -166,4 +166,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
166 .remove = vp27smpx_remove, 166 .remove = vp27smpx_remove,
167 .id_table = vp27smpx_id, 167 .id_table = vp27smpx_id,
168}; 168};
169
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
index fc50299caa36..7be47a255853 100644
--- a/drivers/media/video/wm8739.c
+++ b/drivers/media/video/wm8739.c
@@ -327,4 +327,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
327 .remove = wm8739_remove, 327 .remove = wm8739_remove,
328 .id_table = wm8739_id, 328 .id_table = wm8739_id,
329}; 329};
330
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c
index 506378a508b9..c2ab70a04a74 100644
--- a/drivers/media/video/wm8775.c
+++ b/drivers/media/video/wm8775.c
@@ -42,7 +42,6 @@ MODULE_LICENSE("GPL");
42 42
43static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END }; 43static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END };
44 44
45
46I2C_CLIENT_INSMOD; 45I2C_CLIENT_INSMOD;
47 46
48 47
@@ -230,4 +229,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
230 .remove = wm8775_remove, 229 .remove = wm8775_remove,
231 .id_table = wm8775_id, 230 .id_table = wm8775_id,
232}; 231};
233
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 006d48847e24..0929edb2d4f1 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -59,8 +59,6 @@
59#include "zoran_device.h" 59#include "zoran_device.h"
60#include "zoran_procfs.h" 60#include "zoran_procfs.h"
61 61
62#define I2C_NAME(x) (x)->name
63
64extern const struct zoran_format zoran_formats[]; 62extern const struct zoran_format zoran_formats[];
65 63
66static int card[BUZ_MAX] = { -1, -1, -1, -1 }; 64static int card[BUZ_MAX] = { -1, -1, -1, -1 };
@@ -360,14 +358,6 @@ i2cid_to_modulename (u16 i2c_id)
360 case I2C_DRIVERID_VPX3220: 358 case I2C_DRIVERID_VPX3220:
361 name = "vpx3220"; 359 name = "vpx3220";
362 break; 360 break;
363/* case I2C_DRIVERID_VPX3224:
364 name = "vpx3224";
365 break;
366 case I2C_DRIVERID_MSE3000:
367 name = "mse3000";
368 break;*/
369 default:
370 break;
371 } 361 }
372 362
373 return name; 363 return name;
@@ -388,8 +378,6 @@ codecid_to_modulename (u16 codecid)
388 case CODEC_TYPE_ZR36016: 378 case CODEC_TYPE_ZR36016:
389 name = "zr36016"; 379 name = "zr36016";
390 break; 380 break;
391 default:
392 break;
393 } 381 }
394 382
395 return name; 383 return name;
@@ -430,7 +418,6 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
430 .type = DC10_old, 418 .type = DC10_old,
431 .name = "DC10(old)", 419 .name = "DC10(old)",
432 .i2c_decoder = I2C_DRIVERID_VPX3220, 420 .i2c_decoder = I2C_DRIVERID_VPX3220,
433 /*.i2c_encoder = I2C_DRIVERID_MSE3000,*/
434 .video_codec = CODEC_TYPE_ZR36050, 421 .video_codec = CODEC_TYPE_ZR36050,
435 .video_vfe = CODEC_TYPE_ZR36016, 422 .video_vfe = CODEC_TYPE_ZR36016,
436 423
@@ -809,7 +796,7 @@ clientunreg_unlock_and_return:
809 return res; 796 return res;
810} 797}
811 798
812static struct i2c_algo_bit_data zoran_i2c_bit_data_template = { 799static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
813 .setsda = zoran_i2c_setsda, 800 .setsda = zoran_i2c_setsda,
814 .setscl = zoran_i2c_setscl, 801 .setscl = zoran_i2c_setscl,
815 .getsda = zoran_i2c_getsda, 802 .getsda = zoran_i2c_getsda,
@@ -818,24 +805,17 @@ static struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
818 .timeout = 100, 805 .timeout = 100,
819}; 806};
820 807
821static struct i2c_adapter zoran_i2c_adapter_template = {
822 .name = "zr36057",
823 .id = I2C_HW_B_ZR36067,
824 .algo = NULL,
825 .client_register = zoran_i2c_client_register,
826 .client_unregister = zoran_i2c_client_unregister,
827};
828
829static int 808static int
830zoran_register_i2c (struct zoran *zr) 809zoran_register_i2c (struct zoran *zr)
831{ 810{
832 memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template, 811 memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template,
833 sizeof(struct i2c_algo_bit_data)); 812 sizeof(struct i2c_algo_bit_data));
834 zr->i2c_algo.data = zr; 813 zr->i2c_algo.data = zr;
835 memcpy(&zr->i2c_adapter, &zoran_i2c_adapter_template, 814 zr->i2c_adapter.id = I2C_HW_B_ZR36067;
836 sizeof(struct i2c_adapter)); 815 zr->i2c_adapter.client_register = zoran_i2c_client_register;
837 strncpy(I2C_NAME(&zr->i2c_adapter), ZR_DEVNAME(zr), 816 zr->i2c_adapter.client_unregister = zoran_i2c_client_unregister;
838 sizeof(I2C_NAME(&zr->i2c_adapter)) - 1); 817 strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr),
818 sizeof(zr->i2c_adapter.name));
839 i2c_set_adapdata(&zr->i2c_adapter, zr); 819 i2c_set_adapdata(&zr->i2c_adapter, zr);
840 zr->i2c_adapter.algo_data = &zr->i2c_algo; 820 zr->i2c_adapter.algo_data = &zr->i2c_algo;
841 zr->i2c_adapter.dev.parent = &zr->pci_dev->dev; 821 zr->i2c_adapter.dev.parent = &zr->pci_dev->dev;
@@ -1147,7 +1127,7 @@ zr36057_init (struct zoran *zr)
1147 goto exit_free; 1127 goto exit_free;
1148 } 1128 }
1149 for (j = 0; j < BUZ_NUM_STAT_COM; j++) { 1129 for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
1150 zr->stat_com[j] = 1; /* mark as unavailable to zr36057 */ 1130 zr->stat_com[j] = cpu_to_le32(1); /* mark as unavailable to zr36057 */
1151 } 1131 }
1152 1132
1153 /* 1133 /*
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index 5394d7a5cfee..c0675921fe20 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -94,7 +94,6 @@
94 V4L2_CAP_VIDEO_OVERLAY \ 94 V4L2_CAP_VIDEO_OVERLAY \
95 ) 95 )
96 96
97#include <asm/byteorder.h>
98 97
99#if defined(CONFIG_VIDEO_V4L1_COMPAT) 98#if defined(CONFIG_VIDEO_V4L1_COMPAT)
100#define ZFMT(pal, fcc, cs) \ 99#define ZFMT(pal, fcc, cs) \
@@ -2795,7 +2794,7 @@ zoran_do_ioctl (struct inode *inode,
2795 { 2794 {
2796 struct v4l2_format *fmt = arg; 2795 struct v4l2_format *fmt = arg;
2797 int i, res = 0; 2796 int i, res = 0;
2798 __u32 printformat; 2797 __le32 printformat;
2799 2798
2800 dprintk(3, KERN_DEBUG "%s: VIDIOC_S_FMT - type=%d, ", 2799 dprintk(3, KERN_DEBUG "%s: VIDIOC_S_FMT - type=%d, ",
2801 ZR_DEVNAME(zr), fmt->type); 2800 ZR_DEVNAME(zr), fmt->type);
@@ -3040,7 +3039,7 @@ zoran_do_ioctl (struct inode *inode,
3040 { 3039 {
3041 int i, res = 0; 3040 int i, res = 0;
3042 struct v4l2_framebuffer *fb = arg; 3041 struct v4l2_framebuffer *fb = arg;
3043 __u32 printformat = __cpu_to_le32(fb->fmt.pixelformat); 3042 __le32 printformat = __cpu_to_le32(fb->fmt.pixelformat);
3044 3043
3045 dprintk(3, 3044 dprintk(3,
3046 KERN_DEBUG 3045 KERN_DEBUG
diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
index a0e49dc66301..485df2e36132 100644
--- a/drivers/media/video/zr364xx.c
+++ b/drivers/media/video/zr364xx.c
@@ -521,7 +521,7 @@ static int zr364xx_vidioc_g_ctrl(struct file *file, void *priv,
521 return 0; 521 return 0;
522} 522}
523 523
524static int zr364xx_vidioc_enum_fmt_cap(struct file *file, 524static int zr364xx_vidioc_enum_fmt_vid_cap(struct file *file,
525 void *priv, struct v4l2_fmtdesc *f) 525 void *priv, struct v4l2_fmtdesc *f)
526{ 526{
527 if (f->index > 0) 527 if (f->index > 0)
@@ -537,7 +537,7 @@ static int zr364xx_vidioc_enum_fmt_cap(struct file *file,
537 return 0; 537 return 0;
538} 538}
539 539
540static int zr364xx_vidioc_try_fmt_cap(struct file *file, void *priv, 540static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
541 struct v4l2_format *f) 541 struct v4l2_format *f)
542{ 542{
543 struct video_device *vdev = video_devdata(file); 543 struct video_device *vdev = video_devdata(file);
@@ -564,7 +564,7 @@ static int zr364xx_vidioc_try_fmt_cap(struct file *file, void *priv,
564 return 0; 564 return 0;
565} 565}
566 566
567static int zr364xx_vidioc_g_fmt_cap(struct file *file, void *priv, 567static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
568 struct v4l2_format *f) 568 struct v4l2_format *f)
569{ 569{
570 struct video_device *vdev = video_devdata(file); 570 struct video_device *vdev = video_devdata(file);
@@ -589,7 +589,7 @@ static int zr364xx_vidioc_g_fmt_cap(struct file *file, void *priv,
589 return 0; 589 return 0;
590} 590}
591 591
592static int zr364xx_vidioc_s_fmt_cap(struct file *file, void *priv, 592static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
593 struct v4l2_format *f) 593 struct v4l2_format *f)
594{ 594{
595 struct video_device *vdev = video_devdata(file); 595 struct video_device *vdev = video_devdata(file);
@@ -770,10 +770,10 @@ static struct video_device zr364xx_template = {
770 .minor = -1, 770 .minor = -1,
771 771
772 .vidioc_querycap = zr364xx_vidioc_querycap, 772 .vidioc_querycap = zr364xx_vidioc_querycap,
773 .vidioc_enum_fmt_cap = zr364xx_vidioc_enum_fmt_cap, 773 .vidioc_enum_fmt_vid_cap = zr364xx_vidioc_enum_fmt_vid_cap,
774 .vidioc_try_fmt_cap = zr364xx_vidioc_try_fmt_cap, 774 .vidioc_try_fmt_vid_cap = zr364xx_vidioc_try_fmt_vid_cap,
775 .vidioc_s_fmt_cap = zr364xx_vidioc_s_fmt_cap, 775 .vidioc_s_fmt_vid_cap = zr364xx_vidioc_s_fmt_vid_cap,
776 .vidioc_g_fmt_cap = zr364xx_vidioc_g_fmt_cap, 776 .vidioc_g_fmt_vid_cap = zr364xx_vidioc_g_fmt_vid_cap,
777 .vidioc_enum_input = zr364xx_vidioc_enum_input, 777 .vidioc_enum_input = zr364xx_vidioc_enum_input,
778 .vidioc_g_input = zr364xx_vidioc_g_input, 778 .vidioc_g_input = zr364xx_vidioc_g_input,
779 .vidioc_s_input = zr364xx_vidioc_s_input, 779 .vidioc_s_input = zr364xx_vidioc_s_input,
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index ef13b7c66df3..4862398e05bf 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -33,15 +33,11 @@
33 33
34#define I2C_DRIVERID_MSP3400 1 34#define I2C_DRIVERID_MSP3400 1
35#define I2C_DRIVERID_TUNER 2 35#define I2C_DRIVERID_TUNER 2
36#define I2C_DRIVERID_TDA8425 4 /* stereo sound processor */
37#define I2C_DRIVERID_TEA6420 5 /* audio matrix switch */ 36#define I2C_DRIVERID_TEA6420 5 /* audio matrix switch */
38#define I2C_DRIVERID_TEA6415C 6 /* video matrix switch */ 37#define I2C_DRIVERID_TEA6415C 6 /* video matrix switch */
39#define I2C_DRIVERID_TDA9840 7 /* stereo sound processor */ 38#define I2C_DRIVERID_TDA9840 7 /* stereo sound processor */
40#define I2C_DRIVERID_SAA7111A 8 /* video input processor */ 39#define I2C_DRIVERID_SAA7111A 8 /* video input processor */
41#define I2C_DRIVERID_SAA7185B 13 /* video encoder */ 40#define I2C_DRIVERID_SAA7185B 13 /* video encoder */
42#define I2C_DRIVERID_TEA6300 18 /* audio mixer */
43#define I2C_DRIVERID_TDA9850 20 /* audio mixer */
44#define I2C_DRIVERID_TDA9855 21 /* audio mixer */
45#define I2C_DRIVERID_SAA7110 22 /* video decoder */ 41#define I2C_DRIVERID_SAA7110 22 /* video decoder */
46#define I2C_DRIVERID_MGATVO 23 /* Matrox TVOut */ 42#define I2C_DRIVERID_MGATVO 23 /* Matrox TVOut */
47#define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */ 43#define I2C_DRIVERID_SAA5249 24 /* SAA5249 and compatibles */
@@ -50,9 +46,7 @@
50#define I2C_DRIVERID_TDA7432 27 /* Stereo sound processor */ 46#define I2C_DRIVERID_TDA7432 27 /* Stereo sound processor */
51#define I2C_DRIVERID_TVMIXER 28 /* Mixer driver for tv cards */ 47#define I2C_DRIVERID_TVMIXER 28 /* Mixer driver for tv cards */
52#define I2C_DRIVERID_TVAUDIO 29 /* Generic TV sound driver */ 48#define I2C_DRIVERID_TVAUDIO 29 /* Generic TV sound driver */
53#define I2C_DRIVERID_TDA9873 31 /* TV sound decoder chip */
54#define I2C_DRIVERID_TDA9875 32 /* TV sound decoder chip */ 49#define I2C_DRIVERID_TDA9875 32 /* TV sound decoder chip */
55#define I2C_DRIVERID_PIC16C54_PV9 33 /* Audio mux/ir receiver */
56#define I2C_DRIVERID_BT819 40 /* video decoder */ 50#define I2C_DRIVERID_BT819 40 /* video decoder */
57#define I2C_DRIVERID_BT856 41 /* video encoder */ 51#define I2C_DRIVERID_BT856 41 /* video encoder */
58#define I2C_DRIVERID_VPX3220 42 /* video decoder+vbi/vtxt */ 52#define I2C_DRIVERID_VPX3220 42 /* video decoder+vbi/vtxt */
@@ -63,7 +57,6 @@
63#define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */ 57#define I2C_DRIVERID_INDYCAM 58 /* SGI IndyCam */
64#define I2C_DRIVERID_OVCAMCHIP 61 /* OmniVision CMOS image sens. */ 58#define I2C_DRIVERID_OVCAMCHIP 61 /* OmniVision CMOS image sens. */
65#define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */ 59#define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */
66#define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */
67#define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */ 60#define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */
68#define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */ 61#define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */
69#define I2C_DRIVERID_WM8775 69 /* wm8775 audio processor */ 62#define I2C_DRIVERID_WM8775 69 /* wm8775 audio processor */
@@ -158,7 +151,6 @@
158#define I2C_HW_SMBUS_W9968CF 0x04000d 151#define I2C_HW_SMBUS_W9968CF 0x04000d
159#define I2C_HW_SMBUS_OV511 0x04000e /* OV511(+) USB 1.1 webcam ICs */ 152#define I2C_HW_SMBUS_OV511 0x04000e /* OV511(+) USB 1.1 webcam ICs */
160#define I2C_HW_SMBUS_OV518 0x04000f /* OV518(+) USB 1.1 webcam ICs */ 153#define I2C_HW_SMBUS_OV518 0x04000f /* OV518(+) USB 1.1 webcam ICs */
161#define I2C_HW_SMBUS_OVFX2 0x040011 /* Cypress/OmniVision FX2 webcam */
162#define I2C_HW_SMBUS_CAFE 0x040012 /* Marvell 88ALP01 "CAFE" cam */ 154#define I2C_HW_SMBUS_CAFE 0x040012 /* Marvell 88ALP01 "CAFE" cam */
163#define I2C_HW_SMBUS_ALI1563 0x040013 155#define I2C_HW_SMBUS_ALI1563 0x040013
164 156
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 4a535ea1e123..2e66a95e8d32 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -246,6 +246,7 @@ struct v4l2_capability
246#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */ 246#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */
247#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ 247#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
248#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay */ 248#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay */
249#define V4L2_CAP_HW_FREQ_SEEK 0x00000400 /* Can do hardware frequency seek */
249 250
250#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ 251#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
251#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ 252#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
@@ -309,6 +310,7 @@ struct v4l2_pix_format
309 310
310/* see http://www.siliconimaging.com/RGB%20Bayer.htm */ 311/* see http://www.siliconimaging.com/RGB%20Bayer.htm */
311#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ 312#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */
313#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G','B','R','G') /* 8 GBGB.. RGRG.. */
312#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B','Y','R','2') /* 16 BGBG.. GRGR.. */ 314#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B','Y','R','2') /* 16 BGBG.. GRGR.. */
313 315
314/* compressed formats */ 316/* compressed formats */
@@ -323,6 +325,9 @@ struct v4l2_pix_format
323#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') /* pwc older webcam */ 325#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') /* pwc older webcam */
324#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') /* pwc newer webcam */ 326#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') /* pwc newer webcam */
325#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */ 327#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */
328#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S','5','0','1') /* YUYV per line */
329#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S','5','6','1') /* compressed GBRG bayer */
330#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P','2','0','7') /* compressed BGGR bayer */
326 331
327/* 332/*
328 * F O R M A T E N U M E R A T I O N 333 * F O R M A T E N U M E R A T I O N
@@ -1156,6 +1161,14 @@ struct v4l2_frequency
1156 __u32 reserved[8]; 1161 __u32 reserved[8];
1157}; 1162};
1158 1163
1164struct v4l2_hw_freq_seek {
1165 __u32 tuner;
1166 enum v4l2_tuner_type type;
1167 __u32 seek_upward;
1168 __u32 wrap_around;
1169 __u32 reserved[8];
1170};
1171
1159/* 1172/*
1160 * A U D I O 1173 * A U D I O
1161 */ 1174 */
@@ -1441,6 +1454,7 @@ struct v4l2_chip_ident {
1441 1454
1442#define VIDIOC_G_CHIP_IDENT _IOWR ('V', 81, struct v4l2_chip_ident) 1455#define VIDIOC_G_CHIP_IDENT _IOWR ('V', 81, struct v4l2_chip_ident)
1443#endif 1456#endif
1457#define VIDIOC_S_HW_FREQ_SEEK _IOW ('V', 82, struct v4l2_hw_freq_seek)
1444 1458
1445#ifdef __OLD_VIDIOC_ 1459#ifdef __OLD_VIDIOC_
1446/* for compatibility, will go away some day */ 1460/* for compatibility, will go away some day */
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h
index 5f4608e88476..9ec4d5889ef5 100644
--- a/include/media/cx2341x.h
+++ b/include/media/cx2341x.h
@@ -27,6 +27,7 @@ enum cx2341x_port {
27 27
28enum cx2341x_cap { 28enum cx2341x_cap {
29 CX2341X_CAP_HAS_SLICED_VBI = 1 << 0, 29 CX2341X_CAP_HAS_SLICED_VBI = 1 << 0,
30 CX2341X_CAP_HAS_TS = 1 << 1,
30}; 31};
31 32
32struct cx2341x_mpeg_params { 33struct cx2341x_mpeg_params {
@@ -88,13 +89,13 @@ typedef int (*cx2341x_mbox_func)(void *priv, u32 cmd, int in, int out,
88int cx2341x_update(void *priv, cx2341x_mbox_func func, 89int cx2341x_update(void *priv, cx2341x_mbox_func func,
89 const struct cx2341x_mpeg_params *old, 90 const struct cx2341x_mpeg_params *old,
90 const struct cx2341x_mpeg_params *new); 91 const struct cx2341x_mpeg_params *new);
91int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, 92int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
92 struct v4l2_queryctrl *qctrl); 93 struct v4l2_queryctrl *qctrl);
93const char **cx2341x_ctrl_get_menu(u32 id); 94const char **cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id);
94int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy, 95int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
95 struct v4l2_ext_controls *ctrls, unsigned int cmd); 96 struct v4l2_ext_controls *ctrls, unsigned int cmd);
96void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p); 97void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p);
97void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix); 98void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix);
98 99
99/* Firmware names */ 100/* Firmware names */
100#define CX2341X_FIRM_ENC_FILENAME "v4l-cx2341x-enc.fw" 101#define CX2341X_FIRM_ENC_FILENAME "v4l-cx2341x-enc.fw"
diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h
index a455f7ce5ee8..00fa57eb9fde 100644
--- a/include/media/ir-kbd-i2c.h
+++ b/include/media/ir-kbd-i2c.h
@@ -19,7 +19,4 @@ struct IR_i2c {
19 char phys[32]; 19 char phys[32];
20 int (*get_key)(struct IR_i2c*, u32*, u32*); 20 int (*get_key)(struct IR_i2c*, u32*, u32*);
21}; 21};
22
23int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
24int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
25#endif 22#endif
diff --git a/include/media/pwc-ioctl.h b/include/media/pwc-ioctl.h
index adc1254e887e..0f19779c4634 100644
--- a/include/media/pwc-ioctl.h
+++ b/include/media/pwc-ioctl.h
@@ -55,8 +55,7 @@
55#include <linux/types.h> 55#include <linux/types.h>
56#include <linux/version.h> 56#include <linux/version.h>
57 57
58 58/* Enumeration of image sizes */
59 /* Enumeration of image sizes */
60#define PSZ_SQCIF 0x00 59#define PSZ_SQCIF 0x00
61#define PSZ_QSIF 0x01 60#define PSZ_QSIF 0x01
62#define PSZ_QCIF 0x02 61#define PSZ_QCIF 0x02
diff --git a/include/media/saa7146.h b/include/media/saa7146.h
index 88b2b5a619aa..2f68f4cd0037 100644
--- a/include/media/saa7146.h
+++ b/include/media/saa7146.h
@@ -53,7 +53,7 @@ struct saa7146_vv;
53/* saa7146 page table */ 53/* saa7146 page table */
54struct saa7146_pgtable { 54struct saa7146_pgtable {
55 unsigned int size; 55 unsigned int size;
56 u32 *cpu; 56 __le32 *cpu;
57 dma_addr_t dma; 57 dma_addr_t dma;
58 /* used for offsets for u,v planes for planar capture modes */ 58 /* used for offsets for u,v planes for planar capture modes */
59 unsigned long offset; 59 unsigned long offset;
@@ -101,7 +101,7 @@ struct saa7146_extension
101struct saa7146_dma 101struct saa7146_dma
102{ 102{
103 dma_addr_t dma_handle; 103 dma_addr_t dma_handle;
104 u32 *cpu_addr; 104 __le32 *cpu_addr;
105}; 105};
106 106
107struct saa7146_dev 107struct saa7146_dev
diff --git a/include/media/sh_mobile_ceu.h b/include/media/sh_mobile_ceu.h
new file mode 100644
index 000000000000..234a4711d2ec
--- /dev/null
+++ b/include/media/sh_mobile_ceu.h
@@ -0,0 +1,12 @@
1#ifndef __ASM_SH_MOBILE_CEU_H__
2#define __ASM_SH_MOBILE_CEU_H__
3
4#include <media/soc_camera.h>
5
6struct sh_mobile_ceu_info {
7 unsigned long flags; /* SOCAM_... */
8 void (*enable_camera)(void);
9 void (*disable_camera)(void);
10};
11
12#endif /* __ASM_SH_MOBILE_CEU_H__ */
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 6a8c8be7a1ae..1de98f150e99 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -13,7 +13,7 @@
13#define SOC_CAMERA_H 13#define SOC_CAMERA_H
14 14
15#include <linux/videodev2.h> 15#include <linux/videodev2.h>
16#include <media/videobuf-dma-sg.h> 16#include <media/videobuf-core.h>
17 17
18struct soc_camera_device { 18struct soc_camera_device {
19 struct list_head list; 19 struct list_head list;
@@ -48,15 +48,12 @@ struct soc_camera_device {
48struct soc_camera_file { 48struct soc_camera_file {
49 struct soc_camera_device *icd; 49 struct soc_camera_device *icd;
50 struct videobuf_queue vb_vidq; 50 struct videobuf_queue vb_vidq;
51 spinlock_t *lock;
52}; 51};
53 52
54struct soc_camera_host { 53struct soc_camera_host {
55 struct list_head list; 54 struct list_head list;
56 struct device dev; 55 struct device dev;
57 unsigned char nr; /* Host number */ 56 unsigned char nr; /* Host number */
58 size_t msize;
59 struct videobuf_queue_ops *vbq_ops;
60 void *priv; 57 void *priv;
61 char *drv_name; 58 char *drv_name;
62 struct soc_camera_host_ops *ops; 59 struct soc_camera_host_ops *ops;
@@ -69,13 +66,13 @@ struct soc_camera_host_ops {
69 int (*set_fmt_cap)(struct soc_camera_device *, __u32, 66 int (*set_fmt_cap)(struct soc_camera_device *, __u32,
70 struct v4l2_rect *); 67 struct v4l2_rect *);
71 int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *); 68 int (*try_fmt_cap)(struct soc_camera_device *, struct v4l2_format *);
69 void (*init_videobuf)(struct videobuf_queue *,
70 struct soc_camera_device *);
72 int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); 71 int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *);
73 int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); 72 int (*querycap)(struct soc_camera_host *, struct v4l2_capability *);
74 int (*try_bus_param)(struct soc_camera_device *, __u32); 73 int (*try_bus_param)(struct soc_camera_device *, __u32);
75 int (*set_bus_param)(struct soc_camera_device *, __u32); 74 int (*set_bus_param)(struct soc_camera_device *, __u32);
76 unsigned int (*poll)(struct file *, poll_table *); 75 unsigned int (*poll)(struct file *, poll_table *);
77 spinlock_t* (*spinlock_alloc)(struct soc_camera_file *);
78 void (*spinlock_free)(spinlock_t *);
79}; 76};
80 77
81struct soc_camera_link { 78struct soc_camera_link {
@@ -156,11 +153,12 @@ static inline struct v4l2_queryctrl const *soc_camera_find_qctrl(
156#define SOCAM_DATAWIDTH_8 (1 << 6) 153#define SOCAM_DATAWIDTH_8 (1 << 6)
157#define SOCAM_DATAWIDTH_9 (1 << 7) 154#define SOCAM_DATAWIDTH_9 (1 << 7)
158#define SOCAM_DATAWIDTH_10 (1 << 8) 155#define SOCAM_DATAWIDTH_10 (1 << 8)
159#define SOCAM_PCLK_SAMPLE_RISING (1 << 9) 156#define SOCAM_DATAWIDTH_16 (1 << 9)
160#define SOCAM_PCLK_SAMPLE_FALLING (1 << 10) 157#define SOCAM_PCLK_SAMPLE_RISING (1 << 10)
158#define SOCAM_PCLK_SAMPLE_FALLING (1 << 11)
161 159
162#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \ 160#define SOCAM_DATAWIDTH_MASK (SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_9 | \
163 SOCAM_DATAWIDTH_10) 161 SOCAM_DATAWIDTH_10 | SOCAM_DATAWIDTH_16)
164 162
165static inline unsigned long soc_camera_bus_param_compatible( 163static inline unsigned long soc_camera_bus_param_compatible(
166 unsigned long camera_flags, unsigned long bus_flags) 164 unsigned long camera_flags, unsigned long bus_flags)
diff --git a/include/media/soc_camera_platform.h b/include/media/soc_camera_platform.h
new file mode 100644
index 000000000000..851f18220984
--- /dev/null
+++ b/include/media/soc_camera_platform.h
@@ -0,0 +1,15 @@
1#ifndef __SOC_CAMERA_H__
2#define __SOC_CAMERA_H__
3
4#include <linux/videodev2.h>
5
6struct soc_camera_platform_info {
7 int iface;
8 char *format_name;
9 unsigned long format_depth;
10 struct v4l2_pix_format format;
11 unsigned long bus_param;
12 int (*set_capture)(struct soc_camera_platform_info *info, int enable);
13};
14
15#endif /* __SOC_CAMERA_H__ */
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 859f7a6f6f67..33f379b1ecfe 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -59,8 +59,8 @@ enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global);
59int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local); 59int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
60 60
61/* names for fancy debug output */ 61/* names for fancy debug output */
62extern char *v4l2_field_names[]; 62extern const char *v4l2_field_names[];
63extern char *v4l2_type_names[]; 63extern const char *v4l2_type_names[];
64 64
65/* Compatibility layer interface -- v4l1-compat module */ 65/* Compatibility layer interface -- v4l1-compat module */
66typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file, 66typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
@@ -96,6 +96,8 @@ struct video_device
96 int type; /* v4l1 */ 96 int type; /* v4l1 */
97 int type2; /* v4l2 */ 97 int type2; /* v4l2 */
98 int minor; 98 int minor;
99 /* attribute to diferentiate multiple indexs on one physical device */
100 int index;
99 101
100 int debug; /* Activates debug level*/ 102 int debug; /* Activates debug level*/
101 103
@@ -118,74 +120,76 @@ struct video_device
118 enum v4l2_priority p); 120 enum v4l2_priority p);
119 121
120 /* VIDIOC_ENUM_FMT handlers */ 122 /* VIDIOC_ENUM_FMT handlers */
121 int (*vidioc_enum_fmt_cap) (struct file *file, void *fh, 123 int (*vidioc_enum_fmt_vid_cap) (struct file *file, void *fh,
122 struct v4l2_fmtdesc *f); 124 struct v4l2_fmtdesc *f);
123 int (*vidioc_enum_fmt_overlay) (struct file *file, void *fh, 125 int (*vidioc_enum_fmt_vid_overlay) (struct file *file, void *fh,
124 struct v4l2_fmtdesc *f); 126 struct v4l2_fmtdesc *f);
125 int (*vidioc_enum_fmt_vbi) (struct file *file, void *fh, 127 int (*vidioc_enum_fmt_vid_out) (struct file *file, void *fh,
126 struct v4l2_fmtdesc *f); 128 struct v4l2_fmtdesc *f);
127 int (*vidioc_enum_fmt_vbi_capture) (struct file *file, void *fh, 129#if 1
128 struct v4l2_fmtdesc *f); 130 /* deprecated, will be removed in 2.6.28 */
129 int (*vidioc_enum_fmt_video_output)(struct file *file, void *fh, 131 int (*vidioc_enum_fmt_vbi_cap) (struct file *file, void *fh,
130 struct v4l2_fmtdesc *f);
131 int (*vidioc_enum_fmt_output_overlay) (struct file *file, void *fh,
132 struct v4l2_fmtdesc *f);
133 int (*vidioc_enum_fmt_vbi_output) (struct file *file, void *fh,
134 struct v4l2_fmtdesc *f); 132 struct v4l2_fmtdesc *f);
133#endif
135 int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh, 134 int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
136 struct v4l2_fmtdesc *f); 135 struct v4l2_fmtdesc *f);
137 136
138 /* VIDIOC_G_FMT handlers */ 137 /* VIDIOC_G_FMT handlers */
139 int (*vidioc_g_fmt_cap) (struct file *file, void *fh, 138 int (*vidioc_g_fmt_vid_cap) (struct file *file, void *fh,
140 struct v4l2_format *f); 139 struct v4l2_format *f);
141 int (*vidioc_g_fmt_overlay) (struct file *file, void *fh, 140 int (*vidioc_g_fmt_vid_overlay)(struct file *file, void *fh,
142 struct v4l2_format *f); 141 struct v4l2_format *f);
143 int (*vidioc_g_fmt_vbi) (struct file *file, void *fh, 142 int (*vidioc_g_fmt_vid_out) (struct file *file, void *fh,
144 struct v4l2_format *f); 143 struct v4l2_format *f);
145 int (*vidioc_g_fmt_vbi_output) (struct file *file, void *fh, 144 int (*vidioc_g_fmt_vid_out_overlay)(struct file *file, void *fh,
146 struct v4l2_format *f); 145 struct v4l2_format *f);
147 int (*vidioc_g_fmt_vbi_capture)(struct file *file, void *fh, 146 int (*vidioc_g_fmt_vbi_cap) (struct file *file, void *fh,
148 struct v4l2_format *f); 147 struct v4l2_format *f);
149 int (*vidioc_g_fmt_video_output)(struct file *file, void *fh, 148 int (*vidioc_g_fmt_vbi_out) (struct file *file, void *fh,
150 struct v4l2_format *f); 149 struct v4l2_format *f);
151 int (*vidioc_g_fmt_output_overlay) (struct file *file, void *fh, 150 int (*vidioc_g_fmt_sliced_vbi_cap)(struct file *file, void *fh,
151 struct v4l2_format *f);
152 int (*vidioc_g_fmt_sliced_vbi_out)(struct file *file, void *fh,
152 struct v4l2_format *f); 153 struct v4l2_format *f);
153 int (*vidioc_g_fmt_type_private)(struct file *file, void *fh, 154 int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
154 struct v4l2_format *f); 155 struct v4l2_format *f);
155 156
156 /* VIDIOC_S_FMT handlers */ 157 /* VIDIOC_S_FMT handlers */
157 int (*vidioc_s_fmt_cap) (struct file *file, void *fh, 158 int (*vidioc_s_fmt_vid_cap) (struct file *file, void *fh,
158 struct v4l2_format *f); 159 struct v4l2_format *f);
159 160 int (*vidioc_s_fmt_vid_overlay)(struct file *file, void *fh,
160 int (*vidioc_s_fmt_overlay) (struct file *file, void *fh,
161 struct v4l2_format *f); 161 struct v4l2_format *f);
162 int (*vidioc_s_fmt_vbi) (struct file *file, void *fh, 162 int (*vidioc_s_fmt_vid_out) (struct file *file, void *fh,
163 struct v4l2_format *f); 163 struct v4l2_format *f);
164 int (*vidioc_s_fmt_vbi_output) (struct file *file, void *fh, 164 int (*vidioc_s_fmt_vid_out_overlay)(struct file *file, void *fh,
165 struct v4l2_format *f); 165 struct v4l2_format *f);
166 int (*vidioc_s_fmt_vbi_capture)(struct file *file, void *fh, 166 int (*vidioc_s_fmt_vbi_cap) (struct file *file, void *fh,
167 struct v4l2_format *f); 167 struct v4l2_format *f);
168 int (*vidioc_s_fmt_video_output)(struct file *file, void *fh, 168 int (*vidioc_s_fmt_vbi_out) (struct file *file, void *fh,
169 struct v4l2_format *f); 169 struct v4l2_format *f);
170 int (*vidioc_s_fmt_output_overlay) (struct file *file, void *fh, 170 int (*vidioc_s_fmt_sliced_vbi_cap)(struct file *file, void *fh,
171 struct v4l2_format *f);
172 int (*vidioc_s_fmt_sliced_vbi_out)(struct file *file, void *fh,
171 struct v4l2_format *f); 173 struct v4l2_format *f);
172 int (*vidioc_s_fmt_type_private)(struct file *file, void *fh, 174 int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
173 struct v4l2_format *f); 175 struct v4l2_format *f);
174 176
175 /* VIDIOC_TRY_FMT handlers */ 177 /* VIDIOC_TRY_FMT handlers */
176 int (*vidioc_try_fmt_cap) (struct file *file, void *fh, 178 int (*vidioc_try_fmt_vid_cap) (struct file *file, void *fh,
179 struct v4l2_format *f);
180 int (*vidioc_try_fmt_vid_overlay)(struct file *file, void *fh,
177 struct v4l2_format *f); 181 struct v4l2_format *f);
178 int (*vidioc_try_fmt_overlay) (struct file *file, void *fh, 182 int (*vidioc_try_fmt_vid_out) (struct file *file, void *fh,
179 struct v4l2_format *f); 183 struct v4l2_format *f);
180 int (*vidioc_try_fmt_vbi) (struct file *file, void *fh, 184 int (*vidioc_try_fmt_vid_out_overlay)(struct file *file, void *fh,
181 struct v4l2_format *f); 185 struct v4l2_format *f);
182 int (*vidioc_try_fmt_vbi_output) (struct file *file, void *fh, 186 int (*vidioc_try_fmt_vbi_cap) (struct file *file, void *fh,
183 struct v4l2_format *f); 187 struct v4l2_format *f);
184 int (*vidioc_try_fmt_vbi_capture)(struct file *file, void *fh, 188 int (*vidioc_try_fmt_vbi_out) (struct file *file, void *fh,
185 struct v4l2_format *f); 189 struct v4l2_format *f);
186 int (*vidioc_try_fmt_video_output)(struct file *file, void *fh, 190 int (*vidioc_try_fmt_sliced_vbi_cap)(struct file *file, void *fh,
187 struct v4l2_format *f); 191 struct v4l2_format *f);
188 int (*vidioc_try_fmt_output_overlay)(struct file *file, void *fh, 192 int (*vidioc_try_fmt_sliced_vbi_out)(struct file *file, void *fh,
189 struct v4l2_format *f); 193 struct v4l2_format *f);
190 int (*vidioc_try_fmt_type_private)(struct file *file, void *fh, 194 int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
191 struct v4l2_format *f); 195 struct v4l2_format *f);
@@ -212,8 +216,9 @@ struct video_device
212 int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i); 216 int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);
213 217
214 /* Standard handling 218 /* Standard handling
215 G_STD and ENUMSTD are handled by videodev.c 219 ENUMSTD is handled by videodev.c
216 */ 220 */
221 int (*vidioc_g_std) (struct file *file, void *fh, v4l2_std_id *norm);
217 int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm); 222 int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id *norm);
218 int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a); 223 int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
219 224
@@ -224,7 +229,7 @@ struct video_device
224 int (*vidioc_s_input) (struct file *file, void *fh, unsigned int i); 229 int (*vidioc_s_input) (struct file *file, void *fh, unsigned int i);
225 230
226 /* Output handling */ 231 /* Output handling */
227 int (*vidioc_enumoutput) (struct file *file, void *fh, 232 int (*vidioc_enum_output) (struct file *file, void *fh,
228 struct v4l2_output *a); 233 struct v4l2_output *a);
229 int (*vidioc_g_output) (struct file *file, void *fh, unsigned int *i); 234 int (*vidioc_g_output) (struct file *file, void *fh, unsigned int *i);
230 int (*vidioc_s_output) (struct file *file, void *fh, unsigned int i); 235 int (*vidioc_s_output) (struct file *file, void *fh, unsigned int i);
@@ -306,6 +311,8 @@ struct video_device
306 /* Log status ioctl */ 311 /* Log status ioctl */
307 int (*vidioc_log_status) (struct file *file, void *fh); 312 int (*vidioc_log_status) (struct file *file, void *fh);
308 313
314 int (*vidioc_s_hw_freq_seek) (struct file *file, void *fh,
315 struct v4l2_hw_freq_seek *a);
309 316
310 /* Debugging ioctls */ 317 /* Debugging ioctls */
311#ifdef CONFIG_VIDEO_ADV_DEBUG 318#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -342,6 +349,8 @@ void *priv;
342 349
343/* Version 2 functions */ 350/* Version 2 functions */
344extern int video_register_device(struct video_device *vfd, int type, int nr); 351extern int video_register_device(struct video_device *vfd, int type, int nr);
352int video_register_device_index(struct video_device *vfd, int type, int nr,
353 int index);
345void video_unregister_device(struct video_device *); 354void video_unregister_device(struct video_device *);
346extern int video_ioctl2(struct inode *inode, struct file *file, 355extern int video_ioctl2(struct inode *inode, struct file *file,
347 unsigned int cmd, unsigned long arg); 356 unsigned int cmd, unsigned long arg);
@@ -366,7 +375,7 @@ video_device_create_file(struct video_device *vfd,
366{ 375{
367 int ret = device_create_file(&vfd->class_dev, attr); 376 int ret = device_create_file(&vfd->class_dev, attr);
368 if (ret < 0) 377 if (ret < 0)
369 printk(KERN_WARNING "%s error: %d\n", __FUNCTION__, ret); 378 printk(KERN_WARNING "%s error: %d\n", __func__, ret);
370 return ret; 379 return ret;
371} 380}
372static inline void 381static inline void
diff --git a/include/media/v4l2-i2c-drv-legacy.h b/include/media/v4l2-i2c-drv-legacy.h
index 878562278b67..975ffbf4e2c5 100644
--- a/include/media/v4l2-i2c-drv-legacy.h
+++ b/include/media/v4l2-i2c-drv-legacy.h
@@ -68,7 +68,6 @@ static int v4l2_i2c_drv_detach_legacy(struct i2c_client *client)
68 if (err) 68 if (err)
69 return err; 69 return err;
70 kfree(client); 70 kfree(client);
71
72 return 0; 71 return 0;
73} 72}
74 73
diff --git a/include/media/videobuf-dma-contig.h b/include/media/videobuf-dma-contig.h
new file mode 100644
index 000000000000..549386681aab
--- /dev/null
+++ b/include/media/videobuf-dma-contig.h
@@ -0,0 +1,32 @@
1/*
2 * helper functions for physically contiguous capture buffers
3 *
4 * The functions support hardware lacking scatter gather support
5 * (i.e. the buffers must be linear in physical memory)
6 *
7 * Copyright (c) 2008 Magnus Damm
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2
12 */
13#ifndef _VIDEOBUF_DMA_CONTIG_H
14#define _VIDEOBUF_DMA_CONTIG_H
15
16#include <linux/dma-mapping.h>
17#include <media/videobuf-core.h>
18
19void videobuf_queue_dma_contig_init(struct videobuf_queue *q,
20 struct videobuf_queue_ops *ops,
21 struct device *dev,
22 spinlock_t *irqlock,
23 enum v4l2_buf_type type,
24 enum v4l2_field field,
25 unsigned int msize,
26 void *priv);
27
28dma_addr_t videobuf_to_dma_contig(struct videobuf_buffer *buf);
29void videobuf_dma_contig_free(struct videobuf_queue *q,
30 struct videobuf_buffer *buf);
31
32#endif /* _VIDEOBUF_DMA_CONTIG_H */
diff --git a/include/media/videobuf-dma-sg.h b/include/media/videobuf-dma-sg.h
index be8da269ee33..90edd22d343c 100644
--- a/include/media/videobuf-dma-sg.h
+++ b/include/media/videobuf-dma-sg.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * helper functions for SG DMA video4linux capture buffers 2 * helper functions for SG DMA video4linux capture buffers
3 * 3 *
4 * The functions expect the hardware being able to scatter gatter 4 * The functions expect the hardware being able to scatter gather
5 * (i.e. the buffers are not linear in physical memory, but fragmented 5 * (i.e. the buffers are not linear in physical memory, but fragmented
6 * into PAGE_SIZE chunks). They also assume the driver does not need 6 * into PAGE_SIZE chunks). They also assume the driver does not need
7 * to touch the video data. 7 * to touch the video data.
diff --git a/include/media/videobuf-vmalloc.h b/include/media/videobuf-vmalloc.h
index aed39460c154..e87222c6a125 100644
--- a/include/media/videobuf-vmalloc.h
+++ b/include/media/videobuf-vmalloc.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * helper functions for vmalloc capture buffers 2 * helper functions for vmalloc capture buffers
3 * 3 *
4 * The functions expect the hardware being able to scatter gatter 4 * The functions expect the hardware being able to scatter gather
5 * (i.e. the buffers are not linear in physical memory, but fragmented 5 * (i.e. the buffers are not linear in physical memory, but fragmented
6 * into PAGE_SIZE chunks). They also assume the driver does not need 6 * into PAGE_SIZE chunks). They also assume the driver does not need
7 * to touch the video data. 7 * to touch the video data.