]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
authorLinus Torvalds <torvalds@g5.osdl.org>
Sun, 25 Jun 2006 17:09:31 +0000 (10:09 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 25 Jun 2006 17:09:31 +0000 (10:09 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (244 commits)
  V4L/DVB (4210b): git-dvb: tea575x-tuner build fix
  V4L/DVB (4210a): git-dvb versus matroxfb
  V4L/DVB (4209): Added some BTTV PCI IDs for newer boards
  Fixes some sync issues between V4L/DVB development and GIT
  V4L/DVB (4206): Cx88-blackbird: always set encoder height based on tvnorm->id
  V4L/DVB (4205): Merge tda9887 module into tuner.
  V4L/DVB (4203): Explicitly set the enum values.
  V4L/DVB (4202): allow selecting CX2341x port mode
  V4L/DVB (4200): Disable bitrate_mode when encoding mpeg-1.
  V4L/DVB (4199): Add cx2341x-specific control array to cx2341x.c
  V4L/DVB (4198): Avoid newer usages of obsoleted experimental MPEGCOMP API
  V4L/DVB (4197): Port new MPEG API to saa7134-empress with saa6752hs
  V4L/DVB (4196): Port cx88-blackbird to the new MPEG API.
  V4L/DVB (4193): Update cx2341x fw encoding API doc.
  V4L/DVB (4192): Use control helpers for saa7115, cx25840, msp3400.
  V4L/DVB (4191): Add CX2341X MPEG encoder module.
  V4L/DVB (4190): Add helper functions for control processing to v4l2-common.
  V4L/DVB (4189): Add videodev support for VIDIOC_S/G/TRY_EXT_CTRLS.
  V4L/DVB (4188): Add new MPEG control/ioctl definitions to videodev2.h
  V4L/DVB (4186): Add support for the DNTV Live! mini DVB-T card.
  ...

304 files changed:
Documentation/video4linux/CARDLIST.bttv
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/CARDLIST.tuner
Documentation/video4linux/CQcam.txt
Documentation/video4linux/Zoran
Documentation/video4linux/bttv/CONTRIBUTORS
Documentation/video4linux/cx2341x/fw-calling.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-decoder-api.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-dma.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-encoder-api.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-memory.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-osd-api.txt [new file with mode: 0644]
Documentation/video4linux/cx2341x/fw-upload.txt [new file with mode: 0644]
Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt [new file with mode: 0644]
Documentation/video4linux/et61x251.txt
Documentation/video4linux/ibmcam.txt
Documentation/video4linux/ov511.txt
Documentation/video4linux/sn9c102.txt
Documentation/video4linux/v4lgrab.c [new file with mode: 0644]
Documentation/video4linux/w9968cf.txt
Documentation/video4linux/zc0301.txt
drivers/media/Kconfig
drivers/media/common/Makefile
drivers/media/common/ir-functions.c
drivers/media/common/ir-keymaps.c
drivers/media/common/saa7146_fops.c
drivers/media/common/saa7146_hlp.c
drivers/media/common/saa7146_video.c
drivers/media/common/saa7146_vv_ksyms.c [deleted file]
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/b2c2/flexcop-pci.c
drivers/media/dvb/b2c2/flexcop-usb.c
drivers/media/dvb/b2c2/flexcop.c
drivers/media/dvb/bt8xx/bt878.c
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/bt8xx/dst_ca.c
drivers/media/dvb/bt8xx/dst_common.h
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/bt8xx/dvb-bt8xx.h
drivers/media/dvb/cinergyT2/Kconfig
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dvb-core/Makefile
drivers/media/dvb/dvb-core/dmxdev.c
drivers/media/dvb/dvb-core/dvb_ca_en50221.c
drivers/media/dvb/dvb-core/dvb_demux.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_frontend.h
drivers/media/dvb/dvb-core/dvb_math.c [new file with mode: 0644]
drivers/media/dvb/dvb-core/dvb_math.h [new file with mode: 0644]
drivers/media/dvb/dvb-core/dvb_net.c
drivers/media/dvb/dvb-core/dvbdev.c
drivers/media/dvb/dvb-core/dvbdev.h
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dibusb-common.c
drivers/media/dvb/dvb-usb/dibusb-mb.c
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dtt200u-fe.c
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dvb-usb.h
drivers/media/dvb/dvb-usb/gp8psk-fe.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/gp8psk.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/gp8psk.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/umt-010.c
drivers/media/dvb/dvb-usb/vp702x-fe.c
drivers/media/dvb/dvb-usb/vp7045-fe.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/bcm3510.c
drivers/media/dvb/frontends/bsbe1.h
drivers/media/dvb/frontends/bsru6.h
drivers/media/dvb/frontends/cx22700.c
drivers/media/dvb/frontends/cx22700.h
drivers/media/dvb/frontends/cx22702.c
drivers/media/dvb/frontends/cx22702.h
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/cx24110.h
drivers/media/dvb/frontends/cx24123.c
drivers/media/dvb/frontends/cx24123.h
drivers/media/dvb/frontends/dib3000-common.h
drivers/media/dvb/frontends/dib3000.h
drivers/media/dvb/frontends/dib3000mb.c
drivers/media/dvb/frontends/dib3000mc.c
drivers/media/dvb/frontends/dvb-pll.c
drivers/media/dvb/frontends/dvb-pll.h
drivers/media/dvb/frontends/dvb_dummy_fe.c
drivers/media/dvb/frontends/isl6421.c [new file with mode: 0644]
drivers/media/dvb/frontends/isl6421.h [new file with mode: 0644]
drivers/media/dvb/frontends/l64781.c
drivers/media/dvb/frontends/l64781.h
drivers/media/dvb/frontends/lg_h06xf.h [new file with mode: 0644]
drivers/media/dvb/frontends/lgdt330x.c
drivers/media/dvb/frontends/lgdt330x.h
drivers/media/dvb/frontends/lnbp21.c [new file with mode: 0644]
drivers/media/dvb/frontends/lnbp21.h
drivers/media/dvb/frontends/mt312.c
drivers/media/dvb/frontends/mt312.h
drivers/media/dvb/frontends/mt352.c
drivers/media/dvb/frontends/mt352.h
drivers/media/dvb/frontends/nxt200x.c
drivers/media/dvb/frontends/nxt200x.h
drivers/media/dvb/frontends/nxt6000.c
drivers/media/dvb/frontends/nxt6000.h
drivers/media/dvb/frontends/or51132.c
drivers/media/dvb/frontends/or51132.h
drivers/media/dvb/frontends/or51211.c
drivers/media/dvb/frontends/s5h1420.c
drivers/media/dvb/frontends/s5h1420.h
drivers/media/dvb/frontends/sp8870.c
drivers/media/dvb/frontends/sp8870.h
drivers/media/dvb/frontends/sp887x.c
drivers/media/dvb/frontends/sp887x.h
drivers/media/dvb/frontends/stv0297.c
drivers/media/dvb/frontends/stv0297.h
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/stv0299.h
drivers/media/dvb/frontends/tda10021.c
drivers/media/dvb/frontends/tda10021.h
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/tda1004x.h
drivers/media/dvb/frontends/tda8083.c
drivers/media/dvb/frontends/tda8083.h
drivers/media/dvb/frontends/ves1820.c
drivers/media/dvb/frontends/ves1820.h
drivers/media/dvb/frontends/ves1x93.c
drivers/media/dvb/frontends/ves1x93.h
drivers/media/dvb/frontends/zl10353.c
drivers/media/dvb/frontends/zl10353.h
drivers/media/dvb/pluto2/pluto2.c
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/Makefile
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget-core.c
drivers/media/dvb/ttpci/budget-patch.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttusb-budget/Kconfig
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/dvb/ttusb-dec/ttusbdecfe.c
drivers/media/radio/Kconfig
drivers/media/radio/Makefile
drivers/media/radio/miropcm20-radio.c
drivers/media/radio/miropcm20-rds-core.c
drivers/media/radio/miropcm20-rds.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/arv.c
drivers/media/video/bt866.c [new file with mode: 0644]
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-gpio.c
drivers/media/video/bt8xx/bttv-input.c
drivers/media/video/bt8xx/bttv.h
drivers/media/video/bt8xx/bttvp.h
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cpia.c
drivers/media/video/cpia.h
drivers/media/video/cpia2/cpia2.h
drivers/media/video/cpia2/cpia2_v4l.c
drivers/media/video/cpia_pp.c
drivers/media/video/cpia_usb.c
drivers/media/video/cx2341x.c [new file with mode: 0644]
drivers/media/video/cx25840/cx25840-audio.c
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx25840/cx25840-core.h
drivers/media/video/cx25840/cx25840-vbi.c
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/cx88-alsa.c
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/cx88/cx88-vbi.c
drivers/media/video/cx88/cx88.h
drivers/media/video/dsbr100.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/em28xx/em28xx-i2c.c
drivers/media/video/em28xx/em28xx-input.c
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/ks0127.c [new file with mode: 0644]
drivers/media/video/ks0127.h [new file with mode: 0644]
drivers/media/video/meye.c
drivers/media/video/msp3400-driver.c
drivers/media/video/msp3400-kthreads.c
drivers/media/video/ov511.c
drivers/media/video/ov511.h
drivers/media/video/planb.c
drivers/media/video/pms.c
drivers/media/video/pwc/Kconfig
drivers/media/video/pwc/Makefile
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/pwc/pwc-dec1.c [new file with mode: 0644]
drivers/media/video/pwc/pwc-dec1.h [new file with mode: 0644]
drivers/media/video/pwc/pwc-dec23.c [new file with mode: 0644]
drivers/media/video/pwc/pwc-dec23.h [new file with mode: 0644]
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc-kiara.c
drivers/media/video/pwc/pwc-kiara.h
drivers/media/video/pwc/pwc-misc.c
drivers/media/video/pwc/pwc-timon.c
drivers/media/video/pwc/pwc-timon.h
drivers/media/video/pwc/pwc-uncompress.c
drivers/media/video/pwc/pwc-uncompress.h
drivers/media/video/pwc/pwc-v4l.c [new file with mode: 0644]
drivers/media/video/pwc/pwc.h
drivers/media/video/saa5246a.c
drivers/media/video/saa5249.c
drivers/media/video/saa7110.c
drivers/media/video/saa7115.c
drivers/media/video/saa7127.c
drivers/media/video/saa7134/saa6752hs.c
drivers/media/video/saa7134/saa7134-alsa.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/se401.h
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/stradis.c
drivers/media/video/stv680.c
drivers/media/video/tda9875.c
drivers/media/video/tda9887.c
drivers/media/video/tea5767.c
drivers/media/video/tlv320aic23b.c [new file with mode: 0644]
drivers/media/video/tuner-3036.c
drivers/media/video/tuner-core.c
drivers/media/video/tuner-simple.c
drivers/media/video/tuner-types.c
drivers/media/video/tveeprom.c
drivers/media/video/tvmixer.c
drivers/media/video/tvp5150.c
drivers/media/video/usbvideo/Kconfig
drivers/media/video/usbvideo/Makefile
drivers/media/video/usbvideo/quickcam_messenger.c [new file with mode: 0644]
drivers/media/video/usbvideo/quickcam_messenger.h [new file with mode: 0644]
drivers/media/video/usbvideo/usbvideo.h
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/video-buf-dvb.c
drivers/media/video/videodev.c
drivers/media/video/vino.c
drivers/media/video/vivi.c
drivers/media/video/vpx3220.c
drivers/media/video/w9966.c
drivers/media/video/zc0301/Kconfig
drivers/media/video/zc0301/Makefile
drivers/media/video/zc0301/zc0301_core.c
drivers/media/video/zc0301/zc0301_pas202bcb.c
drivers/media/video/zc0301/zc0301_pb0330.c [new file with mode: 0644]
drivers/media/video/zc0301/zc0301_sensor.h
drivers/media/video/zoran.h
drivers/media/video/zoran_card.c
drivers/media/video/zoran_device.c
drivers/media/video/zoran_driver.c
drivers/media/video/zoran_procfs.c
drivers/video/matrox/matroxfb_base.c
fs/compat_ioctl.c
include/linux/dvb/dmx.h
include/linux/i2c-id.h
include/linux/videodev.h
include/linux/videodev2.h
include/media/cx2341x.h [new file with mode: 0644]
include/media/ir-common.h
include/media/ir-kbd-i2c.h
include/media/ovcamchip.h
include/media/pwc-ioctl.h [new file with mode: 0644]
include/media/saa7115.h
include/media/saa7146_vv.h
include/media/tuner.h
include/media/tvp5150.h [new file with mode: 0644]
include/media/v4l2-common.h
include/media/v4l2-dev.h [new file with mode: 0644]
include/media/video-buf-dvb.h
include/media/video-buf.h
include/sound/tea575x-tuner.h

index b72706c58a442bdb744fb34f74340b1de0337b29..4efa4645885f451e834a39908c4d8e1a26bf6faf 100644 (file)
@@ -87,7 +87,7 @@
  86 -> Osprey 101/151 w/ svid
  87 -> Osprey 200/201/250/251
  88 -> Osprey 200/250                                      [0070:ff01]
- 89 -> Osprey 210/220
+ 89 -> Osprey 210/220/230
  90 -> Osprey 500                                          [0070:ff02]
  91 -> Osprey 540                                          [0070:ff04]
  92 -> Osprey 2000                                         [0070:ff03]
 110 -> IVC-100                                             [ff00:a132]
 111 -> IVC-120G                                            [ff00:a182,ff01:a182,ff02:a182,ff03:a182,ff04:a182,ff05:a182,ff06:a182,ff07:a182,ff08:a182,ff09:a182,ff0a:a182,ff0b:a182,ff0c:a182,ff0d:a182,ff0e:a182,ff0f:a182]
 112 -> pcHDTV HD-2000 TV                                   [7063:2000]
-113 -> Twinhan DST + clones                                [11bd:0026,1822:0001,270f:fc00]
+113 -> Twinhan DST + clones                                [11bd:0026,1822:0001,270f:fc00,1822:0026]
 114 -> Winfast VC100                                       [107d:6607]
 115 -> Teppro TEV-560/InterVision IV-560
 116 -> SIMUS GVC1100                                       [aa6a:82b2]
index 3b39a91b24bd98d48189d862660e81a27ce09005..6cb63ddf6163d7768ab4dfbc99f9318dc6df08a1 100644 (file)
@@ -15,7 +15,7 @@
  14 -> KWorld/VStream XPert DVB-T                          [17de:08a6]
  15 -> DViCO FusionHDTV DVB-T1                             [18ac:db00]
  16 -> KWorld LTV883RF
- 17 -> DViCO FusionHDTV 3 Gold-Q                           [18ac:d810]
+ 17 -> DViCO FusionHDTV 3 Gold-Q                           [18ac:d810,18ac:d800]
  18 -> Hauppauge Nova-T DVB-T                              [0070:9002,0070:9001]
  19 -> Conexant DVB-T reference design                     [14f1:0187]
  20 -> Provideo PV259                                      [1540:2580]
  39 -> KWorld DVB-S 100                                    [17de:08b2]
  40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid                [0070:9400,0070:9402]
  41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)  [0070:9800,0070:9802]
- 42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025]
+ 42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025,1822:0019]
  43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1]
  44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50,18ac:db54]
  45 -> KWorld HardwareMpegTV XPert                         [17de:0840]
  46 -> DViCO FusionHDTV DVB-T Hybrid                       [18ac:db40,18ac:db44]
+ 47 -> pcHDTV HD5500 HDTV                                  [7063:5500]
+ 48 -> Kworld MCE 200 Deluxe                               [17de:0841]
+ 49 -> PixelView PlayTV P7000                              [1554:4813]
+ 50 -> NPG Tech Real TV FM Top 10                          [14f1:0842]
+ 51 -> WinFast DTV2000 H                                   [107d:665e]
index bca50903233f07dc19868b2b3fd466c8b5dabfc9..9068b669f5ee5d34af6dac4ff91a834df623b2f1 100644 (file)
@@ -93,3 +93,4 @@
  92 -> AVerMedia A169 B1                        [1461:6360]
  93 -> Medion 7134 Bridge #2                    [16be:0005]
  94 -> LifeView FlyDVB-T Hybrid Cardbus         [5168:3306,5168:3502]
+ 95 -> LifeView FlyVIDEO3000 (NTSC)             [5169:0138]
index 1bcdac67dd8c140e94dd00e1f0fa856b5a75f86e..44134f04b82afc0999dd51e97c4c073a62c4a3f8 100644 (file)
@@ -62,7 +62,7 @@ tuner=60 - Thomson DTT 761X (ATSC/NTSC)
 tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
 tuner=62 - Philips TEA5767HN FM Radio
 tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
-tuner=64 - LG TDVS-H062F/TUA6034
+tuner=64 - LG TDVS-H06xF
 tuner=65 - Ymec TVF66T5-B/DFF
 tuner=66 - LG TALN series
 tuner=67 - Philips TD1316 Hybrid Tuner
@@ -71,3 +71,4 @@ tuner=69 - Tena TNF 5335 and similar models
 tuner=70 - Samsung TCPN 2121P30A
 tuner=71 - Xceive xc3028
 tuner=72 - Thomson FE6600
+tuner=73 - Samsung TCPG 6121P30A
index 464e4cec94cb82eca91d20d0e411bfdf61c32792..ade8651e24432f879f6e3df5700b2761a9b807bd 100644 (file)
@@ -185,207 +185,10 @@ this work is documented at the video4linux2 site listed below.
 
 9.0 --- A sample program using v4lgrabber,
 
-This program is a simple image grabber that will copy a frame from the
+v4lgrab is a simple image grabber that will copy a frame from the
 first video device, /dev/video0 to standard output in portable pixmap
-format (.ppm)  Using this like: 'v4lgrab | convert - c-qcam.jpg'
-produced this picture of me at
-    http://mug.sys.virginia.edu/~drf5n/extras/c-qcam.jpg
-
--------------------- 8< ---------------- 8< -----------------------------
-
-/* Simple Video4Linux image grabber. */
-/*
- *     Video4Linux Driver Test/Example Framegrabbing Program
- *
- *     Compile with:
- *             gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
- *      Use as:
- *              v4lgrab >image.ppm
- *
- *     Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
- *      Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
- *      with minor modifications (Dave Forrest, drf5n@virginia.edu).
- *
- */
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <stdlib.h>
-
-#include <linux/types.h>
-#include <linux/videodev.h>
-
-#define FILE "/dev/video0"
-
-/* Stole this from tvset.c */
-
-#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b)                   \
-{                                                                       \
-       switch (format)                                                 \
-       {                                                               \
-               case VIDEO_PALETTE_GREY:                                \
-                       switch (depth)                                  \
-                       {                                               \
-                               case 4:                                 \
-                               case 6:                                 \
-                               case 8:                                 \
-                                       (r) = (g) = (b) = (*buf++ << 8);\
-                                       break;                          \
-                                                                       \
-                               case 16:                                \
-                                       (r) = (g) = (b) =               \
-                                               *((unsigned short *) buf);      \
-                                       buf += 2;                       \
-                                       break;                          \
-                       }                                               \
-                       break;                                          \
-                                                                       \
-                                                                       \
-               case VIDEO_PALETTE_RGB565:                              \
-               {                                                       \
-                       unsigned short tmp = *(unsigned short *)buf;    \
-                       (r) = tmp&0xF800;                               \
-                       (g) = (tmp<<5)&0xFC00;                          \
-                       (b) = (tmp<<11)&0xF800;                         \
-                       buf += 2;                                       \
-               }                                                       \
-               break;                                                  \
-                                                                       \
-               case VIDEO_PALETTE_RGB555:                              \
-                       (r) = (buf[0]&0xF8)<<8;                         \
-                       (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8;    \
-                       (b) = ((buf[1] << 2 ) & 0xF8)<<8;               \
-                       buf += 2;                                       \
-                       break;                                          \
-                                                                       \
-               case VIDEO_PALETTE_RGB24:                               \
-                       (r) = buf[0] << 8; (g) = buf[1] << 8;           \
-                       (b) = buf[2] << 8;                              \
-                       buf += 3;                                       \
-                       break;                                          \
-                                                                       \
-               default:                                                \
-                       fprintf(stderr,                                 \
-                               "Format %d not yet supported\n",        \
-                               format);                                \
-       }                                                               \
-}
-
-int get_brightness_adj(unsigned char *image, long size, int *brightness) {
-  long i, tot = 0;
-  for (i=0;i<size*3;i++)
-    tot += image[i];
-  *brightness = (128 - tot/(size*3))/3;
-  return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
-}
-
-int main(int argc, char ** argv)
-{
-  int fd = open(FILE, O_RDONLY), f;
-  struct video_capability cap;
-  struct video_window win;
-  struct video_picture vpic;
-
-  unsigned char *buffer, *src;
-  int bpp = 24, r, g, b;
-  unsigned int i, src_depth;
-
-  if (fd < 0) {
-    perror(FILE);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
-    perror("VIDIOGCAP");
-    fprintf(stderr, "(" FILE " not a video4linux device?)\n");
-    close(fd);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
-    perror("VIDIOCGWIN");
-    close(fd);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
-    perror("VIDIOCGPICT");
-    close(fd);
-    exit(1);
-  }
-
-  if (cap.type & VID_TYPE_MONOCHROME) {
-    vpic.depth=8;
-    vpic.palette=VIDEO_PALETTE_GREY;    /* 8bit grey */
-    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-      vpic.depth=6;
-      if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-       vpic.depth=4;
-       if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-         fprintf(stderr, "Unable to find a supported capture format.\n");
-         close(fd);
-         exit(1);
-       }
-      }
-    }
-  } else {
-    vpic.depth=24;
-    vpic.palette=VIDEO_PALETTE_RGB24;
-
-    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-      vpic.palette=VIDEO_PALETTE_RGB565;
-      vpic.depth=16;
-
-      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-       vpic.palette=VIDEO_PALETTE_RGB555;
-       vpic.depth=15;
-
-       if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-         fprintf(stderr, "Unable to find a supported capture format.\n");
-         return -1;
-       }
-      }
-    }
-  }
-
-  buffer = malloc(win.width * win.height * bpp);
-  if (!buffer) {
-    fprintf(stderr, "Out of memory.\n");
-    exit(1);
-  }
-
-  do {
-    int newbright;
-    read(fd, buffer, win.width * win.height * bpp);
-    f = get_brightness_adj(buffer, win.width * win.height, &newbright);
-    if (f) {
-      vpic.brightness += (newbright << 8);
-      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-       perror("VIDIOSPICT");
-       break;
-      }
-    }
-  } while (f);
-
-  fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
-
-  src = buffer;
-
-  for (i = 0; i < win.width * win.height; i++) {
-    READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
-    fputc(r>>8, stdout);
-    fputc(g>>8, stdout);
-    fputc(b>>8, stdout);
-  }
-
-  close(fd);
-  return 0;
-}
--------------------- 8< ---------------- 8< -----------------------------
+format (.ppm)  To produce .jpg output, you can use it like this:
+'v4lgrab | convert - c-qcam.jpg'
 
 
 10.0 --- Other Information
index be9f21b8455589b6c697b888c1132858bce043ce..040a2c841ae96352365d0048c07744661de7b631 100644 (file)
@@ -33,6 +33,21 @@ Inputs/outputs: Composite and S-video
 Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
 Card number: 7
 
+AverMedia 6 Eyes AVS6EYES:
+* Zoran zr36067 PCI controller
+* Zoran zr36060 MJPEG codec
+* Samsung ks0127 TV decoder
+* Conexant bt866  TV encoder
+Drivers to use: videodev, i2c-core, i2c-algo-bit,
+               videocodec, ks0127, bt866, zr36060, zr36067
+Inputs/outputs: Six physical inputs. 1-6 are composite,
+               1-2, 3-4, 5-6 doubles as S-video,
+               1-3 triples as component.
+               One composite output.
+Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
+Card number: 8
+Not autodetected, card=8 is necessary.
+
 Linux Media Labs LML33:
 * Zoran zr36067 PCI controller
 * Zoran zr36060 MJPEG codec
@@ -192,6 +207,10 @@ Micronas vpx3220a TV decoder
 was introduced in 1996, is used in the DC30 and DC30+ and
 can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC 44, PAL 60, SECAM,NTSC Comb
 
+Samsung ks0127 TV decoder
+is used in the AVS6EYES card and
+can handle: NTSC-M/N/44, PAL-M/N/B/G/H/I/D/K/L and SECAM
+
 ===========================
 
 1.2 What the TV encoder can do an what not
@@ -221,6 +240,10 @@ ITT mse3000 TV encoder
 was introduced in 1991, is used in the DC10 old
 can generate: PAL , NTSC , SECAM
 
+Conexant bt866 TV encoder
+is used in AVS6EYES, and
+can generate: NTSC/PAL, PAL­M, PAL­N
+
 The adv717x, should be able to produce PAL N. But you find nothing PAL N
 specific in the registers. Seem that you have to reuse a other standard
 to generate PAL N, maybe it would work if you use the PAL M settings.
index aef49db8847d7fd3a4c65035103275377dd19c03..8aad6dd93d6be5ea80a2a444af8308619eb6d237 100644 (file)
@@ -1,4 +1,4 @@
-Contributors to bttv: 
+Contributors to bttv:
 
 Michael Chu <mmchu@pobox.com>
   AverMedia fix and more flexible card recognition
@@ -8,8 +8,8 @@ Alan Cox <alan@redhat.com>
 
 Chris Kleitsch
   Hardware I2C
-  
-Gerd Knorr <kraxel@cs.tu-berlin.de> 
+
+Gerd Knorr <kraxel@cs.tu-berlin.de>
   Radio card (ITT sound processor)
 
 bigfoot <bigfoot@net-way.net>
@@ -18,7 +18,7 @@ Ragnar Hojland Espinosa <ragnar@macula.net>
 
 
 + many more (please mail me if you are missing in this list and would
-             like to be mentioned)
+            like to be mentioned)
 
 
 
diff --git a/Documentation/video4linux/cx2341x/fw-calling.txt b/Documentation/video4linux/cx2341x/fw-calling.txt
new file mode 100644 (file)
index 0000000..8d21181
--- /dev/null
@@ -0,0 +1,69 @@
+This page describes how to make calls to the firmware api.
+
+How to call
+===========
+
+The preferred calling convention is known as the firmware mailbox. The
+mailboxes are basically a fixed length array that serves as the call-stack.
+
+Firmware mailboxes can be located by searching the encoder and decoder memory
+for a 16 byte signature. That signature will be located on a 256-byte boundary.
+
+Signature:
+0x78, 0x56, 0x34, 0x12, 0x12, 0x78, 0x56, 0x34,
+0x34, 0x12, 0x78, 0x56, 0x56, 0x34, 0x12, 0x78
+
+The firmware implements 20 mailboxes of 20 32-bit words. The first 10 are
+reserved for API calls. The second 10 are used by the firmware for event
+notification.
+
+  Index  Name
+  -----  ----
+  0      Flags
+  1      Command
+  2      Return value
+  3      Timeout
+  4-19   Parameter/Result
+
+
+The flags are defined in the following table. The direction is from the
+perspective of the firmware.
+
+  Bit  Direction  Purpose
+  ---  ---------  -------
+  2    O          Firmware has processed the command.
+  1    I          Driver has finished setting the parameters.
+  0    I          Driver is using this mailbox.
+
+
+The command is a 32-bit enumerator. The API specifics may be found in the
+fw-*-api.txt documents.
+
+The return value is a 32-bit enumerator. Only two values are currently defined:
+0=success and -1=command undefined.
+
+There are 16 parameters/results 32-bit fields. The driver populates these fields
+with values for all the parameters required by the call. The driver overwrites
+these fields with result values returned by the call. The API specifics may be
+found in the fw-*-api.txt documents.
+
+The timeout value protects the card from a hung driver thread. If the driver
+doesn't handle the completed call within the timeout specified, the firmware
+will reset that mailbox.
+
+To make an API call, the driver iterates over each mailbox looking for the
+first one available (bit 0 has been cleared). The driver sets that bit, fills
+in the command enumerator, the timeout value and any required parameters. The
+driver then sets the parameter ready bit (bit 1). The firmware scans the
+mailboxes for pending commands, processes them, sets the result code, populates
+the result value array with that call's return values and sets the call
+complete bit (bit 2). Once bit 2 is set, the driver should retrieve the results
+and clear all the flags. If the driver does not perform this task within the
+time set in the timeout register, the firmware will reset that mailbox.
+
+Event notifications are sent from the firmware to the host. The host tells the
+firmware which events it is interested in via an API call. That call tells the
+firmware which notification mailbox to use. The firmware signals the host via
+an interrupt. Only the 16 Results fields are used, the Flags, Command, Return
+value and Timeout words are not used.
+
diff --git a/Documentation/video4linux/cx2341x/fw-decoder-api.txt b/Documentation/video4linux/cx2341x/fw-decoder-api.txt
new file mode 100644 (file)
index 0000000..9df4fb3
--- /dev/null
@@ -0,0 +1,319 @@
+Decoder firmware API description
+================================
+
+Note: this API is part of the decoder firmware, so it's cx23415 only.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_PING_FW
+Enum   0/0x00
+Description
+       This API call does nothing. It may be used to check if the firmware
+       is responding.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_START_PLAYBACK
+Enum   1/0x01
+Description
+       Begin or resume playback.
+Param[0]
+       0 based frame number in GOP to begin playback from.
+Param[1]
+       Specifies the number of muted audio frames to play before normal
+       audio resumes.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_STOP_PLAYBACK
+Enum   2/0x02
+Description
+       Ends playback and clears all decoder buffers. If PTS is not zero,
+       playback stops at specified PTS.
+Param[0]
+       Display 0=last frame, 1=black
+Param[1]
+       PTS low
+Param[2]
+       PTS high
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_PLAYBACK_SPEED
+Enum   3/0x03
+Description
+       Playback stream at speed other than normal. There are two modes of
+       operation:
+           Smooth: host transfers entire stream and firmware drops unused
+                   frames.
+           Coarse: host drops frames based on indexing as required to achieve
+                   desired speed.
+Param[0]
+       Bitmap:
+           0:7  0 normal
+                1 fast only "1.5 times"
+                n nX fast, 1/nX slow
+           30   Framedrop:
+                    '0' during 1.5 times play, every other B frame is dropped
+                    '1' during 1.5 times play, stream is unchanged (bitrate
+                        must not exceed 8mbps)
+           31   Speed:
+                    '0' slow
+                    '1' fast
+Param[1]
+       Direction: 0=forward, 1=reverse
+Param[2]
+       Picture mask:
+           1=I frames
+           3=I, P frames
+           7=I, P, B frames
+Param[3]
+       B frames per GOP (for reverse play only)
+Param[4]
+       Mute audio: 0=disable, 1=enable
+Param[5]
+       Display 0=frame, 1=field
+Param[6]
+       Specifies the number of muted audio frames to play before normal audio
+       resumes.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_STEP_VIDEO
+Enum   5/0x05
+Description
+       Each call to this API steps the playback to the next unit defined below
+       in the current playback direction.
+Param[0]
+       0=frame, 1=top field, 2=bottom field
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_DMA_BLOCK_SIZE
+Enum   8/0x08
+Description
+       Set DMA transfer block size. Counterpart to API 0xC9
+Param[0]
+       DMA transfer block size in bytes. A different size may be specified
+       when issuing the DMA transfer command.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_GET_XFER_INFO
+Enum   9/0x09
+Description
+       This API call may be used to detect an end of stream condtion.
+Result[0]
+       Stream type
+Result[1]
+       Address offset
+Result[2]
+       Maximum bytes to transfer
+Result[3]
+       Buffer fullness
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_GET_DMA_STATUS
+Enum   10/0x0A
+Description
+       Status of the last DMA transfer
+Result[0]
+       Bit 1 set means transfer complete
+       Bit 2 set means DMA error
+       Bit 3 set means linked list error
+Result[1]
+       DMA type: 0=MPEG, 1=OSD, 2=YUV
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SCHED_DMA_FROM_HOST
+Enum   11/0x0B
+Description
+       Setup DMA from host operation. Counterpart to API 0xCC
+Param[0]
+       Memory address of link list
+Param[1]
+       Total # of bytes to transfer
+Param[2]
+       DMA type (0=MPEG, 1=OSD, 2=YUV)
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_PAUSE_PLAYBACK
+Enum   13/0x0D
+Description
+       Freeze playback immediately. In this mode, when internal buffers are
+       full, no more data will be accepted and data request IRQs will be
+       masked.
+Param[0]
+       Display: 0=last frame, 1=black
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_HALT_FW
+Enum   14/0x0E
+Description
+       The firmware is halted and no further API calls are serviced until
+       the firmware is uploaded again.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_STANDARD
+Enum   16/0x10
+Description
+       Selects display standard
+Param[0]
+       0=NTSC, 1=PAL
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_GET_VERSION
+Enum   17/0x11
+Description
+       Returns decoder firmware version information
+Result[0]
+       Version bitmask:
+           Bits  0:15 build
+           Bits 16:23 minor
+           Bits 24:31 major
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_STREAM_INPUT
+Enum   20/0x14
+Description
+       Select decoder stream input port
+Param[0]
+       0=memory (default), 1=streaming
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_GET_TIMING_INFO
+Enum   21/0x15
+Description
+       Returns timing information from start of playback
+Result[0]
+       Frame count by decode order
+Result[1]
+       Video PTS bits 0:31 by display order
+Result[2]
+       Video PTS bit 32 by display order
+Result[3]
+       SCR bits 0:31 by display order
+Result[4]
+       SCR bit 32 by display order
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_AUDIO_MODE
+Enum   22/0x16
+Description
+       Select audio mode
+Param[0]
+       Dual mono mode action
+Param[1]
+       Stereo mode action:
+           0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_EVENT_NOTIFICATION
+Enum   23/0x17
+Description
+       Setup firmware to notify the host about a particular event.
+       Counterpart to API 0xD5
+Param[0]
+       Event: 0=Audio mode change between stereo and dual channel
+Param[1]
+       Notification 0=disabled, 1=enabled
+Param[2]
+       Interrupt bit
+Param[3]
+       Mailbox slot, -1 if no mailbox required.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_DISPLAY_BUFFERS
+Enum   24/0x18
+Description
+       Number of display buffers. To decode all frames in reverse playback you
+       must use nine buffers.
+Param[0]
+       0=six buffers, 1=nine buffers
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_EXTRACT_VBI
+Enum   25/0x19
+Description
+       Extracts VBI data
+Param[0]
+       0=extract from extension & user data, 1=extract from private packets
+Result[0]
+       VBI table location
+Result[1]
+       VBI table size
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_DECODER_SOURCE
+Enum   26/0x1A
+Description
+       Selects decoder source. Ensure that the parameters passed to this
+       API match the encoder settings.
+Param[0]
+       Mode: 0=MPEG from host, 1=YUV from encoder, 2=YUV from host
+Param[1]
+       YUV picture width
+Param[2]
+       YUV picture height
+Param[3]
+       Bitmap: see Param[0] of API 0xBD
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_AUDIO_OUTPUT
+Enum   27/0x1B
+Description
+       Select audio output format
+Param[0]
+       Bitmask:
+            0:1  Data size:
+                     '00' 16 bit
+                     '01' 20 bit
+                     '10' 24 bit
+            2:7  Unused
+            8:9  Mode:
+                     '00' 2 channels
+                     '01' 4 channels
+                     '10' 6 channels
+                     '11' 6 channels with one line data mode
+                          (for left justified MSB first mode, 20 bit only)
+           10:11 Unused
+           12:13 Channel format:
+                     '00' right justified MSB first mode
+                     '01' left justified MSB first mode
+                     '10' I2S mode
+           14:15 Unused
+           16:21 Right justify bit count
+           22:31 Unused
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_AV_DELAY
+Enum   28/0x1C
+Description
+       Set audio/video delay in 90Khz ticks
+Param[0]
+       0=A/V in sync, negative=audio lags, positive=video lags
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_DEC_SET_PREBUFFERING
+Enum   30/0x1E
+Description
+       Decoder prebuffering, when enabled up to 128KB are buffered for
+       streams <8mpbs or 640KB for streams >8mbps
+Param[0]
+       0=off, 1=on
diff --git a/Documentation/video4linux/cx2341x/fw-dma.txt b/Documentation/video4linux/cx2341x/fw-dma.txt
new file mode 100644 (file)
index 0000000..8123e26
--- /dev/null
@@ -0,0 +1,94 @@
+This page describes the structures and procedures used by the cx2341x DMA
+engine.
+
+Introduction
+============
+
+The cx2341x PCI interface is busmaster capable. This means it has a DMA
+engine to efficiently transfer large volumes of data between the card and main
+memory without requiring help from a CPU. Like most hardware, it must operate
+on contiguous physical memory. This is difficult to come by in large quantities
+on virtual memory machines.
+
+Therefore, it also supports a technique called "scatter-gather". The card can
+transfer multiple buffers in one operation. Instead of allocating one large
+contiguous buffer, the driver can allocate several smaller buffers.
+
+In practice, I've seen the average transfer to be roughly 80K, but transfers
+above 128K were not uncommon, particularly at startup. The 128K figure is
+important, because that is the largest block that the kernel can normally
+allocate. Even still, 128K blocks are hard to come by, so the driver writer is
+urged to choose a smaller block size and learn the scatter-gather technique.
+
+Mailbox #10 is reserved for DMA transfer information.
+
+Flow
+====
+
+This section describes, in general, the order of events when handling DMA
+transfers. Detailed information follows this section.
+
+- The card raises the Encoder interrupt.
+- The driver reads the transfer type, offset and size from Mailbox #10.
+- The driver constructs the scatter-gather array from enough free dma buffers
+  to cover the size.
+- The driver schedules the DMA transfer via the ScheduleDMAtoHost API call.
+- The card raises the DMA Complete interrupt.
+- The driver checks the DMA status register for any errors.
+- The driver post-processes the newly transferred buffers.
+
+NOTE! It is possible that the Encoder and DMA Complete interrupts get raised
+simultaneously. (End of the last, start of the next, etc.)
+
+Mailbox #10
+===========
+
+The Flags, Command, Return Value and Timeout fields are ignored.
+
+Name:       Mailbox #10
+Results[0]: Type: 0: MPEG.
+Results[1]: Offset: The position relative to the card's memory space.
+Results[2]: Size: The exact number of bytes to transfer.
+
+My speculation is that since the StartCapture API has a capture type of "RAW"
+available, that the type field will have other values that correspond to YUV
+and PCM data.
+
+Scatter-Gather Array
+====================
+
+The scatter-gather array is a contiguously allocated block of memory that
+tells the card the source and destination of each data-block to transfer.
+Card "addresses" are derived from the offset supplied by Mailbox #10. Host
+addresses are the physical memory location of the target DMA buffer.
+
+Each S-G array element is a struct of three 32-bit words. The first word is
+the source address, the second is the destination address. Both take up the
+entire 32 bits. The lowest 16 bits of the third word is the transfer byte
+count. The high-bit of the third word is the "last" flag. The last-flag tells
+the card to raise the DMA_DONE interrupt. From hard personal experience, if
+you forget to set this bit, the card will still "work" but the stream will
+most likely get corrupted.
+
+The transfer count must be a multiple of 256. Therefore, the driver will need
+to track how much data in the target buffer is valid and deal with it
+accordingly.
+
+Array Element:
+
+- 32-bit Source Address
+- 32-bit Destination Address
+- 16-bit reserved (high bit is the last flag)
+- 16-bit byte count
+
+DMA Transfer Status
+===================
+
+Register 0x0004 holds the DMA Transfer Status:
+
+Bit
+4   Scatter-Gather array error
+3   DMA write error
+2   DMA read error
+1   write completed
+0   read completed
diff --git a/Documentation/video4linux/cx2341x/fw-encoder-api.txt b/Documentation/video4linux/cx2341x/fw-encoder-api.txt
new file mode 100644 (file)
index 0000000..001c686
--- /dev/null
@@ -0,0 +1,694 @@
+Encoder firmware API description
+================================
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_PING_FW
+Enum   128/0x80
+Description
+       Does nothing. Can be used to check if the firmware is responding.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_START_CAPTURE
+Enum   129/0x81
+Description
+       Commences the capture of video, audio and/or VBI data. All encoding
+       parameters must be initialized prior to this API call. Captures frames
+       continuously or until a predefined number of frames have been captured.
+Param[0]
+       Capture stream type:
+           0=MPEG
+           1=Raw
+           2=Raw passthrough
+           3=VBI
+
+Param[1]
+       Bitmask:
+           Bit 0 when set, captures YUV
+           Bit 1 when set, captures PCM audio
+           Bit 2 when set, captures VBI (same as param[0]=3)
+           Bit 3 when set, the capture destination is the decoder
+               (same as param[0]=2)
+           Bit 4 when set, the capture destination is the host
+       Note: this parameter is only meaningful for RAW capture type.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_STOP_CAPTURE
+Enum   130/0x82
+Description
+       Ends a capture in progress
+Param[0]
+       0=stop at end of GOP (generates IRQ)
+       1=stop immediate (no IRQ)
+Param[1]
+       Stream type to stop, see param[0] of API 0x81
+Param[2]
+       Subtype, see param[1] of API 0x81
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_AUDIO_ID
+Enum   137/0x89
+Description
+       Assigns the transport stream ID of the encoded audio stream
+Param[0]
+       Audio Stream ID
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_VIDEO_ID
+Enum   139/0x8B
+Description
+       Set video transport stream ID
+Param[0]
+       Video stream ID
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_PCR_ID
+Enum   141/0x8D
+Description
+       Assigns the transport stream ID for PCR packets
+Param[0]
+       PCR Stream ID
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_FRAME_RATE
+Enum   143/0x8F
+Description
+       Set video frames per second. Change occurs at start of new GOP.
+Param[0]
+       0=30fps
+       1=25fps
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_FRAME_SIZE
+Enum   145/0x91
+Description
+       Select video stream encoding resolution.
+Param[0]
+       Height in lines. Default 480
+Param[1]
+       Width in pixels. Default 720
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_BIT_RATE
+Enum   149/0x95
+Description
+       Assign average video stream bitrate. Note on the last three params:
+       Param[3] and [4] seem to be always 0, param [5] doesn't seem to be used.
+Param[0]
+       0=variable bitrate, 1=constant bitrate
+Param[1]
+       bitrate in bits per second
+Param[2]
+       peak bitrate in bits per second, divided by 400
+Param[3]
+       Mux bitrate in bits per second, divided by 400. May be 0 (default).
+Param[4]
+       Rate Control VBR Padding
+Param[5]
+       VBV Buffer used by encoder
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_GOP_PROPERTIES
+Enum   151/0x97
+Description
+       Setup the GOP structure
+Param[0]
+       GOP size (maximum is 34)
+Param[1]
+       Number of B frames between the I and P frame, plus 1.
+       For example: IBBPBBPBBPBB --> GOP size: 12, number of B frames: 2+1 = 3
+       Note that GOP size must be a multiple of (B-frames + 1).
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_ASPECT_RATIO
+Enum   153/0x99
+Description
+       Sets the encoding aspect ratio. Changes in the aspect ratio take effect
+       at the start of the next GOP.
+Param[0]
+       '0000' forbidden
+       '0001' 1:1 square
+       '0010' 4:3
+       '0011' 16:9
+       '0100' 2.21:1
+       '0101' reserved
+        ....
+       '1111' reserved
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_DNR_FILTER_MODE
+Enum   155/0x9B
+Description
+       Assign Dynamic Noise Reduction operating mode
+Param[0]
+       Bit0: Spatial filter, set=auto, clear=manual
+       Bit1: Temporal filter, set=auto, clear=manual
+Param[1]
+       Median filter:
+           0=Disabled
+           1=Horizontal
+           2=Vertical
+           3=Horiz/Vert
+           4=Diagonal
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_DNR_FILTER_PROPS
+Enum   157/0x9D
+Description
+       These Dynamic Noise Reduction filter values are only meaningful when
+       the respective filter is set to "manual" (See API 0x9B)
+Param[0]
+       Spatial filter: default 0, range 0:15
+Param[1]
+       Temporal filter: default 0, range 0:31
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_CORING_LEVELS
+Enum   159/0x9F
+Description
+       Assign Dynamic Noise Reduction median filter properties.
+Param[0]
+       Threshold above which the luminance median filter is enabled.
+       Default: 0, range 0:255
+Param[1]
+       Threshold below which the luminance median filter is enabled.
+       Default: 255, range 0:255
+Param[2]
+       Threshold above which the chrominance median filter is enabled.
+       Default: 0, range 0:255
+Param[3]
+       Threshold below which the chrominance median filter is enabled.
+       Default: 255, range 0:255
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_SPATIAL_FILTER_TYPE
+Enum   161/0xA1
+Description
+       Assign spatial prefilter parameters
+Param[0]
+       Luminance filter
+           0=Off
+           1=1D Horizontal
+           2=1D Vertical
+           3=2D H/V Separable (default)
+           4=2D Symmetric non-separable
+Param[1]
+       Chrominance filter
+           0=Off
+           1=1D Horizontal (default)
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_3_2_PULLDOWN
+Enum   177/0xB1
+Description
+       3:2 pulldown properties
+Param[0]
+       0=enabled
+       1=disabled
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_VBI_LINE
+Enum   183/0xB7
+Description
+       Selects VBI line number.
+Param[0]
+       Bits 0:4        line number
+       Bit  31         0=top_field, 1=bottom_field
+       Bits 0:31       all set specifies "all lines"
+Param[1]
+       VBI line information features: 0=disabled, 1=enabled
+Param[2]
+       Slicing: 0=None, 1=Closed Caption
+       Almost certainly not implemented. Set to 0.
+Param[3]
+       Luminance samples in this line.
+       Almost certainly not implemented. Set to 0.
+Param[4]
+       Chrominance samples in this line
+       Almost certainly not implemented. Set to 0.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_STREAM_TYPE
+Enum   185/0xB9
+Description
+       Assign stream type
+       Note: Transport stream is not working in recent firmwares.
+       And in older firmwares the timestamps in the TS seem to be
+       unreliable.
+Param[0]
+        0=Program stream
+        1=Transport stream
+        2=MPEG1 stream
+        3=PES A/V stream
+        5=PES Video stream
+        7=PES Audio stream
+       10=DVD stream
+       11=VCD stream
+       12=SVCD stream
+       13=DVD_S1 stream
+       14=DVD_S2 stream
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_OUTPUT_PORT
+Enum   187/0xBB
+Description
+       Assign stream output port. Normally 0 when the data is copied through
+       the PCI bus (DMA), and 1 when the data is streamed to another chip
+       (pvrusb and cx88-blackbird).
+Param[0]
+       0=Memory (default)
+       1=Streaming
+       2=Serial
+Param[1]
+       Unknown, but leaving this to 0 seems to work best. Indications are that
+       this might have to do with USB support, although passing anything but 0
+       onl breaks things.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_AUDIO_PROPERTIES
+Enum   189/0xBD
+Description
+       Set audio stream properties, may be called while encoding is in progress.
+       Note: all bitfields are consistent with ISO11172 documentation except
+       bits 2:3 which ISO docs define as:
+               '11' Layer I
+               '10' Layer II
+               '01' Layer III
+               '00' Undefined
+       This discrepancy may indicate a possible error in the documentation.
+       Testing indicated that only Layer II is actually working, and that
+       the minimum bitrate should be 192 kbps.
+Param[0]
+       Bitmask:
+          0:1  '00' 44.1Khz
+               '01' 48Khz
+               '10' 32Khz
+               '11' reserved
+
+          2:3  '01'=Layer I
+               '10'=Layer II
+
+          4:7  Bitrate:
+                    Index | Layer I     | Layer II
+                    ------+-------------+------------
+                   '0000' | free format | free format
+                   '0001' |  32 kbit/s  |  32 kbit/s
+                   '0010' |  64 kbit/s  |  48 kbit/s
+                   '0011' |  96 kbit/s  |  56 kbit/s
+                   '0100' | 128 kbit/s  |  64 kbit/s
+                   '0101' | 160 kbit/s  |  80 kbit/s
+                   '0110' | 192 kbit/s  |  96 kbit/s
+                   '0111' | 224 kbit/s  | 112 kbit/s
+                   '1000' | 256 kbit/s  | 128 kbit/s
+                   '1001' | 288 kbit/s  | 160 kbit/s
+                   '1010' | 320 kbit/s  | 192 kbit/s
+                   '1011' | 352 kbit/s  | 224 kbit/s
+                   '1100' | 384 kbit/s  | 256 kbit/s
+                   '1101' | 416 kbit/s  | 320 kbit/s
+                   '1110' | 448 kbit/s  | 384 kbit/s
+               Note: For Layer II, not all combinations of total bitrate
+               and mode are allowed. See ISO11172-3 3-Annex B, Table 3-B.2
+
+          8:9  '00'=Stereo
+               '01'=JointStereo
+               '10'=Dual
+               '11'=Mono
+               Note: testing seems to indicate that Mono and possibly
+               JointStereo are not working (default to stereo).
+               Dual does work, though.
+
+         10:11 Mode Extension used in joint_stereo mode.
+               In Layer I and II they indicate which subbands are in
+               intensity_stereo. All other subbands are coded in stereo.
+                   '00' subbands 4-31 in intensity_stereo, bound==4
+                   '01' subbands 8-31 in intensity_stereo, bound==8
+                   '10' subbands 12-31 in intensity_stereo, bound==12
+                   '11' subbands 16-31 in intensity_stereo, bound==16
+
+         12:13 Emphasis:
+                   '00' None
+                   '01' 50/15uS
+                   '10' reserved
+                   '11' CCITT J.17
+
+         14    CRC:
+                   '0' off
+                   '1' on
+
+         15    Copyright:
+                   '0' off
+                   '1' on
+
+         16    Generation:
+                   '0' copy
+                   '1' original
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_HALT_FW
+Enum   195/0xC3
+Description
+       The firmware is halted and no further API calls are serviced until the
+       firmware is uploaded again.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_GET_VERSION
+Enum   196/0xC4
+Description
+       Returns the version of the encoder firmware.
+Result[0]
+       Version bitmask:
+           Bits  0:15 build
+           Bits 16:23 minor
+           Bits 24:31 major
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_GOP_CLOSURE
+Enum   197/0xC5
+Description
+       Assigns the GOP open/close property.
+Param[0]
+       0=Open
+       1=Closed
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_GET_SEQ_END
+Enum   198/0xC6
+Description
+       Obtains the sequence end code of the encoder's buffer. When a capture
+       is started a number of interrupts are still generated, the last of
+       which will have Result[0] set to 1 and Result[1] will contain the size
+       of the buffer.
+Result[0]
+       State of the transfer (1 if last buffer)
+Result[1]
+       If Result[0] is 1, this contains the size of the last buffer, undefined
+       otherwise.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_PGM_INDEX_INFO
+Enum   199/0xC7
+Description
+       Sets the Program Index Information.
+Param[0]
+       Picture Mask:
+           0=No index capture
+           1=I frames
+           3=I,P frames
+           7=I,P,B frames
+Param[1]
+       Elements requested (up to 400)
+Result[0]
+       Offset in SDF memory of the table.
+Result[1]
+       Number of allocated elements up to a maximum of Param[1]
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_VBI_CONFIG
+Enum   200/0xC8
+Description
+       Configure VBI settings
+Param[0]
+       Bitmap:
+           0    Mode '0' Sliced, '1' Raw
+           1:3  Insertion:
+                    '000' insert in extension & user data
+                    '001' insert in private packets
+                    '010' separate stream and user data
+                    '111' separate stream and private data
+           8:15 Stream ID (normally 0xBD)
+Param[1]
+       Frames per interrupt (max 8). Only valid in raw mode.
+Param[2]
+       Total raw VBI frames. Only valid in raw mode.
+Param[3]
+       Start codes
+Param[4]
+       Stop codes
+Param[5]
+       Lines per frame
+Param[6]
+       Byte per line
+Result[0]
+       Observed frames per interrupt in raw mode only. Rage 1 to Param[1]
+Result[1]
+       Observed number of frames in raw mode. Range 1 to Param[2]
+Result[2]
+       Memory offset to start or raw VBI data
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_DMA_BLOCK_SIZE
+Enum   201/0xC9
+Description
+       Set DMA transfer block size
+Param[0]
+       DMA transfer block size in bytes or frames. When unit is bytes,
+       supported block sizes are 2^7, 2^8 and 2^9 bytes.
+Param[1]
+       Unit: 0=bytes, 1=frames
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_GET_PREV_DMA_INFO_MB_10
+Enum   202/0xCA
+Description
+       Returns information on the previous DMA transfer in conjunction with
+       bit 27 of the interrupt mask. Uses mailbox 10.
+Result[0]
+       Type of stream
+Result[1]
+       Address Offset
+Result[2]
+       Maximum size of transfer
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_GET_PREV_DMA_INFO_MB_9
+Enum   203/0xCB
+Description
+       Returns information on the previous DMA transfer in conjunction with
+       bit 27 of the interrupt mask. Uses mailbox 9.
+Result[0]
+       Status bits:
+           Bit 0 set indicates transfer complete
+           Bit 2 set indicates transfer error
+           Bit 4 set indicates linked list error
+Result[1]
+       DMA type
+Result[2]
+       Presentation Time Stamp bits 0..31
+Result[3]
+       Presentation Time Stamp bit 32
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SCHED_DMA_TO_HOST
+Enum   204/0xCC
+Description
+       Setup DMA to host operation
+Param[0]
+       Memory address of link list
+Param[1]
+       Length of link list (wtf: what units ???)
+Param[2]
+       DMA type (0=MPEG)
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_INITIALIZE_INPUT
+Enum   205/0xCD
+Description
+       Initializes the video input
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_FRAME_DROP_RATE
+Enum   208/0xD0
+Description
+       For each frame captured, skip specified number of frames.
+Param[0]
+       Number of frames to skip
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_PAUSE_ENCODER
+Enum   210/0xD2
+Description
+       During a pause condition, all frames are dropped instead of being encoded.
+Param[0]
+       0=Pause encoding
+       1=Continue encoding
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_REFRESH_INPUT
+Enum   211/0xD3
+Description
+       Refreshes the video input
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_COPYRIGHT
+Enum   212/0xD4
+Description
+       Sets stream copyright property
+Param[0]
+       0=Stream is not copyrighted
+       1=Stream is copyrighted
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_EVENT_NOTIFICATION
+Enum   213/0xD5
+Description
+       Setup firmware to notify the host about a particular event. Host must
+       unmask the interrupt bit.
+Param[0]
+       Event (0=refresh encoder input)
+Param[1]
+       Notification 0=disabled 1=enabled
+Param[2]
+       Interrupt bit
+Param[3]
+       Mailbox slot, -1 if no mailbox required.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_NUM_VSYNC_LINES
+Enum   214/0xD6
+Description
+       Depending on the analog video decoder used, this assigns the number
+       of lines for field 1 and 2.
+Param[0]
+       Field 1 number of lines:
+           0x00EF for SAA7114
+           0x00F0 for SAA7115
+           0x0105 for Micronas
+Param[1]
+       Field 2 number of lines:
+           0x00EF for SAA7114
+           0x00F0 for SAA7115
+           0x0106 for Micronas
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_SET_PLACEHOLDER
+Enum   215/0xD7
+Description
+       Provides a mechanism of inserting custom user data in the MPEG stream.
+Param[0]
+       0=extension & user data
+       1=private packet with stream ID 0xBD
+Param[1]
+       Rate at which to insert data, in units of frames (for private packet)
+       or GOPs (for ext. & user data)
+Param[2]
+       Number of data DWORDs (below) to insert
+Param[3]
+       Custom data 0
+Param[4]
+       Custom data 1
+Param[5]
+       Custom data 2
+Param[6]
+       Custom data 3
+Param[7]
+       Custom data 4
+Param[8]
+       Custom data 5
+Param[9]
+       Custom data 6
+Param[10]
+       Custom data 7
+Param[11]
+       Custom data 8
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_MUTE_VIDEO
+Enum   217/0xD9
+Description
+       Video muting
+Param[0]
+       Bit usage:
+        0      '0'=video not muted
+               '1'=video muted, creates frames with the YUV color defined below
+        1:7    Unused
+        8:15   V chrominance information
+       16:23   U chrominance information
+       24:31   Y luminance information
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_MUTE_AUDIO
+Enum   218/0xDA
+Description
+       Audio muting
+Param[0]
+       0=audio not muted
+       1=audio muted (produces silent mpeg audio stream)
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_UNKNOWN
+Enum   219/0xDB
+Description
+       Unknown API, it's used by Hauppauge though.
+Param[0]
+       0 This is the value Hauppauge uses, Unknown what it means.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_ENC_MISC
+Enum   220/0xDC
+Description
+       Miscellaneous actions. Not known for 100% what it does. It's really a
+       sort of ioctl call. The first parameter is a command number, the second
+       the value.
+Param[0]
+       Command number:
+        1=set initial SCR value when starting encoding.
+        2=set quality mode (apparently some test setting).
+        3=setup advanced VIM protection handling (supposedly only for the cx23416
+          for raw YUV).
+          Actually it looks like this should be 0 for saa7114/5 based card and 1
+          for cx25840 based cards.
+        4=generate artificial PTS timestamps
+        5=USB flush mode
+        6=something to do with the quantization matrix
+        7=set navigation pack insertion for DVD
+        8=enable scene change detection (seems to be a failure)
+        9=set history parameters of the video input module
+       10=set input field order of VIM
+       11=set quantization matrix
+       12=reset audio interface
+       13=set audio volume delay
+       14=set audio delay
+
+Param[1]
+       Command value.
diff --git a/Documentation/video4linux/cx2341x/fw-memory.txt b/Documentation/video4linux/cx2341x/fw-memory.txt
new file mode 100644 (file)
index 0000000..ef0aad3
--- /dev/null
@@ -0,0 +1,141 @@
+This document describes the cx2341x memory map and documents some of the register
+space.
+
+Warning! This information was figured out from searching through the memory and
+registers, this information may not be correct and is certainly not complete, and
+was not derived from anything more than searching through the memory space with
+commands like:
+
+       ivtvctl -O min=0x02000000,max=0x020000ff
+
+So take this as is, I'm always searching for more stuff, it's a large
+register space :-).
+
+Memory Map
+==========
+
+The cx2341x exposes its entire 64M memory space to the PCI host via the PCI BAR0
+(Base Address Register 0). The addresses here are offsets relative to the
+address held in BAR0.
+
+0x00000000-0x00ffffff Encoder memory space
+0x00000000-0x0003ffff Encode.rom
+      ???-???         MPEG buffer(s)
+      ???-???         Raw video capture buffer(s)
+      ???-???         Raw audio capture buffer(s)
+      ???-???         Display buffers (6 or 9)
+
+0x01000000-0x01ffffff Decoder memory space
+0x01000000-0x0103ffff Decode.rom
+      ???-???         MPEG buffers(s)
+0x0114b000-0x0115afff Audio.rom (deprecated?)
+
+0x02000000-0x0200ffff Register Space
+
+Registers
+=========
+
+The registers occupy the 64k space starting at the 0x02000000 offset from BAR0.
+All of these registers are 32 bits wide.
+
+DMA Registers 0x000-0xff:
+
+ 0x00 - Control:
+       0=reset/cancel, 1=read, 2=write, 4=stop
+ 0x04 - DMA status:
+       1=read busy, 2=write busy, 4=read error, 8=write error, 16=link list error
+ 0x08 - pci DMA pointer for read link list
+ 0x0c - pci DMA pointer for write link list
+ 0x10 - read/write DMA enable:
+       1=read enable, 2=write enable
+ 0x14 - always 0xffffffff, if set any lower instability occurs, 0x00 crashes
+ 0x18 - ??
+ 0x1c - always 0x20 or 32, smaller values slow down DMA transactions
+ 0x20 - always value of 0x780a010a
+ 0x24-0x3c - usually just random values???
+ 0x40 - Interrupt status
+ 0x44 - Write a bit here and shows up in Interrupt status 0x40
+ 0x48 - Interrupt Mask
+ 0x4C - always value of 0xfffdffff,
+       if changed to 0xffffffff DMA write interrupts break.
+ 0x50 - always 0xffffffff
+ 0x54 - always 0xffffffff (0x4c, 0x50, 0x54 seem like interrupt masks, are
+       3 processors on chip, Java ones, VPU, SPU, APU, maybe these are the
+       interrupt masks???).
+ 0x60-0x7C - random values
+ 0x80 - first write linked list reg, for Encoder Memory addr
+ 0x84 - first write linked list reg, for pci memory addr
+ 0x88 - first write linked list reg, for length of buffer in memory addr
+       (|0x80000000 or this for last link)
+ 0x8c-0xcc - rest of write linked list reg, 8 sets of 3 total, DMA goes here
+       from linked list addr in reg 0x0c, firmware must push through or
+       something.
+ 0xe0 - first (and only) read linked list reg, for pci memory addr
+ 0xe4 - first (and only) read linked list reg, for Decoder memory addr
+ 0xe8 - first (and only) read linked list reg, for length of buffer
+ 0xec-0xff - Nothing seems to be in these registers, 0xec-f4 are 0x00000000.
+
+Memory locations for Encoder Buffers 0x700-0x7ff:
+
+These registers show offsets of memory locations pertaining to each
+buffer area used for encoding, have to shift them by <<1 first.
+
+0x07F8: Encoder SDRAM refresh
+0x07FC: Encoder SDRAM pre-charge
+
+Memory locations for Decoder Buffers 0x800-0x8ff:
+
+These registers show offsets of memory locations pertaining to each
+buffer area used for decoding, have to shift them by <<1 first.
+
+0x08F8: Decoder SDRAM refresh
+0x08FC: Decoder SDRAM pre-charge
+
+Other memory locations:
+
+0x2800: Video Display Module control
+0x2D00: AO (audio output?) control
+0x2D24: Bytes Flushed
+0x7000: LSB I2C write clock bit (inverted)
+0x7004: LSB I2C write data bit (inverted)
+0x7008: LSB I2C read clock bit
+0x700c: LSB I2C read data bit
+0x9008: GPIO get input state
+0x900c: GPIO set output state
+0x9020: GPIO direction (Bit7 (GPIO 0..7) - 0:input, 1:output)
+0x9050: SPU control
+0x9054: Reset HW blocks
+0x9058: VPU control
+0xA018: Bit6: interrupt pending?
+0xA064: APU command
+
+
+Interrupt Status Register
+=========================
+
+The definition of the bits in the interrupt status register 0x0040, and the
+interrupt mask 0x0048. If a bit is cleared in the mask, then we want our ISR to
+execute.
+
+Bit
+31 Encoder Start Capture
+30 Encoder EOS
+29 Encoder VBI capture
+28 Encoder Video Input Module reset event
+27 Encoder DMA complete
+26
+25 Decoder copy protect detection event
+24 Decoder audio mode change detection event
+23
+22 Decoder data request
+21 Decoder I-Frame? done
+20 Decoder DMA complete
+19 Decoder VBI re-insertion
+18 Decoder DMA err (linked-list bad)
+
+Missing
+Encoder API call completed
+Decoder API call completed
+Encoder API post(?)
+Decoder API post(?)
+Decoder VTRACE event
diff --git a/Documentation/video4linux/cx2341x/fw-osd-api.txt b/Documentation/video4linux/cx2341x/fw-osd-api.txt
new file mode 100644 (file)
index 0000000..da98ae3
--- /dev/null
@@ -0,0 +1,342 @@
+OSD firmware API description
+============================
+
+Note: this API is part of the decoder firmware, so it's cx23415 only.
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_FRAMEBUFFER
+Enum   65/0x41
+Description
+       Return base and length of contiguous OSD memory.
+Result[0]
+       OSD base address
+Result[1]
+       OSD length
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_PIXEL_FORMAT
+Enum   66/0x42
+Description
+       Query OSD format
+Result[0]
+       0=8bit index, 4=AlphaRGB 8:8:8:8
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_PIXEL_FORMAT
+Enum   67/0x43
+Description
+       Assign pixel format
+Param[0]
+       0=8bit index, 4=AlphaRGB 8:8:8:8
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_STATE
+Enum   68/0x44
+Description
+       Query OSD state
+Result[0]
+       Bit  0   0=off, 1=on
+       Bits 1:2 alpha control
+       Bits 3:5 pixel format
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_STATE
+Enum   69/0x45
+Description
+       OSD switch
+Param[0]
+       0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_OSD_COORDS
+Enum   70/0x46
+Description
+       Retrieve coordinates of OSD area blended with video
+Result[0]
+       OSD buffer address
+Result[1]
+       Stride in pixels
+Result[2]
+       Lines in OSD buffer
+Result[3]
+       Horizontal offset in buffer
+Result[4]
+       Vertical offset in buffer
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_OSD_COORDS
+Enum   71/0x47
+Description
+       Assign the coordinates of the OSD area to blend with video
+Param[0]
+       buffer address
+Param[1]
+       buffer stride in pixels
+Param[2]
+       lines in buffer
+Param[3]
+       horizontal offset
+Param[4]
+       vertical offset
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_SCREEN_COORDS
+Enum   72/0x48
+Description
+       Retrieve OSD screen area coordinates
+Result[0]
+       top left horizontal offset
+Result[1]
+       top left vertical offset
+Result[2]
+       bottom right hotizontal offset
+Result[3]
+       bottom right vertical offset
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_SCREEN_COORDS
+Enum   73/0x49
+Description
+       Assign the coordinates of the screen area to blend with video
+Param[0]
+       top left horizontal offset
+Param[1]
+       top left vertical offset
+Param[2]
+       bottom left horizontal offset
+Param[3]
+       bottom left vertical offset
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_GLOBAL_ALPHA
+Enum   74/0x4A
+Description
+       Retrieve OSD global alpha
+Result[0]
+       global alpha: 0=off, 1=on
+Result[1]
+       bits 0:7 global alpha
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_GLOBAL_ALPHA
+Enum   75/0x4B
+Description
+       Update global alpha
+Param[0]
+       global alpha: 0=off, 1=on
+Param[1]
+       global alpha (8 bits)
+Param[2]
+       local alpha: 0=on, 1=off
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_BLEND_COORDS
+Enum   78/0x4C
+Description
+       Move start of blending area within display buffer
+Param[0]
+       horizontal offset in buffer
+Param[1]
+       vertical offset in buffer
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_FLICKER_STATE
+Enum   79/0x4F
+Description
+       Retrieve flicker reduction module state
+Result[0]
+       flicker state: 0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_FLICKER_STATE
+Enum   80/0x50
+Description
+       Set flicker reduction module state
+Param[0]
+       State: 0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_BLT_COPY
+Enum   82/0x52
+Description
+       BLT copy
+Param[0]
+'0000'  zero
+'0001' ~destination AND ~source
+'0010' ~destination AND  source
+'0011' ~destination
+'0100'  destination AND ~source
+'0101'                  ~source
+'0110'  destination XOR  source
+'0111' ~destination OR  ~source
+'1000' ~destination AND ~source
+'1001'  destination XNOR source
+'1010'                   source
+'1011' ~destination OR   source
+'1100'  destination
+'1101'  destination OR  ~source
+'1110'  destination OR   source
+'1111'  one
+
+Param[1]
+       Resulting alpha blending
+           '01' source_alpha
+           '10' destination_alpha
+           '11' source_alpha*destination_alpha+1
+                (zero if both source and destination alpha are zero)
+Param[2]
+       '00' output_pixel = source_pixel
+
+       '01' if source_alpha=0:
+                output_pixel = destination_pixel
+            if 256 > source_alpha > 1:
+                output_pixel = ((source_alpha + 1)*source_pixel +
+                                (255 - source_alpha)*destination_pixel)/256
+
+       '10' if destination_alpha=0:
+                output_pixel = source_pixel
+             if 255 > destination_alpha > 0:
+                output_pixel = ((255 - destination_alpha)*source_pixel +
+                                (destination_alpha + 1)*destination_pixel)/256
+
+       '11' if source_alpha=0:
+                source_temp = 0
+            if source_alpha=255:
+                source_temp = source_pixel*256
+            if 255 > source_alpha > 0:
+                source_temp = source_pixel*(source_alpha + 1)
+            if destination_alpha=0:
+                destination_temp = 0
+            if destination_alpha=255:
+                destination_temp = destination_pixel*256
+            if 255 > destination_alpha > 0:
+                destination_temp = destination_pixel*(destination_alpha + 1)
+            output_pixel = (source_temp + destination_temp)/256
+Param[3]
+       width
+Param[4]
+       height
+Param[5]
+       destination pixel mask
+Param[6]
+       destination rectangle start address
+Param[7]
+       destination stride in dwords
+Param[8]
+       source stride in dwords
+Param[9]
+       source rectangle start address
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_BLT_FILL
+Enum   83/0x53
+Description
+       BLT fill color
+Param[0]
+       Same as Param[0] on API 0x52
+Param[1]
+       Same as Param[1] on API 0x52
+Param[2]
+       Same as Param[2] on API 0x52
+Param[3]
+       width
+Param[4]
+       height
+Param[5]
+       destination pixel mask
+Param[6]
+       destination rectangle start address
+Param[7]
+       destination stride in dwords
+Param[8]
+       color fill value
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_BLT_TEXT
+Enum   84/0x54
+Description
+       BLT for 8 bit alpha text source
+Param[0]
+       Same as Param[0] on API 0x52
+Param[1]
+       Same as Param[1] on API 0x52
+Param[2]
+       Same as Param[2] on API 0x52
+Param[3]
+       width
+Param[4]
+       height
+Param[5]
+       destination pixel mask
+Param[6]
+       destination rectangle start address
+Param[7]
+       destination stride in dwords
+Param[8]
+       source stride in dwords
+Param[9]
+       source rectangle start address
+Param[10]
+       color fill value
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_FRAMEBUFFER_WINDOW
+Enum   86/0x56
+Description
+       Positions the main output window on the screen. The coordinates must be
+       such that the entire window fits on the screen.
+Param[0]
+       window width
+Param[1]
+       window height
+Param[2]
+       top left window corner horizontal offset
+Param[3]
+       top left window corner vertical offset
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_CHROMA_KEY
+Enum   96/0x60
+Description
+       Chroma key switch and color
+Param[0]
+       state: 0=off, 1=on
+Param[1]
+       color
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_GET_ALPHA_CONTENT_INDEX
+Enum   97/0x61
+Description
+       Retrieve alpha content index
+Result[0]
+       alpha content index, Range 0:15
+
+-------------------------------------------------------------------------------
+
+Name   CX2341X_OSD_SET_ALPHA_CONTENT_INDEX
+Enum   98/0x62
+Description
+       Assign alpha content index
+Param[0]
+       alpha content index, range 0:15
diff --git a/Documentation/video4linux/cx2341x/fw-upload.txt b/Documentation/video4linux/cx2341x/fw-upload.txt
new file mode 100644 (file)
index 0000000..60c502c
--- /dev/null
@@ -0,0 +1,49 @@
+This document describes how to upload the cx2341x firmware to the card.
+
+How to find
+===========
+
+See the web pages of the various projects that uses this chip for information
+on how to obtain the firmware.
+
+The firmware stored in a Windows driver can be detected as follows:
+
+- Each firmware image is 256k bytes.
+- The 1st 32-bit word of the Encoder image is 0x0000da7
+- The 1st 32-bit word of the Decoder image is 0x00003a7
+- The 2nd 32-bit word of both images is 0xaa55bb66
+
+How to load
+===========
+
+- Issue the FWapi command to stop the encoder if it is running. Wait for the
+  command to complete.
+- Issue the FWapi command to stop the decoder if it is running. Wait for the
+  command to complete.
+- Issue the I2C command to the digitizer to stop emitting VSYNC events.
+- Issue the FWapi command to halt the encoder's firmware.
+- Sleep for 10ms.
+- Issue the FWapi command to halt the decoder's firmware.
+- Sleep for 10ms.
+- Write 0x00000000 to register 0x2800 to stop the Video Display Module.
+- Write 0x00000005 to register 0x2D00 to stop the AO (audio output?).
+- Write 0x00000000 to register 0xA064 to ping? the APU.
+- Write 0xFFFFFFFE to register 0x9058 to stop the VPU.
+- Write 0xFFFFFFFF to register 0x9054 to reset the HW blocks.
+- Write 0x00000001 to register 0x9050 to stop the SPU.
+- Sleep for 10ms.
+- Write 0x0000001A to register 0x07FC to init the Encoder SDRAM's pre-charge.
+- Write 0x80000640 to register 0x07F8 to init the Encoder SDRAM's refresh to 1us.
+- Write 0x0000001A to register 0x08FC to init the Decoder SDRAM's pre-charge.
+- Write 0x80000640 to register 0x08F8 to init the Decoder SDRAM's refresh to 1us.
+- Sleep for 512ms. (600ms is recommended)
+- Transfer the encoder's firmware image to offset 0 in Encoder memory space.
+- Transfer the decoder's firmware image to offset 0 in Decoder memory space.
+- Use a read-modify-write operation to Clear bit 0 of register 0x9050 to
+  re-enable the SPU.
+- Sleep for 1 second.
+- Use a read-modify-write operation to Clear bits 3 and 0 of register 0x9058
+  to re-enable the VPU.
+- Sleep for 1 second.
+- Issue status API commands to both firmware images to verify.
+
diff --git a/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt b/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt
new file mode 100644 (file)
index 0000000..93fec32
--- /dev/null
@@ -0,0 +1,54 @@
+The controls for the mux are GPIO [0,1] for source, and GPIO 2 for muting.
+
+GPIO0  GPIO1
+  0        0    TV Audio
+  1        0    FM radio
+  0        1    Line-In
+  1        1    Mono tuner bypass or CD passthru (tuner specific)
+
+GPIO 16(i believe) is tied to the IR port (if present).
+
+------------------------------------------------------------------------------------
+
+>From the data sheet:
+ Register 24'h20004  PCI Interrupt Status
+  bit [18]  IR_SMP_INT Set when 32 input samples have been collected over
+  gpio[16] pin into GP_SAMPLE register.
+
+What's missing from the data sheet:
+
+Setup 4KHz sampling rate (roughly 2x oversampled; good enough for our RC5
+compat remote)
+set register 0x35C050 to  0xa80a80
+
+enable sampling
+set register 0x35C054 to 0x5
+
+Of course, enable the IRQ bit 18 in the interrupt mask register .(and
+provide for a handler)
+
+GP_SAMPLE register is at 0x35C058
+
+Bits are then right shifted into the GP_SAMPLE register at the specified
+rate; you get an interrupt when a full DWORD is recieved.
+You need to recover the actual RC5 bits out of the (oversampled) IR sensor
+bits. (Hint: look for the 0/1and 1/0 crossings of the RC5 bi-phase data)  An
+actual raw RC5 code will span 2-3 DWORDS, depending on the actual alignment.
+
+I'm pretty sure when no IR signal is present the receiver is always in a
+marking state(1); but stray light, etc can cause intermittent noise values
+as well.  Remember, this is a free running sample of the IR receiver state
+over time, so don't assume any sample starts at any particular place.
+
+http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf
+This data sheet (google search) seems to have a lovely description of the
+RC5 basics
+
+http://users.pandora.be/nenya/electronics/rc5/  and more data
+
+http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt
+and even a reference to how to decode a bi-phase data stream.
+
+http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm
+still more info
+
index 29340282ab5f6becb1fe5245d2dff29db0d3cdbf..cd584f20a997df1fc9700824ad95a551a1ef16d1 100644 (file)
@@ -1,9 +1,9 @@
 
-                       ET61X[12]51 PC Camera Controllers
-                                Driver for Linux
-                       =================================
+                      ET61X[12]51 PC Camera Controllers
+                               Driver for Linux
+                      =================================
 
-                               - Documentation -
+                              - Documentation -
 
 
 Index
@@ -156,46 +156,46 @@ Name:           video_nr
 Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L2 minor mode number:
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 64 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                registered camera and use auto for the first one and for every
-                other camera.
+               -1 = use next available
+                n = use minor number n
+               You can specify up to 64 cameras this way.
+               For example:
+               video_nr=-1,2,-1 would assign minor number 2 to the second
+               registered camera and use auto for the first one and for every
+               other camera.
 Default:        -1
 -------------------------------------------------------------------------------
 Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]>
 Description:    Force the application to unmap previously mapped buffer memory
-                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-                all the applications support this feature. This parameter is
-                specific for each detected camera.
-                0 = do not force memory unmapping
-                1 = force memory unmapping (save memory)
+               before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+               all the applications support this feature. This parameter is
+               specific for each detected camera.
+               0 = do not force memory unmapping
+               1 = force memory unmapping (save memory)
 Default:        0
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
 Syntax:         <n[,...]>
 Description:    Timeout for a video frame in seconds. This parameter is
-                specific for each detected camera. This parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+               specific for each detected camera. This parameter can be
+               changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           debug
 Type:           ushort
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 3:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = more verbose messages
-                Level 3 is useful for testing only, when only one device
-                is used at the same time. It also shows some more informations
-                about the hardware being detected. This module parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+               0 = none (use carefully)
+               1 = critical errors
+               2 = significant informations
+               3 = more verbose messages
+               Level 3 is useful for testing only, when only one device
+               is used at the same time. It also shows some more informations
+               about the hardware being detected. This module parameter can be
+               changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 
index 4a40a2e99451a54702b1d2251cc8df2c77666fc0..397a94eb77b8cba67e3ae3303e32b5440926ee3c 100644 (file)
@@ -21,7 +21,7 @@ Internal interface: Video For Linux (V4L)
 Supported controls:
 - by V4L: Contrast,  Brightness, Color, Hue
 - by driver options: frame rate, lighting conditions, video format,
-                     default picture settings, sharpness.
+                    default picture settings, sharpness.
 
 SUPPORTED CAMERAS:
 
@@ -191,66 +191,66 @@ init_model2_sat Integer         0..255 [0x34]   init_model2_sat=65
 init_model2_yb  Integer         0..255 [0xa0]   init_model2_yb=200
 
 debug           You don't need this option unless you are a developer.
-                If you are a developer then you will see in the code
-                what values do what. 0=off.
+               If you are a developer then you will see in the code
+               what values do what. 0=off.
 
 flags           This is a bit mask, and you can combine any number of
-                bits to produce what you want. Usually you don't want
-                any of extra features this option provides:
-
-                FLAGS_RETRY_VIDIOCSYNC  1  This bit allows to retry failed
-                                           VIDIOCSYNC ioctls without failing.
-                                           Will work with xawtv, will not
-                                           with xrealproducer. Default is
-                                           not set.
-                FLAGS_MONOCHROME        2  Activates monochrome (b/w) mode.
-                FLAGS_DISPLAY_HINTS     4  Shows colored pixels which have
-                                           magic meaning to developers.
-                FLAGS_OVERLAY_STATS     8  Shows tiny numbers on screen,
-                                           useful only for debugging.
-                FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers.
-                FLAGS_SEPARATE_FRAMES   32 Shows each frame separately, as
-                                           it was received from the camera.
-                                           Default (not set) is to mix the
-                                           preceding frame in to compensate
-                                           for occasional loss of Isoc data
-                                           on high frame rates.
-                FLAGS_CLEAN_FRAMES      64 Forces "cleanup" of each frame
-                                           prior to use; relevant only if
-                                           FLAGS_SEPARATE_FRAMES is set.
-                                           Default is not to clean frames,
-                                           this is a little faster but may
-                                           produce flicker if frame rate is
-                                           too high and Isoc data gets lost.
-                FLAGS_NO_DECODING      128 This flag turns the video stream
-                                           decoder off, and dumps the raw
-                                           Isoc data from the camera into
-                                           the reading process. Useful to
-                                           developers, but not to users.
+               bits to produce what you want. Usually you don't want
+               any of extra features this option provides:
+
+               FLAGS_RETRY_VIDIOCSYNC  1  This bit allows to retry failed
+                                          VIDIOCSYNC ioctls without failing.
+                                          Will work with xawtv, will not
+                                          with xrealproducer. Default is
+                                          not set.
+               FLAGS_MONOCHROME        2  Activates monochrome (b/w) mode.
+               FLAGS_DISPLAY_HINTS     4  Shows colored pixels which have
+                                          magic meaning to developers.
+               FLAGS_OVERLAY_STATS     8  Shows tiny numbers on screen,
+                                          useful only for debugging.
+               FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers.
+               FLAGS_SEPARATE_FRAMES   32 Shows each frame separately, as
+                                          it was received from the camera.
+                                          Default (not set) is to mix the
+                                          preceding frame in to compensate
+                                          for occasional loss of Isoc data
+                                          on high frame rates.
+               FLAGS_CLEAN_FRAMES      64 Forces "cleanup" of each frame
+                                          prior to use; relevant only if
+                                          FLAGS_SEPARATE_FRAMES is set.
+                                          Default is not to clean frames,
+                                          this is a little faster but may
+                                          produce flicker if frame rate is
+                                          too high and Isoc data gets lost.
+               FLAGS_NO_DECODING      128 This flag turns the video stream
+                                          decoder off, and dumps the raw
+                                          Isoc data from the camera into
+                                          the reading process. Useful to
+                                          developers, but not to users.
 
 framerate       This setting controls frame rate of the camera. This is
-                an approximate setting (in terms of "worst" ... "best")
-                because camera changes frame rate depending on amount
-                of light available. Setting 0 is slowest, 6 is fastest.
-                Beware - fast settings are very demanding and may not
-                work well with all video sizes. Be conservative.
+               an approximate setting (in terms of "worst" ... "best")
+               because camera changes frame rate depending on amount
+               of light available. Setting 0 is slowest, 6 is fastest.
+               Beware - fast settings are very demanding and may not
+               work well with all video sizes. Be conservative.
 
 hue_correction  This highly optional setting allows to adjust the
-                hue of the image in a way slightly different from
-                what usual "hue" control does. Both controls affect
-                YUV colorspace: regular "hue" control adjusts only
-                U component, and this "hue_correction" option similarly
-                adjusts only V component. However usually it is enough
-                to tweak only U or V to compensate for colored light or
-                color temperature; this option simply allows more
-                complicated correction when and if it is necessary.
+               hue of the image in a way slightly different from
+               what usual "hue" control does. Both controls affect
+               YUV colorspace: regular "hue" control adjusts only
+               U component, and this "hue_correction" option similarly
+               adjusts only V component. However usually it is enough
+               to tweak only U or V to compensate for colored light or
+               color temperature; this option simply allows more
+               complicated correction when and if it is necessary.
 
 init_brightness These settings specify _initial_ values which will be
 init_contrast   used to set up the camera. If your V4L application has
 init_color      its own controls to adjust the picture then these
 init_hue        controls will be used too. These options allow you to
-                preconfigure the camera when it gets connected, before
-                any V4L application connects to it. Good for webcams.
+               preconfigure the camera when it gets connected, before
+               any V4L application connects to it. Good for webcams.
 
 init_model2_rg  These initial settings alter color balance of the
 init_model2_rg2 camera on hardware level. All four settings may be used
@@ -258,47 +258,47 @@ init_model2_sat to tune the camera to specific lighting conditions. These
 init_model2_yb  settings only apply to Model 2 cameras.
 
 lighting        This option selects one of three hardware-defined
-                photosensitivity settings of the camera. 0=bright light,
-                1=Medium (default), 2=Low light. This setting affects
-                frame rate: the dimmer the lighting the lower the frame
-                rate (because longer exposition time is needed). The
-                Model 2 cameras allow values more than 2 for this option,
-                thus enabling extremely high sensitivity at cost of frame
-                rate, color saturation and imaging sensor noise.
+               photosensitivity settings of the camera. 0=bright light,
+               1=Medium (default), 2=Low light. This setting affects
+               frame rate: the dimmer the lighting the lower the frame
+               rate (because longer exposition time is needed). The
+               Model 2 cameras allow values more than 2 for this option,
+               thus enabling extremely high sensitivity at cost of frame
+               rate, color saturation and imaging sensor noise.
 
 sharpness       This option controls smoothing (noise reduction)
-                made by camera. Setting 0 is most smooth, setting 6
-                is most sharp. Be aware that CMOS sensor used in the
-                camera is pretty noisy, so if you choose 6 you will
-                be greeted with "snowy" image. Default is 4. Model 2
-                cameras do not support this feature.
+               made by camera. Setting 0 is most smooth, setting 6
+               is most sharp. Be aware that CMOS sensor used in the
+               camera is pretty noisy, so if you choose 6 you will
+               be greeted with "snowy" image. Default is 4. Model 2
+               cameras do not support this feature.
 
 size            This setting chooses one of several image sizes that are
-                supported by this driver. Cameras may support more, but
-                it's difficult to reverse-engineer all formats.
-                Following video sizes are supported:
-
-                size=0     128x96  (Model 1 only)
-                size=1     160x120
-                size=2     176x144
-                size=3     320x240 (Model 2 only)
-                size=4     352x240 (Model 2 only)
-                size=5     352x288
-                size=6     640x480 (Model 3 only)
-
-                The 352x288 is the native size of the Model 1 sensor
-                array, so it's the best resolution the camera can
-                yield. The best resolution of Model 2 is 176x144, and
-                larger images are produced by stretching the bitmap.
-                Model 3 has sensor with 640x480 grid, and it works too,
-                but the frame rate will be exceptionally low (1-2 FPS);
-                it may be still OK for some applications, like security.
-                Choose the image size you need. The smaller image can
-                support faster frame rate. Default is 352x288.
+               supported by this driver. Cameras may support more, but
+               it's difficult to reverse-engineer all formats.
+               Following video sizes are supported:
+
+               size=0     128x96  (Model 1 only)
+               size=1     160x120
+               size=2     176x144
+               size=3     320x240 (Model 2 only)
+               size=4     352x240 (Model 2 only)
+               size=5     352x288
+               size=6     640x480 (Model 3 only)
+
+               The 352x288 is the native size of the Model 1 sensor
+               array, so it's the best resolution the camera can
+               yield. The best resolution of Model 2 is 176x144, and
+               larger images are produced by stretching the bitmap.
+               Model 3 has sensor with 640x480 grid, and it works too,
+               but the frame rate will be exceptionally low (1-2 FPS);
+               it may be still OK for some applications, like security.
+               Choose the image size you need. The smaller image can
+               support faster frame rate. Default is 352x288.
 
 For more information and the Troubleshooting FAQ visit this URL:
 
-                http://www.linux-usb.org/ibmcam/
+               http://www.linux-usb.org/ibmcam/
 
 WHAT NEEDS TO BE DONE:
 
index 142741e3c578693c06d73cd3246ba391456271e1..79af610d4ba59175ebabcb3cb18c58dfc937d914 100644 (file)
@@ -81,7 +81,7 @@ MODULE PARAMETERS:
   TYPE: integer (Boolean)
   DEFAULT: 1
   DESC: Brightness is normally under automatic control and can't be set
-        manually by the video app. Set to 0 for manual control.
+       manually by the video app. Set to 0 for manual control.
 
   NAME: autogain
   TYPE: integer (Boolean)
@@ -97,13 +97,13 @@ MODULE PARAMETERS:
   TYPE: integer (0-6)
   DEFAULT: 3
   DESC: Sets the threshold for printing debug messages. The higher the value,
-        the more is printed. The levels are cumulative, and are as follows:
-          0=no debug messages
-          1=init/detection/unload and other significant messages
-          2=some warning messages
-          3=config/control function calls
-          4=most function calls and data parsing messages
-          5=highly repetitive mesgs
+       the more is printed. The levels are cumulative, and are as follows:
+         0=no debug messages
+         1=init/detection/unload and other significant messages
+         2=some warning messages
+         3=config/control function calls
+         4=most function calls and data parsing messages
+         5=highly repetitive mesgs
 
   NAME: snapshot
   TYPE: integer (Boolean)
@@ -116,24 +116,24 @@ MODULE PARAMETERS:
   TYPE: integer (1-4 for OV511, 1-31 for OV511+)
   DEFAULT: 1
   DESC: Number of cameras allowed to stream simultaneously on a single bus.
-        Values higher than 1 reduce the data rate of each camera, allowing two
-        or more to be used at once. If you have a complicated setup involving
-        both OV511 and OV511+ cameras, trial-and-error may be necessary for
-        finding the optimum setting.
+       Values higher than 1 reduce the data rate of each camera, allowing two
+       or more to be used at once. If you have a complicated setup involving
+       both OV511 and OV511+ cameras, trial-and-error may be necessary for
+       finding the optimum setting.
 
   NAME: compress
   TYPE: integer (Boolean)
   DEFAULT: 0
   DESC: Set this to 1 to turn on the camera's compression engine. This can
-        potentially increase the frame rate at the expense of quality, if you
-        have a fast CPU. You must load the proper compression module for your
-        camera before starting your application (ov511_decomp or ov518_decomp).
+       potentially increase the frame rate at the expense of quality, if you
+       have a fast CPU. You must load the proper compression module for your
+       camera before starting your application (ov511_decomp or ov518_decomp).
 
   NAME: testpat
   TYPE: integer (Boolean)
   DEFAULT: 0
   DESC: This configures the camera's sensor to transmit a colored test-pattern
-        instead of an image. This does not work correctly yet.
+       instead of an image. This does not work correctly yet.
 
   NAME: dumppix
   TYPE: integer (0-2)
index 142920bc011fb9120314182addc312ce57d8c0f8..1d20895b4354b99f2da591adac5027daec0253ff 100644 (file)
@@ -1,9 +1,9 @@
 
-                         SN9C10x PC Camera Controllers
-                                Driver for Linux
-                         =============================
+                        SN9C10x PC Camera Controllers
+                               Driver for Linux
+                        =============================
 
-                               - Documentation -
+                              - Documentation -
 
 
 Index
@@ -176,46 +176,46 @@ Name:           video_nr
 Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L2 minor mode number:
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 64 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                recognized camera and use auto for the first one and for every
-                other camera.
+               -1 = use next available
+                n = use minor number n
+               You can specify up to 64 cameras this way.
+               For example:
+               video_nr=-1,2,-1 would assign minor number 2 to the second
+               recognized camera and use auto for the first one and for every
+               other camera.
 Default:        -1
 -------------------------------------------------------------------------------
 Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]>
 Description:    Force the application to unmap previously mapped buffer memory
-                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-                all the applications support this feature. This parameter is
-                specific for each detected camera.
-                0 = do not force memory unmapping
-                1 = force memory unmapping (save memory)
+               before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+               all the applications support this feature. This parameter is
+               specific for each detected camera.
+               0 = do not force memory unmapping
+               1 = force memory unmapping (save memory)
 Default:        0
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
 Syntax:         <n[,...]>
 Description:    Timeout for a video frame in seconds. This parameter is
-                specific for each detected camera. This parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+               specific for each detected camera. This parameter can be
+               changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           debug
 Type:           ushort
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 3:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = more verbose messages
-                Level 3 is useful for testing only, when only one device
-                is used. It also shows some more informations about the
-                hardware being detected. This parameter can be changed at
-                runtime thanks to the /sys filesystem interface.
+               0 = none (use carefully)
+               1 = critical errors
+               2 = significant informations
+               3 = more verbose messages
+               Level 3 is useful for testing only, when only one device
+               is used. It also shows some more informations about the
+               hardware being detected. This parameter can be changed at
+               runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 
@@ -280,24 +280,24 @@ Byte #  Value         Description
 0x04    0xC4          Frame synchronisation pattern.
 0x05    0x96          Frame synchronisation pattern.
 0x06    0xXX          Unknown meaning. The exact value depends on the chip;
-                      possible values are 0x00, 0x01 and 0x20.
+                     possible values are 0x00, 0x01 and 0x20.
 0x07    0xXX          Variable value, whose bits are ff00uzzc, where ff is a
-                      frame counter, u is unknown, zz is a size indicator
-                      (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
-                      "compression enabled" (1 = yes, 0 = no).
+                     frame counter, u is unknown, zz is a size indicator
+                     (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
+                     "compression enabled" (1 = yes, 0 = no).
 0x08    0xXX          Brightness sum inside Auto-Exposure area (low-byte).
 0x09    0xXX          Brightness sum inside Auto-Exposure area (high-byte).
-                      For a pure white image, this number will be equal to 500
-                      times the area of the specified AE area. For images
-                      that are not pure white, the value scales down according
-                      to relative whiteness.
+                     For a pure white image, this number will be equal to 500
+                     times the area of the specified AE area. For images
+                     that are not pure white, the value scales down according
+                     to relative whiteness.
 0x0A    0xXX          Brightness sum outside Auto-Exposure area (low-byte).
 0x0B    0xXX          Brightness sum outside Auto-Exposure area (high-byte).
-                      For a pure white image, this number will be equal to 125
-                      times the area outside of the specified AE area. For
-                      images that are not pure white, the value scales down
-                      according to relative whiteness.
-                      according to relative whiteness.
+                     For a pure white image, this number will be equal to 125
+                     times the area outside of the specified AE area. For
+                     images that are not pure white, the value scales down
+                     according to relative whiteness.
+                     according to relative whiteness.
 
 The following bytes are used by the SN9C103 bridge only:
 
diff --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c
new file mode 100644 (file)
index 0000000..079b628
--- /dev/null
@@ -0,0 +1,192 @@
+/* Simple Video4Linux image grabber. */
+/*
+ *     Video4Linux Driver Test/Example Framegrabbing Program
+ *
+ *     Compile with:
+ *             gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
+ *      Use as:
+ *              v4lgrab >image.ppm
+ *
+ *     Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
+ *      Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
+ *      with minor modifications (Dave Forrest, drf5n@virginia.edu).
+ *
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+
+#include <linux/types.h>
+#include <linux/videodev.h>
+
+#define FILE "/dev/video0"
+
+/* Stole this from tvset.c */
+
+#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b)                   \
+{                                                                       \
+       switch (format)                                                 \
+       {                                                               \
+               case VIDEO_PALETTE_GREY:                                \
+                       switch (depth)                                  \
+                       {                                               \
+                               case 4:                                 \
+                               case 6:                                 \
+                               case 8:                                 \
+                                       (r) = (g) = (b) = (*buf++ << 8);\
+                                       break;                          \
+                                                                       \
+                               case 16:                                \
+                                       (r) = (g) = (b) =               \
+                                               *((unsigned short *) buf);      \
+                                       buf += 2;                       \
+                                       break;                          \
+                       }                                               \
+                       break;                                          \
+                                                                       \
+                                                                       \
+               case VIDEO_PALETTE_RGB565:                              \
+               {                                                       \
+                       unsigned short tmp = *(unsigned short *)buf;    \
+                       (r) = tmp&0xF800;                               \
+                       (g) = (tmp<<5)&0xFC00;                          \
+                       (b) = (tmp<<11)&0xF800;                         \
+                       buf += 2;                                       \
+               }                                                       \
+               break;                                                  \
+                                                                       \
+               case VIDEO_PALETTE_RGB555:                              \
+                       (r) = (buf[0]&0xF8)<<8;                         \
+                       (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8;    \
+                       (b) = ((buf[1] << 2 ) & 0xF8)<<8;               \
+                       buf += 2;                                       \
+                       break;                                          \
+                                                                       \
+               case VIDEO_PALETTE_RGB24:                               \
+                       (r) = buf[0] << 8; (g) = buf[1] << 8;           \
+                       (b) = buf[2] << 8;                              \
+                       buf += 3;                                       \
+                       break;                                          \
+                                                                       \
+               default:                                                \
+                       fprintf(stderr,                                 \
+                               "Format %d not yet supported\n",        \
+                               format);                                \
+       }                                                               \
+}
+
+int get_brightness_adj(unsigned char *image, long size, int *brightness) {
+  long i, tot = 0;
+  for (i=0;i<size*3;i++)
+    tot += image[i];
+  *brightness = (128 - tot/(size*3))/3;
+  return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
+}
+
+int main(int argc, char ** argv)
+{
+  int fd = open(FILE, O_RDONLY), f;
+  struct video_capability cap;
+  struct video_window win;
+  struct video_picture vpic;
+
+  unsigned char *buffer, *src;
+  int bpp = 24, r, g, b;
+  unsigned int i, src_depth;
+
+  if (fd < 0) {
+    perror(FILE);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
+    perror("VIDIOGCAP");
+    fprintf(stderr, "(" FILE " not a video4linux device?)\n");
+    close(fd);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
+    perror("VIDIOCGWIN");
+    close(fd);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
+    perror("VIDIOCGPICT");
+    close(fd);
+    exit(1);
+  }
+
+  if (cap.type & VID_TYPE_MONOCHROME) {
+    vpic.depth=8;
+    vpic.palette=VIDEO_PALETTE_GREY;    /* 8bit grey */
+    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+      vpic.depth=6;
+      if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+       vpic.depth=4;
+       if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+         fprintf(stderr, "Unable to find a supported capture format.\n");
+         close(fd);
+         exit(1);
+       }
+      }
+    }
+  } else {
+    vpic.depth=24;
+    vpic.palette=VIDEO_PALETTE_RGB24;
+
+    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+      vpic.palette=VIDEO_PALETTE_RGB565;
+      vpic.depth=16;
+
+      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+       vpic.palette=VIDEO_PALETTE_RGB555;
+       vpic.depth=15;
+
+       if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+         fprintf(stderr, "Unable to find a supported capture format.\n");
+         return -1;
+       }
+      }
+    }
+  }
+
+  buffer = malloc(win.width * win.height * bpp);
+  if (!buffer) {
+    fprintf(stderr, "Out of memory.\n");
+    exit(1);
+  }
+
+  do {
+    int newbright;
+    read(fd, buffer, win.width * win.height * bpp);
+    f = get_brightness_adj(buffer, win.width * win.height, &newbright);
+    if (f) {
+      vpic.brightness += (newbright << 8);
+      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+       perror("VIDIOSPICT");
+       break;
+      }
+    }
+  } while (f);
+
+  fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
+
+  src = buffer;
+
+  for (i = 0; i < win.width * win.height; i++) {
+    READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
+    fputc(r>>8, stdout);
+    fputc(g>>8, stdout);
+    fputc(b>>8, stdout);
+  }
+
+  close(fd);
+  return 0;
+}
index 3b704f2aae6dc9218df5f788b92f83818a3c1c9b..0d53ce774b01c75b26d5fb2aff1ce1e9098071de 100644 (file)
@@ -1,9 +1,9 @@
 
-                   W996[87]CF JPEG USB Dual Mode Camera Chip
-                     Driver for Linux 2.6 (basic version)
-                   =========================================
+                  W996[87]CF JPEG USB Dual Mode Camera Chip
+                    Driver for Linux 2.6 (basic version)
+                  =========================================
 
-                               - Documentation -
+                              - Documentation -
 
 
 Index
@@ -188,57 +188,57 @@ Name:            ovmod_load
 Type:            bool
 Syntax:          <0|1>
 Description:     Automatic 'ovcamchip' module loading: 0 disabled, 1 enabled.
-                 If enabled, 'insmod' searches for the required 'ovcamchip'
-                 module in the system, according to its configuration, and
-                 loads that module automatically. This action is performed as
-                 once soon as the 'w9968cf' module is loaded into memory.
+                If enabled, 'insmod' searches for the required 'ovcamchip'
+                module in the system, according to its configuration, and
+                loads that module automatically. This action is performed as
+                once soon as the 'w9968cf' module is loaded into memory.
 Default:         1
 Note:            The kernel must be compiled with the CONFIG_KMOD option
-                 enabled for the 'ovcamchip' module to be loaded and for
-                 this parameter to be present.
+                enabled for the 'ovcamchip' module to be loaded and for
+                this parameter to be present.
 -------------------------------------------------------------------------------
 Name:           simcams
 Type:           int
 Syntax:         <n>
 Description:    Number of cameras allowed to stream simultaneously.
-                n may vary from 0 to 32.
+               n may vary from 0 to 32.
 Default:        32
 -------------------------------------------------------------------------------
 Name:           video_nr
 Type:           int array (min = 0, max = 32)
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L minor mode number.
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 32 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                recognized camera and use auto for the first one and for every
-                other camera.
+               -1 = use next available
+                n = use minor number n
+               You can specify up to 32 cameras this way.
+               For example:
+               video_nr=-1,2,-1 would assign minor number 2 to the second
+               recognized camera and use auto for the first one and for every
+               other camera.
 Default:        -1
 -------------------------------------------------------------------------------
 Name:           packet_size
 Type:           int array (min = 0, max = 32)
 Syntax:         <n[,...]>
 Description:    Specify the maximum data payload size in bytes for alternate
-                settings, for each device. n is scaled between 63 and 1023.
+               settings, for each device. n is scaled between 63 and 1023.
 Default:        1023
 -------------------------------------------------------------------------------
 Name:           max_buffers
 Type:           int array (min = 0, max = 32)
 Syntax:         <n[,...]>
 Description:    For advanced users.
-                Specify the maximum number of video frame buffers to allocate
-                for each device, from 2 to 32.
+               Specify the maximum number of video frame buffers to allocate
+               for each device, from 2 to 32.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           double_buffer
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Hardware double buffering: 0 disabled, 1 enabled.
-                It should be enabled if you want smooth video output: if you
-                obtain out of sync. video, disable it, or try to
-                decrease the 'clockdiv' module parameter value.
+               It should be enabled if you want smooth video output: if you
+               obtain out of sync. video, disable it, or try to
+               decrease the 'clockdiv' module parameter value.
 Default:        1 for every device.
 -------------------------------------------------------------------------------
 Name:           clamping
@@ -251,9 +251,9 @@ Name:           filter_type
 Type:           int array (min = 0, max = 32)
 Syntax:         <0|1|2[,...]>
 Description:    Video filter type.
-                0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
-                The filter is used to reduce noise and aliasing artifacts
-                produced by the CCD or CMOS image sensor.
+               0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
+               The filter is used to reduce noise and aliasing artifacts
+               produced by the CCD or CMOS image sensor.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           largeview
@@ -266,9 +266,9 @@ Name:           upscaling
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Software scaling (for non-compressed video only):
-                0 disabled, 1 enabled.
-                Disable it if you have a slow CPU or you don't have enough
-                memory.
+               0 disabled, 1 enabled.
+               Disable it if you have a slow CPU or you don't have enough
+               memory.
 Default:        0 for every device.
 Note:           If 'w9968cf-vpp' is not present, this parameter is set to 0.
 -------------------------------------------------------------------------------
@@ -276,36 +276,36 @@ Name:           decompression
 Type:           int array (min = 0, max = 32)
 Syntax:         <0|1|2[,...]>
 Description:    Software video decompression:
-                0 = disables decompression
-                    (doesn't allow formats needing decompression).
-                1 = forces decompression
-                    (allows formats needing decompression only).
-                2 = allows any permitted formats.
-                Formats supporting (de)compressed video are YUV422P and
-                YUV420P/YUV420 in any resolutions where width and height are
-                multiples of 16.
+               0 = disables decompression
+                   (doesn't allow formats needing decompression).
+               1 = forces decompression
+                   (allows formats needing decompression only).
+               2 = allows any permitted formats.
+               Formats supporting (de)compressed video are YUV422P and
+               YUV420P/YUV420 in any resolutions where width and height are
+               multiples of 16.
 Default:        2 for every device.
 Note:           If 'w9968cf-vpp' is not present, forcing decompression is not
-                allowed; in this case this parameter is set to 2.
+               allowed; in this case this parameter is set to 2.
 -------------------------------------------------------------------------------
 Name:           force_palette
 Type:           int array (min = 0, max = 32)
 Syntax:         <0|9|10|13|15|8|7|1|6|3|4|5[,...]>
 Description:    Force picture palette.
-                In order:
-                 0 = Off - allows any of the following formats:
-                 9 = UYVY    16 bpp - Original video, compression disabled
-                10 = YUV420  12 bpp - Original video, compression enabled
-                13 = YUV422P 16 bpp - Original video, compression enabled
-                15 = YUV420P 12 bpp - Original video, compression enabled
-                 8 = YUVY    16 bpp - Software conversion from UYVY
-                 7 = YUV422  16 bpp - Software conversion from UYVY
-                 1 = GREY     8 bpp - Software conversion from UYVY
-                 6 = RGB555  16 bpp - Software conversion from UYVY
-                 3 = RGB565  16 bpp - Software conversion from UYVY
-                 4 = RGB24   24 bpp - Software conversion from UYVY
-                 5 = RGB32   32 bpp - Software conversion from UYVY
-                When not 0, this parameter will override 'decompression'.
+               In order:
+                0 = Off - allows any of the following formats:
+                9 = UYVY    16 bpp - Original video, compression disabled
+               10 = YUV420  12 bpp - Original video, compression enabled
+               13 = YUV422P 16 bpp - Original video, compression enabled
+               15 = YUV420P 12 bpp - Original video, compression enabled
+                8 = YUVY    16 bpp - Software conversion from UYVY
+                7 = YUV422  16 bpp - Software conversion from UYVY
+                1 = GREY     8 bpp - Software conversion from UYVY
+                6 = RGB555  16 bpp - Software conversion from UYVY
+                3 = RGB565  16 bpp - Software conversion from UYVY
+                4 = RGB24   24 bpp - Software conversion from UYVY
+                5 = RGB32   32 bpp - Software conversion from UYVY
+               When not 0, this parameter will override 'decompression'.
 Default:        0 for every device. Initial palette is 9 (UYVY).
 Note:           If 'w9968cf-vpp' is not present, this parameter is set to 9.
 -------------------------------------------------------------------------------
@@ -313,77 +313,77 @@ Name:           force_rgb
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Read RGB video data instead of BGR:
-                1 = use RGB component ordering.
-                0 = use BGR component ordering.
-                This parameter has effect when using RGBX palettes only.
+               1 = use RGB component ordering.
+               0 = use BGR component ordering.
+               This parameter has effect when using RGBX palettes only.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           autobright
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Image sensor automatically changes brightness:
-                0 = no, 1 = yes
+               0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           autoexp
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Image sensor automatically changes exposure:
-                0 = no, 1 = yes
+               0 = no, 1 = yes
 Default:        1 for every device.
 -------------------------------------------------------------------------------
 Name:           lightfreq
 Type:           int array (min = 0, max = 32)
 Syntax:         <50|60[,...]>
 Description:    Light frequency in Hz:
-                50 for European and Asian lighting, 60 for American lighting.
+               50 for European and Asian lighting, 60 for American lighting.
 Default:        50 for every device.
 -------------------------------------------------------------------------------
 Name:           bandingfilter
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Banding filter to reduce effects of fluorescent
-                lighting:
-                0 disabled, 1 enabled.
-                This filter tries to reduce the pattern of horizontal
-                light/dark bands caused by some (usually fluorescent) lighting.
+               lighting:
+               0 disabled, 1 enabled.
+               This filter tries to reduce the pattern of horizontal
+               light/dark bands caused by some (usually fluorescent) lighting.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           clockdiv
 Type:           int array (min = 0, max = 32)
 Syntax:         <-1|n[,...]>
 Description:    Force pixel clock divisor to a specific value (for experts):
-                n may vary from 0 to 127.
-                -1 for automatic value.
-                See also the 'double_buffer' module parameter.
+               n may vary from 0 to 127.
+               -1 for automatic value.
+               See also the 'double_buffer' module parameter.
 Default:        -1 for every device.
 -------------------------------------------------------------------------------
 Name:           backlight
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Objects are lit from behind:
-                0 = no, 1 = yes
+               0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           mirror
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Reverse image horizontally:
-                0 = no, 1 = yes
+               0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           monochrome
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    The image sensor is monochrome:
-                0 = no, 1 = yes
+               0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           brightness
 Type:           long array (min = 0, max = 32)
 Syntax:         <n[,...]>
 Description:    Set picture brightness (0-65535).
-                This parameter has no effect if 'autobright' is enabled.
+               This parameter has no effect if 'autobright' is enabled.
 Default:        31000 for every device.
 -------------------------------------------------------------------------------
 Name:           hue
@@ -414,23 +414,23 @@ Name:           debug
 Type:           int
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 6:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = configuration or general messages
-                4 = warnings
-                5 = called functions
-                6 = function internals
-                Level 5 and 6 are useful for testing only, when only one
-                device is used.
+               0 = none (use carefully)
+               1 = critical errors
+               2 = significant informations
+               3 = configuration or general messages
+               4 = warnings
+               5 = called functions
+               6 = function internals
+               Level 5 and 6 are useful for testing only, when only one
+               device is used.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           specific_debug
 Type:           bool
 Syntax:         <0|1>
 Description:    Enable or disable specific debugging messages:
-                0 = print messages concerning every level <= 'debug' level.
-                1 = print messages concerning the level indicated by 'debug'.
+               0 = print messages concerning every level <= 'debug' level.
+               1 = print messages concerning the level indicated by 'debug'.
 Default:        0
 -------------------------------------------------------------------------------
 
index f55262c6733b6c75eba2da87405462288a53e485..f406f5e800464dcd11315459575ad5fb141a752f 100644 (file)
@@ -1,9 +1,9 @@
 
-                    ZC0301 Image Processor and Control Chip
-                                Driver for Linux
-                    =======================================
+             ZC0301 and ZC0301P Image Processor and Control Chip
+                               Driver for Linux
+             ===================================================
 
-                               - Documentation -
+                              - Documentation -
 
 
 Index
@@ -51,13 +51,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 4. Overview and features
 ========================
-This driver supports the video interface of the devices mounting the ZC0301
-Image Processor and Control Chip.
+This driver supports the video interface of the devices mounting the ZC0301 or
+ZC0301P Image Processors and Control Chips.
 
 The driver relies on the Video4Linux2 and USB core modules. It has been
 designed to run properly on SMP systems as well.
 
-The latest version of the ZC0301 driver can be found at the following URL:
+The latest version of the ZC0301[P] driver can be found at the following URL:
 http://www.linux-projects.org/
 
 Some of the features of the driver are:
@@ -117,7 +117,7 @@ supported by the USB Audio driver thanks to the ALSA API:
 
 And finally:
 
-       # USB Multimedia devices
+       # V4L USB devices
        #
        CONFIG_USB_ZC0301=m
 
@@ -146,46 +146,46 @@ Name:           video_nr
 Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L2 minor mode number:
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 64 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                registered camera and use auto for the first one and for every
-                other camera.
+               -1 = use next available
+                n = use minor number n
+               You can specify up to 64 cameras this way.
+               For example:
+               video_nr=-1,2,-1 would assign minor number 2 to the second
+               registered camera and use auto for the first one and for every
+               other camera.
 Default:        -1
 -------------------------------------------------------------------------------
 Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]>
 Description:    Force the application to unmap previously mapped buffer memory
-                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-                all the applications support this feature. This parameter is
-                specific for each detected camera.
-                0 = do not force memory unmapping
-                1 = force memory unmapping (save memory)
+               before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+               all the applications support this feature. This parameter is
+               specific for each detected camera.
+               0 = do not force memory unmapping
+               1 = force memory unmapping (save memory)
 Default:        0
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
 Syntax:         <n[,...]>
 Description:    Timeout for a video frame in seconds. This parameter is
-                specific for each detected camera. This parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+               specific for each detected camera. This parameter can be
+               changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           debug
 Type:           ushort
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 3:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = more verbose messages
-                Level 3 is useful for testing only, when only one device
-                is used at the same time. It also shows some more informations
-                about the hardware being detected. This module parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+               0 = none (use carefully)
+               1 = critical errors
+               2 = significant informations
+               3 = more verbose messages
+               Level 3 is useful for testing only, when only one device
+               is used at the same time. It also shows some more informations
+               about the hardware being detected. This module parameter can be
+               changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 
@@ -204,11 +204,25 @@ Vendor ID  Product ID
 0x041e     0x4017
 0x041e     0x401c
 0x041e     0x401e
+0x041e     0x401f
+0x041e     0x4022
 0x041e     0x4034
 0x041e     0x4035
+0x041e     0x4036
+0x041e     0x403a
+0x0458     0x7007
+0x0458     0x700C
+0x0458     0x700f
+0x046d     0x08ae
+0x055f     0xd003
+0x055f     0xd004
 0x046d     0x08ae
 0x0ac8     0x0301
+0x0ac8     0x301b
+0x0ac8     0x303b
+0x10fd     0x0128
 0x10fd     0x8050
+0x10fd     0x804e
 
 The list above does not imply that all those devices work with this driver: up
 until now only the ones that mount the following image sensors are supported;
@@ -217,6 +231,7 @@ kernel messages will always tell you whether this is the case:
 Model       Manufacturer
 -----       ------------
 PAS202BCB   PixArt Imaging, Inc.
+PB-0330     Photobit Corporation
 
 
 9. Notes for V4L2 application developers
@@ -250,5 +265,6 @@ the fingerprint is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
   been taken from the documentation of the ZC030x Video4Linux1 driver written
   by Andrew Birkett <andy@nobugs.org>;
 - The initialization values of the ZC0301 controller connected to the PAS202BCB
-  image sensor have been taken from the SPCA5XX driver maintained by
-  Michel Xhaard <mxhaard@magic.fr>.
+  and PB-0330 image sensors have been taken from the SPCA5XX driver maintained
+  by Michel Xhaard <mxhaard@magic.fr>;
+- Stanislav Lechev donated one camera.
index 344d83aae3ec3b5d6d7b4e9e41dee2f47d59e79f..583d151b7486a3d1911cba4fbe149242d2c0b98b 100644 (file)
@@ -25,7 +25,7 @@ config VIDEO_DEV
          module will be called videodev.
 
 config VIDEO_V4L1
-       boolean "Enable Video For Linux API 1 (DEPRECATED)"
+       bool "Enable Video For Linux API 1 (DEPRECATED)"
        depends on VIDEO_DEV
        select VIDEO_V4L1_COMPAT
        default y
@@ -36,7 +36,7 @@ config VIDEO_V4L1
          If you are unsure as to whether this is required, answer Y.
 
 config VIDEO_V4L1_COMPAT
-       boolean "Enable Video For Linux API 1 compatible Layer"
+       bool "Enable Video For Linux API 1 compatible Layer"
        depends on VIDEO_DEV
        default y
        ---help---
@@ -82,6 +82,9 @@ config VIDEO_IR
 config VIDEO_TVEEPROM
        tristate
 
+config VIDEO_CX2341X
+       tristate
+
 config USB_DABUSB
        tristate "DABUSB driver"
        depends on USB
index 61b89617a9671589a3d83cacc24e69a44faca9f1..8e744823064382309cbf35a20cfbb41c30842b7e 100644 (file)
@@ -1,5 +1,5 @@
 saa7146-objs    := saa7146_i2c.o saa7146_core.o
-saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
+saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
 ir-common-objs  := ir-functions.o ir-keymaps.o
 
 obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
index 397cff8b345b2afc2b77b53d61f7d94c0658476f..8eaa88fd8b9b7ab3cde535b7ce4499b6c4fe6ffd 100644 (file)
@@ -269,4 +269,3 @@ EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
  * c-basic-offset: 8
  * End:
  */
-
index a294d5c2c73f0748fd096b8c13268cca169a02c4..ca98d94789476f7c7454dc3a034f2b752e68b990 100644 (file)
@@ -618,7 +618,7 @@ IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = {
 
 EXPORT_SYMBOL_GPL(ir_codes_em_terratec);
 
-IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
+IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = {
        [ 0x3a ] = KEY_0,
        [ 0x31 ] = KEY_1,
        [ 0x32 ] = KEY_2,
@@ -670,7 +670,7 @@ IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
        [ 0x27 ] = KEY_RECORD,
 };
 
-EXPORT_SYMBOL_GPL(ir_codes_em_pinnacle_usb);
+EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey);
 
 IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
        [ 0x0f ] = KEY_0,
@@ -1263,34 +1263,51 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
        [ 0x0f ] = KEY_9,
 
        [ 0x00 ] = KEY_POWER,
-       [ 0x02 ] = KEY_TUNER,           /* TV/FM */
-       [ 0x1e ] = KEY_VIDEO,
+       [ 0x1b ] = KEY_AUDIO,           /* Audio Source */
+       [ 0x02 ] = KEY_TUNER,           /* TV/FM, not on Y0400052 */
+       [ 0x1e ] = KEY_VIDEO,           /* Video Source */
+       [ 0x16 ] = KEY_INFO,            /* Display information */
        [ 0x04 ] = KEY_VOLUMEUP,
        [ 0x08 ] = KEY_VOLUMEDOWN,
        [ 0x0c ] = KEY_CHANNELUP,
        [ 0x10 ] = KEY_CHANNELDOWN,
        [ 0x03 ] = KEY_ZOOM,            /* fullscreen */
-       [ 0x1f ] = KEY_SUBTITLE,                /* closed caption/teletext */
+       [ 0x1f ] = KEY_TEXT,            /* closed caption/teletext */
        [ 0x20 ] = KEY_SLEEP,
+       [ 0x29 ] = KEY_CLEAR,           /* boss key */
        [ 0x14 ] = KEY_MUTE,
        [ 0x2b ] = KEY_RED,
        [ 0x2c ] = KEY_GREEN,
        [ 0x2d ] = KEY_YELLOW,
        [ 0x2e ] = KEY_BLUE,
-       [ 0x18 ] = KEY_KPPLUS,          /* fine tune + */
-       [ 0x19 ] = KEY_KPMINUS,         /* fine tune - */
+       [ 0x18 ] = KEY_KPPLUS,          /* fine tune + , not on Y040052 */
+       [ 0x19 ] = KEY_KPMINUS,         /* fine tune - , not on Y040052 */
+       [ 0x2a ] = KEY_MEDIA,           /* PIP (Picture in picture */
        [ 0x21 ] = KEY_DOT,
        [ 0x13 ] = KEY_ENTER,
-       [ 0x22 ] = KEY_BACK,
+       [ 0x11 ] = KEY_LAST,            /* Recall (last channel */
+       [ 0x22 ] = KEY_PREVIOUS,
        [ 0x23 ] = KEY_PLAYPAUSE,
        [ 0x24 ] = KEY_NEXT,
+       [ 0x25 ] = KEY_ARCHIVE,       /* Time Shifting */
        [ 0x26 ] = KEY_STOP,
-       [ 0x27 ] = KEY_RECORD
+       [ 0x27 ] = KEY_RECORD,
+       [ 0x28 ] = KEY_SAVE,          /* Screenshot */
+       [ 0x2f ] = KEY_MENU,
+       [ 0x30 ] = KEY_CANCEL,
+       [ 0x31 ] = KEY_CHANNEL,       /* Channel Surf */
+       [ 0x32 ] = KEY_SUBTITLE,
+       [ 0x33 ] = KEY_LANGUAGE,
+       [ 0x34 ] = KEY_REWIND,
+       [ 0x35 ] = KEY_FASTFORWARD,
+       [ 0x36 ] = KEY_TV,
+       [ 0x37 ] = KEY_RADIO,         /* FM */
+       [ 0x38 ] = KEY_DVD
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_winfast);
 
-IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
+IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = {
        [ 0x59 ] = KEY_MUTE,
        [ 0x4a ] = KEY_POWER,
 
@@ -1348,7 +1365,7 @@ IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
        [ 0x0a ] = KEY_BACKSPACE,
 };
 
-EXPORT_SYMBOL_GPL(ir_codes_pinnacle);
+EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color);
 
 /* Hauppauge: the newer, gray remotes (seems there are multiple
  * slightly different versions), shipped with cx88+ivtv cards.
@@ -1413,3 +1430,46 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
 
 EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new);
 
+IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = {
+       [ 0x1d ] = KEY_SWITCHVIDEOMODE, /* switch inputs */
+       [ 0x2a ] = KEY_FRONT,
+
+       [ 0x3e ] = KEY_1,
+       [ 0x02 ] = KEY_2,
+       [ 0x06 ] = KEY_3,
+       [ 0x0a ] = KEY_4,
+       [ 0x0e ] = KEY_5,
+       [ 0x12 ] = KEY_6,
+       [ 0x16 ] = KEY_7,
+       [ 0x1a ] = KEY_8,
+       [ 0x1e ] = KEY_9,
+       [ 0x3a ] = KEY_0,
+       [ 0x22 ] = KEY_NUMLOCK,         /* -/-- */
+       [ 0x20 ] = KEY_REFRESH,
+
+       [ 0x03 ] = KEY_BRIGHTNESSDOWN,
+       [ 0x28 ] = KEY_AUDIO,
+       [ 0x3c ] = KEY_UP,
+       [ 0x3f ] = KEY_LEFT,
+       [ 0x2e ] = KEY_MUTE,
+       [ 0x3b ] = KEY_RIGHT,
+       [ 0x00 ] = KEY_DOWN,
+       [ 0x07 ] = KEY_BRIGHTNESSUP,
+       [ 0x2c ] = KEY_TEXT,
+
+       [ 0x37 ] = KEY_RECORD,
+       [ 0x17 ] = KEY_PLAY,
+       [ 0x13 ] = KEY_PAUSE,
+       [ 0x26 ] = KEY_STOP,
+       [ 0x18 ] = KEY_FASTFORWARD,
+       [ 0x14 ] = KEY_REWIND,
+       [ 0x33 ] = KEY_ZOOM,
+       [ 0x32 ] = KEY_KEYBOARD,
+       [ 0x30 ] = KEY_GOTO,            /* Pointing arrow */
+       [ 0x36 ] = KEY_MACRO,           /* Maximize/Minimize (yellow) */
+       [ 0x0b ] = KEY_RADIO,
+       [ 0x10 ] = KEY_POWER,
+
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_npgtech);
index 523ab3851c7b8ad71609a4df77104c29bbd099be..0027acc5b8e988b2a271ae79d1a90a96acbbd5d8 100644 (file)
@@ -501,6 +501,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_vv_init);
 
 int saa7146_vv_release(struct saa7146_dev* dev)
 {
@@ -515,6 +516,7 @@ int saa7146_vv_release(struct saa7146_dev* dev)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_vv_release);
 
 int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
                            char *name, int type)
@@ -553,6 +555,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
        *vid = vfd;
        return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_register_device);
 
 int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
 {
@@ -571,6 +574,7 @@ int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_unregister_device);
 
 static int __init saa7146_vv_init_module(void)
 {
index 33bec8a6843b49bdc05ec9345326bad23a316a11..2092e6c33dd289674a51b3c58a2389cb3c77ad4f 100644 (file)
@@ -641,6 +641,7 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sy
        vv->current_hps_source = source;
        vv->current_hps_sync = sync;
 }
+EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
 
 int saa7146_enable_overlay(struct saa7146_fh *fh)
 {
index e7079d1bd5371b19836788ec9064ed9c05a8d151..8393d472d3b81acced0acf7848cac92021ae85ef 100644 (file)
@@ -318,6 +318,7 @@ int saa7146_start_preview(struct saa7146_fh *fh)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_start_preview);
 
 int saa7146_stop_preview(struct saa7146_fh *fh)
 {
@@ -352,6 +353,7 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_stop_preview);
 
 static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
 {
diff --git a/drivers/media/common/saa7146_vv_ksyms.c b/drivers/media/common/saa7146_vv_ksyms.c
deleted file mode 100644 (file)
index 62226eb..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <linux/module.h>
-#include <media/saa7146_vv.h>
-
-EXPORT_SYMBOL_GPL(saa7146_start_preview);
-EXPORT_SYMBOL_GPL(saa7146_stop_preview);
-
-EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
-EXPORT_SYMBOL_GPL(saa7146_register_device);
-EXPORT_SYMBOL_GPL(saa7146_unregister_device);
-
-EXPORT_SYMBOL_GPL(saa7146_vv_init);
-EXPORT_SYMBOL_GPL(saa7146_vv_release);
index 9c7f122826e0089d9931402be70ddedf18c2e436..3be87c72e37b7f6bf13053f3db75a0fd9a4229af 100644 (file)
@@ -14,6 +14,7 @@
 #include "stv0297.h"
 #include "mt312.h"
 #include "lgdt330x.h"
+#include "lg_h06xf.h"
 #include "dvb-pll.h"
 
 /* lnb control */
@@ -166,11 +167,12 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate,
        return 0;
 }
 
-static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
+static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        u8 buf[4];
        u32 div;
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+       struct flexcop_device *fc = fe->dvb->priv;
 
        div = params->frequency / 125;
 
@@ -181,8 +183,11 @@ static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter
 
        if (params->frequency < 1500000) buf[3] |= 0x10;
 
-       if (i2c_transfer(i2c, &msg, 1) != 1)
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
                return -EIO;
+       }
        return 0;
 }
 
@@ -241,7 +246,6 @@ static struct stv0299_config samsung_tbmu24112_config = {
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 100,
        .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
-       .pll_set = samsung_tbmu24112_pll_set,
 };
 
 /* dvb-t mt352 */
@@ -264,11 +268,14 @@ static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
 {
        u32 div;
        unsigned char bs = 0;
 
+       if (buf_len < 5)
+               return -EINVAL;
+
        #define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
        div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
@@ -276,19 +283,18 @@ static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_front
        if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
        if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
 
-       pllbuf[0] = 0xc2; /* Note: non-linux standard PLL i2c address */
+       pllbuf[0] = 0x61;
        pllbuf[1] = div >> 8;
        pllbuf[2] = div & 0xff;
        pllbuf[3] = 0xcc;
        pllbuf[4] = bs;
 
-       return 0;
+       return 5;
 }
 
 static struct mt352_config samsung_tdtc9251dh0_config = {
        .demod_address = 0x0f,
        .demod_init    = samsung_tdtc9251dh0_demod_init,
-       .pll_set       = samsung_tdtc9251dh0_pll_set,
 };
 
 static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
@@ -297,56 +303,21 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
        return request_firmware(fw, name, fc->dev);
 }
 
-static int lgdt3303_pll_set(struct dvb_frontend* fe,
-                           struct dvb_frontend_parameters* params)
+static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct flexcop_device *fc = fe->dvb->priv;
-       u8 buf[4];
-       struct i2c_msg msg =
-               { .addr = 0x61, .flags = 0, .buf = buf, .len = 4 };
-       int err;
-
-       dvb_pll_configure(&dvb_pll_tdvs_tua6034,buf, params->frequency, 0);
-       dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-                       __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
-       if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
-               printk(KERN_WARNING "lgdt3303: %s error "
-                          "(addr %02x <- %02x, err = %i)\n",
-                          __FUNCTION__, buf[0], buf[1], err);
-               if (err < 0)
-                       return err;
-               else
-                       return -EREMOTEIO;
-       }
-
-       buf[0] = 0x86 | 0x18;
-       buf[1] = 0x50;
-       msg.len = 2;
-       if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
-               printk(KERN_WARNING "lgdt3303: %s error "
-                          "(addr %02x <- %02x, err = %i)\n",
-                          __FUNCTION__, buf[0], buf[1], err);
-               if (err < 0)
-                       return err;
-               else
-                       return -EREMOTEIO;
-       }
-
-       return 0;
+       return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
 }
 
 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
        .demod_address       = 0x59,
        .demod_chip          = LGDT3303,
        .serial_mpeg         = 0x04,
-       .pll_set             = lgdt3303_pll_set,
        .clock_polarity_flip = 1,
 };
 
 static struct nxt200x_config samsung_tbmv_config = {
        .demod_address    = 0x0a,
-       .pll_address      = 0xc2,
-       .pll_desc         = &dvb_pll_samsung_tbmv,
 };
 
 static struct bcm3510_config air2pc_atsc_first_gen_config = {
@@ -354,7 +325,7 @@ static struct bcm3510_config air2pc_atsc_first_gen_config = {
        .request_firmware = flexcop_fe_request_firmware,
 };
 
-static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        u8 buf[4];
        u32 div;
@@ -371,6 +342,8 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d
        if (params->frequency < 1550000)
                buf[3] |= 0x02;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -379,9 +352,52 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d
 static struct mt312_config skystar23_samsung_tbdu18132_config = {
 
        .demod_address = 0x0e,
-       .pll_set = skystar23_samsung_tbdu18132_pll_set,
 };
 
+static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
+                                              struct dvb_frontend_parameters *fep)
+{
+       struct flexcop_device *fc = fe->dvb->priv;
+       u8 buf[4];
+       u16 div;
+       int ret;
+
+/*  62.5 kHz * 10 */
+#define REF_FREQ    625
+#define FREQ_OFFSET 36125
+
+       div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10)  / REF_FREQ; // 4 MHz = 4000 KHz
+
+       buf[0] = (u8)( div >> 8) & 0x7f;
+       buf[1] = (u8)        div & 0xff;
+
+/* F(osc) = N * Reference Freq. (62.5 kHz)
+ * byte 2 :  0 N14 N13 N12 N11 N10 N9  N8
+ * byte 3 : N7 N6  N5  N4  N3  N2  N1  N0
+ * byte 4 : 1  *   *   AGD R3  R2  R1  R0
+ * byte 5 : C1 *   RE  RTS BS4 BS3 BS2 BS1
+ * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
+       buf[2] = 0x95;
+
+// Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
+//  47 - 153   0  *  0   0   0   0   0   1   0x01
+// 153 - 430   0  *  0   0   0   0   1   0   0x02
+// 430 - 822   0  *  0   0   1   0   0   0   0x08
+// 822 - 862   1  *  0   0   1   0   0   0   0x88
+
+            if (fep->frequency <= 153000000) buf[3] = 0x01;
+       else if (fep->frequency <= 430000000) buf[3] = 0x02;
+       else if (fep->frequency <= 822000000) buf[3] = 0x08;
+       else buf[3] = 0x88;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
+       ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3);
+       deb_tuner("tuner write returned: %d\n",ret);
+
+       return 0;
+}
 
 static u8 alps_tdee4_stv0297_inittab[] = {
        0x80, 0x01,
@@ -490,7 +506,9 @@ int flexcop_frontend_init(struct flexcop_device *fc)
 
        /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
        if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
-               ops = fc->fe->ops;
+               ops = &fc->fe->ops;
+
+               ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
 
                ops->set_voltage = flexcop_set_voltage;
 
@@ -503,16 +521,19 @@ int flexcop_frontend_init(struct flexcop_device *fc)
        /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
        if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
                fc->dev_type          = FC_AIR_DVB;
+               fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
                info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
        } else
        /* try the air atsc 2nd generation (nxt2002) */
        if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type          = FC_AIR_ATSC2;
+               dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
                info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
        } else
        /* try the air atsc 3nd generation (lgdt3303) */
        if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type          = FC_AIR_ATSC3;
+               fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
                info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
        } else
        /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
@@ -523,11 +544,14 @@ int flexcop_frontend_init(struct flexcop_device *fc)
        /* try the cable dvb (stv0297) */
        if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type                        = FC_CABLE;
+               fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
                info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
        } else
        /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
        if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
-               ops = fc->fe->ops;
+               ops = &fc->fe->ops;
+
+               ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
 
                ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
                ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
@@ -547,7 +571,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
        } else {
                if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
                        err("frontend registration failed!");
-                       ops = fc->fe->ops;
+                       ops = &fc->fe->ops;
                        if (ops->release != NULL)
                                ops->release(fc->fe);
                        fc->fe = NULL;
index 9bc40bdcc282e2bd1d25a79e6275aaab0e3ec780..f04041702191e7eb303f0920820f038756ee5d75 100644 (file)
@@ -242,19 +242,16 @@ static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci)
        if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0)
                return ret;
 
-       if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0)
-               goto dma1_free;
+       if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) {
+               flexcop_dma_free(&fc_pci->dma[0]);
+               return ret;
+       }
 
        flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
        flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO   | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
 
        fc_pci->init_state |= FC_PCI_DMA_INIT;
 
-       goto success;
-dma1_free:
-       flexcop_dma_free(&fc_pci->dma[0]);
-
-success:
        return ret;
 }
 
@@ -303,7 +300,7 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
        spin_lock_init(&fc_pci->irq_lock);
 
        fc_pci->init_state |= FC_PCI_INIT;
-       goto success;
+       return ret;
 
 err_pci_iounmap:
        pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
@@ -312,8 +309,6 @@ err_pci_release_regions:
        pci_release_regions(fc_pci->pdev);
 err_pci_disable_device:
        pci_disable_device(fc_pci->pdev);
-
-success:
        return ret;
 }
 
@@ -378,14 +373,14 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
        INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci);
 
-       goto success;
+       return ret;
+
 err_fc_exit:
        flexcop_device_exit(fc);
 err_pci_exit:
        flexcop_pci_exit(fc_pci);
 err_kfree:
        flexcop_device_kfree(fc);
-success:
        return ret;
 }
 
index 06ec9fff0ec1e5f5d3293685e5f49d9c73a71421..515954f96c9a6afa11eb5e708963216590ee5bdb 100644 (file)
@@ -433,11 +433,10 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
        flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS);
        flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1);
 
-       ret = 0;
-       goto success;
+       return 0;
+
 urb_error:
        flexcop_usb_transfer_exit(fc_usb);
-success:
        return ret;
 }
 
@@ -515,15 +514,14 @@ static int flexcop_usb_probe(struct usb_interface *intf,
                goto err_fc_exit;
 
        info("%s successfully initialized and connected.",DRIVER_NAME);
-       ret = 0;
-       goto success;
+       return 0;
+
 err_fc_exit:
        flexcop_device_exit(fc);
 err_usb_exit:
        flexcop_usb_exit(fc_usb);
 err_kfree:
        flexcop_device_kfree(fc);
-success:
        return ret;
 }
 
index 56ba52470676821070a88050b43c35d634f3d209..29ec4183118e80f744aed424dc1d1715b1b9aeef 100644 (file)
@@ -67,7 +67,7 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 static int flexcop_dvb_init(struct flexcop_device *fc)
 {
        int ret;
-       if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner)) < 0) {
+       if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) {
                err("error registering DVB adapter");
                return ret;
        }
@@ -116,7 +116,7 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
        dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
 
        fc->init_state |= FC_STATE_DVB_INIT;
-       goto success;
+       return 0;
 
 err_connect_frontend:
        fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
@@ -129,9 +129,6 @@ err_dmx_dev:
 err_dmx:
        dvb_unregister_adapter(&fc->dvb_adapter);
        return ret;
-
-success:
-       return 0;
 }
 
 static void flexcop_dvb_exit(struct flexcop_device *fc)
@@ -279,11 +276,10 @@ int flexcop_device_initialize(struct flexcop_device *fc)
 
        flexcop_device_name(fc,"initialization of","complete");
 
-       ret = 0;
-       goto success;
+       return 0;
+
 error:
        flexcop_device_exit(fc);
-success:
        return ret;
 }
 EXPORT_SYMBOL(flexcop_device_initialize);
index 5500f8a0ffe2c6fa1f0013bbc8dc8ccb810f93dd..761fa6e7d76222195638ca7666e027fb72e57b54 100644 (file)
@@ -63,8 +63,6 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off).");
 int bt878_num;
 struct bt878 bt878[BT878_MAX];
 
-EXPORT_SYMBOL(bt878_debug);
-EXPORT_SYMBOL(bt878_verbose);
 EXPORT_SYMBOL(bt878_num);
 EXPORT_SYMBOL(bt878);
 
@@ -393,7 +391,9 @@ static struct cards card_list[] __devinitdata = {
        { 0x07711461, BTTV_BOARD_AVDVBT_771,                    "AVermedia AverTV DVB-T 771" },
        { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,               "DViCO FusionHDTV DVB-T Lite" },
        { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,       "DViCO FusionHDTV 5 Lite" },
-       { 0x20007063, BTTV_BOARD_PC_HDTV,                       "pcHDTV HD-2000 TV"},
+       { 0x20007063, BTTV_BOARD_PC_HDTV,                       "pcHDTV HD-2000 TV" },
+       { 0x00261822, BTTV_BOARD_TWINHAN_DST,                   "DNTV Live! Mini" },
+
        { 0, -1, NULL }
 };
 
@@ -417,6 +417,11 @@ static int __devinit bt878_probe(struct pci_dev *dev,
 
        printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
               bt878_num);
+       if (bt878_num >= BT878_MAX) {
+               printk(KERN_ERR "bt878: Too many devices inserted\n");
+               result = -ENOMEM;
+               goto fail0;
+       }
        if (pci_enable_device(dev))
                return -EIO;
 
index 1cfa5e5035d830f9ca66d1679efa149df2a065ec..d687a14ec0a7aa6b3b72d9fd322d9508cab8c2da 100644 (file)
@@ -38,6 +38,10 @@ static unsigned int dst_addons;
 module_param(dst_addons, int, 0644);
 MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
 
+static unsigned int dst_algo;
+module_param(dst_algo, int, 0644);
+MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
+
 #define HAS_LOCK               1
 #define ATTEMPT_TUNE           2
 #define HAS_POWER              4
@@ -47,20 +51,24 @@ MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
 #define DST_INFO               2
 #define DST_DEBUG              3
 
-#define dprintk(x, y, z, format, arg...) do {                                          \
-       if (z) {                                                                        \
-               if      ((x > DST_ERROR) && (x > y))                                    \
-                       printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg);      \
-               else if ((x > DST_NOTICE) && (x > y))                                   \
-                       printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg);   \
-               else if ((x > DST_INFO) && (x > y))                                     \
-                       printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg);     \
-               else if ((x > DST_DEBUG) && (x > y))                                    \
-                       printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg);    \
-       } else {                                                                        \
-               if (x > y)                                                              \
-                       printk(format, ##arg);                                          \
-       }                                                                               \
+#define dprintk(x, y, z, format, arg...) do {                          \
+       if (z) {                                                        \
+               if      ((x > DST_ERROR) && (x > y))                    \
+                       printk(KERN_ERR "dst(%d) %s: " format "\n",     \
+                               state->bt->nr, __func__ , ##arg);       \
+               else if ((x > DST_NOTICE) && (x > y))                   \
+                       printk(KERN_NOTICE "dst(%d) %s: " format "\n",  \
+                               state->bt->nr, __func__ , ##arg);       \
+               else if ((x > DST_INFO) && (x > y))                     \
+                       printk(KERN_INFO "dst(%d) %s: " format "\n",    \
+                               state->bt->nr, __func__ , ##arg);       \
+               else if ((x > DST_DEBUG) && (x > y))                    \
+                       printk(KERN_DEBUG "dst(%d) %s: " format "\n",   \
+                               state->bt->nr,  __func__ , ##arg);      \
+       } else {                                                        \
+               if (x > y)                                              \
+                       printk(format, ##arg);                          \
+       }                                                               \
 } while(0)
 
 
@@ -110,7 +118,7 @@ int dst_gpio_inb(struct dst_state *state, u8 *result)
 
        *result = 0;
        if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
-               dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err);
+               dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err);
                return -EREMOTEIO;
        }
        *result = (u8) rd_packet.rd.value;
@@ -363,6 +371,17 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
                state->tx_tuna[2] = (freq >> 16) & 0xff;
                state->tx_tuna[3] = (freq >> 8) & 0xff;
                state->tx_tuna[4] = (u8) freq;
+       } else if (state->dst_type == DST_TYPE_IS_ATSC) {
+               freq = freq / 1000;
+               if (freq < 51000 || freq > 858000)
+                       return -EINVAL;
+               state->tx_tuna[2] = (freq >> 16) & 0xff;
+               state->tx_tuna[3] = (freq >>  8) & 0xff;
+               state->tx_tuna[4] = (u8) freq;
+               state->tx_tuna[5] = 0x00;               /*      ATSC    */
+               state->tx_tuna[6] = 0x00;
+               if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG)
+                       state->tx_tuna[7] = 0x00;       /*      Digital */
        } else
                return -EINVAL;
 
@@ -447,29 +466,41 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate)
        }
        dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
        srate /= 1000;
-       if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
-               sval = srate;
-               sval <<= 20;
-               do_div(sval, 88000);
-               symcalc = (u32) sval;
-               dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
-               state->tx_tuna[5] = (u8) (symcalc >> 12);
-               state->tx_tuna[6] = (u8) (symcalc >> 4);
-               state->tx_tuna[7] = (u8) (symcalc << 4);
-       } else {
-               state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
-               state->tx_tuna[6] = (u8) (srate >> 8);
-               state->tx_tuna[7] = (u8) srate;
-       }
-       state->tx_tuna[8] &= ~0x20;
-       if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
-               if (srate > 8000)
-                       state->tx_tuna[8] |= 0x20;
+       if (state->dst_type == DST_TYPE_IS_SAT) {
+               if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
+                       sval = srate;
+                       sval <<= 20;
+                       do_div(sval, 88000);
+                       symcalc = (u32) sval;
+                       dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
+                       state->tx_tuna[5] = (u8) (symcalc >> 12);
+                       state->tx_tuna[6] = (u8) (symcalc >> 4);
+                       state->tx_tuna[7] = (u8) (symcalc << 4);
+               } else {
+                       state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
+                       state->tx_tuna[6] = (u8) (srate >> 8);
+                       state->tx_tuna[7] = (u8) srate;
+               }
+               state->tx_tuna[8] &= ~0x20;
+               if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
+                       if (srate > 8000)
+                               state->tx_tuna[8] |= 0x20;
+               }
+       } else if (state->dst_type == DST_TYPE_IS_CABLE) {
+               dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name);
+               if (!strncmp(state->fw_name, "DCTNEW", 6)) {
+                       state->tx_tuna[5] = (u8) (srate >> 8);
+                       state->tx_tuna[6] = (u8) srate;
+                       state->tx_tuna[7] = 0x00;
+               } else if (!strncmp(state->fw_name, "DCT-CI", 6)) {
+                       state->tx_tuna[5] = 0x00;
+                       state->tx_tuna[6] = (u8) (srate >> 8);
+                       state->tx_tuna[7] = (u8) srate;
+               }
        }
        return 0;
 }
 
-
 static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
 {
        if (state->dst_type != DST_TYPE_IS_CABLE)
@@ -490,7 +521,10 @@ static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulatio
                state->tx_tuna[8] = 0x80;
                break;
        case QAM_256:
-               state->tx_tuna[8] = 0x00;
+               if (!strncmp(state->fw_name, "DCTNEW", 6))
+                       state->tx_tuna[8] = 0xff;
+               else if (!strncmp(state->fw_name, "DCT-CI", 6))
+                       state->tx_tuna[8] = 0x00;
                break;
        case QPSK:
        case QAM_AUTO:
@@ -523,13 +557,19 @@ u8 dst_check_sum(u8 *buf, u32 len)
 }
 EXPORT_SYMBOL(dst_check_sum);
 
-static void dst_type_flags_print(u32 type_flags)
+static void dst_type_flags_print(struct dst_state *state)
 {
+       u32 type_flags = state->type_flags;
+
        dprintk(verbose, DST_ERROR, 0, "DST type flags :");
-       if (type_flags & DST_TYPE_HAS_NEWTUNE)
-               dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
+       if (type_flags & DST_TYPE_HAS_TS188)
+               dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188);
+       if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
+               dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2);
        if (type_flags & DST_TYPE_HAS_TS204)
                dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
+       if (type_flags & DST_TYPE_HAS_VLF)
+               dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF);
        if (type_flags & DST_TYPE_HAS_SYMDIV)
                dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
        if (type_flags & DST_TYPE_HAS_FW_1)
@@ -542,7 +582,7 @@ static void dst_type_flags_print(u32 type_flags)
 }
 
 
-static int dst_type_print(u8 type)
+static int dst_type_print(struct dst_state *state, u8 type)
 {
        char *otype;
        switch (type) {
@@ -558,6 +598,10 @@ static int dst_type_print(u8 type)
                otype = "cable";
                break;
 
+       case DST_TYPE_IS_ATSC:
+               otype = "atsc";
+               break;
+
        default:
                dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
                return -EINVAL;
@@ -567,6 +611,127 @@ static int dst_type_print(u8 type)
        return 0;
 }
 
+struct tuner_types tuner_list[] = {
+       {
+               .tuner_type = TUNER_TYPE_L64724,
+               .tuner_name = "L 64724",
+               .board_name = "UNKNOWN",
+               .fw_name    = "UNKNOWN"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_STV0299,
+               .tuner_name = "STV 0299",
+               .board_name = "VP1020",
+               .fw_name    = "DST-MOT"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_STV0299,
+               .tuner_name = "STV 0299",
+               .board_name = "VP1020",
+               .fw_name    = "DST-03T"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_MB86A15,
+               .tuner_name = "MB 86A15",
+               .board_name = "VP1022",
+               .fw_name    = "DST-03T"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_MB86A15,
+               .tuner_name = "MB 86A15",
+               .board_name = "VP1025",
+               .fw_name    = "DST-03T"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_STV0299,
+               .tuner_name = "STV 0299",
+               .board_name = "VP1030",
+               .fw_name    = "DST-CI"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_STV0299,
+               .tuner_name = "STV 0299",
+               .board_name = "VP1030",
+               .fw_name    = "DSTMCI"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_UNKNOWN,
+               .tuner_name = "UNKNOWN",
+               .board_name = "VP2021",
+               .fw_name    = "DCTNEW"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_UNKNOWN,
+               .tuner_name = "UNKNOWN",
+               .board_name = "VP2030",
+               .fw_name    = "DCT-CI"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_UNKNOWN,
+               .tuner_name = "UNKNOWN",
+               .board_name = "VP2031",
+               .fw_name    = "DCT-CI"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_UNKNOWN,
+               .tuner_name = "UNKNOWN",
+               .board_name = "VP2040",
+               .fw_name    = "DCT-CI"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_UNKNOWN,
+               .tuner_name = "UNKNOWN",
+               .board_name = "VP3020",
+               .fw_name    = "DTTFTA"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_UNKNOWN,
+               .tuner_name = "UNKNOWN",
+               .board_name = "VP3021",
+               .fw_name    = "DTTFTA"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_TDA10046,
+               .tuner_name = "TDA10046",
+               .board_name = "VP3040",
+               .fw_name    = "DTT-CI"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_UNKNOWN,
+               .tuner_name = "UNKNOWN",
+               .board_name = "VP3051",
+               .fw_name    = "DTTNXT"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_NXT200x,
+               .tuner_name = "NXT200x",
+               .board_name = "VP3220",
+               .fw_name    = "ATSCDI"
+       },
+
+       {
+               .tuner_type = TUNER_TYPE_NXT200x,
+               .tuner_name = "NXT200x",
+               .board_name = "VP3250",
+               .fw_name    = "ATSCAD"
+       },
+};
+
 /*
        Known cards list
        Satellite
@@ -608,7 +773,8 @@ static struct dst_types dst_tlist[] = {
                .offset = 0,
                .dst_type =  DST_TYPE_IS_SAT,
                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
-               .dst_feature = 0
+               .dst_feature = 0,
+               .tuner_type = 0
        },      /*      obsolete        */
 
        {
@@ -616,15 +782,17 @@ static struct dst_types dst_tlist[] = {
                .offset = 0,
                .dst_type =  DST_TYPE_IS_SAT,
                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
-               .dst_feature = 0
+               .dst_feature = 0,
+               .tuner_type = 0
        },      /*      obsolete        */
 
        {
                .device_id = "DST-030",
                .offset =  0,
                .dst_type = DST_TYPE_IS_SAT,
-               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
-               .dst_feature = 0
+               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
+               .dst_feature = 0,
+               .tuner_type = 0
        },      /*      obsolete        */
 
        {
@@ -633,7 +801,8 @@ static struct dst_types dst_tlist[] = {
                .dst_type = DST_TYPE_IS_SAT,
                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
                .dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
-                                                        | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO
+                                                        | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO,
+               .tuner_type = TUNER_TYPE_MULTI
         },
 
        {
@@ -641,57 +810,63 @@ static struct dst_types dst_tlist[] = {
                .offset =  0,
                .dst_type = DST_TYPE_IS_SAT,
                .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
-               .dst_feature = 0
+               .dst_feature = 0,
+               .tuner_type = 0
        },      /*      obsolete        */
 
        {
                .device_id = "DST-CI",
                .offset = 1,
                .dst_type = DST_TYPE_IS_SAT,
-               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
-               .dst_feature = DST_TYPE_HAS_CA
+               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1,
+               .dst_feature = DST_TYPE_HAS_CA,
+               .tuner_type = 0
        },      /*      An OEM board    */
 
        {
                .device_id = "DSTMCI",
                .offset = 1,
                .dst_type = DST_TYPE_IS_SAT,
-               .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT,
+               .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF,
                .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
-                                                       | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC
+                                                       | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC,
+               .tuner_type = TUNER_TYPE_MULTI
        },
 
        {
                .device_id = "DSTFCI",
                .offset = 1,
                .dst_type = DST_TYPE_IS_SAT,
-               .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
-               .dst_feature = 0
+               .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
+               .dst_feature = 0,
+               .tuner_type = 0
        },      /* unknown to vendor    */
 
        {
                .device_id = "DCT-CI",
                .offset = 1,
                .dst_type = DST_TYPE_IS_CABLE,
-               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
-                                                       | DST_TYPE_HAS_FW_2,
-               .dst_feature = DST_TYPE_HAS_CA
+               .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF,
+               .dst_feature = DST_TYPE_HAS_CA,
+               .tuner_type = 0
        },
 
        {
                .device_id = "DCTNEW",
                .offset = 1,
                .dst_type = DST_TYPE_IS_CABLE,
-               .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD,
-               .dst_feature = 0
+               .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE,
+               .dst_feature = 0,
+               .tuner_type = 0
        },
 
        {
                .device_id = "DTT-CI",
                .offset = 1,
                .dst_type = DST_TYPE_IS_TERR,
-               .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE,
-               .dst_feature = DST_TYPE_HAS_CA
+               .type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF,
+               .dst_feature = DST_TYPE_HAS_CA,
+               .tuner_type = 0
        },
 
        {
@@ -699,7 +874,8 @@ static struct dst_types dst_tlist[] = {
                .offset = 1,
                .dst_type = DST_TYPE_IS_TERR,
                .type_flags = DST_TYPE_HAS_FW_2,
-               .dst_feature = 0
+               .dst_feature = 0,
+               .tuner_type = 0
        },
 
        {
@@ -707,7 +883,8 @@ static struct dst_types dst_tlist[] = {
                .offset = 1,
                .dst_type = DST_TYPE_IS_TERR,
                .type_flags = DST_TYPE_HAS_FW_2,
-               .dst_feature = DST_TYPE_HAS_ANALOG
+               .dst_feature = DST_TYPE_HAS_ANALOG,
+               .tuner_type = 0
        },
 
        {
@@ -715,15 +892,17 @@ static struct dst_types dst_tlist[] = {
                .offset = 1,
                .dst_type = DST_TYPE_IS_ATSC,
                .type_flags = DST_TYPE_HAS_FW_2,
-               .dst_feature = 0
+               .dst_feature = 0,
+               .tuner_type = 0
        },
 
        {
                .device_id = "ATSCAD",
                .offset = 1,
                .dst_type = DST_TYPE_IS_ATSC,
-               .type_flags = DST_TYPE_HAS_FW_2,
-               .dst_feature = 0
+               .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+               .dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG,
+               .tuner_type = 0
        },
 
        { }
@@ -768,6 +947,9 @@ static int dst_fw_ver(struct dst_state *state)
 
 static int dst_card_type(struct dst_state *state)
 {
+       int j;
+       struct tuner_types *p_tuner_list = NULL;
+
        u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        get_type[7] = dst_check_sum(get_type, 7);
        if (dst_command(state, get_type, 8) < 0) {
@@ -775,9 +957,17 @@ static int dst_card_type(struct dst_state *state)
                return -1;
        }
        memset(&state->card_info, '\0', 8);
-       memcpy(&state->card_info, &state->rxbuffer, 8);
+       memcpy(&state->card_info, &state->rxbuffer, 7);
        dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
 
+       for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
+               if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
+                       state->tuner_type = p_tuner_list->tuner_type;
+                       dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
+                               p_tuner_list->tuner_name, p_tuner_list->tuner_type);
+               }
+       }
+
        return 0;
 }
 
@@ -790,12 +980,64 @@ static int dst_get_vendor(struct dst_state *state)
                return -1;
        }
        memset(&state->vendor, '\0', 8);
-       memcpy(&state->vendor, &state->rxbuffer, 8);
+       memcpy(&state->vendor, &state->rxbuffer, 7);
        dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
 
        return 0;
 }
 
+static void debug_dst_buffer(struct dst_state *state)
+{
+       int i;
+
+       if (verbose > 2) {
+               printk("%s: [", __func__);
+               for (i = 0; i < 8; i++)
+                       printk(" %02x", state->rxbuffer[i]);
+               printk("]\n");
+       }
+}
+
+static int dst_check_stv0299(struct dst_state *state)
+{
+       u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+       check_stv0299[7] = dst_check_sum(check_stv0299, 7);
+       if (dst_command(state, check_stv0299, 8) < 0) {
+               dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
+               return -1;
+       }
+       debug_dst_buffer(state);
+
+       if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
+               dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
+               state->tuner_type = TUNER_TYPE_STV0299;
+               return 0;
+       }
+
+       return -1;
+}
+
+static int dst_check_mb86a15(struct dst_state *state)
+{
+       u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+       check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
+       if (dst_command(state, check_mb86a15, 8) < 0) {
+               dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
+               return -1;
+       }
+       debug_dst_buffer(state);
+
+       if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
+               dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
+               state->tuner_type = TUNER_TYPE_MB86A15;
+               return 0;
+       }
+
+       return -1;
+}
+
 static int dst_get_tuner_info(struct dst_state *state)
 {
        u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -803,60 +1045,59 @@ static int dst_get_tuner_info(struct dst_state *state)
 
        get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
        get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
+       dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
        if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
-               if (dst_command(state, get_tuner_2, 8) < 0) {
-                       dprintk(verbose, DST_INFO, 1, "Unsupported Command");
-                       return -1;
+               if (dst_command(state, get_tuner_1, 8) < 0) {
+                       dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
+                       goto force;
                }
        } else {
-               if (dst_command(state, get_tuner_1, 8) < 0) {
-                       dprintk(verbose, DST_INFO, 1, "Unsupported Command");
-                       return -1;
+               if (dst_command(state, get_tuner_2, 8) < 0) {
+                       dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
+                       goto force;
                }
        }
        memset(&state->board_info, '\0', 8);
        memcpy(&state->board_info, &state->rxbuffer, 8);
        if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
-               if (state->board_info[1] == 0x0b) {
-                       if (state->type_flags & DST_TYPE_HAS_TS204)
-                               state->type_flags &= ~DST_TYPE_HAS_TS204;
-                       state->type_flags |= DST_TYPE_HAS_NEWTUNE;
-                       dprintk(verbose, DST_INFO, 1, "DST type has TS=188");
-               } else {
-                       if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
-                               state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
-                       state->type_flags |= DST_TYPE_HAS_TS204;
-                       dprintk(verbose, DST_INFO, 1, "DST type has TS=204");
-               }
-       } else {
-               if (state->board_info[0] == 0xbc) {
-                       if (state->type_flags & DST_TYPE_HAS_TS204)
-                               state->type_flags &= ~DST_TYPE_HAS_TS204;
-                       state->type_flags |= DST_TYPE_HAS_NEWTUNE;
-                       dprintk(verbose, DST_INFO, 1, "DST type has TS=188, Daughterboard=[%d]", state->board_info[1]);
-
-               } else if (state->board_info[0] == 0xcc) {
-                       if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
-                               state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
-                       state->type_flags |= DST_TYPE_HAS_TS204;
-                       dprintk(verbose, DST_INFO, 1, "DST type has TS=204 Daughterboard=[%d]", state->board_info[1]);
+               dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
+       }
+       if (state->board_info[0] == 0xbc) {
+               if (state->type_flags != DST_TYPE_IS_ATSC)
+                       state->type_flags |= DST_TYPE_HAS_TS188;
+               else
+                       state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;
+
+               if (state->board_info[1] == 0x01) {
+                       state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
+                       dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard");
                }
        }
 
        return 0;
+force:
+       if (!strncmp(state->fw_name, "DCT-CI", 6)) {
+               state->type_flags |= DST_TYPE_HAS_TS204;
+               dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name);
+       }
+
+       return -1;
 }
 
 static int dst_get_device_id(struct dst_state *state)
 {
        u8 reply;
 
-       int i;
-       struct dst_types *p_dst_type;
+       int i, j;
+       struct dst_types *p_dst_type = NULL;
+       struct tuner_types *p_tuner_list = NULL;
+
        u8 use_dst_type = 0;
        u32 use_type_flags = 0;
 
        static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
 
+       state->tuner_type = 0;
        device_type[7] = dst_check_sum(device_type, 7);
 
        if (write_dst(state, device_type, FIXED_COMM))
@@ -888,8 +1129,34 @@ static int dst_get_device_id(struct dst_state *state)
 
                        /*      Card capabilities       */
                        state->dst_hw_cap = p_dst_type->dst_feature;
-                       dprintk(verbose, DST_ERROR, 1, "Recognise [%s]\n", p_dst_type->device_id);
-
+                       dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id);
+                       strncpy(&state->fw_name[0], p_dst_type->device_id, 6);
+                       /*      Multiple tuners         */
+                       if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
+                               switch (use_dst_type) {
+                               case DST_TYPE_IS_SAT:
+                                       /*      STV0299 check   */
+                                       if (dst_check_stv0299(state) < 0) {
+                                               dprintk(verbose, DST_ERROR, 1, "Unsupported");
+                                               state->tuner_type = TUNER_TYPE_MB86A15;
+                                       }
+                                       break;
+                               default:
+                                       break;
+                               }
+                               if (dst_check_mb86a15(state) < 0)
+                                       dprintk(verbose, DST_ERROR, 1, "Unsupported");
+                       /*      Single tuner            */
+                       } else {
+                               state->tuner_type = p_dst_type->tuner_type;
+                       }
+                       for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
+                               if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
+                                       p_tuner_list->tuner_type == state->tuner_type) {
+                                       dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]",
+                                               p_dst_type->device_id, p_tuner_list->tuner_name);
+                               }
+                       }
                        break;
                }
        }
@@ -900,10 +1167,10 @@ static int dst_get_device_id(struct dst_state *state)
                use_dst_type = DST_TYPE_IS_SAT;
                use_type_flags = DST_TYPE_HAS_SYMDIV;
        }
-       dst_type_print(use_dst_type);
+       dst_type_print(state, use_dst_type);
        state->type_flags = use_type_flags;
        state->dst_type = use_dst_type;
-       dst_type_flags_print(state->type_flags);
+       dst_type_flags_print(state);
 
        return 0;
 }
@@ -911,15 +1178,15 @@ static int dst_get_device_id(struct dst_state *state)
 static int dst_probe(struct dst_state *state)
 {
        mutex_init(&state->dst_mutex);
-       if ((rdc_8820_reset(state)) < 0) {
-               dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
-               return -1;
-       }
-       if (dst_addons & DST_TYPE_HAS_CA)
+       if (dst_addons & DST_TYPE_HAS_CA) {
+               if ((rdc_8820_reset(state)) < 0) {
+                       dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
+                       return -1;
+               }
                msleep(4000);
-       else
+       } else {
                msleep(100);
-
+       }
        if ((dst_comm_init(state)) < 0) {
                dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
                return -1;
@@ -931,7 +1198,6 @@ static int dst_probe(struct dst_state *state)
        }
        if (dst_get_mac(state) < 0) {
                dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
-               return 0;
        }
        if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
                if (dst_get_tuner_info(state) < 0)
@@ -1048,6 +1314,10 @@ static int dst_get_signal(struct dst_state *state)
                        state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
                        state->decode_strength = state->rxbuffer[4] << 8;
                        state->decode_snr = state->rxbuffer[3] << 8;
+               } else if (state->dst_type == DST_TYPE_IS_ATSC) {
+                       state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0;
+                       state->decode_strength = state->rxbuffer[4] << 8;
+                       state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
                }
                state->cur_jiff = jiffies;
        }
@@ -1078,8 +1348,9 @@ static int dst_get_tuna(struct dst_state *state)
        state->diseq_flags &= ~(HAS_LOCK);
        if (!dst_wait_dst_ready(state, NO_DELAY))
                return -EIO;
-       if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
-               /* how to get variable length reply ???? */
+       if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+               !(state->dst_type == DST_TYPE_IS_ATSC))
+
                retval = read_dst(state, state->rx_tuna, 10);
        else
                retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
@@ -1087,7 +1358,10 @@ static int dst_get_tuna(struct dst_state *state)
                dprintk(verbose, DST_DEBUG, 1, "read not successful");
                return retval;
        }
-       if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+       if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+               !(state->dst_type == DST_TYPE_IS_CABLE) &&
+               !(state->dst_type == DST_TYPE_IS_ATSC)) {
+
                if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
                        dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
                        return -EIO;
@@ -1133,7 +1407,10 @@ static int dst_write_tuna(struct dvb_frontend *fe)
                dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
                goto error;
        }
-       if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+//     if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+       if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+               (!(state->dst_type == DST_TYPE_IS_ATSC))) {
+
                state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
                retval = write_dst(state, &state->tx_tuna[0], 10);
        } else {
@@ -1189,9 +1466,12 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd
 
        if (state->dst_type != DST_TYPE_IS_SAT)
                return 0;
-       if (cmd->msg_len == 0 || cmd->msg_len > 4)
+       if (cmd->msg_len > 0 && cmd->msg_len < 5)
+               memcpy(&paket[3], cmd->msg, cmd->msg_len);
+       else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
+               memcpy(&paket[2], cmd->msg, cmd->msg_len);
+       else
                return -EINVAL;
-       memcpy(&paket[3], cmd->msg, cmd->msg_len);
        paket[7] = dst_check_sum(&paket[0], 7);
        dst_command(state, paket, 8);
        return 0;
@@ -1287,8 +1567,9 @@ static int dst_init(struct dvb_frontend *fe)
        static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
        static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
        static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
-       static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
        static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+       static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+       static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
 
        state->inversion = INVERSION_OFF;
        state->voltage = SEC_VOLTAGE_13;
@@ -1298,11 +1579,13 @@ static int dst_init(struct dvb_frontend *fe)
        state->bandwidth = BANDWIDTH_7_MHZ;
        state->cur_jiff = jiffies;
        if (state->dst_type == DST_TYPE_IS_SAT)
-               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
+               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
        else if (state->dst_type == DST_TYPE_IS_TERR)
-               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
+               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
        else if (state->dst_type == DST_TYPE_IS_CABLE)
-               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
+               memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
+       else if (state->dst_type == DST_TYPE_IS_ATSC)
+               memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner));
 
        return 0;
 }
@@ -1341,7 +1624,36 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
        return 0;
 }
 
-static int dst_set_frontend(struct dvb_frontend* fe,
+static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+       struct dst_state *state = fe->demodulator_priv;
+
+       if (p != NULL) {
+               dst_set_freq(state, p->frequency);
+               dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+
+               if (state->dst_type == DST_TYPE_IS_SAT) {
+                       if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+                               dst_set_inversion(state, p->inversion);
+                       dst_set_fec(state, p->u.qpsk.fec_inner);
+                       dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+                       dst_set_polarization(state);
+                       dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+
+               } else if (state->dst_type == DST_TYPE_IS_TERR)
+                       dst_set_bandwidth(state, p->u.ofdm.bandwidth);
+               else if (state->dst_type == DST_TYPE_IS_CABLE) {
+                       dst_set_fec(state, p->u.qam.fec_inner);
+                       dst_set_symbolrate(state, p->u.qam.symbol_rate);
+                       dst_set_modulation(state, p->u.qam.modulation);
+               }
+               dst_write_tuna(fe);
+       }
+
+       return 0;
+}
+
+static int dst_tune_frontend(struct dvb_frontend* fe,
                            struct dvb_frontend_parameters* p,
                            unsigned int mode_flags,
                            int *delay,
@@ -1378,6 +1690,11 @@ static int dst_set_frontend(struct dvb_frontend* fe,
        return 0;
 }
 
+static int dst_get_tuning_algo(struct dvb_frontend *fe)
+{
+       return dst_algo;
+}
+
 static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
 {
        struct dst_state *state = fe->demodulator_priv;
@@ -1408,6 +1725,7 @@ static void dst_release(struct dvb_frontend *fe)
 static struct dvb_frontend_ops dst_dvbt_ops;
 static struct dvb_frontend_ops dst_dvbs_ops;
 static struct dvb_frontend_ops dst_dvbc_ops;
+static struct dvb_frontend_ops dst_atsc_ops;
 
 struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
 {
@@ -1417,24 +1735,25 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
                return NULL;
        }
        /* determine settings based on type */
+       /* create dvb_frontend */
        switch (state->dst_type) {
        case DST_TYPE_IS_TERR:
-               memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
+               memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
                break;
        case DST_TYPE_IS_CABLE:
-               memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
+               memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
                break;
        case DST_TYPE_IS_SAT:
-               memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
+               memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
+               break;
+       case DST_TYPE_IS_ATSC:
+               memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
                break;
        default:
                dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
                kfree(state);
                return NULL;
        }
-
-       /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
        state->frontend.demodulator_priv = state;
 
        return state;                           /*      Manu (DST is a card not a frontend)     */
@@ -1455,8 +1774,10 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
 
        .release = dst_release,
        .init = dst_init,
-       .tune = dst_set_frontend,
+       .tune = dst_tune_frontend,
+       .set_frontend = dst_set_frontend,
        .get_frontend = dst_get_frontend,
+       .get_frontend_algo = dst_get_tuning_algo,
        .read_status = dst_read_status,
        .read_signal_strength = dst_read_signal_strength,
        .read_snr = dst_read_snr,
@@ -1479,8 +1800,10 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
 
        .release = dst_release,
        .init = dst_init,
-       .tune = dst_set_frontend,
+       .tune = dst_tune_frontend,
+       .set_frontend = dst_set_frontend,
        .get_frontend = dst_get_frontend,
+       .get_frontend_algo = dst_get_tuning_algo,
        .read_status = dst_read_status,
        .read_signal_strength = dst_read_signal_strength,
        .read_snr = dst_read_snr,
@@ -1506,13 +1829,38 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
 
        .release = dst_release,
        .init = dst_init,
-       .tune = dst_set_frontend,
+       .tune = dst_tune_frontend,
+       .set_frontend = dst_set_frontend,
+       .get_frontend = dst_get_frontend,
+       .get_frontend_algo = dst_get_tuning_algo,
+       .read_status = dst_read_status,
+       .read_signal_strength = dst_read_signal_strength,
+       .read_snr = dst_read_snr,
+};
+
+static struct dvb_frontend_ops dst_atsc_ops = {
+       .info = {
+               .name = "DST ATSC",
+               .type = FE_ATSC,
+               .frequency_stepsize = 62500,
+               .frequency_min = 510000000,
+               .frequency_max = 858000000,
+               .symbol_rate_min = 1000000,
+               .symbol_rate_max = 45000000,
+               .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+       },
+
+       .release = dst_release,
+       .init = dst_init,
+       .tune = dst_tune_frontend,
+       .set_frontend = dst_set_frontend,
        .get_frontend = dst_get_frontend,
+       .get_frontend_algo = dst_get_tuning_algo,
        .read_status = dst_read_status,
        .read_signal_strength = dst_read_signal_strength,
        .read_snr = dst_read_snr,
 };
 
-MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
+MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
 MODULE_AUTHOR("Jamie Honan, Manu Abraham");
 MODULE_LICENSE("GPL");
index f6b49a801eba92ae75e9d8d68ccc58000d1ff199..fa923b9b346ea99440dceeac23e695c4c4b3a193 100644 (file)
@@ -68,6 +68,13 @@ static int ca_set_pid(void)
        return -EOPNOTSUPP;
 }
 
+static void put_command_and_length(u8 *data, int command, int length)
+{
+       data[0] = (command >> 16) & 0xff;
+       data[1] = (command >> 8) & 0xff;
+       data[2] = command & 0xff;
+       data[3] = length;
+}
 
 static void put_checksum(u8 *check_string, int length)
 {
@@ -124,15 +131,18 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
        u8 dst_ca_comm_err = 0;
 
        while (dst_ca_comm_err < RETRIES) {
-               dst_comm_init(state);
                dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
                if (dst_ci_command(state, data, ca_string, len, read)) {        // If error
                        dst_error_recovery(state);
                        dst_ca_comm_err++; // work required here.
+               } else {
+                       break;
                }
-               break;
        }
 
+       if(dst_ca_comm_err == RETRIES)
+               return -1;
+
        return 0;
 }
 
@@ -140,6 +150,7 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
 
 static int ca_get_app_info(struct dst_state *state)
 {
+       int length, str_length;
        static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
 
        put_checksum(&command[0], command[0]);
@@ -154,6 +165,68 @@ static int ca_get_app_info(struct dst_state *state)
                (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
        dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
 
+       // Transform dst message to correct application_info message
+       length = state->messages[5];
+       str_length = length - 6;
+       if (str_length < 0) {
+               str_length = 0;
+               dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering.");
+       }
+
+       // First, the command and length fields
+       put_command_and_length(&state->messages[0], CA_APP_INFO, length);
+
+       // Copy application_type, application_manufacturer and manufacturer_code
+       memcpy(&state->messages[4], &state->messages[7], 5);
+
+       // Set string length and copy string
+       state->messages[9] = str_length;
+       memcpy(&state->messages[10], &state->messages[12], str_length);
+
+       return 0;
+}
+
+static int ca_get_ca_info(struct dst_state *state)
+{
+       int srcPtr, dstPtr, i, num_ids;
+       static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff};
+       const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7;
+
+       put_checksum(&slot_command[0], slot_command[0]);
+       if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) {
+               dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
+               return -1;
+       }
+       dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+
+       // Print raw data
+       dprintk(verbose, DST_CA_INFO, 0, " DST data = [");
+       for (i = 0; i < state->messages[0] + 1; i++) {
+               dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]);
+       }
+       dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
+       // Set the command and length of the output
+       num_ids = state->messages[in_num_ids_pos];
+       if (num_ids >= 100) {
+               num_ids = 100;
+               dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering.");
+       }
+       put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2);
+
+       dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = [");
+       srcPtr = in_system_id_pos;
+       dstPtr = out_system_id_pos;
+       for(i = 0; i < num_ids; i++) {
+               dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]);
+               // Append to output
+               state->messages[dstPtr + 0] = state->messages[srcPtr + 0];
+               state->messages[dstPtr + 1] = state->messages[srcPtr + 1];
+               srcPtr += 2;
+               dstPtr += 2;
+       }
+       dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
        return 0;
 }
 
@@ -174,7 +247,7 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps,
 
        dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
        dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
-       for (i = 0; i < 8; i++)
+       for (i = 0; i < slot_cap[0] + 1; i++)
                dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
        dprintk(verbose, DST_CA_INFO, 0, "\n");
 
@@ -260,6 +333,11 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
                        if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
                                return -EFAULT;
                        break;
+               case CA_INFO:
+                       memcpy(p_ca_message->msg, state->messages, 128);
+                       if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
+                               return -EFAULT;
+                       break;
                }
        }
 
@@ -302,7 +380,7 @@ static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 l
                rdc_reset_state(state);
                return -1;
        }
-       dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes.");
+       dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success.");
 
        return 0;
 }
@@ -340,6 +418,7 @@ static int debug_string(u8 *msg, u32 length, u32 offset)
        return 0;
 }
 
+
 static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
 {
        u32 length = 0;
@@ -455,6 +534,16 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
                        }
                        dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
                        break;
+               case CA_INFO_ENQUIRY:
+                       dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information");
+
+                       if ((ca_get_ca_info(state)) < 0) {
+                               dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !");
+                               result = -1;
+                               goto free_mem_and_exit;
+                       }
+                       dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !");
+                       break;
                }
        }
 free_mem_and_exit:
@@ -473,18 +562,15 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        void __user *arg = (void __user *)ioctl_arg;
        int result = 0;
 
-       if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
-               dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-               return -ENOMEM;
-       }
-       if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
+       p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
+       p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
+       p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL);
+       if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) {
                dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-               return -ENOMEM;
-       }
-       if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
-               dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-               return -ENOMEM;
+               result = -ENOMEM;
+               goto free_mem_and_exit;
        }
+
        /*      We have now only the standard ioctl's, the driver is upposed to handle internals.       */
        switch (cmd) {
        case CA_SEND_MSG:
@@ -582,7 +668,7 @@ static int dst_ca_release(struct inode *inode, struct file *file)
 
 static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
 {
-       int bytes_read = 0;
+       ssize_t bytes_read = 0;
 
        dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
 
index 51d4e043716c19f37899566ee0f3bf97539fb685..0677b047b3a78be3381046c3ef0eb88e576cf5c3 100644 (file)
@@ -42,7 +42,7 @@
 #define DST_TYPE_IS_CABLE      2
 #define DST_TYPE_IS_ATSC       3
 
-#define DST_TYPE_HAS_NEWTUNE   1
+#define DST_TYPE_HAS_TS188     1
 #define DST_TYPE_HAS_TS204     2
 #define DST_TYPE_HAS_SYMDIV    4
 #define DST_TYPE_HAS_FW_1      8
@@ -52,6 +52,9 @@
 #define DST_TYPE_HAS_OBS_REGS  128
 #define DST_TYPE_HAS_INC_COUNT 256
 #define DST_TYPE_HAS_MULTI_FE  512
+#define DST_TYPE_HAS_NEWTUNE_2 1024
+#define DST_TYPE_HAS_DBOARD    2048
+#define DST_TYPE_HAS_VLF       4096
 
 /*     Card capability list    */
 
 #define        DST_TYPE_HAS_ANALOG     64      /*      Analog inputs   */
 #define DST_TYPE_HAS_SESSION   128
 
+#define TUNER_TYPE_MULTI       1
+#define TUNER_TYPE_UNKNOWN     2
+/*     DVB-S           */
+#define TUNER_TYPE_L64724      4
+#define TUNER_TYPE_STV0299     8
+#define TUNER_TYPE_MB86A15     16
+
+/*     DVB-T           */
+#define TUNER_TYPE_TDA10046    32
+
+/*     ATSC            */
+#define TUNER_TYPE_NXT200x     64
+
+
 #define RDC_8820_PIO_0_DISABLE 0
 #define RDC_8820_PIO_0_ENABLE  1
 #define RDC_8820_INT           2
@@ -84,8 +101,6 @@ struct dst_state {
 
        struct bt878* bt;
 
-       struct dvb_frontend_ops ops;
-
        /* configuration settings */
        const struct dst_config* config;
 
@@ -121,8 +136,17 @@ struct dst_state {
        u8 card_info[8];
        u8 vendor[8];
        u8 board_info[8];
-
+       u32 tuner_type;
+       char *tuner_name;
        struct mutex dst_mutex;
+       u8 fw_name[8];
+};
+
+struct tuner_types {
+       u32 tuner_type;
+       char *tuner_name;
+       char *board_name;
+       char *fw_name;
 };
 
 struct dst_types {
@@ -131,6 +155,7 @@ struct dst_types {
        u8 dst_type;
        u32 type_flags;
        u32 dst_feature;
+       u32 tuner_type;
 };
 
 struct dst_config
index ccc7b2eb4a2d33a424e243612634928821c0e096..b715b972d2fcfbfdbd495d5a1cc2ed558c60e632 100644 (file)
@@ -147,12 +147,15 @@ static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
        u32 div;
        unsigned char bs = 0;
        unsigned char cp = 0;
 
+       if (buf_len < 5)
+               return -EINVAL;
+
        div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
        if (params->frequency < 542000000)
@@ -169,22 +172,25 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
        else
                bs = 0x08;
 
-       pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
+       pllbuf[0] = 0x60;
        pllbuf[1] = div >> 8;
        pllbuf[2] = div & 0xff;
        pllbuf[3] = cp;
        pllbuf[4] = bs;
 
-       return 0;
+       return 5;
 }
 
 static struct mt352_config thomson_dtt7579_config = {
        .demod_address = 0x0f,
        .demod_init = thomson_dtt7579_demod_init,
-       .pll_set = thomson_dtt7579_pll_set,
 };
 
-static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static struct zl10353_config thomson_dtt7579_zl10353_config = {
+       .demod_address = 0x0f,
+};
+
+static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        u32 freq = params->frequency;
 
@@ -237,7 +243,7 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
        return 0;
 }
 
-static int pinnsat_pll_init(struct dvb_frontend* fe)
+static int pinnsat_tuner_init(struct dvb_frontend* fe)
 {
        struct dvb_bt8xx_card *card = fe->dvb->priv;
 
@@ -247,7 +253,7 @@ static int pinnsat_pll_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int pinnsat_pll_sleep(struct dvb_frontend* fe)
+static int pinnsat_tuner_sleep(struct dvb_frontend* fe)
 {
        struct dvb_bt8xx_card *card = fe->dvb->priv;
 
@@ -258,12 +264,9 @@ static int pinnsat_pll_sleep(struct dvb_frontend* fe)
 
 static struct cx24110_config pctvsat_config = {
        .demod_address = 0x55,
-       .pll_init = pinnsat_pll_init,
-       .pll_set = cx24108_pll_set,
-       .pll_sleep = pinnsat_pll_sleep,
 };
 
-static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
        u8 cfg, cpump, band_select;
@@ -297,6 +300,8 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front
        data[2] = ((div >> 10) & 0x60) | cfg;
        data[3] = (cpump << 6) | band_select;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(card->i2c_adapter, &msg, 1);
        return (div * 166666 - 36000000);
 }
@@ -310,7 +315,6 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s
 
 static struct sp887x_config microtune_mt7202dtf_config = {
        .demod_address = 0x70,
-       .pll_set = microtune_mt7202dtf_pll_set,
        .request_firmware = microtune_mt7202dtf_request_firmware,
 };
 
@@ -337,12 +341,14 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
        u32 div;
        unsigned char bs = 0;
        unsigned char cp = 0;
 
+       if (buf_len < 5) return -EINVAL;
+
        div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
        if (params->frequency < 150000000)
@@ -383,19 +389,18 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
        else
                bs = 0x08;
 
-       pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
+       pllbuf[0] = 0x61;
        pllbuf[1] = div >> 8;
        pllbuf[2] = div & 0xff;
        pllbuf[3] = cp;
        pllbuf[4] = bs;
 
-       return 0;
+       return 5;
 }
 
 static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
        .demod_address = 0x0f,
        .demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
-       .pll_set = advbt771_samsung_tdtc9251dh0_pll_set,
 };
 
 static struct dst_config dst_config = {
@@ -455,7 +460,7 @@ static struct or51211_config or51211_config = {
        .sleep = or51211_sleep,
 };
 
-static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
        u8 buf[4];
@@ -478,6 +483,8 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
        else
                return -EINVAL;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(card->i2c_adapter, &msg, 1);
        return 0;
 }
@@ -485,7 +492,6 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
 static struct nxt6000_config vp3021_alps_tded4_config = {
        .demod_address = 0x0a,
        .clock_inversion = 1,
-       .pll_set = vp3021_alps_tded4_pll_set,
 };
 
 static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
@@ -506,14 +512,17 @@ static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
        u32 div;
        struct dvb_ofdm_parameters *op = &params->u.ofdm;
 
+       if (buf_len < 5)
+               return -EINVAL;
+
        div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
-       pllbuf[0] = 0xc2;
+       pllbuf[0] = 0x61;
        pllbuf[1] = (div >> 8) & 0x7F;
        pllbuf[2] = div & 0xFF;
        pllbuf[3] = 0x85;
@@ -530,7 +539,7 @@ static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
        if (op->bandwidth == 8)
                pllbuf[4] |= 0x04;
 
-       return 0;
+       return 5;
 }
 
 static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
@@ -557,43 +566,18 @@ static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
 static struct mt352_config digitv_alps_tded4_config = {
        .demod_address = 0x0a,
        .demod_init = digitv_alps_tded4_demod_init,
-       .pll_set = digitv_alps_tded4_pll_set,
 };
 
-static int tdvs_tua6034_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
-       u8 buf[4];
-       struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-       int err;
-
-       dvb_pll_configure(&dvb_pll_tdvs_tua6034, buf, params->frequency, 0);
-       dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-               __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
-       if ((err = i2c_transfer(card->i2c_adapter, &msg, 1)) != 1) {
-               printk(KERN_WARNING "dvb-bt8xx: %s error "
-                       "(addr %02x <- %02x, err = %i)\n",
-                       __FUNCTION__, buf[0], buf[1], err);
-               if (err < 0)
-                       return err;
-               else
-                       return -EREMOTEIO;
-       }
-
-       /* Set the Auxiliary Byte. */
-       buf[2] &= ~0x20;
-       buf[2] |= 0x18;
-       buf[3] = 0x50;
-       i2c_transfer(card->i2c_adapter, &msg, 1);
-
-       return 0;
+       return lg_h06xf_pll_set(fe, card->i2c_adapter, params);
 }
 
 static struct lgdt330x_config tdvs_tua6034_config = {
        .demod_address    = 0x0e,
        .demod_chip       = LGDT3303,
        .serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-       .pll_set          = tdvs_tua6034_pll_set,
 };
 
 static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
@@ -617,17 +601,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
        switch(type) {
        case BTTV_BOARD_DVICO_DVBT_LITE:
                card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
+
+               if (card->fe == NULL)
+                       card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config,
+                                                 card->i2c_adapter);
+
                if (card->fe != NULL) {
-                       card->fe->ops->info.frequency_min = 174000000;
-                       card->fe->ops->info.frequency_max = 862000000;
+                       card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs;
+                       card->fe->ops.info.frequency_min = 174000000;
+                       card->fe->ops.info.frequency_max = 862000000;
                }
                break;
 
        case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
                lgdt330x_reset(card);
                card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
-               if (card->fe != NULL)
+               if (card->fe != NULL) {
+                       card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
                        dprintk ("dvb_bt8xx: lgdt330x detected\n");
+               }
                break;
 
        case BTTV_BOARD_NEBULA_DIGITV:
@@ -640,6 +632,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                digitv_alps_tded4_reset(card);
                card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
                if (card->fe != NULL) {
+                       card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
                        dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
                        break;
                }
@@ -648,19 +641,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                digitv_alps_tded4_reset(card);
                card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
 
-               if (card->fe != NULL)
+               if (card->fe != NULL) {
+                       card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
                        dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
+               }
                break;
 
        case BTTV_BOARD_AVDVBT_761:
                card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
+               if (card->fe) {
+                       card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
+               }
                break;
 
        case BTTV_BOARD_AVDVBT_771:
                card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
                if (card->fe != NULL) {
-                       card->fe->ops->info.frequency_min = 174000000;
-                       card->fe->ops->info.frequency_max = 862000000;
+                       card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
+                       card->fe->ops.info.frequency_min = 174000000;
+                       card->fe->ops.info.frequency_max = 862000000;
                }
                break;
 
@@ -687,6 +686,11 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 
        case BTTV_BOARD_PINNACLESAT:
                card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
+               if (card->fe) {
+                       card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
+                       card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
+                       card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params;
+               }
                break;
 
        case BTTV_BOARD_PC_HDTV:
@@ -703,8 +707,8 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
        else
                if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
                        printk("dvb-bt8xx: Frontend registration failed!\n");
-                       if (card->fe->ops->release)
-                               card->fe->ops->release(card->fe);
+                       if (card->fe->ops.release)
+                               card->fe->ops.release(card->fe);
                        card->fe = NULL;
                }
 }
@@ -713,7 +717,7 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
 {
        int result;
 
-       if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) {
+       if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) {
                printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
                return result;
        }
index 00dd9fa54c82cbeefc3a07fbce4aa5b8843b69c5..4745a9017a1993476f82e2fae5f6ef049ed5910c 100644 (file)
@@ -37,6 +37,8 @@
 #include "cx24110.h"
 #include "or51211.h"
 #include "lgdt330x.h"
+#include "lg_h06xf.h"
+#include "zl10353.h"
 
 struct dvb_bt8xx_card {
        struct mutex lock;
index 6018fcdba1e6dc6ec02fa9a61d1a742c6b2bca71..b5cdd57ec6f51e9d34c07d0bb61368fe438296ab 100644 (file)
@@ -64,7 +64,7 @@ config DVB_CINERGYT2_QUERY_INTERVAL
 config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
        bool "Register the onboard IR Remote Control Receiver as Input Device"
        depends on DVB_CINERGYT2_TUNING
-       default "yes"
+       default y
        help
          Enable this option if you want to use the onboard Infrared Remote
          Control Receiver as Linux-Input device.
index 9325d039ea652c622071b04d8c31ed7e6ff473ef..1b895360042531722a60830aca59e455a1f93913 100644 (file)
@@ -544,15 +544,19 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
 {
        struct dvb_device *dvbdev = file->private_data;
        struct cinergyt2 *cinergyt2 = dvbdev->priv;
+       unsigned int mask = 0;
 
        if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
                return -ERESTARTSYS;
 
        poll_wait(file, &cinergyt2->poll_wq, wait);
 
+       if (cinergyt2->pending_fe_events != 0)
+               mask |= (POLLIN | POLLRDNORM | POLLPRI);
+
        mutex_unlock(&cinergyt2->sem);
 
-       return (POLLIN | POLLRDNORM | POLLPRI);
+       return mask;
 }
 
 
@@ -902,7 +906,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
                return -ENOMEM;
        }
 
-       if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE)) < 0) {
+       if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) {
                kfree(cinergyt2);
                return err;
        }
index 7adb50c1e8ebb0c3f9ab8a5e60c9c9f7784b4328..11054657fdb507491dd4d944ace466bbc6ba7a35 100644 (file)
@@ -2,8 +2,8 @@
 # Makefile for the kernel DVB device drivers.
 #
 
-dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
-               dvb_ca_en50221.o dvb_frontend.o \
-               dvb_net.o dvb_ringbuffer.o
+dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o     \
+               dvb_ca_en50221.o dvb_frontend.o                 \
+               dvb_net.o dvb_ringbuffer.o dvb_math.o
 
 obj-$(CONFIG_DVB_CORE) += dvb-core.o
index 04578df3f24910dd25fa8bbea25b90344cb4c1ed..988499dfddf8d8d17bcffbb6522231f9d1485fd0 100644 (file)
@@ -872,9 +872,6 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
                mutex_unlock(&dmxdevfilter->mutex);
                break;
 
-       case DMX_GET_EVENT:
-               break;
-
        case DMX_GET_PES_PIDS:
                if (!dmxdev->demux->get_pes_pids) {
                        ret = -EINVAL;
index 00347a750681942db7775769de7f7f2cf8f3eea3..2a03bf53cb2960b2c23ac1c387924f9f284b8f54 100644 (file)
@@ -1060,8 +1060,18 @@ static int dvb_ca_en50221_thread(void *data)
                                break;
 
                        case DVB_CA_SLOTSTATE_VALIDATE:
-                               if (dvb_ca_en50221_parse_attributes(ca, slot)
-                                   != 0) {
+                               if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
+                                       /* we need this extra check for annoying interfaces like the budget-av */
+                                       if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
+                                           (ca->pub->poll_slot_status)) {
+                                               int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+                                               if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
+                                                       ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+                                                       dvb_ca_en50221_thread_update_delay(ca);
+                                                       break;
+                                               }
+                                       }
+
                                        printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
                                               ca->dvbdev->adapter->num);
                                        ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
@@ -1108,6 +1118,17 @@ static int dvb_ca_en50221_thread(void *data)
 
                        case DVB_CA_SLOTSTATE_LINKINIT:
                                if (dvb_ca_en50221_link_init(ca, slot) != 0) {
+                                       /* we need this extra check for annoying interfaces like the budget-av */
+                                       if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
+                                           (ca->pub->poll_slot_status)) {
+                                               int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+                                               if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
+                                                       ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+                                                       dvb_ca_en50221_thread_update_delay(ca);
+                                                       break;
+                                               }
+                                       }
+
                                        printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
                                        ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
                                        dvb_ca_en50221_thread_update_delay(ca);
index 83ec5e06c48287ea538ae31920c978b0e3c83a53..fcff5eab21a3fc050d5207f9538c99d6c6ee63bd 100644 (file)
@@ -473,7 +473,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
                        goto bailout;
                }
                memcpy(&demux->tsbuf[i], buf, j);
-               if ((demux->tsbuf[0] == 0x47) | (demux->tsbuf[0] == 0xB8)) {
+               if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) {
                        memcpy(tmppack, demux->tsbuf, 188);
                        if (tmppack[0] == 0xB8)
                                tmppack[0] = 0x47;
@@ -484,7 +484,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
        }
 
        while (p < count) {
-               if ((buf[p] == 0x47) | (buf[p] == 0xB8)) {
+               if ((buf[p] == 0x47) || (buf[p] == 0xB8)) {
                        if (count - p >= 204) {
                                memcpy(tmppack, &buf[p], 188);
                                if (tmppack[0] == 0xB8)
index a051790161b095f674010e0e286c882f8df0b0a3..3152a54a2539ea2aef88abafe350186597961c4d 100644 (file)
@@ -56,7 +56,7 @@ MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AU
 module_param(dvb_override_tune_delay, int, 0644);
 MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
 module_param(dvb_powerdown_on_sleep, int, 0644);
-MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)");
+MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
 
 #define dprintk if (dvb_frontend_debug) printk
 
@@ -72,6 +72,8 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB vola
 #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
 #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
 #define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
+
+#define FE_ALGO_HW             1
 /*
  * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
  * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
@@ -151,8 +153,8 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
                sizeof (struct dvb_frontend_parameters));
 
        if (status & FE_HAS_LOCK)
-               if (fe->ops->get_frontend)
-                       fe->ops->get_frontend(fe, &e->parameters);
+               if (fe->ops.get_frontend)
+                       fe->ops.get_frontend(fe, &e->parameters);
 
        events->eventw = wp;
 
@@ -211,10 +213,15 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
 {
        dprintk ("DVB: initialising frontend %i (%s)...\n",
                 fe->dvb->num,
-                fe->ops->info.name);
-
-       if (fe->ops->init)
-               fe->ops->init(fe);
+                fe->ops.info.name);
+
+       if (fe->ops.init)
+               fe->ops.init(fe);
+       if (fe->ops.tuner_ops.init) {
+               fe->ops.tuner_ops.init(fe);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 }
 
 void dvb_frontend_reinitialise(struct dvb_frontend *fe)
@@ -259,7 +266,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
        u32 original_frequency = fepriv->parameters.frequency;
 
        /* are we using autoinversion? */
-       autoinversion = ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+       autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
                         (fepriv->parameters.inversion == INVERSION_AUTO));
 
        /* setup parameters correctly */
@@ -329,8 +336,8 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
        fepriv->parameters.frequency += fepriv->lnb_drift;
        if (autoinversion)
                fepriv->parameters.inversion = fepriv->inversion;
-       if (fe->ops->set_frontend)
-               fe->ops->set_frontend(fe, &fepriv->parameters);
+       if (fe->ops.set_frontend)
+               fe->ops.set_frontend(fe, &fepriv->parameters);
 
        fepriv->parameters.frequency = original_frequency;
        fepriv->parameters.inversion = original_inversion;
@@ -354,8 +361,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
        /* in SCAN mode, we just set the frontend when asked and leave it alone */
        if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
                if (fepriv->state & FESTATE_RETUNE) {
-                       if (fe->ops->set_frontend)
-                               fe->ops->set_frontend(fe, &fepriv->parameters);
+                       if (fe->ops.set_frontend)
+                               fe->ops.set_frontend(fe, &fepriv->parameters);
                        fepriv->state = FESTATE_TUNED;
                }
                fepriv->delay = 3*HZ;
@@ -367,8 +374,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
        if (fepriv->state & FESTATE_RETUNE) {
                s = 0;
        } else {
-               if (fe->ops->read_status)
-                       fe->ops->read_status(fe, &s);
+               if (fe->ops.read_status)
+                       fe->ops.read_status(fe, &s);
                if (s != fepriv->status) {
                        dvb_frontend_add_event(fe, s);
                        fepriv->status = s;
@@ -381,7 +388,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
                fepriv->state = FESTATE_TUNED;
 
                /* if we're tuned, then we have determined the correct inversion */
-               if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+               if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
                    (fepriv->parameters.inversion == INVERSION_AUTO)) {
                        fepriv->parameters.inversion = fepriv->inversion;
                }
@@ -405,7 +412,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
        /* don't actually do anything if we're in the LOSTLOCK state,
         * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
        if ((fepriv->state & FESTATE_LOSTLOCK) &&
-           (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
+           (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
                dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
                return;
        }
@@ -540,16 +547,16 @@ static int dvb_frontend_thread(void *data)
                if (fepriv->reinitialise) {
                        dvb_frontend_init(fe);
                        if (fepriv->tone != -1) {
-                               fe->ops->set_tone(fe, fepriv->tone);
+                               fe->ops.set_tone(fe, fepriv->tone);
                        }
                        if (fepriv->voltage != -1) {
-                               fe->ops->set_voltage(fe, fepriv->voltage);
+                               fe->ops.set_voltage(fe, fepriv->voltage);
                        }
                        fepriv->reinitialise = 0;
                }
 
                /* do an iteration of the tuning loop */
-               if (fe->ops->tune) {
+               if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
                        /* have we been asked to retune? */
                        params = NULL;
                        if (fepriv->state & FESTATE_RETUNE) {
@@ -557,7 +564,7 @@ static int dvb_frontend_thread(void *data)
                                fepriv->state = FESTATE_TUNED;
                        }
 
-                       fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+                       fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
                        if (s != fepriv->status) {
                                dvb_frontend_add_event(fe, s);
                                fepriv->status = s;
@@ -569,10 +576,15 @@ static int dvb_frontend_thread(void *data)
 
        if (dvb_shutdown_timeout) {
                if (dvb_powerdown_on_sleep)
-                       if (fe->ops->set_voltage)
-                               fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF);
-               if (fe->ops->sleep)
-                       fe->ops->sleep(fe);
+                       if (fe->ops.set_voltage)
+                               fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
+               if (fe->ops.tuner_ops.sleep) {
+                       fe->ops.tuner_ops.sleep(fe);
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 0);
+               }
+               if (fe->ops.sleep)
+                       fe->ops.sleep(fe);
        }
 
        fepriv->thread_pid = 0;
@@ -724,7 +736,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
        switch (cmd) {
        case FE_GET_INFO: {
                struct dvb_frontend_info* info = parg;
-               memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info));
+               memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
 
                /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
                 * do it, it is done for it. */
@@ -744,58 +756,58 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        break;
                }
 
-               if (fe->ops->read_status)
-                       err = fe->ops->read_status(fe, status);
+               if (fe->ops.read_status)
+                       err = fe->ops.read_status(fe, status);
                break;
        }
        case FE_READ_BER:
-               if (fe->ops->read_ber)
-                       err = fe->ops->read_ber(fe, (__u32*) parg);
+               if (fe->ops.read_ber)
+                       err = fe->ops.read_ber(fe, (__u32*) parg);
                break;
 
        case FE_READ_SIGNAL_STRENGTH:
-               if (fe->ops->read_signal_strength)
-                       err = fe->ops->read_signal_strength(fe, (__u16*) parg);
+               if (fe->ops.read_signal_strength)
+                       err = fe->ops.read_signal_strength(fe, (__u16*) parg);
                break;
 
        case FE_READ_SNR:
-               if (fe->ops->read_snr)
-                       err = fe->ops->read_snr(fe, (__u16*) parg);
+               if (fe->ops.read_snr)
+                       err = fe->ops.read_snr(fe, (__u16*) parg);
                break;
 
        case FE_READ_UNCORRECTED_BLOCKS:
-               if (fe->ops->read_ucblocks)
-                       err = fe->ops->read_ucblocks(fe, (__u32*) parg);
+               if (fe->ops.read_ucblocks)
+                       err = fe->ops.read_ucblocks(fe, (__u32*) parg);
                break;
 
 
        case FE_DISEQC_RESET_OVERLOAD:
-               if (fe->ops->diseqc_reset_overload) {
-                       err = fe->ops->diseqc_reset_overload(fe);
+               if (fe->ops.diseqc_reset_overload) {
+                       err = fe->ops.diseqc_reset_overload(fe);
                        fepriv->state = FESTATE_DISEQC;
                        fepriv->status = 0;
                }
                break;
 
        case FE_DISEQC_SEND_MASTER_CMD:
-               if (fe->ops->diseqc_send_master_cmd) {
-                       err = fe->ops->diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
+               if (fe->ops.diseqc_send_master_cmd) {
+                       err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
                        fepriv->state = FESTATE_DISEQC;
                        fepriv->status = 0;
                }
                break;
 
        case FE_DISEQC_SEND_BURST:
-               if (fe->ops->diseqc_send_burst) {
-                       err = fe->ops->diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
+               if (fe->ops.diseqc_send_burst) {
+                       err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
                        fepriv->state = FESTATE_DISEQC;
                        fepriv->status = 0;
                }
                break;
 
        case FE_SET_TONE:
-               if (fe->ops->set_tone) {
-                       err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
+               if (fe->ops.set_tone) {
+                       err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg);
                        fepriv->tone = (fe_sec_tone_mode_t) parg;
                        fepriv->state = FESTATE_DISEQC;
                        fepriv->status = 0;
@@ -803,8 +815,8 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                break;
 
        case FE_SET_VOLTAGE:
-               if (fe->ops->set_voltage) {
-                       err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg);
+               if (fe->ops.set_voltage) {
+                       err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg);
                        fepriv->voltage = (fe_sec_voltage_t) parg;
                        fepriv->state = FESTATE_DISEQC;
                        fepriv->status = 0;
@@ -812,11 +824,11 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                break;
 
        case FE_DISHNETWORK_SEND_LEGACY_CMD:
-               if (fe->ops->dishnetwork_send_legacy_command) {
-                       err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg);
+               if (fe->ops.dishnetwork_send_legacy_command) {
+                       err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg);
                        fepriv->state = FESTATE_DISEQC;
                        fepriv->status = 0;
-               } else if (fe->ops->set_voltage) {
+               } else if (fe->ops.set_voltage) {
                        /*
                         * NOTE: This is a fallback condition.  Some frontends
                         * (stv0299 for instance) take longer than 8msec to
@@ -846,7 +858,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        /* before sending a command, initialize by sending
                         * a 32ms 18V to the switch
                         */
-                       fe->ops->set_voltage(fe, SEC_VOLTAGE_18);
+                       fe->ops.set_voltage(fe, SEC_VOLTAGE_18);
                        dvb_frontend_sleep_until(&nexttime, 32000);
 
                        for (i = 0; i < 9; i++) {
@@ -854,7 +866,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                                        do_gettimeofday(&tv[i + 1]);
                                if ((cmd & 0x01) != last) {
                                        /* set voltage to (last ? 13V : 18V) */
-                                       fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
+                                       fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
                                        last = (last) ? 0 : 1;
                                }
                                cmd = cmd >> 1;
@@ -874,13 +886,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                break;
 
        case FE_DISEQC_RECV_SLAVE_REPLY:
-               if (fe->ops->diseqc_recv_slave_reply)
-                       err = fe->ops->diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
+               if (fe->ops.diseqc_recv_slave_reply)
+                       err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
                break;
 
        case FE_ENABLE_HIGH_LNB_VOLTAGE:
-               if (fe->ops->enable_high_lnb_voltage)
-                       err = fe->ops->enable_high_lnb_voltage(fe, (long) parg);
+               if (fe->ops.enable_high_lnb_voltage)
+                       err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
                break;
 
        case FE_SET_FRONTEND: {
@@ -898,7 +910,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                        fepriv->parameters.inversion = INVERSION_AUTO;
                        fetunesettings.parameters.inversion = INVERSION_AUTO;
                }
-               if (fe->ops->info.type == FE_OFDM) {
+               if (fe->ops.info.type == FE_OFDM) {
                        /* without hierachical coding code_rate_LP is irrelevant,
                         * so we tolerate the otherwise invalid FEC_NONE setting */
                        if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
@@ -907,13 +919,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                }
 
                /* get frontend-specific tuning settings */
-               if (fe->ops->get_tune_settings && (fe->ops->get_tune_settings(fe, &fetunesettings) == 0)) {
+               if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
                        fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
                        fepriv->max_drift = fetunesettings.max_drift;
                        fepriv->step_size = fetunesettings.step_size;
                } else {
                        /* default values */
-                       switch(fe->ops->info.type) {
+                       switch(fe->ops.info.type) {
                        case FE_QPSK:
                                fepriv->min_delay = HZ/20;
                                fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
@@ -928,11 +940,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 
                        case FE_OFDM:
                                fepriv->min_delay = HZ/20;
-                               fepriv->step_size = fe->ops->info.frequency_stepsize * 2;
-                               fepriv->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1;
+                               fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
+                               fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
                                break;
                        case FE_ATSC:
-                               printk("dvb-core: FE_ATSC not handled yet.\n");
+                               fepriv->min_delay = HZ/20;
+                               fepriv->step_size = 0;
+                               fepriv->max_drift = 0;
                                break;
                        }
                }
@@ -952,9 +966,9 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
                break;
 
        case FE_GET_FRONTEND:
-               if (fe->ops->get_frontend) {
+               if (fe->ops.get_frontend) {
                        memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
-                       err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
+                       err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
                }
                break;
 
@@ -1067,7 +1081,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
 
        printk ("DVB: registering frontend %i (%s)...\n",
                fe->dvb->num,
-               fe->ops->info.name);
+               fe->ops.info.name);
 
        dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
                             fe, DVB_DEVICE_FRONTEND);
@@ -1085,10 +1099,15 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
        mutex_lock(&frontend_mutex);
        dvb_unregister_device (fepriv->dvbdev);
        dvb_frontend_stop (fe);
-       if (fe->ops->release)
-               fe->ops->release(fe);
+       if (fe->ops.tuner_ops.release) {
+               fe->ops.tuner_ops.release(fe);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+       if (fe->ops.release)
+               fe->ops.release(fe);
        else
-               printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name);
+               printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name);
        /* fe is invalid now */
        kfree(fepriv);
        mutex_unlock(&frontend_mutex);
index 5926a3b745c9d5525caa074578030f652b634223..2887e2b862a4436d1002a5dcee6ffafb1b5aba1f 100644 (file)
@@ -49,6 +49,44 @@ struct dvb_frontend_tune_settings {
 
 struct dvb_frontend;
 
+struct dvb_tuner_info {
+       char name[128];
+
+       u32 frequency_min;
+       u32 frequency_max;
+       u32 frequency_step;
+
+       u32 bandwidth_min;
+       u32 bandwidth_max;
+       u32 bandwidth_step;
+};
+
+struct dvb_tuner_ops {
+
+       struct dvb_tuner_info info;
+
+       int (*release)(struct dvb_frontend *fe);
+       int (*init)(struct dvb_frontend *fe);
+       int (*sleep)(struct dvb_frontend *fe);
+
+       /** This is for simple PLLs - set all parameters in one go. */
+       int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+
+       /** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
+       int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
+
+       int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
+       int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+
+#define TUNER_STATUS_LOCKED 1
+       int (*get_status)(struct dvb_frontend *fe, u32 *status);
+
+       /** These are provided seperately from set_params in order to facilitate silicon
+        * tuners which require sophisticated tuning loops, controlling each parameter seperately. */
+       int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
+       int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+};
+
 struct dvb_frontend_ops {
 
        struct dvb_frontend_info info;
@@ -64,6 +102,8 @@ struct dvb_frontend_ops {
                    unsigned int mode_flags,
                    int *delay,
                    fe_status_t *status);
+       /* get frontend tuning algorithm from the module */
+       int (*get_frontend_algo)(struct dvb_frontend *fe);
 
        /* these two are only used for the swzigzag code */
        int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
@@ -86,6 +126,8 @@ struct dvb_frontend_ops {
        int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
        int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
        int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
+
+       struct dvb_tuner_ops tuner_ops;
 };
 
 #define MAX_EVENT 8
@@ -100,9 +142,10 @@ struct dvb_fe_events {
 };
 
 struct dvb_frontend {
-       struct dvb_frontend_ops* ops;
+       struct dvb_frontend_ops ops;
        struct dvb_adapter *dvb;
        void* demodulator_priv;
+       void* tuner_priv;
        void* frontend_priv;
        void* misc_priv;
 };
diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c
new file mode 100644 (file)
index 0000000..beb7c93
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/bug.h>
+#include "dvb_math.h"
+
+static const unsigned short logtable[256] = {
+       0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
+       0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508,
+       0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6,
+       0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37,
+       0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f,
+       0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41,
+       0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1,
+       0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142,
+       0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68,
+       0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355,
+       0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c,
+       0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490,
+       0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3,
+       0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507,
+       0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe,
+       0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca,
+       0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c,
+       0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7,
+       0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c,
+       0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c,
+       0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a,
+       0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065,
+       0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730,
+       0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc,
+       0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469,
+       0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9,
+       0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c,
+       0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765,
+       0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
+       0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
+       0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
+       0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
+};
+
+unsigned int intlog2(u32 value)
+{
+       /**
+        *      returns: log2(value) * 2^24
+        *      wrong result if value = 0 (log2(0) is undefined)
+        */
+       unsigned int msb;
+       unsigned int logentry;
+       unsigned int significand;
+       unsigned int interpolation;
+
+       if (unlikely(value == 0)) {
+               WARN_ON(1);
+               return 0;
+       }
+
+       /* first detect the msb (count begins at 0) */
+       msb = fls(value) - 1;
+
+       /**
+        *      now we use a logtable after the following method:
+        *
+        *      log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24
+        *      where x = msb and therefore 1 <= y < 2
+        *      first y is determined by shifting the value left
+        *      so that msb is bit 31
+        *              0x00231f56 -> 0x8C7D5800
+        *      the result is y * 2^31 -> "significand"
+        *      then the highest 9 bits are used for a table lookup
+        *      the highest bit is discarded because it's always set
+        *      the highest nine bits in our example are 100011000
+        *      so we would use the entry 0x18
+        */
+       significand = value << (31 - msb);
+       logentry = (significand >> 23) & 0xff;
+
+       /**
+        *      last step we do is interpolation because of the
+        *      limitations of the log table the error is that part of
+        *      the significand which isn't used for lookup then we
+        *      compute the ratio between the error and the next table entry
+        *      and interpolate it between the log table entry used and the
+        *      next one the biggest error possible is 0x7fffff
+        *      (in our example it's 0x7D5800)
+        *      needed value for next table entry is 0x800000
+        *      so the interpolation is
+        *      (error / 0x800000) * (logtable_next - logtable_current)
+        *      in the implementation the division is moved to the end for
+        *      better accuracy there is also an overflow correction if
+        *      logtable_next is 256
+        */
+       interpolation = ((significand & 0x7fffff) *
+                       ((logtable[(logentry + 1) & 0xff] -
+                         logtable[logentry]) & 0xffff)) >> 15;
+
+       /* now we return the result */
+       return ((msb << 24) + (logtable[logentry] << 8) + interpolation);
+}
+EXPORT_SYMBOL(intlog2);
+
+unsigned int intlog10(u32 value)
+{
+       /**
+        *      returns: log10(value) * 2^24
+        *      wrong result if value = 0 (log10(0) is undefined)
+        */
+       u64 log;
+
+       if (unlikely(value == 0)) {
+               WARN_ON(1);
+               return 0;
+       }
+
+       log = intlog2(value);
+
+       /**
+        *      we use the following method:
+        *      log10(x) = log2(x) * log10(2)
+        */
+
+       return (log * 646456993) >> 31;
+}
+EXPORT_SYMBOL(intlog10);
diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb/dvb-core/dvb_math.h
new file mode 100644 (file)
index 0000000..aecc867
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __DVB_MATH_H
+#define __DVB_MATH_H
+
+#include <linux/types.h>
+
+/**
+ * computes log2 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ *   intlog2(value) = intlog2(value * 2^x) - x * 2^24
+ *
+ * example: intlog2(8) will give 3 << 24 = 3 * 2^24
+ * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
+ * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
+ *
+ * @param value The value (must be != 0)
+ * @return log2(value) * 2^24
+ */
+extern unsigned int intlog2(u32 value);
+
+/**
+ * computes log10 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ *   intlog10(value) = intlog10(value * 10^x) - x * 2^24
+ *
+ * example: intlog10(1000) will give 3 << 24 = 3 * 2^24
+ *   due to the implementation intlog10(1000) might be not exactly 3 * 2^24
+ *
+ * look at intlog2 for similar examples
+ *
+ * @param value The value (must be != 0)
+ * @return log10(value) * 2^24
+ */
+extern unsigned int intlog10(u32 value);
+
+#endif
index 9fd87521a1639bd3dae51dcdce48545614d41a85..8859ab74f0fe4c65c8e75b9350a2a0b138615525 100644 (file)
@@ -12,7 +12,7 @@
  *                          Hilmar Linder <hlinder@cosy.sbg.ac.at>
  *                      and Wolfram Stering <wstering@cosy.sbg.ac.at>
  *
- * ULE Decaps according to draft-ietf-ipdvb-ule-03.txt.
+ * ULE Decaps according to RFC 4326.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -42,6 +42,9 @@
  *                     Bugfixes and robustness improvements.
  *                     Filtering on dest MAC addresses, if present (D-Bit = 0)
  *                     ULE_DEBUG compile-time option.
+ * Apr 2006: cp v3:    Bugfixes and compliency with RFC 4326 (ULE) by
+ *                       Christian Praehauser <cpraehaus@cosy.sbg.ac.at>,
+ *                       Paris Lodron University of Salzburg.
  */
 
 /*
@@ -49,9 +52,6 @@
  *
  * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero.
  *
- * TS_FEED callback is called once for every single TS cell although it is
- * registered (in dvb_net_feed_start()) for 100 TS cells (used for dvb_net_ule()).
- *
  */
 
 #include <linux/module.h>
@@ -89,6 +89,9 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
 
 #ifdef ULE_DEBUG
 
+#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
+#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5]
+
 #define isprint(c)     ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
 
 static void hexdump( const unsigned char *buf, unsigned short len )
@@ -214,6 +217,8 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
 #define ULE_TEST       0
 #define ULE_BRIDGED    1
 
+#define ULE_OPTEXTHDR_PADDING 0
+
 static int ule_test_sndu( struct dvb_net_priv *p )
 {
        return -1;
@@ -221,14 +226,28 @@ static int ule_test_sndu( struct dvb_net_priv *p )
 
 static int ule_bridged_sndu( struct dvb_net_priv *p )
 {
-       /* BRIDGE SNDU handling sucks in draft-ietf-ipdvb-ule-03.txt.
-        * This has to be the last extension header, otherwise it won't work.
-        * Blame the authors!
+       struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr;
+       if(ntohs(hdr->h_proto) < 1536) {
+               int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data);
+               /* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */
+               if(framelen != ntohs(hdr->h_proto)) {
+                       return -1;
+               }
+       }
+       /* Note:
+        * From RFC4326:
+        *  "A bridged SNDU is a Mandatory Extension Header of Type 1.
+        *   It must be the final (or only) extension header specified in the header chain of a SNDU."
+        * The 'ule_bridged' flag will cause the extension header processing loop to terminate.
         */
        p->ule_bridged = 1;
        return 0;
 }
 
+static int ule_exthdr_padding(struct dvb_net_priv *p)
+{
+       return 0;
+}
 
 /** Handle ULE extension headers.
  *  Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
@@ -242,7 +261,8 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
                { [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL,  };
 
        /* Table of optional extension header handlers.  The header type is the index. */
-       static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = { NULL, };
+       static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) =
+               { [0] = ule_exthdr_padding, [1] = NULL, };
 
        int ext_len = 0;
        unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8;
@@ -253,25 +273,31 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
                /* Mandatory extension header */
                if (ule_mandatory_ext_handlers[htype]) {
                        ext_len = ule_mandatory_ext_handlers[htype]( p );
-                       p->ule_next_hdr += ext_len;
-                       if (! p->ule_bridged) {
-                               p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr );
-                               p->ule_next_hdr += 2;
-                       } else {
-                               p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)) );
-                               /* This assures the extension handling loop will terminate. */
+                       if(ext_len >= 0) {
+                               p->ule_next_hdr += ext_len;
+                               if (!p->ule_bridged) {
+                                       p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr);
+                                       p->ule_next_hdr += 2;
+                               } else {
+                                       p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
+                                       /* This assures the extension handling loop will terminate. */
+                               }
                        }
+                       // else: extension handler failed or SNDU should be discarded
                } else
                        ext_len = -1;   /* SNDU has to be discarded. */
        } else {
                /* Optional extension header.  Calculate the length. */
-               ext_len = hlen << 2;
+               ext_len = hlen << 1;
                /* Process the optional extension header according to its type. */
                if (ule_optional_ext_handlers[htype])
                        (void)ule_optional_ext_handlers[htype]( p );
                p->ule_next_hdr += ext_len;
-               p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr );
-               p->ule_next_hdr += 2;
+               p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) );
+               /*
+                * note: the length of the next header type is included in the
+                * length of THIS optional extension header
+                */
        }
 
        return ext_len;
@@ -284,8 +310,14 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
        p->ule_next_hdr = p->ule_skb->data;
        do {
                l = handle_one_ule_extension( p );
-               if (l == -1) return -1; /* Stop extension header processing and discard SNDU. */
+               if (l < 0)
+                       return l;       /* Stop extension header processing and discard SNDU. */
                total_ext_len += l;
+#ifdef ULE_DEBUG
+               dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, "
+                       "l=%i, total_ext_len=%i\n", p->ule_next_hdr,
+                       (int) p->ule_sndu_type, l, total_ext_len);
+#endif
 
        } while (p->ule_sndu_type < 1536);
 
@@ -355,8 +387,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                                if (priv->ule_skb) {
                                        dev_kfree_skb( priv->ule_skb );
                                        /* Prepare for next SNDU. */
-                                       ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-                                       ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
+                                       priv->stats.rx_errors++;
+                                       priv->stats.rx_frame_errors++;
                                }
                                reset_ule(priv);
                                priv->need_pusi = 1;
@@ -396,27 +428,25 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                        }
                }
 
-               /* Check continuity counter. */
                if (new_ts) {
+                       /* Check continuity counter. */
                        if ((ts[3] & 0x0F) == priv->tscc)
                                priv->tscc = (priv->tscc + 1) & 0x0F;
                        else {
                                /* TS discontinuity handling: */
                                printk(KERN_WARNING "%lu: TS discontinuity: got %#x, "
-                                      "exptected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
+                                      "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
                                /* Drop partly decoded SNDU, reset state, resync on PUSI. */
                                if (priv->ule_skb) {
                                        dev_kfree_skb( priv->ule_skb );
                                        /* Prepare for next SNDU. */
                                        // reset_ule(priv);  moved to below.
-                                       ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-                                       ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
+                                       priv->stats.rx_errors++;
+                                       priv->stats.rx_frame_errors++;
                                }
                                reset_ule(priv);
                                /* skip to next PUSI. */
                                priv->need_pusi = 1;
-                               ts += TS_SZ;
-                               priv->ts_count++;
                                continue;
                        }
                        /* If we still have an incomplete payload, but PUSI is
@@ -425,7 +455,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                         * cells (continuity counter wrap). */
                        if (ts[1] & TS_PUSI) {
                                if (! priv->need_pusi) {
-                                       if (*from_where > 181) {
+                                       if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) {
                                                /* Pointer field is invalid.  Drop this TS cell and any started ULE SNDU. */
                                                printk(KERN_WARNING "%lu: Invalid pointer "
                                                       "field: %u.\n", priv->ts_count, *from_where);
@@ -438,8 +468,6 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                                                }
                                                reset_ule(priv);
                                                priv->need_pusi = 1;
-                                               ts += TS_SZ;
-                                               priv->ts_count++;
                                                continue;
                                        }
                                        /* Skip pointer field (we're processing a
@@ -452,8 +480,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                                if (priv->ule_sndu_remain > 183) {
                                        /* Current SNDU lacks more data than there could be available in the
                                         * current TS cell. */
-                                       ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-                                       ((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++;
+                                       priv->stats.rx_errors++;
+                                       priv->stats.rx_length_errors++;
                                        printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
                                               "got PUSI (pf %d, ts_remain %d).  Flushing incomplete payload.\n",
                                               priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
@@ -492,9 +520,11 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                                } else
                                        priv->ule_dbit = 0;
 
-                               if (priv->ule_sndu_len > 32763) {
+                               if (priv->ule_sndu_len < 5) {
                                        printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
                                               "Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
+                                       priv->stats.rx_errors++;
+                                       priv->stats.rx_length_errors++;
                                        priv->ule_sndu_len = 0;
                                        priv->need_pusi = 1;
                                        new_ts = 1;
@@ -608,58 +638,103 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                                ule_dump = 1;
 #endif
 
-                               ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-                               ((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++;
+                               priv->stats.rx_errors++;
+                               priv->stats.rx_crc_errors++;
                                dev_kfree_skb(priv->ule_skb);
                        } else {
                                /* CRC32 verified OK. */
+                               u8 dest_addr[ETH_ALEN];
+                               static const u8 bc_addr[ETH_ALEN] =
+                                       { [ 0 ... ETH_ALEN-1] = 0xff };
+
+                               /* CRC32 was OK. Remove it from skb. */
+                               priv->ule_skb->tail -= 4;
+                               priv->ule_skb->len -= 4;
+
+                               if (!priv->ule_dbit) {
+                                       /*
+                                        * The destination MAC address is the
+                                        * next data in the skb.  It comes
+                                        * before any extension headers.
+                                        *
+                                        * Check if the payload of this SNDU
+                                        * should be passed up the stack.
+                                        */
+                                       register int drop = 0;
+                                       if (priv->rx_mode != RX_MODE_PROMISC) {
+                                               if (priv->ule_skb->data[0] & 0x01) {
+                                                       /* multicast or broadcast */
+                                                       if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) {
+                                                               /* multicast */
+                                                               if (priv->rx_mode == RX_MODE_MULTI) {
+                                                                       int i;
+                                                                       for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++)
+                                                                               ;
+                                                                       if (i == priv->multi_num)
+                                                                               drop = 1;
+                                                               } else if (priv->rx_mode != RX_MODE_ALL_MULTI)
+                                                                       drop = 1; /* no broadcast; */
+                                                               /* else: all multicast mode: accept all multicast packets */
+                                                       }
+                                                       /* else: broadcast */
+                                               }
+                                               else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN))
+                                                       drop = 1;
+                                               /* else: destination address matches the MAC address of our receiver device */
+                                       }
+                                       /* else: promiscious mode; pass everything up the stack */
+
+                                       if (drop) {
+#ifdef ULE_DEBUG
+                                               dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n",
+                                                       MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr));
+#endif
+                                               dev_kfree_skb(priv->ule_skb);
+                                               goto sndu_done;
+                                       }
+                                       else
+                                       {
+                                               memcpy(dest_addr,  priv->ule_skb->data, ETH_ALEN);
+                                               skb_pull(priv->ule_skb, ETH_ALEN);
+                                       }
+                               }
+
                                /* Handle ULE Extension Headers. */
                                if (priv->ule_sndu_type < 1536) {
                                        /* There is an extension header.  Handle it accordingly. */
-                                       int l = handle_ule_extensions( priv );
+                                       int l = handle_ule_extensions(priv);
                                        if (l < 0) {
                                                /* Mandatory extension header unknown or TEST SNDU.  Drop it. */
                                                // printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
-                                               dev_kfree_skb( priv->ule_skb );
+                                               dev_kfree_skb(priv->ule_skb);
                                                goto sndu_done;
                                        }
-                                       skb_pull( priv->ule_skb, l );
+                                       skb_pull(priv->ule_skb, l);
                                }
 
-                               /* CRC32 was OK. Remove it from skb. */
-                               priv->ule_skb->tail -= 4;
-                               priv->ule_skb->len -= 4;
-
-                               /* Filter on receiver's destination MAC address, if present. */
-                               if (!priv->ule_dbit) {
-                                       /* The destination MAC address is the next data in the skb. */
-                                       if (memcmp( priv->ule_skb->data, dev->dev_addr, ETH_ALEN )) {
-                                               /* MAC addresses don't match.  Drop SNDU. */
-                                               // printk( KERN_WARNING "Dropping SNDU, MAC address.\n" );
-                                               dev_kfree_skb( priv->ule_skb );
-                                               goto sndu_done;
-                                       }
-                                       if (! priv->ule_bridged) {
-                                               skb_push( priv->ule_skb, ETH_ALEN + 2 );
-                                               ethh = (struct ethhdr *)priv->ule_skb->data;
-                                               memcpy( ethh->h_dest, ethh->h_source, ETH_ALEN );
-                                               memset( ethh->h_source, 0, ETH_ALEN );
-                                               ethh->h_proto = htons( priv->ule_sndu_type );
-                                       } else {
-                                               /* Skip the Receiver destination MAC address. */
-                                               skb_pull( priv->ule_skb, ETH_ALEN );
-                                       }
-                               } else {
-                                       if (! priv->ule_bridged) {
-                                               skb_push( priv->ule_skb, ETH_HLEN );
-                                               ethh = (struct ethhdr *)priv->ule_skb->data;
-                                               memcpy( ethh->h_dest, dev->dev_addr, ETH_ALEN );
-                                               memset( ethh->h_source, 0, ETH_ALEN );
-                                               ethh->h_proto = htons( priv->ule_sndu_type );
-                                       } else {
-                                               /* skb is in correct state; nothing to do. */
+                               /*
+                                * Construct/assure correct ethernet header.
+                                * Note: in bridged mode (priv->ule_bridged !=
+                                * 0) we already have the (original) ethernet
+                                * header at the start of the payload (after
+                                * optional dest. address and any extension
+                                * headers).
+                                */
+
+                               if (!priv->ule_bridged) {
+                                       skb_push(priv->ule_skb, ETH_HLEN);
+                                       ethh = (struct ethhdr *)priv->ule_skb->data;
+                                       if (!priv->ule_dbit) {
+                                                /* dest_addr buffer is only valid if priv->ule_dbit == 0 */
+                                               memcpy(ethh->h_dest, dest_addr, ETH_ALEN);
+                                               memset(ethh->h_source, 0, ETH_ALEN);
                                        }
+                                       else /* zeroize source and dest */
+                                               memset( ethh, 0, ETH_ALEN*2 );
+
+                                       ethh->h_proto = htons(priv->ule_sndu_type);
                                }
+                               /* else:  skb is in correct state; nothing to do. */
                                priv->ule_bridged = 0;
 
                                /* Stuff into kernel's protocol stack. */
@@ -668,8 +743,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                                 * receive the packet anyhow. */
                                /* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
                                        priv->ule_skb->pkt_type = PACKET_HOST; */
-                               ((struct dvb_net_priv *) dev->priv)->stats.rx_packets++;
-                               ((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len;
+                               priv->stats.rx_packets++;
+                               priv->stats.rx_bytes += priv->ule_skb->len;
                                netif_rx(priv->ule_skb);
                        }
                        sndu_done:
@@ -944,7 +1019,7 @@ static int dvb_net_feed_start(struct net_device *dev)
                dprintk("%s: start filtering\n", __FUNCTION__);
                priv->secfeed->start_filtering(priv->secfeed);
        } else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
-               struct timespec timeout = { 0, 30000000 }; // 30 msec
+               struct timespec timeout = { 0, 10000000 }; // 10 msec
 
                /* we have payloads encapsulated in TS */
                dprintk("%s: alloc tsfeed\n", __FUNCTION__);
@@ -956,10 +1031,13 @@ static int dvb_net_feed_start(struct net_device *dev)
 
                /* Set netdevice pointer for ts decaps callback. */
                priv->tsfeed->priv = (void *)dev;
-               ret = priv->tsfeed->set(priv->tsfeed, priv->pid,
-                                       TS_PACKET, DMX_TS_PES_OTHER,
+               ret = priv->tsfeed->set(priv->tsfeed,
+                                       priv->pid, /* pid */
+                                       TS_PACKET, /* type */
+                                       DMX_TS_PES_OTHER, /* pes type */
                                        32768,     /* circular buffer size */
-                                       timeout);
+                                       timeout    /* timeout */
+                                       );
 
                if (ret < 0) {
                        printk("%s: could not set ts feed\n", dev->name);
index 3852430d0260e65fc5daf8045c07bd19031933e0..134c2bbbeeb5f75e89921413850a0bffec367ed6 100644 (file)
@@ -236,7 +236,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
                        "dvb/adapter%d/%s%d", adap->num, dnames[type], id);
 
        class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
-                           NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
+                           adap->device, "dvb%d.%s%d", adap->num, dnames[type], id);
 
        dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
                adap->num, dnames[type], id, nums2minor(adap->num, type, id),
@@ -285,7 +285,7 @@ skip:
 }
 
 
-int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module)
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
 {
        int num;
 
@@ -306,6 +306,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
        adap->num = num;
        adap->name = name;
        adap->module = module;
+       adap->device = device;
 
        list_add_tail (&adap->list_head, &dvb_adapter_list);
 
index 74ed5853f0fb02c1d0be40518d7426b50c2d3b44..d7a976d040d72249ab8d5558529d328802356c4e 100644 (file)
@@ -51,6 +51,8 @@ struct dvb_adapter {
        u8 proposed_mac [6];
        void* priv;
 
+       struct device *device;
+
        struct module *module;
 };
 
@@ -76,7 +78,7 @@ struct dvb_device {
 };
 
 
-extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module);
+extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device);
 extern int dvb_unregister_adapter (struct dvb_adapter *adap);
 
 extern int dvb_register_device (struct dvb_adapter *adap,
index e388fb1567d6ec6d813158bc29516e07ecd8c496..3bc6722a6443e1e29e80382114a75c46a7d21527 100644 (file)
@@ -88,6 +88,7 @@ config DVB_USB_CXUSB
        select DVB_CX22702
        select DVB_LGDT330X
        select DVB_MT352
+       select DVB_ZL10353
        help
          Say Y here to support the Conexant USB2.0 hybrid reference design.
          Currently, only DVB and ATSC modes are supported, analog mode
@@ -130,6 +131,15 @@ config DVB_USB_VP702X
 
          DVB-S USB2.0 receivers.
 
+config DVB_USB_GP8PSK
+       tristate "GENPIX 8PSK->USB module support"
+       depends on DVB_USB
+       help
+         Say Y here to support the
+           GENPIX 8psk module
+
+         DVB-S USB2.0 receivers.
+
 config DVB_USB_NOVA_T_USB2
        tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
        depends on DVB_USB
index 2dc9aad9681e36825043ce1d0dd8628139fdaa3a..9643f56c7fe9a02e3f5e88e3d01bbd4875bf852a 100644 (file)
@@ -7,6 +7,9 @@ obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
 dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
 obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
 
+dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o
+obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o
+
 dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
 obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
 
index 1f0d3e995c8d67e64419b4493b56085719820204..ae23bdde42a82505271051024dd2d0509ec994cb 100644 (file)
 
 #include "cx22702.h"
 #include "lgdt330x.h"
+#include "lg_h06xf.h"
 #include "mt352.h"
 #include "mt352_priv.h"
+#include "zl10353.h"
 
 /* debug */
 int dvb_usb_cxusb_debug;
@@ -322,32 +324,37 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
+static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe,
+                                         struct dvb_frontend_parameters *fep)
+{
+       struct dvb_usb_device *d = fe->dvb->priv;
+       return lg_h06xf_pll_set(fe, &d->i2c_adap, fep);
+}
+
 static struct cx22702_config cxusb_cx22702_config = {
        .demod_address = 0x63,
 
        .output_mode = CX22702_PARALLEL_OUTPUT,
-
-       .pll_init = dvb_usb_pll_init_i2c,
-       .pll_set  = dvb_usb_pll_set_i2c,
 };
 
 static struct lgdt330x_config cxusb_lgdt3303_config = {
        .demod_address = 0x0e,
        .demod_chip    = LGDT3303,
-       .pll_set       = dvb_usb_pll_set_i2c,
 };
 
 static struct mt352_config cxusb_dee1601_config = {
        .demod_address = 0x0f,
        .demod_init    = cxusb_dee1601_demod_init,
-       .pll_set       = dvb_usb_pll_set,
 };
 
-struct mt352_config cxusb_mt352_config = {
+static struct zl10353_config cxusb_zl10353_dee1601_config = {
+       .demod_address = 0x0f,
+};
+
+static struct mt352_config cxusb_mt352_config = {
        /* used in both lgz201 and th7579 */
        .demod_address = 0x0f,
        .demod_init    = cxusb_mt352_demod_init,
-       .pll_set       = dvb_usb_pll_set,
 };
 
 /* Callbacks for DVB USB */
@@ -357,17 +364,10 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d)
        d->pll_addr = 0x61;
        memcpy(d->pll_init, bpll, 4);
        d->pll_desc = &dvb_pll_fmd1216me;
-       return 0;
-}
 
-static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d)
-{
-       u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 };
-       /* bpll[2] : unset bit 3, set bits 4&5
-          bpll[3] : 0x50 - digital, 0x20 - analog */
-       d->pll_addr = 0x61;
-       memcpy(d->pll_init, bpll, 4);
-       d->pll_desc = &dvb_pll_tdvs_tua6034;
+       d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+       d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+
        return 0;
 }
 
@@ -375,6 +375,7 @@ static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d)
 {
        d->pll_addr = 0x61;
        d->pll_desc = &dvb_pll_thomson_dtt7579;
+       d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
        return 0;
 }
 
@@ -382,6 +383,7 @@ static int cxusb_lgz201_tuner_attach(struct dvb_usb_device *d)
 {
        d->pll_addr = 0x61;
        d->pll_desc = &dvb_pll_lg_z201;
+       d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
        return 0;
 }
 
@@ -389,6 +391,13 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_device *d)
 {
        d->pll_addr = 0x60;
        d->pll_desc = &dvb_pll_thomson_dtt7579;
+       d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+       return 0;
+}
+
+static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_device *d)
+{
+       d->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
        return 0;
 }
 
@@ -439,7 +448,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
 
        cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
 
-       if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL)
+       if (((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
+           ((d->fe = zl10353_attach(&cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
                return 0;
 
        return -EIO;
@@ -555,7 +565,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
        .streaming_ctrl   = cxusb_streaming_ctrl,
        .power_ctrl       = cxusb_bluebird_power_ctrl,
        .frontend_attach  = cxusb_lgdt3303_frontend_attach,
-       .tuner_attach     = cxusb_lgh064f_tuner_attach,
+       .tuner_attach     = cxusb_lgdt3303_tuner_attach,
 
        .i2c_algo         = &cxusb_i2c_algo,
 
index 2d52b76671d35a729eea31b3bb16cf3f50b97953..abd75b4a350dab46c2d054d176edb991668f44bf 100644 (file)
@@ -173,11 +173,10 @@ int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
        struct dib3000_config demod_cfg;
        struct dibusb_state *st = d->priv;
 
-       demod_cfg.pll_set = dvb_usb_pll_set_i2c;
-       demod_cfg.pll_init = dvb_usb_pll_init_i2c;
-
        for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
                if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
+                       d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+                       d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
                        d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
                        return 0;
                }
@@ -190,6 +189,10 @@ int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
 {
        d->pll_addr = 0x60;
        d->pll_desc = &dvb_pll_env57h1xd5;
+
+       d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+       d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+
        return 0;
 }
 EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
index dd5a131958862a8bd7090dc2328c81fc499bfc1a..f4c45f386ebc693992cb7a165bb76896c1c60086 100644 (file)
@@ -20,11 +20,12 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
        struct dibusb_state *st = d->priv;
 
        demod_cfg.demod_address = 0x8;
-       demod_cfg.pll_set = dvb_usb_pll_set_i2c;
-       demod_cfg.pll_init = dvb_usb_pll_init_i2c;
 
-       if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
+       if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
+               d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+               d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
                return -ENODEV;
+       }
 
        d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
 
index 91136c00ce9ddf5bf3b5d1957601c05d0148decc..c14d9efb48fdb7162a809ba16b3cd5b207acebc0 100644 (file)
@@ -112,27 +112,30 @@ static int digitv_mt352_demod_init(struct dvb_frontend *fe)
 
 static struct mt352_config digitv_mt352_config = {
        .demod_init = digitv_mt352_demod_init,
-       .pll_set = dvb_usb_pll_set,
 };
 
-static int digitv_nxt6000_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
        struct dvb_usb_device *d = fe->dvb->priv;
        u8 b[5];
-       dvb_usb_pll_set(fe,fep,b);
+       dvb_usb_tuner_calc_regs(fe,fep,b, 5);
        return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0);
 }
 
 static struct nxt6000_config digitv_nxt6000_config = {
        .clock_inversion = 1,
-       .pll_set = digitv_nxt6000_pll_set,
 };
 
 static int digitv_frontend_attach(struct dvb_usb_device *d)
 {
-       if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL ||
-               (d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL)
+       if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL) {
+               d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
                return 0;
+       }
+       if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
+               d->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
+               return 0;
+       }
        return -EIO;
 }
 
index cd21ddbfd05479f9be098ba01e8fe8c1011f064c..17413adec7a1fbd92199c97d0a45f2dfa37e8875 100644 (file)
@@ -18,7 +18,6 @@ struct dtt200u_fe_state {
 
        struct dvb_frontend_parameters fep;
        struct dvb_frontend frontend;
-       struct dvb_frontend_ops ops;
 };
 
 static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
@@ -163,16 +162,13 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
        deb_info("attaching frontend dtt200u\n");
 
        state->d = d;
-       memcpy(&state->ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
 
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
 
-       goto success;
+       return &state->frontend;
 error:
        return NULL;
-success:
-       return &state->frontend;
 }
 
 static struct dvb_frontend_ops dtt200u_fe_ops = {
index 6fa92100248b8291b7353b070dc7347bfea67d38..ec631708c39480cf7d390267b452c109d2da2088 100644 (file)
@@ -82,7 +82,7 @@ int dvb_usb_dvb_init(struct dvb_usb_device *d)
        int ret;
 
        if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
-                       d->owner)) < 0) {
+                       d->owner, &d->udev->dev)) < 0) {
                deb_info("dvb_register_adapter failed: error %d", ret);
                goto err;
        }
@@ -121,16 +121,15 @@ int dvb_usb_dvb_init(struct dvb_usb_device *d)
 
        dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
 
-       goto success;
+       d->state |= DVB_USB_STATE_DVB;
+       return 0;
+
 err_dmx_dev:
        dvb_dmx_release(&d->demux);
 err_dmx:
        dvb_unregister_adapter(&d->dvb_adap);
 err:
        return ret;
-success:
-       d->state |= DVB_USB_STATE_DVB;
-       return 0;
 }
 
 int dvb_usb_dvb_exit(struct dvb_usb_device *d)
@@ -184,13 +183,13 @@ int dvb_usb_fe_init(struct dvb_usb_device* d)
 
        /* re-assign sleep and wakeup functions */
        if (d->fe != NULL) {
-               d->fe_init = d->fe->ops->init;   d->fe->ops->init  = dvb_usb_fe_wakeup;
-               d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep;
+               d->fe_init = d->fe->ops.init;   d->fe->ops.init  = dvb_usb_fe_wakeup;
+               d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep;
 
                if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
                        err("Frontend registration failed.");
-                       if (d->fe->ops->release)
-                               d->fe->ops->release(d->fe);
+                       if (d->fe->ops.release)
+                               d->fe->ops.release(d->fe);
                        d->fe = NULL;
                        return -ENODEV;
                }
index 9b254532af4dddd6e528c16c0a5770b3d8612173..6b611a72509309d4c4eefd84f513687df785ee5e 100644 (file)
@@ -46,7 +46,7 @@ int dvb_usb_i2c_exit(struct dvb_usb_device *d)
        return 0;
 }
 
-int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
+int dvb_usb_tuner_init_i2c(struct dvb_frontend *fe)
 {
        struct dvb_usb_device *d = fe->dvb->priv;
        struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
@@ -63,6 +63,8 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
        deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1],
                        d->pll_init[2],d->pll_init[3]);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
                err("tuner i2c write failed for pll_init.");
                ret = -EREMOTEIO;
@@ -73,38 +75,42 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
                d->tuner_pass_ctrl(fe,0,d->pll_addr);
        return ret;
 }
-EXPORT_SYMBOL(dvb_usb_pll_init_i2c);
+EXPORT_SYMBOL(dvb_usb_tuner_init_i2c);
 
-int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5])
+int dvb_usb_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 *b, int buf_len)
 {
        struct dvb_usb_device *d = fe->dvb->priv;
 
+       if (buf_len != 5)
+               return -EINVAL;
        if (d->pll_desc == NULL)
                return 0;
 
        deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
 
-       b[0] = d->pll_addr << 1;
+       b[0] = d->pll_addr;
        dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth);
 
        deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
 
-       return 0;
+       return 5;
 }
-EXPORT_SYMBOL(dvb_usb_pll_set);
+EXPORT_SYMBOL(dvb_usb_tuner_calc_regs);
 
-int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
        struct dvb_usb_device *d = fe->dvb->priv;
        int ret = 0;
        u8 b[5];
        struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
 
-       dvb_usb_pll_set(fe,fep,b);
+       dvb_usb_tuner_calc_regs(fe,fep,b,5);
 
        if (d->tuner_pass_ctrl)
                d->tuner_pass_ctrl(fe,1,d->pll_addr);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
                err("tuner i2c write failed for pll_set.");
                ret = -EREMOTEIO;
@@ -116,4 +122,4 @@ int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters
 
        return ret;
 }
-EXPORT_SYMBOL(dvb_usb_pll_set_i2c);
+EXPORT_SYMBOL(dvb_usb_tuner_set_params_i2c);
index cb239049b09836dc46b0f058d961c638aa1333aa..95698918bc116878da6ae4ac96f2b77661cf127d 100644 (file)
@@ -31,6 +31,7 @@
 #define USB_VID_VISIONPLUS                                     0x13d3
 #define USB_VID_TWINHAN                                                0x1822
 #define USB_VID_ULTIMA_ELECTRONIC                      0x05d8
+#define USB_VID_GENPIX                                 0x09c0
 
 /* Product IDs */
 #define USB_PID_ADSTECH_USB2_COLD                      0xa333
 #define USB_PID_KYE_DVB_T_WARM                         0x701f
 #define USB_PID_PCTV_200E                                      0x020e
 #define USB_PID_PCTV_400E                                      0x020f
-
+#define USB_PID_GENPIX_8PSK_COLD                               0x0200
+#define USB_PID_GENPIX_8PSK_WARM                               0x0201
 #endif
index fead958a57e3d0758461cec8317bef45bdb41e80..4cf9f89c51bf91c48f1faebee796d9a2839e0932 100644 (file)
@@ -330,9 +330,9 @@ extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
 extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
 
 /* commonly used pll init and set functions */
-extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
-extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
-extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
+extern int dvb_usb_tuner_init_i2c(struct dvb_frontend *);
+extern int dvb_usb_tuner_calc_regs(struct dvb_frontend *, struct dvb_frontend_parameters *, u8 *buf, int buf_len);
+extern int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
 
 /* commonly used firmware download types and function */
 struct hexline {
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
new file mode 100644 (file)
index 0000000..6ccbdc9
--- /dev/null
@@ -0,0 +1,272 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *     This program is free software; you can redistribute it and/or modify it
+ *     under the terms of the GNU General Public License as published by the Free
+ *     Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "gp8psk.h"
+
+struct gp8psk_fe_state {
+       struct dvb_frontend fe;
+
+       struct dvb_usb_device *d;
+
+       u16 snr;
+
+       unsigned long next_snr_check;
+};
+
+static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+{
+       struct gp8psk_fe_state *st = fe->demodulator_priv;
+       u8 lock;
+
+       if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1))
+               return -EINVAL;
+
+       if (lock)
+               *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
+       else
+               *status = 0;
+
+       return 0;
+}
+
+/* not supported by this Frontend */
+static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+       (void) fe;
+       *ber = 0;
+       return 0;
+}
+
+/* not supported by this Frontend */
+static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+       (void) fe;
+       *unc = 0;
+       return 0;
+}
+
+static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+       struct gp8psk_fe_state *st = fe->demodulator_priv;
+       u8 buf[2];
+
+       if (time_after(jiffies,st->next_snr_check)) {
+               gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2);
+               *snr = (int)(buf[1]) << 8 | buf[0];
+               /* snr is reported in dBu*256 */
+               /* snr / 38.4 ~= 100% strength */
+               /* snr * 17 returns 100% strength as 65535 */
+               if (*snr <= 3855)
+                       *snr = (*snr<<4) + *snr; // snr * 17
+               else
+                       *snr = 65535;
+               st->next_snr_check = jiffies + (10*HZ)/1000;
+       } else {
+               *snr = st->snr;
+       }
+       return 0;
+}
+
+static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+       return gp8psk_fe_read_snr(fe, strength);
+}
+
+static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+       tune->min_delay_ms = 800;
+       return 0;
+}
+
+static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
+                                 struct dvb_frontend_parameters *fep)
+{
+       struct gp8psk_fe_state *state = fe->demodulator_priv;
+       u8 cmd[10];
+       u32 freq = fep->frequency * 1000;
+
+       cmd[4] = freq         & 0xff;
+       cmd[5] = (freq >> 8)  & 0xff;
+       cmd[6] = (freq >> 16) & 0xff;
+       cmd[7] = (freq >> 24) & 0xff;
+
+       switch(fe->ops.info.type) {
+       case FE_QPSK:
+               cmd[0] =  fep->u.qpsk.symbol_rate        & 0xff;
+               cmd[1] = (fep->u.qpsk.symbol_rate >>  8) & 0xff;
+               cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff;
+               cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff;
+               cmd[8] = ADV_MOD_DVB_QPSK;
+               cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/
+               break;
+       default:
+               // other modes are unsuported right now
+               cmd[0] = 0;
+               cmd[1] = 0;
+               cmd[2] = 0;
+               cmd[3] = 0;
+               cmd[8] = 0;
+               cmd[9] = 0;
+               break;
+       }
+
+       gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
+
+       state->next_snr_check = jiffies;
+
+       return 0;
+}
+
+static int gp8psk_fe_get_frontend(struct dvb_frontend* fe,
+                                 struct dvb_frontend_parameters *fep)
+{
+       return 0;
+}
+
+
+static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
+                                   struct dvb_diseqc_master_cmd *m)
+{
+       struct gp8psk_fe_state *st = fe->demodulator_priv;
+
+       deb_fe("%s\n",__FUNCTION__);
+
+       if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
+                       m->msg, m->msg_len)) {
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
+                                   fe_sec_mini_cmd_t burst)
+{
+       struct gp8psk_fe_state *st = fe->demodulator_priv;
+       u8 cmd;
+
+       deb_fe("%s\n",__FUNCTION__);
+
+       /* These commands are certainly wrong */
+       cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
+
+       if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0,
+                       &cmd, 0)) {
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+       struct gp8psk_fe_state* state = fe->demodulator_priv;
+
+       if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE,
+                (tone == SEC_TONE_ON), 0, NULL, 0)) {
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+       struct gp8psk_fe_state* state = fe->demodulator_priv;
+
+       if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE,
+                        voltage == SEC_VOLTAGE_18, 0, NULL, 0)) {
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
+{
+       struct gp8psk_fe_state* state = fe->demodulator_priv;
+       u8 cmd = sw_cmd & 0x7f;
+
+       if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0,
+                       NULL, 0)) {
+               return -EINVAL;
+       }
+       if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
+                       0, NULL, 0)) {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void gp8psk_fe_release(struct dvb_frontend* fe)
+{
+       struct gp8psk_fe_state *state = fe->demodulator_priv;
+       kfree(state);
+}
+
+static struct dvb_frontend_ops gp8psk_fe_ops;
+
+struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d)
+{
+       struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
+       if (s == NULL)
+               goto error;
+
+       s->d = d;
+       memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
+       s->fe.demodulator_priv = s;
+
+       goto success;
+error:
+       return NULL;
+success:
+       return &s->fe;
+}
+
+
+static struct dvb_frontend_ops gp8psk_fe_ops = {
+       .info = {
+               .name                   = "Genpix 8psk-USB DVB-S",
+               .type                   = FE_QPSK,
+               .frequency_min          = 950000,
+               .frequency_max          = 2150000,
+               .frequency_stepsize     = 100,
+               .symbol_rate_min        = 1000000,
+               .symbol_rate_max        = 45000000,
+               .symbol_rate_tolerance  = 500,  /* ppm */
+               .caps = FE_CAN_INVERSION_AUTO |
+                               FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                               FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                               FE_CAN_QPSK
+       },
+
+       .release = gp8psk_fe_release,
+
+       .init = NULL,
+       .sleep = NULL,
+
+       .set_frontend = gp8psk_fe_set_frontend,
+       .get_frontend = gp8psk_fe_get_frontend,
+       .get_tune_settings = gp8psk_fe_get_tune_settings,
+
+       .read_status = gp8psk_fe_read_status,
+       .read_ber = gp8psk_fe_read_ber,
+       .read_signal_strength = gp8psk_fe_read_signal_strength,
+       .read_snr = gp8psk_fe_read_snr,
+       .read_ucblocks = gp8psk_fe_read_unc_blocks,
+
+       .diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg,
+       .diseqc_send_burst = gp8psk_fe_send_diseqc_burst,
+       .set_tone = gp8psk_fe_set_tone,
+       .set_voltage = gp8psk_fe_set_voltage,
+       .dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
+};
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
new file mode 100644 (file)
index 0000000..9a98f3f
--- /dev/null
@@ -0,0 +1,256 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *     This program is free software; you can redistribute it and/or modify it
+ *     under the terms of the GNU General Public License as published by the Free
+ *     Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "gp8psk.h"
+
+/* debug */
+static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
+int dvb_usb_gp8psk_debug;
+module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+       int ret = 0,try = 0;
+
+       if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+               return ret;
+
+       while (ret >= 0 && ret != blen && try < 3) {
+               ret = usb_control_msg(d->udev,
+                       usb_rcvctrlpipe(d->udev,0),
+                       req,
+                       USB_TYPE_VENDOR | USB_DIR_IN,
+                       value,index,b,blen,
+                       2000);
+               deb_info("reading number %d (ret: %d)\n",try,ret);
+               try++;
+       }
+
+       if (ret < 0 || ret != blen) {
+               warn("usb in operation failed.");
+               ret = -EIO;
+       } else
+               ret = 0;
+
+       deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+       debug_dump(b,blen,deb_xfer);
+
+       mutex_unlock(&d->usb_mutex);
+
+       return ret;
+}
+
+int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+                            u16 index, u8 *b, int blen)
+{
+       int ret;
+
+       deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+       debug_dump(b,blen,deb_xfer);
+
+       if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+               return ret;
+
+       if (usb_control_msg(d->udev,
+                       usb_sndctrlpipe(d->udev,0),
+                       req,
+                       USB_TYPE_VENDOR | USB_DIR_OUT,
+                       value,index,b,blen,
+                       2000) != blen) {
+               warn("usb out operation failed.");
+               ret = -EIO;
+       } else
+               ret = 0;
+       mutex_unlock(&d->usb_mutex);
+
+       return ret;
+}
+
+static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
+{
+       int ret;
+       const struct firmware *fw = NULL;
+       u8 *ptr, *buf;
+       if ((ret = request_firmware(&fw, bcm4500_firmware,
+                                       &d->udev->dev)) != 0) {
+               err("did not find the bcm4500 firmware file. (%s) "
+                       "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+                       bcm4500_firmware,ret);
+               return ret;
+       }
+
+       ret = -EINVAL;
+
+       if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
+               goto out_rel_fw;
+
+       info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware);
+
+       ptr = fw->data;
+       buf = kmalloc(512, GFP_KERNEL | GFP_DMA);
+
+       while (ptr[0] != 0xff) {
+               u16 buflen = ptr[0] + 4;
+               if (ptr + buflen >= fw->data + fw->size) {
+                       err("failed to load bcm4500 firmware.");
+                       goto out_free;
+               }
+               memcpy(buf, ptr, buflen);
+               if (dvb_usb_generic_write(d, buf, buflen)) {
+                       err("failed to load bcm4500 firmware.");
+                       goto out_free;
+               }
+               ptr += buflen;
+       }
+
+       ret = 0;
+
+out_free:
+       kfree(buf);
+out_rel_fw:
+       release_firmware(fw);
+
+       return ret;
+}
+
+static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       u8 status, buf;
+       if (onoff) {
+               gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+               if (! (status & 0x01))  /* started */
+                       if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
+                               return -EINVAL;
+
+               if (! (status & 0x02)) /* BCM4500 firmware loaded */
+                       if(gp8psk_load_bcm4500fw(d))
+                               return EINVAL;
+
+               if (! (status & 0x04)) /* LNB Power */
+                       if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
+                                       &buf, 1))
+                               return EINVAL;
+
+               /* Set DVB mode */
+               if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
+                       return -EINVAL;
+               gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+       } else {
+               /* Turn off LNB power */
+               if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
+                       return EINVAL;
+               /* Turn off 8psk power */
+               if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
+                       return -EINVAL;
+
+       }
+       return 0;
+}
+
+
+static int gp8psk_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       return gp8psk_usb_out_op(d, ARM_TRANSFER, onoff, 0 , NULL, 0);
+}
+
+static int gp8psk_frontend_attach(struct dvb_usb_device *d)
+{
+       d->fe = gp8psk_fe_attach(d);
+
+       return 0;
+}
+
+static struct dvb_usb_properties gp8psk_properties;
+
+static int gp8psk_usb_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
+}
+
+static struct usb_device_id gp8psk_usb_table [] = {
+           { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) },
+           { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) },
+           { 0 },
+};
+MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
+
+static struct dvb_usb_properties gp8psk_properties = {
+       .caps = 0,
+
+       .usb_ctrl = CYPRESS_FX2,
+       .firmware = "dvb-usb-gp8psk-01.fw",
+
+       .streaming_ctrl   = gp8psk_streaming_ctrl,
+       .power_ctrl       = gp8psk_power_ctrl,
+       .frontend_attach  = gp8psk_frontend_attach,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+       /* parameter for the MPEG2-data transfer */
+       .urb = {
+               .type = DVB_USB_BULK,
+               .count = 7,
+               .endpoint = 0x82,
+               .u = {
+                       .bulk = {
+                               .buffersize = 8192,
+                       }
+               }
+       },
+
+       .num_device_descs = 1,
+       .devices = {
+               { .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver",
+                 .cold_ids = { &gp8psk_usb_table[0], NULL },
+                 .warm_ids = { &gp8psk_usb_table[1], NULL },
+               },
+               { 0 },
+       }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver gp8psk_usb_driver = {
+       .name           = "dvb_usb_gp8psk",
+       .probe          = gp8psk_usb_probe,
+       .disconnect = dvb_usb_device_exit,
+       .id_table       = gp8psk_usb_table,
+};
+
+/* module stuff */
+static int __init gp8psk_usb_module_init(void)
+{
+       int result;
+       if ((result = usb_register(&gp8psk_usb_driver))) {
+               err("usb_register failed. (%d)",result);
+               return result;
+       }
+
+       return 0;
+}
+
+static void __exit gp8psk_usb_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&gp8psk_usb_driver);
+}
+
+module_init(gp8psk_usb_module_init);
+module_exit(gp8psk_usb_module_exit);
+
+MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
+MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h
new file mode 100644 (file)
index 0000000..3eba706
--- /dev/null
@@ -0,0 +1,79 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *     This program is free software; you can redistribute it and/or modify it
+ *     under the terms of the GNU General Public License as published by the Free
+ *     Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_GP8PSK_H_
+#define _DVB_USB_GP8PSK_H_
+
+#define DVB_USB_LOG_PREFIX "gp8psk"
+#include "dvb-usb.h"
+
+extern int dvb_usb_gp8psk_debug;
+#define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args)
+#define deb_rc(args...)   dprintk(dvb_usb_gp8psk_debug,0x04,args)
+#define deb_fe(args...)   dprintk(dvb_usb_gp8psk_debug,0x08,args)
+/* gp8psk commands */
+
+/* Twinhan Vendor requests */
+#define TH_COMMAND_IN                     0xC0
+#define TH_COMMAND_OUT                    0xC1
+
+/* command bytes */
+#define GET_8PSK_CONFIG                 0x80
+#define SET_8PSK_CONFIG                 0x81
+#define ARM_TRANSFER                    0x85
+#define TUNE_8PSK                       0x86
+#define GET_SIGNAL_STRENGTH             0x87
+#define LOAD_BCM4500                    0x88
+#define BOOT_8PSK                       0x89
+#define START_INTERSIL                  0x8A
+#define SET_LNB_VOLTAGE                 0x8B
+#define SET_22KHZ_TONE                  0x8C
+#define SEND_DISEQC_COMMAND             0x8D
+#define SET_DVB_MODE                    0x8E
+#define SET_DN_SWITCH                   0x8F
+#define GET_SIGNAL_LOCK                 0x90
+
+/* Satellite modulation modes */
+#define ADV_MOD_DVB_QPSK 0     /* DVB-S QPSK */
+#define ADV_MOD_TURBO_QPSK 1   /* Turbo QPSK */
+#define ADV_MOD_TURBO_8PSK 2   /* Turbo 8PSK (also used for Trellis 8PSK) */
+#define ADV_MOD_TURBO_16QAM 3  /* Turbo 16QAM (also used for Trellis 8PSK) */
+
+#define ADV_MOD_DCII_C_QPSK 4  /* Digicipher II Combo */
+#define ADV_MOD_DCII_I_QPSK 5  /* Digicipher II I-stream */
+#define ADV_MOD_DCII_Q_QPSK 6  /* Digicipher II Q-stream */
+#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */
+#define ADV_MOD_DSS_QPSK 8     /* DSS (DIRECTV) QPSK */
+#define ADV_MOD_DVB_BPSK 9     /* DVB-S BPSK */
+
+#define GET_USB_SPEED                     0x07
+ #define USB_SPEED_LOW                    0
+ #define USB_SPEED_FULL                   1
+ #define USB_SPEED_HIGH                   2
+
+#define RESET_FX2                         0x13
+
+#define FW_VERSION_READ                   0x0B
+#define VENDOR_STRING_READ                0x0C
+#define PRODUCT_STRING_READ               0x0D
+#define FW_BCD_VERSION_READ               0x14
+
+extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
+extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+                            u16 index, u8 *b, int blen);
+
+#endif
index 14f1911c79bb29061817eec9ffb209083677896c..97d74da0dad88676457b01081a6d8eaa406d0371 100644 (file)
@@ -57,7 +57,6 @@ static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
        memset(&umt_config,0,sizeof(struct mt352_config));
        umt_config.demod_init = umt_mt352_demod_init;
        umt_config.demod_address = 0xf;
-       umt_config.pll_set = dvb_usb_pll_set;
 
        d->fe = mt352_attach(&umt_config, &d->i2c_adap);
 
@@ -68,6 +67,7 @@ static int umt_tuner_attach (struct dvb_usb_device *d)
 {
        d->pll_addr = 0x61;
        d->pll_desc = &dvb_pll_tua6034;
+       d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
        return 0;
 }
 
index 2a89f8c5da99cf78c8af7fde74c67dd24282d0c1..d4da494132ec7814f0d818ce3fda6d21dcc9a201 100644 (file)
@@ -287,17 +287,16 @@ struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
                goto error;
 
        s->d = d;
-       s->fe.ops = &vp702x_fe_ops;
+
+       memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops));
        s->fe.demodulator_priv = s;
 
        s->lnb_buf[1] = SET_LNB_POWER;
        s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
 
-       goto success;
+       return &s->fe;
 error:
        return NULL;
-success:
-       return &s->fe;
 }
 
 
index 9999336aeeb6797aaa0a6c8be91d3fbde1aafe9d..8452eef90322be8d97e9a08c81881cc47f6cf311 100644 (file)
@@ -23,8 +23,6 @@
 
 struct vp7045_fe_state {
        struct dvb_frontend fe;
-       struct dvb_frontend_ops ops;
-
        struct dvb_usb_device *d;
 };
 
@@ -151,15 +149,12 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
                goto error;
 
        s->d = d;
-       memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
-       s->fe.ops = &s->ops;
+       memcpy(&s->fe.ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
        s->fe.demodulator_priv = s;
 
-       goto success;
+       return &s->fe;
 error:
        return NULL;
-success:
-       return &s->fe;
 }
 
 
index 37d5e0af1683a026722e0e47110c3e4f642bf164..0ef361f0309b59b72ebe10632bae24c4fa5ecbdf 100644 (file)
@@ -157,7 +157,7 @@ config DVB_STV0297
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
-comment "ATSC (North American/Korean Terresterial DTV) frontends"
+comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
        depends on DVB_CORE
 
 config DVB_NXT200X
@@ -216,4 +216,20 @@ config DVB_LGDT330X
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
 
+
+comment "Miscellaneous devices"
+       depends on DVB_CORE
+
+config DVB_LNBP21
+       tristate "LNBP21 SEC controller"
+       depends on DVB_CORE
+       help
+         An SEC control chip.
+
+config DVB_ISL6421
+       tristate "ISL6421 SEC controller"
+       depends on DVB_CORE
+       help
+         An SEC control chip.
+
 endmenu
index d09b6071fbaf23763400135137f3fcd87b64af2c..5222245c7f592573b1708102c8d56035a06950e7 100644 (file)
@@ -31,3 +31,5 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
 obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
 obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
+obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_ISL6421) += isl6421.o
index 1708a1d4893e4a7c9a9173d88555caef7016a171..baeb311de8931b82a12bfa00dbe3513051ec8a0b 100644 (file)
@@ -48,7 +48,6 @@
 struct bcm3510_state {
 
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        const struct bcm3510_config* config;
        struct dvb_frontend frontend;
 
@@ -791,10 +790,9 @@ struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
 
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
 
        mutex_init(&state->hab_mutex);
index 78573b22ada900c824d9482691a2b359eb5aa2a7..d8f65738e5d2520e05d2f6508c317fcaadfb4e1f 100644 (file)
@@ -89,12 +89,13 @@ static int alps_bsbe1_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
        return 0;
 }
 
-static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
+static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        int ret;
        u8 data[4];
        u32 div;
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+       struct i2c_adapter *i2c = fe->tuner_priv;
 
        if ((params->frequency < 950000) || (params->frequency > 2150000))
                return -EINVAL;
@@ -105,6 +106,8 @@ static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c,
        data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
        data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        ret = i2c_transfer(i2c, &msg, 1);
        return (ret != 1) ? -EIO : 0;
 }
@@ -117,7 +120,6 @@ static struct stv0299_config alps_bsbe1_config = {
        .skip_reinit = 0,
        .min_delay_ms = 100,
        .set_symbol_rate = alps_bsbe1_set_symbol_rate,
-       .pll_set = alps_bsbe1_pll_set,
 };
 
 #endif
index 2a5366ce79cc2f73797b66470365347795382507..e231cd84b3a16a49f4744b1c4b86e9962bcc11a5 100644 (file)
@@ -101,11 +101,12 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ra
        return 0;
 }
 
-static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
+static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        u8 buf[4];
        u32 div;
        struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+       struct i2c_adapter *i2c = fe->tuner_priv;
 
        if ((params->frequency < 950000) || (params->frequency > 2150000))
                return -EINVAL;
@@ -119,6 +120,8 @@ static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c,
        if (params->frequency > 1530000)
                buf[3] = 0xc0;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(i2c, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -134,7 +137,6 @@ static struct stv0299_config alps_bsru6_config = {
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 100,
        .set_symbol_rate = alps_bsru6_set_symbol_rate,
-       .pll_set = alps_bsru6_pll_set,
 };
 
 #endif
index 755f774f6b7d4262077def4b7a22b4f5b09efec1..3c7c09a362b2ac88bf517ae1e2499fa347f97f82 100644 (file)
@@ -34,8 +34,6 @@ struct cx22700_state {
 
        struct i2c_adapter* i2c;
 
-       struct dvb_frontend_ops ops;
-
        const struct cx22700_config* config;
 
        struct dvb_frontend frontend;
@@ -247,12 +245,6 @@ static int cx22700_init (struct dvb_frontend* fe)
 
        cx22700_writereg (state, 0x00, 0x01);
 
-       if (state->config->pll_init) {
-               cx22700_writereg (state, 0x0a, 0x00);  /* open i2c bus switch */
-               state->config->pll_init(fe);
-               cx22700_writereg (state, 0x0a, 0x01);  /* close i2c bus switch */
-       }
-
        return 0;
 }
 
@@ -333,9 +325,11 @@ static int cx22700_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
        cx22700_writereg (state, 0x00, 0x00);
 
-       cx22700_writereg (state, 0x0a, 0x00);  /* open i2c bus switch */
-       state->config->pll_set(fe, p);
-       cx22700_writereg (state, 0x0a, 0x01);  /* close i2c bus switch */
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
        cx22700_set_inversion (state, p->inversion);
        cx22700_set_tps (state, &p->u.ofdm);
        cx22700_writereg (state, 0x37, 0x01);  /* PAL loop filter off */
@@ -353,6 +347,17 @@ static int cx22700_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        return cx22700_get_tps (state, &p->u.ofdm);
 }
 
+static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct cx22700_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               return cx22700_writereg(state, 0x0a, 0x00);
+       } else {
+               return cx22700_writereg(state, 0x0a, 0x01);
+       }
+}
+
 static int cx22700_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
        fesettings->min_delay_ms = 150;
@@ -381,13 +386,12 @@ struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
 
        /* check if the demod is there */
        if (cx22700_readreg(state, 0x07) < 0) goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -413,6 +417,7 @@ static struct dvb_frontend_ops cx22700_ops = {
        .release = cx22700_release,
 
        .init = cx22700_init,
+       .i2c_gate_ctrl = cx22700_i2c_gate_ctrl,
 
        .set_frontend = cx22700_set_frontend,
        .get_frontend = cx22700_get_frontend,
index c9145b45874b3214f6424b9d0cfcc4292410876d..dcd8979c1a15e2668b5a5a8a8c276b59366edbb2 100644 (file)
@@ -29,10 +29,6 @@ struct cx22700_config
 {
        /* the demodulator's i2c address */
        u8 demod_address;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
index 0fc899f81c5e9be0a16b1f263a09465fc3adeb96..4106d46c957fa2e081c637790dace69827c791c1 100644 (file)
@@ -40,8 +40,6 @@ struct cx22702_state {
 
        struct i2c_adapter* i2c;
 
-       struct dvb_frontend_ops ops;
-
        /* configuration settings */
        const struct cx22702_config* config;
 
@@ -211,22 +209,10 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
        u8 val;
        struct cx22702_state* state = fe->demodulator_priv;
 
-       /* set PLL */
-       cx22702_i2c_gate_ctrl(fe, 1);
-       if (state->config->pll_set) {
-               state->config->pll_set(fe, p);
-       } else if (state->config->pll_desc) {
-               u8 pllbuf[4];
-               struct i2c_msg msg = { .addr = state->config->pll_address,
-                                      .buf = pllbuf, .len = 4 };
-               dvb_pll_configure(state->config->pll_desc, pllbuf,
-                                 p->frequency,
-                                 p->u.ofdm.bandwidth);
-               i2c_transfer(state->i2c, &msg, 1);
-       } else {
-               BUG();
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
-       cx22702_i2c_gate_ctrl(fe, 0);
 
        /* set inversion */
        cx22702_set_inversion (state, p->inversion);
@@ -358,10 +344,6 @@ static int cx22702_init (struct dvb_frontend* fe)
 
        cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
 
-       /* init PLL */
-       if (state->config->pll_init)
-               state->config->pll_init(fe);
-
        cx22702_i2c_gate_ctrl(fe, 0);
 
        return 0;
@@ -495,7 +477,6 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
        state->prevUCBlocks = 0;
 
        /* check if the demod is there */
@@ -503,7 +484,7 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
                goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -530,6 +511,7 @@ static struct dvb_frontend_ops cx22702_ops = {
        .release = cx22702_release,
 
        .init = cx22702_init,
+       .i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
 
        .set_frontend = cx22702_set_tps,
        .get_frontend = cx22702_get_frontend,
@@ -540,7 +522,6 @@ static struct dvb_frontend_ops cx22702_ops = {
        .read_signal_strength = cx22702_read_signal_strength,
        .read_snr = cx22702_read_snr,
        .read_ucblocks = cx22702_read_ucblocks,
-       .i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
 };
 
 module_param(debug, int, 0644);
index 5633976a58f19b9e90cf5b566510c4c481df6ead..7f2f241e5d4485985cfe0c0c23ddafd489e8add5 100644 (file)
@@ -39,13 +39,6 @@ struct cx22702_config
 #define CX22702_PARALLEL_OUTPUT 0
 #define CX22702_SERIAL_OUTPUT   1
        u8 output_mode;
-
-       /* PLL maintenance */
-       u8 pll_address;
-       struct dvb_pll_desc *pll_desc;
-
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
index f3edf8b517dd274c0e0bd9cfdc2405d175c72355..ce3c7398bac9ffa74168145b9b67d4eccf519c02 100644 (file)
@@ -36,8 +36,6 @@ struct cx24110_state {
 
        struct i2c_adapter* i2c;
 
-       struct dvb_frontend_ops ops;
-
        const struct cx24110_config* config;
 
        struct dvb_frontend frontend;
@@ -250,7 +248,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
        static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
        int i;
 
-dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
+       dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
        if (srate>90999000UL/2)
                srate=90999000UL/2;
        if (srate<500000)
@@ -366,17 +364,6 @@ static int cx24110_initfe(struct dvb_frontend* fe)
                cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
        };
 
-       if (state->config->pll_init) state->config->pll_init(fe);
-
-       return 0;
-}
-
-static int cx24110_sleep(struct dvb_frontend *fe)
-{
-       struct cx24110_state *state = fe->demodulator_priv;
-
-       if (state->config->pll_sleep)
-                 return state->config->pll_sleep(fe);
        return 0;
 }
 
@@ -548,7 +535,12 @@ static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
 {
        struct cx24110_state *state = fe->demodulator_priv;
 
-       state->config->pll_set(fe, p);
+
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
        cx24110_set_inversion (state, p->inversion);
        cx24110_set_fec (state, p->u.qpsk.fec_inner);
        cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate);
@@ -612,7 +604,6 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
        state->lastber = 0;
        state->lastbler = 0;
        state->lastesn0 = 0;
@@ -622,7 +613,7 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
        if ((ret != 0x5a) && (ret != 0x69)) goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -651,7 +642,6 @@ static struct dvb_frontend_ops cx24110_ops = {
        .release = cx24110_release,
 
        .init = cx24110_initfe,
-       .sleep = cx24110_sleep,
        .set_frontend = cx24110_set_frontend,
        .get_frontend = cx24110_get_frontend,
        .read_status = cx24110_read_status,
index 609ac642b406ad748c791cfd441b825460cb9080..b354a64e0e74970f728d4b5f905a24b5abb3ff75 100644 (file)
@@ -31,11 +31,6 @@ struct cx24110_config
 {
        /* the demodulator's i2c address */
        u8 demod_address;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-       int (*pll_sleep)(struct dvb_frontend* fe);
 };
 
 extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
index 691dc840dcc06ee15ad125aec428c6093413ad66..f2f795cba56aec2b18fc03b0c99f8bbe32820c5d 100644 (file)
@@ -41,14 +41,12 @@ static int debug;
 struct cx24123_state
 {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        const struct cx24123_config* config;
 
        struct dvb_frontend frontend;
 
        u32 lastber;
        u16 snr;
-       u8  lnbreg;
 
        /* Some PLL specifics for tuning */
        u32 VCAarg;
@@ -249,29 +247,6 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
        return 0;
 }
 
-static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
-{
-       u8 buf[] = { reg, data };
-       /* fixme: put the intersil addr int the config */
-       struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
-       int err;
-
-       if (debug>1)
-               printk("cx24123: %s:  writeln addr=0x08, reg 0x%02x, value 0x%02x\n",
-                                               __FUNCTION__,reg, data);
-
-       if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-               printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
-                        " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
-               return -EREMOTEIO;
-       }
-
-       /* cache the write, no way to read back */
-       state->lnbreg = data;
-
-       return 0;
-}
-
 static int cx24123_readreg(struct cx24123_state* state, u8 reg)
 {
        int ret;
@@ -295,11 +270,6 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg)
        return b1[0];
 }
 
-static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
-{
-       return state->lnbreg;
-}
-
 static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
 {
        u8 nom_reg = cx24123_readreg(state, 0x0e);
@@ -458,8 +428,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
        u8 pll_mult;
 
        /*  check if symbol rate is within limits */
-       if ((srate > state->ops.info.symbol_rate_max) ||
-           (srate < state->ops.info.symbol_rate_min))
+       if ((srate > state->frontend.ops.info.symbol_rate_max) ||
+           (srate < state->frontend.ops.info.symbol_rate_min))
                return -EOPNOTSUPP;;
 
        /* choose the sampling rate high enough for the required operation,
@@ -687,13 +657,6 @@ static int cx24123_initfe(struct dvb_frontend* fe)
        for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
                cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
 
-       if (state->config->pll_init)
-               state->config->pll_init(fe);
-
-       /* Configure the LNB for 14V */
-       if (state->config->use_isl6421)
-               cx24123_writelnbreg(state, 0x0, 0x2a);
-
        return 0;
 }
 
@@ -702,50 +665,18 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
        struct cx24123_state *state = fe->demodulator_priv;
        u8 val;
 
-       switch (state->config->use_isl6421) {
-
-       case 1:
+       val = cx24123_readreg(state, 0x29) & ~0x40;
 
-               val = cx24123_readlnbreg(state, 0x0);
-
-               switch (voltage) {
-               case SEC_VOLTAGE_13:
-                       dprintk("%s:  isl6421 voltage = 13V\n",__FUNCTION__);
-                       return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
-               case SEC_VOLTAGE_18:
-                       dprintk("%s:  isl6421 voltage = 18V\n",__FUNCTION__);
-                       return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
-               case SEC_VOLTAGE_OFF:
-                       dprintk("%s:  isl5421 voltage off\n",__FUNCTION__);
-                       return cx24123_writelnbreg(state, 0x0, val & 0x30);
-               default:
-                       return -EINVAL;
-               };
-
-       case 0:
-
-               val = cx24123_readreg(state, 0x29);
-
-               switch (voltage) {
-               case SEC_VOLTAGE_13:
-                       dprintk("%s: setting voltage 13V\n", __FUNCTION__);
-                       if (state->config->enable_lnb_voltage)
-                               state->config->enable_lnb_voltage(fe, 1);
-                       return cx24123_writereg(state, 0x29, val | 0x80);
-               case SEC_VOLTAGE_18:
-                       dprintk("%s: setting voltage 18V\n", __FUNCTION__);
-                       if (state->config->enable_lnb_voltage)
-                               state->config->enable_lnb_voltage(fe, 1);
-                       return cx24123_writereg(state, 0x29, val & 0x7f);
-               case SEC_VOLTAGE_OFF:
-                       dprintk("%s: setting voltage off\n", __FUNCTION__);
-                       if (state->config->enable_lnb_voltage)
-                               state->config->enable_lnb_voltage(fe, 0);
-                       return 0;
-               default:
-                       return -EINVAL;
-               };
-       }
+       switch (voltage) {
+       case SEC_VOLTAGE_13:
+               dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+               return cx24123_writereg(state, 0x29, val | 0x80);
+       case SEC_VOLTAGE_18:
+               dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+               return cx24123_writereg(state, 0x29, val & 0x7f);
+       default:
+               return -EINVAL;
+       };
 
        return 0;
 }
@@ -766,27 +697,20 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
 static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
 {
        struct cx24123_state *state = fe->demodulator_priv;
-       int i, val;
+       int i, val, tone;
 
        dprintk("%s:\n",__FUNCTION__);
 
-       /* check if continuous tone has been stopped */
-       if (state->config->use_isl6421)
-               val = cx24123_readlnbreg(state, 0x00) & 0x10;
-       else
-               val = cx24123_readreg(state, 0x29) & 0x10;
-
-
-       if (val) {
-               printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
-               return -ENOTSUPP;
-       }
+       /* stop continuous tone if enabled */
+       tone = cx24123_readreg(state, 0x29);
+       if (tone & 0x10)
+               cx24123_writereg(state, 0x29, tone & ~0x50);
 
        /* wait for diseqc queue ready */
        cx24123_wait_for_diseqc(state);
 
        /* select tone mode */
-       cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8);
+       cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
 
        for (i = 0; i < cmd->msg_len; i++)
                cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
@@ -797,36 +721,33 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
        /* wait for diseqc message to finish sending */
        cx24123_wait_for_diseqc(state);
 
+       /* restart continuous tone if enabled */
+       if (tone & 0x10) {
+               cx24123_writereg(state, 0x29, tone & ~0x40);
+       }
+
        return 0;
 }
 
 static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
 {
        struct cx24123_state *state = fe->demodulator_priv;
-       int val;
+       int val, tone;
 
        dprintk("%s:\n", __FUNCTION__);
 
-       /* check if continuous tone has been stoped */
-       if (state->config->use_isl6421)
-               val = cx24123_readlnbreg(state, 0x00) & 0x10;
-       else
-               val = cx24123_readreg(state, 0x29) & 0x10;
-
-
-       if (val) {
-               printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
-               return -ENOTSUPP;
-       }
+       /* stop continuous tone if enabled */
+       tone = cx24123_readreg(state, 0x29);
+       if (tone & 0x10)
+               cx24123_writereg(state, 0x29, tone & ~0x50);
 
+       /* wait for diseqc queue ready */
        cx24123_wait_for_diseqc(state);
 
        /* select tone mode */
-       val = cx24123_readreg(state, 0x2a) & 0xf8;
-       cx24123_writereg(state, 0x2a, val | 0x04);
-
+       cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4);
+       msleep(30);
        val = cx24123_readreg(state, 0x29);
-
        if (burst == SEC_MINI_A)
                cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
        else if (burst == SEC_MINI_B)
@@ -835,7 +756,12 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
                return -EINVAL;
 
        cx24123_wait_for_diseqc(state);
+       cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
 
+       /* restart continuous tone if enabled */
+       if (tone & 0x10) {
+               cx24123_writereg(state, 0x29, tone & ~0x40);
+       }
        return 0;
 }
 
@@ -976,38 +902,21 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
        struct cx24123_state *state = fe->demodulator_priv;
        u8 val;
 
-       switch (state->config->use_isl6421) {
-       case 1:
-
-               val = cx24123_readlnbreg(state, 0x0);
-
-               switch (tone) {
-               case SEC_TONE_ON:
-                       dprintk("%s:  isl6421 sec tone on\n",__FUNCTION__);
-                       return cx24123_writelnbreg(state, 0x0, val | 0x10);
-               case SEC_TONE_OFF:
-                       dprintk("%s:  isl6421 sec tone off\n",__FUNCTION__);
-                       return cx24123_writelnbreg(state, 0x0, val & 0x2f);
-               default:
-                       printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
-                       return -EINVAL;
-               }
-
-       case 0:
+       /* wait for diseqc queue ready */
+       cx24123_wait_for_diseqc(state);
 
-               val = cx24123_readreg(state, 0x29);
+       val = cx24123_readreg(state, 0x29) & ~0x40;
 
-               switch (tone) {
-               case SEC_TONE_ON:
-                       dprintk("%s: setting tone on\n", __FUNCTION__);
-                       return cx24123_writereg(state, 0x29, val | 0x10);
-               case SEC_TONE_OFF:
-                       dprintk("%s: setting tone off\n",__FUNCTION__);
-                       return cx24123_writereg(state, 0x29, val & 0xef);
-               default:
-                       printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
-                       return -EINVAL;
-               }
+       switch (tone) {
+       case SEC_TONE_ON:
+               dprintk("%s: setting tone on\n", __FUNCTION__);
+               return cx24123_writereg(state, 0x29, val | 0x10);
+       case SEC_TONE_OFF:
+               dprintk("%s: setting tone off\n",__FUNCTION__);
+               return cx24123_writereg(state, 0x29, val & 0xef);
+       default:
+               printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+               return -EINVAL;
        }
 
        return 0;
@@ -1040,10 +949,8 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
        state->lastber = 0;
        state->snr = 0;
-       state->lnbreg = 0;
        state->VCAarg = 0;
        state->VGAarg = 0;
        state->bandselectarg = 0;
@@ -1059,7 +966,7 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
        }
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
index 0c922b5e9263e3579bf0a1a0a38b53d87366a35c..9606f825935c8341f53b760e9c91f06e4146e9a8 100644 (file)
@@ -28,21 +28,8 @@ struct cx24123_config
        /* the demodulator's i2c address */
        u8 demod_address;
 
-       /*
-          cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
-          for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
-          from register 0x29 of the CX24123 demodulator
-       */
-       int use_isl6421;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
        /* Need to set device param for start_dma */
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
-
-       void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
 };
 
 extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
index c31d6df15472ed8e2164febad752bef13192797b..be1c0d3e1389e6ae4241a38fb13228330079c367 100644 (file)
@@ -38,8 +38,6 @@
 struct dib3000_state {
        struct i2c_adapter* i2c;
 
-       struct dvb_frontend_ops ops;
-
 /* configuration settings */
        struct dib3000_config config;
 
index 2d5475b5c0636d5c86df2baf16ac60723e10abd1..ec927628d2734cac2eee5ef633e5eb55de4d680e 100644 (file)
@@ -30,10 +30,6 @@ struct dib3000_config
 {
        /* the demodulator's i2c address */
        u8 demod_address;
-
-       /* PLL maintenance and the i2c address of the PLL */
-       int (*pll_init)(struct dvb_frontend *fe);
-       int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params);
 };
 
 struct dib_fe_xfer_ops
index ae589adb1c0a47b9960bb9e5a130f47dc1619fe7..7c6dc7e30900a428b5a037b0099d096dcc871156 100644 (file)
@@ -60,8 +60,9 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
        fe_code_rate_t fe_cr = FEC_NONE;
        int search_state, seq;
 
-       if (tuner && state->config.pll_set) {
-               state->config.pll_set(fe, fep);
+       if (tuner && fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, fep);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 
                deb_setf("bandwidth: ");
                switch (ofdm->bandwidth) {
@@ -386,9 +387,6 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
 
        wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
 
-       if (state->config.pll_init)
-               state->config.pll_init(fe);
-
        return 0;
 }
 
@@ -707,7 +705,6 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
        /* setup the state */
        state->i2c = i2c;
        memcpy(&state->config,config,sizeof(struct dib3000_config));
-       memcpy(&state->ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
 
        /* check for the correct demod */
        if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
@@ -717,7 +714,7 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
                goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
 
        /* set the xfer operations */
index 3b303dbb61565db54ed15b4bbab810be2c622860..6c3be2529980b2de1b12bf3c7ae680fbb247e000 100644 (file)
@@ -462,8 +462,9 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
        int search_state,auto_val;
        u16 val;
 
-       if (tuner && state->config.pll_set) { /* initial call from dvb */
-               state->config.pll_set(fe,fep);
+       if (tuner && fe->ops.tuner_ops.set_params) { /* initial call from dvb */
+               fe->ops.tuner_ops.set_params(fe, fep);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 
                state->last_tuned_freq = fep->frequency;
        //      if (!scanboost) {
@@ -642,9 +643,6 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
 
        set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
 
-       if (state->config.pll_init)
-               state->config.pll_init(fe);
-
        deb_info("init end\n");
        return 0;
 }
@@ -839,7 +837,6 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
        /* setup the state */
        state->i2c = i2c;
        memcpy(&state->config,config,sizeof(struct dib3000_config));
-       memcpy(&state->ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
 
        /* check for the correct demod */
        if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
@@ -859,7 +856,7 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
        }
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
 
        /* set the xfer operations */
@@ -876,6 +873,7 @@ error:
        kfree(state);
        return NULL;
 }
+EXPORT_SYMBOL(dib3000mc_attach);
 
 static struct dvb_frontend_ops dib3000mc_ops = {
 
@@ -914,5 +912,3 @@ static struct dvb_frontend_ops dib3000mc_ops = {
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dib3000mc_attach);
index 791706ec1da39a5b4ca528a08162ee19f9f70a00..a189683454b7da0ad84cb69cccaba873bf816da1 100644 (file)
@@ -227,10 +227,10 @@ struct dvb_pll_desc dvb_pll_tua6034 = {
 EXPORT_SYMBOL(dvb_pll_tua6034);
 
 /* Infineon TUA6034
- * used in LG TDVS H061F and LG TDVS H062F
+ * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F
  */
-struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
-       .name  = "LG/Infineon TUA6034",
+struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
+       .name  = "LG TDVS-H06xF",
        .min   =  54000000,
        .max   = 863000000,
        .count = 3,
@@ -240,7 +240,7 @@ struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
                {  999999999, 44000000, 62500, 0xce, 0x04 },
        },
 };
-EXPORT_SYMBOL(dvb_pll_tdvs_tua6034);
+EXPORT_SYMBOL(dvb_pll_lg_tdvs_h06xf);
 
 /* Philips FMD1216ME
  * used in Medion Hybrid PCMCIA card and USB Box
@@ -419,6 +419,19 @@ struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
 };
 EXPORT_SYMBOL(dvb_pll_thomson_fe6600);
 
+struct dvb_pll_priv {
+       /* i2c details */
+       int pll_i2c_address;
+       struct i2c_adapter *i2c;
+
+       /* the PLL descriptor */
+       struct dvb_pll_desc *pll_desc;
+
+       /* cached frequency/bandwidth */
+       u32 frequency;
+       u32 bandwidth;
+};
+
 /* ----------------------------------------------------------- */
 /* code                                                        */
 
@@ -443,7 +456,8 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
        if (debug)
                printk("pll: %s: freq=%d bw=%d | i=%d/%d\n",
                       desc->name, freq, bandwidth, i, desc->count);
-       BUG_ON(i == desc->count);
+       if (i == desc->count)
+               return -EINVAL;
 
        div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize;
        buf[0] = div >> 8;
@@ -462,6 +476,163 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
 }
 EXPORT_SYMBOL(dvb_pll_configure);
 
+static int dvb_pll_release(struct dvb_frontend *fe)
+{
+       if (fe->tuner_priv)
+               kfree(fe->tuner_priv);
+       fe->tuner_priv = NULL;
+       return 0;
+}
+
+static int dvb_pll_sleep(struct dvb_frontend *fe)
+{
+       struct dvb_pll_priv *priv = fe->tuner_priv;
+       u8 buf[4];
+       struct i2c_msg msg =
+               { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+       int i;
+       int result;
+
+       for (i = 0; i < priv->pll_desc->count; i++) {
+               if (priv->pll_desc->entries[i].limit == 0)
+                       break;
+       }
+       if (i == priv->pll_desc->count)
+               return 0;
+
+       buf[0] = 0;
+       buf[1] = 0;
+       buf[2] = priv->pll_desc->entries[i].config;
+       buf[3] = priv->pll_desc->entries[i].cb;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+               return result;
+       }
+
+       return 0;
+}
+
+static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+       struct dvb_pll_priv *priv = fe->tuner_priv;
+       u8 buf[4];
+       struct i2c_msg msg =
+               { .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+       int result;
+       u32 div;
+       int i;
+       u32 bandwidth = 0;
+
+       if (priv->i2c == NULL)
+               return -EINVAL;
+
+       // DVBT bandwidth only just now
+       if (fe->ops.info.type == FE_OFDM) {
+               bandwidth = params->u.ofdm.bandwidth;
+       }
+
+       if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0)
+               return result;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+               return result;
+       }
+
+       // calculate the frequency we set it to
+       for (i = 0; i < priv->pll_desc->count; i++) {
+               if (params->frequency > priv->pll_desc->entries[i].limit)
+                       continue;
+               break;
+       }
+       div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
+       priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+       priv->bandwidth = bandwidth;
+
+       return 0;
+}
+
+static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len)
+{
+       struct dvb_pll_priv *priv = fe->tuner_priv;
+       int result;
+       u32 div;
+       int i;
+       u32 bandwidth = 0;
+
+       if (buf_len < 5)
+               return -EINVAL;
+
+       // DVBT bandwidth only just now
+       if (fe->ops.info.type == FE_OFDM) {
+               bandwidth = params->u.ofdm.bandwidth;
+       }
+
+       if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0)
+               return result;
+       buf[0] = priv->pll_i2c_address;
+
+       // calculate the frequency we set it to
+       for (i = 0; i < priv->pll_desc->count; i++) {
+               if (params->frequency > priv->pll_desc->entries[i].limit)
+                       continue;
+               break;
+       }
+       div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
+       priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+       priv->bandwidth = bandwidth;
+
+       return 5;
+}
+
+static int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct dvb_pll_priv *priv = fe->tuner_priv;
+       *frequency = priv->frequency;
+       return 0;
+}
+
+static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+       struct dvb_pll_priv *priv = fe->tuner_priv;
+       *bandwidth = priv->bandwidth;
+       return 0;
+}
+
+static struct dvb_tuner_ops dvb_pll_tuner_ops = {
+       .release = dvb_pll_release,
+       .sleep = dvb_pll_sleep,
+       .set_params = dvb_pll_set_params,
+       .calc_regs = dvb_pll_calc_regs,
+       .get_frequency = dvb_pll_get_frequency,
+       .get_bandwidth = dvb_pll_get_bandwidth,
+};
+
+int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
+{
+       struct dvb_pll_priv *priv = NULL;
+
+       priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
+       if (priv == NULL)
+               return -ENOMEM;
+
+       priv->pll_i2c_address = pll_addr;
+       priv->i2c = i2c;
+       priv->pll_desc = desc;
+
+       memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops));
+       strncpy(fe->ops.tuner_ops.info.name, desc->name, 128);
+       fe->ops.tuner_ops.info.frequency_min = desc->min;
+       fe->ops.tuner_ops.info.frequency_min = desc->max;
+
+       fe->tuner_priv = priv;
+       return 0;
+}
+EXPORT_SYMBOL(dvb_pll_attach);
+
 MODULE_DESCRIPTION("dvb pll library");
 MODULE_AUTHOR("Gerd Knorr");
 MODULE_LICENSE("GPL");
index 2b84617849899cb5cc96d91017638ad5670f7989..66361cd188078c6361d84d255febce35d0685aa2 100644 (file)
@@ -5,6 +5,9 @@
 #ifndef __DVB_PLL_H__
 #define __DVB_PLL_H__
 
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
 struct dvb_pll_desc {
        char *name;
        u32  min;
@@ -31,7 +34,7 @@ extern struct dvb_pll_desc dvb_pll_unknown_1;
 extern struct dvb_pll_desc dvb_pll_tua6010xs;
 extern struct dvb_pll_desc dvb_pll_env57h1xd5;
 extern struct dvb_pll_desc dvb_pll_tua6034;
-extern struct dvb_pll_desc dvb_pll_tdvs_tua6034;
+extern struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf;
 extern struct dvb_pll_desc dvb_pll_tda665x;
 extern struct dvb_pll_desc dvb_pll_fmd1216me;
 extern struct dvb_pll_desc dvb_pll_tded4;
@@ -44,7 +47,18 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316;
 
 extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
 
-int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
+extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
                      u32 freq, int bandwidth);
 
+/**
+ * Attach a dvb-pll to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param pll_addr i2c address of the PLL (if used).
+ * @param i2c i2c adapter to use (set to NULL if not used).
+ * @param desc dvb_pll_desc to use.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
+
 #endif
index 645946a992d94b1dda65bf33e14561238ee6329f..6271b1e7f6ab94c8abdc55a35f64d9ee692223ab 100644 (file)
@@ -30,7 +30,6 @@
 
 
 struct dvb_dummy_fe_state {
-       struct dvb_frontend_ops ops;
        struct dvb_frontend frontend;
 };
 
@@ -77,6 +76,11 @@ static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_fronten
 
 static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
 {
+       if (fe->ops->tuner_ops->set_params) {
+               fe->ops->tuner_ops->set_params(fe, p);
+               if (fe->ops->i2c_gate_ctrl) fe->ops->i2c_gate_ctrl(fe, 0);
+       }
+
        return 0;
 }
 
@@ -116,11 +120,8 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
        state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
-       /* setup the state */
-       memcpy(&state->ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
-
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -139,11 +140,8 @@ struct dvb_frontend* dvb_dummy_fe_qpsk_attach()
        state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
-       /* setup the state */
-       memcpy(&state->ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
-
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -162,11 +160,8 @@ struct dvb_frontend* dvb_dummy_fe_qam_attach()
        state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
-       /* setup the state */
-       memcpy(&state->ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
-
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c
new file mode 100644 (file)
index 0000000..58c34db
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6421.h"
+
+struct isl6421 {
+       u8                      config;
+       u8                      override_or;
+       u8                      override_and;
+       struct i2c_adapter      *i2c;
+       u8                      i2c_addr;
+       void                    (*release_chain)(struct dvb_frontend* fe);
+};
+
+static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+       struct i2c_msg msg = {  .addr = isl6421->i2c_addr, .flags = 0,
+                               .buf = &isl6421->config,
+                               .len = sizeof(isl6421->config) };
+
+       isl6421->config &= ~(ISL6421_VSEL1 | ISL6421_EN1);
+
+       switch(voltage) {
+       case SEC_VOLTAGE_OFF:
+               break;
+       case SEC_VOLTAGE_13:
+               isl6421->config |= ISL6421_EN1;
+               break;
+       case SEC_VOLTAGE_18:
+               isl6421->config |= (ISL6421_EN1 | ISL6421_VSEL1);
+               break;
+       default:
+               return -EINVAL;
+       };
+
+       isl6421->config |= isl6421->override_or;
+       isl6421->config &= isl6421->override_and;
+
+       return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+       struct i2c_msg msg = {  .addr = isl6421->i2c_addr, .flags = 0,
+                               .buf = &isl6421->config,
+                               .len = sizeof(isl6421->config) };
+
+       if (arg)
+               isl6421->config |= ISL6421_LLC1;
+       else
+               isl6421->config &= ~ISL6421_LLC1;
+
+       isl6421->config |= isl6421->override_or;
+       isl6421->config &= isl6421->override_and;
+
+       return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void isl6421_release(struct dvb_frontend *fe)
+{
+       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+
+       /* power off */
+       isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+       /* free data & call next release routine */
+       fe->ops.release = isl6421->release_chain;
+       kfree(fe->misc_priv);
+       fe->misc_priv = NULL;
+       if (fe->ops.release)
+               fe->ops.release(fe);
+}
+
+int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+                  u8 override_set, u8 override_clear)
+{
+       struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
+       if (!isl6421)
+               return -ENOMEM;
+
+       /* default configuration */
+       isl6421->config = ISL6421_ISEL1;
+       isl6421->i2c = i2c;
+       isl6421->i2c_addr = i2c_addr;
+       fe->misc_priv = isl6421;
+
+       /* bits which should be forced to '1' */
+       isl6421->override_or = override_set;
+
+       /* bits which should be forced to '0' */
+       isl6421->override_and = ~override_clear;
+
+       /* detect if it is present or not */
+       if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+               kfree(isl6421);
+               fe->misc_priv = NULL;
+               return -EIO;
+       }
+
+       /* install release callback */
+       isl6421->release_chain = fe->ops.release;
+       fe->ops.release = isl6421_release;
+
+       /* override frontend ops */
+       fe->ops.set_voltage = isl6421_set_voltage;
+       fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
+
+       return 0;
+}
+EXPORT_SYMBOL(isl6421_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421");
+MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h
new file mode 100644 (file)
index 0000000..675f80a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _ISL6421_H
+#define _ISL6421_H
+
+#include <linux/dvb/frontend.h>
+
+/* system register bits */
+#define ISL6421_OLF1   0x01
+#define ISL6421_EN1    0x02
+#define ISL6421_VSEL1  0x04
+#define ISL6421_LLC1   0x08
+#define ISL6421_ENT1   0x10
+#define ISL6421_ISEL1  0x20
+#define ISL6421_DCL    0x40
+
+/* override_set and override_clear control which system register bits (above) to always set & clear */
+extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+                         u8 override_set, u8 override_clear);
+
+#endif
index 1c7c91224472ce6f2078aadec88222eacf46dbd2..f3bc82e44a288b2381066c61683d2be93e55039d 100644 (file)
@@ -32,7 +32,6 @@
 
 struct l64781_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        const struct l64781_config* config;
        struct dvb_frontend frontend;
 
@@ -141,7 +140,10 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
        u8 val0x06;
        int bw = p->bandwidth - BANDWIDTH_8_MHZ;
 
-       state->config->pll_set(fe, param);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, param);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
        if (param->inversion != INVERSION_ON &&
            param->inversion != INVERSION_OFF)
@@ -463,8 +465,6 @@ static int l64781_init(struct dvb_frontend* fe)
        /* Everything is two's complement, soft bit and CSI_OUT too */
        l64781_writereg (state, 0x1e, 0x09);
 
-       if (state->config->pll_init) state->config->pll_init(fe);
-
        /* delay a bit after first init attempt */
        if (state->first) {
                state->first = 0;
@@ -508,7 +508,6 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
        state->first = 1;
 
        /**
@@ -554,7 +553,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
        }
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
index 947f65f87465441f366a21312631b243bbbe50f4..83b8bc21027404563875208b3e559d2037ef287a 100644 (file)
@@ -29,10 +29,6 @@ struct l64781_config
 {
        /* the demodulator's i2c address */
        u8 demod_address;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 
diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h
new file mode 100644 (file)
index 0000000..754d51d
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LG_H06XF_H_
+#define _LG_H06XF_H_
+#include "dvb-pll.h"
+
+static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap,
+                    struct dvb_frontend_parameters* params)
+{
+       u8 buf[4];
+       struct i2c_msg msg = { .addr = 0x61, .flags = 0,
+                              .buf = buf, .len = sizeof(buf) };
+       int err;
+
+       dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
+               printk(KERN_WARNING "lg_h06xf: %s error "
+                       "(addr %02x <- %02x, err = %i)\n",
+                       __FUNCTION__, buf[0], buf[1], err);
+               if (err < 0)
+                       return err;
+               else
+                       return -EREMOTEIO;
+       }
+
+       /* Set the Auxiliary Byte. */
+       buf[0] = buf[2];
+       buf[0] &= ~0x20;
+       buf[0] |= 0x18;
+       buf[1] = 0x50;
+       msg.len = 2;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
+               printk(KERN_WARNING "lg_h06xf: %s error "
+                       "(addr %02x <- %02x, err = %i)\n",
+                       __FUNCTION__, buf[0], buf[1], err);
+               if (err < 0)
+                       return err;
+               else
+                       return -EREMOTEIO;
+       }
+
+       return 0;
+}
+#endif
index 4691ac54bc1d2a8f3202fb43cae0f504d9a8ce7e..6e8ad176e1a1468f0bbb3bf197232e850361f0d6 100644 (file)
@@ -29,6 +29,7 @@
  *   DViCO FusionHDTV 5 Lite
  *   DViCO FusionHDTV 5 USB Gold
  *   Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
+ *   pcHDTV HD5500
  *
  * TODO:
  * signal strength always returns 0.
@@ -59,7 +60,6 @@ if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
 struct lgdt330x_state
 {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
 
        /* Configuration settings */
        const struct lgdt330x_config* config;
@@ -399,8 +399,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
        }
 
        /* Tune to the specified frequency */
-       if (state->config->pll_set)
-               state->config->pll_set(fe, param);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, param);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
        /* Keep track of the new frequency */
        /* FIXME this is the wrong way to do this...           */
@@ -672,6 +674,7 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
 
        if (state->current_modulation == VSB_8) {
 
+               i2c_read_demod_bytes(state, 0x6e, buf, 5);
                /* Phase Tracker Mean-Square Error Register for VSB */
                noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
        } else {
@@ -721,16 +724,19 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
        /* Setup the state */
        state->config = config;
        state->i2c = i2c;
+
+       /* Create dvb_frontend */
        switch (config->demod_chip) {
        case LGDT3302:
-               memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
+               memcpy(&state->frontend.ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
                break;
        case LGDT3303:
-               memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
+               memcpy(&state->frontend.ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
                break;
        default:
                goto error;
        }
+       state->frontend.demodulator_priv = state;
 
        /* Verify communication with demod chip */
        if (i2c_read_demod_bytes(state, 2, buf, 1))
@@ -739,9 +745,6 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
        state->current_frequency = -1;
        state->current_modulation = -1;
 
-       /* Create dvb_frontend */
-       state->frontend.ops = &state->ops;
-       state->frontend.demodulator_priv = state;
        return &state->frontend;
 
 error:
index 2a6529cccf1afe59a1c5204b76c30dab1dc676e3..bad903c6f0f8261111a6b1d2b7dfe3bdbabb9325 100644 (file)
@@ -43,7 +43,6 @@ struct lgdt330x_config
 
        /* PLL interface */
        int (*pll_rf_set) (struct dvb_frontend* fe, int index);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 
        /* Need to set device param for start_dma */
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c
new file mode 100644 (file)
index 0000000..e933edc
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * lnbp21.h - driver for lnb supply and control ic lnbp21
+ *
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "lnbp21.h"
+
+struct lnbp21 {
+       u8                      config;
+       u8                      override_or;
+       u8                      override_and;
+       struct i2c_adapter      *i2c;
+       void                    (*release_chain)(struct dvb_frontend* fe);
+};
+
+static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+       struct i2c_msg msg = {  .addr = 0x08, .flags = 0,
+                               .buf = &lnbp21->config,
+                               .len = sizeof(lnbp21->config) };
+
+       lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
+
+       switch(voltage) {
+       case SEC_VOLTAGE_OFF:
+               break;
+       case SEC_VOLTAGE_13:
+               lnbp21->config |= LNBP21_EN;
+               break;
+       case SEC_VOLTAGE_18:
+               lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
+               break;
+       default:
+               return -EINVAL;
+       };
+
+       lnbp21->config |= lnbp21->override_or;
+       lnbp21->config &= lnbp21->override_and;
+
+       return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+       struct i2c_msg msg = {  .addr = 0x08, .flags = 0,
+                               .buf = &lnbp21->config,
+                               .len = sizeof(lnbp21->config) };
+
+       if (arg)
+               lnbp21->config |= LNBP21_LLC;
+       else
+               lnbp21->config &= ~LNBP21_LLC;
+
+       lnbp21->config |= lnbp21->override_or;
+       lnbp21->config &= lnbp21->override_and;
+
+       return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void lnbp21_release(struct dvb_frontend *fe)
+{
+       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+
+       /* LNBP power off */
+       lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+       /* free data & call next release routine */
+       fe->ops.release = lnbp21->release_chain;
+       kfree(fe->misc_priv);
+       fe->misc_priv = NULL;
+       if (fe->ops.release)
+               fe->ops.release(fe);
+}
+
+int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+{
+       struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
+       if (!lnbp21)
+               return -ENOMEM;
+
+       /* default configuration */
+       lnbp21->config = LNBP21_ISEL;
+       lnbp21->i2c = i2c;
+       fe->misc_priv = lnbp21;
+
+       /* bits which should be forced to '1' */
+       lnbp21->override_or = override_set;
+
+       /* bits which should be forced to '0' */
+       lnbp21->override_and = ~override_clear;
+
+       /* detect if it is present or not */
+       if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+               kfree(lnbp21);
+               fe->misc_priv = NULL;
+               return -EIO;
+       }
+
+       /* install release callback */
+       lnbp21->release_chain = fe->ops.release;
+       fe->ops.release = lnbp21_release;
+
+       /* override frontend ops */
+       fe->ops.set_voltage = lnbp21_set_voltage;
+       fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+
+       return 0;
+}
+EXPORT_SYMBOL(lnbp21_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21");
+MODULE_AUTHOR("Oliver Endriss");
+MODULE_LICENSE("GPL");
index 0dcbe61b61b1c000f1613cabc7e97d62aadaf4b4..047a4ab68c01be0a0cc0c6579eff5f0c3ec149ad 100644 (file)
@@ -27,7 +27,7 @@
 #ifndef _LNBP21_H
 #define _LNBP21_H
 
-/* system register */
+/* system register bits */
 #define LNBP21_OLF     0x01
 #define LNBP21_OTF     0x02
 #define LNBP21_EN      0x04
 #define LNBP21_ISEL    0x40
 #define LNBP21_PCL     0x80
 
-struct lnbp21 {
-       u8                      config;
-       u8                      override_or;
-       u8                      override_and;
-       struct i2c_adapter      *i2c;
-       void                    (*release_chain)(struct dvb_frontend* fe);
-};
+#include <linux/dvb/frontend.h>
 
-static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-       struct i2c_msg msg = {  .addr = 0x08, .flags = 0,
-                               .buf = &lnbp21->config,
-                               .len = sizeof(lnbp21->config) };
-
-       lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
-
-       switch(voltage) {
-       case SEC_VOLTAGE_OFF:
-               break;
-       case SEC_VOLTAGE_13:
-               lnbp21->config |= LNBP21_EN;
-               break;
-       case SEC_VOLTAGE_18:
-               lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
-               break;
-       default:
-               return -EINVAL;
-       };
-
-       lnbp21->config |= lnbp21->override_or;
-       lnbp21->config &= lnbp21->override_and;
-
-       return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
-{
-       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-       struct i2c_msg msg = {  .addr = 0x08, .flags = 0,
-                               .buf = &lnbp21->config,
-                               .len = sizeof(lnbp21->config) };
-
-       if (arg)
-               lnbp21->config |= LNBP21_LLC;
-       else
-               lnbp21->config &= ~LNBP21_LLC;
-
-       lnbp21->config |= lnbp21->override_or;
-       lnbp21->config &= lnbp21->override_and;
-
-       return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static void lnbp21_exit(struct dvb_frontend *fe)
-{
-       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-
-       /* LNBP power off */
-       lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
-
-       /* free data & call next release routine */
-       fe->ops->release = lnbp21->release_chain;
-       kfree(fe->misc_priv);
-       fe->misc_priv = NULL;
-       if (fe->ops->release)
-               fe->ops->release(fe);
-}
-
-static int lnbp21_init(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
-{
-       struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
-
-       if (!lnbp21)
-               return -ENOMEM;
-
-       /* default configuration */
-       lnbp21->config = LNBP21_ISEL;
-
-       /* bits which should be forced to '1' */
-       lnbp21->override_or = override_set;
-
-       /* bits which should be forced to '0' */
-       lnbp21->override_and = ~override_clear;
-
-       /* install release callback */
-       lnbp21->release_chain = fe->ops->release;
-       fe->ops->release = lnbp21_exit;
-
-       /* override frontend ops */
-       fe->ops->set_voltage = lnbp21_set_voltage;
-       fe->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
-
-       lnbp21->i2c = i2c;
-       fe->misc_priv = lnbp21;
-
-       return lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
-}
+/* override_set and override_clear control which system register bits (above) to always set & clear */
+extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
 
 #endif
index d3aea83cf218e23fff5cc841cb1178152af885c7..1ef821825641c1f725a17807f594d404f96e49b7 100644 (file)
@@ -39,7 +39,6 @@
 
 struct mt312_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        /* configuration settings */
        const struct mt312_config* config;
        struct dvb_frontend frontend;
@@ -277,12 +276,6 @@ static int mt312_initfe(struct dvb_frontend* fe)
        if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0)
                return ret;
 
-       if (state->config->pll_init) {
-               mt312_writereg(state, GPP_CTRL, 0x40);
-               state->config->pll_init(fe);
-               mt312_writereg(state, GPP_CTRL, 0x00);
-       }
-
        return 0;
 }
 
@@ -477,16 +470,16 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
 
        dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
 
-       if ((p->frequency < fe->ops->info.frequency_min)
-           || (p->frequency > fe->ops->info.frequency_max))
+       if ((p->frequency < fe->ops.info.frequency_min)
+           || (p->frequency > fe->ops.info.frequency_max))
                return -EINVAL;
 
        if ((p->inversion < INVERSION_OFF)
            || (p->inversion > INVERSION_ON))
                return -EINVAL;
 
-       if ((p->u.qpsk.symbol_rate < fe->ops->info.symbol_rate_min)
-           || (p->u.qpsk.symbol_rate > fe->ops->info.symbol_rate_max))
+       if ((p->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min)
+           || (p->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max))
                return -EINVAL;
 
        if ((p->u.qpsk.fec_inner < FEC_NONE)
@@ -529,9 +522,10 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
                return -EINVAL;
        }
 
-       mt312_writereg(state, GPP_CTRL, 0x40);
-       state->config->pll_set(fe, p);
-       mt312_writereg(state, GPP_CTRL, 0x00);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
        /* sr = (u16)(sr * 256.0 / 1000000.0) */
        sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625);
@@ -578,6 +572,17 @@ static int mt312_get_frontend(struct dvb_frontend* fe,
        return 0;
 }
 
+static int mt312_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct mt312_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               return mt312_writereg(state, GPP_CTRL, 0x40);
+       } else {
+               return mt312_writereg(state, GPP_CTRL, 0x00);
+       }
+}
+
 static int mt312_sleep(struct dvb_frontend* fe)
 {
        struct mt312_state *state = fe->demodulator_priv;
@@ -633,6 +638,7 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
 
        .init = mt312_initfe,
        .sleep = mt312_sleep,
+       .i2c_gate_ctrl = mt312_i2c_gate_ctrl,
 
        .set_frontend = mt312_set_frontend,
        .get_frontend = mt312_get_frontend,
@@ -663,19 +669,22 @@ struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
 
        /* check if the demod is there */
        if (mt312_readreg(state, ID, &state->id) < 0)
                goto error;
 
+       /* create dvb_frontend */
+       memcpy(&state->frontend.ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
+       state->frontend.demodulator_priv = state;
+
        switch (state->id) {
        case ID_VP310:
-               strcpy(state->ops.info.name, "Zarlink VP310 DVB-S");
+               strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
                state->frequency = 90;
                break;
        case ID_MT312:
-               strcpy(state->ops.info.name, "Zarlink MT312 DVB-S");
+               strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
                state->frequency = 60;
                break;
        default:
@@ -683,9 +692,6 @@ struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
                goto error;
        }
 
-       /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
-       state->frontend.demodulator_priv = state;
        return &state->frontend;
 
 error:
index 074d844f01393678e2e271273f8ba54bdcd6641f..666a1bd1c244ff0752c9b79a64d5abb08c5f7d07 100644 (file)
@@ -32,10 +32,6 @@ struct mt312_config
 {
        /* the demodulator's i2c address */
        u8 demod_address;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
index aaaec909ddf830f0372bdf11d19aff43a164852c..5de7376c94ce13e9501b1cda912c17a09be738e6 100644 (file)
@@ -45,7 +45,6 @@
 struct mt352_state {
        struct i2c_adapter* i2c;
        struct dvb_frontend frontend;
-       struct dvb_frontend_ops ops;
 
        /* configuration settings */
        struct mt352_config config;
@@ -286,16 +285,25 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
 
        mt352_calc_nominal_rate(state, op->bandwidth, buf+4);
        mt352_calc_input_freq(state, buf+6);
-       state->config.pll_set(fe, param, buf+8);
 
-       mt352_write(fe, buf, sizeof(buf));
        if (state->config.no_tuner) {
-               /* start decoding */
+               if (fe->ops.tuner_ops.set_params) {
+                       fe->ops.tuner_ops.set_params(fe, param);
+                       if (fe->ops.i2c_gate_ctrl)
+                               fe->ops.i2c_gate_ctrl(fe, 0);
+               }
+
+               mt352_write(fe, buf, 8);
                mt352_write(fe, fsm_go, 2);
        } else {
-               /* start tuning */
-               mt352_write(fe, tuner_go, 2);
+               if (fe->ops.tuner_ops.calc_regs) {
+                       fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5);
+                       buf[8] <<= 1;
+                       mt352_write(fe, buf, sizeof(buf));
+                       mt352_write(fe, tuner_go, 2);
+               }
        }
+
        return 0;
 }
 
@@ -541,13 +549,12 @@ struct dvb_frontend* mt352_attach(const struct mt352_config* config,
        /* setup the state */
        state->i2c = i2c;
        memcpy(&state->config,config,sizeof(struct mt352_config));
-       memcpy(&state->ops, &mt352_ops, sizeof(struct dvb_frontend_ops));
 
        /* check if the demod is there */
        if (mt352_read_register(state, CHIP_ID) != ID_MT352) goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &mt352_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
index 03040cd595bb4b50a0a9cb4d1f4835d663705b02..9e7ff4b8fe5f30156dabb28c4f46408328fe1169 100644 (file)
@@ -49,12 +49,6 @@ struct mt352_config
 
        /* Initialise the demodulator and PLL. Cannot be NULL */
        int (*demod_init)(struct dvb_frontend* fe);
-
-       /* PLL setup - fill out the supplied 5 byte buffer with your PLL settings.
-        * byte0: Set to pll i2c address (nonlinux; left shifted by 1)
-        * byte1-4: PLL configuration.
-        */
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf);
 };
 
 extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
index 9e35353945099f69d073c24996802fa57ab53701..55671cb5255e0aa6972560638cfff7e55552334d 100644 (file)
@@ -55,7 +55,6 @@
 struct nxt200x_state {
 
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        const struct nxt200x_config* config;
        struct dvb_frontend frontend;
 
@@ -333,17 +332,17 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
 
        dprintk("%s\n", __FUNCTION__);
 
-       dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]);
+       dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
 
        /* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip.
         * direct write is required for Philips TUV1236D and ALPS TDHU2 */
        switch (state->demod_chip) {
                case NXT2004:
-                       if (i2c_writebytes(state, state->config->pll_address, data, 4))
+                       if (i2c_writebytes(state, data[0], data+1, 4))
                                printk(KERN_WARNING "nxt200x: error writing to tuner\n");
                        /* wait until we have a lock */
                        while (count < 20) {
-                               i2c_readbytes(state, state->config->pll_address, &buf, 1);
+                               i2c_readbytes(state, data[0], &buf, 1);
                                if (buf & 0x40)
                                        return 0;
                                msleep(100);
@@ -361,10 +360,10 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
                        nxt200x_writebytes(state, 0x34, &buf, 1);
 
                        /* write actual tuner bytes */
-                       nxt200x_writebytes(state, 0x36, data, 4);
+                       nxt200x_writebytes(state, 0x36, data+1, 4);
 
                        /* set tuner i2c address */
-                       buf = state->config->pll_address;
+                       buf = data[0] << 1;
                        nxt200x_writebytes(state, 0x35, &buf, 1);
 
                        /* write UC Opmode to begin transfer */
@@ -534,7 +533,7 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
                                             struct dvb_frontend_parameters *p)
 {
        struct nxt200x_state* state = fe->demodulator_priv;
-       u8 buf[4];
+       u8 buf[5];
 
        /* stop the micro first */
        nxt200x_microcontroller_stop(state);
@@ -548,7 +547,9 @@ static int nxt200x_setup_frontend_parameters (struct dvb_frontend* fe,
        }
 
        /* get tuning information */
-       dvb_pll_configure(state->config->pll_desc, buf, p->frequency, 0);
+       if (fe->ops.tuner_ops.calc_regs) {
+               fe->ops.tuner_ops.calc_regs(fe, p, buf, 5);
+       }
 
        /* set additional params */
        switch (p->u.vsb.modulation) {
@@ -1159,7 +1160,6 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
        state->initialised = 0;
 
        /* read card id */
@@ -1198,7 +1198,7 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
        }
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
index 1d9d70bc37efc06dadcc703423154cadc6243557..34d61735845be8199d3d75e3c89614250b8f57aa 100644 (file)
@@ -38,10 +38,6 @@ struct nxt200x_config
        /* the demodulator's i2c address */
        u8 demod_address;
 
-       /* tuner information */
-       u8 pll_address;
-       struct dvb_pll_desc *pll_desc;
-
        /* used to set pll input */
        int (*set_pll_input)(u8* buf, int input);
 
index a16eeba0020d8484a8a43c44032eb754e831fdba..d313d7dcf3862c6fa67e1a0b6e0cd33a9c386277 100644 (file)
@@ -33,7 +33,6 @@
 
 struct nxt6000_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        /* configuration settings */
        const struct nxt6000_config* config;
        struct dvb_frontend frontend;
@@ -207,12 +206,6 @@ static void nxt6000_setup(struct dvb_frontend* fe)
                nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0);
 
        nxt6000_writereg(state, TS_FORMAT, 0);
-
-       if (state->config->pll_init) {
-               nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);        /* open i2c bus switch */
-               state->config->pll_init(fe);
-               nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);        /* close i2c bus switch */
-       }
 }
 
 static void nxt6000_dump_status(struct nxt6000_state *state)
@@ -469,9 +462,10 @@ static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        struct nxt6000_state* state = fe->demodulator_priv;
        int result;
 
-       nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);        /* open i2c bus switch */
-       state->config->pll_set(fe, param);
-       nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);        /* close i2c bus switch */
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, param);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
        if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0)
                return result;
@@ -532,6 +526,17 @@ static int nxt6000_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_fron
        return 0;
 }
 
+static int nxt6000_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct nxt6000_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);
+       } else {
+               return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);
+       }
+}
+
 static struct dvb_frontend_ops nxt6000_ops;
 
 struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
@@ -546,13 +551,12 @@ struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops));
 
        /* check if the demod is there */
        if (nxt6000_readreg(state, OFDM_MSC_REV) != NXT6000ASICDEVICE) goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -584,6 +588,7 @@ static struct dvb_frontend_ops nxt6000_ops = {
        .release = nxt6000_release,
 
        .init = nxt6000_init,
+       .i2c_gate_ctrl = nxt6000_i2c_gate_ctrl,
 
        .get_tune_settings = nxt6000_fe_get_tune_settings,
 
index b7d9bead30029bbd028019bcffd75c296659897b..117031d117082009c1fab69377059f29110f7a5a 100644 (file)
@@ -31,10 +31,6 @@ struct nxt6000_config
 
        /* should clock inversion be used? */
        u8 clock_inversion:1;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
index 80e0f28127b7bd44b51cb19cc1d7df730983117f..d20ab30c1e8341d37af3600a41d97bb1ff02a7c1 100644 (file)
@@ -54,7 +54,6 @@ static int debug;
 struct or51132_state
 {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
 
        /* Configuration settings */
        const struct or51132_config* config;
@@ -106,9 +105,8 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
 {
        struct or51132_state* state = fe->demodulator_priv;
        static u8 run_buf[] = {0x7F,0x01};
-       static u8 get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
-       u8 rec_buf[14];
-       u8 cmd_buf[14];
+       u8 rec_buf[8];
+       u8 cmd_buf[3];
        u32 firmwareAsize, firmwareBsize;
        int i,ret;
 
@@ -157,7 +155,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
        cmd_buf[0] = 0x10;
        cmd_buf[1] = 0x10;
        cmd_buf[2] = 0x00;
-       cmd_buf[3] = 0x00;
        msleep(20); /* 20ms */
        if ((ret = i2c_writebytes(state,state->config->demod_address,
                                 cmd_buf,3))) {
@@ -167,8 +164,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
 
        cmd_buf[0] = 0x04;
        cmd_buf[1] = 0x17;
-       cmd_buf[2] = 0x00;
-       cmd_buf[3] = 0x00;
        msleep(20); /* 20ms */
        if ((ret = i2c_writebytes(state,state->config->demod_address,
                                 cmd_buf,2))) {
@@ -178,8 +173,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
 
        cmd_buf[0] = 0x00;
        cmd_buf[1] = 0x00;
-       cmd_buf[2] = 0x00;
-       cmd_buf[3] = 0x00;
        msleep(20); /* 20ms */
        if ((ret = i2c_writebytes(state,state->config->demod_address,
                                 cmd_buf,2))) {
@@ -189,7 +182,11 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
 
        for(i=0;i<4;i++) {
                msleep(20); /* 20ms */
-               get_ver_buf[4] = i+1;
+               /* Once upon a time, this command might have had something
+                  to do with getting the firmware version, but it's
+                  not used anymore:
+                  {0x04,0x00,0x30,0x00,i+1} */
+               /* Read 8 bytes, two bytes at a time */
                if ((ret = i2c_readbytes(state,state->config->demod_address,
                                        &rec_buf[i*2],2))) {
                        printk(KERN_WARNING
@@ -208,7 +205,6 @@ static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware
        cmd_buf[0] = 0x10;
        cmd_buf[1] = 0x00;
        cmd_buf[2] = 0x00;
-       cmd_buf[3] = 0x00;
        msleep(20); /* 20ms */
        if ((ret = i2c_writebytes(state,state->config->demod_address,
                                 cmd_buf,3))) {
@@ -243,7 +239,7 @@ static int or51132_sleep(struct dvb_frontend* fe)
 static int or51132_setmode(struct dvb_frontend* fe)
 {
        struct or51132_state* state = fe->demodulator_priv;
-       unsigned char cmd_buf[4];
+       unsigned char cmd_buf[3];
 
        dprintk("setmode %d\n",(int)state->current_modulation);
        /* set operation mode in Receiver 1 register; */
@@ -263,7 +259,6 @@ static int or51132_setmode(struct dvb_frontend* fe)
        default:
                printk("setmode:Modulation set to unsupported value\n");
        };
-       cmd_buf[3] = 0x00;
        if (i2c_writebytes(state,state->config->demod_address,
                           cmd_buf,3)) {
                printk(KERN_WARNING "or51132: set_mode error 1\n");
@@ -301,7 +296,6 @@ static int or51132_setmode(struct dvb_frontend* fe)
        default:
                printk("setmode: Modulation set to unsupported value\n");
        };
-       cmd_buf[3] = 0x00;
        msleep(20); /* 20ms */
        if (i2c_writebytes(state,state->config->demod_address,
                           cmd_buf,3)) {
@@ -313,52 +307,65 @@ static int or51132_setmode(struct dvb_frontend* fe)
        return 0;
 }
 
+/* Some modulations use the same firmware.  This classifies modulations
+   by the firmware they use. */
+#define MOD_FWCLASS_UNKNOWN    0
+#define MOD_FWCLASS_VSB                1
+#define MOD_FWCLASS_QAM                2
+static int modulation_fw_class(fe_modulation_t modulation)
+{
+       switch(modulation) {
+       case VSB_8:
+               return MOD_FWCLASS_VSB;
+       case QAM_AUTO:
+       case QAM_64:
+       case QAM_256:
+               return MOD_FWCLASS_QAM;
+       default:
+               return MOD_FWCLASS_UNKNOWN;
+       }
+}
+
 static int or51132_set_parameters(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *param)
 {
        int ret;
-       u8 buf[4];
        struct or51132_state* state = fe->demodulator_priv;
        const struct firmware *fw;
-
-       /* Change only if we are actually changing the modulation */
-       if (state->current_modulation != param->u.vsb.modulation) {
-               switch(param->u.vsb.modulation) {
-               case VSB_8:
+       const char *fwname;
+       int clock_mode;
+
+       /* Upload new firmware only if we need a different one */
+       if (modulation_fw_class(state->current_modulation) !=
+           modulation_fw_class(param->u.vsb.modulation)) {
+               switch(modulation_fw_class(param->u.vsb.modulation)) {
+               case MOD_FWCLASS_VSB:
                        dprintk("set_parameters VSB MODE\n");
-                       printk("or51132: Waiting for firmware upload(%s)...\n",
-                              OR51132_VSB_FIRMWARE);
-                       ret = request_firmware(&fw, OR51132_VSB_FIRMWARE,
-                                              &state->i2c->dev);
-                       if (ret){
-                               printk(KERN_WARNING "or51132: No firmware up"
-                                      "loaded(timeout or file not found?)\n");
-                               return ret;
-                       }
+                       fwname = OR51132_VSB_FIRMWARE;
+
                        /* Set non-punctured clock for VSB */
-                       state->config->set_ts_params(fe, 0);
+                       clock_mode = 0;
                        break;
-               case QAM_AUTO:
-               case QAM_64:
-               case QAM_256:
+               case MOD_FWCLASS_QAM:
                        dprintk("set_parameters QAM MODE\n");
-                       printk("or51132: Waiting for firmware upload(%s)...\n",
-                              OR51132_QAM_FIRMWARE);
-                       ret = request_firmware(&fw, OR51132_QAM_FIRMWARE,
-                                              &state->i2c->dev);
-                       if (ret){
-                               printk(KERN_WARNING "or51132: No firmware up"
-                                      "loaded(timeout or file not found?)\n");
-                               return ret;
-                       }
+                       fwname = OR51132_QAM_FIRMWARE;
+
                        /* Set punctured clock for QAM */
-                       state->config->set_ts_params(fe, 1);
+                       clock_mode = 1;
                        break;
                default:
-                       printk("or51132:Modulation type(%d) UNSUPPORTED\n",
+                       printk("or51132: Modulation type(%d) UNSUPPORTED\n",
                               param->u.vsb.modulation);
                        return -1;
-               };
+               }
+               printk("or51132: Waiting for firmware upload(%s)...\n",
+                      fwname);
+               ret = request_firmware(&fw, fwname, &state->i2c->dev);
+               if (ret) {
+                       printk(KERN_WARNING "or51132: No firmware up"
+                              "loaded(timeout or file not found?)\n");
+                       return ret;
+               }
                ret = or51132_load_firmware(fe, fw);
                release_firmware(fw);
                if (ret) {
@@ -367,18 +374,18 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
                        return ret;
                }
                printk("or51132: Firmware upload complete.\n");
-
+               state->config->set_ts_params(fe, clock_mode);
+       }
+       /* Change only if we are actually changing the modulation */
+       if (state->current_modulation != param->u.vsb.modulation) {
                state->current_modulation = param->u.vsb.modulation;
                or51132_setmode(fe);
        }
 
-       dvb_pll_configure(state->config->pll_desc, buf,
-                         param->frequency, 0);
-       dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
-               "0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
-       if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
-               printk(KERN_WARNING "or51132: set_parameters error "
-                      "writing to tuner\n");
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, param);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
        /* Set to current mode */
        or51132_setmode(fe);
@@ -388,6 +395,44 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
        return 0;
 }
 
+static int or51132_get_parameters(struct dvb_frontend* fe,
+                                 struct dvb_frontend_parameters *param)
+{
+       struct or51132_state* state = fe->demodulator_priv;
+       u8 buf[2];
+
+       /* Receiver Status */
+       buf[0]=0x04;
+       buf[1]=0x00;
+       msleep(30); /* 30ms */
+       if (i2c_writebytes(state,state->config->demod_address,buf,2)) {
+               printk(KERN_WARNING "or51132: get_parameters write error\n");
+               return -EREMOTEIO;
+       }
+       msleep(30); /* 30ms */
+       if (i2c_readbytes(state,state->config->demod_address,buf,2)) {
+               printk(KERN_WARNING "or51132: get_parameters read error\n");
+               return -EREMOTEIO;
+       }
+       switch(buf[0]) {
+               case 0x06: param->u.vsb.modulation = VSB_8; break;
+               case 0x43: param->u.vsb.modulation = QAM_64; break;
+               case 0x45: param->u.vsb.modulation = QAM_256; break;
+               default:
+                       printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
+                              buf[0]);
+                       return -EREMOTEIO;
+       }
+
+       /* FIXME: Read frequency from frontend, take AFC into account */
+       param->frequency = state->current_frequency;
+
+       /* FIXME: How to read inversion setting? Receiver 6 register? */
+       param->inversion = INVERSION_AUTO;
+
+       return 0;
+}
+
 static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
        struct or51132_state* state = fe->demodulator_priv;
@@ -572,12 +617,11 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
        /* Setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
        state->current_frequency = -1;
        state->current_modulation = -1;
 
        /* Create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -590,7 +634,7 @@ static struct dvb_frontend_ops or51132_ops = {
 
        .info = {
                .name                   = "Oren OR51132 VSB/QAM Frontend",
-               .type                   = FE_ATSC,
+               .type                   = FE_ATSC,
                .frequency_min          = 44000000,
                .frequency_max          = 958000000,
                .frequency_stepsize     = 166666,
@@ -606,6 +650,7 @@ static struct dvb_frontend_ops or51132_ops = {
        .sleep = or51132_sleep,
 
        .set_frontend = or51132_set_parameters,
+       .get_frontend = or51132_get_parameters,
        .get_tune_settings = or51132_get_tune_settings,
 
        .read_status = or51132_read_status,
index 622cdd18381b9e40ecc887cf2d3517d53b4fda1b..89658883abf5eb65a241b9b8f14bd024f8a9738d 100644 (file)
@@ -29,8 +29,6 @@ struct or51132_config
 {
        /* The demodulator's i2c address */
        u8 demod_address;
-       u8 pll_address;
-       struct dvb_pll_desc *pll_desc;
 
        /* Need to set device param for start_dma */
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
index 7c3aed1f546be2609631206639271fbd6f9b178b..26bed616fabec1c1293e10b7ade29940ee443ad5 100644 (file)
@@ -54,7 +54,6 @@ static u8 cmd_buf[] = {0x04,0x01,0x50,0x80,0x06}; // ATSC
 struct or51211_state {
 
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
 
        /* Configuration settings */
        const struct or51211_config* config;
@@ -585,12 +584,11 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config,
        /* Setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
        state->initialized = 0;
        state->current_frequency = 0;
 
        /* Create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
index d69477596921909e38ab53fda4d236f979352eb8..2c2c344c4c648a3c85c92f3c7e6f8f4a98e85594 100644 (file)
@@ -38,7 +38,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 struct s5h1420_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        const struct s5h1420_config* config;
        struct dvb_frontend frontend;
 
@@ -584,7 +583,6 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        struct s5h1420_state* state = fe->demodulator_priv;
        int frequency_delta;
        struct dvb_frontend_tune_settings fesettings;
-       u32 tmp;
 
        /* check if we should do a fast-tune */
        memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
@@ -596,10 +594,17 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
            (state->fec_inner == p->u.qpsk.fec_inner) &&
            (state->symbol_rate == p->u.qpsk.symbol_rate)) {
 
-               if (state->config->pll_set) {
-                       s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
-                       state->config->pll_set(fe, p, &tmp);
+               if (fe->ops.tuner_ops.set_params) {
+                       fe->ops.tuner_ops.set_params(fe, p);
+                       if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+               }
+               if (fe->ops.tuner_ops.get_frequency) {
+                       u32 tmp;
+                       fe->ops.tuner_ops.get_frequency(fe, &tmp);
+                       if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
                        s5h1420_setfreqoffset(state, p->frequency - tmp);
+               } else {
+                       s5h1420_setfreqoffset(state, 0);
                }
                return 0;
        }
@@ -646,9 +651,9 @@ static int s5h1420_set_frontend(struct dvb_frontend* fe,
        s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
 
        /* set tuner PLL */
-       if (state->config->pll_set) {
-               s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
-               state->config->pll_set(fe, p, &tmp);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
                s5h1420_setfreqoffset(state, 0);
        }
 
@@ -708,6 +713,17 @@ static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
        return 0;
 }
 
+static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct s5h1420_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+       } else {
+               return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
+       }
+}
+
 static int s5h1420_init (struct dvb_frontend* fe)
 {
        struct s5h1420_state* state = fe->demodulator_priv;
@@ -717,13 +733,6 @@ static int s5h1420_init (struct dvb_frontend* fe)
        msleep(10);
        s5h1420_reset(state);
 
-       /* init PLL */
-       if (state->config->pll_init) {
-               s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
-               state->config->pll_init(fe);
-               s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
-       }
-
        return 0;
 }
 
@@ -756,7 +765,6 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
        state->postlocked = 0;
        state->fclk = 88000000;
        state->tunedfreq = 0;
@@ -769,7 +777,7 @@ struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
                goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -800,6 +808,7 @@ static struct dvb_frontend_ops s5h1420_ops = {
 
        .init = s5h1420_init,
        .sleep = s5h1420_sleep,
+       .i2c_gate_ctrl = s5h1420_i2c_gate_ctrl,
 
        .set_frontend = s5h1420_set_frontend,
        .get_frontend = s5h1420_get_frontend,
index 73296f13c324b67910b8f55672395d7e63d3351a..4e39015fa67e38c17bf519e8f6b143ff81a2fb3f 100644 (file)
@@ -32,10 +32,6 @@ struct s5h1420_config
 
        /* does the inversion require inversion? */
        u8 invert:1;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout);
 };
 
 extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
index 73829e647e50ad0cccb0e2f8cf6f8b18ada520ff..44ec5b9a469580b943c3f92ca1bcbfd6163f6171 100644 (file)
@@ -44,8 +44,6 @@ struct sp8870_state {
 
        struct i2c_adapter* i2c;
 
-       struct dvb_frontend_ops ops;
-
        const struct sp8870_config* config;
 
        struct dvb_frontend frontend;
@@ -262,9 +260,10 @@ static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
        sp8870_microcontroller_stop(state);
 
        // set tuner parameters
-       sp8870_writereg(state, 0x206, 0x001);
-       state->config->pll_set(fe, p);
-       sp8870_writereg(state, 0x206, 0x000);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
        // sample rate correction bit [23..17]
        sp8870_writereg(state, 0x0319, 0x000A);
@@ -349,13 +348,6 @@ static int sp8870_init (struct dvb_frontend* fe)
        sp8870_writereg(state, 0x0D00, 0x010);
        sp8870_writereg(state, 0x0D01, 0x000);
 
-       /* setup PLL */
-       if (state->config->pll_init) {
-               sp8870_writereg(state, 0x206, 0x001);
-               state->config->pll_init(fe);
-               sp8870_writereg(state, 0x206, 0x000);
-       }
-
        return 0;
 }
 
@@ -541,6 +533,17 @@ static int sp8870_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend
        return 0;
 }
 
+static int sp8870_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct sp8870_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               return sp8870_writereg(state, 0x206, 0x001);
+       } else {
+               return sp8870_writereg(state, 0x206, 0x000);
+       }
+}
+
 static void sp8870_release(struct dvb_frontend* fe)
 {
        struct sp8870_state* state = fe->demodulator_priv;
@@ -561,14 +564,13 @@ struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
        state->initialised = 0;
 
        /* check if the demod is there */
        if (sp8870_readreg(state, 0x0200) < 0) goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -597,6 +599,7 @@ static struct dvb_frontend_ops sp8870_ops = {
 
        .init = sp8870_init,
        .sleep = sp8870_sleep,
+       .i2c_gate_ctrl = sp8870_i2c_gate_ctrl,
 
        .set_frontend = sp8870_set_frontend,
        .get_tune_settings = sp8870_get_tune_settings,
index f3b555dbc960d39370fbb367991ad1048eec904a..93afbb969d6b57f7b54cc104fe575fc5ce4641f4 100644 (file)
@@ -31,10 +31,6 @@ struct sp8870_config
        /* the demodulator's i2c address */
        u8 demod_address;
 
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
        /* request firmware for device */
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
index eb8a602198ca99ad6990c783f31a305c368214b8..b0a2b02f660869f2724aedb46e45c0b3e8e08a22 100644 (file)
@@ -24,7 +24,6 @@
 
 struct sp887x_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        const struct sp887x_config* config;
        struct dvb_frontend frontend;
 
@@ -208,15 +207,6 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
        /* bit 0x010: enable data valid signal */
        sp887x_writereg(state, 0xd00, 0x010);
        sp887x_writereg(state, 0x0d1, 0x000);
-
-       /* setup the PLL */
-       if (state->config->pll_init) {
-               sp887x_writereg(state, 0x206, 0x001);
-               state->config->pll_init(fe);
-               sp887x_writereg(state, 0x206, 0x000);
-       }
-
-       printk ("done.\n");
        return 0;
 };
 
@@ -362,9 +352,16 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
        sp887x_microcontroller_stop(state);
 
        /* setup the PLL */
-       sp887x_writereg(state, 0x206, 0x001);
-       actual_freq = state->config->pll_set(fe, p);
-       sp887x_writereg(state, 0x206, 0x000);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+       if (fe->ops.tuner_ops.get_frequency) {
+               fe->ops.tuner_ops.get_frequency(fe, &actual_freq);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       } else {
+               actual_freq = p->frequency;
+       }
 
        /* read status reg in order to clear <pending irqs */
        sp887x_readreg(state, 0x200);
@@ -486,6 +483,17 @@ static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
        return 0;
 }
 
+static int sp887x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct sp887x_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               return sp887x_writereg(state, 0x206, 0x001);
+       } else {
+               return sp887x_writereg(state, 0x206, 0x000);
+       }
+}
+
 static int sp887x_sleep(struct dvb_frontend* fe)
 {
        struct sp887x_state* state = fe->demodulator_priv;
@@ -555,14 +563,13 @@ struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
        state->initialised = 0;
 
        /* check if the demod is there */
        if (sp887x_readreg(state, 0x0200) < 0) goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -589,6 +596,7 @@ static struct dvb_frontend_ops sp887x_ops = {
 
        .init = sp887x_init,
        .sleep = sp887x_sleep,
+       .i2c_gate_ctrl = sp887x_i2c_gate_ctrl,
 
        .set_frontend = sp887x_setup_frontend_parameters,
        .get_tune_settings = sp887x_get_tune_settings,
index 6a05d8f8e8cc4d4ef642188c5d87bafa0f340df4..c44b0ebdf1e220e32dd2c10a469e106ba1401c9f 100644 (file)
@@ -13,12 +13,6 @@ struct sp887x_config
        /* the demodulator's i2c address */
        u8 demod_address;
 
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-
-       /* this should return the actual frequency tuned to */
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
        /* request firmware for device */
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
index eb15676d374f1fd4aadee45345163cd094ab56c3..1ca64249010ce54d4a3fa58946695396d22ccf74 100644 (file)
@@ -32,7 +32,6 @@
 
 struct stv0297_state {
        struct i2c_adapter *i2c;
-       struct dvb_frontend_ops ops;
        const struct stv0297_config *config;
        struct dvb_frontend frontend;
 
@@ -68,19 +67,25 @@ static int stv0297_readreg(struct stv0297_state *state, u8 reg)
        int ret;
        u8 b0[] = { reg };
        u8 b1[] = { 0 };
-       struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len =
-                                 1},
-       {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
-       };
+       struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1},
+                                {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
+                              };
 
        // this device needs a STOP between the register and data
-       if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
-               dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
-               return -1;
-       }
-       if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
-               dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
-               return -1;
+       if (state->config->stop_during_read) {
+               if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+                       return -1;
+               }
+               if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+                       return -1;
+               }
+       } else {
+               if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+                       return -1;
+               }
        }
 
        return b1[0];
@@ -107,13 +112,20 @@ static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len
        };
 
        // this device needs a STOP between the register and data
-       if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
-               dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
-               return -1;
-       }
-       if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
-               dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
-               return -1;
+       if (state->config->stop_during_read) {
+               if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+                       return -1;
+               }
+               if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+                       return -1;
+               }
+       } else {
+               if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+                       dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+                       return -1;
+               }
        }
 
        return 0;
@@ -276,12 +288,14 @@ static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_invers
        return 0;
 }
 
-int stv0297_enable_plli2c(struct dvb_frontend *fe)
+static int stv0297_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
        struct stv0297_state *state = fe->demodulator_priv;
 
-       stv0297_writereg(state, 0x87, 0x78);
-       stv0297_writereg(state, 0x86, 0xc8);
+       if (enable) {
+               stv0297_writereg(state, 0x87, 0x78);
+               stv0297_writereg(state, 0x86, 0xc8);
+       }
 
        return 0;
 }
@@ -296,9 +310,6 @@ static int stv0297_init(struct dvb_frontend *fe)
                stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);
        msleep(200);
 
-       if (state->config->pll_init)
-               state->config->pll_init(fe);
-
        return 0;
 }
 
@@ -389,7 +400,7 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        case QAM_32:
        case QAM_64:
                delay = 100;
-               sweeprate = 1500;
+               sweeprate = 1000;
                break;
 
        case QAM_128:
@@ -421,7 +432,10 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
        }
 
        stv0297_init(fe);
-       state->config->pll_set(fe, p);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
        /* clear software interrupts */
        stv0297_writereg(state, 0x82, 0x0);
@@ -634,7 +648,6 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
        state->base_freq = 0;
 
        /* check if the demod is there */
@@ -642,7 +655,7 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
                goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -668,6 +681,7 @@ static struct dvb_frontend_ops stv0297_ops = {
 
        .init = stv0297_init,
        .sleep = stv0297_sleep,
+       .i2c_gate_ctrl = stv0297_i2c_gate_ctrl,
 
        .set_frontend = stv0297_set_frontend,
        .get_frontend = stv0297_get_frontend,
@@ -684,4 +698,3 @@ MODULE_AUTHOR("Dennis Noermann and Andrew de Quincey");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(stv0297_attach);
-EXPORT_SYMBOL(stv0297_enable_plli2c);
index 9e53f019db717e284cf50fd1b4f7390f2f173fe6..1da5384fb985454b06f6aa8b027dba583853338d 100644 (file)
@@ -38,13 +38,11 @@ struct stv0297_config
        /* does the "inversion" need inverted? */
        u8 invert:1;
 
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+       /* set to 1 if the device requires an i2c STOP during reading */
+       u8 stop_during_read:1;
 };
 
 extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
                                           struct i2c_adapter* i2c);
-extern int stv0297_enable_plli2c(struct dvb_frontend* fe);
 
 #endif // STV0297_H
index 5bcd00f792e63ac7dbe255223103c91b4015865e..96648a75440dc9f7972bb27a1f113faec024d7b3 100644 (file)
@@ -56,7 +56,6 @@
 
 struct stv0299_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        const struct stv0299_config* config;
        struct dvb_frontend frontend;
 
@@ -131,13 +130,6 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
        return ret == 2 ? 0 : ret;
 }
 
-int stv0299_enable_plli2c (struct dvb_frontend* fe)
-{
-       struct stv0299_state* state = fe->demodulator_priv;
-
-       return stv0299_writeregI(state, 0x05, 0xb5);    /*  enable i2c repeater on stv0299  */
-}
-
 static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
 {
        dprintk ("%s\n", __FUNCTION__);
@@ -457,12 +449,6 @@ static int stv0299_init (struct dvb_frontend* fe)
        for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
                stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]);
 
-       if (state->config->pll_init) {
-               stv0299_writeregI(state, 0x05, 0xb5);   /*  enable i2c repeater on stv0299  */
-               state->config->pll_init(fe, state->i2c);
-               stv0299_writeregI(state, 0x05, 0x35);   /*  disable i2c repeater on stv0299  */
-       }
-
        return 0;
 }
 
@@ -560,9 +546,10 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
        if (state->config->invert) invval = (~invval) & 1;
        stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval);
 
-       stv0299_writeregI(state, 0x05, 0xb5);   /*  enable i2c repeater on stv0299  */
-       state->config->pll_set(fe, state->i2c, p);
-       stv0299_writeregI(state, 0x05, 0x35);   /*  disable i2c repeater on stv0299  */
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
        stv0299_set_FEC (state, p->u.qpsk.fec_inner);
        stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate);
@@ -611,6 +598,19 @@ static int stv0299_sleep(struct dvb_frontend* fe)
        return 0;
 }
 
+static int stv0299_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct stv0299_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               stv0299_writeregI(state, 0x05, 0xb5);
+       } else {
+               stv0299_writeregI(state, 0x05, 0x35);
+       }
+       udelay(1);
+       return 0;
+}
+
 static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
        struct stv0299_state* state = fe->demodulator_priv;
@@ -647,7 +647,6 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &stv0299_ops, sizeof(struct dvb_frontend_ops));
        state->initialised = 0;
        state->tuner_frequency = 0;
        state->symbol_rate = 0;
@@ -664,7 +663,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
        if (id != 0xa1 && id != 0x80) goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &stv0299_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -695,6 +694,7 @@ static struct dvb_frontend_ops stv0299_ops = {
 
        .init = stv0299_init,
        .sleep = stv0299_sleep,
+       .i2c_gate_ctrl = stv0299_i2c_gate_ctrl,
 
        .set_frontend = stv0299_set_frontend,
        .get_frontend = stv0299_get_frontend,
@@ -721,9 +721,8 @@ MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
 MODULE_DESCRIPTION("ST STV0299 DVB Demodulator driver");
 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
-             "Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy");
+             "Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(stv0299_enable_plli2c);
 EXPORT_SYMBOL(stv0299_writereg);
 EXPORT_SYMBOL(stv0299_attach);
index 32c87b4c2f1375ec78c267db07cc666130eb6642..1504828e423246faf41c4c5f09a9b864344af627 100644 (file)
@@ -87,14 +87,9 @@ struct stv0299_config
 
        /* Set the symbol rate */
        int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend *fe, struct i2c_adapter *i2c);
-       int (*pll_set)(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params);
 };
 
 extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
-extern int stv0299_enable_plli2c (struct dvb_frontend* fe);
 
 extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
                                           struct i2c_adapter* i2c);
index 21255cac9793e89b07a3627a076120364cb83163..e83ff2104c9b650c2e30a52118b7e291afa581f9 100644 (file)
@@ -36,7 +36,6 @@
 
 struct tda10021_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        /* configuration settings */
        const struct tda10021_config* config;
        struct dvb_frontend frontend;
@@ -90,6 +89,14 @@ static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
        return (ret != 1) ? -EREMOTEIO : 0;
 }
 
+int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data)
+{
+       struct tda10021_state* state = fe->demodulator_priv;
+
+       return tda10021_writereg(state, reg, data);
+}
+EXPORT_SYMBOL(tda10021_write_byte);
+
 static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
 {
        u8 b0 [] = { reg };
@@ -225,13 +232,6 @@ static int tda10021_init (struct dvb_frontend *fe)
 
        //Activate PLL
        tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
-
-       if (state->config->pll_init) {
-               lock_tuner(state);
-               state->config->pll_init(fe);
-               unlock_tuner(state);
-       }
-
        return 0;
 }
 
@@ -259,9 +259,10 @@ static int tda10021_set_parameters (struct dvb_frontend *fe,
 
        //printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate);
 
-       lock_tuner(state);
-       state->config->pll_set(fe, p);
-       unlock_tuner(state);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
 
        tda10021_set_symbolrate (state, p->u.qam.symbol_rate);
        tda10021_writereg (state, 0x34, state->pwm);
@@ -376,6 +377,18 @@ static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
        return 0;
 }
 
+static int tda10021_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct tda10021_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               lock_tuner(state);
+       } else {
+               unlock_tuner(state);
+       }
+       return 0;
+}
+
 static int tda10021_sleep(struct dvb_frontend* fe)
 {
        struct tda10021_state* state = fe->demodulator_priv;
@@ -407,7 +420,6 @@ struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
        state->pwm = pwm;
        state->reg0 = tda10021_inittab[0];
 
@@ -415,7 +427,7 @@ struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
        if ((tda10021_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -448,6 +460,7 @@ static struct dvb_frontend_ops tda10021_ops = {
 
        .init = tda10021_init,
        .sleep = tda10021_sleep,
+       .i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
 
        .set_frontend = tda10021_set_parameters,
        .get_frontend = tda10021_get_frontend,
index 53be939e8c5583e679f09e5afd25134224d22aab..b1df4259bee9f4d7c16a0030d34f04e062517dcf 100644 (file)
@@ -30,13 +30,11 @@ struct tda10021_config
 {
        /* the demodulator's i2c address */
        u8 demod_address;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
                                            struct i2c_adapter* i2c, u8 pwm);
 
+extern int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data);
+
 #endif // TDA10021_H
index b83dafa4e12cdcc79a023fe683f1394eeb05de72..59a2ed614fca4046d4bd2474851f5f2552ac55c3 100644 (file)
@@ -47,7 +47,6 @@ enum tda1004x_demod {
 
 struct tda1004x_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        const struct tda1004x_config* config;
        struct dvb_frontend frontend;
 
@@ -600,13 +599,6 @@ static int tda10045_init(struct dvb_frontend* fe)
 
        tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC
 
-       // Init the PLL
-       if (state->config->pll_init) {
-               tda1004x_enable_tuner_i2c(state);
-               state->config->pll_init(fe);
-               tda1004x_disable_tuner_i2c(state);
-       }
-
        // tda setup
        tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
        tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream
@@ -635,16 +627,6 @@ static int tda10046_init(struct dvb_frontend* fe)
                        return -EIO;
        }
 
-       // Init the tuner PLL
-       if (state->config->pll_init) {
-               tda1004x_enable_tuner_i2c(state);
-               if (state->config->pll_init(fe)) {
-                       printk(KERN_ERR "tda1004x: pll init failed\n");
-                       return  -EIO;
-               }
-               tda1004x_disable_tuner_i2c(state);
-       }
-
        // tda setup
        tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
        tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87);    // 100 ppm crystal, select HP stream
@@ -712,12 +694,10 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
        }
 
        // set frequency
-       tda1004x_enable_tuner_i2c(state);
-       if (state->config->pll_set(fe, fe_params)) {
-               printk(KERN_ERR "tda1004x: pll set failed\n");
-               return  -EIO;
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, fe_params);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
        }
-       tda1004x_disable_tuner_i2c(state);
 
        // Hardcoded to use auto as much as possible on the TDA10045 as it
        // is very unreliable if AUTO mode is _not_ used.
@@ -1183,16 +1163,6 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
                break;
 
        case TDA1004X_DEMOD_TDA10046:
-               if (state->config->pll_sleep != NULL) {
-                       tda1004x_enable_tuner_i2c(state);
-                       state->config->pll_sleep(fe);
-                       if (state->config->if_freq != TDA10046_FREQ_052) {
-                               /* special hack for Philips EUROPA Based boards:
-                                * keep the I2c bridge open for tuner access in analog mode
-                                */
-                               tda1004x_disable_tuner_i2c(state);
-                       }
-               }
                /* set outputs to tristate */
                tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff);
                tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
@@ -1202,6 +1172,17 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
        return 0;
 }
 
+static int tda1004x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct tda1004x_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               return tda1004x_enable_tuner_i2c(state);
+       } else {
+               return tda1004x_disable_tuner_i2c(state);
+       }
+}
+
 static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
        fesettings->min_delay_ms = 800;
@@ -1235,6 +1216,7 @@ static struct dvb_frontend_ops tda10045_ops = {
 
        .init = tda10045_init,
        .sleep = tda1004x_sleep,
+       .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
 
        .set_frontend = tda1004x_set_fe,
        .get_frontend = tda1004x_get_fe,
@@ -1260,7 +1242,6 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
        state->demod_type = TDA1004X_DEMOD_TDA10045;
 
        /* check if the demod is there */
@@ -1270,7 +1251,7 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
        }
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 }
@@ -1293,6 +1274,7 @@ static struct dvb_frontend_ops tda10046_ops = {
 
        .init = tda10046_init,
        .sleep = tda1004x_sleep,
+       .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
 
        .set_frontend = tda1004x_set_fe,
        .get_frontend = tda1004x_get_fe,
@@ -1318,7 +1300,6 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
        state->demod_type = TDA1004X_DEMOD_TDA10046;
 
        /* check if the demod is there */
@@ -1328,7 +1309,7 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
        }
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 }
index cc0c4af64067037312fde708aef5dea56c9b5459..b877b23ed734e07398f2ac9d2ee5d2ef58508fc0 100644 (file)
@@ -66,11 +66,6 @@ struct tda1004x_config
        /* AGC configuration */
        enum tda10046_agc agc_config;
 
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       void (*pll_sleep)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
        /* request firmware for device */
        /* set this to NULL if the card has a firmware EEPROM */
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
index 91baa9cedd79846c90d58db1e4c12ee23551bb10..3aa45ebbac3da34252cb40d42f11c73f53abf7e6 100644 (file)
@@ -37,7 +37,6 @@
 
 struct tda8083_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        /* configuration settings */
        const struct tda8083_config* config;
        struct dvb_frontend frontend;
@@ -293,7 +292,11 @@ static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
 {
        struct tda8083_state* state = fe->demodulator_priv;
 
-       state->config->pll_set(fe, p);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
        tda8083_set_inversion (state, p->inversion);
        tda8083_set_fec (state, p->u.qpsk.fec_inner);
        tda8083_set_symbolrate (state, p->u.qpsk.symbol_rate);
@@ -334,8 +337,6 @@ static int tda8083_init(struct dvb_frontend* fe)
        for (i=0; i<44; i++)
                tda8083_writereg (state, i, tda8083_init_tab[i]);
 
-       if (state->config->pll_init) state->config->pll_init(fe);
-
        tda8083_writereg (state, 0x00, 0x3c);
        tda8083_writereg (state, 0x00, 0x04);
 
@@ -395,13 +396,12 @@ struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
 
        /* check if the demod is there */
        if ((tda8083_readreg(state, 0x00)) != 0x05) goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
index 466663307bf173693fb5cf94fd9269002a573455..e7a48f61ea2c6382e2e272f7f1b37f5e3c58d813 100644 (file)
@@ -33,10 +33,6 @@ struct tda8083_config
 {
        /* the demodulator's i2c address */
        u8 demod_address;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
index ad8647a3c85e69c6caa321e2d2a334afa6e54526..6bffe85c161cd1b54cbba3758c7402879e079fb6 100644 (file)
@@ -35,7 +35,6 @@
 
 struct ves1820_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        /* configuration settings */
        const struct ves1820_config* config;
        struct dvb_frontend frontend;
@@ -204,9 +203,6 @@ static int ves1820_init(struct dvb_frontend* fe)
 
        ves1820_writereg(state, 0x34, state->pwm);
 
-       if (state->config->pll_init)
-               state->config->pll_init(fe);
-
        return 0;
 }
 
@@ -223,7 +219,11 @@ static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_p
        if (real_qam < 0 || real_qam > 4)
                return -EINVAL;
 
-       state->config->pll_set(fe, p);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
+
        ves1820_set_symbolrate(state, p->u.qam.symbol_rate);
        ves1820_writereg(state, 0x34, state->pwm);
 
@@ -380,7 +380,6 @@ struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
                goto error;
 
        /* setup the state */
-       memcpy(&state->ops, &ves1820_ops, sizeof(struct dvb_frontend_ops));
        state->reg0 = ves1820_inittab[0];
        state->config = config;
        state->i2c = i2c;
@@ -393,12 +392,12 @@ struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
        if (verbose)
                printk("ves1820: pwm=0x%02x\n", state->pwm);
 
-       state->ops.info.symbol_rate_min = (state->config->xin / 2) / 64;      /* SACLK/64 == (XIN/2)/64 */
-       state->ops.info.symbol_rate_max = (state->config->xin / 2) / 4;       /* SACLK/4 */
-
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &ves1820_ops, sizeof(struct dvb_frontend_ops));
+       state->frontend.ops.info.symbol_rate_min = (state->config->xin / 2) / 64;      /* SACLK/64 == (XIN/2)/64 */
+       state->frontend.ops.info.symbol_rate_max = (state->config->xin / 2) / 4;       /* SACLK/4 */
        state->frontend.demodulator_priv = state;
+
        return &state->frontend;
 
 error:
index 355f130b1be8e13f35454c81c7c7ad459253b998..520f09522fbbd0bc7604738ea61c366801aef75c 100644 (file)
@@ -39,10 +39,6 @@ struct ves1820_config
 
        /* SELAGC control */
        u8 selagc:1;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
index 821df8e839d056669d594ac1bcf47adb7d65e9b1..54d7b07571b8e3ac23482a5ad2acd9eb9704dd45 100644 (file)
@@ -36,7 +36,6 @@
 
 struct ves1x93_state {
        struct i2c_adapter* i2c;
-       struct dvb_frontend_ops ops;
        /* configuration settings */
        const struct ves1x93_config* config;
        struct dvb_frontend frontend;
@@ -278,12 +277,6 @@ static int ves1x93_init (struct dvb_frontend* fe)
                }
        }
 
-       if (state->config->pll_init) {
-               ves1x93_writereg(state, 0x00, 0x11);
-               state->config->pll_init(fe);
-               ves1x93_writereg(state, 0x00, 0x01);
-       }
-
        return 0;
 }
 
@@ -395,9 +388,10 @@ static int ves1x93_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
 {
        struct ves1x93_state* state = fe->demodulator_priv;
 
-       ves1x93_writereg(state, 0x00, 0x11);
-       state->config->pll_set(fe, p);
-       ves1x93_writereg(state, 0x00, 0x01);
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, p);
+               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+       }
        ves1x93_set_inversion (state, p->inversion);
        ves1x93_set_fec (state, p->u.qpsk.fec_inner);
        ves1x93_set_symbolrate (state, p->u.qpsk.symbol_rate);
@@ -442,6 +436,17 @@ static void ves1x93_release(struct dvb_frontend* fe)
        kfree(state);
 }
 
+static int ves1x93_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct ves1x93_state* state = fe->demodulator_priv;
+
+       if (enable) {
+               return ves1x93_writereg(state, 0x00, 0x11);
+       } else {
+               return ves1x93_writereg(state, 0x00, 0x01);
+       }
+}
+
 static struct dvb_frontend_ops ves1x93_ops;
 
 struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
@@ -457,7 +462,6 @@ struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops));
        state->inversion = INVERSION_OFF;
 
        /* check if the demod is there + identify it */
@@ -492,7 +496,7 @@ struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
        }
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -523,6 +527,7 @@ static struct dvb_frontend_ops ves1x93_ops = {
 
        .init = ves1x93_init,
        .sleep = ves1x93_sleep,
+       .i2c_gate_ctrl = ves1x93_i2c_gate_ctrl,
 
        .set_frontend = ves1x93_set_frontend,
        .get_frontend = ves1x93_get_frontend,
index 1627e37c57a4681c20da0d42e6eafafc4439cb98..ba88ae0855c994025b4a13c5e07ae65ab919bca7 100644 (file)
@@ -38,10 +38,6 @@ struct ves1x93_config
 
        /* should PWM be inverted? */
        u8 invert_pwm:1;
-
-       /* PLL maintenance */
-       int (*pll_init)(struct dvb_frontend* fe);
-       int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
index d7d9f59d76d2be53de299ad63f6e2d85caa43520..2b95e8b6cd3973dd8613f3edbe47e97c5b4871f4 100644 (file)
@@ -34,7 +34,6 @@
 struct zl10353_state {
        struct i2c_adapter *i2c;
        struct dvb_frontend frontend;
-       struct dvb_frontend_ops ops;
 
        struct zl10353_config config;
 };
@@ -126,6 +125,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
                                  struct dvb_frontend_parameters *param)
 {
        struct zl10353_state *state = fe->demodulator_priv;
+
        u8 pllbuf[6] = { 0x67 };
 
        /* These settings set "auto-everything" and start the FSM. */
@@ -142,7 +142,30 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
        zl10353_single_write(fe, 0x66, 0xE9);
        zl10353_single_write(fe, 0x62, 0x0A);
 
-       state->config.pll_set(fe, param, pllbuf + 1);
+       // if there is no attached secondary tuner, we call set_params to program
+       // a potential tuner attached somewhere else
+       if (state->config.no_tuner) {
+               if (fe->ops.tuner_ops.set_params) {
+                       fe->ops.tuner_ops.set_params(fe, param);
+                       if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+               }
+       }
+
+       // if pllbuf is defined, retrieve the settings
+       if (fe->ops.tuner_ops.calc_regs) {
+               fe->ops.tuner_ops.calc_regs(fe, param, pllbuf+1, 5);
+               pllbuf[1] <<= 1;
+       } else {
+               // fake pllbuf settings
+               pllbuf[1] = 0x61 << 1;
+               pllbuf[2] = 0;
+               pllbuf[3] = 0;
+               pllbuf[3] = 0;
+               pllbuf[4] = 0;
+       }
+
+       // there is no call to _just_ start decoding, so we send the pllbuf anyway
+       // even if there isn't a PLL attached to the secondary bus
        zl10353_write(fe, pllbuf, sizeof(pllbuf));
 
        zl10353_single_write(fe, 0x70, 0x01);
@@ -254,14 +277,13 @@ struct dvb_frontend *zl10353_attach(const struct zl10353_config *config,
        /* setup the state */
        state->i2c = i2c;
        memcpy(&state->config, config, sizeof(struct zl10353_config));
-       memcpy(&state->ops, &zl10353_ops, sizeof(struct dvb_frontend_ops));
 
        /* check if the demod is there */
        if (zl10353_read_register(state, CHIP_ID) != ID_ZL10353)
                goto error;
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &zl10353_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
 
        return &state->frontend;
index 5cc4ae718d8c2a68e98b5b6dc9b545115ddfb479..9770cb840cfccbfc4ae96657201a69fbcb112455 100644 (file)
@@ -29,10 +29,8 @@ struct zl10353_config
        /* demodulator's I2C address */
        u8 demod_address;
 
-       /* function which configures the PLL buffer (for secondary I2C
-        * connected tuner) or tunes the PLL (for direct connected tuner) */
-       int (*pll_set)(struct dvb_frontend *fe,
-                      struct dvb_frontend_parameters *params, u8 *pllbuf);
+       /* set if no pll is connected to the secondary i2c bus */
+       int no_tuner;
 };
 
 extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
index 1c5316e209efc9993ccc4d4def81e3032e6142e6..acabea0793b6d08ab7845bad4d9d08fec2212298 100644 (file)
@@ -424,8 +424,8 @@ static inline u32 divide(u32 numerator, u32 denominator)
 }
 
 /* LG Innotek TDTE-E001P (Infineon TUA6034) */
-static int lg_tdtpe001p_pll_set(struct dvb_frontend *fe,
-                               struct dvb_frontend_parameters *p)
+static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe,
+                                        struct dvb_frontend_parameters *p)
 {
        struct pluto *pluto = frontend_to_pluto(fe);
        struct i2c_msg msg;
@@ -473,6 +473,8 @@ static int lg_tdtpe001p_pll_set(struct dvb_frontend *fe,
        msg.buf = buf;
        msg.len = sizeof(buf);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        ret = i2c_transfer(&pluto->i2c_adap, &msg, 1);
        if (ret < 0)
                return ret;
@@ -497,8 +499,6 @@ static struct tda1004x_config pluto2_fe_config __devinitdata = {
        .xtal_freq = TDA10046_XTAL_16M,
        .agc_config = TDA10046_AGC_DEFAULT,
        .if_freq = TDA10046_FREQ_3617,
-       .pll_set = lg_tdtpe001p_pll_set,
-       .pll_sleep = NULL,
        .request_firmware = pluto2_request_firmware,
 };
 
@@ -511,11 +511,12 @@ static int __devinit frontend_init(struct pluto *pluto)
                dev_err(&pluto->pdev->dev, "could not attach frontend\n");
                return -ENODEV;
        }
+       pluto->fe->ops.tuner_ops.set_params = lg_tdtpe001p_tuner_set_params;
 
        ret = dvb_register_frontend(&pluto->dvb_adapter, pluto->fe);
        if (ret < 0) {
-               if (pluto->fe->ops->release)
-                       pluto->fe->ops->release(pluto->fe);
+               if (pluto->fe->ops.release)
+                       pluto->fe->ops.release(pluto->fe);
                return ret;
        }
 
@@ -647,7 +648,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev,
                goto err_pluto_hw_exit;
 
        /* dvb */
-       ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE);
+       ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
        if (ret < 0)
                goto err_i2c_bit_del_bus;
 
index b5ac7dfde52f745aef95da9cc167d9b5562fee22..987881fa988ccaba688bd6b08c6ac89e4222e8fc 100644 (file)
@@ -10,6 +10,7 @@ config DVB_AV7110
        select DVB_SP8870
        select DVB_STV0297
        select DVB_L64781
+       select DVB_LNBP21
        help
          Support for SAA7146 and AV7110 based DVB cards as produced
          by Fujitsu-Siemens, Technotrend, Hauppauge and others.
@@ -67,6 +68,7 @@ config DVB_BUDGET
        select DVB_TDA8083
        select DVB_TDA10021
        select DVB_S5H1420
+       select DVB_LNBP21
        help
          Support for simple SAA7146 based DVB cards
          (so called Budget- or Nova-PCI cards) without onboard
@@ -84,6 +86,7 @@ config DVB_BUDGET_CI
        select DVB_STV0297
        select DVB_STV0299
        select DVB_TDA1004X
+       select DVB_LNBP21
        help
          Support for simple SAA7146 based DVB cards
          (so called Budget- or Nova-PCI cards) without onboard
index a690730ac39d831054956e4a953ce560e18b7486..aa85ecdc6c8079965f8bd8db54288c064a2c2df5 100644 (file)
@@ -15,9 +15,9 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 
 hostprogs-y    := fdump
 
-ifdef CONFIG_DVB_AV7110_FIRMWARE
-$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
+ifeq ($(CONFIG_DVB_AV7110_FIRMWARE),y)
+$(obj)/av7110.o: $(obj)/av7110_firm.h
 
-$(obj)/av7110_firm.h:
+$(obj)/av7110_firm.h: $(obj)/fdump
        $(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@
 endif
index d028245c8eede256eee4fdd6de60610ea266816f..8832f80c05f7a92b7a5a5af8cf4d5fc8af4006ee 100644 (file)
@@ -1552,7 +1552,7 @@ static int get_firmware(struct av7110* av7110)
 #endif
 
 
-static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
        u8 pwr = 0;
@@ -1575,6 +1575,8 @@ static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        // NOTE: since we're using a prescaler of 2, we set the
        // divisor frequency to 62.5kHz and divide by 125 above
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -1584,10 +1586,9 @@ static struct ves1x93_config alps_bsrv2_config = {
        .demod_address = 0x08,
        .xin = 90100000UL,
        .invert_pwm = 0,
-       .pll_set = alps_bsrv2_pll_set,
 };
 
-static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
@@ -1601,6 +1602,8 @@ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        data[2] = 0x85 | ((div >> 10) & 0x60);
        data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -1611,14 +1614,12 @@ static struct ves1820_config alps_tdbe2_config = {
        .xin = 57840000UL,
        .invert = 1,
        .selagc = VES1820_SELAGC_SIGNAMPERR,
-       .pll_set = alps_tdbe2_pll_set,
 };
 
 
 
 
-static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
-                                    struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
@@ -1631,6 +1632,8 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
        data[2] = 0x8e;
        data[3] = 0x00;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -1638,13 +1641,11 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
 
 static struct tda8083_config grundig_29504_451_config = {
        .demod_address = 0x68,
-       .pll_set = grundig_29504_451_pll_set,
 };
 
 
 
-static int philips_cd1516_pll_set(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters* params)
+static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
@@ -1659,6 +1660,8 @@ static int philips_cd1516_pll_set(struct dvb_frontend* fe,
        data[2] = 0x8e;
        data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -1669,12 +1672,11 @@ static struct ves1820_config philips_cd1516_config = {
        .xin = 57840000UL,
        .invert = 1,
        .selagc = VES1820_SELAGC_SIGNAMPERR,
-       .pll_set = philips_cd1516_pll_set,
 };
 
 
 
-static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = fe->dvb->priv;
        u32 div, pwr;
@@ -1693,6 +1695,8 @@ static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        data[2] = 0x85;
        data[3] = pwr << 6;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -1708,7 +1712,6 @@ static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct fir
 static struct sp8870_config alps_tdlb7_config = {
 
        .demod_address = 0x71,
-       .pll_set = alps_tdlb7_pll_set,
        .request_firmware = alps_tdlb7_request_firmware,
 };
 
@@ -1806,7 +1809,7 @@ static u8 nexusca_stv0297_inittab[] = {
        0xff, 0xff,
 };
 
-static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = fe->dvb->priv;
        u32 div;
@@ -1832,7 +1835,8 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
        else
                return -EINVAL;
 
-       stv0297_enable_plli2c(fe);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
                printk("nexusca: pll transfer failed!\n");
                return -EIO;
@@ -1840,8 +1844,8 @@ static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
 
        // wait for PLL lock
        for(i = 0; i < 20; i++) {
-
-               stv0297_enable_plli2c(fe);
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
                if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
                        if (data[0] & 0x40) break;
                msleep(10);
@@ -1855,12 +1859,12 @@ static struct stv0297_config nexusca_stv0297_config = {
        .demod_address = 0x1C,
        .inittab = nexusca_stv0297_inittab,
        .invert = 1,
-       .pll_set = nexusca_stv0297_pll_set,
+       .stop_during_read = 1,
 };
 
 
 
-static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
        struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
        u32 div;
@@ -1887,13 +1891,14 @@ static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_fronten
        data[2] = ((div >> 10) & 0x60) | cfg;
        data[3] = (cpump << 6) | band_select;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
        return 0;
 }
 
 static struct l64781_config grundig_29504_401_config = {
        .demod_address = 0x55,
-       .pll_set = grundig_29504_401_pll_set,
 };
 
 
@@ -2079,6 +2084,9 @@ static int frontend_init(struct av7110 *av7110)
                case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
                        av7110->fe = ves1820_attach(&philips_cd1516_config,
                                                    &av7110->i2c_adap, read_pwm(av7110));
+                       if (av7110->fe) {
+                               av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
+                       }
                        break;
                }
 
@@ -2091,9 +2099,10 @@ static int frontend_init(struct av7110 *av7110)
                        // try the ALPS BSRV2 first of all
                        av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-                               av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-                               av7110->fe->ops->set_tone = av7110_set_tone;
+                               av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+                               av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+                               av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+                               av7110->fe->ops.set_tone = av7110_set_tone;
                                av7110->recover = dvb_s_recover;
                                break;
                        }
@@ -2101,9 +2110,12 @@ static int frontend_init(struct av7110 *av7110)
                        // try the ALPS BSRU6 now
                        av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-                               av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-                               av7110->fe->ops->set_tone = av7110_set_tone;
+                               av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+                               av7110->fe->tuner_priv = &av7110->i2c_adap;
+
+                               av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+                               av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+                               av7110->fe->ops.set_tone = av7110_set_tone;
                                av7110->recover = dvb_s_recover;
                                break;
                        }
@@ -2111,9 +2123,10 @@ static int frontend_init(struct av7110 *av7110)
                        // Try the grundig 29504-451
                        av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-                               av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-                               av7110->fe->ops->set_tone = av7110_set_tone;
+                               av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+                               av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+                               av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+                               av7110->fe->ops.set_tone = av7110_set_tone;
                                av7110->recover = dvb_s_recover;
                                break;
                        }
@@ -2124,11 +2137,17 @@ static int frontend_init(struct av7110 *av7110)
                                /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
                                av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap,
                                                        read_pwm(av7110));
+                               if (av7110->fe) {
+                                       av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
+                               }
                                break;
                        case 0x0003:
                                /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
                                av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
                                                        read_pwm(av7110));
+                               if (av7110->fe) {
+                                       av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+                               }
                                break;
                        }
                        break;
@@ -2137,20 +2156,27 @@ static int frontend_init(struct av7110 *av7110)
 
                        // ALPS TDLB7
                        av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
+                       if (av7110->fe) {
+                               av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
+                       }
                        break;
 
                case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
 
                        av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
+                       if (av7110->fe) {
+                               av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+                       }
                        break;
 
                case 0x0004: // Galaxis DVB-S rev1.3
                        /* ALPS BSRV2 */
                        av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-                               av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-                               av7110->fe->ops->set_tone = av7110_set_tone;
+                               av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+                               av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+                               av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+                               av7110->fe->ops.set_tone = av7110_set_tone;
                                av7110->recover = dvb_s_recover;
                        }
                        break;
@@ -2159,9 +2185,10 @@ static int frontend_init(struct av7110 *av7110)
                        /* Grundig 29504-451 */
                        av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-                               av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-                               av7110->fe->ops->set_tone = av7110_set_tone;
+                               av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+                               av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+                               av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+                               av7110->fe->ops.set_tone = av7110_set_tone;
                                av7110->recover = dvb_s_recover;
                        }
                        break;
@@ -2169,12 +2196,17 @@ static int frontend_init(struct av7110 *av7110)
                case 0x0008: // Hauppauge/TT DVB-T
 
                        av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);
+                       if (av7110->fe) {
+                               av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+                       }
                        break;
 
                case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
 
                        av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
                        if (av7110->fe) {
+                               av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
+
                                /* set TDA9819 into DVB mode */
                                saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
                                saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
@@ -2189,13 +2221,16 @@ static int frontend_init(struct av7110 *av7110)
                        /* ALPS BSBE1 */
                        av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
                        if (av7110->fe) {
-                               if (lnbp21_init(av7110->fe, &av7110->i2c_adap, 0, 0)) {
+                               av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+                               av7110->fe->tuner_priv = &av7110->i2c_adap;
+
+                               if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) {
                                        printk("dvb-ttpci: LNBP21 not found!\n");
-                                       if (av7110->fe->ops->release)
-                                               av7110->fe->ops->release(av7110->fe);
+                                       if (av7110->fe->ops.release)
+                                               av7110->fe->ops.release(av7110->fe);
                                        av7110->fe = NULL;
                                } else {
-                                       av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
+                                       av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
                                        av7110->recover = dvb_s_recover;
                                }
                        }
@@ -2212,21 +2247,21 @@ static int frontend_init(struct av7110 *av7110)
                       av7110->dev->pci->subsystem_vendor,
                       av7110->dev->pci->subsystem_device);
        } else {
-               FE_FUNC_OVERRIDE(av7110->fe->ops->init, av7110->fe_init, av7110_fe_init);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->read_status, av7110->fe_read_status, av7110_fe_read_status);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
-               FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
-               FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
+               FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
+               FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
 
                ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
                if (ret < 0) {
                        printk("av7110: Frontend registration failed!\n");
-                       if (av7110->fe->ops->release)
-                               av7110->fe->ops->release(av7110->fe);
+                       if (av7110->fe->ops.release)
+                               av7110->fe->ops.release(av7110->fe);
                        av7110->fe = NULL;
                }
        }
@@ -2413,7 +2448,7 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
                goto err_kfree_0;
 
        ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
-                                  THIS_MODULE);
+                                  THIS_MODULE, &dev->pci->dev);
        if (ret < 0)
                goto err_put_firmware_1;
 
index 8a7cd7d505cf533997dc76f2613f5e98a1d0c0d8..6163cb03b8f418e9859263be98d668881ad97482 100644 (file)
 
 #define DEBICICAM              0x02420000
 
+#define SLOTSTATUS_NONE         1
+#define SLOTSTATUS_PRESENT      2
+#define SLOTSTATUS_RESET        4
+#define SLOTSTATUS_READY        8
+#define SLOTSTATUS_OCCUPIED     (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
+
 struct budget_av {
        struct budget budget;
        struct video_device *vd;
@@ -58,8 +64,15 @@ struct budget_av {
        struct tasklet_struct ciintf_irq_tasklet;
        int slot_status;
        struct dvb_ca_en50221 ca;
+       u8 reinitialise_demod:1;
+       u8 tda10021_poclkp:1;
+       u8 tda10021_ts_enabled;
+       int (*tda10021_set_frontend)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
 };
 
+static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);
+
+
 /* GPIO Connections:
  * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
  * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
@@ -129,9 +142,10 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
        udelay(1);
 
        result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
-
-       if (result == -ETIMEDOUT)
-               budget_av->slot_status = 0;
+       if (result == -ETIMEDOUT) {
+               ciintf_slot_shutdown(ca, slot);
+               printk(KERN_INFO "budget-av: cam ejected 1\n");
+       }
        return result;
 }
 
@@ -147,9 +161,10 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
        udelay(1);
 
        result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
-
-       if (result == -ETIMEDOUT)
-               budget_av->slot_status = 0;
+       if (result == -ETIMEDOUT) {
+               ciintf_slot_shutdown(ca, slot);
+               printk(KERN_INFO "budget-av: cam ejected 2\n");
+       }
        return result;
 }
 
@@ -165,9 +180,11 @@ static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addre
        udelay(1);
 
        result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
-
-       if (result == -ETIMEDOUT)
-               budget_av->slot_status = 0;
+       if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
+               ciintf_slot_shutdown(ca, slot);
+               printk(KERN_INFO "budget-av: cam ejected 3\n");
+               return -ETIMEDOUT;
+       }
        return result;
 }
 
@@ -183,9 +200,10 @@ static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 addr
        udelay(1);
 
        result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
-
-       if (result == -ETIMEDOUT)
-               budget_av->slot_status = 0;
+       if (result == -ETIMEDOUT) {
+               ciintf_slot_shutdown(ca, slot);
+               printk(KERN_INFO "budget-av: cam ejected 5\n");
+       }
        return result;
 }
 
@@ -193,12 +211,12 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
 {
        struct budget_av *budget_av = (struct budget_av *) ca->data;
        struct saa7146_dev *saa = budget_av->budget.dev;
-       int timeout = 50; // 5 seconds (4.4.6 Ready)
 
        if (slot != 0)
                return -EINVAL;
 
        dprintk(1, "ciintf_slot_reset\n");
+       budget_av->slot_status = SLOTSTATUS_RESET;
 
        saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
 
@@ -208,20 +226,17 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
        msleep(20); /* 20 ms Vcc settling time */
 
        saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
+       ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+       msleep(20);
 
-       /* This should have been based on pin 16 READY of the pcmcia port,
-        * but AFAICS it is not routed to the saa7146 */
-       while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
-               msleep(100);
-
-       /* reinitialise the frontend */
-       dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
+       /* reinitialise the frontend if necessary */
+       if (budget_av->reinitialise_demod)
+               dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
 
-       if (timeout <= 0)
-       {
-               printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
-               saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
-               return -ETIMEDOUT;
+       /* set tda10021 back to original clock configuration on reset */
+       if (budget_av->tda10021_poclkp) {
+               tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+               budget_av->tda10021_ts_enabled = 0;
        }
 
        return 0;
@@ -238,7 +253,13 @@ static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
        dprintk(1, "ciintf_slot_shutdown\n");
 
        ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
-       budget_av->slot_status = 0;
+       budget_av->slot_status = SLOTSTATUS_NONE;
+
+       /* set tda10021 back to original clock configuration when cam removed */
+       if (budget_av->tda10021_poclkp) {
+               tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+               budget_av->tda10021_ts_enabled = 0;
+       }
        return 0;
 }
 
@@ -253,6 +274,13 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
        dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
 
        ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
+
+       /* tda10021 seems to need a different TS clock config when data is routed to the CAM */
+       if (budget_av->tda10021_poclkp) {
+               tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
+               budget_av->tda10021_ts_enabled = 1;
+       }
+
        return 0;
 }
 
@@ -260,50 +288,61 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
 {
        struct budget_av *budget_av = (struct budget_av *) ca->data;
        struct saa7146_dev *saa = budget_av->budget.dev;
-       int cam_present = 0;
+       int result;
 
        if (slot != 0)
                return -EINVAL;
 
-       if (!budget_av->slot_status)
-       {
-               // first of all test the card detect line
+       /* test the card detect line - needs to be done carefully
+        * since it never goes high for some CAMs on this interface (e.g. topuptv) */
+       if (budget_av->slot_status == SLOTSTATUS_NONE) {
                saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
                udelay(1);
-               if (saa7146_read(saa, PSR) & MASK_06)
-               {
-                       cam_present = 1;
+               if (saa7146_read(saa, PSR) & MASK_06) {
+                       if (budget_av->slot_status == SLOTSTATUS_NONE) {
+                               budget_av->slot_status = SLOTSTATUS_PRESENT;
+                               printk(KERN_INFO "budget-av: cam inserted A\n");
+                       }
                }
                saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+       }
 
-               // that is unreliable however, so try and read from IO memory
-               if (!cam_present)
-               {
-                       saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
-                       if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT)
-                       {
-                               cam_present = 1;
+       /* We also try and read from IO memory to work round the above detection bug. If
+        * there is no CAM, we will get a timeout. Only done if there is no cam
+        * present, since this test actually breaks some cams :(
+        *
+        * if the CI interface is not open, we also do the above test since we
+        * don't care if the cam has problems - we'll be resetting it on open() anyway */
+       if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
+               saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+               result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
+               if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
+                       budget_av->slot_status = SLOTSTATUS_PRESENT;
+                       printk(KERN_INFO "budget-av: cam inserted B\n");
+               } else if (result < 0) {
+                       if (budget_av->slot_status != SLOTSTATUS_NONE) {
+                               ciintf_slot_shutdown(ca, slot);
+                               printk(KERN_INFO "budget-av: cam ejected 5\n");
+                               return 0;
                        }
                }
+       }
 
-               // did we find something?
-               if (cam_present) {
-                       printk(KERN_INFO "budget-av: cam inserted\n");
-                       budget_av->slot_status = 1;
-               }
-       } else if (!open) {
-               saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
-               if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
-               {
-                       printk(KERN_INFO "budget-av: cam ejected\n");
-                       saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
-                       budget_av->slot_status = 0;
+       /* read from attribute memory in reset/ready state to know when the CAM is ready */
+       if (budget_av->slot_status == SLOTSTATUS_RESET) {
+               result = ciintf_read_attribute_mem(ca, slot, 0);
+               if (result == 0x1d) {
+                       budget_av->slot_status = SLOTSTATUS_READY;
                }
        }
 
-       if (budget_av->slot_status == 1)
-               return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
-
+       /* work out correct return code */
+       if (budget_av->slot_status != SLOTSTATUS_NONE) {
+               if (budget_av->slot_status & SLOTSTATUS_READY) {
+                       return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
+               }
+               return DVB_CA_EN50221_POLL_CAM_PRESENT;
+       }
        return 0;
 }
 
@@ -333,6 +372,8 @@ static int ciintf_init(struct budget_av *budget_av)
        budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
        budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
        budget_av->ca.data = budget_av;
+       budget_av->budget.ci_present = 1;
+       budget_av->slot_status = SLOTSTATUS_NONE;
 
        if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
                                          &budget_av->ca, 0, 1)) != 0) {
@@ -341,7 +382,6 @@ static int ciintf_init(struct budget_av *budget_av)
        }
 
        printk(KERN_INFO "budget-av: ci interface initialised.\n");
-       budget_av->budget.ci_present = 1;
        return 0;
 
 error:
@@ -472,12 +512,12 @@ static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 sra
        return 0;
 }
 
-static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
-                                       struct i2c_adapter *i2c,
-                                       struct dvb_frontend_parameters *params)
+static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe,
+                                                struct dvb_frontend_parameters *params)
 {
        u32 div;
        u8 buf[4];
+       struct budget *budget = (struct budget *) fe->dvb->priv;
        struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
 
        if ((params->frequency < 950000) || (params->frequency > 2150000))
@@ -501,7 +541,9 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
        else if (params->frequency < 2150000)
                buf[3] |= 0xC0;
 
-       if (i2c_transfer(i2c, &msg, 1) != 1)
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
 }
@@ -509,9 +551,8 @@ static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
 #define MIN2(a,b) ((a) < (b) ? (a) : (b))
 #define MIN3(a,b,c) MIN2(MIN2(a,b),c)
 
-static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe,
-                                       struct i2c_adapter *i2c,
-                                       struct dvb_frontend_parameters *params)
+static int philips_su1278sh2_tua6100_tuner_set_params(struct dvb_frontend *fe,
+                                                     struct dvb_frontend_parameters *params)
 {
        u8 reg0 [2] = { 0x00, 0x00 };
        u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 };
@@ -521,6 +562,7 @@ static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe,
        int R, A, N, P, M;
        struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 };
        int freq = params->frequency;
+       struct budget *budget = (struct budget *) fe->dvb->priv;
 
        first_ZF = (freq) / 1000;
 
@@ -620,21 +662,25 @@ static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe,
        reg0[1] |= 0x03;
 
        /* already enabled - do not reenable i2c repeater or TX fails */
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        msg.buf = reg0;
        msg.len = sizeof(reg0);
-       if (i2c_transfer(i2c, &msg, 1) != 1)
+       if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
                return -EIO;
 
-       stv0299_enable_plli2c(fe);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        msg.buf = reg1;
        msg.len = sizeof(reg1);
-       if (i2c_transfer(i2c, &msg, 1) != 1)
+       if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
                return -EIO;
 
-       stv0299_enable_plli2c(fe);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        msg.buf = reg2;
        msg.len = sizeof(reg2);
-       if (i2c_transfer(i2c, &msg, 1) != 1)
+       if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
                return -EIO;
 
        return 0;
@@ -692,7 +738,6 @@ static struct stv0299_config typhoon_config = {
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-       .pll_set = philips_su1278_ty_ci_pll_set,
 };
 
 
@@ -706,7 +751,6 @@ static struct stv0299_config cinergy_1200s_config = {
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-       .pll_set = philips_su1278_ty_ci_pll_set,
 };
 
 static struct stv0299_config cinergy_1200s_1894_0010_config = {
@@ -719,10 +763,9 @@ static struct stv0299_config cinergy_1200s_1894_0010_config = {
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-       .pll_set = philips_su1278sh2_tua6100_pll_set,
 };
 
-static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct budget *budget = (struct budget *) fe->dvb->priv;
        u8 buf[4];
@@ -738,6 +781,8 @@ static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
        buf[3] = (params->frequency < 150000000 ? 0x01 :
                  params->frequency < 445000000 ? 0x02 : 0x04);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
@@ -745,19 +790,20 @@ static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
 
 static struct tda10021_config philips_cu1216_config = {
        .demod_address = 0x0c,
-       .pll_set = philips_cu1216_pll_set,
 };
 
 
 
 
-static int philips_tu1216_pll_init(struct dvb_frontend *fe)
+static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
 {
        struct budget *budget = (struct budget *) fe->dvb->priv;
        static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
        struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
 
        // setup PLL configuration
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
        msleep(1);
@@ -765,7 +811,7 @@ static int philips_tu1216_pll_init(struct dvb_frontend *fe)
        return 0;
 }
 
-static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct budget *budget = (struct budget *) fe->dvb->priv;
        u8 tuner_buf[4];
@@ -839,6 +885,8 @@ static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_p
        tuner_buf[2] = 0xca;
        tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
 
@@ -862,9 +910,6 @@ static struct tda1004x_config philips_tu1216_config = {
        .xtal_freq = TDA10046_XTAL_4M,
        .agc_config = TDA10046_AGC_DEFAULT,
        .if_freq = TDA10046_FREQ_3617,
-       .pll_init = philips_tu1216_pll_init,
-       .pll_set = philips_tu1216_pll_set,
-       .pll_sleep = NULL,
        .request_firmware = philips_tu1216_request_firmware,
 };
 
@@ -911,13 +956,13 @@ static u8 philips_sd1878_inittab[] = {
        0xff, 0xff
 };
 
-static int philips_sd1878_tda8261_pll_set(struct dvb_frontend *fe,
-               struct i2c_adapter *i2c,
-               struct dvb_frontend_parameters *params)
+static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe,
+                                                  struct dvb_frontend_parameters *params)
 {
        u8              buf[4];
        int             rc;
        struct i2c_msg  tuner_msg = {.addr=0x60,.flags=0,.buf=buf,.len=sizeof(buf)};
+       struct budget *budget = (struct budget *) fe->dvb->priv;
 
        if((params->frequency < 950000) || (params->frequency > 2150000))
                return -EINVAL;
@@ -926,7 +971,9 @@ static int philips_sd1878_tda8261_pll_set(struct dvb_frontend *fe,
                        params->frequency, 0);
        if(rc < 0) return rc;
 
-       if(i2c_transfer(i2c, &tuner_msg, 1) != 1)
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if(i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
 
     return 0;
@@ -969,7 +1016,7 @@ static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
 
 static struct stv0299_config philips_sd1878_config = {
        .demod_address = 0x68,
-       .inittab = philips_sd1878_inittab,
+     .inittab = philips_sd1878_inittab,
        .mclk = 88000000UL,
        .invert = 0,
        .skip_reinit = 0,
@@ -977,7 +1024,6 @@ static struct stv0299_config philips_sd1878_config = {
        .volt13_op0_op1 = STV0299_VOLT13_OP0,
        .min_delay_ms = 100,
        .set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
-       .pll_set = philips_sd1878_tda8261_pll_set,
 };
 
 static u8 read_pwm(struct budget_av *budget_av)
@@ -1003,6 +1049,7 @@ static u8 read_pwm(struct budget_av *budget_av)
 
 #define SUBID_DVBS_TV_STAR     0x0014
 #define SUBID_DVBS_TV_STAR_CI  0x0016
+#define SUBID_DVBS_EASYWATCH_1  0x001a
 #define SUBID_DVBS_EASYWATCH   0x001e
 #define SUBID_DVBC_KNC1                0x0020
 #define SUBID_DVBC_KNC1_PLUS   0x0021
@@ -1012,17 +1059,36 @@ static u8 read_pwm(struct budget_av *budget_av)
 #define SUBID_DVBT_KNC1                0x0030
 #define SUBID_DVBT_CINERGY1200 0x1157
 
+
+static int tda10021_set_frontend(struct dvb_frontend *fe,
+                                struct dvb_frontend_parameters *p)
+{
+       struct budget_av* budget_av = fe->dvb->priv;
+       int result;
+
+       result = budget_av->tda10021_set_frontend(fe, p);
+       if (budget_av->tda10021_ts_enabled) {
+               tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
+       } else {
+               tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+       }
+
+       return result;
+}
+
 static void frontend_init(struct budget_av *budget_av)
 {
        struct saa7146_dev * saa = budget_av->budget.dev;
        struct dvb_frontend * fe = NULL;
 
+       /* Enable / PowerON Frontend */
+       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+
+       /* additional setup necessary for the PLUS cards */
        switch (saa->pci->subsystem_device) {
                case SUBID_DVBS_KNC1_PLUS:
                case SUBID_DVBC_KNC1_PLUS:
                case SUBID_DVBT_KNC1_PLUS:
-                       // Enable / PowerON Frontend
-                       saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
                        saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
                        break;
        }
@@ -1030,12 +1096,19 @@ static void frontend_init(struct budget_av *budget_av)
        switch (saa->pci->subsystem_device) {
 
        case SUBID_DVBS_KNC1:
+       case SUBID_DVBS_EASYWATCH_1:
                if (saa->pci->subsystem_vendor == 0x1894) {
                        fe = stv0299_attach(&cinergy_1200s_1894_0010_config,
                                             &budget_av->budget.i2c_adap);
+                       if (fe) {
+                               fe->ops.tuner_ops.set_params = philips_su1278sh2_tua6100_tuner_set_params;
+                       }
                } else {
                        fe = stv0299_attach(&typhoon_config,
                                             &budget_av->budget.i2c_adap);
+                       if (fe) {
+                               fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+                       }
                }
                break;
 
@@ -1045,41 +1118,53 @@ static void frontend_init(struct budget_av *budget_av)
        case SUBID_DVBS_EASYWATCH:
                fe = stv0299_attach(&philips_sd1878_config,
                                &budget_av->budget.i2c_adap);
+               if (fe) {
+                       fe->ops.tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params;
+               }
                break;
 
        case SUBID_DVBS_KNC1_PLUS:
        case SUBID_DVBS_TYPHOON:
                fe = stv0299_attach(&typhoon_config,
                                    &budget_av->budget.i2c_adap);
+               if (fe) {
+                       fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+               }
                break;
 
        case SUBID_DVBS_CINERGY1200:
                fe = stv0299_attach(&cinergy_1200s_config,
                                    &budget_av->budget.i2c_adap);
+               if (fe) {
+                       fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+               }
                break;
 
        case SUBID_DVBC_KNC1:
        case SUBID_DVBC_KNC1_PLUS:
+       case SUBID_DVBC_CINERGY1200:
+               budget_av->reinitialise_demod = 1;
                fe = tda10021_attach(&philips_cu1216_config,
                                     &budget_av->budget.i2c_adap,
                                     read_pwm(budget_av));
+               if (fe) {
+                       budget_av->tda10021_poclkp = 1;
+                       budget_av->tda10021_set_frontend = fe->ops.set_frontend;
+                       fe->ops.set_frontend = tda10021_set_frontend;
+                       fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
+               }
                break;
 
        case SUBID_DVBT_KNC1:
        case SUBID_DVBT_KNC1_PLUS:
-               fe = tda10046_attach(&philips_tu1216_config,
-                                    &budget_av->budget.i2c_adap);
-               break;
-
-       case SUBID_DVBC_CINERGY1200:
-               fe = tda10021_attach(&philips_cu1216_config,
-                                    &budget_av->budget.i2c_adap,
-                                    read_pwm(budget_av));
-               break;
-
        case SUBID_DVBT_CINERGY1200:
+               budget_av->reinitialise_demod = 1;
                fe = tda10046_attach(&philips_tu1216_config,
                                     &budget_av->budget.i2c_adap);
+               if (fe) {
+                       fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
+                       fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params;
+               }
                break;
        }
 
@@ -1098,8 +1183,8 @@ static void frontend_init(struct budget_av *budget_av)
        if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
                                  budget_av->budget.dvb_frontend)) {
                printk(KERN_ERR "budget-av: Frontend registration failed!\n");
-               if (budget_av->budget.dvb_frontend->ops->release)
-                       budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
+               if (budget_av->budget.dvb_frontend->ops.release)
+                       budget_av->budget.dvb_frontend->ops.release(budget_av->budget.dvb_frontend);
                budget_av->budget.dvb_frontend = NULL;
        }
 }
@@ -1293,6 +1378,7 @@ MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
 MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
 MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
 MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
+MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
 MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
 MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
 MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
@@ -1309,6 +1395,7 @@ static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
        MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
        MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
+       MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
        MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
        MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
        MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
index e64a609cf4ff4825ac119047b3dd7cfddc7d7cdb..4b966eea3834b52dc07668c7f99721ce907e2a2c 100644 (file)
@@ -620,10 +620,10 @@ static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
        return 0;
 }
 
-static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
-                                    struct i2c_adapter *i2c,
-                                    struct dvb_frontend_parameters *params)
+static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
+                                          struct dvb_frontend_parameters *params)
 {
+       struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        u32 div;
        u8 buf[4];
        struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -649,7 +649,9 @@ static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
        else if (params->frequency < 2150000)
                buf[3] |= 0xC0;
 
-       if (i2c_transfer(i2c, &msg, 1) != 1)
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
                return -EIO;
        return 0;
 }
@@ -665,12 +667,11 @@ static struct stv0299_config philips_su1278_tt_config = {
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 50,
        .set_symbol_rate = philips_su1278_tt_set_symbol_rate,
-       .pll_set = philips_su1278_tt_pll_set,
 };
 
 
 
-static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
+static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
 {
        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
@@ -679,6 +680,8 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
                        sizeof(td1316_init) };
 
        // setup PLL configuration
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
        msleep(1);
@@ -687,14 +690,18 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
        tuner_msg.addr = 0x65;
        tuner_msg.buf = disable_mc44BC374c;
        tuner_msg.len = sizeof(disable_mc44BC374c);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
                i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
        }
 
        return 0;
 }
 
-static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        u8 tuner_buf[4];
@@ -770,6 +777,8 @@ static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend
        tuner_buf[2] = 0xca;
        tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
 
@@ -793,13 +802,10 @@ static struct tda1004x_config philips_tdm1316l_config = {
        .xtal_freq = TDA10046_XTAL_4M,
        .agc_config = TDA10046_AGC_DEFAULT,
        .if_freq = TDA10046_FREQ_3617,
-       .pll_init = philips_tdm1316l_pll_init,
-       .pll_set = philips_tdm1316l_pll_set,
-       .pll_sleep = NULL,
        .request_firmware = philips_tdm1316l_request_firmware,
 };
 
-static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
        u8 tuner_buf[5];
@@ -857,13 +863,15 @@ static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_fro
        tuner_buf[3] = (cp << 5) | (filter << 3) | band;
        tuner_buf[4] = 0x80;
 
-       stv0297_enable_plli2c(fe);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
 
        msleep(50);
 
-       stv0297_enable_plli2c(fe);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
 
@@ -969,7 +977,7 @@ static struct stv0297_config dvbc_philips_tdm1316l_config = {
        .demod_address = 0x1c,
        .inittab = dvbc_philips_tdm1316l_inittab,
        .invert = 0,
-       .pll_set = dvbc_philips_tdm1316l_pll_set,
+       .stop_during_read = 1,
 };
 
 
@@ -982,6 +990,8 @@ static void frontend_init(struct budget_ci *budget_ci)
                budget_ci->budget.dvb_frontend =
                        stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
+                       budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+                       budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
                        break;
                }
                break;
@@ -990,6 +1000,7 @@ static void frontend_init(struct budget_ci *budget_ci)
                budget_ci->budget.dvb_frontend =
                        stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
+                       budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
                        break;
                }
                break;
@@ -999,6 +1010,7 @@ static void frontend_init(struct budget_ci *budget_ci)
                budget_ci->budget.dvb_frontend =
                        stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
+                       budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
                        break;
                }
                break;
@@ -1008,6 +1020,8 @@ static void frontend_init(struct budget_ci *budget_ci)
                budget_ci->budget.dvb_frontend =
                        tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
+                       budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+                       budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
                        break;
                }
                break;
@@ -1017,6 +1031,8 @@ static void frontend_init(struct budget_ci *budget_ci)
                budget_ci->budget.dvb_frontend =
                        tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
+                       budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+                       budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
                        break;
                }
                break;
@@ -1024,11 +1040,14 @@ static void frontend_init(struct budget_ci *budget_ci)
        case 0x1017:            // TT S-1500 PCI
                budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget_ci->budget.i2c_adap);
                if (budget_ci->budget.dvb_frontend) {
-                       budget_ci->budget.dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
-                       if (lnbp21_init(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) {
+                       budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+                       budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
+
+                       budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+                       if (lnbp21_attach(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) {
                                printk("%s: No LNBP21 found!\n", __FUNCTION__);
-                               if (budget_ci->budget.dvb_frontend->ops->release)
-                                       budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend);
+                               if (budget_ci->budget.dvb_frontend->ops.release)
+                                       budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend);
                                budget_ci->budget.dvb_frontend = NULL;
                        }
                }
@@ -1046,8 +1065,8 @@ static void frontend_init(struct budget_ci *budget_ci)
                if (dvb_register_frontend
                    (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
                        printk("budget-ci: Frontend registration failed!\n");
-                       if (budget_ci->budget.dvb_frontend->ops->release)
-                               budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend);
+                       if (budget_ci->budget.dvb_frontend->ops.release)
+                               budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend);
                        budget_ci->budget.dvb_frontend = NULL;
                }
        }
index ea2066d461fc95fcd9fe770d2e9c4fca34d72563..e4cf7775e07f75f21447fa2f051af771180aad63 100644 (file)
@@ -400,7 +400,9 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
                budget->dev->name, budget->buffer_width, budget->buffer_height);
        printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
 
-       dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner);
+       if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) {
+               return ret;
+       }
 
        /* set dd1 stream a & b */
        saa7146_write(dev, DD1_STREAM_B, 0x00000000);
index 1b3aaac5e7636fbdade5d426b52087bbdfaa95c7..ee60ce90a4005f562d62ed85f6b8a1b155e68a2f 100644 (file)
@@ -258,7 +258,7 @@ static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_c
        return 0;
 }
 
-static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
        u8 pwr = 0;
@@ -281,7 +281,10 @@ static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        // NOTE: since we're using a prescaler of 2, we set the
        // divisor frequency to 62.5kHz and divide by 125 above
 
-       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
+               return -EIO;
        return 0;
 }
 
@@ -289,10 +292,9 @@ static struct ves1x93_config alps_bsrv2_config = {
        .demod_address = 0x08,
        .xin = 90100000UL,
        .invert_pwm = 0,
-       .pll_set = alps_bsrv2_pll_set,
 };
 
-static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
        u32 div;
@@ -305,13 +307,15 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_fronten
        data[2] = 0x8e;
        data[3] = 0x00;
 
-       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
+               return -EIO;
        return 0;
 }
 
 static struct tda8083_config grundig_29504_451_config = {
        .demod_address = 0x68,
-       .pll_set = grundig_29504_451_pll_set,
 };
 
 static void frontend_init(struct budget_patch* budget)
@@ -323,27 +327,32 @@ static void frontend_init(struct budget_patch* budget)
                // try the ALPS BSRV2 first of all
                budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
-                       budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
-                       budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst;
-                       budget->dvb_frontend->ops->set_tone = budget_patch_set_tone;
+                       budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+                       budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
+                       budget->dvb_frontend->ops.diseqc_send_burst = budget_patch_diseqc_send_burst;
+                       budget->dvb_frontend->ops.set_tone = budget_patch_set_tone;
                        break;
                }
 
                // try the ALPS BSRU6 now
                budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
-                       budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-                       budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
-                       budget->dvb_frontend->ops->set_tone = budget_set_tone;
+                       budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+                       budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+
+                       budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+                       budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+                       budget->dvb_frontend->ops.set_tone = budget_set_tone;
                        break;
                }
 
                // Try the grundig 29504-451
                budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
-                       budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-                       budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
-                       budget->dvb_frontend->ops->set_tone = budget_set_tone;
+                       budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+                       budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+                       budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+                       budget->dvb_frontend->ops.set_tone = budget_set_tone;
                        break;
                }
                break;
@@ -358,8 +367,8 @@ static void frontend_init(struct budget_patch* budget)
        } else {
                if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
                        printk("budget-av: Frontend registration failed!\n");
-                       if (budget->dvb_frontend->ops->release)
-                               budget->dvb_frontend->ops->release(budget->dvb_frontend);
+                       if (budget->dvb_frontend->ops.release)
+                               budget->dvb_frontend->ops.release(budget->dvb_frontend);
                        budget->dvb_frontend = NULL;
                }
        }
index c23c02d95641867d8b6163c2fa99dca218bd0299..35761f13c12b051fac37d2d48ffda657e7d90e75 100644 (file)
@@ -186,7 +186,7 @@ static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t m
        return 0;
 }
 
-static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct budget* budget = (struct budget*) fe->dvb->priv;
        u8 pwr = 0;
@@ -209,6 +209,8 @@ static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        // NOTE: since we're using a prescaler of 2, we set the
        // divisor frequency to 62.5kHz and divide by 125 above
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
        return 0;
 }
@@ -218,10 +220,9 @@ static struct ves1x93_config alps_bsrv2_config =
        .demod_address = 0x08,
        .xin = 90100000UL,
        .invert_pwm = 0,
-       .pll_set = alps_bsrv2_pll_set,
 };
 
-static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct budget* budget = (struct budget*) fe->dvb->priv;
        u32 div;
@@ -235,6 +236,8 @@ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        data[2] = 0x85 | ((div >> 10) & 0x60);
        data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
        return 0;
 }
@@ -244,10 +247,9 @@ static struct ves1820_config alps_tdbe2_config = {
        .xin = 57840000UL,
        .invert = 1,
        .selagc = VES1820_SELAGC_SIGNAMPERR,
-       .pll_set = alps_tdbe2_pll_set,
 };
 
-static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct budget* budget = (struct budget*) fe->dvb->priv;
        u32 div;
@@ -274,16 +276,17 @@ static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_fronten
        data[2] = ((div >> 10) & 0x60) | cfg;
        data[3] = (cpump << 6) | band_select;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
        return 0;
 }
 
 static struct l64781_config grundig_29504_401_config = {
        .demod_address = 0x55,
-       .pll_set = grundig_29504_401_pll_set,
 };
 
-static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct budget* budget = (struct budget*) fe->dvb->priv;
        u32 div;
@@ -296,16 +299,17 @@ static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_fronten
        data[2] = 0x8e;
        data[3] = 0x00;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
        return 0;
 }
 
 static struct tda8083_config grundig_29504_451_config = {
        .demod_address = 0x68,
-       .pll_set = grundig_29504_451_pll_set,
 };
 
-static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout)
+static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct budget* budget = (struct budget*) fe->dvb->priv;
        u32 div;
@@ -326,16 +330,16 @@ static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
        else
                data[3] = 0xc0;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 
-       *freqout = div * 1000;
        return 0;
 }
 
 static struct s5h1420_config s5h1420_config = {
        .demod_address = 0x53,
        .invert = 1,
-       .pll_set = s5h1420_pll_set,
 };
 
 static u8 read_pwm(struct budget* budget)
@@ -359,18 +363,21 @@ static void frontend_init(struct budget *budget)
                // try the ALPS BSRV2 first of all
                budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
-                       budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-                       budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
-                       budget->dvb_frontend->ops->set_tone = budget_set_tone;
+                       budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+                       budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+                       budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+                       budget->dvb_frontend->ops.set_tone = budget_set_tone;
                        break;
                }
 
                // try the ALPS BSRU6 now
                budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
-                       budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-                       budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
-                       budget->dvb_frontend->ops->set_tone = budget_set_tone;
+                       budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+                       budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+                       budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+                       budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+                       budget->dvb_frontend->ops.set_tone = budget_set_tone;
                        break;
                }
                break;
@@ -378,35 +385,45 @@ static void frontend_init(struct budget *budget)
        case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
 
                budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
-               if (budget->dvb_frontend) break;
+               if (budget->dvb_frontend) {
+                       budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+                       break;
+               }
                break;
 
        case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
 
                budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
-               if (budget->dvb_frontend) break;
+               if (budget->dvb_frontend) {
+                       budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+                       break;
+               }
                break;
 
        case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
                budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
-                       budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
-                       budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
+                       budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+                       budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+                       budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+                       budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
                }
                break;
 
        case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
                budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
-                       budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
-                       budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
+                       budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+                       budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+                       budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
                }
                break;
 
        case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
                budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap);
                if (budget->dvb_frontend) {
-                       if (lnbp21_init(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) {
+                       budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
+                       if (lnbp21_attach(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) {
                                printk("%s: No LNBP21 found!\n", __FUNCTION__);
                                goto error_out;
                        }
@@ -428,8 +445,8 @@ static void frontend_init(struct budget *budget)
 
 error_out:
        printk("budget: Frontend registration failed!\n");
-       if (budget->dvb_frontend->ops->release)
-               budget->dvb_frontend->ops->release(budget->dvb_frontend);
+       if (budget->dvb_frontend->ops.release)
+               budget->dvb_frontend->ops.release(budget->dvb_frontend);
        budget->dvb_frontend = NULL;
        return;
 }
index 914587d52b57622131592134d7feef0e9d651c6b..92c7cdcf89815750113d68f866aa220aded41b3c 100644 (file)
@@ -6,6 +6,8 @@ config DVB_TTUSB_BUDGET
        select DVB_VES1820
        select DVB_TDA8083
        select DVB_STV0299
+       select DVB_STV0297
+       select DVB_LNBP21
        help
          Support for external USB adapters designed by Technotrend and
          produced by Hauppauge, shipped under the brand name 'Nova-USB'.
index 6ceae38125c7546990623d62028e35c56750f4a1..14559ef6153c4ead4a0468e1411a35ef70c5e5ca 100644 (file)
@@ -30,6 +30,8 @@
 #include "tda1004x.h"
 #include "stv0299.h"
 #include "tda8083.h"
+#include "stv0297.h"
+#include "lnbp21.h"
 
 #include <linux/dvb/frontend.h>
 #include <linux/dvb/dmx.h>
@@ -486,31 +488,6 @@ static int ttusb_send_diseqc(struct dvb_frontend* fe,
 }
 #endif
 
-static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-       struct  ttusb* ttusb = (struct ttusb*)  fe->dvb->priv;
-       int ret;
-       u8 data[1];
-       struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = sizeof(data) };
-
-       switch(voltage) {
-       case SEC_VOLTAGE_OFF:
-               data[0] = 0x00;
-               break;
-       case SEC_VOLTAGE_13:
-               data[0] = 0x44;
-               break;
-       case SEC_VOLTAGE_18:
-               data[0] = 0x4c;
-               break;
-       default:
-               return -EINVAL;
-       };
-
-       ret = i2c_transfer(&ttusb->i2c_adap, &msg, 1);
-       return (ret != 1) ? -EIO : 0;
-}
-
 static int ttusb_update_lnb(struct ttusb *ttusb)
 {
        u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1,
@@ -1048,7 +1025,7 @@ static u32 functionality(struct i2c_adapter *adapter)
 
 
 
-static int alps_tdmb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdmb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
        u8 data[4];
@@ -1062,20 +1039,21 @@ static int alps_tdmb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        data[2] = ((div >> 10) & 0x60) | 0x85;
        data[3] = params->frequency < 592000000 ? 0x40 : 0x80;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO;
        return 0;
 }
 
 static struct cx22700_config alps_tdmb7_config = {
        .demod_address = 0x43,
-       .pll_set = alps_tdmb7_pll_set,
 };
 
 
 
 
 
-static int philips_tdm1316l_pll_init(struct dvb_frontend* fe)
+static int philips_tdm1316l_tuner_init(struct dvb_frontend* fe)
 {
        struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
        static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
@@ -1083,6 +1061,8 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend* fe)
        struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) };
 
        // setup PLL configuration
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO;
        msleep(1);
 
@@ -1090,6 +1070,8 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend* fe)
        tuner_msg.addr = 0x65;
        tuner_msg.buf = disable_mc44BC374c;
        tuner_msg.len = sizeof(disable_mc44BC374c);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
                i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1);
        }
@@ -1097,7 +1079,7 @@ static int philips_tdm1316l_pll_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int philips_tdm1316l_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
        u8 tuner_buf[4];
@@ -1157,6 +1139,8 @@ static int philips_tdm1316l_pll_set(struct dvb_frontend* fe, struct dvb_frontend
        tuner_buf[2] = 0xca;
        tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
 
@@ -1176,8 +1160,6 @@ static struct tda1004x_config philips_tdm1316l_config = {
        .demod_address = 0x8,
        .invert = 1,
        .invert_oclk = 0,
-       .pll_init = philips_tdm1316l_pll_init,
-       .pll_set = philips_tdm1316l_pll_set,
        .request_firmware = philips_tdm1316l_request_firmware,
 };
 
@@ -1299,7 +1281,7 @@ static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32
        return 0;
 }
 
-static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
+static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
        u8 buf[4];
@@ -1322,7 +1304,9 @@ static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct i2c_adapter *
        if (ttusb->revision == TTUSB_REV_2_2)
                buf[3] |= 0x20;
 
-       if (i2c_transfer(i2c, &msg, 1) != 1)
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
                return -EIO;
 
        return 0;
@@ -1338,10 +1322,9 @@ static struct stv0299_config alps_stv0299_config = {
        .volt13_op0_op1 = STV0299_VOLT13_OP1,
        .min_delay_ms = 100,
        .set_symbol_rate = alps_stv0299_set_symbol_rate,
-       .pll_set = philips_tsa5059_pll_set,
 };
 
-static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
        u8 buf[4];
@@ -1355,6 +1338,8 @@ static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct
        buf[2] = 0x8e;
        buf[3] = 0x00;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
                return -EIO;
 
@@ -1364,10 +1349,9 @@ static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct
 static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
 
        .demod_address = 0x68,
-       .pll_set = ttusb_novas_grundig_29504_491_pll_set,
 };
 
-static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct ttusb* ttusb = fe->dvb->priv;
        u32 div;
@@ -1381,6 +1365,8 @@ static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
        data[2] = 0x85 | ((div >> 10) & 0x60);
        data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer (&ttusb->i2c_adap, &msg, 1) != 1)
                return -EIO;
 
@@ -1393,7 +1379,6 @@ static struct ves1820_config alps_tdbe2_config = {
        .xin = 57840000UL,
        .invert = 1,
        .selagc = VES1820_SELAGC_SIGNAMPERR,
-       .pll_set = alps_tdbe2_pll_set,
 };
 
 static u8 read_pwm(struct ttusb* ttusb)
@@ -1410,6 +1395,174 @@ static u8 read_pwm(struct ttusb* ttusb)
 }
 
 
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+       struct ttusb *ttusb = (struct ttusb *) fe->dvb->priv;
+       u8 tuner_buf[5];
+       struct i2c_msg tuner_msg = {.addr = 0x60,
+                                   .flags = 0,
+                                   .buf = tuner_buf,
+                                   .len = sizeof(tuner_buf) };
+       int tuner_frequency = 0;
+       u8 band, cp, filter;
+
+       // determine charge pump
+       tuner_frequency = params->frequency;
+       if      (tuner_frequency <  87000000) {return -EINVAL;}
+       else if (tuner_frequency < 130000000) {cp = 3; band = 1;}
+       else if (tuner_frequency < 160000000) {cp = 5; band = 1;}
+       else if (tuner_frequency < 200000000) {cp = 6; band = 1;}
+       else if (tuner_frequency < 290000000) {cp = 3; band = 2;}
+       else if (tuner_frequency < 420000000) {cp = 5; band = 2;}
+       else if (tuner_frequency < 480000000) {cp = 6; band = 2;}
+       else if (tuner_frequency < 620000000) {cp = 3; band = 4;}
+       else if (tuner_frequency < 830000000) {cp = 5; band = 4;}
+       else if (tuner_frequency < 895000000) {cp = 7; band = 4;}
+       else {return -EINVAL;}
+
+       // assume PLL filter should always be 8MHz for the moment.
+       filter = 1;
+
+       // calculate divisor
+       // (Finput + Fif)/Fref; Fif = 36125000 Hz, Fref = 62500 Hz
+       tuner_frequency = ((params->frequency + 36125000) / 62500);
+
+       // setup tuner buffer
+       tuner_buf[0] = tuner_frequency >> 8;
+       tuner_buf[1] = tuner_frequency & 0xff;
+       tuner_buf[2] = 0xc8;
+       tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+       tuner_buf[4] = 0x80;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
+               printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 1\n");
+               return -EIO;
+       }
+
+       msleep(50);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
+               printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 2\n");
+               return -EIO;
+       }
+
+       msleep(1);
+
+       return 0;
+}
+
+static u8 dvbc_philips_tdm1316l_inittab[] = {
+       0x80, 0x21,
+       0x80, 0x20,
+       0x81, 0x01,
+       0x81, 0x00,
+       0x00, 0x09,
+       0x01, 0x69,
+       0x03, 0x00,
+       0x04, 0x00,
+       0x07, 0x00,
+       0x08, 0x00,
+       0x20, 0x00,
+       0x21, 0x40,
+       0x22, 0x00,
+       0x23, 0x00,
+       0x24, 0x40,
+       0x25, 0x88,
+       0x30, 0xff,
+       0x31, 0x00,
+       0x32, 0xff,
+       0x33, 0x00,
+       0x34, 0x50,
+       0x35, 0x7f,
+       0x36, 0x00,
+       0x37, 0x20,
+       0x38, 0x00,
+       0x40, 0x1c,
+       0x41, 0xff,
+       0x42, 0x29,
+       0x43, 0x20,
+       0x44, 0xff,
+       0x45, 0x00,
+       0x46, 0x00,
+       0x49, 0x04,
+       0x4a, 0xff,
+       0x4b, 0x7f,
+       0x52, 0x30,
+       0x55, 0xae,
+       0x56, 0x47,
+       0x57, 0xe1,
+       0x58, 0x3a,
+       0x5a, 0x1e,
+       0x5b, 0x34,
+       0x60, 0x00,
+       0x63, 0x00,
+       0x64, 0x00,
+       0x65, 0x00,
+       0x66, 0x00,
+       0x67, 0x00,
+       0x68, 0x00,
+       0x69, 0x00,
+       0x6a, 0x02,
+       0x6b, 0x00,
+       0x70, 0xff,
+       0x71, 0x00,
+       0x72, 0x00,
+       0x73, 0x00,
+       0x74, 0x0c,
+       0x80, 0x00,
+       0x81, 0x00,
+       0x82, 0x00,
+       0x83, 0x00,
+       0x84, 0x04,
+       0x85, 0x80,
+       0x86, 0x24,
+       0x87, 0x78,
+       0x88, 0x00,
+       0x89, 0x00,
+       0x90, 0x01,
+       0x91, 0x01,
+       0xa0, 0x00,
+       0xa1, 0x00,
+       0xa2, 0x00,
+       0xb0, 0x91,
+       0xb1, 0x0b,
+       0xc0, 0x4b,
+       0xc1, 0x00,
+       0xc2, 0x00,
+       0xd0, 0x00,
+       0xd1, 0x00,
+       0xd2, 0x00,
+       0xd3, 0x00,
+       0xd4, 0x00,
+       0xd5, 0x00,
+       0xde, 0x00,
+       0xdf, 0x00,
+       0x61, 0x38,
+       0x62, 0x0a,
+       0x53, 0x13,
+       0x59, 0x08,
+       0x55, 0x00,
+       0x56, 0x40,
+       0x57, 0x08,
+       0x58, 0x3d,
+       0x88, 0x10,
+       0xa0, 0x00,
+       0xa0, 0x00,
+       0xa0, 0x00,
+       0xa0, 0x04,
+       0xff, 0xff,
+};
+
+static struct stv0297_config dvbc_philips_tdm1316l_config = {
+       .demod_address = 0x1c,
+       .inittab = dvbc_philips_tdm1316l_inittab,
+       .invert = 0,
+};
+
 static void frontend_init(struct ttusb* ttusb)
 {
        switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) {
@@ -1417,11 +1570,13 @@ static void frontend_init(struct ttusb* ttusb)
                // try the stv0299 based first
                ttusb->fe = stv0299_attach(&alps_stv0299_config, &ttusb->i2c_adap);
                if (ttusb->fe != NULL) {
+                       ttusb->fe->ops.tuner_ops.set_params = philips_tsa5059_tuner_set_params;
+
                        if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1
                                alps_stv0299_config.inittab = alps_bsbe1_inittab;
-                               ttusb->fe->ops->set_voltage = lnbp21_set_voltage;
+                               lnbp21_attach(ttusb->fe, &ttusb->i2c_adap, 0, 0);
                        } else { // ALPS BSRU6
-                               ttusb->fe->ops->set_voltage = ttusb_set_voltage;
+                               ttusb->fe->ops.set_voltage = ttusb_set_voltage;
                        }
                        break;
                }
@@ -1429,28 +1584,41 @@ static void frontend_init(struct ttusb* ttusb)
                // Grundig 29504-491
                ttusb->fe = tda8083_attach(&ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap);
                if (ttusb->fe != NULL) {
-                       ttusb->fe->ops->set_voltage = ttusb_set_voltage;
+                       ttusb->fe->ops.tuner_ops.set_params = ttusb_novas_grundig_29504_491_tuner_set_params;
+                       ttusb->fe->ops.set_voltage = ttusb_set_voltage;
                        break;
                }
-
                break;
 
        case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
                ttusb->fe = ves1820_attach(&alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb));
-               if (ttusb->fe != NULL)
+               if (ttusb->fe != NULL) {
+                       ttusb->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+                       break;
+               }
+
+               ttusb->fe = stv0297_attach(&dvbc_philips_tdm1316l_config, &ttusb->i2c_adap);
+               if (ttusb->fe != NULL) {
+                       ttusb->fe->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
                        break;
+               }
                break;
 
        case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??))
                // try the ALPS TDMB7 first
                ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap);
-               if (ttusb->fe != NULL)
+               if (ttusb->fe != NULL) {
+                       ttusb->fe->ops.tuner_ops.set_params = alps_tdmb7_tuner_set_params;
                        break;
+               }
 
                // Philips td1316
                ttusb->fe = tda10046_attach(&philips_tdm1316l_config, &ttusb->i2c_adap);
-               if (ttusb->fe != NULL)
+               if (ttusb->fe != NULL) {
+                       ttusb->fe->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+                       ttusb->fe->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
                        break;
+               }
                break;
        }
 
@@ -1461,8 +1629,8 @@ static void frontend_init(struct ttusb* ttusb)
        } else {
                if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) {
                        printk("dvb-ttusb-budget: Frontend registration failed!\n");
-                       if (ttusb->fe->ops->release)
-                               ttusb->fe->ops->release(ttusb->fe);
+                       if (ttusb->fe->ops.release)
+                               ttusb->fe->ops.release(ttusb->fe);
                        ttusb->fe = NULL;
                }
        }
@@ -1507,7 +1675,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
 
        mutex_unlock(&ttusb->semi2c);
 
-       if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE)) < 0) {
+       if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) {
                ttusb_free_iso_urbs(ttusb);
                kfree(ttusb);
                return result;
index 44dea32118483e9dbf14868dd927b84fdfad7ea1..6c1cb770bcf5d28ccecd3ea2d743fc7099bea056 100644 (file)
@@ -1432,7 +1432,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
        dprintk("%s\n", __FUNCTION__);
 
        if ((result = dvb_register_adapter(&dec->adapter,
-                                          dec->model_name, THIS_MODULE)) < 0) {
+                                          dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) {
                printk("%s: dvb_register_adapter failed: error %d\n",
                       __FUNCTION__, result);
 
@@ -1657,8 +1657,8 @@ static int ttusb_dec_probe(struct usb_interface *intf,
        } else {
                if (dvb_register_frontend(&dec->adapter, dec->fe)) {
                        printk("budget-ci: Frontend registration failed!\n");
-                       if (dec->fe->ops->release)
-                               dec->fe->ops->release(dec->fe);
+                       if (dec->fe->ops.release)
+                               dec->fe->ops.release(dec->fe);
                        dec->fe = NULL;
                }
        }
index a5a46175fa0969e302e59e75e14afa5a2e5cf2ab..42f39a89bc4d7a05c039e68515394e9b2c59fedc 100644 (file)
@@ -28,8 +28,6 @@
 
 struct ttusbdecfe_state {
 
-       struct dvb_frontend_ops ops;
-
        /* configuration settings */
        const struct ttusbdecfe_config* config;
 
@@ -203,10 +201,9 @@ struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* conf
 
        /* setup the state */
        state->config = config;
-       memcpy(&state->ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 }
@@ -226,10 +223,9 @@ struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* conf
        state->config = config;
        state->voltage = 0;
        state->hi_band = 0;
-       memcpy(&state->ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
 
        /* create dvb_frontend */
-       state->frontend.ops = &state->ops;
+       memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 }
index 3fff7576369323b5ff9bc3772408f595e32f0e58..de3128a31de825f6d31b2c9c7a2431d83f7f98b0 100644 (file)
@@ -136,7 +136,7 @@ config RADIO_GEMTEK_PCI
          Choose Y here if you have this PCI FM radio card.
 
          In order to control your radio card, you will need to use programs
-         that are compatible with the Video for Linux API.  Information on 
+         that are compatible with the Video for Linux API.  Information on
          this API and pointers to "v4l" programs may be found at
          <file:Documentation/video4linux/API.html>.
 
index 8b351945d0665caf31f31ade3a241da0b9d6aff0..e95b6805e00257ecdc752a405bc81eba2e443f8a 100644 (file)
@@ -20,3 +20,5 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
 obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
 obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
 obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
+
+EXTRA_CFLAGS += -Isound
index dc292da2605ffb4204dfcfb7c24b1ffc23256c42..c4312fa0e2f5278d071ef5eea2fe12ae82bf970a 100644 (file)
 
 /* What ever you think about the ACI, version 0x07 is not very well!
  * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono
- * conditions...                Robert 
+ * conditions...                Robert
  */
 
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/videodev.h>
-#include "../../../sound/oss/aci.h"
+#include <media/v4l2-common.h>
+#include "oss/aci.h"
 #include "miropcm20-rds-core.h"
 
 static int radio_nr = -1;
@@ -123,7 +124,7 @@ static int pcm20_do_ioctl(struct inode *inode, struct file *file,
        struct video_device *dev = video_devdata(file);
        struct pcm20_device *pcm20 = dev->priv;
        int i;
-       
+
        switch(cmd)
        {
                case VIDIOCGCAP:
@@ -139,7 +140,7 @@ static int pcm20_do_ioctl(struct inode *inode, struct file *file,
                case VIDIOCGTUNER:
                {
                        struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */ 
+                       if(v->tuner)    /* Only 1 tuner */
                                return -EINVAL;
                        v->rangelow=87*16000;
                        v->rangehigh=108*16000;
@@ -172,7 +173,7 @@ static int pcm20_do_ioctl(struct inode *inode, struct file *file,
                        return i;
                }
                case VIDIOCGAUDIO:
-               {       
+               {
                        struct video_audio *v = arg;
                        memset(v,0, sizeof(*v));
                        v->flags=VIDEO_AUDIO_MUTABLE;
@@ -183,12 +184,12 @@ static int pcm20_do_ioctl(struct inode *inode, struct file *file,
                                v->mode|=VIDEO_SOUND_MONO;
                        /* v->step=2048; */
                        strcpy(v->name, "Radio");
-                       return 0;                       
+                       return 0;
                }
                case VIDIOCSAUDIO:
                {
                        struct video_audio *v = arg;
-                       if(v->audio) 
+                       if(v->audio)
                                return -EINVAL;
 
                        pcm20_mute(pcm20, !!(v->flags&VIDEO_AUDIO_MUTE));
@@ -237,7 +238,7 @@ static int __init pcm20_init(void)
 {
        if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1)
                goto video_register_device;
-               
+
        if(attach_aci_rds()<0)
                goto attach_aci_rds;
 
index b602c73e2309ea9cf3313f225d32628599175025..9428d8b2642c9b7a103eca1f8b8156d3e66e3935 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/mutex.h>
 
 #include <asm/io.h>
-#include "../../../sound/oss/aci.h"
+#include "oss/aci.h"
 #include "miropcm20-rds-core.h"
 
 #define DEBUG 0
@@ -33,24 +33,24 @@ static struct mutex aci_rds_mutex;
 #define RDS_BUSYMASK        0x10   /* Bit 4 */
 #define RDS_CLOCKMASK       0x08   /* Bit 3 */
 
-#define RDS_DATA(x)         (((x) >> RDS_DATASHIFT) & 1) 
+#define RDS_DATA(x)         (((x) >> RDS_DATASHIFT) & 1)
 
 
 #if DEBUG
 static void print_matrix(char array[], unsigned int length)
 {
-        int i, j;
-
-        for (i=0; i<length; i++) {
-                printk(KERN_DEBUG "aci-rds: ");
-                for (j=7; j>=0; j--) {
-                        printk("%d", (array[i] >> j) & 0x1);
-                }
-                if (i%8 == 0)
-                        printk(" byte-border\n");
-                else
-                        printk("\n");
-        }
+       int i, j;
+
+       for (i=0; i<length; i++) {
+               printk(KERN_DEBUG "aci-rds: ");
+               for (j=7; j>=0; j--) {
+                       printk("%d", (array[i] >> j) & 0x1);
+               }
+               if (i%8 == 0)
+                       printk(" byte-border\n");
+               else
+                       printk("\n");
+       }
 }
 #endif /* DEBUG */
 
@@ -114,7 +114,7 @@ static int rds_write(unsigned char cmd)
 {
        unsigned char sendbuffer[8];
        int i;
-       
+
        if (byte2trans(cmd, sendbuffer, 8) != 0){
                return -1;
        } else {
@@ -151,7 +151,7 @@ static int rds_read(unsigned char databuffer[], int datasize)
           I have to waitread() here */
        if (rds_waitread() < 0)
                return -1;
-       
+
        memset(databuffer, 0, datasize);
 
        for (i=0; i< READSIZE; i++)
@@ -194,7 +194,7 @@ int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize)
                ret = 0;
 
        mutex_unlock(&aci_rds_mutex);
-       
+
        return ret;
 }
 EXPORT_SYMBOL(aci_rds_cmd);
index e09214082e011ef974bdd09297786e3839eef424..87b37b7691dad387cd082b10c030b9c0829947f3 100644 (file)
@@ -48,7 +48,7 @@ static int rds_f_release(struct inode *in, struct file *fi)
 
 static void print_matrix(char *ch, char out[])
 {
-        int j;
+       int j;
 
        for (j=7; j>=0; j--) {
                 out[7-j] = ((*ch >> j) & 0x1) + '0';
index 557fb5c4af38ea59c5fad2cc3ae80cc29e125760..df22a582e7a2fae4762b07801313eec005bbc66d 100644 (file)
@@ -24,7 +24,7 @@
  *   out(port, start_increasing_volume);
  *   wait(a_wee_while);
  *   out(port, stop_changing_the_volume);
- *  
+ *
  */
 
 #include <linux/module.h>      /* Modules                      */
@@ -34,6 +34,7 @@
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev.h>    /* kernel radio structs         */
+#include <media/v4l2-common.h>
 #include <linux/config.h>      /* CONFIG_RADIO_RTRACK_PORT     */
 #include <asm/semaphore.h>     /* Lock for the I/O             */
 
@@ -41,7 +42,7 @@
 #define CONFIG_RADIO_RTRACK_PORT -1
 #endif
 
-static int io = CONFIG_RADIO_RTRACK_PORT; 
+static int io = CONFIG_RADIO_RTRACK_PORT;
 static int radio_nr = -1;
 static struct mutex lock;
 
@@ -93,12 +94,12 @@ static int rt_setvol(struct rt_device *dev, int vol)
        int i;
 
        mutex_lock(&lock);
-       
+
        if(vol == dev->curvol) {        /* requested volume = current */
                if (dev->muted) {       /* user is unmuting the card  */
                        dev->muted = 0;
                        outb (0xd8, io);        /* enable card */
-               }       
+               }
                mutex_unlock(&lock);
                return 0;
        }
@@ -114,10 +115,10 @@ static int rt_setvol(struct rt_device *dev, int vol)
 
        dev->muted = 0;
        if(vol > dev->curvol)
-               for(i = dev->curvol; i < vol; i++) 
+               for(i = dev->curvol; i < vol; i++)
                        rt_incvol();
        else
-               for(i = dev->curvol; i > vol; i--) 
+               for(i = dev->curvol; i > vol; i--)
                        rt_decvol();
 
        dev->curvol = vol;
@@ -125,7 +126,7 @@ static int rt_setvol(struct rt_device *dev, int vol)
        return 0;
 }
 
-/* the 128+64 on these outb's is to keep the volume stable while tuning 
+/* the 128+64 on these outb's is to keep the volume stable while tuning
  * without them, the volume _will_ creep up with each frequency change
  * and bit 4 (+16) is to keep the signal strength meter enabled
  */
@@ -140,7 +141,7 @@ static void send_0_byte(int port, struct rt_device *dev)
                outb_p(128+64+16+8+  1, port);  /* on + wr-enable + data low */
                outb_p(128+64+16+8+2+1, port);  /* clock */
        }
-       sleep_delay(1000); 
+       sleep_delay(1000);
 }
 
 static void send_1_byte(int port, struct rt_device *dev)
@@ -148,13 +149,13 @@ static void send_1_byte(int port, struct rt_device *dev)
        if ((dev->curvol == 0) || (dev->muted)) {
                outb_p(128+64+16+4  +1, port);   /* wr-enable+data high */
                outb_p(128+64+16+4+2+1, port);   /* clock */
-       } 
+       }
        else {
                outb_p(128+64+16+8+4  +1, port); /* on+wr-enable+data high */
                outb_p(128+64+16+8+4+2+1, port); /* clock */
        }
 
-       sleep_delay(1000); 
+       sleep_delay(1000);
 }
 
 static int rt_setfreq(struct rt_device *dev, unsigned long freq)
@@ -167,9 +168,9 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq)
 
        freq += 171200;                 /* Add 10.7 MHz IF              */
        freq /= 800;                    /* Convert to 50 kHz units      */
-       
+
        mutex_lock(&lock);                      /* Stop other ops interfering */
-        
+
        send_0_byte (io, dev);          /*  0: LSB of frequency         */
 
        for (i = 0; i < 13; i++)        /*   : frequency bits (1-13)    */
@@ -195,7 +196,7 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq)
                outb (0xd0, io);        /* volume steady + sigstr */
        else
                outb (0xd8, io);        /* volume steady + sigstr + on */
-               
+
        mutex_unlock(&lock);
 
        return 0;
@@ -213,7 +214,7 @@ static int rt_do_ioctl(struct inode *inode, struct file *file,
 {
        struct video_device *dev = video_devdata(file);
        struct rt_device *rt=dev->priv;
-       
+
        switch(cmd)
        {
                case VIDIOCGCAP:
@@ -229,7 +230,7 @@ static int rt_do_ioctl(struct inode *inode, struct file *file,
                case VIDIOCGTUNER:
                {
                        struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */ 
+                       if(v->tuner)    /* Only 1 tuner */
                                return -EINVAL;
                        v->rangelow=(87*16000);
                        v->rangehigh=(108*16000);
@@ -261,21 +262,21 @@ static int rt_do_ioctl(struct inode *inode, struct file *file,
                        return 0;
                }
                case VIDIOCGAUDIO:
-               {       
+               {
                        struct video_audio *v = arg;
                        memset(v,0, sizeof(*v));
                        v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
                        v->volume=rt->curvol * 6554;
                        v->step=6554;
                        strcpy(v->name, "Radio");
-                       return 0;                       
+                       return 0;
                }
                case VIDIOCSAUDIO:
                {
                        struct video_audio *v = arg;
-                       if(v->audio) 
+                       if(v->audio)
                                return -EINVAL;
-                       if(v->flags&VIDEO_AUDIO_MUTE) 
+                       if(v->flags&VIDEO_AUDIO_MUTE)
                                rt_mute(rt);
                        else
                                rt_setvol(rt,v->volume/6554);
@@ -298,7 +299,7 @@ static struct file_operations rtrack_fops = {
        .owner          = THIS_MODULE,
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
-       .ioctl          = rt_ioctl,
+       .ioctl          = rt_ioctl,
        .compat_ioctl   = v4l_compat_ioctl32,
        .llseek         = no_llseek,
 };
@@ -320,14 +321,14 @@ static int __init rtrack_init(void)
                return -EINVAL;
        }
 
-       if (!request_region(io, 2, "rtrack")) 
+       if (!request_region(io, 2, "rtrack"))
        {
                printk(KERN_ERR "rtrack: port 0x%x already in use\n", io);
                return -EBUSY;
        }
 
        rtrack_radio.priv=&rtrack_unit;
-       
+
        if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr)==-1)
        {
                release_region(io, 2);
@@ -336,10 +337,10 @@ static int __init rtrack_init(void)
        printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n");
 
        /* Set up the I/O locking */
-       
+
        mutex_init(&lock);
-       
-       /* mute card - prevents noisy bootups */
+
+       /* mute card - prevents noisy bootups */
 
        /* this ensures that the volume is all the way down  */
        outb(0x48, io);         /* volume down but still "on"   */
index 83bdae23417d930386d600850df4f51ecab1d4b4..95e6322133ee43289c1077af080cf50a57825db8 100644 (file)
@@ -1,11 +1,11 @@
-/* radio-aztech.c - Aztech radio card driver for Linux 2.2 
+/* radio-aztech.c - Aztech radio card driver for Linux 2.2
  *
- * Adapted to support the Video for Linux API by 
+ * Adapted to support the Video for Linux API by
  * Russell Kroll <rkroll@exploits.org>.  Based on original tuner code by:
  *
  * Quay Ly
  * Donald Song
- * Jason Lewis      (jlewis@twilight.vtc.vsc.edu) 
+ * Jason Lewis      (jlewis@twilight.vtc.vsc.edu)
  * Scott McGrath    (smcgrath@twilight.vtc.vsc.edu)
  * William McGrath  (wmcgrath@twilight.vtc.vsc.edu)
  *
@@ -31,6 +31,7 @@
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev.h>    /* kernel radio structs         */
+#include <media/v4l2-common.h>
 #include <linux/config.h>      /* CONFIG_RADIO_AZTECH_PORT     */
 
 /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
@@ -39,7 +40,7 @@
 #define CONFIG_RADIO_AZTECH_PORT -1
 #endif
 
-static int io = CONFIG_RADIO_AZTECH_PORT; 
+static int io = CONFIG_RADIO_AZTECH_PORT;
 static int radio_nr = -1;
 static int radio_wait_time = 1000;
 static struct mutex lock;
@@ -53,15 +54,15 @@ struct az_device
 
 static int volconvert(int level)
 {
-       level>>=14;             /* Map 16bits down to 2 bit */
-       level&=3;
-       
+       level>>=14;             /* Map 16bits down to 2 bit */
+       level&=3;
+
        /* convert to card-friendly values */
-       switch (level) 
+       switch (level)
        {
-               case 0: 
+               case 0:
                        return 0;
-               case 1: 
+               case 1:
                        return 1;
                case 2:
                        return 4;
@@ -121,9 +122,9 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency)
 
        frequency += 171200;            /* Add 10.7 MHz IF              */
        frequency /= 800;               /* Convert to 50 kHz units      */
-                                       
+
        mutex_lock(&lock);
-       
+
        send_0_byte (dev);              /*  0: LSB of frequency       */
 
        for (i = 0; i < 13; i++)        /*   : frequency bits (1-13)  */
@@ -151,7 +152,7 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency)
 
        udelay (radio_wait_time);
        outb_p(128+64+volconvert(dev->curvol), io);
-       
+
        mutex_unlock(&lock);
 
        return 0;
@@ -162,7 +163,7 @@ static int az_do_ioctl(struct inode *inode, struct file *file,
 {
        struct video_device *dev = video_devdata(file);
        struct az_device *az = dev->priv;
-       
+
        switch(cmd)
        {
                case VIDIOCGCAP:
@@ -178,7 +179,7 @@ static int az_do_ioctl(struct inode *inode, struct file *file,
                case VIDIOCGTUNER:
                {
                        struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */ 
+                       if(v->tuner)    /* Only 1 tuner */
                                return -EINVAL;
                        v->rangelow=(87*16000);
                        v->rangehigh=(108*16000);
@@ -211,7 +212,7 @@ static int az_do_ioctl(struct inode *inode, struct file *file,
                        return 0;
                }
                case VIDIOCGAUDIO:
-               {       
+               {
                        struct video_audio *v = arg;
                        memset(v,0, sizeof(*v));
                        v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
@@ -222,17 +223,17 @@ static int az_do_ioctl(struct inode *inode, struct file *file,
                        v->volume=az->curvol;
                        v->step=16384;
                        strcpy(v->name, "Radio");
-                       return 0;                       
+                       return 0;
                }
                case VIDIOCSAUDIO:
                {
                        struct video_audio *v = arg;
-                       if(v->audio) 
+                       if(v->audio)
                                return -EINVAL;
                        az->curvol=v->volume;
 
                        az->stereo=(v->mode&VIDEO_SOUND_STEREO)?1:0;
-                       if(v->flags&VIDEO_AUDIO_MUTE) 
+                       if(v->flags&VIDEO_AUDIO_MUTE)
                                az_setvol(az,0);
                        else
                                az_setvol(az,az->curvol);
@@ -277,7 +278,7 @@ static int __init aztech_init(void)
                return -EINVAL;
        }
 
-       if (!request_region(io, 2, "aztech")) 
+       if (!request_region(io, 2, "aztech"))
        {
                printk(KERN_ERR "aztech: port 0x%x already in use\n", io);
                return -EBUSY;
@@ -285,13 +286,13 @@ static int __init aztech_init(void)
 
        mutex_init(&lock);
        aztech_radio.priv=&aztech_unit;
-       
+
        if(video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr)==-1)
        {
                release_region(io,2);
                return -EINVAL;
        }
-               
+
        printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
        /* mute card - prevents noisy bootups */
        outb (0, io);
index f1b5ac81e9d2bc734d6dd3345c12d0bd46fa235e..8641aec7baf87093e8faf1ea90331d913abe0ca9 100644 (file)
@@ -8,7 +8,7 @@
  * Russell Kroll    (rkroll@exploits.org)
  * Quay Ly
  * Donald Song
- * Jason Lewis      (jlewis@twilight.vtc.vsc.edu) 
+ * Jason Lewis      (jlewis@twilight.vtc.vsc.edu)
  * Scott McGrath    (smcgrath@twilight.vtc.vsc.edu)
  * William McGrath  (wmcgrath@twilight.vtc.vsc.edu)
  *
@@ -34,6 +34,7 @@
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev.h>    /* kernel radio structs         */
+#include <media/v4l2-common.h>
 #include <linux/param.h>
 #include <linux/pnp.h>
 
@@ -55,29 +56,29 @@ static int cadet_probe(void);
 
 /*
  * Signal Strength Threshold Values
- * The V4L API spec does not define any particular unit for the signal 
+ * The V4L API spec does not define any particular unit for the signal
  * strength value.  These values are in microvolts of RF at the tuner's input.
  */
 static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}};
 
 static int cadet_getrds(void)
 {
-        int rdsstat=0;
+       int rdsstat=0;
 
        spin_lock(&cadet_io_lock);
-        outb(3,io);                 /* Select Decoder Control/Status */
+       outb(3,io);                 /* Select Decoder Control/Status */
        outb(inb(io+1)&0x7f,io+1);  /* Reset RDS detection */
        spin_unlock(&cadet_io_lock);
-       
+
        msleep(100);
 
-       spin_lock(&cadet_io_lock);      
-        outb(3,io);                 /* Select Decoder Control/Status */
+       spin_lock(&cadet_io_lock);
+       outb(3,io);                 /* Select Decoder Control/Status */
        if((inb(io+1)&0x80)!=0) {
-               rdsstat|=VIDEO_TUNER_RDS_ON;
+               rdsstat|=VIDEO_TUNER_RDS_ON;
        }
        if((inb(io+1)&0x10)!=0) {
-               rdsstat|=VIDEO_TUNER_MBS_ON;
+               rdsstat|=VIDEO_TUNER_MBS_ON;
        }
        spin_unlock(&cadet_io_lock);
        return rdsstat;
@@ -86,49 +87,49 @@ static int cadet_getrds(void)
 static int cadet_getstereo(void)
 {
        int ret = 0;
-        if(curtuner != 0)      /* Only FM has stereo capability! */
-               return 0;
+       if(curtuner != 0)       /* Only FM has stereo capability! */
+               return 0;
 
        spin_lock(&cadet_io_lock);
-        outb(7,io);          /* Select tuner control */
+       outb(7,io);          /* Select tuner control */
        if( (inb(io+1) & 0x40) == 0)
-               ret = 1;
-        spin_unlock(&cadet_io_lock);
-        return ret;
+               ret = 1;
+       spin_unlock(&cadet_io_lock);
+       return ret;
 }
 
 static unsigned cadet_gettune(void)
 {
-        int curvol,i;
+       int curvol,i;
        unsigned fifo=0;
 
-        /*
-         * Prepare for read
-         */
+       /*
+        * Prepare for read
+        */
 
        spin_lock(&cadet_io_lock);
-       
-        outb(7,io);       /* Select tuner control */
-        curvol=inb(io+1); /* Save current volume/mute setting */
-        outb(0x00,io+1);  /* Ensure WRITE-ENABLE is LOW */
+
+       outb(7,io);       /* Select tuner control */
+       curvol=inb(io+1); /* Save current volume/mute setting */
+       outb(0x00,io+1);  /* Ensure WRITE-ENABLE is LOW */
        tunestat=0xffff;
 
-        /*
-         * Read the shift register
-         */
-        for(i=0;i<25;i++) {
-                fifo=(fifo<<1)|((inb(io+1)>>7)&0x01);
-                if(i<24) {
-                        outb(0x01,io+1);
+       /*
+        * Read the shift register
+        */
+       for(i=0;i<25;i++) {
+               fifo=(fifo<<1)|((inb(io+1)>>7)&0x01);
+               if(i<24) {
+                       outb(0x01,io+1);
                        tunestat&=inb(io+1);
-                        outb(0x00,io+1);
-                }
-        }
-
-        /*
-         * Restore volume/mute setting
-         */
-        outb(curvol,io+1);
+                       outb(0x00,io+1);
+               }
+       }
+
+       /*
+        * Restore volume/mute setting
+        */
+       outb(curvol,io+1);
        spin_unlock(&cadet_io_lock);
 
        return fifo;
@@ -136,43 +137,43 @@ static unsigned cadet_gettune(void)
 
 static unsigned cadet_getfreq(void)
 {
-        int i;
-        unsigned freq=0,test,fifo=0;
+       int i;
+       unsigned freq=0,test,fifo=0;
 
        /*
         * Read current tuning
         */
        fifo=cadet_gettune();
 
-        /*
-         * Convert to actual frequency
-         */
+       /*
+        * Convert to actual frequency
+        */
        if(curtuner==0) {    /* FM */
-               test=12500;
-                for(i=0;i<14;i++) {
-                        if((fifo&0x01)!=0) {
-                                freq+=test;
-                        }
-                        test=test<<1;
-                        fifo=fifo>>1;
-                }
-                freq-=10700000;           /* IF frequency is 10.7 MHz */
-                freq=(freq*16)/1000000;   /* Make it 1/16 MHz */
+               test=12500;
+               for(i=0;i<14;i++) {
+                       if((fifo&0x01)!=0) {
+                               freq+=test;
+                       }
+                       test=test<<1;
+                       fifo=fifo>>1;
+               }
+               freq-=10700000;           /* IF frequency is 10.7 MHz */
+               freq=(freq*16)/1000000;   /* Make it 1/16 MHz */
        }
        if(curtuner==1) {    /* AM */
-               freq=((fifo&0x7fff)-2010)*16;
+               freq=((fifo&0x7fff)-2010)*16;
        }
 
-        return freq;
+       return freq;
 }
 
 static void cadet_settune(unsigned fifo)
 {
-        int i;
-       unsigned test;  
+       int i;
+       unsigned test;
 
        spin_lock(&cadet_io_lock);
-       
+
        outb(7,io);                /* Select tuner control */
        /*
         * Write the shift register
@@ -183,7 +184,7 @@ static void cadet_settune(unsigned fifo)
        outb(7,io);                /* Select tuner control */
        outb(test,io+1);           /* Initialize for write */
        for(i=0;i<25;i++) {
-               test|=0x01;              /* Toggle SCK High */
+               test|=0x01;              /* Toggle SCK High */
                outb(test,io+1);
                test&=0xfe;              /* Toggle SCK Low */
                outb(test,io+1);
@@ -196,57 +197,57 @@ static void cadet_settune(unsigned fifo)
 
 static void cadet_setfreq(unsigned freq)
 {
-        unsigned fifo;
-        int i,j,test;
-        int curvol;
+       unsigned fifo;
+       int i,j,test;
+       int curvol;
 
-        /* 
-         * Formulate a fifo command
-         */
+       /*
+        * Formulate a fifo command
+        */
        fifo=0;
        if(curtuner==0) {    /* FM */
-               test=102400;
-                freq=(freq*1000)/16;       /* Make it kHz */
-                freq+=10700;               /* IF is 10700 kHz */
-                for(i=0;i<14;i++) {
-                        fifo=fifo<<1;
-                        if(freq>=test) {
-                                fifo|=0x01;
-                                freq-=test;
-                        }
-                        test=test>>1;
-                }
+               test=102400;
+               freq=(freq*1000)/16;       /* Make it kHz */
+               freq+=10700;               /* IF is 10700 kHz */
+               for(i=0;i<14;i++) {
+                       fifo=fifo<<1;
+                       if(freq>=test) {
+                               fifo|=0x01;
+                               freq-=test;
+                       }
+                       test=test>>1;
+               }
        }
        if(curtuner==1) {    /* AM */
-                fifo=(freq/16)+2010;            /* Make it kHz */
+               fifo=(freq/16)+2010;            /* Make it kHz */
                fifo|=0x100000;            /* Select AM Band */
        }
 
-        /*
-         * Save current volume/mute setting
-         */
+       /*
+        * Save current volume/mute setting
+        */
 
        spin_lock(&cadet_io_lock);
        outb(7,io);                /* Select tuner control */
-        curvol=inb(io+1); 
-        spin_unlock(&cadet_io_lock);
+       curvol=inb(io+1);
+       spin_unlock(&cadet_io_lock);
 
        /*
         * Tune the card
         */
        for(j=3;j>-1;j--) {
-               cadet_settune(fifo|(j<<16));
-               
-               spin_lock(&cadet_io_lock);
+               cadet_settune(fifo|(j<<16));
+
+               spin_lock(&cadet_io_lock);
                outb(7,io);         /* Select tuner control */
                outb(curvol,io+1);
                spin_unlock(&cadet_io_lock);
-               
+
                msleep(100);
 
                cadet_gettune();
                if((tunestat & 0x40) == 0) {   /* Tuned */
-                       sigstrength=sigtable[curtuner][j];
+                       sigstrength=sigtable[curtuner][j];
                        return;
                }
        }
@@ -257,28 +258,28 @@ static void cadet_setfreq(unsigned freq)
 static int cadet_getvol(void)
 {
        int ret = 0;
-       
+
        spin_lock(&cadet_io_lock);
-       
-        outb(7,io);                /* Select tuner control */
-        if((inb(io + 1) & 0x20) != 0)
-               ret = 0xffff;
-        
-        spin_unlock(&cadet_io_lock);
-        return ret;
+
+       outb(7,io);                /* Select tuner control */
+       if((inb(io + 1) & 0x20) != 0)
+               ret = 0xffff;
+
+       spin_unlock(&cadet_io_lock);
+       return ret;
 }
 
 
 static void cadet_setvol(int vol)
 {
        spin_lock(&cadet_io_lock);
-        outb(7,io);                /* Select tuner control */
-        if(vol>0)
-                outb(0x20,io+1);
-        else
-                outb(0x00,io+1);
+       outb(7,io);                /* Select tuner control */
+       if(vol>0)
+               outb(0x20,io+1);
+       else
+               outb(0x00,io+1);
        spin_unlock(&cadet_io_lock);
-}  
+}
 
 static void cadet_handler(unsigned long data)
 {
@@ -288,15 +289,15 @@ static void cadet_handler(unsigned long data)
 
        if(spin_trylock(&cadet_io_lock))
        {
-               outb(0x3,io);       /* Select RDS Decoder Control */
+               outb(0x3,io);       /* Select RDS Decoder Control */
                if((inb(io+1)&0x20)!=0) {
-                       printk(KERN_CRIT "cadet: RDS fifo overflow\n");
+                       printk(KERN_CRIT "cadet: RDS fifo overflow\n");
                }
                outb(0x80,io);      /* Select RDS fifo */
                while((inb(io)&0x80)!=0) {
-                       rdsbuf[rdsin]=inb(io+1);
+                       rdsbuf[rdsin]=inb(io+1);
                        if(rdsin==rdsout)
-                               printk(KERN_WARNING "cadet: RDS buffer overflow\n");
+                               printk(KERN_WARNING "cadet: RDS buffer overflow\n");
                        else
                                rdsin++;
                }
@@ -307,9 +308,9 @@ static void cadet_handler(unsigned long data)
         * Service pending read
         */
        if( rdsin!=rdsout)
-               wake_up_interruptible(&read_queue);
+               wake_up_interruptible(&read_queue);
 
-       /* 
+       /*
         * Clean up and exit
         */
        init_timer(&readtimer);
@@ -324,12 +325,12 @@ static void cadet_handler(unsigned long data)
 static ssize_t cadet_read(struct file *file, char __user *data,
                          size_t count, loff_t *ppos)
 {
-        int i=0;
+       int i=0;
        unsigned char readbuf[RDS_BUFFER];
 
-        if(rdsstat==0) {
+       if(rdsstat==0) {
                spin_lock(&cadet_io_lock);
-               rdsstat=1;
+               rdsstat=1;
                outb(0x80,io);        /* Select RDS fifo */
                spin_unlock(&cadet_io_lock);
                init_timer(&readtimer);
@@ -339,15 +340,15 @@ static ssize_t cadet_read(struct file *file, char __user *data,
                add_timer(&readtimer);
        }
        if(rdsin==rdsout) {
-               if (file->f_flags & O_NONBLOCK)
-                       return -EWOULDBLOCK;
-               interruptible_sleep_on(&read_queue);
-       }               
+               if (file->f_flags & O_NONBLOCK)
+                       return -EWOULDBLOCK;
+               interruptible_sleep_on(&read_queue);
+       }
        while( i<count && rdsin!=rdsout)
-               readbuf[i++]=rdsbuf[rdsout++];
+               readbuf[i++]=rdsbuf[rdsout++];
 
        if (copy_to_user(data,readbuf,i))
-               return -EFAULT;
+               return -EFAULT;
        return i;
 }
 
@@ -375,29 +376,29 @@ static int cadet_do_ioctl(struct inode *inode, struct file *file,
                                return -EINVAL;
                        }
                        switch(v->tuner) {
-                               case 0:
-                               strcpy(v->name,"FM");
-                               v->rangelow=1400;     /* 87.5 MHz */
-                               v->rangehigh=1728;    /* 108.0 MHz */
-                               v->flags=0;
-                               v->mode=0;
-                               v->mode|=VIDEO_MODE_AUTO;
-                               v->signal=sigstrength;
-                               if(cadet_getstereo()==1) {
-                                       v->flags|=VIDEO_TUNER_STEREO_ON;
-                               }
+                               case 0:
+                               strcpy(v->name,"FM");
+                               v->rangelow=1400;     /* 87.5 MHz */
+                               v->rangehigh=1728;    /* 108.0 MHz */
+                               v->flags=0;
+                               v->mode=0;
+                               v->mode|=VIDEO_MODE_AUTO;
+                               v->signal=sigstrength;
+                               if(cadet_getstereo()==1) {
+                                       v->flags|=VIDEO_TUNER_STEREO_ON;
+                               }
                                v->flags|=cadet_getrds();
-                               break;
-                               case 1:
-                               strcpy(v->name,"AM");
-                               v->rangelow=8320;      /* 520 kHz */
-                               v->rangehigh=26400;    /* 1650 kHz */
-                               v->flags=0;
-                               v->flags|=VIDEO_TUNER_LOW;
-                               v->mode=0;
-                               v->mode|=VIDEO_MODE_AUTO;
-                               v->signal=sigstrength;
-                               break;
+                               break;
+                               case 1:
+                               strcpy(v->name,"AM");
+                               v->rangelow=8320;      /* 520 kHz */
+                               v->rangehigh=26400;    /* 1650 kHz */
+                               v->flags=0;
+                               v->flags|=VIDEO_TUNER_LOW;
+                               v->mode=0;
+                               v->mode|=VIDEO_MODE_AUTO;
+                               v->signal=sigstrength;
+                               break;
                        }
                        return 0;
                }
@@ -407,49 +408,49 @@ static int cadet_do_ioctl(struct inode *inode, struct file *file,
                        if((v->tuner<0)||(v->tuner>1)) {
                                return -EINVAL;
                        }
-                       curtuner=v->tuner;      
+                       curtuner=v->tuner;
                        return 0;
                }
                case VIDIOCGFREQ:
                {
-                       unsigned long *freq = arg;
+                       unsigned long *freq = arg;
                        *freq = cadet_getfreq();
                        return 0;
                }
                case VIDIOCSFREQ:
                {
-                       unsigned long *freq = arg;
+                       unsigned long *freq = arg;
                        if((curtuner==0)&&((*freq<1400)||(*freq>1728))) {
-                               return -EINVAL;
+                               return -EINVAL;
                        }
                        if((curtuner==1)&&((*freq<8320)||(*freq>26400))) {
-                               return -EINVAL;
+                               return -EINVAL;
                        }
                        cadet_setfreq(*freq);
                        return 0;
                }
                case VIDIOCGAUDIO:
-               {       
+               {
                        struct video_audio *v = arg;
                        memset(v,0, sizeof(*v));
                        v->flags=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
                        if(cadet_getstereo()==0) {
-                               v->mode=VIDEO_SOUND_MONO;
+                               v->mode=VIDEO_SOUND_MONO;
                        } else {
                                v->mode=VIDEO_SOUND_STEREO;
                        }
                        v->volume=cadet_getvol();
                        v->step=0xffff;
                        strcpy(v->name, "Radio");
-                       return 0;                       
+                       return 0;
                }
                case VIDIOCSAUDIO:
                {
                        struct video_audio *v = arg;
-                       if(v->audio) 
+                       if(v->audio)
                                return -EINVAL;
                        cadet_setvol(v->volume);
-                       if(v->flags&VIDEO_AUDIO_MUTE) 
+                       if(v->flags&VIDEO_AUDIO_MUTE)
                                cadet_setvol(0);
                        else
                                cadet_setvol(0xffff);
@@ -539,16 +540,16 @@ static struct pnp_driver cadet_pnp_driver = {
 
 static int cadet_probe(void)
 {
-        static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e};
+       static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e};
        int i;
 
        for(i=0;i<8;i++) {
-               io=iovals[i];
+               io=iovals[i];
                if (request_region(io, 2, "cadet-probe")) {
-                       cadet_setfreq(1410);
+                       cadet_setfreq(1410);
                        if(cadet_getfreq()==1410) {
                                release_region(io, 2);
-                               return io;
+                               return io;
                        }
                        release_region(io, 2);
                }
@@ -556,7 +557,7 @@ static int cadet_probe(void)
        return -1;
 }
 
-/* 
+/*
  * io should only be set if the user has used something like
  * isapnp (the userspace program) to initialize this card for us
  */
@@ -564,7 +565,7 @@ static int cadet_probe(void)
 static int __init cadet_init(void)
 {
        spin_lock_init(&cadet_io_lock);
-       
+
        /*
         *      If a probe was requested then probe ISAPnP first (safest)
         */
@@ -579,12 +580,12 @@ static int __init cadet_init(void)
        /*
         *      Else we bail out
         */
-        
-        if(io < 0) {
-#ifdef MODULE        
+
+       if(io < 0) {
+#ifdef MODULE
                printk(KERN_ERR "You must set an I/O address with io=0x???\n");
 #endif
-               goto fail;
+               goto fail;
        }
        if (!request_region(io,2,"cadet"))
                goto fail;
index 8e499b8f64c79e88474db41b93f6ae824c164db1..9f249e7e60c9b16d2a0d9b4081d18ea28a478d20 100644 (file)
@@ -1,6 +1,6 @@
 /*
  ***************************************************************************
- *     
+ *
  *     radio-gemtek-pci.c - Gemtek PCI Radio driver
  *     (C) 2001 Vladimir Shebordaev <vshebordaev@mail.ru>
  *
@@ -31,7 +31,7 @@
  *     radio device driver.
  *
  *     Please, let me know if this piece of code was useful :)
- * 
+ *
  *     TODO: multiple device support and portability were not tested
  *
  ***************************************************************************
@@ -44,6 +44,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/errno.h>
 
 #include <asm/io.h>
 #define TRUE (1)
 #endif
 
-#ifndef FALSE 
+#ifndef FALSE
 #define FALSE (0)
 #endif
 
 struct gemtek_pci_card {
        struct video_device *videodev;
-       
+
        u32 iobase;
        u32 length;
        u8  chiprev;
        u16 model;
-       
+
        u32 current_frequency;
        u8  mute;
 };
@@ -96,7 +97,7 @@ static inline u8 gemtek_pci_out( u16 value, u32 port )
        return (u8)value;
 }
 
-#define _b0( v ) *((u8 *)&v)  
+#define _b0( v ) *((u8 *)&v)
 static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep )
 {
        register u8 byte = *last_byte;
@@ -104,7 +105,7 @@ static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep )
        if ( !value ) {
                if ( !keep )
                        value = (u16)port;
-               byte &= 0xfd;   
+               byte &= 0xfd;
        } else
                byte |= 2;
 
@@ -116,7 +117,7 @@ static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep )
        byte &= 0xfe;
        _b0( value ) = byte;
        outw( value, port );
-       
+
        *last_byte = byte;
 }
 
@@ -193,13 +194,13 @@ static int gemtek_pci_do_ioctl(struct inode *inode, struct file *file,
                        c->audios = 1;
                        strcpy( c->name, "Gemtek PCI Radio" );
                        return 0;
-               } 
+               }
 
                case VIDIOCGTUNER:
                {
                        struct video_tuner *t = arg;
 
-                       if ( t->tuner ) 
+                       if ( t->tuner )
                                return -EINVAL;
 
                        t->rangelow = GEMTEK_PCI_RANGE_LOW;
@@ -228,7 +229,7 @@ static int gemtek_pci_do_ioctl(struct inode *inode, struct file *file,
                case VIDIOCSFREQ:
                {
                        unsigned long *freq = arg;
-        
+
                        if ( (*freq < GEMTEK_PCI_RANGE_LOW) ||
                             (*freq > GEMTEK_PCI_RANGE_HIGH) )
                                return -EINVAL;
@@ -239,9 +240,9 @@ static int gemtek_pci_do_ioctl(struct inode *inode, struct file *file,
 
                        return 0;
                }
-  
+
                case VIDIOCGAUDIO:
-               {       
+               {
                        struct video_audio *a = arg;
 
                        memset( a, 0, sizeof( *a ) );
@@ -249,17 +250,17 @@ static int gemtek_pci_do_ioctl(struct inode *inode, struct file *file,
                        a->volume = 1;
                        a->step = 65535;
                        strcpy( a->name, "Radio" );
-                       return 0;                       
+                       return 0;
                }
 
                case VIDIOCSAUDIO:
                {
                        struct video_audio *a = arg;
 
-                       if ( a->audio ) 
+                       if ( a->audio )
                                return -EINVAL;
 
-                       if ( a->flags & VIDEO_AUDIO_MUTE ) 
+                       if ( a->flags & VIDEO_AUDIO_MUTE )
                                gemtek_pci_mute( card );
                        else
                                gemtek_pci_unmute( card );
@@ -323,9 +324,9 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
                return -ENOMEM;
        }
 
-       if ( pci_enable_device( pci_dev ) ) 
+       if ( pci_enable_device( pci_dev ) )
                goto err_pci;
-       
+
        card->iobase = pci_resource_start( pci_dev, 0 );
        card->length = pci_resource_len( pci_dev, 0 );
 
@@ -338,7 +339,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
        pci_read_config_word( pci_dev, PCI_SUBSYSTEM_ID, &card->model );
 
        pci_set_drvdata( pci_dev, card );
+
        if ( (devradio = kmalloc( sizeof( struct video_device ), GFP_KERNEL )) == NULL ) {
                printk( KERN_ERR "gemtek_pci: out of memory\n" );
                goto err_video;
@@ -354,7 +355,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
        devradio->priv = card;
        gemtek_pci_mute( card );
 
-       printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", 
+       printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
                card->chiprev, card->iobase, card->iobase + card->length - 1 );
 
        return 0;
@@ -364,7 +365,7 @@ err_video:
 
 err_pci:
        kfree( card );
-       return -ENODEV;        
+       return -ENODEV;
 }
 
 static void __devexit gemtek_pci_remove( struct pci_dev *pci_dev )
@@ -375,12 +376,12 @@ static void __devexit gemtek_pci_remove( struct pci_dev *pci_dev )
        kfree( card->videodev );
 
        release_region( card->iobase, card->length );
-       
+
        if ( mx )
                gemtek_pci_mute( card );
 
        kfree( card );
-       
+
        pci_set_drvdata( pci_dev, NULL );
 }
 
index 47173be97b9fa5dbd74d84e6e5ebce0007393609..162f37d8bf9623f52d9e46dc120089c53879b628 100644 (file)
@@ -6,7 +6,7 @@
  * Besides the protocol changes, this is mostly a copy of:
  *
  *    RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
- * 
+ *
  *    Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
  *    Converted to new API by Alan Cox <Alan.Cox@linux.org>
  *    Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
@@ -22,6 +22,7 @@
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev.h>    /* kernel radio structs         */
+#include <media/v4l2-common.h>
 #include <linux/config.h>      /* CONFIG_RADIO_GEMTEK_PORT     */
 #include <linux/spinlock.h>
 
@@ -29,7 +30,7 @@
 #define CONFIG_RADIO_GEMTEK_PORT -1
 #endif
 
-static int io = CONFIG_RADIO_GEMTEK_PORT; 
+static int io = CONFIG_RADIO_GEMTEK_PORT;
 static int radio_nr = -1;
 static spinlock_t lock;
 
@@ -48,7 +49,7 @@ struct gemtek_device
  */
 static void gemtek_mute(struct gemtek_device *dev)
 {
-        if(dev->muted)
+       if(dev->muted)
                return;
        spin_lock(&lock);
        outb(0x10, io);
@@ -94,20 +95,20 @@ static int gemtek_setfreq(struct gemtek_device *dev, unsigned long freq)
        freq /= 100000;
 
        spin_lock(&lock);
-       
+
        /* 2 start bits */
        outb_p(0x03, io);
        udelay(5);
        outb_p(0x07, io);
        udelay(5);
 
-        /* 28 frequency bits (lsb first) */
+       /* 28 frequency bits (lsb first) */
        for (i = 0; i < 14; i++)
                if (freq & (1 << i))
                        one();
                else
                        zero();
-        /* 36 unknown bits */
+       /* 36 unknown bits */
        for (i = 0; i < 11; i++)
                zero();
        one();
@@ -123,7 +124,7 @@ static int gemtek_setfreq(struct gemtek_device *dev, unsigned long freq)
        udelay(5);
 
        spin_unlock(&lock);
-       
+
        return 0;
 }
 
@@ -159,7 +160,7 @@ static int gemtek_do_ioctl(struct inode *inode, struct file *file,
                case VIDIOCGTUNER:
                {
                        struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */ 
+                       if(v->tuner)    /* Only 1 tuner */
                                return -EINVAL;
                        v->rangelow=87*16000;
                        v->rangehigh=108*16000;
@@ -193,25 +194,25 @@ static int gemtek_do_ioctl(struct inode *inode, struct file *file,
                        return 0;
                }
                case VIDIOCGAUDIO:
-               {       
+               {
                        struct video_audio *v = arg;
                        memset(v,0, sizeof(*v));
                        v->flags|=VIDEO_AUDIO_MUTABLE;
                        v->volume=1;
                        v->step=65535;
                        strcpy(v->name, "Radio");
-                       return 0;                       
+                       return 0;
                }
                case VIDIOCSAUDIO:
                {
                        struct video_audio *v = arg;
-                       if(v->audio) 
+                       if(v->audio)
                                return -EINVAL;
 
-                       if(v->flags&VIDEO_AUDIO_MUTE) 
+                       if(v->flags&VIDEO_AUDIO_MUTE)
                                gemtek_mute(rt);
                        else
-                               gemtek_unmute(rt);
+                               gemtek_unmute(rt);
 
                        return 0;
                }
@@ -254,14 +255,14 @@ static int __init gemtek_init(void)
                return -EINVAL;
        }
 
-       if (!request_region(io, 4, "gemtek")) 
+       if (!request_region(io, 4, "gemtek"))
        {
                printk(KERN_ERR "gemtek: port 0x%x already in use\n", io);
                return -EBUSY;
        }
 
        gemtek_radio.priv=&gemtek_unit;
-       
+
        if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr)==-1)
        {
                release_region(io, 4);
@@ -274,7 +275,7 @@ static int __init gemtek_init(void)
        /* this is _maybe_ unnecessary */
        outb(0x01, io);
 
-       /* mute card - prevents noisy bootups */
+       /* mute card - prevents noisy bootups */
        gemtek_unit.muted = 0;
        gemtek_mute(&gemtek_unit);
 
index 39c1d9118636af1a03804a42cde2f0559d2ca173..fcfa6c9fe2256df1b949014831ad0b3e000819e5 100644 (file)
@@ -2,7 +2,7 @@
  * (c) 2000 A. Tlalka, atlka@pg.gda.pl
  * Notes on the hardware
  *
- *  + Frequency control is done digitally 
+ *  + Frequency control is done digitally
  *  + No volume control - only mute/unmute - you have to use Aux line volume
  *  control on Maestro card to set the volume
  *  + Radio status (tuned/not_tuned and stereo/mono) is valid some time after
@@ -26,7 +26,7 @@
 #include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/videodev.h>
-
+#include <media/v4l2-common.h>
 
 #define DRIVER_VERSION "0.05"
 
@@ -103,7 +103,7 @@ static struct video_device maestro_radio = {
 struct radio_device {
        u16     io,     /* base of Maestro card radio io (GPIO_DATA)*/
                muted,  /* VIDEO_AUDIO_MUTE */
-               stereo, /* VIDEO_TUNER_STEREO_ON */     
+               stereo, /* VIDEO_TUNER_STEREO_ON */
                tuned;  /* signal strength (0 or 0xffff) */
        struct mutex lock;
 };
@@ -122,14 +122,14 @@ static u32 radio_bits_get(struct radio_device *dev)
        for (l=24;l--;) {
                outw(STR_CLK, io);              /* HI state */
                udelay(2);
-               if(!l) 
+               if(!l)
                        dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff;
                outw(0, io);                    /* LO state */
                udelay(2);
                data <<= 1;                     /* shift data */
                rdata = inw(io);
                if(!l)
-                       dev->stereo =  rdata & STR_MOST ? 
+                       dev->stereo =  rdata & STR_MOST ?
                        0 : VIDEO_TUNER_STEREO_ON;
                else
                        if(rdata & STR_DATA)
index f0bf47bcb64cfd3859b98625b9041761f46458e2..f93d7afe7304c97d1159967f20e5ee130c41f608 100644 (file)
@@ -1,15 +1,15 @@
-/* 
- * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux 
+/*
+ * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux
  * (C) 2001 Dimitromanolakis Apostolos <apdim@grecian.net>
  *
  * Based in the radio Maestro PCI driver. Actually it uses the same chip
  * for radio but different pci controller.
  *
  * I didn't have any specs I reversed engineered the protocol from
- * the windows driver (radio.dll). 
+ * the windows driver (radio.dll).
  *
  * The card uses the TEA5757 chip that includes a search function but it
- * is useless as I haven't found any way to read back the frequency. If 
+ * is useless as I haven't found any way to read back the frequency. If
  * anybody does please mail me.
  *
  * For the pdf file see:
@@ -24,7 +24,7 @@
  *     - tiding up
  *     - removed support for multiple devices as it didn't work anyway
  *
- * BUGS: 
+ * BUGS:
  *   - card unmutes if you change frequency
  *
  */
@@ -41,6 +41,7 @@
 
 #include <linux/pci.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 
 /* version 0.75      Sun Feb  4 22:51:27 EET 2001 */
 #define DRIVER_VERSION "0.75"
@@ -80,7 +81,7 @@ static struct file_operations maxiradio_fops = {
        .owner          = THIS_MODULE,
        .open           = video_exclusive_open,
        .release        = video_exclusive_release,
-       .ioctl          = radio_ioctl,
+       .ioctl          = radio_ioctl,
        .compat_ioctl   = v4l_compat_ioctl32,
        .llseek         = no_llseek,
 };
@@ -97,11 +98,11 @@ static struct radio_device
 {
        __u16   io,     /* base of radio io */
                muted,  /* VIDEO_AUDIO_MUTE */
-               stereo, /* VIDEO_TUNER_STEREO_ON */     
+               stereo, /* VIDEO_TUNER_STEREO_ON */
                tuned;  /* signal strength (0 or 0xffff) */
-               
+
        unsigned long freq;
-       
+
        struct mutex lock;
 } radio_unit = {0, 0, 0, 0, };
 
@@ -114,7 +115,7 @@ static void outbit(unsigned long bit, __u16 io)
                        outb(  power|wren|data|clk ,io); udelay(4);
                        outb(  power|wren|data     ,io); udelay(4);
                }
-       else    
+       else
                {
                        outb(  power|wren          ,io); udelay(4);
                        outb(  power|wren|clk      ,io); udelay(4);
@@ -132,12 +133,12 @@ static void set_freq(__u16 io, __u32 data)
 {
        unsigned long int si;
        int bl;
-       
+
        /* TEA5757 shift register bits (see pdf) */
 
-       outbit(0,io); // 24  search 
+       outbit(0,io); // 24  search
        outbit(1,io); // 23  search up/down
-       
+
        outbit(0,io); // 22  stereo/mono
 
        outbit(0,io); // 21  band
@@ -145,24 +146,24 @@ static void set_freq(__u16 io, __u32 data)
 
        outbit(0,io); // 19  port ?
        outbit(0,io); // 18  port ?
-       
+
        outbit(0,io); // 17  search level
        outbit(0,io); // 16  search level
+
        si = 0x8000;
        for(bl = 1; bl <= 16 ; bl++) { outbit(data & si,io); si >>=1; }
-       
+
        outb(power,io);
 }
 
 static int get_stereo(__u16 io)
-{      
+{
        outb(power,io); udelay(4);
        return !(inb(io) & mo_st);
 }
 
 static int get_tune(__u16 io)
-{      
+{
        outb(power+clk,io); udelay(4);
        return !(inb(io) & mo_st);
 }
@@ -177,7 +178,7 @@ static inline int radio_function(struct inode *inode, struct file *file,
        switch(cmd) {
                case VIDIOCGCAP: {
                        struct video_capability *v = arg;
-                       
+
                        memset(v,0,sizeof(*v));
                        strcpy(v->name, "Maxi Radio FM2000 radio");
                        v->type=VID_TYPE_TUNER;
@@ -186,22 +187,22 @@ static inline int radio_function(struct inode *inode, struct file *file,
                }
                case VIDIOCGTUNER: {
                        struct video_tuner *v = arg;
-                       
+
                        if(v->tuner)
                                return -EINVAL;
-                               
+
                        card->stereo = 0xffff * get_stereo(card->io);
                        card->tuned = 0xffff * get_tune(card->io);
-                       
+
                        v->flags = VIDEO_TUNER_LOW | card->stereo;
                        v->signal = card->tuned;
-                       
+
                        strcpy(v->name, "FM");
-                       
+
                        v->rangelow = FREQ_LO;
                        v->rangehigh = FREQ_HI;
                        v->mode = VIDEO_MODE_AUTO;
-                       
+
                        return 0;
                }
                case VIDIOCSTUNER: {
@@ -212,13 +213,13 @@ static inline int radio_function(struct inode *inode, struct file *file,
                }
                case VIDIOCGFREQ: {
                        unsigned long *freq = arg;
-                       
+
                        *freq = card->freq;
                        return 0;
                }
                case VIDIOCSFREQ: {
                        unsigned long *freq = arg;
-                       
+
                        if (*freq < FREQ_LO || *freq > FREQ_HI)
                                return -EINVAL;
                        card->freq = *freq;
@@ -226,18 +227,18 @@ static inline int radio_function(struct inode *inode, struct file *file,
                        msleep(125);
                        return 0;
                }
-               case VIDIOCGAUDIO: {    
+               case VIDIOCGAUDIO: {
                        struct video_audio *v = arg;
                        memset(v,0,sizeof(*v));
                        strcpy(v->name, "Radio");
                        v->flags=VIDEO_AUDIO_MUTABLE | card->muted;
                        v->mode=VIDEO_SOUND_STEREO;
-                       return 0;               
+                       return 0;
                }
-               
+
                case VIDIOCSAUDIO: {
                        struct video_audio *v = arg;
-                       
+
                        if(v->audio)
                                return -EINVAL;
                        card->muted = v->flags & VIDEO_AUDIO_MUTE;
@@ -249,13 +250,13 @@ static inline int radio_function(struct inode *inode, struct file *file,
                }
                case VIDIOCGUNIT: {
                        struct video_unit *v = arg;
-                       
+
                        v->video=VIDEO_NO_UNIT;
                        v->vbi=VIDEO_NO_UNIT;
                        v->radio=dev->minor;
                        v->audio=0;
                        v->teletext=VIDEO_NO_UNIT;
-                       return 0;               
+                       return 0;
                }
                default: return -ENOIOCTLCMD;
        }
@@ -267,7 +268,7 @@ static int radio_ioctl(struct inode *inode, struct file *file,
        struct video_device *dev = video_devdata(file);
        struct radio_device *card=dev->priv;
        int ret;
-       
+
        mutex_lock(&card->lock);
        ret = video_usercopy(inode, file, cmd, arg, radio_function);
        mutex_unlock(&card->lock);
@@ -282,21 +283,21 @@ MODULE_LICENSE("GPL");
 static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        if(!request_region(pci_resource_start(pdev, 0),
-                          pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) {
-               printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n");
-               goto err_out;
+                          pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) {
+               printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n");
+               goto err_out;
        }
 
        if (pci_enable_device(pdev))
-               goto err_out_free_region;
+               goto err_out_free_region;
 
        radio_unit.io = pci_resource_start(pdev, 0);
        mutex_init(&radio_unit.lock);
        maxiradio_radio.priv = &radio_unit;
 
        if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
-               printk("radio-maxiradio: can't register device!");
-               goto err_out_free_region;
+               printk("radio-maxiradio: can't register device!");
+               goto err_out_free_region;
        }
 
        printk(KERN_INFO "radio-maxiradio: version "
index 28a47c9e7a819a4791d122d02380ca12e46ffd40..5b68ac4c7322e710c112bb787a996ef621f48e04 100644 (file)
@@ -1,5 +1,5 @@
 /* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
- * 
+ *
  * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
  * Converted to new API by Alan Cox <Alan.Cox@linux.org>
  * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
@@ -15,6 +15,7 @@
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev.h>    /* kernel radio structs         */
+#include <media/v4l2-common.h>
 #include <linux/config.h>      /* CONFIG_RADIO_RTRACK2_PORT    */
 #include <linux/spinlock.h>
 
@@ -22,7 +23,7 @@
 #define CONFIG_RADIO_RTRACK2_PORT -1
 #endif
 
-static int io = CONFIG_RADIO_RTRACK2_PORT; 
+static int io = CONFIG_RADIO_RTRACK2_PORT;
 static int radio_nr = -1;
 static spinlock_t lock;
 
@@ -38,7 +39,7 @@ struct rt_device
 
 static void rt_mute(struct rt_device *dev)
 {
-        if(dev->muted)
+       if(dev->muted)
                return;
        spin_lock(&lock);
        outb(1, io);
@@ -58,14 +59,14 @@ static void rt_unmute(struct rt_device *dev)
 
 static void zero(void)
 {
-        outb_p(1, io);
+       outb_p(1, io);
        outb_p(3, io);
        outb_p(1, io);
 }
 
 static void one(void)
 {
-        outb_p(5, io);
+       outb_p(5, io);
        outb_p(7, io);
        outb_p(5, io);
 }
@@ -75,7 +76,7 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq)
        int i;
 
        freq = freq / 200 + 856;
-       
+
        spin_lock(&lock);
 
        outb_p(0xc8, io);
@@ -94,7 +95,7 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq)
        outb_p(0xc8, io);
        if (!dev->muted)
                outb_p(0, io);
-               
+
        spin_unlock(&lock);
        return 0;
 }
@@ -127,7 +128,7 @@ static int rt_do_ioctl(struct inode *inode, struct file *file,
                case VIDIOCGTUNER:
                {
                        struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */ 
+                       if(v->tuner)    /* Only 1 tuner */
                                return -EINVAL;
                        v->rangelow=88*16000;
                        v->rangehigh=108*16000;
@@ -159,25 +160,25 @@ static int rt_do_ioctl(struct inode *inode, struct file *file,
                        return 0;
                }
                case VIDIOCGAUDIO:
-               {       
+               {
                        struct video_audio *v = arg;
                        memset(v,0, sizeof(*v));
                        v->flags|=VIDEO_AUDIO_MUTABLE;
                        v->volume=1;
                        v->step=65535;
                        strcpy(v->name, "Radio");
-                       return 0;                       
+                       return 0;
                }
                case VIDIOCSAUDIO:
                {
                        struct video_audio *v = arg;
-                       if(v->audio) 
+                       if(v->audio)
                                return -EINVAL;
 
-                       if(v->flags&VIDEO_AUDIO_MUTE) 
+                       if(v->flags&VIDEO_AUDIO_MUTE)
                                rt_mute(rt);
                        else
-                               rt_unmute(rt);
+                               rt_unmute(rt);
 
                        return 0;
                }
@@ -219,7 +220,7 @@ static int __init rtrack2_init(void)
                printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n");
                return -EINVAL;
        }
-       if (!request_region(io, 4, "rtrack2")) 
+       if (!request_region(io, 4, "rtrack2"))
        {
                printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io);
                return -EBUSY;
@@ -227,16 +228,16 @@ static int __init rtrack2_init(void)
 
        rtrack2_radio.priv=&rtrack2_unit;
 
-       spin_lock_init(&lock);  
+       spin_lock_init(&lock);
        if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr)==-1)
        {
                release_region(io, 4);
                return -EINVAL;
        }
-               
+
        printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n");
 
-       /* mute card - prevents noisy bootups */
+       /* mute card - prevents noisy bootups */
        outb(1, io);
        rtrack2_unit.muted = 1;
 
index 53073b424107ba5972478f6773bb096c11e7b554..efee6e339d15b0b7d7110160640e2c2ca35536e1 100644 (file)
@@ -12,7 +12,7 @@
  *  Frequency control is done digitally -- ie out(port,encodefreq(95.8));
  *  No volume control - only mute/unmute - you have to use line volume
  *  control on SB-part of SF16FMI
- *  
+ *
  */
 
 #include <linux/kernel.h>      /* __setup                      */
@@ -21,6 +21,7 @@
 #include <linux/ioport.h>      /* request_region               */
 #include <linux/delay.h>       /* udelay                       */
 #include <linux/videodev.h>    /* kernel radio structs         */
+#include <media/v4l2-common.h>
 #include <linux/isapnp.h>
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 struct fmi_device
 {
        int port;
-        int curvol; /* 1 or 0 */
-        unsigned long curfreq; /* freq in kHz */
-        __u32 flags;
+       int curvol; /* 1 or 0 */
+       unsigned long curfreq; /* freq in kHz */
+       __u32 flags;
 };
 
-static int io = -1; 
+static int io = -1;
 static int radio_nr = -1;
 static struct pnp_dev *dev = NULL;
 static struct mutex lock;
 
 /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
 /* It is only useful to give freq in intervall of 800 (=0.05Mhz),
- * other bits will be truncated, e.g 92.7400016 -> 92.7, but 
+ * other bits will be truncated, e.g 92.7400016 -> 92.7, but
  * 92.7400017 -> 92.75
  */
 #define RSF16_ENCODE(x)        ((x)/800+214)
@@ -51,7 +52,7 @@ static struct mutex lock;
 static void outbits(int bits, unsigned int data, int port)
 {
        while(bits--) {
-               if(data & 1) {
+               if(data & 1) {
                        outb(5, port);
                        udelay(6);
                        outb(7, port);
@@ -101,7 +102,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev)
        int res;
        int myport = dev->port;
 
-       
+
        mutex_lock(&lock);
        val = dev->curvol ? 0x08 : 0x00;        /* unmute/mute */
        outb(val, myport);
@@ -109,7 +110,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev)
        msleep(143);            /* was schedule_timeout(HZ/7) */
        res = (int)inb(myport+1);
        outb(val, myport);
-       
+
        mutex_unlock(&lock);
        return (res & 2) ? 0 : 0xFFFF;
 }
@@ -119,7 +120,7 @@ static int fmi_do_ioctl(struct inode *inode, struct file *file,
 {
        struct video_device *dev = video_devdata(file);
        struct fmi_device *fmi=dev->priv;
-       
+
        switch(cmd)
        {
                case VIDIOCGCAP:
@@ -174,18 +175,18 @@ static int fmi_do_ioctl(struct inode *inode, struct file *file,
                                return -EINVAL;
                        /*rounding in steps of 800 to match th freq
                          that will be used */
-                       fmi->curfreq = (*freq/800)*800; 
+                       fmi->curfreq = (*freq/800)*800;
                        fmi_setfreq(fmi);
                        return 0;
                }
                case VIDIOCGAUDIO:
-               {       
+               {
                        struct video_audio *v = arg;
                        memset(v,0,sizeof(*v));
                        v->flags=( (!fmi->curvol)*VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE);
                        strcpy(v->name, "Radio");
                        v->mode=VIDEO_SOUND_STEREO;
-                       return 0;                       
+                       return 0;
                }
                case VIDIOCSAUDIO:
                {
@@ -193,19 +194,19 @@ static int fmi_do_ioctl(struct inode *inode, struct file *file,
                        if(v->audio)
                                return -EINVAL;
                        fmi->curvol= v->flags&VIDEO_AUDIO_MUTE ? 0 : 1;
-                       fmi->curvol ? 
+                       fmi->curvol ?
                                fmi_unmute(fmi->port) : fmi_mute(fmi->port);
                        return 0;
                }
-               case VIDIOCGUNIT:
+               case VIDIOCGUNIT:
                {
-                               struct video_unit *v = arg;
+                       struct video_unit *v = arg;
                        v->video=VIDEO_NO_UNIT;
                        v->vbi=VIDEO_NO_UNIT;
                        v->radio=dev->minor;
                        v->audio=0; /* How do we find out this??? */
                        v->teletext=VIDEO_NO_UNIT;
-                       return 0;                       
+                       return 0;
                }
                default:
                        return -ENOIOCTLCMD;
@@ -295,14 +296,14 @@ static int __init fmi_init(void)
        fmi_unit.curfreq = 0;
        fmi_unit.flags = VIDEO_TUNER_LOW;
        fmi_radio.priv = &fmi_unit;
-       
+
        mutex_init(&lock);
-       
+
        if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) == -1) {
                release_region(io, 2);
                return -EINVAL;
        }
-               
+
        printk(KERN_INFO "SF16FMx radio card driver at 0x%x\n", io);
        /* mute card - prevents noisy bootups */
        fmi_mute(io);
index bcebd8cb19ad43e0accfb4aa97088d27781837d1..3483b2c7bc9d70488c26cb99b9a2f696192c03e2 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev.h>    /* kernel radio structs         */
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 static struct mutex lock;
@@ -202,7 +203,7 @@ static int fmr2_setvolume(struct fmr2_device *dev)
 }
 
 static int fmr2_do_ioctl(struct inode *inode, struct file *file,
-                      unsigned int cmd, void *arg)
+                     unsigned int cmd, void *arg)
 {
        struct video_device *dev = video_devdata(file);
        struct fmr2_device *fmr2 = dev->priv;
@@ -344,7 +345,7 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file,
 }
 
 static int fmr2_ioctl(struct inode *inode, struct file *file,
-                      unsigned int cmd, unsigned long arg)
+                     unsigned int cmd, unsigned long arg)
  {
        return video_usercopy(inode, file, cmd, arg, fmr2_do_ioctl);
 }
index fcfde2e4f1958d47d1c4ec34d69f610cb1733e0b..dfba4ae596cd342abb3e737234274d4488ae4e23 100644 (file)
@@ -2,11 +2,11 @@
  * (c) 1999 R. Offermanns (rolf@offermanns.de)
  * based on the aimslab radio driver from M. Kirkwood
  * many thanks to Michael Becker and Friedhelm Birth (from TerraTec)
- * 
+ *
  *
  * History:
  * 1999-05-21  First preview release
- * 
+ *
  *  Notes on the hardware:
  *  There are two "main" chips on the card:
  *  - Philips OM5610 (http://www-us.semiconductors.philips.com/acrobat/datasheets/OM5610_2.pdf)
@@ -20,7 +20,7 @@
  *  (as soon i have understand how to get started :)
  *  If you can help me out with that, please contact me!!
  *
- *  
+ *
  */
 
 #include <linux/module.h>      /* Modules                      */
@@ -30,6 +30,7 @@
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev.h>    /* kernel radio structs         */
+#include <media/v4l2-common.h>
 #include <linux/config.h>      /* CONFIG_RADIO_TERRATEC_PORT   */
 #include <linux/spinlock.h>
 
@@ -49,7 +50,7 @@
 #define WRT_EN         0x10
 /*******************************************************************/
 
-static int io = CONFIG_RADIO_TERRATEC_PORT; 
+static int io = CONFIG_RADIO_TERRATEC_PORT;
 static int radio_nr = -1;
 static spinlock_t lock;
 
@@ -88,15 +89,15 @@ static void tt_mute(struct tt_device *dev)
 
 static int tt_setvol(struct tt_device *dev, int vol)
 {
-       
+
 //     printk(KERN_ERR "setvol called, vol = %d\n", vol);
 
        if(vol == dev->curvol) {        /* requested volume = current */
                if (dev->muted) {       /* user is unmuting the card  */
                        dev->muted = 0;
                        cardWriteVol(vol);      /* enable card */
-               }       
-       
+               }
+
                return 0;
        }
 
@@ -107,9 +108,9 @@ static int tt_setvol(struct tt_device *dev, int vol)
        }
 
        dev->muted = 0;
-       
+
        cardWriteVol(vol);
-        
+
        dev->curvol = vol;
 
        return 0;
@@ -121,13 +122,13 @@ static int tt_setvol(struct tt_device *dev, int vol)
 /* many more or less strange things are going on here, but hey, it works :) */
 
 static int tt_setfreq(struct tt_device *dev, unsigned long freq1)
-{      
+{
        int freq;
        int i;
        int p;
        int  temp;
        long rest;
-     
+
        unsigned char buffer[25];               /* we have to bit shift 25 registers */
        freq = freq1/160;                       /* convert the freq. to a nice to handle value */
        for(i=24;i>-1;i--)
@@ -142,9 +143,9 @@ static int tt_setfreq(struct tt_device *dev, unsigned long freq1)
        {
                if (rest%temp  == rest)
                        buffer[i] = 0;
-               else 
+               else
                {
-                       buffer[i] = 1; 
+                       buffer[i] = 1;
                        rest = rest-temp;
                }
                i--;
@@ -153,10 +154,10 @@ static int tt_setfreq(struct tt_device *dev, unsigned long freq1)
        }
 
        spin_lock(&lock);
-       
+
        for (i=24;i>-1;i--)                     /* bit shift the values to the radiocard */
        {
-               if (buffer[i]==1) 
+               if (buffer[i]==1)
                {
                        outb(WRT_EN|DATA, BASEPORT);
                        outb(WRT_EN|DATA|CLK_ON  , BASEPORT);
@@ -168,11 +169,11 @@ static int tt_setfreq(struct tt_device *dev, unsigned long freq1)
                        outb(WRT_EN|0x00|CLK_ON  , BASEPORT);
                }
        }
-       outb(0x00, BASEPORT);     
-       
+       outb(0x00, BASEPORT);
+
        spin_unlock(&lock);
-  
-       return 0;
+
+       return 0;
 }
 
 static int tt_getsigstr(struct tt_device *dev)         /* TODO */
@@ -190,7 +191,7 @@ static int tt_do_ioctl(struct inode *inode, struct file *file,
 {
        struct video_device *dev = video_devdata(file);
        struct tt_device *tt=dev->priv;
-       
+
        switch(cmd)
        {
                case VIDIOCGCAP:
@@ -206,7 +207,7 @@ static int tt_do_ioctl(struct inode *inode, struct file *file,
                case VIDIOCGTUNER:
                {
                        struct video_tuner *v = arg;
-                       if(v->tuner)    /* Only 1 tuner */ 
+                       if(v->tuner)    /* Only 1 tuner */
                                return -EINVAL;
                        v->rangelow=(87*16000);
                        v->rangehigh=(108*16000);
@@ -238,21 +239,21 @@ static int tt_do_ioctl(struct inode *inode, struct file *file,
                        return 0;
                }
                case VIDIOCGAUDIO:
-               {       
+               {
                        struct video_audio *v = arg;
                        memset(v,0, sizeof(*v));
                        v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
                        v->volume=tt->curvol * 6554;
                        v->step=6554;
                        strcpy(v->name, "Radio");
-                       return 0;                       
+                       return 0;
                }
                case VIDIOCSAUDIO:
                {
                        struct video_audio *v = arg;
-                       if(v->audio) 
+                       if(v->audio)
                                return -EINVAL;
-                       if(v->flags&VIDEO_AUDIO_MUTE) 
+                       if(v->flags&VIDEO_AUDIO_MUTE)
                                tt_mute(tt);
                        else
                                tt_setvol(tt,v->volume/6554);
@@ -296,25 +297,25 @@ static int __init terratec_init(void)
                printk(KERN_ERR "You must set an I/O address with io=0x???\n");
                return -EINVAL;
        }
-       if (!request_region(io, 2, "terratec")) 
+       if (!request_region(io, 2, "terratec"))
        {
                printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io);
                return -EBUSY;
        }
 
        terratec_radio.priv=&terratec_unit;
-       
+
        spin_lock_init(&lock);
-       
+
        if(video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr)==-1)
        {
                release_region(io,2);
                return -EINVAL;
        }
-               
+
        printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver.\n");
 
-       /* mute card - prevents noisy bootups */
+       /* mute card - prevents noisy bootups */
 
        /* this ensures that the volume is all the way down  */
        cardWriteVol(0);
@@ -334,7 +335,7 @@ static void __exit terratec_cleanup_module(void)
 {
        video_unregister_device(&terratec_radio);
        release_region(io,2);
-       printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n");     
+       printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n");
 }
 
 module_init(terratec_init);
index 5a099a50d4d060e1af66e7a31711d7b3182fb2c8..8da4badc22b47f399ae8c3ce3f9e80e60a3f127c 100644 (file)
@@ -1,14 +1,14 @@
-/* radio-trust.c - Trust FM Radio card driver for Linux 2.2 
+/* radio-trust.c - Trust FM Radio card driver for Linux 2.2
  * by Eric Lammerts <eric@scintilla.utwente.nl>
  *
  * Based on radio-aztech.c. Original notes:
  *
- * Adapted to support the Video for Linux API by 
+ * Adapted to support the Video for Linux API by
  * Russell Kroll <rkroll@exploits.org>.  Based on original tuner code by:
  *
  * Quay Ly
  * Donald Song
- * Jason Lewis      (jlewis@twilight.vtc.vsc.edu) 
+ * Jason Lewis      (jlewis@twilight.vtc.vsc.edu)
  * Scott McGrath    (smcgrath@twilight.vtc.vsc.edu)
  * William McGrath  (wmcgrath@twilight.vtc.vsc.edu)
  *
@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/config.h>      /* CONFIG_RADIO_TRUST_PORT      */
 
 /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
@@ -30,7 +31,7 @@
 #define CONFIG_RADIO_TRUST_PORT -1
 #endif
 
-static int io = CONFIG_RADIO_TRUST_PORT; 
+static int io = CONFIG_RADIO_TRUST_PORT;
 static int radio_nr = -1;
 static int ioval = 0xf;
 static __u16 curvol;
@@ -135,7 +136,7 @@ static void tr_setmute(int mute)
 static int tr_getsigstr(void)
 {
        int i, v;
-       
+
        for(i = 0, v = 0; i < 100; i++) v |= inb(io);
        return (v & 1)? 0 : 0xffff;
 }
@@ -175,7 +176,7 @@ static int tr_do_ioctl(struct inode *inode, struct file *file,
                {
                        struct video_tuner *v = arg;
 
-                       if(v->tuner)    /* Only 1 tuner */ 
+                       if(v->tuner)    /* Only 1 tuner */
                                return -EINVAL;
 
                        v->rangelow = 87500 * 16;
@@ -211,28 +212,28 @@ static int tr_do_ioctl(struct inode *inode, struct file *file,
                        return 0;
                }
                case VIDIOCGAUDIO:
-               {       
+               {
                        struct video_audio *v = arg;
 
                        memset(v,0, sizeof(*v));
                        v->flags = VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME |
-                                 VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE;
+                                 VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE;
                        v->mode = curstereo? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
                        v->volume = curvol * 2048;
                        v->step = 2048;
                        v->bass = curbass * 4370;
                        v->treble = curtreble * 4370;
-                       
+
                        strcpy(v->name, "Trust FM Radio");
-                       return 0;                       
+                       return 0;
                }
                case VIDIOCSAUDIO:
                {
                        struct video_audio *v = arg;
 
-                       if(v->audio) 
+                       if(v->audio)
                                return -EINVAL;
-                       tr_setvol(v->volume);                                   
+                       tr_setvol(v->volume);
                        tr_setbass(v->bass);
                        tr_settreble(v->treble);
                        tr_setstereo(v->mode & VIDEO_SOUND_STEREO);
@@ -292,7 +293,7 @@ static int __init trust_init(void)
        write_i2c(2, TDA7318_ADDR, 0xe0);       /* speaker att. RR = 0 dB */
        write_i2c(2, TDA7318_ADDR, 0x40);       /* stereo 1 input, gain = 18.75 dB */
 
-       tr_setvol(0x8000);                                      
+       tr_setvol(0x8000);
        tr_setbass(0x8000);
        tr_settreble(0x8000);
        tr_setstereo(1);
index e50955836d6b1a829dc273846157a443866c9d76..edd0122886693183f89245d799131869be0c0475 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/io.h>            /* outb, outb_p                   */
 #include <asm/uaccess.h>       /* copy to/from user              */
 #include <linux/videodev.h>    /* kernel radio structs           */
+#include <media/v4l2-common.h>
 #include <linux/config.h>      /* CONFIG_RADIO_TYPHOON_*         */
 
 #define BANNER "Typhoon Radio Card driver v0.1\n"
@@ -361,8 +362,8 @@ static int __init typhoon_init(void)
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
        if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL,
-                                   typhoon_get_info)) 
-               printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
+                                   typhoon_get_info))
+               printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
 #endif
 
        return 0;
index 7bf1a4264891deca514dd6a5465497b46e02919d..59b86a6b4b0e745a008276ede9a2a1d50e30e260 100644 (file)
@@ -1,7 +1,7 @@
 /* zoltrix radio plus driver for Linux radio support
  * (c) 1998 C. van Schaik <carl@leg.uct.ac.za>
  *
- * BUGS  
+ * BUGS
  *  Due to the inconsistency in reading from the signal flags
  *  it is difficult to get an accurate tuned signal.
  *
@@ -14,7 +14,7 @@
  *
  * 1999-05-06 - (C. van Schaik)
  *           - Make signal strength and stereo scans
- *             kinder to cpu while in delay
+ *             kinder to cpu while in delay
  * 1999-01-05 - (C. van Schaik)
  *           - Changed tuning to 1/160Mhz accuracy
  *           - Added stereo support
@@ -33,6 +33,7 @@
 #include <asm/io.h>            /* outb, outb_p                   */
 #include <asm/uaccess.h>       /* copy to/from user              */
 #include <linux/videodev.h>    /* kernel radio structs           */
+#include <media/v4l2-common.h>
 #include <linux/config.h>      /* CONFIG_RADIO_ZOLTRIX_PORT      */
 
 #ifndef CONFIG_RADIO_ZOLTRIX_PORT
@@ -105,7 +106,7 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq)
        i = 45;
 
        mutex_lock(&dev->lock);
-       
+
        outb(0, io);
        outb(0, io);
        inb(io + 3);            /* Zoltrix needs to be read to confirm */
@@ -139,8 +140,8 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq)
        udelay(1000);
        inb(io+2);
 
-        udelay(1000);
-        
+       udelay(1000);
+
        if (dev->muted)
        {
                outb(0, io);
@@ -148,12 +149,12 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq)
                inb(io + 3);
                udelay(1000);
        }
-       
+
        mutex_unlock(&dev->lock);
-       
+
        if(!dev->muted)
        {
-               zol_setvol(dev, dev->curvol);
+               zol_setvol(dev, dev->curvol);
        }
        return 0;
 }
@@ -174,14 +175,14 @@ static int zol_getsigstr(struct zol_device *dev)
        b = inb(io);
 
        mutex_unlock(&dev->lock);
-       
+
        if (a != b)
                return (0);
 
-        if ((a == 0xcf) || (a == 0xdf)  /* I found this out by playing */
+       if ((a == 0xcf) || (a == 0xdf)  /* I found this out by playing */
                || (a == 0xef))       /* with a binary scanner on the card io */
                return (1);
-       return (0);
+       return (0);
 }
 
 static int zol_is_stereo (struct zol_device *dev)
@@ -189,7 +190,7 @@ static int zol_is_stereo (struct zol_device *dev)
        int x1, x2;
 
        mutex_lock(&dev->lock);
-       
+
        outb(0x00, io);
        outb(dev->curvol, io);
        msleep(20);
@@ -199,7 +200,7 @@ static int zol_is_stereo (struct zol_device *dev)
        x2 = inb(io);
 
        mutex_unlock(&dev->lock);
-       
+
        if ((x1 == x2) && (x1 == 0xcf))
                return 1;
        return 0;
@@ -226,7 +227,7 @@ static int zol_do_ioctl(struct inode *inode, struct file *file,
        case VIDIOCGTUNER:
                {
                        struct video_tuner *v = arg;
-                       if (v->tuner)   
+                       if (v->tuner)
                                return -EINVAL;
                        strcpy(v->name, "FM");
                        v->rangelow = (int) (88.0 * 16000);
@@ -351,7 +352,7 @@ static int __init zoltrix_init(void)
        printk(KERN_INFO "Zoltrix Radio Plus card driver.\n");
 
        mutex_init(&zoltrix_unit.lock);
-       
+
        /* mute card - prevents noisy bootups */
 
        /* this ensures that the volume is all the way down  */
index 6b41970185610780327355a0f4d4af6f5a852e8e..824a63c92629ddf8566ec760f1e8bb314d4ff545 100644 (file)
@@ -224,6 +224,12 @@ config VIDEO_ZORAN_LML33R10
          support for the Linux Media Labs LML33R10 MJPEG capture/playback
          card.
 
+config VIDEO_ZORAN_AVS6EYES
+       tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
+       depends on VIDEO_ZORAN && EXPERIMENTAL && VIDEO_V4L1
+       help
+         Support for the AverMedia 6 Eyes video surveillance card.
+
 config VIDEO_ZR36120
        tristate "Zoran ZR36120/36125 Video For Linux"
        depends on PCI && I2C && VIDEO_V4L1 && BROKEN
@@ -306,17 +312,6 @@ config VIDEO_HEXIUM_GEMINI
 
 source "drivers/media/video/cx88/Kconfig"
 
-config VIDEO_OVCAMCHIP
-       tristate "OmniVision Camera Chip support"
-       depends on I2C && VIDEO_V4L1
-       ---help---
-         Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
-         This driver is intended to be used with the ov511 and w9968cf USB
-         camera drivers.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ovcamchip.
-
 config VIDEO_M32R_AR
        tristate "AR devices"
        depends on M32R && VIDEO_V4L1
@@ -357,6 +352,15 @@ config VIDEO_CS53L32A
          To compile this driver as a module, choose M here: the
          module will be called cs53l32a.
 
+config VIDEO_TLV320AIC23B
+       tristate "Texas Instruments TLV320AIC23B audio codec"
+       depends on VIDEO_DEV && I2C && EXPERIMENTAL
+       ---help---
+         Support for the Texas Instruments TLV320AIC23B audio codec.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tlv320aic23b.
+
 config VIDEO_WM8775
        tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
        depends on VIDEO_DEV && I2C && EXPERIMENTAL
@@ -380,10 +384,10 @@ config VIDEO_WM8739
 source "drivers/media/video/cx25840/Kconfig"
 
 config VIDEO_SAA711X
-       tristate "Philips SAA7113/4/5 video decoders (OBSOLETED)"
-       depends on VIDEO_V4L1 && I2C && EXPERIMENTAL
+       tristate "Philips SAA7113/4/5 video decoders"
+       depends on VIDEO_DEV && I2C && EXPERIMENTAL
        ---help---
-         Old support for the Philips SAA7113/4 video decoders.
+         Support for the Philips SAA7113/4/5 video decoders.
 
          To compile this driver as a module, choose M here: the
          module will be called saa7115.
@@ -447,6 +451,35 @@ source "drivers/media/video/usbvideo/Kconfig"
 
 source "drivers/media/video/et61x251/Kconfig"
 
+config VIDEO_OVCAMCHIP
+       tristate "OmniVision Camera Chip support"
+       depends on I2C && VIDEO_V4L1
+       ---help---
+         Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
+         This driver is intended to be used with the ov511 and w9968cf USB
+         camera drivers.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ovcamchip.
+
+config USB_W9968CF
+       tristate "USB W996[87]CF JPEG Dual Mode Camera support"
+       depends on USB && VIDEO_V4L1 && I2C
+       select VIDEO_OVCAMCHIP
+       ---help---
+         Say Y here if you want support for cameras based on OV681 or
+         Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
+
+         This driver has an optional plugin, which is distributed as a
+         separate module only (released under GPL). It allows to use higher
+         resolutions and framerates, but cannot be included in the official
+         Linux kernel for performance purposes.
+
+         See <file:Documentation/video4linux/w9968cf.txt> for more info.
+
+         To compile this driver as a module, choose M here: the
+         module will be called w9968cf.
+
 config USB_OV511
        tristate "USB OV511 Camera support"
        depends on USB && VIDEO_V4L1
@@ -483,24 +516,6 @@ config USB_STV680
          To compile this driver as a module, choose M here: the
          module will be called stv680.
 
-config USB_W9968CF
-       tristate "USB W996[87]CF JPEG Dual Mode Camera support"
-       depends on USB && VIDEO_V4L1 && I2C
-       select VIDEO_OVCAMCHIP
-       ---help---
-         Say Y here if you want support for cameras based on OV681 or
-         Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
-
-         This driver has an optional plugin, which is distributed as a
-         separate module only (released under GPL). It allows to use higher
-         resolutions and framerates, but cannot be included in the official
-         Linux kernel for performance purposes.
-
-         See <file:Documentation/video4linux/w9968cf.txt> for more info.
-
-         To compile this driver as a module, choose M here: the
-         module will be called w9968cf.
-
 source "drivers/media/video/zc0301/Kconfig"
 
 source "drivers/media/video/pwc/Kconfig"
index e5bf2687b76de83f15508429f327ca0f3d4046df..6c401b46398a11d8615fadd5641c88d0d6b76fbb 100644 (file)
@@ -6,7 +6,7 @@ zoran-objs      :=      zr36120.o zr36120_i2c.o zr36120_mem.o
 zr36067-objs   :=      zoran_procfs.o zoran_device.o \
                        zoran_driver.o zoran_card.o
 tuner-objs     :=      tuner-core.o tuner-types.o tuner-simple.o \
-                       mt20xx.o tda8290.o tea5767.o
+                       mt20xx.o tda8290.o tea5767.o tda9887.o
 
 msp3400-objs   :=      msp3400-driver.o msp3400-kthreads.o
 
@@ -33,6 +33,7 @@ obj-$(CONFIG_VIDEO_ZORAN_DC30) += adv7175.o vpx3220.o zr36050.o \
        zr36016.o
 obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o zr36060.o
 obj-$(CONFIG_VIDEO_ZORAN_LML33R10) += saa7114.o adv7170.o zr36060.o
+obj-$(CONFIG_VIDEO_ZORAN_AVS6EYES) += bt866.o ks0127.o zr36060.o
 obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
 obj-$(CONFIG_VIDEO_PMS) += pms.o
 obj-$(CONFIG_VIDEO_PLANB) += planb.o
@@ -48,6 +49,7 @@ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
 obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
 obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
+obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
 obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
 obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
 obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
@@ -58,7 +60,7 @@ obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
 obj-$(CONFIG_VIDEO_DPC) += saa7111.o dpc7146.o
 obj-$(CONFIG_TUNER_3036) += tuner-3036.o
 
-obj-$(CONFIG_VIDEO_TUNER) += tuner.o tda9887.o
+obj-$(CONFIG_VIDEO_TUNER) += tuner.o
 obj-$(CONFIG_VIDEO_BUF)   += video-buf.o
 obj-$(CONFIG_VIDEO_BUF_DVB) += video-buf-dvb.o
 obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
@@ -71,6 +73,7 @@ obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
 obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
+obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
 
 obj-$(CONFIG_USB_DABUSB)        += dabusb.o
 obj-$(CONFIG_USB_DSBR)          += dsbr100.o
index dbe025170599df7c11bcd03b5730d8d05e717886..6e08e32346eb9272774c14796e81a0c36da8b7e7 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 #include <asm/uaccess.h>
@@ -212,7 +213,7 @@ void init_iic(void)
        ar_outl(0x0300, PLDI2CMOD);     /* I2CMOD ACK/8b-data/7b-addr/auto */
        ar_outl(0x1, PLDI2CACK);        /* I2CACK ACK                      */
 
-       /* I2C CLK */
+       /* I2C CLK */
        /* 50MH-100k */
        if (freq == 75) {
                ar_outl(369, PLDI2CFREQ);       /* BCLK = 75MHz */
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c
new file mode 100644 (file)
index 0000000..05e42bb
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+    bt866 - BT866 Digital Video Encoder (Rockwell Part)
+
+    Copyright (C) 1999 Mike Bernson <mike@mlb.org>
+    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+
+    Modifications for LML33/DC10plus unified driver
+    Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+
+    This code was modify/ported from the saa7111 driver written
+    by Dave Perks.
+
+    This code was adapted for the bt866 by Christer Weinigel and ported
+    to 2.6 by Martin Samuelsson.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/signal.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+#include <linux/videodev.h>
+#include <asm/uaccess.h>
+
+#include <linux/video_encoder.h>
+
+MODULE_LICENSE("GPL");
+
+#define        BT866_DEVNAME   "bt866"
+#define I2C_BT866      0x88
+
+MODULE_LICENSE("GPL");
+
+#define DEBUG(x)               /* Debug driver */
+
+/* ----------------------------------------------------------------------- */
+
+struct bt866 {
+       struct i2c_client *i2c;
+       int addr;
+       unsigned char reg[128];
+
+       int norm;
+       int enable;
+       int bright;
+       int contrast;
+       int hue;
+       int sat;
+};
+
+static int bt866_write(struct bt866 *dev,
+                       unsigned char subaddr, unsigned char data);
+
+static int bt866_do_command(struct bt866 *encoder,
+                       unsigned int cmd, void *arg)
+{
+       switch (cmd) {
+       case ENCODER_GET_CAPABILITIES:
+       {
+               struct video_encoder_capability *cap = arg;
+
+               DEBUG(printk
+                     (KERN_INFO "%s: get capabilities\n",
+                      encoder->i2c->name));
+
+               cap->flags
+                       = VIDEO_ENCODER_PAL
+                       | VIDEO_ENCODER_NTSC
+                       | VIDEO_ENCODER_CCIR;
+               cap->inputs = 2;
+               cap->outputs = 1;
+       }
+       break;
+
+       case ENCODER_SET_NORM:
+       {
+               int *iarg = arg;
+
+               DEBUG(printk(KERN_INFO "%s: set norm %d\n",
+                            encoder->i2c->name, *iarg));
+
+               switch (*iarg) {
+
+               case VIDEO_MODE_NTSC:
+                       break;
+
+               case VIDEO_MODE_PAL:
+                       break;
+
+               default:
+                       return -EINVAL;
+
+               }
+               encoder->norm = *iarg;
+       }
+       break;
+
+       case ENCODER_SET_INPUT:
+       {
+               int *iarg = arg;
+               static const __u8 init[] = {
+                       0xc8, 0xcc, /* CRSCALE */
+                       0xca, 0x91, /* CBSCALE */
+                       0xcc, 0x24, /* YC16 | OSDNUM */
+                       0xda, 0x00, /*  */
+                       0xdc, 0x24, /* SETMODE | PAL */
+                       0xde, 0x02, /* EACTIVE */
+
+                       /* overlay colors */
+                       0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
+                       0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
+                       0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
+                       0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
+                       0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
+                       0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
+                       0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
+                       0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
+
+                       0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
+                       0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
+                       0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
+                       0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
+                       0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
+                       0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
+                       0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
+                       0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
+               };
+               int i;
+               u8 val;
+
+               for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
+                       bt866_write(encoder, init[i], init[i+1]);
+
+               val = encoder->reg[0xdc];
+
+               if (*iarg == 0)
+                       val |= 0x40; /* CBSWAP */
+               else
+                       val &= ~0x40; /* !CBSWAP */
+
+               bt866_write(encoder, 0xdc, val);
+
+               val = encoder->reg[0xcc];
+               if (*iarg == 2)
+                       val |= 0x01; /* OSDBAR */
+               else
+                       val &= ~0x01; /* !OSDBAR */
+               bt866_write(encoder, 0xcc, val);
+
+               DEBUG(printk(KERN_INFO "%s: set input %d\n",
+                            encoder->i2c->name, *iarg));
+
+               switch (*iarg) {
+               case 0:
+                       break;
+               case 1:
+                       break;
+               default:
+                       return -EINVAL;
+
+               }
+       }
+       break;
+
+       case ENCODER_SET_OUTPUT:
+       {
+               int *iarg = arg;
+
+               DEBUG(printk(KERN_INFO "%s: set output %d\n",
+                            encoder->i2c->name, *iarg));
+
+               /* not much choice of outputs */
+               if (*iarg != 0)
+                       return -EINVAL;
+       }
+       break;
+
+       case ENCODER_ENABLE_OUTPUT:
+       {
+               int *iarg = arg;
+               encoder->enable = !!*iarg;
+
+               DEBUG(printk
+                     (KERN_INFO "%s: enable output %d\n",
+                      encoder->i2c->name, encoder->enable));
+       }
+       break;
+
+       case 4711:
+       {
+               int *iarg = arg;
+               __u8 val;
+
+               printk("bt866: square = %d\n", *iarg);
+
+               val = encoder->reg[0xdc];
+               if (*iarg)
+                       val |= 1; /* SQUARE */
+               else
+                       val &= ~1; /* !SQUARE */
+               bt866_write(encoder, 0xdc, val);
+               break;
+       }
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int bt866_write(struct bt866 *encoder,
+                       unsigned char subaddr, unsigned char data)
+{
+       unsigned char buffer[2];
+       int err;
+
+       buffer[0] = subaddr;
+       buffer[1] = data;
+
+       encoder->reg[subaddr] = data;
+
+       DEBUG(printk
+             ("%s: write 0x%02X = 0x%02X\n",
+              encoder->i2c->name, subaddr, data));
+
+       for (err = 0; err < 3;) {
+               if (i2c_master_send(encoder->i2c, buffer, 2) == 2)
+                       break;
+               err++;
+               printk(KERN_WARNING "%s: I/O error #%d "
+                      "(write 0x%02x/0x%02x)\n",
+                      encoder->i2c->name, err, encoder->addr, subaddr);
+               schedule_timeout_interruptible(HZ/10);
+       }
+       if (err == 3) {
+               printk(KERN_WARNING "%s: giving up\n",
+                      encoder->i2c->name);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int bt866_attach(struct i2c_adapter *adapter);
+static int bt866_detach(struct i2c_client *client);
+static int bt866_command(struct i2c_client *client,
+                        unsigned int cmd, void *arg);
+
+
+/* Addresses to scan */
+static unsigned short normal_i2c[]     = {I2C_BT866>>1, I2C_CLIENT_END};
+static unsigned short probe[2]         = {I2C_CLIENT_END, I2C_CLIENT_END};
+static unsigned short ignore[2]                = {I2C_CLIENT_END, I2C_CLIENT_END};
+
+static struct i2c_client_address_data addr_data = {
+       normal_i2c,
+       probe,
+       ignore,
+};
+
+static struct i2c_driver i2c_driver_bt866 = {
+       .driver.name = BT866_DEVNAME,
+       .id = I2C_DRIVERID_BT866,
+       .attach_adapter = bt866_attach,
+       .detach_client = bt866_detach,
+       .command = bt866_command
+};
+
+
+static struct i2c_client bt866_client_tmpl =
+{
+       .name = "(nil)",
+       .addr = 0,
+       .adapter = NULL,
+       .driver = &i2c_driver_bt866,
+       .usage_count = 0
+};
+
+static int bt866_found_proc(struct i2c_adapter *adapter,
+                           int addr, int kind)
+{
+       struct bt866 *encoder;
+       struct i2c_client *client;
+
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (client == NULL)
+               return -ENOMEM;
+       memcpy(client, &bt866_client_tmpl, sizeof(*client));
+
+       encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
+       if (encoder == NULL) {
+               kfree(client);
+               return -ENOMEM;
+       }
+
+       i2c_set_clientdata(client, encoder);
+       client->adapter = adapter;
+       client->addr = addr;
+       sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id);
+
+       encoder->i2c = client;
+       encoder->addr = addr;
+       //encoder->encoder_type = ENCODER_TYPE_UNKNOWN;
+
+       /* initialize */
+
+       i2c_attach_client(client);
+
+       return 0;
+}
+
+static int bt866_attach(struct i2c_adapter *adapter)
+{
+       if (adapter->id == I2C_HW_B_ZR36067)
+               return i2c_probe(adapter, &addr_data, bt866_found_proc);
+       return 0;
+}
+
+static int bt866_detach(struct i2c_client *client)
+{
+       struct bt866 *encoder = i2c_get_clientdata(client);
+
+       i2c_detach_client(client);
+       kfree(encoder);
+       kfree(client);
+
+       return 0;
+}
+
+static int bt866_command(struct i2c_client *client,
+                        unsigned int cmd, void *arg)
+{
+       struct bt866 *encoder = i2c_get_clientdata(client);
+       return bt866_do_command(encoder, cmd, arg);
+}
+
+static int __devinit bt866_init(void)
+{
+       i2c_add_driver(&i2c_driver_bt866);
+       return 0;
+}
+
+static void __devexit bt866_exit(void)
+{
+       i2c_del_driver(&i2c_driver_bt866);
+}
+
+module_init(bt866_init);
+module_exit(bt866_exit);
index 2b64aa835b423663a203685b6c95a9fc94348fef..3116345c93b16b1ce6af92f6dd814a68bbaa95de 100644 (file)
@@ -269,7 +269,7 @@ static struct CARD {
        { 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" },
        { 0x18501f7f, BTTV_BOARD_FLYVIDEO_98,   "Lifeview Flyvideo 98" },
 
-       { 0x010115cb, BTTV_BOARD_GMV1,          "AG GMV1" },
+       { 0x010115cb, BTTV_BOARD_GMV1,          "AG GMV1" },
        { 0x010114c7, BTTV_BOARD_MODTEC_205,    "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
 
        { 0x10b42636, BTTV_BOARD_HAUPPAUGE878,  "STB ???" },
@@ -309,6 +309,7 @@ static struct CARD {
        { 0x07611461, BTTV_BOARD_AVDVBT_761,    "AverMedia AverTV DVB-T 761" },
        { 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,    "DViCO FusionHDTV DVB-T Lite" },
        { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
+       { 0x00261822, BTTV_BOARD_TWINHAN_DST,   "DNTV Live! Mini "},
 
        { 0, -1, NULL }
 };
@@ -1903,7 +1904,7 @@ struct tvcard bttv_tvcards[] = {
                .no_tda7432     = 1,
        },
        [BTTV_BOARD_OSPREY2x0] = {
-               .name           = "Osprey 210/220",   /* 0x1(A|B)-04C0-C1 */
+               .name           = "Osprey 210/220/230",   /* 0x1(A|B)-04C0-C1 */
                .video_inputs   = 2,
                .audio_inputs   = 1,
                .tuner          = -1,
@@ -2745,7 +2746,7 @@ struct tvcard bttv_tvcards[] = {
                /* Michael Krufky <mkrufky@m1k.net> */
                .name           = "DViCO FusionHDTV 5 Lite",
                .tuner          = 0,
-               .tuner_type     = TUNER_LG_TDVS_H062F,
+               .tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .video_inputs   = 3,
@@ -2762,7 +2763,7 @@ struct tvcard bttv_tvcards[] = {
        },
                /* ---- card 0x88---------------------------------- */
        [BTTV_BOARD_ACORP_Y878F] = {
-               /* Mauro Carvalho Chehab <mchehab@brturbo.com.br> */
+               /* Mauro Carvalho Chehab <mchehab@infradead.org> */
                .name           = "Acorp Y878F",
                .video_inputs   = 3,
                .audio_inputs   = 1,
@@ -3790,6 +3791,7 @@ static void __devinit osprey_eeprom(struct bttv *btv)
                       break;
               case 0x0060:
               case 0x0070:
+              case 0x00A0:
                       btv->c.type = BTTV_BOARD_OSPREY2x0;
                       /* enable output on select control lines */
                       gpio_inout(0xffffff,0x000303);
index c4d5e2b70c28e12c28761b09713e5d669cb3fcdc..ba081f6f8c82c6818b93e11c50f4682c3e36bd43 100644 (file)
@@ -118,20 +118,6 @@ int bttv_sub_del_devices(struct bttv_core *core)
        return 0;
 }
 
-void bttv_gpio_irq(struct bttv_core *core)
-{
-       struct bttv_sub_driver *drv;
-       struct bttv_sub_device *dev;
-       struct list_head *item;
-
-       list_for_each(item,&core->subs) {
-               dev = list_entry(item,struct bttv_sub_device,list);
-               drv = to_bttv_sub_drv(dev->dev.driver);
-               if (drv && drv->gpio_irq)
-                       drv->gpio_irq(dev);
-       }
-}
-
 /* ----------------------------------------------------------------------- */
 /* external: sub-driver register/unregister                                */
 
index 69efa0e5174d58ffb113d97479f8b82180490b65..b41f81d2372ccd8b4e0a25d95c8a57e6491d4915 100644 (file)
@@ -355,7 +355,7 @@ int bttv_input_init(struct bttv *btv)
 
        if (ir->rc5_gpio) {
                u32 gpio;
-               /* enable remote irq */
+               /* enable remote irq */
                bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4);
                gpio = bttv_gpio_read(&btv->c);
                bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
index 3a23265c153860a1efe06176576f4aa2e02ed32e..f9c9e3c4d111944cf2c42d93c45513b5a28304da 100644 (file)
@@ -350,7 +350,6 @@ struct bttv_sub_driver {
        char                   wanted[BUS_ID_SIZE];
        int                    (*probe)(struct bttv_sub_device *sub);
        void                   (*remove)(struct bttv_sub_device *sub);
-       void                   (*gpio_irq)(struct bttv_sub_device *sub);
 };
 #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
 
index ee989d2e15d9ede516d1ff51113f7c6a64a29809..d2956010f763c0cb05a58fb21c6fc629086f86dc 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/pci.h>
 #include <linux/input.h>
 #include <linux/mutex.h>
@@ -214,7 +215,6 @@ extern struct videobuf_queue_ops bttv_vbi_qops;
 extern struct bus_type bttv_sub_bus_type;
 int bttv_sub_add_device(struct bttv_core *core, char *name);
 int bttv_sub_del_devices(struct bttv_core *core);
-void bttv_gpio_irq(struct bttv_core *core);
 
 
 /* ---------------------------------------------------------- */
index cf61c590f4ada90bb038e9e2b9610a4870336013..7d0b6e59c6e2449b3030a70a4584499039a1cd66 100644 (file)
@@ -73,6 +73,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <linux/parport.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 
@@ -759,7 +760,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
                {
                        struct video_picture *p = arg;
                        if(p->palette!=VIDEO_PALETTE_GREY)
-                               return -EINVAL;
+                               return -EINVAL;
                        if(p->depth!=4 && p->depth!=6)
                                return -EINVAL;
 
index 22a7386bbea6f537b8f8b30dc32965ef5609fe7f..a3989bd2f81bb99b94c49127d36d7f277ba53689 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/parport.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 #include <asm/uaccess.h>
index 85d84e89d8f4d9fbb7d878ae8aa3010836dc3d13..95c5aceecc5bb9566f64887d805713d4cfc28286 100644 (file)
 
 #include "cpia.h"
 
-#ifdef CONFIG_VIDEO_CPIA_PP
-extern int cpia_pp_init(void);
-#endif
-#ifdef CONFIG_VIDEO_CPIA_USB
-extern int cpia_usb_init(void);
-#endif
-
 static int video_nr = -1;
 
 #ifdef MODULE
@@ -67,10 +60,10 @@ MODULE_SUPPORTED_DEVICE("video");
 static unsigned short colorspace_conv;
 module_param(colorspace_conv, ushort, 0444);
 MODULE_PARM_DESC(colorspace_conv,
-                 " Colorspace conversion:"
-                 "\n  0 = disable, 1 = enable"
-                 "\n  Default value is 0"
-                 );
+                " Colorspace conversion:"
+                "\n  0 = disable, 1 = enable"
+                "\n  Default value is 0"
+                );
 
 #define ABOUT "V4L-Driver for Vision CPiA based cameras"
 
@@ -4047,13 +4040,6 @@ static int __init cpia_init(void)
        proc_cpia_create();
 #endif
 
-#ifdef CONFIG_VIDEO_CPIA_PP
-       cpia_pp_init();
-#endif
-#ifdef CONFIG_VIDEO_CPIA_USB
-       cpia_usb_init();
-#endif
-
        return 0;
 }
 
index dde27a6a4a095bbc084cfe1f96d58d58466f12c3..6eaa692021c58f61c52843df4e60bea7172cddb1 100644 (file)
@@ -45,6 +45,7 @@
 
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/list.h>
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
@@ -247,7 +248,7 @@ enum v4l_camstates {
 struct cam_data {
        struct list_head cam_data_list;
 
-       struct mutex busy_lock;     /* guard against SMP multithreading */
+       struct mutex busy_lock;         /* guard against SMP multithreading */
        struct cpia_camera_ops *ops;    /* lowlevel driver operations */
        void *lowlevel_data;            /* private data for lowlevel driver */
        u8 *raw_image;                  /* buffer for raw image data */
index 1764991b0ac98df4c26b32cefa63f17bab80dcd9..c5ecb2be5f9313d692f0c9826e6202f2b64c357b 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/version.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/usb.h>
 #include <linux/poll.h>
 
index 481e178ef56df58b197463a0ba250d94811b79d3..d129db57fcd4bab57861528b200092326bf86bc4 100644 (file)
@@ -343,7 +343,9 @@ static int cpia2_close(struct inode *inode, struct file *file)
                cpia2_free_buffers(cam);
                if (!cam->present) {
                        video_unregister_device(dev);
+                       mutex_unlock(&cam->busy_lock);
                        kfree(cam);
+                       return 0;
                }
        }
 
@@ -1167,9 +1169,9 @@ static int ioctl_g_ctrl(void *arg,struct camera_data *cam)
                } else {
                    if(cam->params.flicker_control.cam_register &
                       CPIA2_VP_FLICKER_MODES_50HZ) {
-                       mode = FLICKER_50;
+                       mode = FLICKER_50;
                    } else {
-                       mode = FLICKER_60;
+                       mode = FLICKER_60;
                    }
                }
                for(i=0; i<NUM_FLICKER_CONTROLS; i++) {
index 0b00e6027dfb302669a688f0167bc7a0bf8e1377..4c89bd395d3e6d275d78fda9580d16ed3a427d4a 100644 (file)
@@ -803,7 +803,7 @@ static struct parport_driver cpia_pp_driver = {
        .detach = cpia_pp_detach,
 };
 
-int cpia_pp_init(void)
+static int cpia_pp_init(void)
 {
        printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
               CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
@@ -860,6 +860,8 @@ void cleanup_module(void)
 
 static int __init cpia_pp_setup(char *str)
 {
+       int err;
+
        if (!strncmp(str, "parport", 7)) {
                int n = simple_strtoul(str + 7, NULL, 10);
                if (parport_ptr < PARPORT_MAX) {
@@ -873,6 +875,10 @@ static int __init cpia_pp_setup(char *str)
                parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE;
        }
 
+       err=cpia_pp_init();
+       if (err)
+               return err;
+
        return 1;
 }
 
index 9c49a4b00116f1ef7075888ecd26f6b261bcb75b..2ee34a3b92807bf96654c4ce6cd89aa79a8b6ca7 100644 (file)
@@ -474,12 +474,6 @@ static int cpia_usb_close(void *privdata)
        return 0;
 }
 
-int cpia_usb_init(void)
-{
-       /* return -ENODEV; */
-       return 0;
-}
-
 /* Probing and initializing */
 
 static int cpia_probe(struct usb_interface *intf,
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
new file mode 100644 (file)
index 0000000..554813e
--- /dev/null
@@ -0,0 +1,915 @@
+/*
+ * cx2341x - generic code for cx23415/6 based devices
+ *
+ * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+
+#include <media/tuner.h>
+#include <media/cx2341x.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("cx23415/6 driver");
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+const u32 cx2341x_mpeg_ctrls[] = {
+       V4L2_CID_MPEG_CLASS,
+       V4L2_CID_MPEG_STREAM_TYPE,
+       V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+       V4L2_CID_MPEG_AUDIO_ENCODING,
+       V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+       V4L2_CID_MPEG_AUDIO_MODE,
+       V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
+       V4L2_CID_MPEG_AUDIO_EMPHASIS,
+       V4L2_CID_MPEG_AUDIO_CRC,
+       V4L2_CID_MPEG_VIDEO_ENCODING,
+       V4L2_CID_MPEG_VIDEO_ASPECT,
+       V4L2_CID_MPEG_VIDEO_B_FRAMES,
+       V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+       V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+       V4L2_CID_MPEG_VIDEO_PULLDOWN,
+       V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+       V4L2_CID_MPEG_VIDEO_BITRATE,
+       V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+       V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
+       V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
+       V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
+       V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
+       V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
+       V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
+       V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
+       V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
+       V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
+       V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
+       V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
+       V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
+       0
+};
+
+
+/* Map the control ID to the correct field in the cx2341x_mpeg_params
+   struct. Return -EINVAL if the ID is unknown, else return 0. */
+static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
+               struct v4l2_ext_control *ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+               ctrl->value = params->audio_sampling_freq;
+               break;
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               ctrl->value = params->audio_encoding;
+               break;
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               ctrl->value = params->audio_l2_bitrate;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MODE:
+               ctrl->value = params->audio_mode;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+               ctrl->value = params->audio_mode_extension;
+               break;
+       case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+               ctrl->value = params->audio_emphasis;
+               break;
+       case V4L2_CID_MPEG_AUDIO_CRC:
+               ctrl->value = params->audio_crc;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               ctrl->value = params->video_encoding;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               ctrl->value = params->video_aspect;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               ctrl->value = params->video_b_frames;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               ctrl->value = params->video_gop_size;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+               ctrl->value = params->video_gop_closure;
+               break;
+       case V4L2_CID_MPEG_VIDEO_PULLDOWN:
+               ctrl->value = params->video_pulldown;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               ctrl->value = params->video_bitrate_mode;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               ctrl->value = params->video_bitrate;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               ctrl->value = params->video_bitrate_peak;
+               break;
+       case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+               ctrl->value = params->video_temporal_decimation;
+               break;
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               ctrl->value = params->stream_type;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+               ctrl->value = params->video_spatial_filter_mode;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+               ctrl->value = params->video_spatial_filter;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+               ctrl->value = params->video_luma_spatial_filter_type;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+               ctrl->value = params->video_chroma_spatial_filter_type;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+               ctrl->value = params->video_temporal_filter_mode;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+               ctrl->value = params->video_temporal_filter;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               ctrl->value = params->video_median_filter_type;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+               ctrl->value = params->video_luma_median_filter_top;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+               ctrl->value = params->video_luma_median_filter_bottom;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+               ctrl->value = params->video_chroma_median_filter_top;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+               ctrl->value = params->video_chroma_median_filter_bottom;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* Map the control ID to the correct field in the cx2341x_mpeg_params
+   struct. Return -EINVAL if the ID is unknown, else return 0. */
+static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
+               struct v4l2_ext_control *ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+               params->audio_sampling_freq = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               params->audio_encoding = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               params->audio_l2_bitrate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MODE:
+               params->audio_mode = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+               params->audio_mode_extension = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+               params->audio_emphasis = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_CRC:
+               params->audio_crc = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               params->video_aspect = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
+               int b = ctrl->value + 1;
+               int gop = params->video_gop_size;
+               params->video_b_frames = ctrl->value;
+               params->video_gop_size = b * ((gop + b - 1) / b);
+               /* Max GOP size = 34 */
+               while (params->video_gop_size > 34)
+                       params->video_gop_size -= b;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
+               int b = params->video_b_frames + 1;
+               int gop = ctrl->value;
+               params->video_gop_size = b * ((gop + b - 1) / b);
+               /* Max GOP size = 34 */
+               while (params->video_gop_size > 34)
+                       params->video_gop_size -= b;
+               ctrl->value = params->video_gop_size;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+               params->video_gop_closure = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_PULLDOWN:
+               params->video_pulldown = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               /* MPEG-1 only allows CBR */
+               if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
+                   ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+                       return -EINVAL;
+               params->video_bitrate_mode = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               params->video_bitrate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               params->video_bitrate_peak = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+               params->video_temporal_decimation = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               params->stream_type = ctrl->value;
+               params->video_encoding =
+                       (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
+                        params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
+                       V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+               if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
+                       /* MPEG-1 implies CBR */
+                       params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+               }
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+               params->video_spatial_filter_mode = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+               params->video_spatial_filter = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+               params->video_luma_spatial_filter_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+               params->video_chroma_spatial_filter_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+               params->video_temporal_filter_mode = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+               params->video_temporal_filter = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               params->video_median_filter_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+               params->video_luma_median_filter_top = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+               params->video_luma_median_filter_bottom = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+               params->video_chroma_median_filter_top = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+               params->video_chroma_median_filter_bottom = ctrl->value;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+{
+       const char *name;
+
+       qctrl->flags = 0;
+       switch (qctrl->id) {
+       /* MPEG controls */
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+               name = "Spatial Filter Mode";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+               name = "Spatial Filter";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+               name = "Spatial Luma Filter Type";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+               name = "Spatial Chroma Filter Type";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+               name = "Temporal Filter Mode";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+               name = "Temporal Filter";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               name = "Median Filter Type";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+               name = "Median Luma Filter Maximum";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+               name = "Median Luma Filter Minimum";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+               name = "Median Chroma Filter Maximum";
+               break;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+               name = "Median Chroma Filter Minimum";
+               break;
+
+       default:
+               return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
+       }
+       switch (qctrl->id) {
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               qctrl->type = V4L2_CTRL_TYPE_MENU;
+               min = 0;
+               step = 1;
+               break;
+       default:
+               qctrl->type = V4L2_CTRL_TYPE_INTEGER;
+               break;
+       }
+       switch (qctrl->id) {
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
+               break;
+       }
+       qctrl->minimum = min;
+       qctrl->maximum = max;
+       qctrl->step = step;
+       qctrl->default_value = def;
+       qctrl->reserved[0] = qctrl->reserved[1] = 0;
+       snprintf(qctrl->name, sizeof(qctrl->name), name);
+       return 0;
+}
+
+int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl)
+{
+       int err;
+
+       switch (qctrl->id) {
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+                               V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
+                               V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_192K,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_224K);
+
+       case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+       case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+               return -EINVAL;
+
+       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+               err = v4l2_ctrl_query_fill_std(qctrl);
+               if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
+                       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return err;
+
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               /* this setting is read-only for the cx2341x since the
+                  V4L2_CID_MPEG_STREAM_TYPE really determines the
+                  MPEG-1/2 setting */
+               err = v4l2_ctrl_query_fill_std(qctrl);
+               if (err == 0)
+                       qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+               return err;
+
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               err = v4l2_ctrl_query_fill_std(qctrl);
+               if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
+                       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return err;
+
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               err = v4l2_ctrl_query_fill_std(qctrl);
+               if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+                       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return err;
+
+       /* CX23415/6 specific */
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+               return cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+                               V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
+                               V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+               cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+               cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
+                               V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1,
+                               V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
+               if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+               cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
+                               V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1,
+                               V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
+               if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+               return cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+                               V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
+                               V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+               cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               return cx2341x_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+                               V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
+                               V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+               cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+               cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+               cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+               cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+                      qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return 0;
+
+       default:
+               return v4l2_ctrl_query_fill_std(qctrl);
+
+       }
+}
+
+const char **cx2341x_ctrl_get_menu(u32 id)
+{
+       static const char *mpeg_stream_type[] = {
+               "MPEG-2 Program Stream",
+               "",
+               "MPEG-1 System Stream",
+               "MPEG-2 DVD-compatible Stream",
+               "MPEG-1 VCD-compatible Stream",
+               "MPEG-2 SVCD-compatible Stream",
+               NULL
+       };
+
+       static const char *cx2341x_video_spatial_filter_mode_menu[] = {
+               "Manual",
+               "Auto",
+               NULL
+       };
+
+       static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
+               "Off",
+               "1D Horizontal",
+               "1D Vertical",
+               "2D H/V Separable",
+               "2D Symmetric non-separable",
+               NULL
+       };
+
+       static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
+               "Off",
+               "1D Horizontal",
+               NULL
+       };
+
+       static const char *cx2341x_video_temporal_filter_mode_menu[] = {
+               "Manual",
+               "Auto",
+               NULL
+       };
+
+       static const char *cx2341x_video_median_filter_type_menu[] = {
+               "Off",
+               "Horizontal",
+               "Vertical",
+               "Horizontal/Vertical",
+               "Diagonal",
+               NULL
+       };
+
+       switch (id) {
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               return mpeg_stream_type;
+       case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+       case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+               return NULL;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+               return cx2341x_video_spatial_filter_mode_menu;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+               return cx2341x_video_luma_spatial_filter_type_menu;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+               return cx2341x_video_chroma_spatial_filter_type_menu;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+               return cx2341x_video_temporal_filter_mode_menu;
+       case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+               return cx2341x_video_median_filter_type_menu;
+       default:
+               return v4l2_ctrl_get_menu(id);
+       }
+}
+
+static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
+{
+       params->audio_properties = (params->audio_sampling_freq << 0) |
+               ((3 - params->audio_encoding) << 2) |
+               ((1 + params->audio_l2_bitrate) << 4) |
+               (params->audio_mode << 8) |
+               (params->audio_mode_extension << 10) |
+               (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ?
+                 3 :
+                 params->audio_emphasis) << 12) |
+               (params->audio_crc << 14);
+}
+
+int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
+                 struct v4l2_ext_controls *ctrls, int cmd)
+{
+       int err = 0;
+       int i;
+
+       if (cmd == VIDIOC_G_EXT_CTRLS) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = cx2341x_get_ctrl(params, ctrl);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+       }
+       for (i = 0; i < ctrls->count; i++) {
+               struct v4l2_ext_control *ctrl = ctrls->controls + i;
+               struct v4l2_queryctrl qctrl;
+               const char **menu_items = NULL;
+
+               qctrl.id = ctrl->id;
+               err = cx2341x_ctrl_query(params, &qctrl);
+               if (err)
+                       break;
+               if (qctrl.type == V4L2_CTRL_TYPE_MENU)
+                       menu_items = cx2341x_ctrl_get_menu(qctrl.id);
+               err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
+               if (err)
+                       break;
+               err = cx2341x_set_ctrl(params, ctrl);
+               if (err)
+                       break;
+       }
+       if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+                       params->video_bitrate_peak < params->video_bitrate) {
+               err = -ERANGE;
+               ctrls->error_idx = ctrls->count;
+       }
+       if (err) {
+               ctrls->error_idx = i;
+       }
+       else {
+               cx2341x_calc_audio_properties(params);
+       }
+       return err;
+}
+
+void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
+{
+       static struct cx2341x_mpeg_params default_params = {
+       /* misc */
+       .port = CX2341X_PORT_MEMORY,
+       .width = 720,
+       .height = 480,
+       .is_50hz = 0,
+
+       /* stream */
+       .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+
+       /* audio */
+       .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+       .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+       .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
+       .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
+       .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
+       .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
+       .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
+
+       /* video */
+       .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
+       .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
+       .video_b_frames = 2,
+       .video_gop_size = 12,
+       .video_gop_closure = 1,
+       .video_pulldown = 0,
+       .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+       .video_bitrate = 6000000,
+       .video_bitrate_peak = 8000000,
+       .video_temporal_decimation = 0,
+
+       /* encoding filters */
+       .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+       .video_spatial_filter = 0,
+       .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
+       .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
+       .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+       .video_temporal_filter = 0,
+       .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+       .video_luma_median_filter_top = 255,
+       .video_luma_median_filter_bottom = 0,
+       .video_chroma_median_filter_top = 255,
+       .video_chroma_median_filter_bottom = 0,
+       };
+
+       *p = default_params;
+       cx2341x_calc_audio_properties(p);
+}
+
+static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       va_list vargs;
+       int i;
+
+       va_start(vargs, args);
+
+       for (i = 0; i < args; i++) {
+               data[i] = va_arg(vargs, int);
+       }
+       va_end(vargs);
+       return func(priv, cmd, args, 0, data);
+}
+
+int cx2341x_update(void *priv, cx2341x_mbox_func func,
+               const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new)
+{
+       static int mpeg_stream_type[] = {
+               0,      /* MPEG-2 PS */
+               1,      /* MPEG-2 TS */
+               2,      /* MPEG-1 SS */
+               14,     /* DVD */
+               11,     /* VCD */
+               12,     /* SVCD */
+       };
+
+       int err = 0;
+
+       cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
+
+       if (old == NULL || old->is_50hz != new->is_50hz) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
+               if (err) return err;
+       }
+
+       if (old == NULL || old->width != new->width || old->height != new->height ||
+                       old->video_encoding != new->video_encoding) {
+               u16 w = new->width;
+               u16 h = new->height;
+
+               if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
+                       w /= 2;
+                       h /= 2;
+               }
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
+               if (err) return err;
+       }
+
+       if (old == NULL || old->stream_type != new->stream_type) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_aspect != new->video_aspect) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_b_frames != new->video_b_frames ||
+               old->video_gop_size != new->video_gop_size) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
+                               new->video_gop_size, new->video_b_frames + 1);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_pulldown != new->video_pulldown) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown);
+               if (err) return err;
+       }
+       if (old == NULL || old->audio_properties != new->audio_properties) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
+               old->video_bitrate != new->video_bitrate ||
+               old->video_bitrate_peak != new->video_bitrate_peak) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
+                               new->video_bitrate_mode, new->video_bitrate,
+                               new->video_bitrate_peak / 400, 0, 0);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
+               old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
+               old->video_median_filter_type != new->video_median_filter_type) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
+                               new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
+                               new->video_median_filter_type);
+               if (err) return err;
+       }
+       if (old == NULL ||
+               old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
+               old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
+               old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
+               old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
+                               new->video_luma_median_filter_bottom,
+                               new->video_luma_median_filter_top,
+                               new->video_chroma_median_filter_bottom,
+                               new->video_chroma_median_filter_top);
+               if (err) return err;
+       }
+       if (old == NULL ||
+               old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
+               old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
+                       new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
+               if (err) return err;
+       }
+       if (old == NULL ||
+               old->video_spatial_filter != new->video_spatial_filter ||
+               old->video_temporal_filter != new->video_temporal_filter) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
+                       new->video_spatial_filter, new->video_temporal_filter);
+               if (err) return err;
+       }
+       if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
+               err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
+                       new->video_temporal_decimation);
+               if (err) return err;
+       }
+       return 0;
+}
+
+static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
+{
+       const char **menu = cx2341x_ctrl_get_menu(id);
+       struct v4l2_ext_control ctrl;
+
+       if (menu == NULL)
+               goto invalid;
+       ctrl.id = id;
+       if (cx2341x_get_ctrl(p, &ctrl))
+               goto invalid;
+       while (ctrl.value-- && *menu) menu++;
+       if (*menu == NULL)
+               goto invalid;
+       return *menu;
+
+invalid:
+       return "<invalid>";
+}
+
+void cx2341x_log_status(struct cx2341x_mpeg_params *p, int card_id)
+{
+       int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+
+       /* Stream */
+       printk(KERN_INFO "cx2341x-%d: Stream: %s\n",
+               card_id,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
+
+       /* Video */
+       printk(KERN_INFO "cx2341x-%d: Video:  %dx%d, %d fps\n",
+               card_id,
+               p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
+               p->is_50hz ? 25 : 30);
+       printk(KERN_INFO "cx2341x-%d: Video:  %s, %s, %s, %d",
+               card_id,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
+               p->video_bitrate);
+       if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
+               printk(", Peak %d", p->video_bitrate_peak);
+       }
+       printk("\n");
+       printk(KERN_INFO "cx2341x-%d: Video:  GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n",
+               card_id,
+               p->video_gop_size, p->video_b_frames,
+               p->video_gop_closure ? "" : "No ",
+               p->video_pulldown ? "" : "No ");
+       if (p->video_temporal_decimation) {
+               printk(KERN_INFO "cx2341x-%d: Video: Temporal Decimation %d\n",
+                       card_id, p->video_temporal_decimation);
+       }
+
+       /* Audio */
+       printk(KERN_INFO "cx2341x-%d: Audio:  %s, %s, %s, %s",
+               card_id,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE));
+       if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
+               printk(", %s",
+                       cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
+       }
+       printk(", %s, %s\n",
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
+
+       /* Encoding filters */
+       printk(KERN_INFO "cx2341x-%d: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
+               card_id,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
+               cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
+               p->video_spatial_filter);
+       printk(KERN_INFO "cx2341x-%d: Temporal Filter: %s, %d\n",
+               card_id,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
+               p->video_temporal_filter);
+       printk(KERN_INFO "cx2341x-%d: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
+               card_id,
+               cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
+               p->video_luma_median_filter_bottom,
+               p->video_luma_median_filter_top,
+               p->video_chroma_median_filter_bottom,
+               p->video_chroma_median_filter_top);
+}
+
+EXPORT_SYMBOL(cx2341x_fill_defaults);
+EXPORT_SYMBOL(cx2341x_ctrl_query);
+EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
+EXPORT_SYMBOL(cx2341x_ext_ctrls);
+EXPORT_SYMBOL(cx2341x_update);
+EXPORT_SYMBOL(cx2341x_log_status);
+EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
index 9a4b813152e56a4f8c9af4e825a7cb834f9b2b8d..f897c1ebd5f3d809f4bf6bf6f111b2754395a4bc 100644 (file)
@@ -30,9 +30,6 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
        if (freq != 32000 && freq != 44100 && freq != 48000)
                return -EINVAL;
 
-       /* assert soft reset */
-       cx25840_and_or(client, 0x810, ~0x1, 0x01);
-
        /* common for all inputs and rates */
        /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
        cx25840_write(client, 0x127, 0x50);
@@ -46,6 +43,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
                        /* AUX_PLL_FRAC */
                        cx25840_write4(client, 0x110, 0xee39bb01);
 
+                       if (state->is_cx25836)
+                               break;
+
                        /* src3/4/6_ctl = 0x0801f77f */
                        cx25840_write4(client, 0x900, 0x7ff70108);
                        cx25840_write4(client, 0x904, 0x7ff70108);
@@ -59,6 +59,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
                        /* AUX_PLL_FRAC */
                        cx25840_write4(client, 0x110, 0xd66bec00);
 
+                       if (state->is_cx25836)
+                               break;
+
                        /* src3/4/6_ctl = 0x08016d59 */
                        cx25840_write4(client, 0x900, 0x596d0108);
                        cx25840_write4(client, 0x904, 0x596d0108);
@@ -72,6 +75,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
                        /* AUX_PLL_FRAC */
                        cx25840_write4(client, 0x110, 0xe5d69800);
 
+                       if (state->is_cx25836)
+                               break;
+
                        /* src3/4/6_ctl = 0x08014faa */
                        cx25840_write4(client, 0x900, 0xaa4f0108);
                        cx25840_write4(client, 0x904, 0xaa4f0108);
@@ -87,6 +93,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
                        /* AUX_PLL_FRAC */
                        cx25840_write4(client, 0x110, 0x69082a01);
 
+                       if (state->is_cx25836)
+                               break;
+
                        /* src1_ctl = 0x08010000 */
                        cx25840_write4(client, 0x8f8, 0x00000108);
 
@@ -106,6 +115,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
                        /* AUX_PLL_FRAC */
                        cx25840_write4(client, 0x110, 0xd66bec00);
 
+                       if (state->is_cx25836)
+                               break;
+
                        /* src1_ctl = 0x08010000 */
                        cx25840_write4(client, 0x8f8, 0xcd600108);
 
@@ -122,6 +134,9 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
                        /* AUX_PLL_FRAC */
                        cx25840_write4(client, 0x110, 0xe5d69800);
 
+                       if (state->is_cx25836)
+                               break;
+
                        /* src1_ctl = 0x08010000 */
                        cx25840_write4(client, 0x8f8, 0x00800108);
 
@@ -133,9 +148,6 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
                }
        }
 
-       /* deassert soft reset */
-       cx25840_and_or(client, 0x810, ~0x1, 0x00);
-
        state->audclk_freq = freq;
 
        return 0;
@@ -148,6 +160,10 @@ void cx25840_audio_set_path(struct i2c_client *client)
        /* stop microcontroller */
        cx25840_and_or(client, 0x803, ~0x10, 0);
 
+       /* assert soft reset */
+       if (!state->is_cx25836)
+               cx25840_and_or(client, 0x810, ~0x1, 0x01);
+
        /* Mute everything to prevent the PFFT! */
        cx25840_write(client, 0x8d3, 0x1f);
 
@@ -161,13 +177,19 @@ void cx25840_audio_set_path(struct i2c_client *client)
        } else {
                /* Set Path1 to Analog Demod Main Channel */
                cx25840_write4(client, 0x8d0, 0x7038061f);
+       }
 
+       set_audclk_freq(client, state->audclk_freq);
+
+       /* deassert soft reset */
+       if (!state->is_cx25836)
+               cx25840_and_or(client, 0x810, ~0x1, 0x00);
+
+       if (state->aud_input != CX25840_AUDIO_SERIAL) {
                /* When the microcontroller detects the
                 * audio format, it will unmute the lines */
                cx25840_and_or(client, 0x803, ~0x10, 0x10);
        }
-
-       set_audclk_freq(client, state->audclk_freq);
 }
 
 static int get_volume(struct i2c_client *client)
@@ -291,11 +313,25 @@ static void set_mute(struct i2c_client *client, int mute)
 
 int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
 {
+       struct cx25840_state *state = i2c_get_clientdata(client);
        struct v4l2_control *ctrl = arg;
+       int retval;
 
        switch (cmd) {
        case VIDIOC_INT_AUDIO_CLOCK_FREQ:
-               return set_audclk_freq(client, *(u32 *)arg);
+               if (state->aud_input != CX25840_AUDIO_SERIAL) {
+                       cx25840_and_or(client, 0x803, ~0x10, 0);
+                       cx25840_write(client, 0x8d3, 0x1f);
+               }
+               if (!state->is_cx25836)
+                       cx25840_and_or(client, 0x810, ~0x1, 1);
+               retval = set_audclk_freq(client, *(u32 *)arg);
+               if (!state->is_cx25836)
+                       cx25840_and_or(client, 0x810, ~0x1, 0);
+               if (state->aud_input != CX25840_AUDIO_SERIAL) {
+                       cx25840_and_or(client, 0x803, ~0x10, 0x10);
+               }
+               return retval;
 
        case VIDIOC_G_CTRL:
                switch (ctrl->id) {
index a961bb2ab0fdcda188618a19ba99dfedc7aab747..5c2036b40ea11e8373b101a3a9c2844ddbcf0dd5 100644 (file)
@@ -10,6 +10,9 @@
  *
  * VBI support by Hans Verkuil <hverkuil@xs4all.nl>.
  *
+ * NTSC sliced VBI support by Christopher Neufeld <television@cneufeld.ca>
+ * with additional fixes by Hans Verkuil <hverkuil@xs4all.nl>.
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
@@ -43,7 +46,7 @@ MODULE_LICENSE("GPL");
 static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
 
 
-static int cx25840_debug;
+int cx25840_debug;
 
 module_param_named(debug,cx25840_debug, int, 0644);
 
@@ -105,7 +108,7 @@ u32 cx25840_read4(struct i2c_client * client, u16 addr)
            (buffer[2] << 8) | buffer[3];
 }
 
-int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask,
+int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
                   u8 or_value)
 {
        return cx25840_write(client, addr,
@@ -117,7 +120,8 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask,
 
 static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
                                                enum cx25840_audio_input aud_input);
-static void log_status(struct i2c_client *client);
+static void log_audio_status(struct i2c_client *client);
+static void log_video_status(struct i2c_client *client);
 
 /* ----------------------------------------------------------------------- */
 
@@ -147,6 +151,33 @@ static void init_dll2(struct i2c_client *client)
        cx25840_write(client, 0x15d, 0xe1);
 }
 
+static void cx25836_initialize(struct i2c_client *client)
+{
+       /* reset configuration is described on page 3-77 of the CX25836 datasheet */
+       /* 2. */
+       cx25840_and_or(client, 0x000, ~0x01, 0x01);
+       cx25840_and_or(client, 0x000, ~0x01, 0x00);
+       /* 3a. */
+       cx25840_and_or(client, 0x15a, ~0x70, 0x00);
+       /* 3b. */
+       cx25840_and_or(client, 0x15b, ~0x1e, 0x06);
+       /* 3c. */
+       cx25840_and_or(client, 0x159, ~0x02, 0x02);
+       /* 3d. */
+       /* There should be a 10-us delay here, but since the
+          i2c bus already has a 10-us delay we don't need to do
+          anything */
+       /* 3e. */
+       cx25840_and_or(client, 0x159, ~0x02, 0x00);
+       /* 3f. */
+       cx25840_and_or(client, 0x159, ~0xc0, 0xc0);
+       /* 3g. */
+       cx25840_and_or(client, 0x159, ~0x01, 0x00);
+       cx25840_and_or(client, 0x159, ~0x01, 0x01);
+       /* 3h. */
+       cx25840_and_or(client, 0x15b, ~0x1e, 0x10);
+}
+
 static void cx25840_initialize(struct i2c_client *client, int loadfw)
 {
        struct cx25840_state *state = i2c_get_clientdata(client);
@@ -220,17 +251,7 @@ static void input_change(struct i2c_client *client)
        cx25840_and_or(client, 0x401, ~0x60, 0);
        cx25840_and_or(client, 0x401, ~0x60, 0x60);
 
-       /* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC
-          instead of V4L2_STD_PAL. Someone needs to test this. */
-       if (std & V4L2_STD_PAL) {
-               /* Follow tuner change procedure for PAL */
-               cx25840_write(client, 0x808, 0xff);
-               cx25840_write(client, 0x80b, 0x10);
-       } else if (std & V4L2_STD_SECAM) {
-               /* Select autodetect for SECAM */
-               cx25840_write(client, 0x808, 0xff);
-               cx25840_write(client, 0x80b, 0x10);
-       } else if (std & V4L2_STD_NTSC) {
+       if (std & V4L2_STD_525_60) {
                /* Certain Hauppauge PVR150 models have a hardware bug
                   that causes audio to drop out. For these models the
                   audio standard must be set explicitly.
@@ -249,6 +270,14 @@ static void input_change(struct i2c_client *client)
                        cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6);
                }
                cx25840_write(client, 0x80b, 0x00);
+       } else if (std & V4L2_STD_PAL) {
+               /* Follow tuner change procedure for PAL */
+               cx25840_write(client, 0x808, 0xff);
+               cx25840_write(client, 0x80b, 0x10);
+       } else if (std & V4L2_STD_SECAM) {
+               /* Select autodetect for SECAM */
+               cx25840_write(client, 0x808, 0xff);
+               cx25840_write(client, 0x80b, 0x10);
        }
 
        if (cx25840_read(client, 0x803) & 0x10) {
@@ -319,8 +348,10 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
 
        state->vid_input = vid_input;
        state->aud_input = aud_input;
-       cx25840_audio_set_path(client);
-       input_change(client);
+       if (!state->is_cx25836) {
+               cx25840_audio_set_path(client);
+               input_change(client);
+       }
        return 0;
 }
 
@@ -354,6 +385,8 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
                }
        }
 
+       v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);
+
        /* Follow step 9 of section 3.16 in the cx25840 datasheet.
           Without this PAL may display a vertical ghosting effect.
           This happens for example with the Yuan MPC622. */
@@ -370,6 +403,7 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
 
 v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
 {
+       struct cx25840_state *state = i2c_get_clientdata(client);
        /* check VID_FMT_SEL first */
        u8 fmt = cx25840_read(client, 0x400) & 0xf;
 
@@ -383,7 +417,7 @@ v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
        {
                /* if the audio std is A2-M, then this is the South Korean
                   NTSC standard */
-               if (cx25840_read(client, 0x805) == 2)
+               if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2)
                        return V4L2_STD_NTSC_M_KR;
                return V4L2_STD_NTSC_M;
        }
@@ -456,6 +490,8 @@ static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
        case V4L2_CID_AUDIO_TREBLE:
        case V4L2_CID_AUDIO_BALANCE:
        case V4L2_CID_AUDIO_MUTE:
+               if (state->is_cx25836)
+                       return -EINVAL;
                return cx25840_audio(client, VIDIOC_S_CTRL, ctrl);
 
        default:
@@ -490,6 +526,8 @@ static int get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
        case V4L2_CID_AUDIO_TREBLE:
        case V4L2_CID_AUDIO_BALANCE:
        case V4L2_CID_AUDIO_MUTE:
+               if (state->is_cx25836)
+                       return -EINVAL;
                return cx25840_audio(client, VIDIOC_G_CTRL, ctrl);
        default:
                return -EINVAL;
@@ -579,91 +617,6 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 
 /* ----------------------------------------------------------------------- */
 
-static struct v4l2_queryctrl cx25840_qctrl[] = {
-       {
-               .id            = V4L2_CID_BRIGHTNESS,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Brightness",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 1,
-               .default_value = 128,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_CONTRAST,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Contrast",
-               .minimum       = 0,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 64,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_SATURATION,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Saturation",
-               .minimum       = 0,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 64,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_HUE,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Hue",
-               .minimum       = -128,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 0,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_AUDIO_VOLUME,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Volume",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 58880,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_AUDIO_BALANCE,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Balance",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 32768,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_AUDIO_MUTE,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-               .name          = "Mute",
-               .minimum       = 0,
-               .maximum       = 1,
-               .step          = 1,
-               .default_value = 1,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_AUDIO_BASS,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Bass",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 32768,
-       }, {
-               .id            = V4L2_CID_AUDIO_TREBLE,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Treble",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 32768,
-       },
-};
-
-/* ----------------------------------------------------------------------- */
-
 static int cx25840_command(struct i2c_client *client, unsigned int cmd,
                           void *arg)
 {
@@ -706,8 +659,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
 
        case VIDIOC_STREAMON:
                v4l_dbg(1, cx25840_debug, client, "enable output\n");
-               cx25840_write(client, 0x115, 0x8c);
-               cx25840_write(client, 0x116, 0x07);
+               cx25840_write(client, 0x115, state->is_cx25836 ? 0x0c : 0x8c);
+               cx25840_write(client, 0x116, state->is_cx25836 ? 0x04 : 0x07);
                break;
 
        case VIDIOC_STREAMOFF:
@@ -717,7 +670,9 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
                break;
 
        case VIDIOC_LOG_STATUS:
-               log_status(client);
+               log_video_status(client);
+               if (!state->is_cx25836)
+                       log_audio_status(client);
                break;
 
        case VIDIOC_G_CTRL:
@@ -729,13 +684,29 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
        case VIDIOC_QUERYCTRL:
        {
                struct v4l2_queryctrl *qc = arg;
-               int i;
 
-               for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++)
-                       if (qc->id && qc->id == cx25840_qctrl[i].id) {
-                               memcpy(qc, &cx25840_qctrl[i], sizeof(*qc));
-                               return 0;
-                       }
+               switch (qc->id) {
+                       case V4L2_CID_BRIGHTNESS:
+                       case V4L2_CID_CONTRAST:
+                       case V4L2_CID_SATURATION:
+                       case V4L2_CID_HUE:
+                               return v4l2_ctrl_query_fill_std(qc);
+                       default:
+                               break;
+               }
+               if (state->is_cx25836)
+                       return -EINVAL;
+
+               switch (qc->id) {
+                       case V4L2_CID_AUDIO_VOLUME:
+                       case V4L2_CID_AUDIO_MUTE:
+                       case V4L2_CID_AUDIO_BALANCE:
+                       case V4L2_CID_AUDIO_BASS:
+                       case V4L2_CID_AUDIO_TREBLE:
+                               return v4l2_ctrl_query_fill_std(qc);
+                       default:
+                               return -EINVAL;
+               }
                return -EINVAL;
        }
 
@@ -760,31 +731,41 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
                return set_input(client, route->input, state->aud_input);
 
        case VIDIOC_INT_G_AUDIO_ROUTING:
+               if (state->is_cx25836)
+                       return -EINVAL;
                route->input = state->aud_input;
                route->output = 0;
                break;
 
        case VIDIOC_INT_S_AUDIO_ROUTING:
+               if (state->is_cx25836)
+                       return -EINVAL;
                return set_input(client, state->vid_input, route->input);
 
        case VIDIOC_S_FREQUENCY:
-               input_change(client);
+               if (!state->is_cx25836) {
+                       input_change(client);
+               }
                break;
 
        case VIDIOC_G_TUNER:
        {
-               u8 mode = cx25840_read(client, 0x804);
-               u8 vpres = cx25840_read(client, 0x80a) & 0x10;
+               u8 vpres = cx25840_read(client, 0x40e) & 0x20;
+               u8 mode;
                int val = 0;
 
                if (state->radio)
                        break;
 
+               vt->signal = vpres ? 0xffff : 0x0;
+               if (state->is_cx25836)
+                       break;
+
                vt->capability |=
                    V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
                    V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
 
-               vt->signal = vpres ? 0xffff : 0x0;
+               mode = cx25840_read(client, 0x804);
 
                /* get rxsubchans and audmode */
                if ((mode & 0xf) == 1)
@@ -804,7 +785,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
        }
 
        case VIDIOC_S_TUNER:
-               if (state->radio)
+               if (state->radio || state->is_cx25836)
                        break;
 
                switch (vt->audmode) {
@@ -846,12 +827,14 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
                return set_v4lfmt(client, (struct v4l2_format *)arg);
 
        case VIDIOC_INT_RESET:
-               cx25840_initialize(client, 0);
+               if (state->is_cx25836)
+                       cx25836_initialize(client);
+               else
+                       cx25840_initialize(client, 0);
                break;
 
        case VIDIOC_INT_G_CHIP_IDENT:
-               *(enum v4l2_chip_ident *)arg =
-                       V4L2_IDENT_CX25840 + ((cx25840_read(client, 0x100) >> 4) & 0xf);
+               *(enum v4l2_chip_ident *)arg = state->id;
                break;
 
        default:
@@ -870,6 +853,7 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
 {
        struct i2c_client *client;
        struct cx25840_state *state;
+       enum v4l2_chip_ident id;
        u16 device_id;
 
        /* Check if the adapter supports the needed features
@@ -878,10 +862,11 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
        if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
                return 0;
 
-       client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-       if (client == 0)
+       state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL);
+       if (state == 0)
                return -ENOMEM;
 
+       client = &state->c;
        client->addr = address;
        client->adapter = adapter;
        client->driver = &i2c_driver_cx25840;
@@ -893,10 +878,18 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
        device_id |= cx25840_read(client, 0x100);
 
        /* The high byte of the device ID should be
-        * 0x84 if chip is present */
-       if ((device_id & 0xff00) != 0x8400) {
+        * 0x83 for the cx2583x and 0x84 for the cx2584x */
+       if ((device_id & 0xff00) == 0x8300) {
+               id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;
+               state->is_cx25836 = 1;
+       }
+       else if ((device_id & 0xff00) == 0x8400) {
+               id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf);
+               state->is_cx25836 = 0;
+       }
+       else {
                v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
-               kfree(client);
+               kfree(state);
                return 0;
        }
 
@@ -905,21 +898,19 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
                    (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3,
                    address << 1, adapter->name);
 
-       state = kmalloc(sizeof(struct cx25840_state), GFP_KERNEL);
-       if (state == NULL) {
-               kfree(client);
-               return -ENOMEM;
-       }
-
        i2c_set_clientdata(client, state);
-       memset(state, 0, sizeof(struct cx25840_state));
        state->vid_input = CX25840_COMPOSITE7;
        state->aud_input = CX25840_AUDIO8;
        state->audclk_freq = 48000;
        state->pvr150_workaround = 0;
        state->audmode = V4L2_TUNER_MODE_LANG1;
+       state->vbi_line_offset = 8;
+       state->id = id;
 
-       cx25840_initialize(client, 1);
+       if (state->is_cx25836)
+               cx25836_initialize(client);
+       else
+               cx25840_initialize(client, 1);
 
        i2c_attach_client(client);
 
@@ -944,7 +935,6 @@ static int cx25840_detach_client(struct i2c_client *client)
        }
 
        kfree(state);
-       kfree(client);
 
        return 0;
 }
@@ -977,7 +967,7 @@ module_exit(m__exit);
 
 /* ----------------------------------------------------------------------- */
 
-static void log_status(struct i2c_client *client)
+static void log_video_status(struct i2c_client *client)
 {
        static const char *const fmt_strs[] = {
                "0x0",
@@ -989,9 +979,36 @@ static void log_status(struct i2c_client *client)
        };
 
        struct cx25840_state *state = i2c_get_clientdata(client);
-       u8 microctrl_vidfmt = cx25840_read(client, 0x80a);
        u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf;
        u8 gen_stat1 = cx25840_read(client, 0x40d);
+       u8 gen_stat2 = cx25840_read(client, 0x40e);
+       int vid_input = state->vid_input;
+
+       v4l_info(client, "Video signal:              %spresent\n",
+                   (gen_stat2 & 0x20) ? "" : "not ");
+       v4l_info(client, "Detected format:           %s\n",
+                   fmt_strs[gen_stat1 & 0xf]);
+
+       v4l_info(client, "Specified standard:        %s\n",
+                   vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
+
+       if (vid_input >= CX25840_COMPOSITE1 &&
+           vid_input <= CX25840_COMPOSITE8) {
+               v4l_info(client, "Specified video input:     Composite %d\n",
+                       vid_input - CX25840_COMPOSITE1 + 1);
+       } else {
+               v4l_info(client, "Specified video input:     S-Video (Luma In%d, Chroma In%d)\n",
+                       (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
+       }
+
+       v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void log_audio_status(struct i2c_client *client)
+{
+       struct cx25840_state *state = i2c_get_clientdata(client);
        u8 download_ctl = cx25840_read(client, 0x803);
        u8 mod_det_stat0 = cx25840_read(client, 0x804);
        u8 mod_det_stat1 = cx25840_read(client, 0x805);
@@ -999,15 +1016,9 @@ static void log_status(struct i2c_client *client)
        u8 pref_mode = cx25840_read(client, 0x809);
        u8 afc0 = cx25840_read(client, 0x80b);
        u8 mute_ctl = cx25840_read(client, 0x8d3);
-       int vid_input = state->vid_input;
        int aud_input = state->aud_input;
        char *p;
 
-       v4l_info(client, "Video signal:              %spresent\n",
-                   (microctrl_vidfmt & 0x10) ? "" : "not ");
-       v4l_info(client, "Detected format:           %s\n",
-                   fmt_strs[gen_stat1 & 0xf]);
-
        switch (mod_det_stat0) {
        case 0x00: p = "mono"; break;
        case 0x01: p = "stereo"; break;
@@ -1107,25 +1118,12 @@ static void log_status(struct i2c_client *client)
                v4l_info(client, "Configured audio system:   %s\n", p);
        }
 
-       v4l_info(client, "Specified standard:        %s\n",
-                   vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
-
-       if (vid_input >= CX25840_COMPOSITE1 &&
-           vid_input <= CX25840_COMPOSITE8) {
-               v4l_info(client, "Specified video input:     Composite %d\n",
-                       vid_input - CX25840_COMPOSITE1 + 1);
-       } else {
-               v4l_info(client, "Specified video input:     S-Video (Luma In%d, Chroma In%d)\n",
-                       (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
-       }
        if (aud_input) {
                v4l_info(client, "Specified audio input:     Tuner (In%d)\n", aud_input);
        } else {
                v4l_info(client, "Specified audio input:     External\n");
        }
 
-       v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
-
        switch (pref_mode & 0xf) {
        case 0: p = "mono/language A"; break;
        case 1: p = "language B"; break;
index 1736929fc20491b3548549133bf6b4d099d10ffa..28049064dd7d4d7cb02fc1314de47bf3d48d66ec 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 
+extern int cx25840_debug;
+
 /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is
    present in Hauppauge PVR-150 (and possibly PVR-500) cards that have
    certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The
 #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)
 
 struct cx25840_state {
+       struct i2c_client c;
        int pvr150_workaround;
        int radio;
        enum cx25840_video_input vid_input;
        enum cx25840_audio_input aud_input;
        u32 audclk_freq;
        int audmode;
+       int vbi_line_offset;
+       enum v4l2_chip_ident id;
+       int is_cx25836;
 };
 
 /* ----------------------------------------------------------------------- */
@@ -47,7 +53,7 @@ int cx25840_write(struct i2c_client *client, u16 addr, u8 value);
 int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
 u8 cx25840_read(struct i2c_client *client, u16 addr);
 u32 cx25840_read4(struct i2c_client *client, u16 addr);
-int cx25840_and_or(struct i2c_client *client, u16 addr, u8 mask, u8 value);
+int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
 v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client);
 
 /* ----------------------------------------------------------------------- */
index 57feca288d2bad25635254ee186bd296014d2040..6cc8bf215e851c548beedecd46d254d626dc052f 100644 (file)
@@ -84,67 +84,140 @@ static int decode_vps(u8 * dst, u8 * p)
 
 void cx25840_vbi_setup(struct i2c_client *client)
 {
+       struct cx25840_state *state = i2c_get_clientdata(client);
        v4l2_std_id std = cx25840_get_v4lstd(client);
+       int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
+       int luma_lpf,uv_lpf, comb;
+       u32 pll_int,pll_frac,pll_post;
 
+       /* datasheet startup, step 8d */
        if (std & ~V4L2_STD_NTSC) {
-               /* datasheet startup, step 8d */
                cx25840_write(client, 0x49f, 0x11);
+       } else {
+               cx25840_write(client, 0x49f, 0x14);
+       }
 
-               cx25840_write(client, 0x470, 0x84);
-               cx25840_write(client, 0x471, 0x00);
-               cx25840_write(client, 0x472, 0x2d);
-               cx25840_write(client, 0x473, 0x5d);
-
-               cx25840_write(client, 0x474, 0x24);
-               cx25840_write(client, 0x475, 0x40);
-               cx25840_write(client, 0x476, 0x24);
-               cx25840_write(client, 0x477, 0x28);
-
-               cx25840_write(client, 0x478, 0x1f);
-               cx25840_write(client, 0x479, 0x02);
+       if (std & V4L2_STD_625_50) {
+               hblank=0x084;
+               hactive=0x2d0;
+               burst=0x5d;
+               vblank=0x024;
+               vactive=0x244;
+               vblank656=0x28;
+               src_decimation=0x21f;
 
+               luma_lpf=2;
                if (std & V4L2_STD_SECAM) {
-                       cx25840_write(client, 0x47a, 0x80);
-                       cx25840_write(client, 0x47b, 0x00);
-                       cx25840_write(client, 0x47c, 0x5f);
-                       cx25840_write(client, 0x47d, 0x42);
+                       uv_lpf=0;
+                       comb=0;
+                       sc=0x0a425f;
                } else {
-                       cx25840_write(client, 0x47a, 0x90);
-                       cx25840_write(client, 0x47b, 0x20);
-                       cx25840_write(client, 0x47c, 0x63);
-                       cx25840_write(client, 0x47d, 0x82);
+                       uv_lpf=1;
+                       comb=0x20;
+                       sc=0x0a8263;
                }
-
-               cx25840_write(client, 0x47e, 0x0a);
-               cx25840_write(client, 0x47f, 0x01);
        } else {
-               /* datasheet startup, step 8d */
-               cx25840_write(client, 0x49f, 0x14);
+               hactive=720;
+               hblank=122;
+               vactive=487;
+               luma_lpf=1;
+               uv_lpf=1;
+
+               src_decimation=0x21f;
+               if (std == V4L2_STD_PAL_M) {
+                       vblank=20;
+                       vblank656=24;
+                       burst=0x61;
+                       comb=0x20;
+
+                       sc=555452;
+               } else {
+                       vblank=26;
+                       vblank656=26;
+                       burst=0x5b;
+                       comb=0x66;
+                       sc=556063;
+               }
+       }
+
+       /* DEBUG: Displays configured PLL frequency */
+       pll_int=cx25840_read(client, 0x108);
+       pll_frac=cx25840_read4(client, 0x10c)&0x1ffffff;
+       pll_post=cx25840_read(client, 0x109);
+       v4l_dbg(1, cx25840_debug, client,
+                               "PLL regs = int: %u, frac: %u, post: %u\n",
+                               pll_int,pll_frac,pll_post);
+
+       if (pll_post) {
+               int fin, fsc;
+               int pll= (28636363L*((((u64)pll_int)<<25L)+pll_frac)) >>25L;
+
+               pll/=pll_post;
+               v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n",
+                                               pll/1000000, pll%1000000);
+               v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n",
+                                               pll/8000000, (pll/8)%1000000);
+
+               fin=((u64)src_decimation*pll)>>12;
+               v4l_dbg(1, cx25840_debug, client, "ADC Sampling freq = "
+                                               "%d.%06d MHz\n",
+                                               fin/1000000,fin%1000000);
+
+               fsc= (((u64)sc)*pll) >> 24L;
+               v4l_dbg(1, cx25840_debug, client, "Chroma sub-carrier freq = "
+                                               "%d.%06d MHz\n",
+                                               fsc/1000000,fsc%1000000);
+
+               v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
+                       "vblank %i , vactive %i, vblank656 %i, src_dec %i,"
+                       "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
+                       " sc 0x%06x\n",
+                       hblank, hactive, vblank, vactive, vblank656,
+                       src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
+       }
+
+       /* Sets horizontal blanking delay and active lines */
+       cx25840_write(client, 0x470, hblank);
+       cx25840_write(client, 0x471, 0xff&(((hblank>>8)&0x3)|(hactive <<4)));
+       cx25840_write(client, 0x472, hactive>>4);
+
+       /* Sets burst gate delay */
+       cx25840_write(client, 0x473, burst);
 
-               cx25840_write(client, 0x470, 0x7a);
-               cx25840_write(client, 0x471, 0x00);
-               cx25840_write(client, 0x472, 0x2d);
-               cx25840_write(client, 0x473, 0x5b);
+       /* Sets vertical blanking delay and active duration */
+       cx25840_write(client, 0x474, vblank);
+       cx25840_write(client, 0x475, 0xff&(((vblank>>8)&0x3)|(vactive <<4)));
+       cx25840_write(client, 0x476, vactive>>4);
+       cx25840_write(client, 0x477, vblank656);
 
-               cx25840_write(client, 0x474, 0x1a);
-               cx25840_write(client, 0x475, 0x70);
-               cx25840_write(client, 0x476, 0x1e);
-               cx25840_write(client, 0x477, 0x1e);
+       /* Sets src decimation rate */
+       cx25840_write(client, 0x478, 0xff&src_decimation);
+       cx25840_write(client, 0x479, 0xff&(src_decimation>>8));
 
-               cx25840_write(client, 0x478, 0x1f);
-               cx25840_write(client, 0x479, 0x02);
-               cx25840_write(client, 0x47a, 0x50);
-               cx25840_write(client, 0x47b, 0x66);
+       /* Sets Luma and UV Low pass filters */
+       cx25840_write(client, 0x47a, luma_lpf<<6|((uv_lpf<<4)&0x30));
 
-               cx25840_write(client, 0x47c, 0x1f);
-               cx25840_write(client, 0x47d, 0x7c);
-               cx25840_write(client, 0x47e, 0x08);
+       /* Enables comb filters */
+       cx25840_write(client, 0x47b, comb);
+
+       /* Sets SC Step*/
+       cx25840_write(client, 0x47c, sc);
+       cx25840_write(client, 0x47d, 0xff&sc>>8);
+       cx25840_write(client, 0x47e, 0xff&sc>>16);
+
+       /* Sets VBI parameters */
+       if (std & V4L2_STD_625_50) {
+               cx25840_write(client, 0x47f, 0x01);
+               state->vbi_line_offset = 5;
+       } else {
                cx25840_write(client, 0x47f, 0x00);
+               state->vbi_line_offset = 8;
        }
 }
 
 int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
 {
+       struct cx25840_state *state = i2c_get_clientdata(client);
        struct v4l2_format *fmt;
        struct v4l2_sliced_vbi_format *svbi;
 
@@ -182,7 +255,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
 
        case VIDIOC_S_FMT:
        {
-               int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC);
+               int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
                int vbi_offset = is_pal ? 1 : 0;
                int i, x;
                u8 lcr[24];
@@ -211,7 +284,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
                cx25840_vbi_setup(client);
 
                /* Sliced VBI */
-               cx25840_write(client, 0x404, 0x36);     /* Ancillery data */
+               cx25840_write(client, 0x404, 0x32);     /* Ancillary data */
                cx25840_write(client, 0x406, 0x13);
                cx25840_write(client, 0x47f, vbi_offset);
 
@@ -248,8 +321,18 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
                        }
                }
 
-               for (x = 1, i = 0x424; i <= 0x434; i++, x++) {
-                       cx25840_write(client, i, lcr[6 + x]);
+               if (is_pal) {
+                       for (x = 1, i = 0x424; i <= 0x434; i++, x++) {
+                               cx25840_write(client, i, lcr[6 + x]);
+                       }
+               }
+               else {
+                       for (x = 1, i = 0x424; i <= 0x430; i++, x++) {
+                               cx25840_write(client, i, lcr[9 + x]);
+                       }
+                       for (i = 0x431; i <= 0x434; i++) {
+                               cx25840_write(client, i, 0);
+                       }
                }
 
                cx25840_write(client, 0x43c, 0x16);
@@ -257,7 +340,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
                if (is_pal) {
                        cx25840_write(client, 0x474, 0x2a);
                } else {
-                       cx25840_write(client, 0x474, 0x1a + 6);
+                       cx25840_write(client, 0x474, 0x22);
                }
                break;
        }
@@ -278,7 +361,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
                id1 = p[-1];
                id2 = p[0] & 0xf;
                l = p[2] & 0x3f;
-               l += 5;
+               l += state->vbi_line_offset;
                p += 4;
 
                switch (id2) {
index 630273992a419b05986bd00a462366db212709f4..91e1c481a164a850645e5a3b7086bedcdc966ef9 100644 (file)
@@ -11,6 +11,7 @@ config VIDEO_CX88
        select VIDEO_BUF
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
+       select VIDEO_CX2341X
        select VIDEO_IR
        ---help---
          This is a video4linux driver for Conexant 2388x based
@@ -61,6 +62,7 @@ config VIDEO_CX88_DVB_ALL_FRONTENDS
        select DVB_LGDT330X
        select DVB_NXT200X
        select DVB_CX24123
+       select DVB_ISL6421
        ---help---
          This builds cx88-dvb with all currently supported frontend
          demodulators.  If you wish to tweak your configuration, and
@@ -139,6 +141,7 @@ config VIDEO_CX88_DVB_CX24123
        default y
        depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
        select DVB_CX24123
+       select DVB_ISL6421
        ---help---
          This adds DVB-S support for cards based on the
          Connexant 2388x chip and the CX24123 demodulator.
index 320b3d9384ba1365e346ce710df52cb93ed37425..2194cbeca33b61b3c1eccf4864cbccbec44e4566 100644 (file)
@@ -4,7 +4,7 @@
  *  PCI function #1 of the cx2388x.
  *
  *    (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org>
- *    (c) 2005 Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+ *    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
  *    Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org>
  *    Based on dummy.c by Jaroslav Kysela <perex@suse.cz>
  *
@@ -111,7 +111,7 @@ MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s).");
 
 MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Ricardo Cerqueira");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@brturbo.com.br>");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
                        "{{Conexant,23882},"
@@ -696,7 +696,6 @@ static int __devinit snd_cx88_create(struct snd_card *card,
        chip->irq = -1;
        spin_lock_init(&chip->reg_lock);
 
-       cx88_reset(core);
        chip->core = core;
 
        /* get irq */
index e100d8ef369a250155cde5378c999a98201ba39b..67fd3302e8f2372949960b70567f4da282479f53 100644 (file)
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <media/v4l2-common.h>
+#include <media/cx2341x.h>
 
 #include "cx88.h"
-#include <media/v4l2-common.h>
 
 MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
 MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -53,7 +54,6 @@ static LIST_HEAD(cx8802_devlist);
 
 /* ------------------------------------------------------------------ */
 
-#define BLACKBIRD_FIRM_ENC_FILENAME "blackbird-fw-enc.bin"
 #define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024
 
 /* defines below are from ivtv-driver.h */
@@ -63,8 +63,6 @@ static LIST_HEAD(cx8802_devlist);
 /* Firmware API commands */
 #define IVTV_API_STD_TIMEOUT 500
 
-#define BLACKBIRD_API_PING               0x80
-#define BLACKBIRD_API_BEGIN_CAPTURE      0x81
 enum blackbird_capture_type {
        BLACKBIRD_MPEG_CAPTURE,
        BLACKBIRD_RAW_CAPTURE,
@@ -78,205 +76,29 @@ enum blackbird_capture_bits {
        BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
        BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE  = 0x10
 };
-#define BLACKBIRD_API_END_CAPTURE        0x82
 enum blackbird_capture_end {
        BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
        BLACKBIRD_END_NOW, /* stop immediately, no irq */
 };
-#define BLACKBIRD_API_SET_AUDIO_ID       0x89
-#define BLACKBIRD_API_SET_VIDEO_ID       0x8B
-#define BLACKBIRD_API_SET_PCR_ID         0x8D
-#define BLACKBIRD_API_SET_FRAMERATE      0x8F
 enum blackbird_framerate {
        BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
        BLACKBIRD_FRAMERATE_PAL_25   /* PAL: 25fps */
 };
-#define BLACKBIRD_API_SET_RESOLUTION     0x91
-#define BLACKBIRD_API_SET_VIDEO_BITRATE  0x95
-enum blackbird_video_bitrate_type {
-       BLACKBIRD_VIDEO_VBR,
-       BLACKBIRD_VIDEO_CBR
-};
-#define BLACKBIRD_PEAK_RATE_DIVISOR 400
-enum blackbird_mux_rate {
-       BLACKBIRD_MUX_RATE_DEFAULT,
-        /* dvd mux rate: multiply by 400 to get the actual rate */
-       BLACKBIRD_MUX_RATE_DVD = 25200
-};
-#define BLACKBIRD_API_SET_GOP_STRUCTURE  0x97
-#define BLACKBIRD_API_SET_ASPECT_RATIO   0x99
-enum blackbird_aspect_ratio {
-       BLACKBIRD_ASPECT_RATIO_FORBIDDEN,
-       BLACKBIRD_ASPECT_RATIO_1_1_SQUARE,
-       BLACKBIRD_ASPECT_RATIO_4_3,
-       BLACKBIRD_ASPECT_RATIO_16_9,
-       BLACKBIRD_ASPECT_RATIO_221_100,
-       BLACKBIRD_ASPECT_RATIO_RESERVED
-};
-#define BLACKBIRD_API_SET_DNR_MODE       0x9B
-enum blackbird_dnr_bits {
-       BLACKBIRD_DNR_BITS_MANUAL,
-       BLACKBIRD_DNR_BITS_AUTO_SPATIAL,
-       BLACKBIRD_DNR_BITS_AUTO_TEMPORAL,
-       BLACKBIRD_DNR_BITS_AUTO
-};
-enum blackbird_median_filter {
-       BLACKBIRD_MEDIAN_FILTER_DISABLED,
-       BLACKBIRD_MEDIAN_FILTER_HORIZONTAL,
-       BLACKBIRD_MEDIAN_FILTER_VERTICAL,
-       BLACKBIRD_MEDIAN_FILTER_HV,
-       BLACKBIRD_MEDIAN_FILTER_DIAGONAL
-};
-#define BLACKBIRD_API_SET_MANUAL_DNR     0x9D
-#define BLACKBIRD_API_SET_DNR_MEDIAN     0x9F
-#define BLACKBIRD_API_SET_SPATIAL_FILTER 0xA1
-enum blackbird_spatial_filter_luma {
-       BLACKBIRD_SPATIAL_FILTER_LUMA_DISABLED,
-       BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ,
-       BLACKBIRD_SPATIAL_FILTER_LUMA_1D_VERT,
-       BLACKBIRD_SPATIAL_FILTER_LUMA_2D_HV, /* separable, default */
-       BLACKBIRD_SPATIAL_FILTER_LUMA_2D_SYMM /* symmetric non-separable */
-};
-enum blackbird_spatial_filter_chroma {
-       BLACKBIRD_SPATIAL_FILTER_CHROMA_DISABLED,
-       BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ /* default */
-};
-#define BLACKBIRD_API_SET_3_2_PULLDOWN   0xB1
-enum blackbird_pulldown {
-       BLACKBIRD_3_2_PULLDOWN_DISABLED,
-       BLACKBIRD_3_2_PULLDOWN_ENABLED
-};
-#define BLACKBIRD_API_SET_VBI_LINE_NO    0xB7
-enum blackbird_vbi_line_bits {
-       BLACKBIRD_VBI_LINE_BITS_TOP_FIELD,
-       BLACKBIRD_VBI_LINE_BITS_BOT_FIELD = (1 << 31),
-       BLACKBIRD_VBI_LINE_BITS_ALL_LINES = 0xFFFFFFFF
-};
-enum blackbird_vbi_line {
-       BLACKBIRD_VBI_LINE_DISABLED,
-       BLACKBIRD_VBI_LINE_ENABLED
-};
-enum blackbird_vbi_slicing {
-       BLACKBIRD_VBI_SLICING_NONE,
-       BLACKBIRD_VBI_SLICING_CLOSED_CAPTION
-};
-#define BLACKBIRD_API_SET_STREAM_TYPE    0xB9
-enum blackbird_stream_type {
-       BLACKBIRD_STREAM_PROGRAM,
-       BLACKBIRD_STREAM_TRANSPORT,
-       BLACKBIRD_STREAM_MPEG1,
-       BLACKBIRD_STREAM_PES_AV,
-       BLACKBIRD_STREAM_UNKNOWN4,
-       BLACKBIRD_STREAM_PES_VIDEO,
-       BLACKBIRD_STREAM_UNKNOWN6,
-       BLACKBIRD_STREAM_PES_AUDIO,
-       BLACKBIRD_STREAM_UNKNOWN8,
-       BLACKBIRD_STREAM_UNKNOWN9, /* audio/pcm ? */
-       BLACKBIRD_STREAM_DVD,
-       BLACKBIRD_STREAM_VCD,
-       BLACKBIRD_STREAM_UNKNOWN12 /* svcd/xvcd ? */
-};
-#define BLACKBIRD_API_SET_OUTPUT_PORT    0xBB
 enum blackbird_stream_port {
        BLACKBIRD_OUTPUT_PORT_MEMORY,
        BLACKBIRD_OUTPUT_PORT_STREAMING,
        BLACKBIRD_OUTPUT_PORT_SERIAL
 };
-#define BLACKBIRD_API_SET_AUDIO_PARAMS   0xBD
-enum blackbird_audio_bits_sample_rate {
-       BLACKBIRD_AUDIO_BITS_44100HZ,
-       BLACKBIRD_AUDIO_BITS_48000HZ,
-       BLACKBIRD_AUDIO_BITS_32000HZ,
-       BLACKBIRD_AUDIO_BITS_RESERVED_HZ,
-};
-enum blackbird_audio_bits_encoding {
-       BLACKBIRD_AUDIO_BITS_LAYER_1 = 0x1 << 2,
-       BLACKBIRD_AUDIO_BITS_LAYER_2 = 0x2 << 2,
-};
-enum blackbird_audio_bits_bitrate_layer_1 {
-       BLACKBIRD_AUDIO_BITS_LAYER_1_FREE_FORMAT,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_32  = 0x01 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_64  = 0x02 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_96  = 0x03 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_128 = 0x04 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_160 = 0x05 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_192 = 0x06 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_224 = 0x07 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_256 = 0x08 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_288 = 0x09 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_320 = 0x0A << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_352 = 0x0B << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_384 = 0x0C << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_416 = 0x0D << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_1_448 = 0x0E << 4,
-};
-enum blackbird_audio_bits_bitrate_layer_2 {
-       BLACKBIRD_AUDIO_BITS_LAYER_2_FREE_FORMAT,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_32  = 0x01 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_48  = 0x02 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_56  = 0x03 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_64  = 0x04 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_80  = 0x05 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_96  = 0x06 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_112 = 0x07 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_128 = 0x08 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_160 = 0x09 << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_192 = 0x0A << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_224 = 0x0B << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_256 = 0x0C << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_320 = 0x0D << 4,
-       BLACKBIRD_AUDIO_BITS_LAYER_2_384 = 0x0E << 4,
-};
-enum blackbird_audio_bits_mode {
-       BLACKBIRD_AUDIO_BITS_STEREO,
-       BLACKBIRD_AUDIO_BITS_JOINT_STEREO = 0x1 << 8,
-       BLACKBIRD_AUDIO_BITS_DUAL         = 0x2 << 8,
-       BLACKBIRD_AUDIO_BITS_MONO         = 0x3 << 8,
-};
-enum blackbird_audio_bits_mode_extension {
-       BLACKBIRD_AUDIO_BITS_BOUND_4,
-       BLACKBIRD_AUDIO_BITS_BOUND_8  = 0x1 << 10,
-       BLACKBIRD_AUDIO_BITS_BOUND_12 = 0x2 << 10,
-       BLACKBIRD_AUDIO_BITS_BOUND_16 = 0x3 << 10,
-};
-enum blackbird_audio_bits_emphasis {
-       BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE,
-       BLACKBIRD_AUDIO_BITS_EMPHASIS_50_15     = 0x1 << 12,
-       BLACKBIRD_AUDIO_BITS_EMPHASIS_RESERVED  = 0x2 << 12,
-       BLACKBIRD_AUDIO_BITS_EMPHASIS_CCITT_J17 = 0x3 << 12,
-};
-enum blackbird_audio_bits_crc {
-       BLACKBIRD_AUDIO_BITS_CRC_OFF,
-       BLACKBIRD_AUDIO_BITS_CRC_ON = 0x1 << 14,
-};
-enum blackbird_audio_bits_copyright {
-       BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF,
-       BLACKBIRD_AUDIO_BITS_COPYRIGHT_ON = 0x1 << 15,
-};
-enum blackbird_audio_bits_original {
-       BLACKBIRD_AUDIO_BITS_COPY,
-       BLACKBIRD_AUDIO_BITS_ORIGINAL = 0x1 << 16,
-};
-#define BLACKBIRD_API_HALT               0xC3
-#define BLACKBIRD_API_GET_VERSION        0xC4
-#define BLACKBIRD_API_SET_GOP_CLOSURE    0xC5
-enum blackbird_gop_closure {
-       BLACKBIRD_GOP_CLOSURE_OFF,
-       BLACKBIRD_GOP_CLOSURE_ON,
-};
-#define BLACKBIRD_API_DATA_XFER_STATUS   0xC6
 enum blackbird_data_xfer_status {
        BLACKBIRD_MORE_BUFFERS_FOLLOW,
        BLACKBIRD_LAST_BUFFER,
 };
-#define BLACKBIRD_API_PROGRAM_INDEX_INFO 0xC7
 enum blackbird_picture_mask {
        BLACKBIRD_PICTURE_MASK_NONE,
        BLACKBIRD_PICTURE_MASK_I_FRAMES,
        BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
        BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
 };
-#define BLACKBIRD_API_SET_VBI_PARAMS     0xC8
 enum blackbird_vbi_mode_bits {
        BLACKBIRD_VBI_BITS_SLICED,
        BLACKBIRD_VBI_BITS_RAW,
@@ -288,33 +110,23 @@ enum blackbird_vbi_insertion_bits {
        BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
        BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
 };
-#define BLACKBIRD_API_SET_DMA_BLOCK_SIZE 0xC9
 enum blackbird_dma_unit {
        BLACKBIRD_DMA_BYTES,
        BLACKBIRD_DMA_FRAMES,
 };
-#define BLACKBIRD_API_DMA_TRANSFER_INFO  0xCA
-#define BLACKBIRD_API_DMA_TRANSFER_STAT  0xCB
 enum blackbird_dma_transfer_status_bits {
        BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
        BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
        BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
 };
-#define BLACKBIRD_API_SET_DMA2HOST_ADDR  0xCC
-#define BLACKBIRD_API_INIT_VIDEO_INPUT   0xCD
-#define BLACKBIRD_API_SET_FRAMESKIP      0xD0
-#define BLACKBIRD_API_PAUSE              0xD2
 enum blackbird_pause {
        BLACKBIRD_PAUSE_ENCODING,
        BLACKBIRD_RESUME_ENCODING,
 };
-#define BLACKBIRD_API_REFRESH_INPUT      0xD3
-#define BLACKBIRD_API_SET_COPYRIGHT      0xD4
 enum blackbird_copyright {
        BLACKBIRD_COPYRIGHT_OFF,
        BLACKBIRD_COPYRIGHT_ON,
 };
-#define BLACKBIRD_API_SET_NOTIFICATION   0xD5
 enum blackbird_notification_type {
        BLACKBIRD_NOTIFICATION_REFRESH,
 };
@@ -325,7 +137,6 @@ enum blackbird_notification_status {
 enum blackbird_notification_mailbox {
        BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
 };
-#define BLACKBIRD_API_SET_CAPTURE_LINES  0xD6
 enum blackbird_field1_lines {
        BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
        BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
@@ -336,12 +147,10 @@ enum blackbird_field2_lines {
        BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
        BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
 };
-#define BLACKBIRD_API_SET_CUSTOM_DATA    0xD7
 enum blackbird_custom_data_type {
        BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
        BLACKBIRD_CUSTOM_PRIVATE_PACKET,
 };
-#define BLACKBIRD_API_MUTE_VIDEO         0xD9
 enum blackbird_mute {
        BLACKBIRD_UNMUTE,
        BLACKBIRD_MUTE,
@@ -356,7 +165,6 @@ enum blackbird_mute_video_shift {
        BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
        BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
 };
-#define BLACKBIRD_API_MUTE_AUDIO         0xDA
 
 /* Registers */
 #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
@@ -498,15 +306,12 @@ static int register_read(struct cx88_core *core, u32 address, u32 *value)
 
 /* ------------------------------------------------------------------ */
 
-/* We don't need to call the API often, so using just one mailbox will probably suffice */
-static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
-                            u32 inputcnt, u32 outputcnt, ...)
+static int blackbird_mbox_func(void *priv, int command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
 {
+       struct cx8802_dev *dev = priv;
        unsigned long timeout;
        u32 value, flag, retval;
        int i;
-       va_list args;
-       va_start(args, outputcnt);
 
        dprintk(1,"%s: 0x%X\n", __FUNCTION__, command);
 
@@ -530,12 +335,11 @@ static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
        /* write command + args + fill remaining with zeros */
        memory_write(dev->core, dev->mailbox + 1, command); /* command code */
        memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
-       for (i = 0; i < inputcnt ; i++) {
-               value = va_arg(args, int);
-               memory_write(dev->core, dev->mailbox + 4 + i, value);
-               dprintk(1, "API Input %d = %d\n", i, value);
+       for (i = 0; i < in; i++) {
+               memory_write(dev->core, dev->mailbox + 4 + i, data[i]);
+               dprintk(1, "API Input %d = %d\n", i, data[i]);
        }
-       for (; i < 16 ; i++)
+       for (; i < CX2341X_MBOX_MAX_DATA; i++)
                memory_write(dev->core, dev->mailbox + 4 + i, 0);
 
        flag |= 3; /* tell 'em we're done writing */
@@ -555,12 +359,10 @@ static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
        }
 
        /* read output values */
-       for (i = 0; i < outputcnt ; i++) {
-               int *vptr = va_arg(args, int *);
-               memory_read(dev->core, dev->mailbox + 4 + i, vptr);
-               dprintk(1, "API Output %d = %d\n", i, *vptr);
+       for (i = 0; i < out; i++) {
+               memory_read(dev->core, dev->mailbox + 4 + i, data + i);
+               dprintk(1, "API Output %d = %d\n", i, data[i]);
        }
-       va_end(args);
 
        memory_read(dev->core, dev->mailbox + 2, &retval);
        dprintk(1, "API result = %d\n",retval);
@@ -569,7 +371,29 @@ static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
        memory_write(dev->core, dev->mailbox, flag);
        return retval;
 }
+/* ------------------------------------------------------------------ */
 
+/* We don't need to call the API often, so using just one mailbox will probably suffice */
+static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
+                            u32 inputcnt, u32 outputcnt, ...)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       va_list vargs;
+       int i, err;
+
+       va_start(vargs, outputcnt);
+
+       for (i = 0; i < inputcnt; i++) {
+               data[i] = va_arg(vargs, int);
+       }
+       err = blackbird_mbox_func(dev, command, inputcnt, outputcnt, data);
+       for (i = 0; i < outputcnt; i++) {
+               int *vptr = va_arg(vargs, int *);
+               *vptr = data[i];
+       }
+       va_end(vargs);
+       return err;
+}
 
 static int blackbird_find_mailbox(struct cx8802_dev *dev)
 {
@@ -614,13 +438,13 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
        if (retval < 0)
                dprintk(0, "Error with register_write\n");
 
-       retval = request_firmware(&firmware, BLACKBIRD_FIRM_ENC_FILENAME,
+       retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
                                  &dev->pci->dev);
 
 
        if (retval != 0) {
                dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
-                       BLACKBIRD_FIRM_ENC_FILENAME);
+                       CX2341X_FIRM_ENC_FILENAME);
                dprintk(0, "Please fix your hotplug setup, the board will "
                        "not work without firmware loaded!\n");
                return -1;
@@ -686,12 +510,19 @@ DB* DVD | MPEG2 | 720x576PAL | CBR     | 600 :Good    | 6000 Kbps  | 25fps   | M
 *DB: "DirectBurn"
 */
 
-static struct blackbird_dnr default_dnr_params = {
-       .mode     = BLACKBIRD_DNR_BITS_MANUAL,
-       .type     = BLACKBIRD_MEDIAN_FILTER_DISABLED,
-       .spatial  = 0,
-       .temporal = 0
-};
+static void blackbird_codec_settings(struct cx8802_dev *dev)
+{
+       /* assign frame size */
+       blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+                               dev->height, dev->width);
+
+       dev->params.width = dev->width;
+       dev->params.height = dev->height;
+       dev->params.is_50hz = (dev->core->tvnorm->id & V4L2_STD_625_50) != 0;
+
+       cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);
+}
+
 static struct v4l2_mpeg_compression default_mpeg_params = {
        .st_type          = V4L2_MPEG_PS_2,
        .st_bitrate       = {
@@ -712,7 +543,7 @@ static struct v4l2_mpeg_compression default_mpeg_params = {
                .target   = 224,
                .max      = 224
        },
-       .au_sample_rate    = 44100,
+       .au_sample_rate    = 48000,
        .au_pesid          = 0,
        .vi_type           = V4L2_MPEG_VI_2,
        .vi_aspect_ratio   = V4L2_MPEG_ASPECT_4_3,
@@ -723,524 +554,13 @@ static struct v4l2_mpeg_compression default_mpeg_params = {
                .max       = 6000
        },
        .vi_frame_rate     = 25,
-       .vi_frames_per_gop = 15,
+       .vi_frames_per_gop = 12,
        .vi_bframes_count  = 2,
        .vi_pesid          = 0,
-       .closed_gops       = 0,
+       .closed_gops       = 1,
        .pulldown          = 0
 };
 
-static enum blackbird_stream_type mpeg_stream_types[] = {
-       [V4L2_MPEG_SS_1]   = BLACKBIRD_STREAM_MPEG1,
-       [V4L2_MPEG_PS_2]   = BLACKBIRD_STREAM_PROGRAM,
-       [V4L2_MPEG_TS_2]   = BLACKBIRD_STREAM_TRANSPORT,
-       [V4L2_MPEG_PS_DVD] = BLACKBIRD_STREAM_DVD,
-};
-static enum blackbird_aspect_ratio mpeg_stream_ratios[] = {
-       [V4L2_MPEG_ASPECT_SQUARE] = BLACKBIRD_ASPECT_RATIO_1_1_SQUARE,
-       [V4L2_MPEG_ASPECT_4_3]    = BLACKBIRD_ASPECT_RATIO_4_3,
-       [V4L2_MPEG_ASPECT_16_9]   = BLACKBIRD_ASPECT_RATIO_16_9,
-       [V4L2_MPEG_ASPECT_1_221]  = BLACKBIRD_ASPECT_RATIO_221_100,
-};
-static enum blackbird_video_bitrate_type mpeg_video_bitrates[] = {
-       [V4L2_BITRATE_NONE] = BLACKBIRD_VIDEO_CBR,
-       [V4L2_BITRATE_CBR]  = BLACKBIRD_VIDEO_CBR,
-       [V4L2_BITRATE_VBR]  = BLACKBIRD_VIDEO_VBR,
-};
-/* find the best layer I/II bitrate to fit a given numeric value */
-struct bitrate_bits {
-       u32 bits; /* layer bits for the best fit */
-       u32 rate; /* actual numeric value for the layer best fit */
-};
-struct bitrate_approximation {
-       u32                 target;   /* numeric value of the rate we want */
-       struct bitrate_bits layer[2];
-};
-static struct bitrate_approximation mpeg_audio_bitrates[] = {
-       /* target  layer[0].bits           layer[0].rate       layer[1].bits           layer[1].rate */
-       {   0, { {                                0,   0, }, {                                0,   0, }, }, },
-       {  32, { { BLACKBIRD_AUDIO_BITS_LAYER_1_32 ,  32, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_32 ,  32, }, }, },
-       {  48, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 ,  64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_48 ,  48, }, }, },
-       {  56, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 ,  64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_56 ,  56, }, }, },
-       {  64, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 ,  64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_64 ,  64, }, }, },
-       {  80, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 ,  96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_80 ,  80, }, }, },
-       {  96, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 ,  96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_96 ,  96, }, }, },
-       { 112, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_112, 112, }, }, },
-       { 128, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_128, 128, }, }, },
-       { 160, { { BLACKBIRD_AUDIO_BITS_LAYER_1_160, 160, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_160, 160, }, }, },
-       { 192, { { BLACKBIRD_AUDIO_BITS_LAYER_1_192, 192, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_192, 192, }, }, },
-       { 224, { { BLACKBIRD_AUDIO_BITS_LAYER_1_224, 224, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_224, 224, }, }, },
-       { 256, { { BLACKBIRD_AUDIO_BITS_LAYER_1_256, 256, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_256, 256, }, }, },
-       { 288, { { BLACKBIRD_AUDIO_BITS_LAYER_1_288, 288, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, },
-       { 320, { { BLACKBIRD_AUDIO_BITS_LAYER_1_320, 320, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, },
-       { 352, { { BLACKBIRD_AUDIO_BITS_LAYER_1_352, 352, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
-       { 384, { { BLACKBIRD_AUDIO_BITS_LAYER_1_384, 384, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
-       { 416, { { BLACKBIRD_AUDIO_BITS_LAYER_1_416, 416, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
-       { 448, { { BLACKBIRD_AUDIO_BITS_LAYER_1_448, 448, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
-};
-static const int BITRATES_SIZE = ARRAY_SIZE(mpeg_audio_bitrates);
-
-static void blackbird_set_default_params(struct cx8802_dev *dev)
-{
-       struct v4l2_mpeg_compression *params = &dev->params;
-       u32 au_params;
-
-       /* assign stream type */
-       if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) )
-               params->st_type = V4L2_MPEG_PS_2;
-       if( params->st_type == V4L2_MPEG_SS_1 )
-               params->vi_type = V4L2_MPEG_VI_1;
-       else
-               params->vi_type = V4L2_MPEG_VI_2;
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]);
-
-       /* assign framerate */
-       if( params->vi_frame_rate <= 25 )
-       {
-               params->vi_frame_rate = 25;
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25);
-       }
-       else
-       {
-               params->vi_frame_rate = 30;
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30);
-       }
-
-       /* assign aspect ratio */
-       if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) )
-               params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3;
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]);
-
-       /* assign gop properties */
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1);
-
-       /* assign gop closure */
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops);
-
-       /* assign 3 2 pulldown */
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown);
-
-       /* make sure the params are within bounds */
-       if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-               params->vi_bitrate.mode = V4L2_BITRATE_NONE;
-       if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-               params->vi_bitrate.mode = V4L2_BITRATE_NONE;
-       if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-               params->au_bitrate.mode = V4L2_BITRATE_NONE;
-
-       /* assign audio properties */
-       /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
-       au_params = BLACKBIRD_AUDIO_BITS_STEREO |
-                       /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */
-                       BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE |
-                       BLACKBIRD_AUDIO_BITS_CRC_OFF |
-                       BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF |
-                       BLACKBIRD_AUDIO_BITS_COPY |
-                       0;
-       if( params->au_sample_rate <= 32000 )
-       {
-               params->au_sample_rate = 32000;
-               au_params |= BLACKBIRD_AUDIO_BITS_32000HZ;
-       }
-       else if( params->au_sample_rate <= 44100 )
-       {
-               params->au_sample_rate = 44100;
-               au_params |= BLACKBIRD_AUDIO_BITS_44100HZ;
-       }
-       else
-       {
-               params->au_sample_rate = 48000;
-               au_params |= BLACKBIRD_AUDIO_BITS_48000HZ;
-       }
-       if( params->au_type == V4L2_MPEG_AU_2_I )
-       {
-               au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1;
-       }
-       else
-       {
-               /* TODO: try to handle the other formats more gracefully */
-               params->au_type = V4L2_MPEG_AU_2_II;
-               au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2;
-       }
-       if( params->au_bitrate.mode )
-       {
-               int layer;
-
-               if( params->au_bitrate.mode == V4L2_BITRATE_CBR )
-                       params->au_bitrate.max = params->vi_bitrate.target;
-               else
-                       params->au_bitrate.target = params->vi_bitrate.max;
-
-               layer = params->au_type;
-               if( params->au_bitrate.target == 0 )
-               {
-                       /* TODO: use the minimum possible bitrate instead of 0 ? */
-                       au_params |= 0;
-               }
-               else if( params->au_bitrate.target >=
-                        mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate )
-               {
-                       /* clamp the bitrate to the max supported by the standard */
-                       params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate;
-                       params->au_bitrate.max = params->au_bitrate.target;
-                       au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits;
-               }
-               else
-               {
-                       /* round up to the nearest supported bitrate */
-                       int i;
-                       for(i = 1; i < BITRATES_SIZE; i++)
-                       {
-                               if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate &&
-                                   params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate )
-                               {
-                                       params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate;
-                                       params->au_bitrate.max = params->au_bitrate.target;
-                                       au_params |= mpeg_audio_bitrates[i].layer[layer].bits;
-                                       break;
-                               }
-                       }
-               }
-       }
-       else
-       {
-               /* TODO: ??? */
-               params->au_bitrate.target = params->au_bitrate.max = 0;
-               au_params |= 0;
-       }
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params );
-
-       /* assign bitrates */
-       if( params->vi_bitrate.mode )
-       {
-               /* bitrate is set, let's figure out the cbr/vbr mess */
-               if( params->vi_bitrate.max < params->vi_bitrate.target )
-               {
-                       if( params->vi_bitrate.mode == V4L2_BITRATE_CBR )
-                               params->vi_bitrate.max = params->vi_bitrate.target;
-                       else
-                               params->vi_bitrate.target = params->vi_bitrate.max;
-               }
-       }
-       else
-       {
-               if( params->st_bitrate.max < params->st_bitrate.target )
-               {
-                       if( params->st_bitrate.mode == V4L2_BITRATE_VBR )
-                               params->st_bitrate.target = params->st_bitrate.max;
-                       else
-                               params->st_bitrate.max = params->st_bitrate.target;
-               }
-               /* calculate vi_bitrate = st_bitrate - au_bitrate */
-               params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max;
-               params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target;
-       }
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0,
-                               mpeg_video_bitrates[params->vi_bitrate.mode],
-                               params->vi_bitrate.target * 1000, /* kbps -> bps */
-                               params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */
-                               BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */
-
-       /* TODO: implement the stream ID stuff:
-               ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr,
-               ps_size, au_pesid, vi_pesid
-       */
-}
-#define CHECK_PARAM( name ) ( dev->params.name != params->name )
-#define IF_PARAM( name ) if( CHECK_PARAM( name ) )
-#define UPDATE_PARAM( name ) dev->params.name = params->name
-void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression *params)
-{
-       u32 au_params;
-
-       /* assign stream type */
-       if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) )
-               params->st_type = V4L2_MPEG_PS_2;
-       if( params->st_type == V4L2_MPEG_SS_1 )
-               params->vi_type = V4L2_MPEG_VI_1;
-       else
-               params->vi_type = V4L2_MPEG_VI_2;
-       if( CHECK_PARAM( st_type ) || CHECK_PARAM( vi_type ) )
-       {
-               UPDATE_PARAM( st_type );
-               UPDATE_PARAM( vi_type );
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]);
-       }
-
-       /* assign framerate */
-       if( params->vi_frame_rate <= 25 )
-               params->vi_frame_rate = 25;
-       else
-               params->vi_frame_rate = 30;
-       IF_PARAM( vi_frame_rate )
-       {
-               UPDATE_PARAM( vi_frame_rate );
-               if( params->vi_frame_rate == 25 )
-                       blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25);
-               else
-                       blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30);
-       }
-
-       /* assign aspect ratio */
-       if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) )
-               params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3;
-       IF_PARAM( vi_aspect_ratio )
-       {
-               UPDATE_PARAM( vi_aspect_ratio );
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]);
-       }
-
-       /* assign gop properties */
-       if( CHECK_PARAM( vi_frames_per_gop ) || CHECK_PARAM( vi_bframes_count ) )
-       {
-               UPDATE_PARAM( vi_frames_per_gop );
-               UPDATE_PARAM( vi_bframes_count );
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1);
-       }
-
-       /* assign gop closure */
-       IF_PARAM( closed_gops )
-       {
-               UPDATE_PARAM( closed_gops );
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops);
-       }
-
-       /* assign 3 2 pulldown */
-       IF_PARAM( pulldown )
-       {
-               UPDATE_PARAM( pulldown );
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown);
-       }
-
-       /* make sure the params are within bounds */
-       if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-               params->vi_bitrate.mode = V4L2_BITRATE_NONE;
-       if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-               params->vi_bitrate.mode = V4L2_BITRATE_NONE;
-       if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-               params->au_bitrate.mode = V4L2_BITRATE_NONE;
-
-       /* assign audio properties */
-       /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
-       au_params = BLACKBIRD_AUDIO_BITS_STEREO |
-                       /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */
-       BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE |
-               BLACKBIRD_AUDIO_BITS_CRC_OFF |
-               BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF |
-               BLACKBIRD_AUDIO_BITS_COPY |
-               0;
-       if( params->au_sample_rate < 32000 )
-       {
-               params->au_sample_rate = 32000;
-               au_params |= BLACKBIRD_AUDIO_BITS_32000HZ;
-       }
-       else if( params->au_sample_rate < 44100 )
-       {
-               params->au_sample_rate = 44100;
-               au_params |= BLACKBIRD_AUDIO_BITS_44100HZ;
-       }
-       else
-       {
-               params->au_sample_rate = 48000;
-               au_params |= BLACKBIRD_AUDIO_BITS_48000HZ;
-       }
-       if( params->au_type == V4L2_MPEG_AU_2_I )
-       {
-               au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1;
-       }
-       else
-       {
-               /* TODO: try to handle the other formats more gracefully */
-               params->au_type = V4L2_MPEG_AU_2_II;
-               au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2;
-       }
-       if( params->au_bitrate.mode )
-       {
-               int layer;
-
-               if( params->au_bitrate.mode == V4L2_BITRATE_CBR )
-                       params->au_bitrate.max = params->vi_bitrate.target;
-               else
-                       params->au_bitrate.target = params->vi_bitrate.max;
-
-               layer = params->au_type;
-               if( params->au_bitrate.target == 0 )
-               {
-                       /* TODO: use the minimum possible bitrate instead of 0 ? */
-                       au_params |= 0;
-               }
-               else if( params->au_bitrate.target >=
-                        mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate )
-               {
-                       /* clamp the bitrate to the max supported by the standard */
-                       params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate;
-                       params->au_bitrate.max = params->au_bitrate.target;
-                       au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits;
-               }
-               else
-               {
-                       /* round up to the nearest supported bitrate */
-                       int i;
-                       for(i = 1; i < BITRATES_SIZE; i++)
-                       {
-                               if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate &&
-                                   params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate )
-                               {
-                                       params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate;
-                                       params->au_bitrate.max = params->au_bitrate.target;
-                                       au_params |= mpeg_audio_bitrates[i].layer[layer].bits;
-                                       break;
-                               }
-                       }
-               }
-       }
-       else
-       {
-               /* TODO: ??? */
-               params->au_bitrate.target = params->au_bitrate.max = 0;
-               au_params |= 0;
-       }
-       if( CHECK_PARAM( au_type ) || CHECK_PARAM( au_sample_rate )
-               || CHECK_PARAM( au_bitrate.mode ) || CHECK_PARAM( au_bitrate.max )
-               || CHECK_PARAM( au_bitrate.target )
-       )
-       {
-               UPDATE_PARAM( au_type );
-               UPDATE_PARAM( au_sample_rate );
-               UPDATE_PARAM( au_bitrate );
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params );
-       }
-
-       /* assign bitrates */
-       if( params->vi_bitrate.mode )
-       {
-               /* bitrate is set, let's figure out the cbr/vbr mess */
-               if( params->vi_bitrate.max < params->vi_bitrate.target )
-               {
-                       if( params->vi_bitrate.mode == V4L2_BITRATE_CBR )
-                               params->vi_bitrate.max = params->vi_bitrate.target;
-                       else
-                               params->vi_bitrate.target = params->vi_bitrate.max;
-               }
-       }
-       else
-       {
-               if( params->st_bitrate.max < params->st_bitrate.target )
-               {
-                       if( params->st_bitrate.mode == V4L2_BITRATE_VBR )
-                               params->st_bitrate.target = params->st_bitrate.max;
-                       else
-                               params->st_bitrate.max = params->st_bitrate.target;
-               }
-               /* calculate vi_bitrate = st_bitrate - au_bitrate */
-               params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max;
-               params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target;
-       }
-       UPDATE_PARAM( st_bitrate );
-       if( CHECK_PARAM( vi_bitrate.mode ) || CHECK_PARAM( vi_bitrate.max )
-               || CHECK_PARAM( vi_bitrate.target )
-       )
-       {
-               UPDATE_PARAM( vi_bitrate );
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0,
-                               mpeg_video_bitrates[params->vi_bitrate.mode],
-                               params->vi_bitrate.target * 1000, /* kbps -> bps */
-                               params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */
-                               BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */
-       }
-
-       /* TODO: implement the stream ID stuff:
-               ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr,
-               ps_size, au_pesid, vi_pesid
-       */
-       UPDATE_PARAM( ts_pid_pmt );
-       UPDATE_PARAM( ts_pid_audio );
-       UPDATE_PARAM( ts_pid_video );
-       UPDATE_PARAM( ts_pid_pcr );
-       UPDATE_PARAM( ps_size );
-       UPDATE_PARAM( au_pesid );
-       UPDATE_PARAM( vi_pesid );
-}
-
-static void blackbird_set_default_dnr_params(struct cx8802_dev *dev)
-{
-       /* assign dnr filter mode */
-       if( dev->dnr_params.mode > BLACKBIRD_DNR_BITS_AUTO )
-               dev->dnr_params.mode = BLACKBIRD_DNR_BITS_MANUAL;
-       if( dev->dnr_params.type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL )
-               dev->dnr_params.type = BLACKBIRD_MEDIAN_FILTER_DISABLED;
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0,
-                               dev->dnr_params.mode,
-                               dev->dnr_params.type
-                       );
-
-       /* assign dnr filter props*/
-       if( dev->dnr_params.spatial > 15 )
-               dev->dnr_params.spatial = 15;
-       if( dev->dnr_params.temporal > 31 )
-               dev->dnr_params.temporal = 31;
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0,
-                               dev->dnr_params.spatial,
-                               dev->dnr_params.temporal
-                       );
-}
-#define CHECK_DNR_PARAM( name ) ( dev->dnr_params.name != dnr_params->name )
-#define UPDATE_DNR_PARAM( name ) dev->dnr_params.name = dnr_params->name
-void blackbird_set_dnr_params(struct cx8802_dev *dev, struct blackbird_dnr* dnr_params)
-{
-       /* assign dnr filter mode */
-       /* clamp values */
-       if( dnr_params->mode > BLACKBIRD_DNR_BITS_AUTO )
-               dnr_params->mode = BLACKBIRD_DNR_BITS_MANUAL;
-       if( dnr_params->type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL )
-               dnr_params->type = BLACKBIRD_MEDIAN_FILTER_DISABLED;
-       /* check if the params actually changed */
-       if( CHECK_DNR_PARAM( mode ) || CHECK_DNR_PARAM( type ) )
-       {
-               UPDATE_DNR_PARAM( mode );
-               UPDATE_DNR_PARAM( type );
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, dnr_params->mode, dnr_params->type);
-       }
-
-       /* assign dnr filter props*/
-       if( dnr_params->spatial > 15 )
-               dnr_params->spatial = 15;
-       if( dnr_params->temporal > 31 )
-               dnr_params->temporal = 31;
-       if( CHECK_DNR_PARAM( spatial ) || CHECK_DNR_PARAM( temporal ) )
-       {
-               UPDATE_DNR_PARAM( spatial );
-               UPDATE_DNR_PARAM( temporal );
-               blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, dnr_params->spatial, dnr_params->temporal);
-       }
-}
-
-static void blackbird_codec_settings(struct cx8802_dev *dev)
-{
-
-       /* assign output port */
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */
-
-       /* assign frame size */
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0,
-                               dev->height, dev->width);
-
-       /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MEDIAN, 4, 0, 0, 255, 0, 255);
-
-       /* assign spatial filter type: luma_t: horiz_only, chroma_t: horiz_only */
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_SPATIAL_FILTER, 2, 0,
-                               BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ,
-                               BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ
-                       );
-
-       /* assign frame drop rate */
-       /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */
-
-       blackbird_set_default_params(dev);
-       blackbird_set_default_dnr_params(dev);
-}
-
 static int blackbird_initialize_codec(struct cx8802_dev *dev)
 {
        struct cx88_core *core = dev->core;
@@ -1248,7 +568,7 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
        int retval;
 
        dprintk(1,"Initialize codec\n");
-       retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */
+       retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
        if (retval < 0) {
                /* ping was not successful, reset and upload firmware */
                cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
@@ -1263,13 +583,13 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
                if (dev->mailbox < 0)
                        return -1;
 
-               retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */
+               retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
                if (retval < 0) {
                        dprintk(0, "ERROR: Firmware ping failed!\n");
                        return -1;
                }
 
-               retval = blackbird_api_cmd(dev, BLACKBIRD_API_GET_VERSION, 0, 1, &version);
+               retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version);
                if (retval < 0) {
                        dprintk(0, "ERROR: Firmware get encoder version failed!\n");
                        return -1;
@@ -1289,35 +609,35 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
        /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef);
           blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0);
           blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_CAPTURE_LINES, 2, 0,
+       blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
                        BLACKBIRD_FIELD1_SAA7115,
-                       BLACKBIRD_FIELD1_SAA7115
+                       BLACKBIRD_FIELD2_SAA7115
                );
 
        /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */
-       blackbird_api_cmd(dev, BLACKBIRD_API_SET_CUSTOM_DATA, 12, 0,
+       blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
                        BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
        /* initialize the video input */
-       blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0);
+       blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
 
        msleep(1);
 
-       blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE);
+       blackbird_api_cmd(dev, CX2341X_ENC_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE);
        msleep(1);
-       blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
+       blackbird_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
        msleep(1);
 
        /* start capturing to the host interface */
-       /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); */
-       blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0,
+       /* blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 0, 0x13); */
+       blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
                        BLACKBIRD_MPEG_CAPTURE,
                        BLACKBIRD_RAW_BITS_NONE
                );
        msleep(10);
 
-       blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0);
+       blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0);
        return 0;
 }
 
@@ -1485,14 +805,52 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
        {
                struct v4l2_mpeg_compression *f = arg;
 
-               memcpy(f,&dev->params,sizeof(*f));
+               printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
+                                   "Replace with VIDIOC_G_EXT_CTRLS!");
+               memcpy(f,&default_mpeg_params,sizeof(*f));
                return 0;
        }
        case VIDIOC_S_MPEGCOMP:
+               printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
+                                   "Replace with VIDIOC_S_EXT_CTRLS!");
+               return 0;
+       case VIDIOC_G_EXT_CTRLS:
        {
-               struct v4l2_mpeg_compression *f = arg;
+               struct v4l2_ext_controls *f = arg;
 
-               blackbird_set_params(dev, f);
+               if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+                       return -EINVAL;
+               return cx2341x_ext_ctrls(&dev->params, f, cmd);
+       }
+       case VIDIOC_S_EXT_CTRLS:
+       case VIDIOC_TRY_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *f = arg;
+               struct cx2341x_mpeg_params p;
+               int err;
+
+               if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+                       return -EINVAL;
+               p = dev->params;
+               err = cx2341x_ext_ctrls(&p, f, cmd);
+               if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
+                       err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
+                       dev->params = p;
+               }
+               return err;
+       }
+       case VIDIOC_S_FREQUENCY:
+       {
+               blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+                                 BLACKBIRD_END_NOW,
+                                 BLACKBIRD_MPEG_CAPTURE,
+                                 BLACKBIRD_RAW_BITS_NONE);
+
+               cx88_do_ioctl( inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook );
+
+               blackbird_initialize_codec(dev);
+               cx88_set_scale(dev->core, dev->width, dev->height,
+                              fh->mpegq.field);
                return 0;
        }
 
@@ -1562,13 +920,14 @@ static int mpeg_release(struct inode *inode, struct file *file)
 {
        struct cx8802_fh  *fh  = file->private_data;
 
-       /* blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
-       blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0,
+       /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
+       blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
                        BLACKBIRD_END_NOW,
                        BLACKBIRD_MPEG_CAPTURE,
                        BLACKBIRD_RAW_BITS_NONE
                );
 
+       cx8802_cancel_buffers(fh->dev);
        /* stop mpeg capture */
        if (fh->mpegq.streaming)
                videobuf_streamoff(&fh->mpegq);
@@ -1683,19 +1042,13 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
        dev->core = core;
        dev->width = 720;
        dev->height = 576;
-       memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params));
-       memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params));
-
-       if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) {
-
-               if (core->tuner_formats & V4L2_STD_525_60) {
-                       dev->height = 480;
-                       dev->params.vi_frame_rate = 30;
-               } else {
-                       dev->height = 576;
-                       dev->params.vi_frame_rate = 25;
-               }
+       cx2341x_fill_defaults(&dev->params);
+       dev->params.port = CX2341X_PORT_STREAMING;
 
+       if (core->tvnorm->id & V4L2_STD_525_60) {
+               dev->height = 480;
+       } else {
+               dev->height = 576;
        }
 
        err = cx8802_init_common(dev);
@@ -1781,8 +1134,6 @@ module_exit(blackbird_fini);
 
 EXPORT_SYMBOL(cx88_ioctl_hook);
 EXPORT_SYMBOL(cx88_ioctl_translator);
-EXPORT_SYMBOL(blackbird_set_params);
-EXPORT_SYMBOL(blackbird_set_dnr_params);
 
 /* ----------------------------------------------------------- */
 /*
index f80154b87d22977d337e4d0159472ca8b074f899..67cdd82708630fc921b94be343a61847fe24edc0 100644 (file)
@@ -114,7 +114,7 @@ struct cx88_board cx88_boards[] = {
                .radio = {
                         .type  = CX88_RADIO,
                         .gpio0 = 0xff10,
-                },
+               },
        },
        [CX88_BOARD_ATI_WONDER_PRO] = {
                .name           = "ATI TV Wonder Pro",
@@ -267,7 +267,7 @@ struct cx88_board cx88_boards[] = {
                        .gpio1  = 0x00007004,
                        .gpio2  = 0x0035d700,
                        .gpio3  = 0x02000000,
-                },
+               },
        },
        [CX88_BOARD_LEADTEK_PVR2000] = {
                // gpio values for PAL version from regspy by DScaler
@@ -413,7 +413,7 @@ struct cx88_board cx88_boards[] = {
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
                        .gpio0  = 0x000027df,
-                },{
+               },{
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
                        .gpio0  = 0x000027df,
@@ -536,7 +536,7 @@ struct cx88_board cx88_boards[] = {
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
                        .gpio0  = 0x000027df,
-                },{
+               },{
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
                        .gpio0  = 0x000027df,
@@ -759,7 +759,7 @@ struct cx88_board cx88_boards[] = {
        },
        [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = {
                .name           = "DViCO FusionHDTV 5 Gold",
-               .tuner_type     = TUNER_LG_TDVS_H062F,
+               .tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H062F */
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
@@ -1050,11 +1050,7 @@ struct cx88_board cx88_boards[] = {
                .dvb            = 1,
        },
        [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
-               /* FIXME: Standard video using the cx88 broadcast decoder is
-                * working, but blackbird isn't working yet, audio is only
-                * working correctly for television mode. S-Video and Composite
-                * are working for video-only, so I have them disabled for now.
-                */
+               /* FIXME: Audio not working for s-video / composite inputs. */
                .name           = "KWorld HardwareMpegTV XPert",
                .tuner_type     = TUNER_PHILIPS_TDA8290,
                .radio_type     = UNSET,
@@ -1065,12 +1061,21 @@ struct cx88_board cx88_boards[] = {
                        .vmux   = 0,
                        .gpio0  = 0x3de2,
                        .gpio2  = 0x00ff,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x3de6,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x3de6,
                }},
                .radio = {
                        .type   = CX88_RADIO,
                        .gpio0  = 0x3de6,
                        .gpio2  = 0x00ff,
                },
+               .blackbird      = 1,
        },
        [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = {
                .name           = "DViCO FusionHDTV DVB-T Hybrid",
@@ -1093,7 +1098,102 @@ struct cx88_board cx88_boards[] = {
                }},
                .dvb            = 1,
        },
-
+       [CX88_BOARD_PCHDTV_HD5500] = {
+               .name           = "pcHDTV HD5500 HDTV",
+               .tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x87fd,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x87f9,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x87f9,
+               }},
+               .dvb            = 1,
+       },
+       [CX88_BOARD_KWORLD_MCE200_DELUXE] = {
+               /* FIXME: tested TV input only, disabled composite,
+                  svideo and radio until they can be tested also. */
+               .name           = "Kworld MCE 200 Deluxe",
+               .tuner_type     = TUNER_TENA_9533_DI,
+               .radio_type     = UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0000BDE6
+               }},
+               .blackbird = 1,
+       },
+       [CX88_BOARD_PIXELVIEW_PLAYTV_P7000] = {
+               /* FIXME: SVideo, Composite and FM inputs are untested */
+               .name           = "PixelView PlayTV P7000",
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
+                                 TDA9887_PORT2_ACTIVE,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x5da6,
+               }},
+               .blackbird = 1,
+       },
+       [CX88_BOARD_NPGTECH_REALTV_TOP10FM] = {
+               .name           = "NPG Tech Real TV FM Top 10",
+               .tuner_type     = TUNER_TNF_5335MF, /* Actually a TNF9535 */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0788,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x078b,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x078b,
+               }},
+               .radio = {
+                        .type  = CX88_RADIO,
+                        .gpio0 = 0x074a,
+               },
+       },
+       [CX88_BOARD_WINFAST_DTV2000H] = {
+               /* video inputs and radio still in testing */
+               .name           = "WinFast DTV2000 H",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00017304,
+                       .gpio1  = 0x00008203,
+                       .gpio2  = 0x00017304,
+                       .gpio3  = 0x02000000,
+               }},
+               .dvb            = 1,
+       },
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
 
@@ -1311,6 +1411,34 @@ struct cx88_subid cx88_subids[] = {
                .subvendor = 0x18ac,
                .subdevice = 0xdb44,
                .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
+       },{
+               .subvendor = 0x7063,
+               .subdevice = 0x5500,
+               .card      = CX88_BOARD_PCHDTV_HD5500,
+       },{
+               .subvendor = 0x17de,
+               .subdevice = 0x0841,
+               .card      = CX88_BOARD_KWORLD_MCE200_DELUXE,
+       },{
+               .subvendor = 0x1822,
+               .subdevice = 0x0019,
+               .card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
+       },{
+               .subvendor = 0x1554,
+               .subdevice = 0x4813,
+               .card      = CX88_BOARD_PIXELVIEW_PLAYTV_P7000,
+       },{
+               .subvendor = 0x14f1,
+               .subdevice = 0x0842,
+               .card      = CX88_BOARD_NPGTECH_REALTV_TOP10FM,
+       },{
+               .subvendor = 0x107d,
+               .subdevice = 0x665e,
+               .card      = CX88_BOARD_WINFAST_DTV2000H,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
        },
 };
 const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
index e1092d5d4628de6d078971be4ca62ce1a92c4592..c56292d8d93bee7f47e02fb2d51e5030813055bc 100644 (file)
@@ -677,7 +677,7 @@ static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
 
 static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
 {
-       return (norm->id & V4L2_STD_625_50) ? 511 : 288;
+       return (norm->id & V4L2_STD_625_50) ? 511 : 400;
 }
 
 int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
@@ -932,9 +932,9 @@ int cx88_set_tvnorm(struct cx88_core *core, struct cx88_tvnorm *norm)
                htotal, cx_read(MO_HTOTAL), (u32)tmp64);
        cx_write(MO_HTOTAL, htotal);
 
-       // vbi stuff
-       cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm)   << 11) | */
-                                norm_vbipack(norm)));
+       // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
+       // the effective vbi offset ~244 samples, the same as the Bt8x8
+       cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
 
        // this is needed as well to set all tvnorm parameter
        cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
index 3619a449aefd91899e9ed26453006b7f8c124b4d..dce1feddd55d16f9d6ece0457cd71c47d7a681cb 100644 (file)
@@ -51,6 +51,7 @@
 #endif
 #ifdef HAVE_LGDT330X
 # include "lgdt330x.h"
+# include "lg_h06xf.h"
 #endif
 #ifdef HAVE_NXT200X
 # include "nxt200x.h"
@@ -58,6 +59,7 @@
 #ifdef HAVE_CX24123
 # include "cx24123.h"
 #endif
+#include "isl6421.h"
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -113,21 +115,6 @@ static struct videobuf_queue_ops dvb_qops = {
 
 /* ------------------------------------------------------------------ */
 
-#if defined(HAVE_MT352) || defined(HAVE_ZL10353)
-static int zarlink_pll_set(struct dvb_frontend *fe,
-                             struct dvb_frontend_parameters *params,
-                             u8 *pllbuf)
-{
-       struct cx8802_dev *dev = fe->dvb->priv;
-
-       pllbuf[0] = dev->core->pll_addr << 1;
-       dvb_pll_configure(dev->core->pll_desc, pllbuf + 1,
-                         params->frequency,
-                         params->u.ofdm.bandwidth);
-       return 0;
-}
-#endif
-
 #ifdef HAVE_MT352
 static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
 {
@@ -196,19 +183,16 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
 static struct mt352_config dvico_fusionhdtv = {
        .demod_address = 0x0F,
        .demod_init    = dvico_fusionhdtv_demod_init,
-       .pll_set       = zarlink_pll_set,
 };
 
 static struct mt352_config dntv_live_dvbt_config = {
        .demod_address = 0x0f,
        .demod_init    = dntv_live_dvbt_demod_init,
-       .pll_set       = zarlink_pll_set,
 };
 
 static struct mt352_config dvico_fusionhdtv_dual = {
        .demod_address = 0x0F,
        .demod_init    = dvico_dual_demod_init,
-       .pll_set       = zarlink_pll_set,
 };
 
 #ifdef HAVE_VP3054_I2C
@@ -246,6 +230,8 @@ static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
                  .buf = fmd1216_init, .len = sizeof(fmd1216_init) };
        int err;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
                if (err < 0)
                        return err;
@@ -256,14 +242,14 @@ static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
        return 0;
 }
 
-static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe,
-                                     struct dvb_frontend_parameters* params,
-                                     u8* pllbuf)
+static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe,
+                                              struct dvb_frontend_parameters* params)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
+       u8 buf[4];
        struct i2c_msg msg =
                { .addr = dev->core->pll_addr, .flags = 0,
-                 .buf = pllbuf+1, .len = 4 };
+                 .buf = buf, .len = 4 };
        int err;
 
        /* Switch PLL to DVB mode */
@@ -272,14 +258,16 @@ static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe,
                return err;
 
        /* Tune PLL */
-       pllbuf[0] = dev->core->pll_addr << 1;
-       dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
+       dvb_pll_configure(dev->core->pll_desc, buf,
                          params->frequency,
                          params->u.ofdm.bandwidth);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+
                printk(KERN_WARNING "cx88-dvb: %s error "
                           "(addr %02x <- %02x, err = %i)\n",
-                          __FUNCTION__, pllbuf[0], pllbuf[1], err);
+                          __FUNCTION__, dev->core->pll_addr, buf[0], err);
                if (err < 0)
                        return err;
                else
@@ -293,27 +281,27 @@ static struct mt352_config dntv_live_dvbt_pro_config = {
        .demod_address = 0x0f,
        .no_tuner      = 1,
        .demod_init    = dntv_live_dvbt_pro_demod_init,
-       .pll_set       = dntv_live_dvbt_pro_pll_set,
 };
 #endif
 #endif
 
 #ifdef HAVE_ZL10353
-static int dvico_hybrid_tune_pll(struct dvb_frontend *fe,
-                                struct dvb_frontend_parameters *params,
-                                u8 *pllbuf)
+static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe,
+                                        struct dvb_frontend_parameters *params)
 {
+       u8 pllbuf[4];
        struct cx8802_dev *dev= fe->dvb->priv;
        struct i2c_msg msg =
                { .addr = dev->core->pll_addr, .flags = 0,
-                 .buf = pllbuf + 1, .len = 4 };
+                 .buf = pllbuf, .len = 4 };
        int err;
 
-       pllbuf[0] = dev->core->pll_addr << 1;
-       dvb_pll_configure(dev->core->pll_desc, pllbuf + 1,
+       dvb_pll_configure(dev->core->pll_desc, pllbuf,
                          params->frequency,
                          params->u.ofdm.bandwidth);
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
                printk(KERN_WARNING "cx88-dvb: %s error "
                           "(addr %02x <- %02x, err = %i)\n",
@@ -329,12 +317,11 @@ static int dvico_hybrid_tune_pll(struct dvb_frontend *fe,
 
 static struct zl10353_config dvico_fusionhdtv_hybrid = {
        .demod_address = 0x0F,
-       .pll_set       = dvico_hybrid_tune_pll,
+       .no_tuner      = 1,
 };
 
 static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
        .demod_address = 0x0F,
-       .pll_set       = zarlink_pll_set,
 };
 #endif
 
@@ -342,21 +329,15 @@ static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
 static struct cx22702_config connexant_refboard_config = {
        .demod_address = 0x43,
        .output_mode   = CX22702_SERIAL_OUTPUT,
-       .pll_address   = 0x60,
-       .pll_desc      = &dvb_pll_thomson_dtt7579,
 };
 
 static struct cx22702_config hauppauge_novat_config = {
        .demod_address = 0x43,
        .output_mode   = CX22702_SERIAL_OUTPUT,
-       .pll_address   = 0x61,
-       .pll_desc      = &dvb_pll_thomson_dtt759x,
 };
 static struct cx22702_config hauppauge_hvr1100_config = {
        .demod_address = 0x63,
        .output_mode   = CX22702_SERIAL_OUTPUT,
-       .pll_address   = 0x61,
-       .pll_desc      = &dvb_pll_fmd1216me,
 };
 #endif
 
@@ -371,15 +352,13 @@ static int or51132_set_ts_param(struct dvb_frontend* fe,
 
 static struct or51132_config pchdtv_hd3000 = {
        .demod_address    = 0x15,
-       .pll_address      = 0x61,
-       .pll_desc         = &dvb_pll_thomson_dtt761x,
        .set_ts_params    = or51132_set_ts_param,
 };
 #endif
 
 #ifdef HAVE_LGDT330X
-static int lgdt330x_pll_set(struct dvb_frontend* fe,
-                           struct dvb_frontend_parameters* params)
+static int lgdt3302_tuner_set_params(struct dvb_frontend* fe,
+                                    struct dvb_frontend_parameters* params)
 {
        /* FIXME make this routine use the tuner-simple code.
         * It could probably be shared with a number of ATSC
@@ -392,12 +371,12 @@ static int lgdt330x_pll_set(struct dvb_frontend* fe,
                { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
        int err;
 
-       /* Put the analog decoder in standby to keep it quiet */
-       cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
-
        dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
        dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
                        __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
                printk(KERN_WARNING "cx88-dvb: %s error "
                           "(addr %02x <- %02x, err = %i)\n",
@@ -407,16 +386,21 @@ static int lgdt330x_pll_set(struct dvb_frontend* fe,
                else
                        return -EREMOTEIO;
        }
-       if (core->tuner_type == TUNER_LG_TDVS_H062F) {
-               /* Set the Auxiliary Byte. */
-               buf[2] &= ~0x20;
-               buf[2] |= 0x18;
-               buf[3] = 0x50;
-               i2c_transfer(&core->i2c_adap, &msg, 1);
-       }
        return 0;
 }
 
+static int lgdt3303_tuner_set_params(struct dvb_frontend* fe,
+                                    struct dvb_frontend_parameters* params)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       struct cx88_core *core = dev->core;
+
+       /* Put the analog decoder in standby to keep it quiet */
+       cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
+       return lg_h06xf_pll_set(fe, &core->i2c_adap, params);
+}
+
 static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
@@ -444,7 +428,6 @@ static struct lgdt330x_config fusionhdtv_3_gold = {
        .demod_address    = 0x0e,
        .demod_chip       = LGDT3302,
        .serial_mpeg      = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
-       .pll_set          = lgdt330x_pll_set,
        .set_ts_params    = lgdt330x_set_ts_param,
 };
 
@@ -452,7 +435,13 @@ static struct lgdt330x_config fusionhdtv_5_gold = {
        .demod_address    = 0x0e,
        .demod_chip       = LGDT3303,
        .serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-       .pll_set          = lgdt330x_pll_set,
+       .set_ts_params    = lgdt330x_set_ts_param,
+};
+
+static struct lgdt330x_config pchdtv_hd5500 = {
+       .demod_address    = 0x59,
+       .demod_chip       = LGDT3303,
+       .serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
        .set_ts_params    = lgdt330x_set_ts_param,
 };
 #endif
@@ -477,8 +466,6 @@ static int nxt200x_set_pll_input(u8* buf, int input)
 
 static struct nxt200x_config ati_hdtvwonder = {
        .demod_address    = 0x0a,
-       .pll_address      = 0x61,
-       .pll_desc         = &dvb_pll_tuv1236d,
        .set_pll_input    = nxt200x_set_pll_input,
        .set_ts_params    = nxt200x_set_ts_param,
 };
@@ -493,28 +480,30 @@ static int cx24123_set_ts_param(struct dvb_frontend* fe,
        return 0;
 }
 
-static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on)
+static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
        struct cx88_core *core = dev->core;
 
-       if (on)
-               cx_write(MO_GP0_IO, 0x000006f9);
-       else
+       if (voltage == SEC_VOLTAGE_OFF) {
                cx_write(MO_GP0_IO, 0x000006fB);
+       } else {
+               cx_write(MO_GP0_IO, 0x000006f9);
+       }
+
+       if (core->prev_set_voltage)
+               return core->prev_set_voltage(fe, voltage);
+       return 0;
 }
 
 static struct cx24123_config hauppauge_novas_config = {
        .demod_address          = 0x55,
-       .use_isl6421            = 1,
        .set_ts_params          = cx24123_set_ts_param,
 };
 
 static struct cx24123_config kworld_dvbs_100_config = {
        .demod_address          = 0x15,
-       .use_isl6421            = 0,
        .set_ts_params          = cx24123_set_ts_param,
-       .enable_lnb_voltage     = cx24123_enable_lnb_voltage,
 };
 #endif
 
@@ -530,6 +519,11 @@ static int dvb_register(struct cx8802_dev *dev)
        case CX88_BOARD_HAUPPAUGE_DVB_T1:
                dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
                                                   &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_thomson_dtt759x);
+               }
                break;
        case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
        case CX88_BOARD_CONEXANT_DVB_T1:
@@ -537,44 +531,92 @@ static int dvb_register(struct cx8802_dev *dev)
        case CX88_BOARD_WINFAST_DTV1000:
                dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
                                                   &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x60,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_thomson_dtt7579);
+               }
                break;
+       case CX88_BOARD_WINFAST_DTV2000H:
        case CX88_BOARD_HAUPPAUGE_HVR1100:
        case CX88_BOARD_HAUPPAUGE_HVR1100LP:
                dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config,
                                                   &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_fmd1216me);
+               }
                break;
 #endif
 #if defined(HAVE_MT352) || defined(HAVE_ZL10353)
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
-               dev->core->pll_addr = 0x60;
-               dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
 #ifdef HAVE_MT352
                dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
                                                 &dev->core->i2c_adap);
-               if (dev->dvb.frontend != NULL)
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x60,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_thomson_dtt7579);
                        break;
+               }
 #endif
 #ifdef HAVE_ZL10353
                /* ZL10353 replaces MT352 on later cards */
                dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1,
                                                   &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x60,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_thomson_dtt7579);
+               }
+#endif
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+#ifdef HAVE_MT352
+               /* The tin box says DEE1601, but it seems to be DTT7579
+                * compatible, with a slightly different MT352 AGC gain. */
+               dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
+                                                &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_thomson_dtt7579);
+                       break;
+               }
+#endif
+#ifdef HAVE_ZL10353
+               /* ZL10353 replaces MT352 on later cards */
+               dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1,
+                                                  &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_thomson_dtt7579);
+               }
 #endif
                break;
 #endif /* HAVE_MT352 || HAVE_ZL10353 */
 #ifdef HAVE_MT352
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
-               dev->core->pll_addr = 0x61;
-               dev->core->pll_desc = &dvb_pll_lg_z201;
                dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
                                                 &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_lg_z201);
+               }
                break;
        case CX88_BOARD_KWORLD_DVB_T:
        case CX88_BOARD_DNTV_LIVE_DVB_T:
        case CX88_BOARD_ADSTECH_DVB_T_PCI:
-               dev->core->pll_addr = 0x61;
-               dev->core->pll_desc = &dvb_pll_unknown_1;
                dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
                                                 &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_unknown_1);
+               }
                break;
        case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
 #ifdef HAVE_VP3054_I2C
@@ -582,18 +624,13 @@ static int dvb_register(struct cx8802_dev *dev)
                dev->core->pll_desc = &dvb_pll_fmd1216me;
                dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config,
                        &((struct vp3054_i2c_state *)dev->card_priv)->adap);
+               if (dev->dvb.frontend != NULL) {
+                       dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params;
+               }
 #else
                printk("%s: built without vp3054 support\n", dev->core->name);
 #endif
                break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
-               /* The tin box says DEE1601, but it seems to be DTT7579
-                * compatible, with a slightly different MT352 AGC gain. */
-               dev->core->pll_addr = 0x61;
-               dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
-               dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
-                                                &dev->core->i2c_adap);
-               break;
 #endif
 #ifdef HAVE_ZL10353
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
@@ -601,12 +638,20 @@ static int dvb_register(struct cx8802_dev *dev)
                dev->core->pll_desc = &dvb_pll_thomson_fe6600;
                dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid,
                                                   &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params;
+               }
                break;
 #endif
 #ifdef HAVE_OR51132
        case CX88_BOARD_PCHDTV_HD3000:
                dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
                                                 &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_thomson_dtt761x);
+               }
                break;
 #endif
 #ifdef HAVE_LGDT330X
@@ -627,6 +672,9 @@ static int dvb_register(struct cx8802_dev *dev)
                dev->core->pll_desc = &dvb_pll_microtune_4042;
                dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
                                                    &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
+               }
                }
                break;
        case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
@@ -643,6 +691,9 @@ static int dvb_register(struct cx8802_dev *dev)
                dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
                dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
                                                    &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
+               }
                }
                break;
        case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
@@ -655,10 +706,28 @@ static int dvb_register(struct cx8802_dev *dev)
                mdelay(100);
                cx_set(MO_GP0_IO, 1);
                mdelay(200);
-               dev->core->pll_addr = 0x61;
-               dev->core->pll_desc = &dvb_pll_tdvs_tua6034;
                dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold,
                                                    &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
+               }
+               }
+               break;
+       case CX88_BOARD_PCHDTV_HD5500:
+               dev->ts_gen_cntrl = 0x08;
+               {
+               /* Do a hardware reset of chip before using it. */
+               struct cx88_core *core = dev->core;
+
+               cx_clear(MO_GP0_IO, 1);
+               mdelay(100);
+               cx_set(MO_GP0_IO, 1);
+               mdelay(200);
+               dev->dvb.frontend = lgdt330x_attach(&pchdtv_hd5500,
+                                                   &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
+               }
                }
                break;
 #endif
@@ -666,6 +735,11 @@ static int dvb_register(struct cx8802_dev *dev)
        case CX88_BOARD_ATI_HDTVWONDER:
                dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder,
                                                 &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                                      &dev->core->i2c_adap,
+                                      &dvb_pll_tuv1236d);
+               }
                break;
 #endif
 #ifdef HAVE_CX24123
@@ -673,10 +747,18 @@ static int dvb_register(struct cx8802_dev *dev)
        case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
                dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config,
                        &dev->core->i2c_adap);
+               if (dev->dvb.frontend) {
+                       isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap,
+                                      0x08, 0x00, 0x00);
+               }
                break;
        case CX88_BOARD_KWORLD_DVBS_100:
                dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config,
                        &dev->core->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
+                       dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
+               }
                break;
 #endif
        default:
@@ -690,15 +772,15 @@ static int dvb_register(struct cx8802_dev *dev)
        }
 
        if (dev->core->pll_desc) {
-               dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min;
-               dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
+               dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min;
+               dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max;
        }
 
        /* Put the analog decoder in standby to keep it quiet */
        cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
 
        /* register everything */
-       return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
+       return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
 }
 
 /* ----------------------------------------------------------- */
index f720901e963866bec677d1bed8354c7d71a77535..7efa6def0bdeff6cb6c8e362a2a238a9ba2d9392 100644 (file)
@@ -138,13 +138,13 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg)
                return;
 
        if (core->dvbdev) {
-               if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl)
-                       core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
+               if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
+                       core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
 
                i2c_clients_command(&core->i2c_adap, cmd, arg);
 
-               if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl)
-                       core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0);
+               if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
+                       core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0);
        } else
                i2c_clients_command(&core->i2c_adap, cmd, arg);
 }
index 78a63b7dd380a33e806ef0f2c9d000eb523b6314..72b630a91f41e1aa06ed1e6ef6bf96d1001a34e6 100644 (file)
@@ -70,14 +70,33 @@ MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
 static void cx88_ir_handle_key(struct cx88_IR *ir)
 {
        struct cx88_core *core = ir->core;
-       u32 gpio, data;
+       u32 gpio, data, auxgpio;
 
        /* read gpio value */
        gpio = cx_read(ir->gpio_addr);
+       if (core->board == CX88_BOARD_NPGTECH_REALTV_TOP10FM) {
+               /* This board apparently uses a combination of 2 GPIO
+                  to represent the keys. Additionally, the second GPIO
+                  can be used for parity.
+
+                  Example:
+
+                  for key "5"
+                       gpio = 0x758, auxgpio = 0xe5 or 0xf5
+                  for key "Power"
+                       gpio = 0x758, auxgpio = 0xed or 0xfd
+                */
+
+               auxgpio = cx_read(MO_GP1_IO);
+               /* Take out the parity part */
+               gpio+=(gpio & 0x7fd) + (auxgpio & 0xef);
+       } else
+               auxgpio = gpio;
+
        if (ir->polling) {
-               if (ir->last_gpio == gpio)
+               if (ir->last_gpio == auxgpio)
                        return;
-               ir->last_gpio = gpio;
+               ir->last_gpio = auxgpio;
        }
 
        /* extract data */
@@ -172,12 +191,13 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir_type = IR_TYPE_RC5;
                ir->sampling = 1;
                break;
+       case CX88_BOARD_WINFAST_DTV2000H:
        case CX88_BOARD_WINFAST2000XP_EXPERT:
                ir_codes = ir_codes_winfast;
                ir->gpio_addr = MO_GP0_IO;
                ir->mask_keycode = 0x8f8;
                ir->mask_keyup = 0x100;
-               ir->polling = 1; /* ms */
+               ir->polling = 50; /* ms */
                break;
        case CX88_BOARD_IODATA_GVBCTV7E:
                ir_codes = ir_codes_iodata_bctv7e;
@@ -228,6 +248,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
                ir_type = IR_TYPE_PD;
                ir->sampling = 0xff00; /* address */
                break;
+       case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
+               ir_codes = ir_codes_npgtech;
+               ir->gpio_addr = MO_GP0_IO;
+               ir->mask_keycode = 0xfa;
+               ir->polling = 50; /* ms */
+               break;
        }
 
        if (NULL == ir_codes) {
index 7d16888b4a866d2d250a1dce4c81b7b6c63a1426..a9d7795a8e143563ed155c109d474d725671012e 100644 (file)
@@ -54,7 +54,7 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
 {
        struct cx88_core *core = dev->core;
 
-       dprintk(0, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field);
+       dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field);
 
        /* setup fifo + format */
        cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
@@ -76,6 +76,7 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
                case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
                case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
                case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+               case CX88_BOARD_PCHDTV_HD5500:
                        cx_write(TS_SOP_STAT, 1<<13);
                        break;
                case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
@@ -109,7 +110,7 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
        q->count = 1;
 
        /* enable irqs */
-       dprintk( 0, "setting the interrupt mask\n" );
+       dprintk( 1, "setting the interrupt mask\n" );
        cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
        cx_set(MO_TS_INTMSK,  0x1f0011);
 
@@ -122,7 +123,7 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
 static int cx8802_stop_dma(struct cx8802_dev *dev)
 {
        struct cx88_core *core = dev->core;
-       dprintk( 0, "cx8802_stop_dma\n" );
+       dprintk( 1, "cx8802_stop_dma\n" );
 
        /* stop dma */
        cx_clear(MO_TS_DMACNTRL, 0x11);
@@ -142,10 +143,43 @@ static int cx8802_restart_queue(struct cx8802_dev    *dev,
        struct cx88_buffer *buf;
        struct list_head *item;
 
-       dprintk( 0, "cx8802_restart_queue\n" );
+       dprintk( 1, "cx8802_restart_queue\n" );
        if (list_empty(&q->active))
        {
-               dprintk( 0, "cx8802_restart_queue: queue is empty\n" );
+              struct cx88_buffer *prev;
+              prev = NULL;
+
+              dprintk(1, "cx8802_restart_queue: queue is empty\n" );
+
+              for (;;) {
+                      if (list_empty(&q->queued))
+                              return 0;
+                      buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
+                      if (NULL == prev) {
+                              list_del(&buf->vb.queue);
+                              list_add_tail(&buf->vb.queue,&q->active);
+                              cx8802_start_dma(dev, q, buf);
+                              buf->vb.state = STATE_ACTIVE;
+                              buf->count    = q->count++;
+                              mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+                              dprintk(1,"[%p/%d] restart_queue - first active\n",
+                                      buf,buf->vb.i);
+
+                      } else if (prev->vb.width  == buf->vb.width  &&
+                                 prev->vb.height == buf->vb.height &&
+                                 prev->fmt       == buf->fmt) {
+                              list_del(&buf->vb.queue);
+                              list_add_tail(&buf->vb.queue,&q->active);
+                              buf->vb.state = STATE_ACTIVE;
+                              buf->count    = q->count++;
+                              prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+                              dprintk(1,"[%p/%d] restart_queue - move to active\n",
+                                      buf,buf->vb.i);
+                      } else {
+                              return 0;
+                      }
+                      prev = buf;
+              }
                return 0;
        }
 
@@ -204,13 +238,13 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
        buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
 
        if (list_empty(&cx88q->active)) {
-               dprintk( 0, "queue is empty - first active\n" );
+               dprintk( 1, "queue is empty - first active\n" );
                list_add_tail(&buf->vb.queue,&cx88q->active);
                cx8802_start_dma(dev, cx88q, buf);
                buf->vb.state = STATE_ACTIVE;
                buf->count    = cx88q->count++;
                mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
-               dprintk(0,"[%p/%d] %s - first active\n",
+               dprintk(1,"[%p/%d] %s - first active\n",
                        buf, buf->vb.i, __FUNCTION__);
 
        } else {
@@ -244,7 +278,7 @@ static void do_cancel_buffers(struct cx8802_dev *dev, char *reason, int restart)
        }
        if (restart)
        {
-               dprintk(0, "restarting queue\n" );
+               dprintk(1, "restarting queue\n" );
                cx8802_restart_queue(dev,q);
        }
        spin_unlock_irqrestore(&dev->slock,flags);
index 641a0c5a64907422777039dfd9f34f0d4f321828..1e4278b588d8830c14b60de00b076bbb1cff63c8 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
+#include <linux/config.h>
 #include <linux/kthread.h>
 
 #include "cx88.h"
@@ -137,21 +138,28 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
 {
        u32 volume;
 
-#ifndef USING_CX88_ALSA
+#ifndef CONFIG_VIDEO_CX88_ALSA
        /* restart dma; This avoids buzz in NICAM and is good in others  */
        cx88_stop_audio_dma(core);
 #endif
        cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
-#ifndef USING_CX88_ALSA
+#ifndef CONFIG_VIDEO_CX88_ALSA
        cx88_start_audio_dma(core);
 #endif
 
        if (cx88_boards[core->board].blackbird) {
                /* sets sound input from external adc */
-               if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN)
+               switch (core->board) {
+               case CX88_BOARD_HAUPPAUGE_ROSLYN:
+               case CX88_BOARD_KWORLD_MCE200_DELUXE:
+               case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT:
+               case CX88_BOARD_PIXELVIEW_PLAYTV_P7000:
+               case CX88_BOARD_ASUS_PVR_416:
                        cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
-               else
+                       break;
+               default:
                        cx_set(AUD_CTL, EN_I2SIN_ENABLE);
+               }
 
                cx_write(AUD_I2SINPUTCNTL, 4);
                cx_write(AUD_BAUDRATE, 1);
index 846faadc9f1c22c20e1373cfa9d35b11a516c54f..aa2a69770098cf48b085d9f35c79f154ec20c9b6 100644 (file)
@@ -34,8 +34,8 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f)
        if (dev->core->tvnorm->id & V4L2_STD_525_60) {
                /* ntsc */
                f->fmt.vbi.sampling_rate = 28636363;
-               f->fmt.vbi.start[0] = 10 -1;
-               f->fmt.vbi.start[1] = 273 -1;
+               f->fmt.vbi.start[0] = 10;
+               f->fmt.vbi.start[1] = 273;
 
        } else if (dev->core->tvnorm->id & V4L2_STD_625_50) {
                /* pal */
index 326a25f147f67c4e96ee16cd81d92b107829c0cd..dc7bc35f18f4069f5aaada4b65202890c1e7ad9a 100644 (file)
 #include <linux/videodev2.h>
 #include <linux/kdev_t.h>
 
+#include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include <media/tveeprom.h>
 #include <media/video-buf.h>
+#include <media/cx2341x.h>
 #include <media/video-buf-dvb.h>
 
 #include "btcx-risc.h"
@@ -35,7 +37,7 @@
 
 #include <linux/version.h>
 #include <linux/mutex.h>
-#define CX88_VERSION_CODE KERNEL_VERSION(0,0,5)
+#define CX88_VERSION_CODE KERNEL_VERSION(0,0,6)
 
 #ifndef TRUE
 # define TRUE (1==1)
@@ -189,6 +191,11 @@ extern struct sram_channel cx88_sram_channels[];
 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
 #define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45
 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46
+#define CX88_BOARD_PCHDTV_HD5500           47
+#define CX88_BOARD_KWORLD_MCE200_DELUXE    48
+#define CX88_BOARD_PIXELVIEW_PLAYTV_P7000  49
+#define CX88_BOARD_NPGTECH_REALTV_TOP10FM  50
+#define CX88_BOARD_WINFAST_DTV2000H        51
 
 enum cx88_itype {
        CX88_VMUX_COMPOSITE1 = 1,
@@ -296,6 +303,7 @@ struct cx88_core {
        /* config info -- dvb */
        struct dvb_pll_desc        *pll_desc;
        unsigned int               pll_addr;
+       int                        (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
 
        /* state info */
        struct task_struct         *kthread;
@@ -391,14 +399,6 @@ struct cx8802_suspend_state {
        int                        disabled;
 };
 
-/* TODO: move this to struct v4l2_mpeg_compression ? */
-struct blackbird_dnr {
-       u32                       mode;
-       u32                       type;
-       u32                       spatial;
-       u32                       temporal;
-};
-
 struct cx8802_dev {
        struct cx88_core           *core;
        spinlock_t                 slock;
@@ -432,8 +432,7 @@ struct cx8802_dev {
        unsigned char              ts_gen_cntrl;
 
        /* mpeg params */
-       struct v4l2_mpeg_compression params;
-       struct blackbird_dnr       dnr_params;
+       struct cx2341x_mpeg_params params;
 };
 
 /* ----------------------------------------------------------- */
@@ -598,10 +597,6 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
 extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
                                unsigned int cmd, void *arg);
 extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
-void blackbird_set_params(struct cx8802_dev *dev,
-                               struct v4l2_mpeg_compression *params);
-void blackbird_set_dnr_params(struct cx8802_dev *dev,
-                               struct blackbird_dnr* dnr_params);
 
 /*
  * Local variables:
index 3b4e9985c3d76442083e1a163b791112411ef454..f7e33f9ee8e921fddbe569e0898fece377e5b97b 100644 (file)
@@ -72,6 +72,7 @@
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/usb.h>
 #include <linux/smp_lock.h>
 
index 3ba3439db580f605a32a5fc3b5982c810387e0f3..ed882ebc7b958a1f5fc7febf94a8b48c6c4f1497 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
                      Markus Rechberger <mrechberger@gmail.com>
-                     Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
                      Sascha Sommer <saschasommer@freenet.de>
 
    This program is free software; you can redistribute it and/or modify
@@ -29,6 +29,8 @@
 #include <linux/usb.h>
 #include <media/tuner.h>
 #include <media/msp3400.h>
+#include <media/saa7115.h>
+#include <media/tvp5150.h>
 #include <media/tveeprom.h>
 #include <media/audiochip.h>
 #include <media/v4l2-common.h>
@@ -46,11 +48,11 @@ struct em28xx_board em28xx_boards[] = {
                .decoder      = EM28XX_SAA7113,
                .input           = {{
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
+                       .vmux     = SAA7115_COMPOSITE0,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 9,
+                       .vmux     = SAA7115_SVIDEO3,
                        .amux     = 1,
                }},
        },
@@ -64,11 +66,11 @@ struct em28xx_board em28xx_boards[] = {
                .decoder      = EM28XX_SAA7113,
                .input           = {{
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
+                       .vmux     = SAA7115_COMPOSITE0,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 9,
+                       .vmux     = SAA7115_SVIDEO3,
                        .amux     = 1,
                }},
        },
@@ -82,11 +84,11 @@ struct em28xx_board em28xx_boards[] = {
                .decoder      = EM28XX_SAA7113,
                .input           = {{
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
+                       .vmux     = SAA7115_COMPOSITE0,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 9,
+                       .vmux     = SAA7115_SVIDEO3,
                        .amux     = 1,
                }},
        },
@@ -100,15 +102,15 @@ struct em28xx_board em28xx_boards[] = {
                .decoder      = EM28XX_SAA7113,
                .input          = {{
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = 2,
+                       .vmux     = SAA7115_COMPOSITE2,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
+                       .vmux     = SAA7115_COMPOSITE0,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 9,
+                       .vmux     = SAA7115_SVIDEO3,
                        .amux     = 1,
                }},
        },
@@ -122,15 +124,15 @@ struct em28xx_board em28xx_boards[] = {
                .decoder      = EM28XX_SAA7113,
                .input          = {{
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = 2,
+                       .vmux     = SAA7115_COMPOSITE2,
                        .amux     = 0,
                },{
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
+                       .vmux     = SAA7115_COMPOSITE0,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 9,
+                       .vmux     = SAA7115_SVIDEO3,
                        .amux     = 1,
                }},
        },
@@ -146,11 +148,11 @@ struct em28xx_board em28xx_boards[] = {
                /*FIXME: S-Video not tested */
                .input          = {{
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = 0,
+                       .vmux     = TVP5150_COMPOSITE0,
                        .amux     = MSP_INPUT_DEFAULT,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 2,
+                       .vmux     = TVP5150_SVIDEO,
                        .amux     = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
                                        MSP_DSP_IN_SCART, MSP_DSP_IN_SCART),
                }},
@@ -165,15 +167,15 @@ struct em28xx_board em28xx_boards[] = {
                .decoder        = EM28XX_SAA7114,
                .input          = {{
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = 4,
+                       .vmux     = SAA7115_COMPOSITE4,
                        .amux     = 0,
                },{
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
+                       .vmux     = SAA7115_COMPOSITE0,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 9,
+                       .vmux     = SAA7115_SVIDEO3,
                        .amux     = 1,
                }},
        },
@@ -188,15 +190,15 @@ struct em28xx_board em28xx_boards[] = {
                .decoder      = EM28XX_SAA7113,
                .input          = {{
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = 2,
+                       .vmux     = SAA7115_COMPOSITE2,
                        .amux     = 0,
                },{
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
+                       .vmux     = SAA7115_COMPOSITE0,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 9,
+                       .vmux     = SAA7115_SVIDEO3,
                        .amux     = 1,
                }},
        },
@@ -211,15 +213,15 @@ struct em28xx_board em28xx_boards[] = {
                .decoder      = EM28XX_SAA7113,
                .input          = {{
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = 2,
+                       .vmux     = SAA7115_COMPOSITE2,
                        .amux     = 0,
                },{
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
+                       .vmux     = SAA7115_COMPOSITE0,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 9,
+                       .vmux     = SAA7115_SVIDEO3,
                        .amux     = 1,
                }},
        },
@@ -234,15 +236,15 @@ struct em28xx_board em28xx_boards[] = {
                .decoder      = EM28XX_SAA7113,
                .input          = {{
                        .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = 2,
+                       .vmux     = SAA7115_COMPOSITE2,
                        .amux     = 0,
                },{
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
+                       .vmux     = SAA7115_COMPOSITE0,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 9,
+                       .vmux     = SAA7115_SVIDEO3,
                        .amux     = 1,
                }},
        },
@@ -254,11 +256,11 @@ struct em28xx_board em28xx_boards[] = {
                .decoder      = EM28XX_SAA7113,
                .input          = {{
                        .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
+                       .vmux     = SAA7115_COMPOSITE0,
                        .amux     = 1,
                },{
                        .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = 9,
+                       .vmux     = SAA7115_SVIDEO3,
                        .amux     = 1,
                }},
        },
@@ -324,8 +326,4 @@ void em28xx_card_setup(struct em28xx *dev)
        }
 }
 
-EXPORT_SYMBOL(em28xx_boards);
-EXPORT_SYMBOL(em28xx_bcount);
-EXPORT_SYMBOL(em28xx_id_table);
-
 MODULE_DEVICE_TABLE (usb, em28xx_id_table);
index e5ee8bceb210c19fa606fe7248dbbdbfbbc38d5a..4350cc75b025a0ffcf24252fb1af9d5517dad938 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
                      Markus Rechberger <mrechberger@gmail.com>
-                     Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
                      Sascha Sommer <saschasommer@freenet.de>
 
    This program is free software; you can redistribute it and/or modify
@@ -317,8 +317,8 @@ int em28xx_outfmt_set_yuv422(struct em28xx *dev)
        return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1);
 }
 
-int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin,
-                                 u8 ymax)
+static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
+                                 u8 ymin, u8 ymax)
 {
        em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax);
 
@@ -328,7 +328,7 @@ int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin,
        return em28xx_write_regs(dev, YMAX_REG, &ymax, 1);
 }
 
-int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
+static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
                                   u16 width, u16 height)
 {
        u8 cwidth = width;
@@ -345,7 +345,7 @@ int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
        return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1);
 }
 
-int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
+static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
 {
        u8 mode;
        /* the em2800 scaler only supports scaling down to 50% */
@@ -534,7 +534,7 @@ static inline void em28xx_isoc_video_copy(struct em28xx *dev,
  * em28xx_isoIrq()
  * handles the incoming isoc urbs and fills the frames from our inqueue
  */
-void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs)
+static void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs)
 {
        struct em28xx *dev = urb->context;
        int i, status;
index 5b6cece37aee9bebcd629f9b76474fd8190d7b96..d829d8f8c1f670a11f57f856f16f666069b08bda 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
                      Markus Rechberger <mrechberger@gmail.com>
-                     Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
                      Sascha Sommer <saschasommer@freenet.de>
 
    This program is free software; you can redistribute it and/or modify
@@ -399,17 +399,6 @@ static u32 functionality(struct i2c_adapter *adap)
        return I2C_FUNC_SMBUS_EMUL;
 }
 
-#ifndef I2C_PEC
-static void inc_use(struct i2c_adapter *adap)
-{
-       MOD_INC_USE_COUNT;
-}
-
-static void dec_use(struct i2c_adapter *adap)
-{
-       MOD_DEC_USE_COUNT;
-}
-#endif
 
 static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client)
 {
@@ -436,9 +425,19 @@ static int attach_inform(struct i2c_client *client)
        struct em28xx *dev = client->adapter->algo_data;
 
        switch (client->addr << 1) {
-               case 0x86:
+               case 0x43:
+               case 0x4b:
+               {
+                       struct tuner_setup tun_setup;
+
+                       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+                       tun_setup.type = TUNER_TDA9887;
+                       tun_setup.addr = client->addr;
+
+                       em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
                        em28xx_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf);
                        break;
+               }
                case 0x42:
                        dprintk1(1,"attach_inform: saa7114 detected.\n");
                        break;
@@ -464,6 +463,7 @@ static int attach_inform(struct i2c_client *client)
                case 0xba:
                        dprintk1(1,"attach_inform: tvp5150 detected.\n");
                        break;
+
                default:
                        dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1);
                        dev->tuner_addr = client->addr;
@@ -480,12 +480,7 @@ static struct i2c_algorithm em28xx_algo = {
 };
 
 static struct i2c_adapter em28xx_adap_template = {
-#ifdef I2C_PEC
        .owner = THIS_MODULE,
-#else
-       .inc_use = inc_use,
-       .dec_use = dec_use,
-#endif
        .class = I2C_CLASS_TV_ANALOG,
        .name = "em28xx",
        .id = I2C_HW_B_EM28XX,
index 31e89e4f18be5764200c57a76730e3bda95f93d5..3ffb5684f127ecaa3e9bc68584df8450370edaf0 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
                      Markus Rechberger <mrechberger@gmail.com>
-                     Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
                      Sascha Sommer <saschasommer@freenet.de>
 
   This program is free software; you can redistribute it and/or modify
@@ -105,7 +105,7 @@ static int get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        return 1;
 }
 
-static int get_key_pinnacle_usb(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 {
        unsigned char buf[3];
 
@@ -148,8 +148,8 @@ void em28xx_set_ir(struct em28xx * dev,struct IR_i2c *ir)
                snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)");
                break;
        case (EM2820_BOARD_PINNACLE_USB_2):
-               ir->ir_codes = ir_codes_em_pinnacle_usb;
-               ir->get_key = get_key_pinnacle_usb;
+               ir->ir_codes = ir_codes_pinnacle_grey;
+               ir->get_key = get_key_pinnacle_usb_grey;
                snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)");
                break;
        case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
index cf7cdf9ef6178e50f3cf1596bf65b856a5fa5df6..9286090817cd2d564d97a100fd8ceeb99789e4fe 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
                      Markus Rechberger <mrechberger@gmail.com>
-                     Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
                      Sascha Sommer <saschasommer@freenet.de>
 
        Some parts based on SN9C10x PC Camera Controllers GPL driver made
@@ -42,7 +42,7 @@
 
 #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
                      "Markus Rechberger <mrechberger@gmail.com>, " \
-                     "Mauro Carvalho Chehab <mchehab@brturbo.com.br>, " \
+                     "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
                      "Sascha Sommer <saschasommer@freenet.de>"
 
 #define DRIVER_NAME         "em28xx"
@@ -170,8 +170,12 @@ static int em28xx_config(struct em28xx *dev)
 static void em28xx_config_i2c(struct em28xx *dev)
 {
        struct v4l2_frequency f;
+       struct v4l2_routing route;
+
+       route.input = INPUT(dev->ctl_input)->vmux;
+       route.output = 0;
        em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL);
-       em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &dev->ctl_input);
+       em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
        em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
 
        /* configure tuner */
@@ -206,19 +210,19 @@ static void em28xx_empty_framequeues(struct em28xx *dev)
 
 static void video_mux(struct em28xx *dev, int index)
 {
-       int input, ainput;
+       int ainput;
+       struct v4l2_routing route;
 
-       input = INPUT(index)->vmux;
+       route.input = INPUT(index)->vmux;
+       route.output = 0;
        dev->ctl_input = index;
        dev->ctl_ainput = INPUT(index)->amux;
 
-       em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &input);
+       em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
 
-       em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput);
+       em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,route.input,dev->ctl_ainput);
 
        if (dev->has_msp34xx) {
-               struct v4l2_routing route;
-
                if (dev->i2s_speed)
                        em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
                route.input = dev->ctl_ainput;
index e1ddc2f27a2152df39dbe8f9af74749cb2bbdb31..d8fcc9e17ac004c47e35325eb1feda1812824180 100644 (file)
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
                      Ludovico Cavedon <cavedon@sssup.it>
-                     Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
 
    Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de>
 
@@ -319,13 +319,7 @@ int em28xx_audio_analog_set(struct em28xx *dev);
 int em28xx_colorlevels_set_default(struct em28xx *dev);
 int em28xx_capture_start(struct em28xx *dev, int start);
 int em28xx_outfmt_set_yuv422(struct em28xx *dev);
-int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin,
-                          u8 ymax);
-int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
-                           u16 width, u16 height);
-int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v);
 int em28xx_resolution_set(struct em28xx *dev);
-void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs);
 int em28xx_init_isoc(struct em28xx *dev);
 void em28xx_uninit_isoc(struct em28xx *dev);
 int em28xx_set_alternate(struct em28xx *dev);
index dfc9dd732c9d0f817fb0554b77f49d03a857b0f2..8992b6e62b9f76ee9fa03068756633c7ac67e65f 100644 (file)
@@ -2341,11 +2341,9 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_G_CTRL:
                return et61x251_vidioc_g_ctrl(cam, arg);
 
-       case VIDIOC_S_CTRL_OLD:
        case VIDIOC_S_CTRL:
                return et61x251_vidioc_s_ctrl(cam, arg);
 
-       case VIDIOC_CROPCAP_OLD:
        case VIDIOC_CROPCAP:
                return et61x251_vidioc_cropcap(cam, arg);
 
@@ -2392,7 +2390,6 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_G_PARM:
                return et61x251_vidioc_g_parm(cam, arg);
 
-       case VIDIOC_S_PARM_OLD:
        case VIDIOC_S_PARM:
                return et61x251_vidioc_s_parm(cam, arg);
 
index 7e66d83fe0ce672f6fb4cc0b4b53e28246d5b186..fba30a40e9c6fface92fe3909314e64fefd39057 100644 (file)
@@ -150,12 +150,11 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        return 1;
 }
 
-/* The new pinnacle PCTV remote (with the colored buttons)
+/* Common (grey or coloured) pinnacle PCTV remote handling
  *
- * Ricardo Cerqueira <v4l@cerqueira.org>
  */
-
-int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
+                           int parity_offset, int marker, int code_modulo)
 {
        unsigned char b[4];
        unsigned int start = 0,parity = 0,code = 0;
@@ -167,9 +166,9 @@ int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        }
 
        for (start = 0; start<4; start++) {
-               if (b[start] == 0x80) {
-                       code=b[(start+3)%4];
-                       parity=b[(start+2)%4];
+               if (b[start] == marker) {
+                       code=b[(start+parity_offset+1)%4];
+                       parity=b[(start+parity_offset)%4];
                }
        }
 
@@ -181,16 +180,14 @@ int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        if (ir->old == parity)
                return 0;
 
-
        ir->old = parity;
 
-       /* Reduce code value to fit inside IR_KEYTAB_SIZE
-        *
-        * this is the only value that results in 42 unique
-        * codes < 128
-        */
+       /* drop special codes when a key is held down a long time for the grey controller
+          In this case, the second bit of the code is asserted */
+       if (marker == 0xfe && (code & 0x40))
+               return 0;
 
-       code %= 0x88;
+       code %= code_modulo;
 
        *ir_raw = code;
        *ir_key = code;
@@ -200,7 +197,40 @@ int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
        return 1;
 }
 
-EXPORT_SYMBOL_GPL(get_key_pinnacle);
+/* The grey pinnacle PCTV remote
+ *
+ *  There are one issue with this remote:
+ *   - I2c packet does not change when the same key is pressed quickly. The workaround
+ *     is to hold down each key for about half a second, so that another code is generated
+ *     in the i2c packet, and the function can distinguish key presses.
+ *
+ * Sylvain Pasche <sylvain.pasche@gmail.com>
+ */
+int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+
+       return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
+}
+
+EXPORT_SYMBOL_GPL(get_key_pinnacle_grey);
+
+
+/* The new pinnacle PCTV remote (with the colored buttons)
+ *
+ * Ricardo Cerqueira <v4l@cerqueira.org>
+ */
+int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
+        *
+        * this is the only value that results in 42 unique
+        * codes < 128
+        */
+
+       return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
+}
+
+EXPORT_SYMBOL_GPL(get_key_pinnacle_color);
 
 /* ----------------------------------------------------------------------- */
 
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c
new file mode 100644 (file)
index 0000000..3bf7ac4
--- /dev/null
@@ -0,0 +1,846 @@
+/*
+ * Video Capture Driver (Video for Linux 1/2)
+ * for the Matrox Marvel G200,G400 and Rainbow Runner-G series
+ *
+ * This module is an interface to the KS0127 video decoder chip.
+ *
+ * Copyright (C) 1999  Ryan Drake <stiletto@mediaone.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *****************************************************************************
+ *
+ * Modified and extended by
+ *     Mike Bernson <mike@mlb.org>
+ *     Gerard v.d. Horst
+ *     Leon van Stuivenberg <l.vanstuivenberg@chello.nl>
+ *     Gernot Ziegler <gz@lysator.liu.se>
+ *
+ * Version History:
+ * V1.0 Ryan Drake        Initial version by Ryan Drake
+ * V1.1 Gerard v.d. Horst  Added some debugoutput, reset the video-standard
+ */
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include "ks0127.h"
+
+#include <linux/i2c.h>
+#include <linux/video_decoder.h>
+
+#define dprintk     if (debug) printk
+
+/* i2c identification */
+#define I2C_KS0127_ADDON   0xD8
+#define I2C_KS0127_ONBOARD 0xDA
+
+#define KS_TYPE_UNKNOWN        0
+#define KS_TYPE_0122S  1
+#define KS_TYPE_0127   2
+#define KS_TYPE_0127B  3
+
+/* ks0127 control registers */
+#define KS_STAT     0x00
+#define KS_CMDA     0x01
+#define KS_CMDB     0x02
+#define KS_CMDC     0x03
+#define KS_CMDD     0x04
+#define KS_HAVB     0x05
+#define KS_HAVE     0x06
+#define KS_HS1B     0x07
+#define KS_HS1E     0x08
+#define KS_HS2B     0x09
+#define KS_HS2E     0x0a
+#define KS_AGC      0x0b
+#define KS_HXTRA    0x0c
+#define KS_CDEM     0x0d
+#define KS_PORTAB   0x0e
+#define KS_LUMA     0x0f
+#define KS_CON      0x10
+#define KS_BRT      0x11
+#define KS_CHROMA   0x12
+#define KS_CHROMB   0x13
+#define KS_DEMOD    0x14
+#define KS_SAT      0x15
+#define KS_HUE      0x16
+#define KS_VERTIA   0x17
+#define KS_VERTIB   0x18
+#define KS_VERTIC   0x19
+#define KS_HSCLL    0x1a
+#define KS_HSCLH    0x1b
+#define KS_VSCLL    0x1c
+#define KS_VSCLH    0x1d
+#define KS_OFMTA    0x1e
+#define KS_OFMTB    0x1f
+#define KS_VBICTL   0x20
+#define KS_CCDAT2   0x21
+#define KS_CCDAT1   0x22
+#define KS_VBIL30   0x23
+#define KS_VBIL74   0x24
+#define KS_VBIL118  0x25
+#define KS_VBIL1512 0x26
+#define KS_TTFRAM   0x27
+#define KS_TESTA    0x28
+#define KS_UVOFFH   0x29
+#define KS_UVOFFL   0x2a
+#define KS_UGAIN    0x2b
+#define KS_VGAIN    0x2c
+#define KS_VAVB     0x2d
+#define KS_VAVE     0x2e
+#define KS_CTRACK   0x2f
+#define KS_POLCTL   0x30
+#define KS_REFCOD   0x31
+#define KS_INVALY   0x32
+#define KS_INVALU   0x33
+#define KS_INVALV   0x34
+#define KS_UNUSEY   0x35
+#define KS_UNUSEU   0x36
+#define KS_UNUSEV   0x37
+#define KS_USRSAV   0x38
+#define KS_USREAV   0x39
+#define KS_SHS1A    0x3a
+#define KS_SHS1B    0x3b
+#define KS_SHS1C    0x3c
+#define KS_CMDE     0x3d
+#define KS_VSDEL    0x3e
+#define KS_CMDF     0x3f
+#define KS_GAMMA0   0x40
+#define KS_GAMMA1   0x41
+#define KS_GAMMA2   0x42
+#define KS_GAMMA3   0x43
+#define KS_GAMMA4   0x44
+#define KS_GAMMA5   0x45
+#define KS_GAMMA6   0x46
+#define KS_GAMMA7   0x47
+#define KS_GAMMA8   0x48
+#define KS_GAMMA9   0x49
+#define KS_GAMMA10  0x4a
+#define KS_GAMMA11  0x4b
+#define KS_GAMMA12  0x4c
+#define KS_GAMMA13  0x4d
+#define KS_GAMMA14  0x4e
+#define KS_GAMMA15  0x4f
+#define KS_GAMMA16  0x50
+#define KS_GAMMA17  0x51
+#define KS_GAMMA18  0x52
+#define KS_GAMMA19  0x53
+#define KS_GAMMA20  0x54
+#define KS_GAMMA21  0x55
+#define KS_GAMMA22  0x56
+#define KS_GAMMA23  0x57
+#define KS_GAMMA24  0x58
+#define KS_GAMMA25  0x59
+#define KS_GAMMA26  0x5a
+#define KS_GAMMA27  0x5b
+#define KS_GAMMA28  0x5c
+#define KS_GAMMA29  0x5d
+#define KS_GAMMA30  0x5e
+#define KS_GAMMA31  0x5f
+#define KS_GAMMAD0  0x60
+#define KS_GAMMAD1  0x61
+#define KS_GAMMAD2  0x62
+#define KS_GAMMAD3  0x63
+#define KS_GAMMAD4  0x64
+#define KS_GAMMAD5  0x65
+#define KS_GAMMAD6  0x66
+#define KS_GAMMAD7  0x67
+#define KS_GAMMAD8  0x68
+#define KS_GAMMAD9  0x69
+#define KS_GAMMAD10 0x6a
+#define KS_GAMMAD11 0x6b
+#define KS_GAMMAD12 0x6c
+#define KS_GAMMAD13 0x6d
+#define KS_GAMMAD14 0x6e
+#define KS_GAMMAD15 0x6f
+#define KS_GAMMAD16 0x70
+#define KS_GAMMAD17 0x71
+#define KS_GAMMAD18 0x72
+#define KS_GAMMAD19 0x73
+#define KS_GAMMAD20 0x74
+#define KS_GAMMAD21 0x75
+#define KS_GAMMAD22 0x76
+#define KS_GAMMAD23 0x77
+#define KS_GAMMAD24 0x78
+#define KS_GAMMAD25 0x79
+#define KS_GAMMAD26 0x7a
+#define KS_GAMMAD27 0x7b
+#define KS_GAMMAD28 0x7c
+#define KS_GAMMAD29 0x7d
+#define KS_GAMMAD30 0x7e
+#define KS_GAMMAD31 0x7f
+
+
+/****************************************************************************
+* mga_dev : represents one ks0127 chip.
+****************************************************************************/
+
+struct adjust {
+       int     contrast;
+       int     bright;
+       int     hue;
+       int     ugain;
+       int     vgain;
+};
+
+struct ks0127 {
+       struct i2c_client *client;
+       unsigned char   addr;
+       int             format_width;
+       int             format_height;
+       int             cap_width;
+       int             cap_height;
+       int             norm;
+       int             ks_type;
+       u8              regs[256];
+};
+
+
+static int debug; /* insmod parameter */
+
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug output");
+MODULE_LICENSE("GPL");
+
+static u8 reg_defaults[64];
+
+
+
+static void init_reg_defaults(void)
+{
+       u8 *table = reg_defaults;
+
+       table[KS_CMDA]     = 0x2c;  /* VSE=0, CCIR 601, autodetect standard */
+       table[KS_CMDB]     = 0x12;  /* VALIGN=0, AGC control and input */
+       table[KS_CMDC]     = 0x00;  /* Test options */
+       /* clock & input select, write 1 to PORTA */
+       table[KS_CMDD]     = 0x01;
+       table[KS_HAVB]     = 0x00;  /* HAV Start Control */
+       table[KS_HAVE]     = 0x00;  /* HAV End Control */
+       table[KS_HS1B]     = 0x10;  /* HS1 Start Control */
+       table[KS_HS1E]     = 0x00;  /* HS1 End Control */
+       table[KS_HS2B]     = 0x00;  /* HS2 Start Control */
+       table[KS_HS2E]     = 0x00;  /* HS2 End Control */
+       table[KS_AGC]      = 0x53;  /* Manual setting for AGC */
+       table[KS_HXTRA]    = 0x00;  /* Extra Bits for HAV and HS1/2 */
+       table[KS_CDEM]     = 0x00;  /* Chroma Demodulation Control */
+       table[KS_PORTAB]   = 0x0f;  /* port B is input, port A output GPPORT */
+       table[KS_LUMA]     = 0x01;  /* Luma control */
+       table[KS_CON]      = 0x00;  /* Contrast Control */
+       table[KS_BRT]      = 0x00;  /* Brightness Control */
+       table[KS_CHROMA]   = 0x2a;  /* Chroma control A */
+       table[KS_CHROMB]   = 0x90;  /* Chroma control B */
+       table[KS_DEMOD]    = 0x00;  /* Chroma Demodulation Control & Status */
+       table[KS_SAT]      = 0x00;  /* Color Saturation Control*/
+       table[KS_HUE]      = 0x00;  /* Hue Control */
+       table[KS_VERTIA]   = 0x00;  /* Vertical Processing Control A */
+       /* Vertical Processing Control B, luma 1 line delayed */
+       table[KS_VERTIB]   = 0x12;
+       table[KS_VERTIC]   = 0x0b;  /* Vertical Processing Control C */
+       table[KS_HSCLL]    = 0x00;  /* Horizontal Scaling Ratio Low */
+       table[KS_HSCLH]    = 0x00;  /* Horizontal Scaling Ratio High */
+       table[KS_VSCLL]    = 0x00;  /* Vertical Scaling Ratio Low */
+       table[KS_VSCLH]    = 0x00;  /* Vertical Scaling Ratio High */
+       /* 16 bit YCbCr 4:2:2 output; I can't make the bt866 like 8 bit /Sam */
+       table[KS_OFMTA]    = 0x30;
+       table[KS_OFMTB]    = 0x00;  /* Output Control B */
+       /* VBI Decoder Control; 4bit fmt: avoid Y overflow */
+       table[KS_VBICTL]   = 0x5d;
+       table[KS_CCDAT2]   = 0x00;  /* Read Only register */
+       table[KS_CCDAT1]   = 0x00;  /* Read Only register */
+       table[KS_VBIL30]   = 0xa8;  /* VBI data decoding options */
+       table[KS_VBIL74]   = 0xaa;  /* VBI data decoding options */
+       table[KS_VBIL118]  = 0x2a;  /* VBI data decoding options */
+       table[KS_VBIL1512] = 0x00;  /* VBI data decoding options */
+       table[KS_TTFRAM]   = 0x00;  /* Teletext frame alignment pattern */
+       table[KS_TESTA]    = 0x00;  /* test register, shouldn't be written */
+       table[KS_UVOFFH]   = 0x00;  /* UV Offset Adjustment High */
+       table[KS_UVOFFL]   = 0x00;  /* UV Offset Adjustment Low */
+       table[KS_UGAIN]    = 0x00;  /* U Component Gain Adjustment */
+       table[KS_VGAIN]    = 0x00;  /* V Component Gain Adjustment */
+       table[KS_VAVB]     = 0x07;  /* VAV Begin */
+       table[KS_VAVE]     = 0x00;  /* VAV End */
+       table[KS_CTRACK]   = 0x00;  /* Chroma Tracking Control */
+       table[KS_POLCTL]   = 0x41;  /* Timing Signal Polarity Control */
+       table[KS_REFCOD]   = 0x80;  /* Reference Code Insertion Control */
+       table[KS_INVALY]   = 0x10;  /* Invalid Y Code */
+       table[KS_INVALU]   = 0x80;  /* Invalid U Code */
+       table[KS_INVALV]   = 0x80;  /* Invalid V Code */
+       table[KS_UNUSEY]   = 0x10;  /* Unused Y Code */
+       table[KS_UNUSEU]   = 0x80;  /* Unused U Code */
+       table[KS_UNUSEV]   = 0x80;  /* Unused V Code */
+       table[KS_USRSAV]   = 0x00;  /* reserved */
+       table[KS_USREAV]   = 0x00;  /* reserved */
+       table[KS_SHS1A]    = 0x00;  /* User Defined SHS1 A */
+       /* User Defined SHS1 B, ALT656=1 on 0127B */
+       table[KS_SHS1B]    = 0x80;
+       table[KS_SHS1C]    = 0x00;  /* User Defined SHS1 C */
+       table[KS_CMDE]     = 0x00;  /* Command Register E */
+       table[KS_VSDEL]    = 0x00;  /* VS Delay Control */
+       /* Command Register F, update -immediately- */
+       /* (there might come no vsync)*/
+       table[KS_CMDF]     = 0x02;
+}
+
+
+/* We need to manually read because of a bug in the KS0127 chip.
+ *
+ * An explanation from kayork@mail.utexas.edu:
+ *
+ * During I2C reads, the KS0127 only samples for a stop condition
+ * during the place where the acknoledge bit should be. Any standard
+ * I2C implementation (correctly) throws in another clock transition
+ * at the 9th bit, and the KS0127 will not recognize the stop condition
+ * and will continue to clock out data.
+ *
+ * So we have to do the read ourself.  Big deal.
+          workaround in i2c-algo-bit
+ */
+
+
+static u8 ks0127_read(struct ks0127 *ks, u8 reg)
+{
+       struct i2c_client *c = ks->client;
+       char val = 0;
+       struct i2c_msg msgs[] = {
+               {c->addr, 0, sizeof(reg), &reg},
+               {c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val}};
+       int ret;
+
+       ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs));
+       if (ret != ARRAY_SIZE(msgs))
+               dprintk("ks0127_write error\n");
+
+       return val;
+}
+
+
+static void ks0127_write(struct ks0127 *ks, u8 reg, u8 val)
+{
+       char msg[] = {reg, val};
+
+       if (i2c_master_send(ks->client, msg, sizeof(msg)) != sizeof(msg))
+               dprintk("ks0127_write error\n");
+
+       ks->regs[reg] = val;
+}
+
+
+/* generic bit-twiddling */
+static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v)
+{
+       u8 val = ks->regs[reg];
+       val = (val & and_v) | or_v;
+       ks0127_write(ks, reg, val);
+}
+
+
+
+/****************************************************************************
+* ks0127 private api
+****************************************************************************/
+static void ks0127_reset(struct ks0127* ks)
+{
+       int i;
+       u8 *table = reg_defaults;
+
+       ks->ks_type = KS_TYPE_UNKNOWN;
+
+       dprintk("ks0127: reset\n");
+       msleep(1);
+
+       /* initialize all registers to known values */
+       /* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */
+
+       for(i = 1; i < 33; i++)
+               ks0127_write(ks, i, table[i]);
+
+       for(i = 35; i < 40; i++)
+               ks0127_write(ks, i, table[i]);
+
+       for(i = 41; i < 56; i++)
+               ks0127_write(ks, i, table[i]);
+
+       for(i = 58; i < 64; i++)
+               ks0127_write(ks, i, table[i]);
+
+
+       if ((ks0127_read(ks, KS_STAT) & 0x80) == 0) {
+               ks->ks_type = KS_TYPE_0122S;
+               dprintk("ks0127: ks0122s Found\n");
+               return;
+       }
+
+       switch(ks0127_read(ks, KS_CMDE) & 0x0f) {
+
+       case 0:
+               ks->ks_type = KS_TYPE_0127;
+               dprintk("ks0127: ks0127 found\n");
+               break;
+
+       case 9:
+               ks->ks_type = KS_TYPE_0127B;
+               dprintk("ks0127: ks0127B Revision A found\n");
+               break;
+
+       default:
+               dprintk("ks0127: unknown revision\n");
+               break;
+       }
+}
+
+static int ks0127_command(struct i2c_client *client,
+                         unsigned int cmd, void *arg)
+{
+       struct ks0127 *ks = i2c_get_clientdata(client);
+
+       int             *iarg = (int*)arg;
+
+       int             status;
+
+       if (!ks)
+               return -ENODEV;
+
+       switch (cmd) {
+
+       case DECODER_INIT:
+               dprintk("ks0127: command DECODER_INIT\n");
+               ks0127_reset(ks);
+               break;
+
+       case DECODER_SET_INPUT:
+               switch(*iarg) {
+               case KS_INPUT_COMPOSITE_1:
+               case KS_INPUT_COMPOSITE_2:
+               case KS_INPUT_COMPOSITE_3:
+               case KS_INPUT_COMPOSITE_4:
+               case KS_INPUT_COMPOSITE_5:
+               case KS_INPUT_COMPOSITE_6:
+                       dprintk("ks0127: command DECODER_SET_INPUT %d: "
+                               "Composite\n", *iarg);
+                       /* autodetect 50/60 Hz */
+                       ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+                       /* VSE=0 */
+                       ks0127_and_or(ks, KS_CMDA,   ~0x40, 0x00);
+                       /* set input line */
+                       ks0127_and_or(ks, KS_CMDB,   0xb0, *iarg);
+                       /* non-freerunning mode */
+                       ks0127_and_or(ks, KS_CMDC,   0x70, 0x0a);
+                       /* analog input */
+                       ks0127_and_or(ks, KS_CMDD,   0x03, 0x00);
+                       /* enable chroma demodulation */
+                       ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);
+                       /* chroma trap, HYBWR=1 */
+                       ks0127_and_or(ks, KS_LUMA,   0x00,
+                                      (reg_defaults[KS_LUMA])|0x0c);
+                       /* scaler fullbw, luma comb off */
+                       ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);
+                       /* manual chroma comb .25 .5 .25 */
+                       ks0127_and_or(ks, KS_VERTIC, 0x0f, 0x90);
+
+                       /* chroma path delay */
+                       ks0127_and_or(ks, KS_CHROMB, 0x0f, 0x90);
+
+                       ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);
+                       ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);
+                       ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+                       ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
+                       break;
+
+               case KS_INPUT_SVIDEO_1:
+               case KS_INPUT_SVIDEO_2:
+               case KS_INPUT_SVIDEO_3:
+                       dprintk("ks0127: command DECODER_SET_INPUT %d: "
+                               "S-Video\n", *iarg);
+                       /* autodetect 50/60 Hz */
+                       ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+                       /* VSE=0 */
+                       ks0127_and_or(ks, KS_CMDA,   ~0x40, 0x00);
+                       /* set input line */
+                       ks0127_and_or(ks, KS_CMDB,   0xb0, *iarg);
+                       /* non-freerunning mode */
+                       ks0127_and_or(ks, KS_CMDC,   0x70, 0x0a);
+                       /* analog input */
+                       ks0127_and_or(ks, KS_CMDD,   0x03, 0x00);
+                       /* enable chroma demodulation */
+                       ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);
+                       ks0127_and_or(ks, KS_LUMA, 0x00,
+                                      reg_defaults[KS_LUMA]);
+                       /* disable luma comb */
+                       ks0127_and_or(ks, KS_VERTIA, 0x08,
+                                      (reg_defaults[KS_VERTIA]&0xf0)|0x01);
+                       ks0127_and_or(ks, KS_VERTIC, 0x0f,
+                                      reg_defaults[KS_VERTIC]&0xf0);
+
+                       ks0127_and_or(ks, KS_CHROMB, 0x0f,
+                                      reg_defaults[KS_CHROMB]&0xf0);
+
+                       ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);
+                       ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);
+                       ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+                       ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
+                       break;
+
+               case KS_INPUT_YUV656:
+                       dprintk("ks0127: command DECODER_SET_INPUT 15: "
+                               "YUV656\n");
+                       if (ks->norm == VIDEO_MODE_NTSC ||
+                           ks->norm == KS_STD_PAL_M)
+                               /* force 60 Hz */
+                               ks0127_and_or(ks, KS_CMDA,   0xfc, 0x03);
+                       else
+                               /* force 50 Hz */
+                               ks0127_and_or(ks, KS_CMDA,   0xfc, 0x02);
+
+                       ks0127_and_or(ks, KS_CMDA,   0xff, 0x40); /* VSE=1 */
+                       /* set input line and VALIGN */
+                       ks0127_and_or(ks, KS_CMDB,   0xb0, (*iarg | 0x40));
+                       /* freerunning mode, */
+                       /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0  VMEM=1*/
+                       ks0127_and_or(ks, KS_CMDC,   0x70, 0x87);
+                       /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */
+                       ks0127_and_or(ks, KS_CMDD,   0x03, 0x08);
+                       /* disable chroma demodulation */
+                       ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x30);
+                       /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */
+                       ks0127_and_or(ks, KS_LUMA,   0x00, 0x71);
+                       ks0127_and_or(ks, KS_VERTIC, 0x0f,
+                                      reg_defaults[KS_VERTIC]&0xf0);
+
+                       /* scaler fullbw, luma comb off */
+                       ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);
+
+                       ks0127_and_or(ks, KS_CHROMB, 0x0f,
+                                      reg_defaults[KS_CHROMB]&0xf0);
+
+                       ks0127_and_or(ks, KS_CON, 0x00, 0x00);
+                       ks0127_and_or(ks, KS_BRT, 0x00, 32);    /* spec: 34 */
+                               /* spec: 229 (e5) */
+                       ks0127_and_or(ks, KS_SAT, 0x00, 0xe8);
+                       ks0127_and_or(ks, KS_HUE, 0x00, 0);
+
+                       ks0127_and_or(ks, KS_UGAIN, 0x00, 238);
+                       ks0127_and_or(ks, KS_VGAIN, 0x00, 0x00);
+
+                       /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */
+                       ks0127_and_or(ks, KS_UVOFFH, 0x00, 0x4f);
+                       ks0127_and_or(ks, KS_UVOFFL, 0x00, 0x00);
+                       break;
+
+               default:
+                       dprintk("ks0127: command DECODER_SET_INPUT: "
+                               "Unknown input %d\n", *iarg);
+                       break;
+               }
+
+               /* hack: CDMLPF sometimes spontaneously switches on; */
+               /* force back off */
+               ks0127_write(ks, KS_DEMOD, reg_defaults[KS_DEMOD]);
+               break;
+
+       case DECODER_SET_OUTPUT:
+               switch(*iarg) {
+               case KS_OUTPUT_YUV656E:
+                       dprintk("ks0127: command DECODER_SET_OUTPUT: "
+                               "OUTPUT_YUV656E (Missing)\n");
+                       return -EINVAL;
+                       break;
+
+               case KS_OUTPUT_EXV:
+                       dprintk("ks0127: command DECODER_SET_OUTPUT: "
+                               "OUTPUT_EXV\n");
+                       ks0127_and_or(ks, KS_OFMTA, 0xf0, 0x09);
+                       break;
+               }
+               break;
+
+       case DECODER_SET_NORM: //sam This block mixes old and new norm names...
+               /* Set to automatic SECAM/Fsc mode */
+               ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);
+
+               ks->norm = *iarg;
+               switch(*iarg)
+               {
+               /* this is untested !! */
+               /* It just detects PAL_N/NTSC_M (no special frequencies) */
+               /* And you have to set the standard a second time afterwards */
+               case VIDEO_MODE_AUTO:
+                       dprintk("ks0127: command DECODER_SET_NORM: AUTO\n");
+
+                       /* The chip determines the format */
+                       /* based on the current field rate */
+                       ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+                       ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+                       /* This is wrong for PAL ! As I said, */
+                       /* you need to set the standard once again !! */
+                       ks->format_height = 240;
+                       ks->format_width = 704;
+                       break;
+
+               case VIDEO_MODE_NTSC:
+                       dprintk("ks0127: command DECODER_SET_NORM: NTSC_M\n");
+                       ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+                       ks->format_height = 240;
+                       ks->format_width = 704;
+                       break;
+
+               case KS_STD_NTSC_N:
+                       dprintk("ks0127: command KS0127_SET_STANDARD: "
+                               "NTSC_N (fixme)\n");
+                       ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);
+                       ks->format_height = 240;
+                       ks->format_width = 704;
+                       break;
+
+               case VIDEO_MODE_PAL:
+                       dprintk("ks0127: command DECODER_SET_NORM: PAL_N\n");
+                       ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+                       ks->format_height = 290;
+                       ks->format_width = 704;
+                       break;
+
+               case KS_STD_PAL_M:
+                       dprintk("ks0127: command KS0127_SET_STANDARD: "
+                               "PAL_M (fixme)\n");
+                       ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);
+                       ks->format_height = 290;
+                       ks->format_width = 704;
+                       break;
+
+               case VIDEO_MODE_SECAM:
+                       dprintk("ks0127: command KS0127_SET_STANDARD: "
+                               "SECAM\n");
+                       ks->format_height = 290;
+                       ks->format_width = 704;
+
+                       /* set to secam autodetection */
+                       ks0127_and_or(ks, KS_CHROMA, 0xdf, 0x20);
+                       ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);
+                       schedule_timeout_interruptible(HZ/10+1);
+
+                       /* did it autodetect? */
+                       if (ks0127_read(ks, KS_DEMOD) & 0x40)
+                               break;
+
+                       /* force to secam mode */
+                       ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x0f);
+                       break;
+
+               default:
+                       dprintk("ks0127: command DECODER_SET_NORM: "
+                               "Unknown norm %d\n", *iarg);
+                       break;
+               }
+               break;
+
+       case DECODER_SET_PICTURE:
+               dprintk("ks0127: command DECODER_SET_PICTURE "
+                       "not yet supported (fixme)\n");
+               return -EINVAL;
+
+       //sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE
+       //sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE
+       //sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE?
+       //sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE
+       //sam todo: KS0127_SET_AGC_MODE:
+       //sam todo: KS0127_SET_AGC:
+       //sam todo: KS0127_SET_CHROMA_MODE:
+       //sam todo: KS0127_SET_PIXCLK_MODE:
+       //sam todo: KS0127_SET_GAMMA_MODE:
+       //sam todo: KS0127_SET_UGAIN:
+       //sam todo: KS0127_SET_VGAIN:
+       //sam todo: KS0127_SET_INVALY:
+       //sam todo: KS0127_SET_INVALU:
+       //sam todo: KS0127_SET_INVALV:
+       //sam todo: KS0127_SET_UNUSEY:
+       //sam todo: KS0127_SET_UNUSEU:
+       //sam todo: KS0127_SET_UNUSEV:
+       //sam todo: KS0127_SET_VSALIGN_MODE:
+
+       case DECODER_ENABLE_OUTPUT:
+       {
+
+               int *iarg = arg;
+               int enable = (*iarg != 0);
+                       if (enable) {
+                               dprintk("ks0127: command "
+                                       "DECODER_ENABLE_OUTPUT on "
+                                       "(%d)\n", enable);
+                               /* All output pins on */
+                               ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30);
+                               /* Obey the OEN pin */
+                               ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00);
+                       } else {
+                               dprintk("ks0127: command "
+                                       "DECODER_ENABLE_OUTPUT off "
+                                       "(%d)\n", enable);
+                               /* Video output pins off */
+                               ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00);
+                               /* Ignore the OEN pin */
+                               ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80);
+                       }
+       }
+               break;
+
+       //sam todo: KS0127_SET_OUTPUT_MODE:
+       //sam todo: KS0127_SET_WIDTH:
+       //sam todo: KS0127_SET_HEIGHT:
+       //sam todo: KS0127_SET_HSCALE:
+
+       case DECODER_GET_STATUS:
+               dprintk("ks0127: command DECODER_GET_STATUS\n");
+               *iarg = 0;
+               status = ks0127_read(ks, KS_STAT);
+               if (!(status & 0x20))            /* NOVID not set */
+                       *iarg = (*iarg & DECODER_STATUS_GOOD);
+               if ((status & 0x01))                  /* CLOCK set */
+                       *iarg = (*iarg & DECODER_STATUS_COLOR);
+               if ((status & 0x08))               /* PALDET set */
+                       *iarg = (*iarg & DECODER_STATUS_PAL);
+               else
+                       *iarg = (*iarg & DECODER_STATUS_NTSC);
+               break;
+
+       //Catch any unknown command
+       default:
+               dprintk("ks0127: command unknown: %04X\n", cmd);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+
+
+
+static int ks0127_probe(struct i2c_adapter *adapter);
+static int ks0127_detach(struct i2c_client *client);
+static int ks0127_command(struct i2c_client *client,
+                         unsigned int cmd, void *arg);
+
+
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {I2C_KS0127_ADDON>>1,
+                                      I2C_KS0127_ONBOARD>>1, I2C_CLIENT_END};
+static unsigned short probe[2] =       {I2C_CLIENT_END, I2C_CLIENT_END};
+static unsigned short ignore[2] =      {I2C_CLIENT_END, I2C_CLIENT_END};
+static struct i2c_client_address_data addr_data = {
+       normal_i2c,
+       probe,
+       ignore,
+};
+
+static struct i2c_driver i2c_driver_ks0127 = {
+       .driver.name = "ks0127",
+       .id             = I2C_DRIVERID_KS0127,
+       .attach_adapter = ks0127_probe,
+       .detach_client  = ks0127_detach,
+       .command        = ks0127_command
+};
+
+static struct i2c_client ks0127_client_tmpl =
+{
+       .name = "(ks0127 unset)",
+       .addr = 0,
+       .adapter = NULL,
+       .driver = &i2c_driver_ks0127,
+       .usage_count = 0
+};
+
+static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind)
+{
+       struct ks0127 *ks;
+       struct i2c_client *client;
+
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
+       if (client == NULL)
+               return -ENOMEM;
+       memcpy(client, &ks0127_client_tmpl, sizeof(*client));
+
+       ks = kzalloc(sizeof(*ks), GFP_KERNEL);
+       if (ks == NULL) {
+               kfree(client);
+               return -ENOMEM;
+       }
+
+       i2c_set_clientdata(client, ks);
+       client->adapter = adapter;
+       client->addr = addr;
+       sprintf(client->name, "ks0127-%02x", adapter->id);
+
+       ks->client = client;
+       ks->addr = addr;
+       ks->ks_type = KS_TYPE_UNKNOWN;
+
+       /* power up */
+       ks0127_write(ks, KS_CMDA, 0x2c);
+       mdelay(10);
+
+       /* reset the device */
+       ks0127_reset(ks);
+       printk(KERN_INFO "ks0127: attach: %s video decoder\n",
+              ks->addr==(I2C_KS0127_ADDON>>1) ? "addon" : "on-board");
+
+       i2c_attach_client(client);
+       return 0;
+}
+
+
+static int ks0127_probe(struct i2c_adapter *adapter)
+{
+       if (adapter->id == I2C_HW_B_ZR36067)
+               return i2c_probe(adapter, &addr_data, ks0127_found_proc);
+       return 0;
+}
+
+static int ks0127_detach(struct i2c_client *client)
+{
+       struct ks0127 *ks = i2c_get_clientdata(client);
+
+       ks0127_write(ks, KS_OFMTA, 0x20); /*tristate*/
+       ks0127_write(ks, KS_CMDA, 0x2c | 0x80); /* power down */
+
+       i2c_detach_client(client);
+       kfree(ks);
+       kfree(client);
+
+       dprintk("ks0127: detach\n");
+       return 0;
+}
+
+
+static int __devinit ks0127_init_module(void)
+{
+       init_reg_defaults();
+       i2c_add_driver(&i2c_driver_ks0127);
+       return 0;
+}
+
+static void __devexit ks0127_cleanup_module(void)
+{
+       i2c_del_driver(&i2c_driver_ks0127);
+}
+
+
+module_init(ks0127_init_module);
+module_exit(ks0127_cleanup_module);
diff --git a/drivers/media/video/ks0127.h b/drivers/media/video/ks0127.h
new file mode 100644 (file)
index 0000000..1ec5788
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Video Capture Driver ( Video for Linux 1/2 )
+ * for the Matrox Marvel G200,G400 and Rainbow Runner-G series
+ *
+ * This module is an interface to the KS0127 video decoder chip.
+ *
+ * Copyright (C) 1999  Ryan Drake <stiletto@mediaone.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef KS0127_H
+#define KS0127_H
+
+#include <linux/videodev.h>
+
+/* input channels */
+#define KS_INPUT_COMPOSITE_1    0
+#define KS_INPUT_COMPOSITE_2    1
+#define KS_INPUT_COMPOSITE_3    2
+#define KS_INPUT_COMPOSITE_4    4
+#define KS_INPUT_COMPOSITE_5    5
+#define KS_INPUT_COMPOSITE_6    6
+
+#define KS_INPUT_SVIDEO_1       8
+#define KS_INPUT_SVIDEO_2       9
+#define KS_INPUT_SVIDEO_3       10
+
+#define KS_INPUT_YUV656                15
+#define KS_INPUT_COUNT          10
+
+/* output channels */
+#define KS_OUTPUT_YUV656E       0
+#define KS_OUTPUT_EXV           1
+
+/* video standards */
+#define KS_STD_NTSC_N           112       /* 50 Hz NTSC */
+#define KS_STD_PAL_M            113       /* 60 Hz PAL  */
+
+#endif /* KS0127_H */
+
index 850bee97090c91e169531c0d218d9933c4b9f1e1..f68ca7d9f5319b28a34e47e834022b6ea2a970c3 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/delay.h>
@@ -1682,13 +1683,13 @@ static unsigned int meye_poll(struct file *file, poll_table *wait)
 
 static void meye_vm_open(struct vm_area_struct *vma)
 {
-       int idx = (int)vma->vm_private_data;
+       long idx = (long)vma->vm_private_data;
        meye.vma_use_count[idx]++;
 }
 
 static void meye_vm_close(struct vm_area_struct *vma)
 {
-       int idx = (int)vma->vm_private_data;
+       long idx = (long)vma->vm_private_data;
        meye.vma_use_count[idx]--;
 }
 
index b806999d6e0fc69e11c01c2accf67ba4a38562d5..dbb75a7db199ca6635ca2b194e204542f2c2fd66 100644 (file)
@@ -385,67 +385,6 @@ static int msp_mode_v4l1_to_v4l2(int mode)
        return V4L2_TUNER_MODE_MONO;
 }
 
-static struct v4l2_queryctrl msp_qctrl_std[] = {
-       {
-               .id            = V4L2_CID_AUDIO_VOLUME,
-               .name          = "Volume",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 58880,
-               .flags         = 0,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_AUDIO_MUTE,
-               .name          = "Mute",
-               .minimum       = 0,
-               .maximum       = 1,
-               .step          = 1,
-               .default_value = 1,
-               .flags         = 0,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },
-};
-
-static struct v4l2_queryctrl msp_qctrl_sound_processing[] = {
-       {
-               .id            = V4L2_CID_AUDIO_BALANCE,
-               .name          = "Balance",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 32768,
-               .flags         = 0,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_AUDIO_BASS,
-               .name          = "Bass",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 32768,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_AUDIO_TREBLE,
-               .name          = "Treble",
-               .minimum       = 0,
-               .maximum       = 65535,
-               .step          = 65535/100,
-               .default_value = 32768,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_AUDIO_LOUDNESS,
-               .name          = "Loudness",
-               .minimum       = 0,
-               .maximum       = 1,
-               .step          = 1,
-               .default_value = 1,
-               .flags         = 0,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },
-};
-
-
 static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
 {
        struct msp_state *state = i2c_get_clientdata(client);
@@ -674,22 +613,31 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
                int sc1_out = rt->output & 0xf;
                int sc2_out = (rt->output >> 4) & 0xf;
                u16 val, reg;
+               int i;
+               int extern_input = 1;
 
                if (state->routing.input == rt->input &&
                    state->routing.output == rt->output)
                        break;
                state->routing = *rt;
+               /* check if the tuner input is used */
+               for (i = 0; i < 5; i++) {
+                       if (((rt->input >> (4 + i * 4)) & 0xf) == 0)
+                               extern_input = 0;
+               }
+               if (extern_input)
+                       state->mode = MSP_MODE_EXTERN;
+               else
+                       state->mode = MSP_MODE_AM_DETECT;
                msp_set_scart(client, sc_in, 0);
                msp_set_scart(client, sc1_out, 1);
                msp_set_scart(client, sc2_out, 2);
                msp_set_audmode(client);
                reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb;
                val = msp_read_dem(client, reg);
-               if (tuner != ((val >> 8) & 1)) {
-                       msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));
-                       /* wake thread when a new tuner input is chosen */
-                       msp_wake_thread(client);
-               }
+               msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));
+               /* wake thread when a new input is chosen */
+               msp_wake_thread(client);
                break;
        }
 
@@ -744,21 +692,25 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
        case VIDIOC_QUERYCTRL:
        {
                struct v4l2_queryctrl *qc = arg;
-               int i;
 
-               for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++)
-                       if (qc->id && qc->id == msp_qctrl_std[i].id) {
-                               memcpy(qc, &msp_qctrl_std[i], sizeof(*qc));
-                               return 0;
-                       }
+               switch (qc->id) {
+                       case V4L2_CID_AUDIO_VOLUME:
+                       case V4L2_CID_AUDIO_MUTE:
+                               return v4l2_ctrl_query_fill_std(qc);
+                       default:
+                               break;
+               }
                if (!state->has_sound_processing)
                        return -EINVAL;
-               for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++)
-                       if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) {
-                               memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc));
-                               return 0;
-                       }
-               return -EINVAL;
+               switch (qc->id) {
+                       case V4L2_CID_AUDIO_LOUDNESS:
+                       case V4L2_CID_AUDIO_BALANCE:
+                       case V4L2_CID_AUDIO_BASS:
+                       case V4L2_CID_AUDIO_TREBLE:
+                               return v4l2_ctrl_query_fill_std(qc);
+                       default:
+                               return -EINVAL;
+               }
        }
 
        case VIDIOC_G_CTRL:
@@ -794,7 +746,9 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
                case MSP_MODE_EXTERN: p = "External input"; break;
                default: p = "unknown"; break;
                }
-               if (state->opmode == OPMODE_MANUAL) {
+               if (state->mode == MSP_MODE_EXTERN) {
+                       v4l_info(client, "Mode:     %s\n", p);
+               } else if (state->opmode == OPMODE_MANUAL) {
                        v4l_info(client, "Mode:     %s (%s%s)\n", p,
                                (state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
                                (state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
index 633a1021378930261d3ff20f8b4edfc42a846fa5..f2fd9195b3ac6491468deec543c9c68fdf0af379 100644 (file)
@@ -244,19 +244,21 @@ static void msp3400c_set_audmode(struct i2c_client *client)
           the hardware does not support SAP. So the rxsubchans combination
           of STEREO | LANG2 does not occur. */
 
-       /* switch to mono if only mono is available */
-       if (state->rxsubchans == V4L2_TUNER_SUB_MONO)
-               audmode = V4L2_TUNER_MODE_MONO;
-       /* if bilingual */
-       else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) {
-               /* and mono or stereo, then fallback to lang1 */
-               if (audmode == V4L2_TUNER_MODE_MONO ||
-                   audmode == V4L2_TUNER_MODE_STEREO)
-                       audmode = V4L2_TUNER_MODE_LANG1;
+       if (state->mode != MSP_MODE_EXTERN) {
+               /* switch to mono if only mono is available */
+               if (state->rxsubchans == V4L2_TUNER_SUB_MONO)
+                       audmode = V4L2_TUNER_MODE_MONO;
+               /* if bilingual */
+               else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) {
+                       /* and mono or stereo, then fallback to lang1 */
+                       if (audmode == V4L2_TUNER_MODE_MONO ||
+                           audmode == V4L2_TUNER_MODE_STEREO)
+                               audmode = V4L2_TUNER_MODE_LANG1;
+               }
+               /* if stereo, and audmode is not mono, then switch to stereo */
+               else if (audmode != V4L2_TUNER_MODE_MONO)
+                       audmode = V4L2_TUNER_MODE_STEREO;
        }
-       /* if stereo, and audmode is not mono, then switch to stereo */
-       else if (audmode != V4L2_TUNER_MODE_MONO)
-               audmode = V4L2_TUNER_MODE_STEREO;
 
        /* switch demodulator */
        switch (state->mode) {
@@ -481,6 +483,7 @@ int msp3400c_thread(void *data)
                        /* no carrier scan, just unmute */
                        v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
                        state->scan_in_progress = 0;
+                       state->rxsubchans = V4L2_TUNER_SUB_STEREO;
                        msp_set_audio(client);
                        continue;
                }
@@ -947,6 +950,14 @@ int msp34xxg_thread(void *data)
                if (kthread_should_stop())
                        break;
 
+               if (state->mode == MSP_MODE_EXTERN) {
+                       /* no carrier scan needed, just unmute */
+                       v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+                       state->scan_in_progress = 0;
+                       msp_set_audio(client);
+                       continue;
+               }
+
                /* setup the chip*/
                msp34xxg_reset(client);
                state->std = state->radio ? 0x40 : msp_standard;
@@ -978,6 +989,11 @@ int msp34xxg_thread(void *data)
                v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n",
                        msp_standard_std_name(state->std), state->std);
 
+               if (state->std == 9) {
+                       /* AM NICAM mode */
+                       msp_write_dsp(client, 0x0e, 0x7c00);
+               }
+
                /* unmute: dispatch sound to scart output, set scart volume */
                msp_set_audio(client);
 
index fdc8e3f139373880f68045a7c1381f26e67b0a70..a988df226aabc3aa4c709c322735c33156067dcd 100644 (file)
@@ -3239,7 +3239,7 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
                RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
 
                if (frame->scanstate == STATE_LINES) {
-                       int nextf;
+                       int nextf;
 
                        frame->grabstate = FRAME_DONE;
                        wake_up_interruptible(&frame->wq);
@@ -3405,7 +3405,7 @@ eof:
        RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
 
        if (frame->scanstate == STATE_LINES) {
-               int nextf;
+               int nextf;
 
                frame->grabstate = FRAME_DONE;
                wake_up_interruptible(&frame->wq);
index 12b3d51e1c343bdd77c0d66f99d7962562d71af7..68b082bcee1dcf2c704f53d0b194a61a1365a506 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
index d9e3cada52f4fba0bd349915834a811951a57247..3484e36b68016f4d2c58953ed9fa60dc3d4c6e7a 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
index 09835ca098b169b4226c1da8f030786776559e35..5d681fa8bcb18d80504bb92d1bd58fbd90aabbff 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/io.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 #include <asm/uaccess.h>
@@ -804,7 +805,7 @@ static int pms_do_ioctl(struct inode *inode, struct file *file,
                        struct video_picture *p = arg;
                        if(!((p->palette==VIDEO_PALETTE_RGB565 && p->depth==16)
                            ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15)))
-                               return -EINVAL;
+                               return -EINVAL;
                        pd->picture= *p;
 
                        /*
index 53cbc950f95c6a74066ba64c840b8fe28ac35b6e..697145e0bf15b551c7073ef727a6c602fc2e0180 100644 (file)
@@ -7,6 +7,7 @@ config USB_PWC
           * Philips PCA645, PCA646
           * Philips PCVC675, PCVC680, PCVC690
           * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
+          * Philips SPC900NC
           * Askey VC010
           * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
             and 'Orbit'/'Sphere'
@@ -19,10 +20,18 @@ config USB_PWC
          and never will be, but the 665 and 720/20 are supported by other
          drivers.
 
-         See <file:Documentation/usb/philips.txt> for more information and
-         installation instructions.
+         Some newer logitech webcams are not handled by this driver but by the
+         Usb Video Class driver (linux-uvc).
 
          The built-in microphone is enabled by selecting USB Audio support.
 
          To compile this driver as a module, choose M here: the
          module will be called pwc.
+
+config USB_PWC_DEBUG
+       bool "USB Philips Cameras verbose debug"
+       depends USB_PWC
+       help
+         Say Y here in order to have the pwc driver generate verbose debugging
+         messages.
+         A special module options 'trace' is used to control the verbosity.
index 33d60126c02499b27a29a4bfcd2628669c9f6ccc..9db2260d10ccb345c59845f7dd9ba33e5b1a8384 100644 (file)
@@ -1,3 +1,12 @@
-pwc-objs       := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o
+pwc-objs       := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o
+pwc-objs       += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
 
 obj-$(CONFIG_USB_PWC) += pwc.o
+
+ifeq ($(CONFIG_USB_PWC_DEBUG),y)
+EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=1
+else
+EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=0
+endif
+
+
index 4ba549bfa0e0cef6707e4955249bcaa886d425f9..0bd115588f319934a12b514fcda709736c34b916 100644 (file)
@@ -2,7 +2,7 @@
    Functions that send various control messages to the webcam, including
    video modes.
    (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
 #include <asm/uaccess.h>
 #endif
 #include <asm/errno.h>
+#include <linux/version.h>
 
 #include "pwc.h"
-#include "pwc-ioctl.h"
 #include "pwc-uncompress.h"
 #include "pwc-kiara.h"
 #include "pwc-timon.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
 
 /* Request types: video */
 #define SET_LUM_CTL                    0x01
 #define GET_STATUS_CTL                 0x06
 #define SET_EP_STREAM_CTL              0x07
 #define GET_EP_STREAM_CTL              0x08
+#define GET_XX_CTL                     0x09
+#define SET_XX_CTL                     0x0A
+#define GET_XY_CTL                     0x0B
+#define SET_XY_CTL                     0x0C
 #define SET_MPT_CTL                    0x0D
 #define GET_MPT_CTL                    0x0E
 
 #define READ_SHUTTER_FORMATTER                 0x0600
 #define READ_RED_GAIN_FORMATTER                        0x0700
 #define READ_BLUE_GAIN_FORMATTER               0x0800
+#define GET_STATUS_B00                         0x0B00
 #define SENSOR_TYPE_FORMATTER1                 0x0C00
+#define GET_STATUS_3000                                0x3000
 #define READ_RAW_Y_MEAN_FORMATTER              0x3100
 #define SET_POWER_SAVE_MODE_FORMATTER          0x3200
 #define MIRROR_IMAGE_FORMATTER                 0x3300
 #define LED_FORMATTER                          0x3400
+#define LOWLIGHT                               0x3500
+#define GET_STATUS_3600                                0x3600
 #define SENSOR_TYPE_FORMATTER2                 0x3700
+#define GET_STATUS_3800                                0x3800
+#define GET_STATUS_4000                                0x4000
+#define GET_STATUS_4100                                0x4100  /* Get */
+#define CTL_STATUS_4200                                0x4200  /* [GS] 1 */
 
 /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
 #define VIDEO_OUTPUT_CONTROL_FORMATTER         0x0100
@@ -138,6 +152,7 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
 #include "pwc-nala.h"
 };
 
+static void pwc_set_image_buffer_size(struct pwc_device *pdev);
 
 /****************************************************************************/
 
@@ -159,31 +174,7 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
                &buf, buflen, 500)
 
 
-#if PWC_DEBUG
-void pwc_hexdump(void *p, int len)
-{
-       int i;
-       unsigned char *s;
-       char buf[100], *d;
-
-       s = (unsigned char *)p;
-       d = buf;
-       *d = '\0';
-       Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
-       for (i = 0; i < len; i++) {
-               d += sprintf(d, "%02X ", *s++);
-               if ((i & 0xF) == 0xF) {
-                       Debug("%s\n", buf);
-                       d = buf;
-                       *d = '\0';
-               }
-       }
-       if ((i & 0xF) != 0)
-               Debug("%s\n", buf);
-}
-#endif
-
-static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
+static int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
 {
        return usb_control_msg(udev,
                usb_sndctrlpipe(udev, 0),
@@ -196,7 +187,7 @@ static inline int send_video_command(struct usb_device *udev, int index, void *b
 
 
 
-static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
+static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
 {
        unsigned char buf[3];
        int ret, fps;
@@ -229,34 +220,14 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
        if (pEntry->alternate == 0)
                return -EINVAL;
 
-       if (pEntry->compressed)
-               return -ENOENT; /* Not supported. */
-
        memcpy(buf, pEntry->mode, 3);
        ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
        if (ret < 0) {
-               Debug("Failed to send video command... %d\n", ret);
+               PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
                return ret;
        }
        if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW)
-        {
-          switch(pdev->type) {
-            case 645:
-            case 646:
-/*            pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
-              break;
-
-            case 675:
-            case 680:
-            case 690:
-            case 720:
-            case 730:
-            case 740:
-            case 750:
-/*            pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
-              break;
-          }
-       }
+               pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
 
        pdev->cmd_len = 3;
        memcpy(pdev->cmd_buf, buf, 3);
@@ -283,7 +254,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
 }
 
 
-static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
 {
        unsigned char buf[13];
        const struct Timon_table_entry *pChoose;
@@ -315,8 +286,8 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
        if (ret < 0)
                return ret;
 
-/*     if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
-          pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
+       if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+               pwc_dec23_init(pdev, pdev->type, buf);
 
        pdev->cmd_len = 13;
        memcpy(pdev->cmd_buf, buf, 13);
@@ -336,7 +307,7 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
 }
 
 
-static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
 {
        const struct Kiara_table_entry *pChoose = NULL;
        int fps, ret;
@@ -350,21 +321,14 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
        fps = (frames / 5) - 1;
 
        /* special case: VGA @ 5 fps and snapshot is raw bayer mode */
-       if (size == PSZ_VGA && frames == 5 && snapshot)
+       if (size == PSZ_VGA && frames == 5 && snapshot && pdev->vpalette == VIDEO_PALETTE_RAW)
        {
                /* Only available in case the raw palette is selected or
                   we have the decompressor available. This mode is
                   only available in compressed form
                */
-               if (pdev->vpalette == VIDEO_PALETTE_RAW)
-               {
-                       Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
-                       pChoose = &RawEntry;
-               }
-               else
-               {
-                       Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n");
-               }
+               PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode.\n");
+               pChoose = &RawEntry;
        }
        else
        {
@@ -372,6 +336,7 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
                   if the preferred ratio is not available.
                   Skip this step when using RAW modes.
                */
+               snapshot = 0;
                while (compression <= 3) {
                        pChoose = &Kiara_table[size][fps][compression];
                        if (pChoose->alternate != 0)
@@ -382,7 +347,7 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
        if (pChoose == NULL || pChoose->alternate == 0)
                return -ENOENT; /* Not supported. */
 
-       Debug("Using alternate setting %d.\n", pChoose->alternate);
+       PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate);
 
        /* usb_control_msg won't take staticly allocated arrays as argument?? */
        memcpy(buf, pChoose->mode, 12);
@@ -394,8 +359,8 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
        if (ret < 0)
                return ret;
 
-/*     if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
-         pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
+       if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+               pwc_dec23_init(pdev, pdev->type, buf);
 
        pdev->cmd_len = 12;
        memcpy(pdev->cmd_buf, buf, 12);
@@ -410,49 +375,13 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
                pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
        else
                pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+       PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n",
+           pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength);
        return 0;
 }
 
 
 
-static void pwc_set_image_buffer_size(struct pwc_device *pdev)
-{
-       int i, factor = 0, filler = 0;
-
-       /* for PALETTE_YUV420P */
-       switch(pdev->vpalette)
-       {
-       case VIDEO_PALETTE_YUV420P:
-               factor = 6;
-               filler = 128;
-               break;
-       case VIDEO_PALETTE_RAW:
-               factor = 6; /* can be uncompressed YUV420P */
-               filler = 0;
-               break;
-       }
-
-       /* Set sizes in bytes */
-       pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
-       pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
-
-       /* Align offset, or you'll get some very weird results in
-          YUV420 mode... x must be multiple of 4 (to get the Y's in
-          place), and y even (or you'll mixup U & V). This is less of a
-          problem for YUV420P.
-        */
-       pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
-       pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
-
-       /* Fill buffers with gray or black */
-       for (i = 0; i < MAX_IMAGES; i++) {
-               if (pdev->image_ptr[i] != NULL)
-                       memset(pdev->image_ptr[i], filler, pdev->view.size);
-       }
-}
-
-
-
 /**
    @pdev: device structure
    @width: viewport width
@@ -465,50 +394,78 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
 {
        int ret, size;
 
-       Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
+       PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
        size = pwc_decode_size(pdev, width, height);
        if (size < 0) {
-               Debug("Could not find suitable size.\n");
+               PWC_DEBUG_MODULE("Could not find suitable size.\n");
                return -ERANGE;
        }
-       Debug("decode_size = %d.\n", size);
+       PWC_TRACE("decode_size = %d.\n", size);
 
-       ret = -EINVAL;
-       switch(pdev->type) {
-       case 645:
-       case 646:
+       if (DEVICE_USE_CODEC1(pdev->type)) {
                ret = set_video_mode_Nala(pdev, size, frames);
-               break;
 
-       case 675:
-       case 680:
-       case 690:
-               ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
-               break;
-
-       case 720:
-       case 730:
-       case 740:
-       case 750:
+       } else if (DEVICE_USE_CODEC3(pdev->type)) {
                ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
-               break;
+
+       } else {
+               ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
        }
        if (ret < 0) {
-               if (ret == -ENOENT)
-                       Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
-               else {
-                       Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
-               }
+               PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
                return ret;
        }
        pdev->view.x = width;
        pdev->view.y = height;
        pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
        pwc_set_image_buffer_size(pdev);
-       Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
+       PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
        return 0;
 }
 
+#define BLACK_Y 0
+#define BLACK_U 128
+#define BLACK_V 128
+
+static void pwc_set_image_buffer_size(struct pwc_device *pdev)
+{
+       int i, factor = 0;
+
+       /* for PALETTE_YUV420P */
+       switch(pdev->vpalette)
+       {
+       case VIDEO_PALETTE_YUV420P:
+               factor = 6;
+               break;
+       case VIDEO_PALETTE_RAW:
+               factor = 6; /* can be uncompressed YUV420P */
+               break;
+       }
+
+       /* Set sizes in bytes */
+       pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
+       pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
+
+       /* Align offset, or you'll get some very weird results in
+          YUV420 mode... x must be multiple of 4 (to get the Y's in
+          place), and y even (or you'll mixup U & V). This is less of a
+          problem for YUV420P.
+        */
+       pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
+       pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
+
+       /* Fill buffers with black colors */
+       for (i = 0; i < pwc_mbufs; i++) {
+               unsigned char *p = pdev->image_data + pdev->images[i].offset;
+               memset(p, BLACK_Y, pdev->view.x * pdev->view.y);
+               p += pdev->view.x * pdev->view.y;
+               memset(p, BLACK_U, pdev->view.x * pdev->view.y/4);
+               p += pdev->view.x * pdev->view.y/4;
+               memset(p, BLACK_V, pdev->view.x * pdev->view.y/4);
+       }
+}
+
+
 
 /* BRIGHTNESS */
 
@@ -520,7 +477,7 @@ int pwc_get_brightness(struct pwc_device *pdev)
        ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
        if (ret < 0)
                return ret;
-       return buf << 9;
+       return buf;
 }
 
 int pwc_set_brightness(struct pwc_device *pdev, int value)
@@ -545,7 +502,7 @@ int pwc_get_contrast(struct pwc_device *pdev)
        ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1);
        if (ret < 0)
                return ret;
-       return buf << 10;
+       return buf;
 }
 
 int pwc_set_contrast(struct pwc_device *pdev, int value)
@@ -570,7 +527,7 @@ int pwc_get_gamma(struct pwc_device *pdev)
        ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1);
        if (ret < 0)
                return ret;
-       return buf << 11;
+       return buf;
 }
 
 int pwc_set_gamma(struct pwc_device *pdev, int value)
@@ -588,37 +545,47 @@ int pwc_set_gamma(struct pwc_device *pdev, int value)
 
 /* SATURATION */
 
-int pwc_get_saturation(struct pwc_device *pdev)
+/* return a value between [-100 , 100] */
+int pwc_get_saturation(struct pwc_device *pdev, int *value)
 {
        char buf;
-       int ret;
+       int ret, saturation_register;
 
        if (pdev->type < 675)
-               return -1;
-       ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1);
+               return -EINVAL;
+       if (pdev->type < 730)
+               saturation_register = SATURATION_MODE_FORMATTER2;
+       else
+               saturation_register = SATURATION_MODE_FORMATTER1;
+       ret = RecvControlMsg(GET_CHROM_CTL, saturation_register, 1);
        if (ret < 0)
                return ret;
-       return 32768 + buf * 327;
+       *value = (signed)buf;
+       return 0;
 }
 
+/* @param value saturation color between [-100 , 100] */
 int pwc_set_saturation(struct pwc_device *pdev, int value)
 {
        char buf;
+       int saturation_register;
 
        if (pdev->type < 675)
                return -EINVAL;
-       if (value < 0)
-               value = 0;
-       if (value > 0xffff)
-               value = 0xffff;
-       /* saturation ranges from -100 to +100 */
-       buf = (value - 32768) / 327;
-       return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1);
+       if (value < -100)
+               value = -100;
+       if (value > 100)
+               value = 100;
+       if (pdev->type < 730)
+               saturation_register = SATURATION_MODE_FORMATTER2;
+       else
+               saturation_register = SATURATION_MODE_FORMATTER1;
+       return SendControlMsg(SET_CHROM_CTL, saturation_register, 1);
 }
 
 /* AGC */
 
-static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
+int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
 {
        char buf;
        int ret;
@@ -643,7 +610,7 @@ static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
        return 0;
 }
 
-static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
+int pwc_get_agc(struct pwc_device *pdev, int *value)
 {
        unsigned char buf;
        int ret;
@@ -673,7 +640,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
        return 0;
 }
 
-static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
+int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
 {
        char buf[2];
        int speed, ret;
@@ -691,23 +658,16 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
                        value = 0;
                if (value > 0xffff)
                        value = 0xffff;
-               switch(pdev->type) {
-               case 675:
-               case 680:
-               case 690:
+
+               if (DEVICE_USE_CODEC2(pdev->type)) {
                        /* speed ranges from 0x0 to 0x290 (656) */
                        speed = (value / 100);
                        buf[1] = speed >> 8;
                        buf[0] = speed & 0xff;
-                       break;
-               case 720:
-               case 730:
-               case 740:
-               case 750:
+               } else if (DEVICE_USE_CODEC3(pdev->type)) {
                        /* speed seems to range from 0x0 to 0xff */
                        buf[1] = 0;
                        buf[0] = value >> 8;
-                       break;
                }
 
                ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2);
@@ -715,6 +675,25 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
        return ret;
 }
 
+/* This function is not exported to v4l1, so output values between 0 -> 256 */
+int pwc_get_shutter_speed(struct pwc_device *pdev, int *value)
+{
+       unsigned char buf[2];
+       int ret;
+
+       ret = RecvControlMsg(GET_STATUS_CTL, READ_SHUTTER_FORMATTER, 2);
+       if (ret < 0)
+               return ret;
+       *value = buf[0] + (buf[1] << 8);
+       if (DEVICE_USE_CODEC2(pdev->type)) {
+               /* speed ranges from 0x0 to 0x290 (656) */
+               *value *= 256/656;
+       } else if (DEVICE_USE_CODEC3(pdev->type)) {
+               /* speed seems to range from 0x0 to 0xff */
+       }
+       return 0;
+}
+
 
 /* POWER */
 
@@ -736,19 +715,19 @@ int pwc_camera_power(struct pwc_device *pdev, int power)
 
 /* private calls */
 
-static inline int pwc_restore_user(struct pwc_device *pdev)
+int pwc_restore_user(struct pwc_device *pdev)
 {
        char buf; /* dummy */
        return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0);
 }
 
-static inline int pwc_save_user(struct pwc_device *pdev)
+int pwc_save_user(struct pwc_device *pdev)
 {
        char buf; /* dummy */
        return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0);
 }
 
-static inline int pwc_restore_factory(struct pwc_device *pdev)
+int pwc_restore_factory(struct pwc_device *pdev)
 {
        char buf; /* dummy */
        return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0);
@@ -766,7 +745,7 @@ static inline int pwc_restore_factory(struct pwc_device *pdev)
   * 03: manual
   * 04: auto
   */
-static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
+int pwc_set_awb(struct pwc_device *pdev, int mode)
 {
        char buf;
        int ret;
@@ -786,7 +765,7 @@ static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
        return 0;
 }
 
-static inline int pwc_get_awb(struct pwc_device *pdev)
+int pwc_get_awb(struct pwc_device *pdev)
 {
        unsigned char buf;
        int ret;
@@ -798,7 +777,7 @@ static inline int pwc_get_awb(struct pwc_device *pdev)
        return buf;
 }
 
-static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
+int pwc_set_red_gain(struct pwc_device *pdev, int value)
 {
        unsigned char buf;
 
@@ -811,7 +790,7 @@ static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
        return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
 }
 
-static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value)
+int pwc_get_red_gain(struct pwc_device *pdev, int *value)
 {
        unsigned char buf;
        int ret;
@@ -824,7 +803,7 @@ static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value)
 }
 
 
-static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
+int pwc_set_blue_gain(struct pwc_device *pdev, int value)
 {
        unsigned char buf;
 
@@ -837,7 +816,7 @@ static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
        return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
 }
 
-static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
+int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
 {
        unsigned char buf;
        int ret;
@@ -854,7 +833,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
    internal red/blue gains, which may be different from the manual
    gains set or read above.
  */
-static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value)
+static int pwc_read_red_gain(struct pwc_device *pdev, int *value)
 {
        unsigned char buf;
        int ret;
@@ -866,7 +845,7 @@ static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value)
        return 0;
 }
 
-static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
+static int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
 {
        unsigned char buf;
        int ret;
@@ -879,7 +858,7 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
 }
 
 
-static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
+static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
 {
        unsigned char buf;
 
@@ -888,7 +867,7 @@ static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
        return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
 }
 
-static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
+static int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
 {
        unsigned char buf;
        int ret;
@@ -901,7 +880,7 @@ static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
 }
 
 
-static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
+static int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
 {
        unsigned char buf;
 
@@ -910,7 +889,7 @@ static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
        return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
 }
 
-static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
+static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
 {
        unsigned char buf;
        int ret;
@@ -965,7 +944,7 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
        return 0;
 }
 
-static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
+int pwc_set_contour(struct pwc_device *pdev, int contour)
 {
        unsigned char buf;
        int ret;
@@ -990,7 +969,7 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
        return 0;
 }
 
-static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
+int pwc_get_contour(struct pwc_device *pdev, int *contour)
 {
        unsigned char buf;
        int ret;
@@ -1012,7 +991,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
 }
 
 
-static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
+int pwc_set_backlight(struct pwc_device *pdev, int backlight)
 {
        unsigned char buf;
 
@@ -1023,7 +1002,7 @@ static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
        return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
 }
 
-static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
+int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
 {
        int ret;
        unsigned char buf;
@@ -1031,12 +1010,35 @@ static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
        ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
        if (ret < 0)
                return ret;
-       *backlight = buf;
+       *backlight = !!buf;
        return 0;
 }
 
+int pwc_set_colour_mode(struct pwc_device *pdev, int colour)
+{
+       unsigned char buf;
 
-static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
+       if (colour)
+               buf = 0xff;
+       else
+               buf = 0x0;
+       return SendControlMsg(SET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1);
+}
+
+int pwc_get_colour_mode(struct pwc_device *pdev, int *colour)
+{
+       int ret;
+       unsigned char buf;
+
+       ret = RecvControlMsg(GET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1);
+       if (ret < 0)
+               return ret;
+       *colour = !!buf;
+       return 0;
+}
+
+
+int pwc_set_flicker(struct pwc_device *pdev, int flicker)
 {
        unsigned char buf;
 
@@ -1047,7 +1049,7 @@ static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
        return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
 }
 
-static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
+int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
 {
        int ret;
        unsigned char buf;
@@ -1055,12 +1057,11 @@ static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
        ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
        if (ret < 0)
                return ret;
-       *flicker = buf;
+       *flicker = !!buf;
        return 0;
 }
 
-
-static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
+int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
 {
        unsigned char buf;
 
@@ -1072,7 +1073,7 @@ static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
        return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
 }
 
-static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
+int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
 {
        int ret;
        unsigned char buf;
@@ -1084,7 +1085,7 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
        return 0;
 }
 
-static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
+static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
 {
        unsigned char buf;
 
@@ -1092,7 +1093,18 @@ static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
        return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
 }
 
-static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
+int pwc_mpt_reset(struct pwc_device *pdev, int flags)
+{
+       int ret;
+       ret = _pwc_mpt_reset(pdev, flags);
+       if (ret >= 0) {
+               pdev->pan_angle = 0;
+               pdev->tilt_angle = 0;
+       }
+       return ret;
+}
+
+static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
 {
        unsigned char buf[4];
 
@@ -1110,7 +1122,35 @@ static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
        return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);
 }
 
-static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
+int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
+{
+       int ret;
+
+       /* check absolute ranges */
+       if (pan  < pdev->angle_range.pan_min  ||
+           pan  > pdev->angle_range.pan_max  ||
+           tilt < pdev->angle_range.tilt_min ||
+           tilt > pdev->angle_range.tilt_max)
+               return -ERANGE;
+
+       /* go to relative range, check again */
+       pan  -= pdev->pan_angle;
+       tilt -= pdev->tilt_angle;
+       /* angles are specified in degrees * 100, thus the limit = 36000 */
+       if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000)
+               return -ERANGE;
+
+       ret = _pwc_mpt_set_angle(pdev, pan, tilt);
+       if (ret >= 0) {
+               pdev->pan_angle  += pan;
+               pdev->tilt_angle += tilt;
+       }
+       if (ret == -EPIPE) /* stall -> out of range */
+               ret = -ERANGE;
+       return ret;
+}
+
+static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
 {
        int ret;
        unsigned char buf[5];
@@ -1151,6 +1191,26 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
  /* End of Add-Ons                                    */
  /* ************************************************* */
 
+/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
+   ioctl() calls. With 2.4, you have to do tedious copy_from_user()
+   and copy_to_user() calls. With these macros we circumvent this,
+   and let me maintain only one source file. The functionality is
+   exactly the same otherwise.
+ */
+
+
+/* define local variable for arg */
+#define ARG_DEF(ARG_type, ARG_name)\
+       ARG_type *ARG_name = arg;
+/* copy arg to local variable */
+#define ARG_IN(ARG_name) /* nothing */
+/* argument itself (referenced) */
+#define ARGR(ARG_name) (*ARG_name)
+/* argument address */
+#define ARGA(ARG_name) ARG_name
+/* copy local variable to arg */
+#define ARG_OUT(ARG_name) /* nothing */
+
 
 int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 {
@@ -1180,206 +1240,243 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 
        case VIDIOCPWCSCQUAL:
        {
-               int *qual = arg;
+               ARG_DEF(int, qual)
 
-               if (*qual < 0 || *qual > 3)
+               ARG_IN(qual)
+               if (ARGR(qual) < 0 || ARGR(qual) > 3)
                        ret = -EINVAL;
                else
-                       ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot);
+                       ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
                if (ret >= 0)
-                       pdev->vcompression = *qual;
+                       pdev->vcompression = ARGR(qual);
                break;
        }
 
        case VIDIOCPWCGCQUAL:
        {
-               int *qual = arg;
-               *qual = pdev->vcompression;
+               ARG_DEF(int, qual)
+
+               ARGR(qual) = pdev->vcompression;
+               ARG_OUT(qual)
                break;
        }
 
        case VIDIOCPWCPROBE:
        {
-               struct pwc_probe *probe = arg;
-               strcpy(probe->name, pdev->vdev->name);
-               probe->type = pdev->type;
+               ARG_DEF(struct pwc_probe, probe)
+
+               strcpy(ARGR(probe).name, pdev->vdev->name);
+               ARGR(probe).type = pdev->type;
+               ARG_OUT(probe)
                break;
        }
 
        case VIDIOCPWCGSERIAL:
        {
-               struct pwc_serial *serial = arg;
-               strcpy(serial->serial, pdev->serial);
+               ARG_DEF(struct pwc_serial, serial)
+
+               strcpy(ARGR(serial).serial, pdev->serial);
+               ARG_OUT(serial)
                break;
        }
 
        case VIDIOCPWCSAGC:
        {
-               int *agc = arg;
-               if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc))
+               ARG_DEF(int, agc)
+
+               ARG_IN(agc)
+               if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
                        ret = -EINVAL;
                break;
        }
 
        case VIDIOCPWCGAGC:
        {
-               int *agc = arg;
+               ARG_DEF(int, agc)
 
-               if (pwc_get_agc(pdev, agc))
+               if (pwc_get_agc(pdev, ARGA(agc)))
                        ret = -EINVAL;
+               ARG_OUT(agc)
                break;
        }
 
        case VIDIOCPWCSSHUTTER:
        {
-               int *shutter_speed = arg;
-               ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
+               ARG_DEF(int, shutter_speed)
+
+               ARG_IN(shutter_speed)
+               ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
                break;
        }
 
        case VIDIOCPWCSAWB:
        {
-               struct pwc_whitebalance *wb = arg;
+               ARG_DEF(struct pwc_whitebalance, wb)
 
-               ret = pwc_set_awb(pdev, wb->mode);
-               if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
-                       pwc_set_red_gain(pdev, wb->manual_red);
-                       pwc_set_blue_gain(pdev, wb->manual_blue);
+               ARG_IN(wb)
+               ret = pwc_set_awb(pdev, ARGR(wb).mode);
+               if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {
+                       pwc_set_red_gain(pdev, ARGR(wb).manual_red);
+                       pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
                }
                break;
        }
 
        case VIDIOCPWCGAWB:
        {
-               struct pwc_whitebalance *wb = arg;
+               ARG_DEF(struct pwc_whitebalance, wb)
 
-               memset(wb, 0, sizeof(struct pwc_whitebalance));
-               wb->mode = pwc_get_awb(pdev);
-               if (wb->mode < 0)
+               memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));
+               ARGR(wb).mode = pwc_get_awb(pdev);
+               if (ARGR(wb).mode < 0)
                        ret = -EINVAL;
                else {
-                       if (wb->mode == PWC_WB_MANUAL) {
-                               ret = pwc_get_red_gain(pdev, &wb->manual_red);
+                       if (ARGR(wb).mode == PWC_WB_MANUAL) {
+                               ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
                                if (ret < 0)
                                        break;
-                               ret = pwc_get_blue_gain(pdev, &wb->manual_blue);
+                               ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
                                if (ret < 0)
                                        break;
                        }
-                       if (wb->mode == PWC_WB_AUTO) {
-                               ret = pwc_read_red_gain(pdev, &wb->read_red);
+                       if (ARGR(wb).mode == PWC_WB_AUTO) {
+                               ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
                                if (ret < 0)
                                        break;
-                               ret = pwc_read_blue_gain(pdev, &wb->read_blue);
+                               ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
                                if (ret < 0)
                                        break;
                        }
                }
+               ARG_OUT(wb)
                break;
        }
 
        case VIDIOCPWCSAWBSPEED:
        {
-               struct pwc_wb_speed *wbs = arg;
+               ARG_DEF(struct pwc_wb_speed, wbs)
 
-               if (wbs->control_speed > 0) {
-                       ret = pwc_set_wb_speed(pdev, wbs->control_speed);
+               if (ARGR(wbs).control_speed > 0) {
+                       ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
                }
-               if (wbs->control_delay > 0) {
-                       ret = pwc_set_wb_delay(pdev, wbs->control_delay);
+               if (ARGR(wbs).control_delay > 0) {
+                       ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
                }
                break;
        }
 
        case VIDIOCPWCGAWBSPEED:
        {
-               struct pwc_wb_speed *wbs = arg;
+               ARG_DEF(struct pwc_wb_speed, wbs)
 
-               ret = pwc_get_wb_speed(pdev, &wbs->control_speed);
+               ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
                if (ret < 0)
                        break;
-               ret = pwc_get_wb_delay(pdev, &wbs->control_delay);
+               ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
                if (ret < 0)
                        break;
+               ARG_OUT(wbs)
                break;
        }
 
        case VIDIOCPWCSLED:
        {
-               struct pwc_leds *leds = arg;
-               ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
-               break;
+               ARG_DEF(struct pwc_leds, leds)
+
+               ARG_IN(leds)
+               ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
+               break;
        }
 
 
        case VIDIOCPWCGLED:
        {
-               struct pwc_leds *leds = arg;
-               ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off);
+               ARG_DEF(struct pwc_leds, leds)
+
+               ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
+               ARG_OUT(leds)
                break;
        }
 
        case VIDIOCPWCSCONTOUR:
        {
-               int *contour = arg;
-               ret = pwc_set_contour(pdev, *contour);
+               ARG_DEF(int, contour)
+
+               ARG_IN(contour)
+               ret = pwc_set_contour(pdev, ARGR(contour));
                break;
        }
 
        case VIDIOCPWCGCONTOUR:
        {
-               int *contour = arg;
-               ret = pwc_get_contour(pdev, contour);
+               ARG_DEF(int, contour)
+
+               ret = pwc_get_contour(pdev, ARGA(contour));
+               ARG_OUT(contour)
                break;
        }
 
        case VIDIOCPWCSBACKLIGHT:
        {
-               int *backlight = arg;
-               ret = pwc_set_backlight(pdev, *backlight);
+               ARG_DEF(int, backlight)
+
+               ARG_IN(backlight)
+               ret = pwc_set_backlight(pdev, ARGR(backlight));
                break;
        }
 
        case VIDIOCPWCGBACKLIGHT:
        {
-               int *backlight = arg;
-               ret = pwc_get_backlight(pdev, backlight);
+               ARG_DEF(int, backlight)
+
+               ret = pwc_get_backlight(pdev, ARGA(backlight));
+               ARG_OUT(backlight)
                break;
        }
 
        case VIDIOCPWCSFLICKER:
        {
-               int *flicker = arg;
-               ret = pwc_set_flicker(pdev, *flicker);
+               ARG_DEF(int, flicker)
+
+               ARG_IN(flicker)
+               ret = pwc_set_flicker(pdev, ARGR(flicker));
                break;
        }
 
        case VIDIOCPWCGFLICKER:
        {
-               int *flicker = arg;
-               ret = pwc_get_flicker(pdev, flicker);
+               ARG_DEF(int, flicker)
+
+               ret = pwc_get_flicker(pdev, ARGA(flicker));
+               ARG_OUT(flicker)
                break;
        }
 
        case VIDIOCPWCSDYNNOISE:
        {
-               int *dynnoise = arg;
-               ret = pwc_set_dynamic_noise(pdev, *dynnoise);
+               ARG_DEF(int, dynnoise)
+
+               ARG_IN(dynnoise)
+               ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
                break;
        }
 
        case VIDIOCPWCGDYNNOISE:
        {
-               int *dynnoise = arg;
-               ret = pwc_get_dynamic_noise(pdev, dynnoise);
+               ARG_DEF(int, dynnoise)
+
+               ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
+               ARG_OUT(dynnoise);
                break;
        }
 
        case VIDIOCPWCGREALSIZE:
        {
-               struct pwc_imagesize *size = arg;
-               size->width = pdev->image.x;
-               size->height = pdev->image.y;
+               ARG_DEF(struct pwc_imagesize, size)
+
+               ARGR(size).width = pdev->image.x;
+               ARGR(size).height = pdev->image.y;
+               ARG_OUT(size)
                break;
        }
 
@@ -1387,14 +1484,10 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
        {
                if (pdev->features & FEATURE_MOTOR_PANTILT)
                {
-                       int *flags = arg;
+                       ARG_DEF(int, flags)
 
-                       ret = pwc_mpt_reset(pdev, *flags);
-                       if (ret >= 0)
-                       {
-                               pdev->pan_angle = 0;
-                               pdev->tilt_angle = 0;
-                       }
+                       ARG_IN(flags)
+                       ret = pwc_mpt_reset(pdev, ARGR(flags));
                }
                else
                {
@@ -1407,8 +1500,10 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
        {
                if (pdev->features & FEATURE_MOTOR_PANTILT)
                {
-                       struct pwc_mpt_range *range = arg;
-                       *range = pdev->angle_range;
+                       ARG_DEF(struct pwc_mpt_range, range)
+
+                       ARGR(range) = pdev->angle_range;
+                       ARG_OUT(range)
                }
                else
                {
@@ -1423,48 +1518,23 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 
                if (pdev->features & FEATURE_MOTOR_PANTILT)
                {
-                       struct pwc_mpt_angles *angles = arg;
+                       ARG_DEF(struct pwc_mpt_angles, angles)
+
+                       ARG_IN(angles)
                        /* The camera can only set relative angles, so
                           do some calculations when getting an absolute angle .
                         */
-                       if (angles->absolute)
+                       if (ARGR(angles).absolute)
                        {
-                               new_pan  = angles->pan;
-                               new_tilt = angles->tilt;
+                               new_pan  = ARGR(angles).pan;
+                               new_tilt = ARGR(angles).tilt;
                        }
                        else
                        {
-                               new_pan  = pdev->pan_angle  + angles->pan;
-                               new_tilt = pdev->tilt_angle + angles->tilt;
-                       }
-                       /* check absolute ranges */
-                       if (new_pan  < pdev->angle_range.pan_min  ||
-                           new_pan  > pdev->angle_range.pan_max  ||
-                           new_tilt < pdev->angle_range.tilt_min ||
-                           new_tilt > pdev->angle_range.tilt_max)
-                       {
-                               ret = -ERANGE;
-                       }
-                       else
-                       {
-                               /* go to relative range, check again */
-                               new_pan  -= pdev->pan_angle;
-                               new_tilt -= pdev->tilt_angle;
-                               /* angles are specified in degrees * 100, thus the limit = 36000 */
-                               if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000)
-                                       ret = -ERANGE;
-                       }
-                       if (ret == 0) /* no errors so far */
-                       {
-                               ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
-                               if (ret >= 0)
-                               {
-                                       pdev->pan_angle  += new_pan;
-                                       pdev->tilt_angle += new_tilt;
-                               }
-                               if (ret == -EPIPE) /* stall -> out of range */
-                                       ret = -ERANGE;
+                               new_pan  = pdev->pan_angle  + ARGR(angles).pan;
+                               new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
                        }
+                       ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
                }
                else
                {
@@ -1478,11 +1548,12 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 
                if (pdev->features & FEATURE_MOTOR_PANTILT)
                {
-                       struct pwc_mpt_angles *angles = arg;
+                       ARG_DEF(struct pwc_mpt_angles, angles)
 
-                       angles->absolute = 1;
-                       angles->pan  = pdev->pan_angle;
-                       angles->tilt = pdev->tilt_angle;
+                       ARGR(angles).absolute = 1;
+                       ARGR(angles).pan  = pdev->pan_angle;
+                       ARGR(angles).tilt = pdev->tilt_angle;
+                       ARG_OUT(angles)
                }
                else
                {
@@ -1495,8 +1566,10 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
        {
                if (pdev->features & FEATURE_MOTOR_PANTILT)
                {
-                       struct pwc_mpt_status *status = arg;
-                       ret = pwc_mpt_get_status(pdev, status);
+                       ARG_DEF(struct pwc_mpt_status, status)
+
+                       ret = pwc_mpt_get_status(pdev, ARGA(status));
+                       ARG_OUT(status)
                }
                else
                {
@@ -1507,22 +1580,24 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 
        case VIDIOCPWCGVIDCMD:
        {
-               struct pwc_video_command *cmd = arg;
-
-               cmd->type = pdev->type;
-               cmd->release = pdev->release;
-               cmd->command_len = pdev->cmd_len;
-               memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len);
-               cmd->bandlength = pdev->vbandlength;
-               cmd->frame_size = pdev->frame_size;
+               ARG_DEF(struct pwc_video_command, cmd);
+
+               ARGR(cmd).type = pdev->type;
+               ARGR(cmd).release = pdev->release;
+               ARGR(cmd).command_len = pdev->cmd_len;
+               memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
+               ARGR(cmd).bandlength = pdev->vbandlength;
+               ARGR(cmd).frame_size = pdev->frame_size;
+               ARG_OUT(cmd)
                break;
        }
        /*
        case VIDIOCPWCGVIDTABLE:
        {
-               struct pwc_table_init_buffer *table = arg;
-               table->len = pdev->cmd_len;
-               memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size);
+               ARG_DEF(struct pwc_table_init_buffer, table);
+               ARGR(table).len = pdev->cmd_len;
+               memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);
+               ARG_OUT(table)
                break;
        }
        */
@@ -1538,4 +1613,4 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 }
 
 
-
+/* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/video/pwc/pwc-dec1.c
new file mode 100644 (file)
index 0000000..c29593f
--- /dev/null
@@ -0,0 +1,50 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 1
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+
+#include "pwc-dec1.h"
+
+
+void pwc_dec1_init(int type, int release, void *buffer, void *table)
+{
+
+}
+
+void pwc_dec1_exit(void)
+{
+
+
+
+}
+
+int pwc_dec1_alloc(struct pwc_device *pwc)
+{
+       pwc->decompress_data = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
+       if (pwc->decompress_data == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h
new file mode 100644 (file)
index 0000000..8b62ddc
--- /dev/null
@@ -0,0 +1,43 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+
+#ifndef PWC_DEC1_H
+#define PWC_DEC1_H
+
+#include "pwc.h"
+
+struct pwc_dec1_private
+{
+       int version;
+
+};
+
+int  pwc_dec1_alloc(struct pwc_device *pwc);
+void pwc_dec1_init(int type, int release, void *buffer, void *private_data);
+void pwc_dec1_exit(void);
+
+#endif
+
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c
new file mode 100644 (file)
index 0000000..9e2d91f
--- /dev/null
@@ -0,0 +1,941 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 2 et 3
+   (C) 2004-2006  Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#include "pwc-timon.h"
+#include "pwc-kiara.h"
+#include "pwc-dec23.h"
+#include <media/pwc-ioctl.h>
+
+#include <linux/string.h>
+
+/*
+ * USE_LOOKUP_TABLE_TO_CLAMP
+ *   0: use a C version of this tests:  {  a<0?0:(a>255?255:a) }
+ *   1: use a faster lookup table for cpu with a big cache (intel)
+ */
+#define USE_LOOKUP_TABLE_TO_CLAMP      1
+/*
+ * UNROLL_LOOP_FOR_COPYING_BLOCK
+ *   0: use a loop for a smaller code (but little slower)
+ *   1: when unrolling the loop, gcc produces some faster code (perhaps only
+ *   valid for intel processor class). Activating this option, automaticaly
+ *   activate USE_LOOKUP_TABLE_TO_CLAMP
+ */
+#define UNROLL_LOOP_FOR_COPY           1
+#if UNROLL_LOOP_FOR_COPY
+# undef USE_LOOKUP_TABLE_TO_CLAMP
+# define USE_LOOKUP_TABLE_TO_CLAMP 1
+#endif
+
+/*
+ * ENABLE_BAYER_DECODER
+ *   0: bayer decoder is not build (save some space)
+ *   1: bayer decoder is build and can be used
+ */
+#define ENABLE_BAYER_DECODER 0
+
+static void build_subblock_pattern(struct pwc_dec23_private *pdec)
+{
+       static const unsigned int initial_values[12] = {
+               -0x526500, -0x221200, 0x221200, 0x526500,
+                          -0x3de200, 0x3de200,
+               -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,
+                          -0x12c200, 0x12c200
+
+       };
+       static const unsigned int values_derivated[12] = {
+               0xa4ca, 0x4424, -0x4424, -0xa4ca,
+                       0x7bc4, -0x7bc4,
+               0xdb69, 0x5aba, -0x5aba, -0xdb69,
+                       0x2584, -0x2584
+       };
+       unsigned int temp_values[12];
+       int i, j;
+
+       memcpy(temp_values, initial_values, sizeof(initial_values));
+       for (i = 0; i < 256; i++) {
+               for (j = 0; j < 12; j++) {
+                       pdec->table_subblock[i][j] = temp_values[j];
+                       temp_values[j] += values_derivated[j];
+               }
+       }
+}
+
+static void build_bit_powermask_table(struct pwc_dec23_private *pdec)
+{
+       unsigned char *p;
+       unsigned int bit, byte, mask, val;
+       unsigned int bitpower = 1;
+
+       for (bit = 0; bit < 8; bit++) {
+               mask = bitpower - 1;
+               p = pdec->table_bitpowermask[bit];
+               for (byte = 0; byte < 256; byte++) {
+                       val = (byte & mask);
+                       if (byte & bitpower)
+                               val = -val;
+                       *p++ = val;
+               }
+               bitpower<<=1;
+       }
+}
+
+
+static void build_table_color(const unsigned int romtable[16][8],
+                             unsigned char p0004[16][1024],
+                             unsigned char p8004[16][256])
+{
+       int compression_mode, j, k, bit, pw;
+       unsigned char *p0, *p8;
+       const unsigned int *r;
+
+       /* We have 16 compressions tables */
+       for (compression_mode = 0; compression_mode < 16; compression_mode++) {
+               p0 = p0004[compression_mode];
+               p8 = p8004[compression_mode];
+               r  = romtable[compression_mode];
+
+               for (j = 0; j < 8; j++, r++, p0 += 128) {
+
+                       for (k = 0; k < 16; k++) {
+                               if (k == 0)
+                                       bit = 1;
+                               else if (k >= 1 && k < 3)
+                                       bit = (r[0] >> 15) & 7;
+                               else if (k >= 3 && k < 6)
+                                       bit = (r[0] >> 12) & 7;
+                               else if (k >= 6 && k < 10)
+                                       bit = (r[0] >> 9) & 7;
+                               else if (k >= 10 && k < 13)
+                                       bit = (r[0] >> 6) & 7;
+                               else if (k >= 13 && k < 15)
+                                       bit = (r[0] >> 3) & 7;
+                               else
+                                       bit = (r[0]) & 7;
+                               if (k == 0)
+                                       *p8++ = 8;
+                               else
+                                       *p8++ = j - bit;
+                               *p8++ = bit;
+
+                               pw = 1 << bit;
+                               p0[k + 0x00] = (1 * pw) + 0x80;
+                               p0[k + 0x10] = (2 * pw) + 0x80;
+                               p0[k + 0x20] = (3 * pw) + 0x80;
+                               p0[k + 0x30] = (4 * pw) + 0x80;
+                               p0[k + 0x40] = (-1 * pw) + 0x80;
+                               p0[k + 0x50] = (-2 * pw) + 0x80;
+                               p0[k + 0x60] = (-3 * pw) + 0x80;
+                               p0[k + 0x70] = (-4 * pw) + 0x80;
+                       }       /* end of for (k=0; k<16; k++, p8++) */
+               }       /* end of for (j=0; j<8; j++ , table++) */
+       } /* end of foreach compression_mode */
+}
+
+/*
+ *
+ */
+static void fill_table_dc00_d800(struct pwc_dec23_private *pdec)
+{
+#define SCALEBITS 15
+#define ONE_HALF  (1UL << (SCALEBITS - 1))
+       int i;
+       unsigned int offset1 = ONE_HALF;
+       unsigned int offset2 = 0x0000;
+
+       for (i=0; i<256; i++) {
+               pdec->table_dc00[i] = offset1 & ~(ONE_HALF);
+               pdec->table_d800[i] = offset2;
+
+               offset1 += 0x7bc4;
+               offset2 += 0x7bc4;
+       }
+}
+
+/*
+ * To decode the stream:
+ *   if look_bits(2) == 0:     # op == 2 in the lookup table
+ *      skip_bits(2)
+ *      end of the stream
+ *   elif look_bits(3) == 7:   # op == 1 in the lookup table
+ *      skip_bits(3)
+ *      yyyy = get_bits(4)
+ *      xxxx = get_bits(8)
+ *   else:                     # op == 0 in the lookup table
+ *      skip_bits(x)
+ *
+ * For speedup processing, we build a lookup table and we takes the first 6 bits.
+ *
+ * struct {
+ *   unsigned char op;     // operation to execute
+ *   unsigned char bits;    // bits use to perform operation
+ *   unsigned char offset1; // offset to add to access in the table_0004 % 16
+ *   unsigned char offset2; // offset to add to access in the table_0004
+ * }
+ *
+ * How to build this table ?
+ *   op == 2 when (i%4)==0
+ *   op == 1 when (i%8)==7
+ *   op == 0 otherwise
+ *
+ */
+static const unsigned char hash_table_ops[64*4] = {
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x01, 0x30,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x20,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x00,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x02, 0x10,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x60,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x40,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x40,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x01, 0x70,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x20,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x00,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x02, 0x50,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x60,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x40,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x40,
+       0x01, 0x00, 0x00, 0x00
+};
+
+/*
+ *
+ */
+static const unsigned int MulIdx[16][16] = {
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+       {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},
+       {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},
+       {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},
+       {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},
+       {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},
+       {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},
+       {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},
+       {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},
+       {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},
+       {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},
+       {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},
+       {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},
+       {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},
+       {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},
+       {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}
+};
+
+#if USE_LOOKUP_TABLE_TO_CLAMP
+#define MAX_OUTER_CROP_VALUE   (512)
+static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
+#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
+#else
+#define CLAMP(x) ((x)>255?255:((x)<0?0:x))
+#endif
+
+
+/* If the type or the command change, we rebuild the lookup table */
+int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
+{
+       int flags, version, shift, i;
+       struct pwc_dec23_private *pdec;
+
+       if (pwc->decompress_data == NULL) {
+               pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
+               if (pdec == NULL)
+                       return -ENOMEM;
+               pwc->decompress_data = pdec;
+       }
+       pdec = pwc->decompress_data;
+
+       if (DEVICE_USE_CODEC3(type)) {
+               flags = cmd[2] & 0x18;
+               if (flags == 8)
+                       pdec->nbits = 7;        /* More bits, mean more bits to encode the stream, but better quality */
+               else if (flags == 0x10)
+                       pdec->nbits = 8;
+               else
+                       pdec->nbits = 6;
+
+               version = cmd[2] >> 5;
+               build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
+               build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
+
+       } else {
+
+               flags = cmd[2] & 6;
+               if (flags == 2)
+                       pdec->nbits = 7;
+               else if (flags == 4)
+                       pdec->nbits = 8;
+               else
+                       pdec->nbits = 6;
+
+               version = cmd[2] >> 3;
+               build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
+               build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
+       }
+
+       /* Informations can be coded on a variable number of bits but never less than 8 */
+       shift = 8 - pdec->nbits;
+       pdec->scalebits = SCALEBITS - shift;
+       pdec->nbitsmask = 0xFF >> shift;
+
+       fill_table_dc00_d800(pdec);
+       build_subblock_pattern(pdec);
+       build_bit_powermask_table(pdec);
+
+#if USE_LOOKUP_TABLE_TO_CLAMP
+       /* Build the static table to clamp value [0-255] */
+       for (i=0;i<MAX_OUTER_CROP_VALUE;i++)
+               pwc_crop_table[i] = 0;
+       for (i=0; i<256; i++)
+               pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;
+       for (i=0; i<MAX_OUTER_CROP_VALUE; i++)
+               pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
+#endif
+
+       return 0;
+}
+
+/*
+ * Copy the 4x4 image block to Y plane buffer
+ */
+static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+       const int *c = src;
+       unsigned char *d = dst;
+
+       *d++ = cm[c[0] >> scalebits];
+       *d++ = cm[c[1] >> scalebits];
+       *d++ = cm[c[2] >> scalebits];
+       *d++ = cm[c[3] >> scalebits];
+
+       d = dst + bytes_per_line;
+       *d++ = cm[c[4] >> scalebits];
+       *d++ = cm[c[5] >> scalebits];
+       *d++ = cm[c[6] >> scalebits];
+       *d++ = cm[c[7] >> scalebits];
+
+       d = dst + bytes_per_line*2;
+       *d++ = cm[c[8] >> scalebits];
+       *d++ = cm[c[9] >> scalebits];
+       *d++ = cm[c[10] >> scalebits];
+       *d++ = cm[c[11] >> scalebits];
+
+       d = dst + bytes_per_line*3;
+       *d++ = cm[c[12] >> scalebits];
+       *d++ = cm[c[13] >> scalebits];
+       *d++ = cm[c[14] >> scalebits];
+       *d++ = cm[c[15] >> scalebits];
+#else
+       int i;
+       const int *c = src;
+       unsigned char *d = dst;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line*2;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line*3;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+#endif
+}
+
+/*
+ * Copy the 4x4 image block to a CrCb plane buffer
+ *
+ */
+static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+       /* Unroll all loops */
+       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+       const int *c = src;
+       unsigned char *d = dst;
+
+       *d++ = cm[c[0] >> scalebits];
+       *d++ = cm[c[4] >> scalebits];
+       *d++ = cm[c[1] >> scalebits];
+       *d++ = cm[c[5] >> scalebits];
+       *d++ = cm[c[2] >> scalebits];
+       *d++ = cm[c[6] >> scalebits];
+       *d++ = cm[c[3] >> scalebits];
+       *d++ = cm[c[7] >> scalebits];
+
+       d = dst + bytes_per_line;
+       *d++ = cm[c[12] >> scalebits];
+       *d++ = cm[c[8] >> scalebits];
+       *d++ = cm[c[13] >> scalebits];
+       *d++ = cm[c[9] >> scalebits];
+       *d++ = cm[c[14] >> scalebits];
+       *d++ = cm[c[10] >> scalebits];
+       *d++ = cm[c[15] >> scalebits];
+       *d++ = cm[c[11] >> scalebits];
+#else
+       int i;
+       const int *c1 = src;
+       const int *c2 = src + 4;
+       unsigned char *d = dst;
+
+       for (i = 0; i < 4; i++, c1++, c2++) {
+               *d++ = CLAMP((*c1) >> scalebits);
+               *d++ = CLAMP((*c2) >> scalebits);
+       }
+       c1 = src + 12;
+       d = dst + bytes_per_line;
+       for (i = 0; i < 4; i++, c1++, c2++) {
+               *d++ = CLAMP((*c1) >> scalebits);
+               *d++ = CLAMP((*c2) >> scalebits);
+       }
+#endif
+}
+
+#if ENABLE_BAYER_DECODER
+/*
+ * Format: 8x2 pixels
+ *   . G . G . G . G . G . G . G
+ *   . . . . . . . . . . . . . .
+ *   . G . G . G . G . G . G . G
+ *   . . . . . . . . . . . . . .
+ *   or
+ *   . . . . . . . . . . . . . .
+ *   G . G . G . G . G . G . G .
+ *   . . . . . . . . . . . . . .
+ *   G . G . G . G . G . G . G .
+*/
+static void copy_image_block_Green(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+       /* Unroll all loops */
+       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+       unsigned char *d = dst;
+       const int *c = src;
+
+       d[0] = cm[c[0] >> scalebits];
+       d[2] = cm[c[1] >> scalebits];
+       d[4] = cm[c[2] >> scalebits];
+       d[6] = cm[c[3] >> scalebits];
+       d[8] = cm[c[4] >> scalebits];
+       d[10] = cm[c[5] >> scalebits];
+       d[12] = cm[c[6] >> scalebits];
+       d[14] = cm[c[7] >> scalebits];
+
+       d = dst + bytes_per_line;
+       d[0] = cm[c[8] >> scalebits];
+       d[2] = cm[c[9] >> scalebits];
+       d[4] = cm[c[10] >> scalebits];
+       d[6] = cm[c[11] >> scalebits];
+       d[8] = cm[c[12] >> scalebits];
+       d[10] = cm[c[13] >> scalebits];
+       d[12] = cm[c[14] >> scalebits];
+       d[14] = cm[c[15] >> scalebits];
+#else
+       int i;
+       unsigned char *d;
+       const int *c = src;
+
+       d = dst;
+       for (i = 0; i < 8; i++, c++)
+               d[i*2] = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line;
+       for (i = 0; i < 8; i++, c++)
+               d[i*2] = CLAMP((*c) >> scalebits);
+#endif
+}
+#endif
+
+#if ENABLE_BAYER_DECODER
+/*
+ * Format: 4x4 pixels
+ *   R . R . R . R
+ *   . B . B . B .
+ *   R . R . R . R
+ *   . B . B . B .
+ */
+static void copy_image_block_RedBlue(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+       /* Unroll all loops */
+       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+       unsigned char *d = dst;
+       const int *c = src;
+
+       d[0] = cm[c[0] >> scalebits];
+       d[2] = cm[c[1] >> scalebits];
+       d[4] = cm[c[2] >> scalebits];
+       d[6] = cm[c[3] >> scalebits];
+
+       d = dst + bytes_per_line;
+       d[1] = cm[c[4] >> scalebits];
+       d[3] = cm[c[5] >> scalebits];
+       d[5] = cm[c[6] >> scalebits];
+       d[7] = cm[c[7] >> scalebits];
+
+       d = dst + bytes_per_line*2;
+       d[0] = cm[c[8] >> scalebits];
+       d[2] = cm[c[9] >> scalebits];
+       d[4] = cm[c[10] >> scalebits];
+       d[6] = cm[c[11] >> scalebits];
+
+       d = dst + bytes_per_line*3;
+       d[1] = cm[c[12] >> scalebits];
+       d[3] = cm[c[13] >> scalebits];
+       d[5] = cm[c[14] >> scalebits];
+       d[7] = cm[c[15] >> scalebits];
+#else
+       int i;
+       unsigned char *d;
+       const int *c = src;
+
+       d = dst;
+       for (i = 0; i < 4; i++, c++)
+               d[i*2] = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line;
+       for (i = 0; i < 4; i++, c++)
+               d[i*2+1] = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line*2;
+       for (i = 0; i < 4; i++, c++)
+               d[i*2] = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line*3;
+       for (i = 0; i < 4; i++, c++)
+               d[i*2+1] = CLAMP((*c) >> scalebits);
+#endif
+}
+#endif
+
+/*
+ * To manage the stream, we keep bits in a 32 bits register.
+ * fill_nbits(n): fill the reservoir with at least n bits
+ * skip_bits(n): discard n bits from the reservoir
+ * get_bits(n): fill the reservoir, returns the first n bits and discard the
+ *              bits from the reservoir.
+ * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
+ *                 contains at least n bits. bits returned is discarded.
+ */
+#define fill_nbits(pdec, nbits_wanted) do { \
+   while (pdec->nbits_in_reservoir<(nbits_wanted)) \
+    { \
+      pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
+      pdec->nbits_in_reservoir += 8; \
+    } \
+}  while(0);
+
+#define skip_nbits(pdec, nbits_to_skip) do { \
+   pdec->reservoir >>= (nbits_to_skip); \
+   pdec->nbits_in_reservoir -= (nbits_to_skip); \
+}  while(0);
+
+#define get_nbits(pdec, nbits_wanted, result) do { \
+   fill_nbits(pdec, nbits_wanted); \
+   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
+   skip_nbits(pdec, nbits_wanted); \
+}  while(0);
+
+#define __get_nbits(pdec, nbits_wanted, result) do { \
+   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
+   skip_nbits(pdec, nbits_wanted); \
+}  while(0);
+
+#define look_nbits(pdec, nbits_wanted) \
+   ((pdec->reservoir) & ((1U<<(nbits_wanted))-1))
+
+/*
+ * Decode a 4x4 pixel block
+ */
+static void decode_block(struct pwc_dec23_private *pdec,
+                        const unsigned char *ptable0004,
+                        const unsigned char *ptable8004)
+{
+       unsigned int primary_color;
+       unsigned int channel_v, offset1, op;
+       int i;
+
+       fill_nbits(pdec, 16);
+       __get_nbits(pdec, pdec->nbits, primary_color);
+
+       if (look_nbits(pdec,2) == 0) {
+               skip_nbits(pdec, 2);
+               /* Very simple, the color is the same for all pixels of the square */
+               for (i = 0; i < 16; i++)
+                       pdec->temp_colors[i] = pdec->table_dc00[primary_color];
+
+               return;
+       }
+
+       /* This block is encoded with small pattern */
+       for (i = 0; i < 16; i++)
+               pdec->temp_colors[i] = pdec->table_d800[primary_color];
+
+       __get_nbits(pdec, 3, channel_v);
+       channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2);
+
+       ptable0004 += (channel_v * 128);
+       ptable8004 += (channel_v * 32);
+
+       offset1 = 0;
+       do
+       {
+               unsigned int htable_idx, rows = 0;
+               const unsigned int *block;
+
+               /* [  zzzz y x x ]
+                *     xx == 00 :=> end of the block def, remove the two bits from the stream
+                *    yxx == 111
+                *    yxx == any other value
+                *
+                */
+               fill_nbits(pdec, 16);
+               htable_idx = look_nbits(pdec, 6);
+               op = hash_table_ops[htable_idx * 4];
+
+               if (op == 2) {
+                       skip_nbits(pdec, 2);
+
+               } else if (op == 1) {
+                       /* 15bits [ xxxx xxxx yyyy 111 ]
+                        * yyy => offset in the table8004
+                        * xxx => offset in the tabled004 (tree)
+                        */
+                       unsigned int mask, shift;
+                       unsigned int nbits, col1;
+                       unsigned int yyyy;
+
+                       skip_nbits(pdec, 3);
+                       /* offset1 += yyyy */
+                       __get_nbits(pdec, 4, yyyy);
+                       offset1 += 1 + yyyy;
+                       offset1 &= 0x0F;
+                       nbits = ptable8004[offset1 * 2];
+
+                       /* col1 = xxxx xxxx */
+                       __get_nbits(pdec, nbits+1, col1);
+
+                       /* Bit mask table */
+                       mask = pdec->table_bitpowermask[nbits][col1];
+                       shift = ptable8004[offset1 * 2 + 1];
+                       rows = ((mask << shift) + 0x80) & 0xFF;
+
+                       block = pdec->table_subblock[rows];
+                       for (i = 0; i < 16; i++)
+                               pdec->temp_colors[i] += block[MulIdx[offset1][i]];
+
+               } else {
+                       /* op == 0
+                        * offset1 is coded on 3 bits
+                        */
+                       unsigned int shift;
+
+                       offset1 += hash_table_ops [htable_idx * 4 + 2];
+                       offset1 &= 0x0F;
+
+                       rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]];
+                       block = pdec->table_subblock[rows];
+                       for (i = 0; i < 16; i++)
+                               pdec->temp_colors[i] += block[MulIdx[offset1][i]];
+
+                       shift = hash_table_ops[htable_idx * 4 + 1];
+                       skip_nbits(pdec, shift);
+               }
+
+       } while (op != 2);
+
+}
+
+static void DecompressBand23(struct pwc_dec23_private *pdec,
+                            const unsigned char *rawyuv,
+                            unsigned char *planar_y,
+                            unsigned char *planar_u,
+                            unsigned char *planar_v,
+                            unsigned int   compressed_image_width,
+                            unsigned int   real_image_width)
+{
+       int compression_index, nblocks;
+       const unsigned char *ptable0004;
+       const unsigned char *ptable8004;
+
+       pdec->reservoir = 0;
+       pdec->nbits_in_reservoir = 0;
+       pdec->stream = rawyuv + 1;      /* The first byte of the stream is skipped */
+
+       get_nbits(pdec, 4, compression_index);
+
+       /* pass 1: uncompress Y component */
+       nblocks = compressed_image_width / 4;
+
+       ptable0004 = pdec->table_0004_pass1[compression_index];
+       ptable8004 = pdec->table_8004_pass1[compression_index];
+
+       /* Each block decode a square of 4x4 */
+       while (nblocks) {
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);
+               planar_y += 4;
+               nblocks--;
+       }
+
+       /* pass 2: uncompress UV component */
+       nblocks = compressed_image_width / 8;
+
+       ptable0004 = pdec->table_0004_pass2[compression_index];
+       ptable8004 = pdec->table_8004_pass2[compression_index];
+
+       /* Each block decode a square of 4x4 */
+       while (nblocks) {
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits);
+
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits);
+
+               planar_v += 8;
+               planar_u += 8;
+               nblocks -= 2;
+       }
+
+}
+
+#if ENABLE_BAYER_DECODER
+/*
+ * Size need to be a multiple of 8 in width
+ *
+ * Return a block of four line encoded like this:
+ *
+ *   G R G R G R G R G R G R G R G R
+ *   B G B G B G B G B G B G B G B G
+ *   G R G R G R G R G R G R G R G R
+ *   B G B G B G B G B G B G B G B G
+ *
+ */
+static void DecompressBandBayer(struct pwc_dec23_private *pdec,
+                               const unsigned char *rawyuv,
+                               unsigned char *rgbbayer,
+                               unsigned int   compressed_image_width,
+                               unsigned int   real_image_width)
+{
+       int compression_index, nblocks;
+       const unsigned char *ptable0004;
+       const unsigned char *ptable8004;
+       unsigned char *dest;
+
+       pdec->reservoir = 0;
+       pdec->nbits_in_reservoir = 0;
+       pdec->stream = rawyuv + 1;      /* The first byte of the stream is skipped */
+
+       get_nbits(pdec, 4, compression_index);
+
+       /* pass 1: uncompress RB component */
+       nblocks = compressed_image_width / 4;
+
+       ptable0004 = pdec->table_0004_pass1[compression_index];
+       ptable8004 = pdec->table_8004_pass1[compression_index];
+       dest = rgbbayer;
+
+       /* Each block decode a square of 4x4 */
+       while (nblocks) {
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits);
+               dest += 8;
+               nblocks--;
+       }
+
+       /* pass 2: uncompress G component */
+       nblocks = compressed_image_width / 8;
+
+       ptable0004 = pdec->table_0004_pass2[compression_index];
+       ptable8004 = pdec->table_8004_pass2[compression_index];
+
+       /* Each block decode a square of 4x4 */
+       while (nblocks) {
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits);
+
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits);
+
+               rgbbayer += 16;
+               nblocks -= 2;
+       }
+}
+#endif
+
+
+/**
+ *
+ * Uncompress a pwc23 buffer.
+ *
+ * pwc.view: size of the image wanted
+ * pwc.image: size of the image returned by the camera
+ * pwc.offset: (x,y) to displayer image in the view
+ *
+ * src: raw data
+ * dst: image output
+ * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER
+ */
+void pwc_dec23_decompress(const struct pwc_device *pwc,
+                         const void *src,
+                         void *dst,
+                         int flags)
+{
+       int bandlines_left, stride, bytes_per_block;
+
+       bandlines_left = pwc->image.y / 4;
+       bytes_per_block = pwc->view.x * 4;
+
+       if (flags & PWCX_FLAG_BAYER) {
+#if ENABLE_BAYER_DECODER
+               /* RGB Bayer format */
+               unsigned char *rgbout;
+
+               stride = pwc->view.x * pwc->offset.y;
+               rgbout = dst + stride + pwc->offset.x;
+
+
+               while (bandlines_left--) {
+
+                       DecompressBandBayer(pwc->decompress_data,
+                                           src,
+                                           rgbout,
+                                           pwc->image.x, pwc->view.x);
+
+                       src += pwc->vbandlength;
+                       rgbout += bytes_per_block;
+
+               }
+#else
+               memset(dst, 0, pwc->view.x * pwc->view.y);
+#endif
+
+       } else {
+               /* YUV420P image format */
+               unsigned char *pout_planar_y;
+               unsigned char *pout_planar_u;
+               unsigned char *pout_planar_v;
+               unsigned int   plane_size;
+
+               plane_size = pwc->view.x * pwc->view.y;
+
+               /* offset in Y plane */
+               stride = pwc->view.x * pwc->offset.y;
+               pout_planar_y = dst + stride + pwc->offset.x;
+
+               /* offsets in U/V planes */
+               stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2;
+               pout_planar_u = dst + plane_size + stride;
+               pout_planar_v = dst + plane_size + plane_size / 4 + stride;
+
+               while (bandlines_left--) {
+
+                       DecompressBand23(pwc->decompress_data,
+                                        src,
+                                        pout_planar_y, pout_planar_u, pout_planar_v,
+                                        pwc->image.x, pwc->view.x);
+                       src += pwc->vbandlength;
+                       pout_planar_y += bytes_per_block;
+                       pout_planar_u += pwc->view.x;
+                       pout_planar_v += pwc->view.x;
+
+               }
+
+       }
+
+}
+
+void pwc_dec23_exit(void)
+{
+       /* Do nothing */
+
+}
+
+/**
+ * Allocate a private structure used by lookup table.
+ * You must call kfree() to free the memory allocated.
+ */
+int pwc_dec23_alloc(struct pwc_device *pwc)
+{
+       pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
+       if (pwc->decompress_data == NULL)
+               return -ENOMEM;
+       return 0;
+}
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h
new file mode 100644 (file)
index 0000000..1c55298
--- /dev/null
@@ -0,0 +1,67 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef PWC_DEC23_H
+#define PWC_DEC23_H
+
+#include "pwc.h"
+
+struct pwc_dec23_private
+{
+  unsigned int scalebits;
+  unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
+
+  unsigned int reservoir;
+  unsigned int nbits_in_reservoir;
+  const unsigned char *stream;
+  int temp_colors[16];
+
+  unsigned char table_0004_pass1[16][1024];
+  unsigned char table_0004_pass2[16][1024];
+  unsigned char table_8004_pass1[16][256];
+  unsigned char table_8004_pass2[16][256];
+  unsigned int  table_subblock[256][12];
+
+  unsigned char table_bitpowermask[8][256];
+  unsigned int  table_d800[256];
+  unsigned int  table_dc00[256];
+
+};
+
+
+int pwc_dec23_alloc(struct pwc_device *pwc);
+int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
+void pwc_dec23_exit(void);
+void pwc_dec23_decompress(const struct pwc_device *pwc,
+                         const void *src,
+                         void *dst,
+                         int flags);
+
+
+
+#endif
+
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
+
index 41418294a32bc96440de0180e393c5fdf1c9a48b..47d0d83a0264445fd4f68b61b5e4b9d1f5906b23 100644 (file)
@@ -1,7 +1,7 @@
 /* Linux driver for Philips webcam
    USB and Video4Linux interface part.
    (C) 1999-2004 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
 #include <linux/poll.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/version.h>
 #include <asm/io.h>
+#include <linux/moduleparam.h>
 
 #include "pwc.h"
-#include "pwc-ioctl.h"
 #include "pwc-kiara.h"
 #include "pwc-timon.h"
+#include "pwc-dec23.h"
+#include "pwc-dec1.h"
 #include "pwc-uncompress.h"
 
 /* Function prototypes and driver templates */
 
 /* hotplug device table support */
-static struct usb_device_id pwc_device_table [] = {
+static const struct usb_device_id pwc_device_table [] = {
        { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
        { USB_DEVICE(0x0471, 0x0303) },
        { USB_DEVICE(0x0471, 0x0304) },
@@ -81,9 +84,10 @@ static struct usb_device_id pwc_device_table [] = {
        { USB_DEVICE(0x0471, 0x0308) },
        { USB_DEVICE(0x0471, 0x030C) },
        { USB_DEVICE(0x0471, 0x0310) },
-       { USB_DEVICE(0x0471, 0x0311) },
+       { USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */
        { USB_DEVICE(0x0471, 0x0312) },
        { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
+       { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */
        { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
        { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
        { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
@@ -94,8 +98,9 @@ static struct usb_device_id pwc_device_table [] = {
        { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */
        { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */
        { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
-       { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */
-       { USB_DEVICE(0x055D, 0x9001) },
+       { USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */
+       { USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */
+       { USB_DEVICE(0x055D, 0x9002) }, /* Samsung SNC-35E (Ver3.0) */
        { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
        { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */
        { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
@@ -122,11 +127,13 @@ static struct usb_driver pwc_driver = {
 static int default_size = PSZ_QCIF;
 static int default_fps = 10;
 static int default_fbufs = 3;   /* Default number of frame buffers */
-static int default_mbufs = 2;  /* Default number of mmap() buffers */
-       int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
+       int pwc_mbufs = 2;      /* Default number of mmap() buffers */
+#if CONFIG_PWC_DEBUG
+       int pwc_trace = PWC_DEBUG_LEVEL;
+#endif
 static int power_save = 0;
 static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
-static int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
 static struct {
        int type;
        char serial_number[30];
@@ -138,7 +145,7 @@ static struct {
 
 static int pwc_video_open(struct inode *inode, struct file *file);
 static int pwc_video_close(struct inode *inode, struct file *file);
-static ssize_t pwc_video_read(struct file *file, char __user * buf,
+static ssize_t pwc_video_read(struct file *file, char __user *buf,
                          size_t count, loff_t *ppos);
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
 static int  pwc_video_ioctl(struct inode *inode, struct file *file,
@@ -153,7 +160,6 @@ static struct file_operations pwc_fops = {
        .poll =         pwc_video_poll,
        .mmap =         pwc_video_mmap,
        .ioctl =        pwc_video_ioctl,
-       .compat_ioctl = v4l_compat_ioctl32,
        .llseek =       no_llseek,
 };
 static struct video_device pwc_template = {
@@ -203,52 +209,44 @@ static struct video_device pwc_template = {
 /* Here we want the physical address of the memory.
  * This is used when initializing the contents of the area.
  */
-static inline unsigned long kvirt_to_pa(unsigned long adr)
-{
-       unsigned long kva, ret;
 
-       kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-       kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-       ret = __pa(kva);
-       return ret;
-}
 
-static void * rvmalloc(unsigned long size)
+
+static void *pwc_rvmalloc(unsigned long size)
 {
        void * mem;
        unsigned long adr;
 
-       size=PAGE_ALIGN(size);
        mem=vmalloc_32(size);
-       if (mem)
-       {
-               memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-               adr=(unsigned long) mem;
-               while (size > 0)
-               {
-                       SetPageReserved(vmalloc_to_page((void *)adr));
-                       adr+=PAGE_SIZE;
-                       size-=PAGE_SIZE;
-               }
-       }
+       if (!mem)
+               return NULL;
+
+       memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+       adr=(unsigned long) mem;
+       while (size > 0)
+        {
+          SetPageReserved(vmalloc_to_page((void *)adr));
+          adr  += PAGE_SIZE;
+          size -= PAGE_SIZE;
+        }
        return mem;
 }
 
-static void rvfree(void * mem, unsigned long size)
+static void pwc_rvfree(void * mem, unsigned long size)
 {
        unsigned long adr;
 
-       if (mem)
-       {
-               adr=(unsigned long) mem;
-               while ((long) size > 0)
-               {
-                       ClearPageReserved(vmalloc_to_page((void *)adr));
-                       adr+=PAGE_SIZE;
-                       size-=PAGE_SIZE;
-               }
-               vfree(mem);
-       }
+       if (!mem)
+               return;
+
+       adr=(unsigned long) mem;
+       while ((long) size > 0)
+        {
+          ClearPageReserved(vmalloc_to_page((void *)adr));
+          adr  += PAGE_SIZE;
+          size -= PAGE_SIZE;
+        }
+       vfree(mem);
 }
 
 
@@ -256,100 +254,83 @@ static void rvfree(void * mem, unsigned long size)
 
 static int pwc_allocate_buffers(struct pwc_device *pdev)
 {
-       int i;
+       int i, err;
        void *kbuf;
 
-       Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
+       PWC_DEBUG_MEMORY(">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
 
        if (pdev == NULL)
                return -ENXIO;
 
-#ifdef PWC_MAGIC
-       if (pdev->magic != PWC_MAGIC) {
-               Err("allocate_buffers(): magic failed.\n");
-               return -ENXIO;
-       }
-#endif
-       /* Allocate Isochronous pipe buffers */
+       /* Allocate Isochronuous pipe buffers */
        for (i = 0; i < MAX_ISO_BUFS; i++) {
                if (pdev->sbuf[i].data == NULL) {
-                       kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
+                       kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
                        if (kbuf == NULL) {
-                               Err("Failed to allocate iso buffer %d.\n", i);
+                               PWC_ERROR("Failed to allocate iso buffer %d.\n", i);
                                return -ENOMEM;
                        }
-                       Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf);
+                       PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf);
                        pdev->sbuf[i].data = kbuf;
-                       memset(kbuf, 0, ISO_BUFFER_SIZE);
                }
        }
 
        /* Allocate frame buffer structure */
        if (pdev->fbuf == NULL) {
-               kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
+               kbuf = kzalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
                if (kbuf == NULL) {
-                       Err("Failed to allocate frame buffer structure.\n");
+                       PWC_ERROR("Failed to allocate frame buffer structure.\n");
                        return -ENOMEM;
                }
-               Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf);
+               PWC_DEBUG_MEMORY("Allocated frame buffer structure at %p.\n", kbuf);
                pdev->fbuf = kbuf;
-               memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
        }
+
        /* create frame buffers, and make circular ring */
        for (i = 0; i < default_fbufs; i++) {
                if (pdev->fbuf[i].data == NULL) {
                        kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
                        if (kbuf == NULL) {
-                               Err("Failed to allocate frame buffer %d.\n", i);
+                               PWC_ERROR("Failed to allocate frame buffer %d.\n", i);
                                return -ENOMEM;
                        }
-                       Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf);
+                       PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf);
                        pdev->fbuf[i].data = kbuf;
-                       memset(kbuf, 128, PWC_FRAME_SIZE);
+                       memset(kbuf, 0, PWC_FRAME_SIZE);
                }
        }
 
        /* Allocate decompressor table space */
-       kbuf = NULL;
-       switch (pdev->type)
-        {
-         case 675:
-         case 680:
-         case 690:
-         case 720:
-         case 730:
-         case 740:
-         case 750:
-#if 0
-           Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private));
-           kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);       /* Timon & Kiara */
-           break;
-         case 645:
-         case 646:
-           /* TODO & FIXME */
-           kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
-           break;
-#endif
-       ;
-        }
-       pdev->decompress_data = kbuf;
+       if (DEVICE_USE_CODEC1(pdev->type))
+               err = pwc_dec1_alloc(pdev);
+       else
+               err = pwc_dec23_alloc(pdev);
+
+       if (err) {
+               PWC_ERROR("Failed to allocate decompress table.\n");
+               return err;
+       }
 
        /* Allocate image buffer; double buffer for mmap() */
-       kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
+       kbuf = pwc_rvmalloc(pwc_mbufs * pdev->len_per_image);
        if (kbuf == NULL) {
-               Err("Failed to allocate image buffer(s). needed (%d)\n",default_mbufs * pdev->len_per_image);
+               PWC_ERROR("Failed to allocate image buffer(s). needed (%d)\n",
+                               pwc_mbufs * pdev->len_per_image);
                return -ENOMEM;
        }
-       Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf);
+       PWC_DEBUG_MEMORY("Allocated image buffer at %p.\n", kbuf);
        pdev->image_data = kbuf;
-       for (i = 0; i < default_mbufs; i++)
-               pdev->image_ptr[i] = kbuf + i * pdev->len_per_image;
-       for (; i < MAX_IMAGES; i++)
-               pdev->image_ptr[i] = NULL;
+       for (i = 0; i < pwc_mbufs; i++) {
+               pdev->images[i].offset = i * pdev->len_per_image;
+               pdev->images[i].vma_use_count = 0;
+       }
+       for (; i < MAX_IMAGES; i++) {
+               pdev->images[i].offset = 0;
+       }
 
        kbuf = NULL;
 
-       Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
+       PWC_DEBUG_MEMORY("<< pwc_allocate_buffers()\n");
        return 0;
 }
 
@@ -357,21 +338,14 @@ static void pwc_free_buffers(struct pwc_device *pdev)
 {
        int i;
 
-       Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev);
+       PWC_DEBUG_MEMORY("Entering free_buffers(%p).\n", pdev);
 
        if (pdev == NULL)
                return;
-#ifdef PWC_MAGIC
-       if (pdev->magic != PWC_MAGIC) {
-               Err("free_buffers(): magic failed.\n");
-               return;
-       }
-#endif
-
        /* Release Iso-pipe buffers */
        for (i = 0; i < MAX_ISO_BUFS; i++)
                if (pdev->sbuf[i].data != NULL) {
-                       Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
+                       PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
                        kfree(pdev->sbuf[i].data);
                        pdev->sbuf[i].data = NULL;
                }
@@ -380,7 +354,7 @@ static void pwc_free_buffers(struct pwc_device *pdev)
        if (pdev->fbuf != NULL) {
                for (i = 0; i < default_fbufs; i++) {
                        if (pdev->fbuf[i].data != NULL) {
-                               Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
+                               PWC_DEBUG_MEMORY("Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
                                vfree(pdev->fbuf[i].data);
                                pdev->fbuf[i].data = NULL;
                        }
@@ -391,20 +365,19 @@ static void pwc_free_buffers(struct pwc_device *pdev)
 
        /* Intermediate decompression buffer & tables */
        if (pdev->decompress_data != NULL) {
-               Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data);
+               PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n", pdev->decompress_data);
                kfree(pdev->decompress_data);
                pdev->decompress_data = NULL;
        }
-       pdev->decompressor = NULL;
 
        /* Release image buffers */
        if (pdev->image_data != NULL) {
-               Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
-               rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
+               PWC_DEBUG_MEMORY("Freeing image buffer at %p.\n", pdev->image_data);
+               pwc_rvfree(pdev->image_data, pwc_mbufs * pdev->len_per_image);
        }
        pdev->image_data = NULL;
 
-       Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
+       PWC_DEBUG_MEMORY("Leaving free_buffers().\n");
 }
 
 /* The frame & image buffer mess.
@@ -464,7 +437,7 @@ static void pwc_free_buffers(struct pwc_device *pdev)
 /**
   \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
  */
-static inline int pwc_next_fill_frame(struct pwc_device *pdev)
+static int pwc_next_fill_frame(struct pwc_device *pdev)
 {
        int ret;
        unsigned long flags;
@@ -489,23 +462,17 @@ static inline int pwc_next_fill_frame(struct pwc_device *pdev)
        }
        else {
                /* Hmm. Take it from the full list */
-#if PWC_DEBUG
                /* sanity check */
                if (pdev->full_frames == NULL) {
-                       Err("Neither empty or full frames available!\n");
+                       PWC_ERROR("Neither empty or full frames available!\n");
                        spin_unlock_irqrestore(&pdev->ptrlock, flags);
                        return -EINVAL;
                }
-#endif
                pdev->fill_frame = pdev->full_frames;
                pdev->full_frames = pdev->full_frames->next;
                ret = 1;
        }
        pdev->fill_frame->next = NULL;
-#if PWC_DEBUG
-       Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence);
-       pdev->fill_frame->sequence = pdev->sequence++;
-#endif
        spin_unlock_irqrestore(&pdev->ptrlock, flags);
        return ret;
 }
@@ -521,6 +488,8 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
        int i;
        unsigned long flags;
 
+       PWC_DEBUG_MEMORY(">> %s __enter__\n", __FUNCTION__);
+
        spin_lock_irqsave(&pdev->ptrlock, flags);
        pdev->full_frames = NULL;
        pdev->full_frames_tail = NULL;
@@ -540,13 +509,15 @@ static void pwc_reset_buffers(struct pwc_device *pdev)
        pdev->image_read_pos = 0;
        pdev->fill_image = 0;
        spin_unlock_irqrestore(&pdev->ptrlock, flags);
+
+       PWC_DEBUG_MEMORY("<< %s __leaving__\n", __FUNCTION__);
 }
 
 
 /**
   \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
  */
-static int pwc_handle_frame(struct pwc_device *pdev)
+int pwc_handle_frame(struct pwc_device *pdev)
 {
        int ret = 0;
        unsigned long flags;
@@ -556,41 +527,40 @@ static int pwc_handle_frame(struct pwc_device *pdev)
           we can release the lock after this without problems */
        if (pdev->read_frame != NULL) {
                /* This can't theoretically happen */
-               Err("Huh? Read frame still in use?\n");
+               PWC_ERROR("Huh? Read frame still in use?\n");
+               spin_unlock_irqrestore(&pdev->ptrlock, flags);
+               return ret;
+       }
+
+
+       if (pdev->full_frames == NULL) {
+               PWC_ERROR("Woops. No frames ready.\n");
        }
        else {
-               if (pdev->full_frames == NULL) {
-                       Err("Woops. No frames ready.\n");
+               pdev->read_frame = pdev->full_frames;
+               pdev->full_frames = pdev->full_frames->next;
+               pdev->read_frame->next = NULL;
+       }
+
+       if (pdev->read_frame != NULL) {
+               /* Decompression is a lenghty process, so it's outside of the lock.
+                  This gives the isoc_handler the opportunity to fill more frames
+                  in the mean time.
+               */
+               spin_unlock_irqrestore(&pdev->ptrlock, flags);
+               ret = pwc_decompress(pdev);
+               spin_lock_irqsave(&pdev->ptrlock, flags);
+
+               /* We're done with read_buffer, tack it to the end of the empty buffer list */
+               if (pdev->empty_frames == NULL) {
+                       pdev->empty_frames = pdev->read_frame;
+                       pdev->empty_frames_tail = pdev->empty_frames;
                }
                else {
-                       pdev->read_frame = pdev->full_frames;
-                       pdev->full_frames = pdev->full_frames->next;
-                       pdev->read_frame->next = NULL;
-               }
-
-               if (pdev->read_frame != NULL) {
-#if PWC_DEBUG
-                       Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence);
-#endif
-                       /* Decompression is a lenghty process, so it's outside of the lock.
-                          This gives the isoc_handler the opportunity to fill more frames
-                          in the mean time.
-                       */
-                       spin_unlock_irqrestore(&pdev->ptrlock, flags);
-                       ret = pwc_decompress(pdev);
-                       spin_lock_irqsave(&pdev->ptrlock, flags);
-
-                       /* We're done with read_buffer, tack it to the end of the empty buffer list */
-                       if (pdev->empty_frames == NULL) {
-                               pdev->empty_frames = pdev->read_frame;
-                               pdev->empty_frames_tail = pdev->empty_frames;
-                       }
-                       else {
-                               pdev->empty_frames_tail->next = pdev->read_frame;
-                               pdev->empty_frames_tail = pdev->read_frame;
-                       }
-                       pdev->read_frame = NULL;
+                       pdev->empty_frames_tail->next = pdev->read_frame;
+                       pdev->empty_frames_tail = pdev->read_frame;
                }
+               pdev->read_frame = NULL;
        }
        spin_unlock_irqrestore(&pdev->ptrlock, flags);
        return ret;
@@ -599,12 +569,114 @@ static int pwc_handle_frame(struct pwc_device *pdev)
 /**
   \brief Advance pointers of image buffer (after each user request)
 */
-static inline void pwc_next_image(struct pwc_device *pdev)
+void pwc_next_image(struct pwc_device *pdev)
 {
        pdev->image_used[pdev->fill_image] = 0;
-       pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
+       pdev->fill_image = (pdev->fill_image + 1) % pwc_mbufs;
 }
 
+/**
+ * Print debug information when a frame is discarded because all of our buffer
+ * is full
+ */
+static void pwc_frame_dumped(struct pwc_device *pdev)
+{
+       pdev->vframes_dumped++;
+       if (pdev->vframe_count < FRAME_LOWMARK)
+               return;
+
+       if (pdev->vframes_dumped < 20)
+               PWC_DEBUG_FLOW("Dumping frame %d\n", pdev->vframe_count);
+       else if (pdev->vframes_dumped == 20)
+               PWC_DEBUG_FLOW("Dumping frame %d (last message)\n",
+                               pdev->vframe_count);
+}
+
+static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf)
+{
+       int awake = 0;
+
+       /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
+          frames on the USB wire after an exposure change. This conditition is
+          however detected  in the cam and a bit is set in the header.
+          */
+       if (pdev->type == 730) {
+               unsigned char *ptr = (unsigned char *)fbuf->data;
+
+               if (ptr[1] == 1 && ptr[0] & 0x10) {
+                       PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
+                       pdev->drop_frames += 2;
+                       pdev->vframes_error++;
+               }
+               if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+                       if (ptr[0] & 0x01) {
+                               pdev->snapshot_button_status = 1;
+                               PWC_TRACE("Snapshot button pressed.\n");
+                       }
+                       else {
+                               PWC_TRACE("Snapshot button released.\n");
+                       }
+               }
+               if ((ptr[0] ^ pdev->vmirror) & 0x02) {
+                       if (ptr[0] & 0x02)
+                               PWC_TRACE("Image is mirrored.\n");
+                       else
+                               PWC_TRACE("Image is normal.\n");
+               }
+               pdev->vmirror = ptr[0] & 0x03;
+               /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
+                  after a short frame; this condition is filtered out specifically. A 4 byte
+                  frame doesn't make sense anyway.
+                  So we get either this sequence:
+                  drop_bit set -> 4 byte frame -> short frame -> good frame
+                  Or this one:
+                  drop_bit set -> short frame -> good frame
+                  So we drop either 3 or 2 frames in all!
+                  */
+               if (fbuf->filled == 4)
+                       pdev->drop_frames++;
+       }
+       else if (pdev->type == 740 || pdev->type == 720) {
+               unsigned char *ptr = (unsigned char *)fbuf->data;
+               if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+                       if (ptr[0] & 0x01) {
+                               pdev->snapshot_button_status = 1;
+                               PWC_TRACE("Snapshot button pressed.\n");
+                       }
+                       else
+                               PWC_TRACE("Snapshot button released.\n");
+               }
+               pdev->vmirror = ptr[0] & 0x03;
+       }
+
+       /* In case we were instructed to drop the frame, do so silently.
+          The buffer pointers are not updated either (but the counters are reset below).
+          */
+       if (pdev->drop_frames > 0)
+               pdev->drop_frames--;
+       else {
+               /* Check for underflow first */
+               if (fbuf->filled < pdev->frame_total_size) {
+                       PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
+                                      " discarded.\n", fbuf->filled);
+                       pdev->vframes_error++;
+               }
+               else {
+                       /* Send only once per EOF */
+                       awake = 1; /* delay wake_ups */
+
+                       /* Find our next frame to fill. This will always succeed, since we
+                        * nick a frame from either empty or full list, but if we had to
+                        * take it from the full list, it means a frame got dropped.
+                        */
+                       if (pwc_next_fill_frame(pdev))
+                               pwc_frame_dumped(pdev);
+
+               }
+       } /* !drop_frames */
+       pdev->vframe_count++;
+       return awake;
+}
 
 /* This gets called for the Isochronous pipe (video). This is done in
  * interrupt time, so it has to be fast, not crash, and not stall. Neat.
@@ -620,17 +692,12 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
        awake = 0;
        pdev = (struct pwc_device *)urb->context;
        if (pdev == NULL) {
-               Err("isoc_handler() called with NULL device?!\n");
-               return;
-       }
-#ifdef PWC_MAGIC
-       if (pdev->magic != PWC_MAGIC) {
-               Err("isoc_handler() called with bad magic!\n");
+               PWC_ERROR("isoc_handler() called with NULL device?!\n");
                return;
        }
-#endif
+
        if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
-               Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
+               PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
                return;
        }
        if (urb->status != -EINPROGRESS && urb->status != 0) {
@@ -645,13 +712,13 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
                        case -EILSEQ:           errmsg = "CRC/Timeout (could be anything)"; break;
                        case -ETIMEDOUT:        errmsg = "NAK (device does not respond)"; break;
                }
-               Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
+               PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
                /* Give up after a number of contiguous errors on the USB bus.
                   Appearantly something is wrong so we simulate an unplug event.
                 */
                if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
                {
-                       Info("Too many ISOC errors, bailing out.\n");
+                       PWC_INFO("Too many ISOC errors, bailing out.\n");
                        pdev->error_status = EIO;
                        awake = 1;
                        wake_up_interruptible(&pdev->frameq);
@@ -661,7 +728,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
 
        fbuf = pdev->fill_frame;
        if (fbuf == NULL) {
-               Err("pwc_isoc_handler without valid fill frame.\n");
+               PWC_ERROR("pwc_isoc_handler without valid fill frame.\n");
                awake = 1;
                goto handler_end;
        }
@@ -688,7 +755,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
 
                                        /* ...copy data to frame buffer, if possible */
                                        if (flen + fbuf->filled > pdev->frame_total_size) {
-                                               Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size);
+                                               PWC_DEBUG_FLOW("Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size);
                                                pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
                                                pdev->vframes_error++;
                                        }
@@ -704,96 +771,28 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
                                /* Shorter packet... We probably have the end of an image-frame;
                                   wake up read() process and let select()/poll() do something.
                                   Decompression is done in user time over there.
-                                */
+                                  */
                                if (pdev->vsync == 2) {
-                                       /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
-                                          frames on the USB wire after an exposure change. This conditition is
-                                          however detected  in the cam and a bit is set in the header.
-                                        */
-                                       if (pdev->type == 730) {
-                                               unsigned char *ptr = (unsigned char *)fbuf->data;
-
-                                               if (ptr[1] == 1 && ptr[0] & 0x10) {
-#if PWC_DEBUG
-                                                       Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
-#endif
-                                                       pdev->drop_frames += 2;
-                                                       pdev->vframes_error++;
-                                               }
-                                               if ((ptr[0] ^ pdev->vmirror) & 0x01) {
-                                                       if (ptr[0] & 0x01)
-                                                               Info("Snapshot button pressed.\n");
-                                                       else
-                                                               Info("Snapshot button released.\n");
-                                               }
-                                               if ((ptr[0] ^ pdev->vmirror) & 0x02) {
-                                                       if (ptr[0] & 0x02)
-                                                               Info("Image is mirrored.\n");
-                                                       else
-                                                               Info("Image is normal.\n");
-                                               }
-                                               pdev->vmirror = ptr[0] & 0x03;
-                                               /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
-                                                  after a short frame; this condition is filtered out specifically. A 4 byte
-                                                  frame doesn't make sense anyway.
-                                                  So we get either this sequence:
-                                                       drop_bit set -> 4 byte frame -> short frame -> good frame
-                                                  Or this one:
-                                                       drop_bit set -> short frame -> good frame
-                                                  So we drop either 3 or 2 frames in all!
-                                                */
-                                               if (fbuf->filled == 4)
-                                                       pdev->drop_frames++;
+                                       if (pwc_rcv_short_packet(pdev, fbuf)) {
+                                               awake = 1;
+                                               fbuf = pdev->fill_frame;
                                        }
-
-                                       /* In case we were instructed to drop the frame, do so silently.
-                                          The buffer pointers are not updated either (but the counters are reset below).
-                                        */
-                                       if (pdev->drop_frames > 0)
-                                               pdev->drop_frames--;
-                                       else {
-                                               /* Check for underflow first */
-                                               if (fbuf->filled < pdev->frame_total_size) {
-                                                       Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled);
-                                                       pdev->vframes_error++;
-                                               }
-                                               else {
-                                                       /* Send only once per EOF */
-                                                       awake = 1; /* delay wake_ups */
-
-                                                       /* Find our next frame to fill. This will always succeed, since we
-                                                        * nick a frame from either empty or full list, but if we had to
-                                                        * take it from the full list, it means a frame got dropped.
-                                                        */
-                                                       if (pwc_next_fill_frame(pdev)) {
-                                                               pdev->vframes_dumped++;
-                                                               if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) {
-                                                                       if (pdev->vframes_dumped < 20)
-                                                                               Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count);
-                                                                       if (pdev->vframes_dumped == 20)
-                                                                               Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count);
-                                                               }
-                                                       }
-                                                       fbuf = pdev->fill_frame;
-                                               }
-                                       } /* !drop_frames */
-                                       pdev->vframe_count++;
                                }
                                fbuf->filled = 0;
                                fillptr = fbuf->data;
                                pdev->vsync = 1;
-                       } /* .. flen < last_packet_size */
+                       }
+
                        pdev->vlast_packet_size = flen;
                } /* ..status == 0 */
-#if PWC_DEBUG
-               /* This is normally not interesting to the user, unless you are really debugging something */
                else {
+                       /* This is normally not interesting to the user, unless
+                        * you are really debugging something */
                        static int iso_error = 0;
                        iso_error++;
                        if (iso_error < 20)
-                               Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
+                               PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);
                }
-#endif
        }
 
 handler_end:
@@ -803,11 +802,11 @@ handler_end:
        urb->dev = pdev->udev;
        i = usb_submit_urb(urb, GFP_ATOMIC);
        if (i != 0)
-               Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
+               PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
 }
 
 
-static int pwc_isoc_init(struct pwc_device *pdev)
+int pwc_isoc_init(struct pwc_device *pdev)
 {
        struct usb_device *udev;
        struct urb *urb;
@@ -826,7 +825,6 @@ static int pwc_isoc_init(struct pwc_device *pdev)
        /* Get the current alternate interface, adjust packet size */
        if (!udev->actconfig)
                return -EFAULT;
-
        intf = usb_ifnum_to_if(udev, 0);
        if (intf)
                idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
@@ -836,20 +834,21 @@ static int pwc_isoc_init(struct pwc_device *pdev)
 
        /* Search video endpoint */
        pdev->vmax_packet_size = -1;
-       for (i = 0; i < idesc->desc.bNumEndpoints; i++)
+       for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
                if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
                        pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
                        break;
                }
+       }
 
        if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
-               Err("Failed to find packet size for video endpoint in current alternate setting.\n");
+               PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
                return -ENFILE; /* Odd error, that should be noticeable */
        }
 
        /* Set alternate interface */
        ret = 0;
-       Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate);
+       PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
        ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
        if (ret < 0)
                return ret;
@@ -857,12 +856,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
        for (i = 0; i < MAX_ISO_BUFS; i++) {
                urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
                if (urb == NULL) {
-                       Err("Failed to allocate urb %d\n", i);
+                       PWC_ERROR("Failed to allocate urb %d\n", i);
                        ret = -ENOMEM;
                        break;
                }
                pdev->sbuf[i].urb = urb;
-               Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb);
+               PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
        }
        if (ret) {
                /* De-allocate in reverse order */
@@ -899,24 +898,26 @@ static int pwc_isoc_init(struct pwc_device *pdev)
        for (i = 0; i < MAX_ISO_BUFS; i++) {
                ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
                if (ret)
-                       Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+                       PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
                else
-                       Trace(TRACE_MEMORY, "URB 0x%p submitted.\n", pdev->sbuf[i].urb);
+                       PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb);
        }
 
        /* All is done... */
        pdev->iso_init = 1;
-       Trace(TRACE_OPEN, "<< pwc_isoc_init()\n");
+       PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
        return 0;
 }
 
-static void pwc_isoc_cleanup(struct pwc_device *pdev)
+void pwc_isoc_cleanup(struct pwc_device *pdev)
 {
        int i;
 
-       Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n");
+       PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
        if (pdev == NULL)
                return;
+       if (pdev->iso_init == 0)
+               return;
 
        /* Unlinking ISOC buffers one by one */
        for (i = 0; i < MAX_ISO_BUFS; i++) {
@@ -925,10 +926,10 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
                urb = pdev->sbuf[i].urb;
                if (urb != 0) {
                        if (pdev->iso_init) {
-                               Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb);
+                               PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);
                                usb_kill_urb(urb);
                        }
-                       Trace(TRACE_MEMORY, "Freeing URB\n");
+                       PWC_DEBUG_MEMORY("Freeing URB\n");
                        usb_free_urb(urb);
                        pdev->sbuf[i].urb = NULL;
                }
@@ -938,12 +939,12 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
           is signalled by EPIPE)
         */
        if (pdev->error_status && pdev->error_status != EPIPE) {
-               Trace(TRACE_OPEN, "Setting alternate interface 0.\n");
+               PWC_DEBUG_OPEN("Setting alternate interface 0.\n");
                usb_set_interface(pdev->udev, 0, 0);
        }
 
        pdev->iso_init = 0;
-       Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n");
+       PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
 }
 
 int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
@@ -957,18 +958,18 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f
        /* Try to set video mode... */
        start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
        if (ret) {
-               Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n");
+               PWC_DEBUG_FLOW("pwc_set_video_mode attempt 1 failed.\n");
                /* That failed... restore old mode (we know that worked) */
                start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
                if (start) {
-                       Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n");
+                       PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n");
                }
        }
        if (start == 0)
        {
                if (pwc_isoc_init(pdev) < 0)
                {
-                       Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
+                       PWC_WARNING("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
                        ret = -EAGAIN; /* let's try again, who knows if it works a second time */
                }
        }
@@ -976,54 +977,129 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f
        return ret; /* Return original error code */
 }
 
+/*********
+ * sysfs
+ *********/
+static struct pwc_device *cd_to_pwc(struct class_device *cd)
+{
+       struct video_device *vdev = to_video_device(cd);
+       return video_get_drvdata(vdev);
+}
+
+static ssize_t show_pan_tilt(struct class_device *class_dev, char *buf)
+{
+       struct pwc_device *pdev = cd_to_pwc(class_dev);
+       return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
+}
+
+static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf,
+                        size_t count)
+{
+       struct pwc_device *pdev = cd_to_pwc(class_dev);
+       int pan, tilt;
+       int ret = -EINVAL;
+
+       if (strncmp(buf, "reset", 5) == 0)
+               ret = pwc_mpt_reset(pdev, 0x3);
+
+       else if (sscanf(buf, "%d %d", &pan, &tilt) > 0)
+               ret = pwc_mpt_set_angle(pdev, pan, tilt);
+
+       if (ret < 0)
+               return ret;
+       return strlen(buf);
+}
+static CLASS_DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
+                        store_pan_tilt);
+
+static ssize_t show_snapshot_button_status(struct class_device *class_dev, char *buf)
+{
+       struct pwc_device *pdev = cd_to_pwc(class_dev);
+       int status = pdev->snapshot_button_status;
+       pdev->snapshot_button_status = 0;
+       return sprintf(buf, "%d\n", status);
+}
+
+static CLASS_DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
+                        NULL);
+
+static void pwc_create_sysfs_files(struct video_device *vdev)
+{
+       struct pwc_device *pdev = video_get_drvdata(vdev);
+       if (pdev->features & FEATURE_MOTOR_PANTILT)
+               video_device_create_file(vdev, &class_device_attr_pan_tilt);
+       video_device_create_file(vdev, &class_device_attr_button);
+}
+
+static void pwc_remove_sysfs_files(struct video_device *vdev)
+{
+       struct pwc_device *pdev = video_get_drvdata(vdev);
+       if (pdev->features & FEATURE_MOTOR_PANTILT)
+               video_device_remove_file(vdev, &class_device_attr_pan_tilt);
+       video_device_remove_file(vdev, &class_device_attr_button);
+}
+
+#if CONFIG_PWC_DEBUG
+static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
+{
+       switch(sensor_type) {
+               case 0x00:
+                       return "Hyundai CMOS sensor";
+               case 0x20:
+                       return "Sony CCD sensor + TDA8787";
+               case 0x2E:
+                       return "Sony CCD sensor + Exas 98L59";
+               case 0x2F:
+                       return "Sony CCD sensor + ADI 9804";
+               case 0x30:
+                       return "Sharp CCD sensor + TDA8787";
+               case 0x3E:
+                       return "Sharp CCD sensor + Exas 98L59";
+               case 0x3F:
+                       return "Sharp CCD sensor + ADI 9804";
+               case 0x40:
+                       return "UPA 1021 sensor";
+               case 0x100:
+                       return "VGA sensor";
+               case 0x101:
+                       return "PAL MR sensor";
+               default:
+                       return "unknown type of sensor";
+       }
+}
+#endif
 
 /***************************************************************************/
 /* Video4Linux functions */
 
 static int pwc_video_open(struct inode *inode, struct file *file)
 {
-       int i;
+       int i, ret;
        struct video_device *vdev = video_devdata(file);
        struct pwc_device *pdev;
 
-       Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
+       PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
 
        pdev = (struct pwc_device *)vdev->priv;
        if (pdev == NULL)
                BUG();
-       if (pdev->vopen)
+       if (pdev->vopen) {
+               PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");
                return -EBUSY;
+       }
 
        down(&pdev->modlock);
        if (!pdev->usb_init) {
-               Trace(TRACE_OPEN, "Doing first time initialization.\n");
+               PWC_DEBUG_OPEN("Doing first time initialization.\n");
                pdev->usb_init = 1;
 
-               if (pwc_trace & TRACE_OPEN)
+               /* Query sensor type */
+               ret = pwc_get_cmos_sensor(pdev, &i);
+               if (ret >= 0)
                {
-                       /* Query sensor type */
-                       const char *sensor_type = NULL;
-                       int ret;
-
-                       ret = pwc_get_cmos_sensor(pdev, &i);
-                       if (ret >= 0)
-                       {
-                               switch(i) {
-                               case 0x00:  sensor_type = "Hyundai CMOS sensor"; break;
-                               case 0x20:  sensor_type = "Sony CCD sensor + TDA8787"; break;
-                               case 0x2E:  sensor_type = "Sony CCD sensor + Exas 98L59"; break;
-                               case 0x2F:  sensor_type = "Sony CCD sensor + ADI 9804"; break;
-                               case 0x30:  sensor_type = "Sharp CCD sensor + TDA8787"; break;
-                               case 0x3E:  sensor_type = "Sharp CCD sensor + Exas 98L59"; break;
-                               case 0x3F:  sensor_type = "Sharp CCD sensor + ADI 9804"; break;
-                               case 0x40:  sensor_type = "UPA 1021 sensor"; break;
-                               case 0x100: sensor_type = "VGA sensor"; break;
-                               case 0x101: sensor_type = "PAL MR sensor"; break;
-                               default:    sensor_type = "unknown type of sensor"; break;
-                               }
-                       }
-                       if (sensor_type != NULL)
-                               Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i);
+                       PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
+                                       pdev->vdev->name,
+                                       pwc_sensor_type_to_string(i), i);
                }
        }
 
@@ -1031,34 +1107,32 @@ static int pwc_video_open(struct inode *inode, struct file *file)
        if (power_save) {
                i = pwc_camera_power(pdev, 1);
                if (i < 0)
-                       Info("Failed to restore power to the camera! (%d)\n", i);
+                       PWC_DEBUG_OPEN("Failed to restore power to the camera! (%d)\n", i);
        }
        /* Set LED on/off time */
        if (pwc_set_leds(pdev, led_on, led_off) < 0)
-               Info("Failed to set LED on/off time.\n");
+               PWC_DEBUG_OPEN("Failed to set LED on/off time.\n");
 
        pwc_construct(pdev); /* set min/max sizes correct */
 
        /* So far, so good. Allocate memory. */
        i = pwc_allocate_buffers(pdev);
        if (i < 0) {
-               Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n");
+               PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n");
+               pwc_free_buffers(pdev);
                up(&pdev->modlock);
                return i;
        }
 
        /* Reset buffers & parameters */
        pwc_reset_buffers(pdev);
-       for (i = 0; i < default_mbufs; i++)
+       for (i = 0; i < pwc_mbufs; i++)
                pdev->image_used[i] = 0;
        pdev->vframe_count = 0;
        pdev->vframes_dumped = 0;
        pdev->vframes_error = 0;
        pdev->visoc_errors = 0;
        pdev->error_status = 0;
-#if PWC_DEBUG
-       pdev->sequence = 0;
-#endif
        pwc_construct(pdev); /* set min/max sizes correct */
 
        /* Set some defaults */
@@ -1070,29 +1144,44 @@ static int pwc_video_open(struct inode *inode, struct file *file)
         */
        i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0);
        if (i)  {
-               Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n");
-               if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750)
-                       i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0);
+               unsigned int default_resolution;
+               PWC_DEBUG_OPEN("First attempt at set_video_mode failed.\n");
+               if (pdev->type>= 730)
+                       default_resolution = PSZ_QSIF;
                else
-                       i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0);
+                       default_resolution = PSZ_QCIF;
+
+               i = pwc_set_video_mode(pdev,
+                                      pwc_image_sizes[default_resolution].x,
+                                      pwc_image_sizes[default_resolution].y,
+                                      10,
+                                      pdev->vcompression,
+                                      0);
        }
        if (i) {
-               Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n");
+               PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n");
+               pwc_free_buffers(pdev);
                up(&pdev->modlock);
                return i;
        }
 
        i = pwc_isoc_init(pdev);
        if (i) {
-               Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
+               PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i);
+               pwc_isoc_cleanup(pdev);
+               pwc_free_buffers(pdev);
                up(&pdev->modlock);
                return i;
        }
 
+       /* Initialize the webcam to sane value */
+       pwc_set_brightness(pdev, 0x7fff);
+       pwc_set_agc(pdev, 1, 0);
+
        pdev->vopen++;
        file->private_data = vdev;
        up(&pdev->modlock);
-       Trace(TRACE_OPEN, "<< video_open() returns 0.\n");
+       PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
        return 0;
 }
 
@@ -1103,35 +1192,23 @@ static int pwc_video_close(struct inode *inode, struct file *file)
        struct pwc_device *pdev;
        int i;
 
-       Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev);
+       PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
 
        pdev = (struct pwc_device *)vdev->priv;
        if (pdev->vopen == 0)
-               Info("video_close() called on closed device?\n");
+               PWC_DEBUG_MODULE("video_close() called on closed device?\n");
 
        /* Dump statistics, but only if a reasonable amount of frames were
           processed (to prevent endless log-entries in case of snap-shot
           programs)
         */
        if (pdev->vframe_count > 20)
-               Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
+               PWC_DEBUG_MODULE("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
 
-       switch (pdev->type)
-        {
-         case 675:
-         case 680:
-         case 690:
-         case 720:
-         case 730:
-         case 740:
-         case 750:
-/*         pwc_dec23_exit();   *//* Timon & Kiara */
-           break;
-         case 645:
-         case 646:
-/*         pwc_dec1_exit(); */
-           break;
-        }
+       if (DEVICE_USE_CODEC1(pdev->type))
+           pwc_dec1_exit();
+       else
+           pwc_dec23_exit();
 
        pwc_isoc_cleanup(pdev);
        pwc_free_buffers(pdev);
@@ -1140,15 +1217,15 @@ static int pwc_video_close(struct inode *inode, struct file *file)
        if (pdev->error_status != EPIPE) {
                /* Turn LEDs off */
                if (pwc_set_leds(pdev, 0, 0) < 0)
-                       Info("Failed to set LED on/off time.\n");
+                       PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
                if (power_save) {
                        i = pwc_camera_power(pdev, 0);
                        if (i < 0)
-                               Err("Failed to power down camera (%d)\n", i);
+                               PWC_ERROR("Failed to power down camera (%d)\n", i);
                }
        }
-       pdev->vopen = 0;
-       Trace(TRACE_OPEN, "<< video_close()\n");
+       pdev->vopen--;
+       PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
        return 0;
 }
 
@@ -1164,7 +1241,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
                device is tricky anyhow.
  */
 
-static ssize_t pwc_video_read(struct file *file, char __user * buf,
+static ssize_t pwc_video_read(struct file *file, char __user *buf,
                          size_t count, loff_t *ppos)
 {
        struct video_device *vdev = file->private_data;
@@ -1172,8 +1249,10 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf,
        int noblock = file->f_flags & O_NONBLOCK;
        DECLARE_WAITQUEUE(wait, current);
        int bytes_to_read;
+       void *image_buffer_addr;
 
-       Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count);
+       PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n",
+                       vdev, buf, count);
        if (vdev == NULL)
                return -EFAULT;
        pdev = vdev->priv;
@@ -1214,16 +1293,19 @@ static ssize_t pwc_video_read(struct file *file, char __user * buf,
                        return -EFAULT;
        }
 
-       Trace(TRACE_READ, "Copying data to user space.\n");
+       PWC_DEBUG_READ("Copying data to user space.\n");
        if (pdev->vpalette == VIDEO_PALETTE_RAW)
-               bytes_to_read = pdev->frame_size;
+               bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame);
        else
                bytes_to_read = pdev->view.size;
 
        /* copy bytes to user space; we allow for partial reads */
        if (count + pdev->image_read_pos > bytes_to_read)
                count = bytes_to_read - pdev->image_read_pos;
-       if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count))
+       image_buffer_addr = pdev->image_data;
+       image_buffer_addr += pdev->images[pdev->fill_image].offset;
+       image_buffer_addr += pdev->image_read_pos;
+       if (copy_to_user(buf, image_buffer_addr, count))
                return -EFAULT;
        pdev->image_read_pos += count;
        if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */
@@ -1253,370 +1335,56 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
        return 0;
 }
 
-static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
-                             unsigned int cmd, void *arg)
-{
-       struct video_device *vdev = file->private_data;
-       struct pwc_device *pdev;
-       DECLARE_WAITQUEUE(wait, current);
-
-       if (vdev == NULL)
-               return -EFAULT;
-       pdev = vdev->priv;
-       if (pdev == NULL)
-               return -EFAULT;
-
-       switch (cmd) {
-               /* Query cabapilities */
-               case VIDIOCGCAP:
-               {
-                       struct video_capability *caps = arg;
-
-                       strcpy(caps->name, vdev->name);
-                       caps->type = VID_TYPE_CAPTURE;
-                       caps->channels = 1;
-                       caps->audios = 1;
-                       caps->minwidth  = pdev->view_min.x;
-                       caps->minheight = pdev->view_min.y;
-                       caps->maxwidth  = pdev->view_max.x;
-                       caps->maxheight = pdev->view_max.y;
-                       break;
-               }
-
-               /* Channel functions (simulate 1 channel) */
-               case VIDIOCGCHAN:
-               {
-                       struct video_channel *v = arg;
-
-                       if (v->channel != 0)
-                               return -EINVAL;
-                       v->flags = 0;
-                       v->tuners = 0;
-                       v->type = VIDEO_TYPE_CAMERA;
-                       strcpy(v->name, "Webcam");
-                       return 0;
-               }
-
-               case VIDIOCSCHAN:
-               {
-                       /* The spec says the argument is an integer, but
-                          the bttv driver uses a video_channel arg, which
-                          makes sense becasue it also has the norm flag.
-                        */
-                       struct video_channel *v = arg;
-                       if (v->channel != 0)
-                               return -EINVAL;
-                       return 0;
-               }
-
-
-               /* Picture functions; contrast etc. */
-               case VIDIOCGPICT:
-               {
-                       struct video_picture *p = arg;
-                       int val;
-
-                       val = pwc_get_brightness(pdev);
-                       if (val >= 0)
-                               p->brightness = val;
-                       else
-                               p->brightness = 0xffff;
-                       val = pwc_get_contrast(pdev);
-                       if (val >= 0)
-                               p->contrast = val;
-                       else
-                               p->contrast = 0xffff;
-                       /* Gamma, Whiteness, what's the difference? :) */
-                       val = pwc_get_gamma(pdev);
-                       if (val >= 0)
-                               p->whiteness = val;
-                       else
-                               p->whiteness = 0xffff;
-                       val = pwc_get_saturation(pdev);
-                       if (val >= 0)
-                               p->colour = val;
-                       else
-                               p->colour = 0xffff;
-                       p->depth = 24;
-                       p->palette = pdev->vpalette;
-                       p->hue = 0xFFFF; /* N/A */
-                       break;
-               }
-
-               case VIDIOCSPICT:
-               {
-                       struct video_picture *p = arg;
-                       /*
-                        *      FIXME:  Suppose we are mid read
-                               ANSWER: No problem: the firmware of the camera
-                                       can handle brightness/contrast/etc
-                                       changes at _any_ time, and the palette
-                                       is used exactly once in the uncompress
-                                       routine.
-                        */
-                       pwc_set_brightness(pdev, p->brightness);
-                       pwc_set_contrast(pdev, p->contrast);
-                       pwc_set_gamma(pdev, p->whiteness);
-                       pwc_set_saturation(pdev, p->colour);
-                       if (p->palette && p->palette != pdev->vpalette) {
-                               switch (p->palette) {
-                                       case VIDEO_PALETTE_YUV420P:
-                                       case VIDEO_PALETTE_RAW:
-                                               pdev->vpalette = p->palette;
-                                               return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-                                               break;
-                                       default:
-                                               return -EINVAL;
-                                               break;
-                               }
-                       }
-                       break;
-               }
-
-               /* Window/size parameters */
-               case VIDIOCGWIN:
-               {
-                       struct video_window *vw = arg;
-
-                       vw->x = 0;
-                       vw->y = 0;
-                       vw->width = pdev->view.x;
-                       vw->height = pdev->view.y;
-                       vw->chromakey = 0;
-                       vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
-                                  (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
-                       break;
-               }
-
-               case VIDIOCSWIN:
-               {
-                       struct video_window *vw = arg;
-                       int fps, snapshot, ret;
-
-                       fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
-                       snapshot = vw->flags & PWC_FPS_SNAPSHOT;
-                       if (fps == 0)
-                               fps = pdev->vframes;
-                       if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
-                               return 0;
-                       ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
-                       if (ret)
-                               return ret;
-                       break;
-               }
-
-               /* We don't have overlay support (yet) */
-               case VIDIOCGFBUF:
-               {
-                       struct video_buffer *vb = arg;
-
-                       memset(vb,0,sizeof(*vb));
-                       break;
-               }
-
-               /* mmap() functions */
-               case VIDIOCGMBUF:
-               {
-                       /* Tell the user program how much memory is needed for a mmap() */
-                       struct video_mbuf *vm = arg;
-                       int i;
-
-                       memset(vm, 0, sizeof(*vm));
-                       vm->size = default_mbufs * pdev->len_per_image;
-                       vm->frames = default_mbufs; /* double buffering should be enough for most applications */
-                       for (i = 0; i < default_mbufs; i++)
-                               vm->offsets[i] = i * pdev->len_per_image;
-                       break;
-               }
-
-               case VIDIOCMCAPTURE:
-               {
-                       /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
-                       struct video_mmap *vm = arg;
-
-                       Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
-                       if (vm->frame < 0 || vm->frame >= default_mbufs)
-                               return -EINVAL;
-
-                       /* xawtv is nasty. It probes the available palettes
-                          by setting a very small image size and trying
-                          various palettes... The driver doesn't support
-                          such small images, so I'm working around it.
-                        */
-                       if (vm->format)
-                       {
-                               switch (vm->format)
-                               {
-                                       case VIDEO_PALETTE_YUV420P:
-                                       case VIDEO_PALETTE_RAW:
-                                               break;
-                                       default:
-                                               return -EINVAL;
-                                               break;
-                               }
-                       }
-
-                       if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
-                           (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
-                               int ret;
-
-                               Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
-                               ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-                               if (ret)
-                                       return ret;
-                       } /* ... size mismatch */
-
-                       /* FIXME: should we lock here? */
-                       if (pdev->image_used[vm->frame])
-                               return -EBUSY;  /* buffer wasn't available. Bummer */
-                       pdev->image_used[vm->frame] = 1;
-
-                       /* Okay, we're done here. In the SYNC call we wait until a
-                          frame comes available, then expand image into the given
-                          buffer.
-                          In contrast to the CPiA cam the Philips cams deliver a
-                          constant stream, almost like a grabber card. Also,
-                          we have separate buffers for the rawdata and the image,
-                          meaning we can nearly always expand into the requested buffer.
-                        */
-                       Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");
-                       break;
-               }
-
-               case VIDIOCSYNC:
-               {
-                       /* The doc says: "Whenever a buffer is used it should
-                          call VIDIOCSYNC to free this frame up and continue."
-
-                          The only odd thing about this whole procedure is
-                          that MCAPTURE flags the buffer as "in use", and
-                          SYNC immediately unmarks it, while it isn't
-                          after SYNC that you know that the buffer actually
-                          got filled! So you better not start a CAPTURE in
-                          the same frame immediately (use double buffering).
-                          This is not a problem for this cam, since it has
-                          extra intermediate buffers, but a hardware
-                          grabber card will then overwrite the buffer
-                          you're working on.
-                        */
-                       int *mbuf = arg;
-                       int ret;
-
-                       Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf);
-
-                       /* bounds check */
-                       if (*mbuf < 0 || *mbuf >= default_mbufs)
-                               return -EINVAL;
-                       /* check if this buffer was requested anyway */
-                       if (pdev->image_used[*mbuf] == 0)
-                               return -EINVAL;
-
-                       /* Add ourselves to the frame wait-queue.
-
-                          FIXME: needs auditing for safety.
-                          QUESTION: In what respect? I think that using the
-                                    frameq is safe now.
-                        */
-                       add_wait_queue(&pdev->frameq, &wait);
-                       while (pdev->full_frames == NULL) {
-                               if (pdev->error_status) {
-                                       remove_wait_queue(&pdev->frameq, &wait);
-                                       set_current_state(TASK_RUNNING);
-                                       return -pdev->error_status;
-                               }
-
-                               if (signal_pending(current)) {
-                                       remove_wait_queue(&pdev->frameq, &wait);
-                                       set_current_state(TASK_RUNNING);
-                                       return -ERESTARTSYS;
-                               }
-                               schedule();
-                               set_current_state(TASK_INTERRUPTIBLE);
-                       }
-                       remove_wait_queue(&pdev->frameq, &wait);
-                       set_current_state(TASK_RUNNING);
-
-                       /* The frame is ready. Expand in the image buffer
-                          requested by the user. I don't care if you
-                          mmap() 5 buffers and request data in this order:
-                          buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
-                          Grabber hardware may not be so forgiving.
-                        */
-                       Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");
-                       pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
-                       /* Decompress, etc */
-                       ret = pwc_handle_frame(pdev);
-                       pdev->image_used[*mbuf] = 0;
-                       if (ret)
-                               return -EFAULT;
-                       break;
-               }
-
-               case VIDIOCGAUDIO:
-               {
-                       struct video_audio *v = arg;
-
-                       strcpy(v->name, "Microphone");
-                       v->audio = -1; /* unknown audio minor */
-                       v->flags = 0;
-                       v->mode = VIDEO_SOUND_MONO;
-                       v->volume = 0;
-                       v->bass = 0;
-                       v->treble = 0;
-                       v->balance = 0x8000;
-                       v->step = 1;
-                       break;
-               }
-
-               case VIDIOCSAUDIO:
-               {
-                       /* Dummy: nothing can be set */
-                       break;
-               }
-
-               case VIDIOCGUNIT:
-               {
-                       struct video_unit *vu = arg;
-
-                       vu->video = pdev->vdev->minor & 0x3F;
-                       vu->audio = -1; /* not known yet */
-                       vu->vbi = -1;
-                       vu->radio = -1;
-                       vu->teletext = -1;
-                       break;
-               }
-               default:
-                       return pwc_ioctl(pdev, cmd, arg);
-       } /* ..switch */
-       return 0;
-}
-
 static int pwc_video_ioctl(struct inode *inode, struct file *file,
                           unsigned int cmd, unsigned long arg)
 {
        return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
 }
 
-
 static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct video_device *vdev = file->private_data;
        struct pwc_device *pdev;
-       unsigned long start = vma->vm_start;
-       unsigned long size  = vma->vm_end-vma->vm_start;
-       unsigned long page, pos;
+       unsigned long start;
+       unsigned long size;
+       unsigned long page, pos = 0;
+       int index;
 
-       Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
+       PWC_DEBUG_MEMORY(">> %s\n", __FUNCTION__);
        pdev = vdev->priv;
+       size = vma->vm_end - vma->vm_start;
+       start = vma->vm_start;
 
-       vma->vm_flags |= VM_IO;
+       /* Find the idx buffer for this mapping */
+       for (index = 0; index < pwc_mbufs; index++) {
+               pos = pdev->images[index].offset;
+               if ((pos>>PAGE_SHIFT) == vma->vm_pgoff)
+                       break;
+       }
+       if (index == MAX_IMAGES)
+               return -EINVAL;
+       if (index == 0) {
+               /*
+                * Special case for v4l1. In v4l1, we map only one big buffer,
+                * but in v4l2 each buffer is mapped
+                */
+               unsigned long total_size;
+               total_size = pwc_mbufs * pdev->len_per_image;
+               if (size != pdev->len_per_image && size != total_size) {
+                       PWC_ERROR("Wrong size (%lu) needed to be len_per_image=%d or total_size=%lu\n",
+                                  size, pdev->len_per_image, total_size);
+                       return -EINVAL;
+               }
+       } else if (size > pdev->len_per_image)
+               return -EINVAL;
 
-       pos = (unsigned long)pdev->image_data;
+       vma->vm_flags |= VM_IO; /* from 2.6.9-acX */
+
+       pos += (unsigned long)pdev->image_data;
        while (size > 0) {
                page = vmalloc_to_pfn((void *)pos);
                if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
                        return -EAGAIN;
-
                start += PAGE_SIZE;
                pos += PAGE_SIZE;
                if (size > PAGE_SIZE)
@@ -1624,7 +1392,6 @@ static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
                else
                        size = 0;
        }
-
        return 0;
 }
 
@@ -1645,10 +1412,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        int video_nr = -1; /* default: use next available device */
        char serial_number[30], *name;
 
+       vendor_id = le16_to_cpu(udev->descriptor.idVendor);
+       product_id = le16_to_cpu(udev->descriptor.idProduct);
+
        /* Check if we can handle this device */
-       Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n",
-               le16_to_cpu(udev->descriptor.idVendor),
-               le16_to_cpu(udev->descriptor.idProduct),
+       PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
+               vendor_id, product_id,
                intf->altsetting->desc.bInterfaceNumber);
 
        /* the interfaces are probed one by one. We are only interested in the
@@ -1658,61 +1427,63 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        if (intf->altsetting->desc.bInterfaceNumber > 0)
                return -ENODEV;
 
-       vendor_id = le16_to_cpu(udev->descriptor.idVendor);
-       product_id = le16_to_cpu(udev->descriptor.idProduct);
-
        if (vendor_id == 0x0471) {
                switch (product_id) {
                case 0x0302:
-                       Info("Philips PCA645VC USB webcam detected.\n");
+                       PWC_INFO("Philips PCA645VC USB webcam detected.\n");
                        name = "Philips 645 webcam";
                        type_id = 645;
                        break;
                case 0x0303:
-                       Info("Philips PCA646VC USB webcam detected.\n");
+                       PWC_INFO("Philips PCA646VC USB webcam detected.\n");
                        name = "Philips 646 webcam";
                        type_id = 646;
                        break;
                case 0x0304:
-                       Info("Askey VC010 type 2 USB webcam detected.\n");
+                       PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
                        name = "Askey VC010 webcam";
                        type_id = 646;
                        break;
                case 0x0307:
-                       Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
+                       PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
                        name = "Philips 675 webcam";
                        type_id = 675;
                        break;
                case 0x0308:
-                       Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+                       PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
                        name = "Philips 680 webcam";
                        type_id = 680;
                        break;
                case 0x030C:
-                       Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
+                       PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
                        name = "Philips 690 webcam";
                        type_id = 690;
                        break;
                case 0x0310:
-                       Info("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
+                       PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
                        name = "Philips 730 webcam";
                        type_id = 730;
                        break;
                case 0x0311:
-                       Info("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
+                       PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
                        name = "Philips 740 webcam";
                        type_id = 740;
                        break;
                case 0x0312:
-                       Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
+                       PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
                        name = "Philips 750 webcam";
                        type_id = 750;
                        break;
                case 0x0313:
-                       Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
+                       PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
                        name = "Philips 720K/40 webcam";
                        type_id = 720;
                        break;
+               case 0x0329:
+                       PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
+                       name = "Philips SPC 900NC webcam";
+                       type_id = 720;
+                       break;
                default:
                        return -ENODEV;
                        break;
@@ -1721,7 +1492,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        else if (vendor_id == 0x069A) {
                switch(product_id) {
                case 0x0001:
-                       Info("Askey VC010 type 1 USB webcam detected.\n");
+                       PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
                        name = "Askey VC010 webcam";
                        type_id = 645;
                        break;
@@ -1733,32 +1504,33 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        else if (vendor_id == 0x046d) {
                switch(product_id) {
                case 0x08b0:
-                       Info("Logitech QuickCam Pro 3000 USB webcam detected.\n");
+                       PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
                        name = "Logitech QuickCam Pro 3000";
                        type_id = 740; /* CCD sensor */
                        break;
                case 0x08b1:
-                       Info("Logitech QuickCam Notebook Pro USB webcam detected.\n");
+                       PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
                        name = "Logitech QuickCam Notebook Pro";
                        type_id = 740; /* CCD sensor */
                        break;
                case 0x08b2:
-                       Info("Logitech QuickCam 4000 Pro USB webcam detected.\n");
+                       PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
                        name = "Logitech QuickCam Pro 4000";
                        type_id = 740; /* CCD sensor */
                        break;
                case 0x08b3:
-                       Info("Logitech QuickCam Zoom USB webcam detected.\n");
+                       PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
                        name = "Logitech QuickCam Zoom";
                        type_id = 740; /* CCD sensor */
                        break;
                case 0x08B4:
-                       Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
+                       PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
                        name = "Logitech QuickCam Zoom";
                        type_id = 740; /* CCD sensor */
+                       power_save = 1;
                        break;
                case 0x08b5:
-                       Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
+                       PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
                        name = "Logitech QuickCam Orbit";
                        type_id = 740; /* CCD sensor */
                        features |= FEATURE_MOTOR_PANTILT;
@@ -1766,7 +1538,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                case 0x08b6:
                case 0x08b7:
                case 0x08b8:
-                       Info("Logitech QuickCam detected (reserved ID).\n");
+                       PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
                        name = "Logitech QuickCam (res.)";
                        type_id = 730; /* Assuming CMOS */
                        break;
@@ -1782,15 +1554,20 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                 */
                switch(product_id) {
                case 0x9000:
-                       Info("Samsung MPC-C10 USB webcam detected.\n");
+                       PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
                        name = "Samsung MPC-C10";
                        type_id = 675;
                        break;
                case 0x9001:
-                       Info("Samsung MPC-C30 USB webcam detected.\n");
+                       PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
                        name = "Samsung MPC-C30";
                        type_id = 675;
                        break;
+               case 0x9002:
+                       PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
+                       name = "Samsung MPC-C30";
+                       type_id = 740;
+                       break;
                default:
                        return -ENODEV;
                        break;
@@ -1799,12 +1576,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        else if (vendor_id == 0x041e) {
                switch(product_id) {
                case 0x400c:
-                       Info("Creative Labs Webcam 5 detected.\n");
+                       PWC_INFO("Creative Labs Webcam 5 detected.\n");
                        name = "Creative Labs Webcam 5";
                        type_id = 730;
                        break;
                case 0x4011:
-                       Info("Creative Labs Webcam Pro Ex detected.\n");
+                       PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
                        name = "Creative Labs Webcam Pro Ex";
                        type_id = 740;
                        break;
@@ -1816,7 +1593,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        else if (vendor_id == 0x04cc) {
                switch(product_id) {
                case 0x8116:
-                       Info("Sotec Afina Eye USB webcam detected.\n");
+                       PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
                        name = "Sotec Afina Eye";
                        type_id = 730;
                        break;
@@ -1829,7 +1606,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                switch(product_id) {
                case 0x8116:
                        /* This is essentially the same cam as the Sotec Afina Eye */
-                       Info("AME Co. Afina Eye USB webcam detected.\n");
+                       PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
                        name = "AME Co. Afina Eye";
                        type_id = 750;
                        break;
@@ -1842,12 +1619,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        else if (vendor_id == 0x0d81) {
                switch(product_id) {
                case 0x1900:
-                       Info("Visionite VCS-UC300 USB webcam detected.\n");
+                       PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
                        name = "Visionite VCS-UC300";
                        type_id = 740; /* CCD sensor */
                        break;
                case 0x1910:
-                       Info("Visionite VCS-UM100 USB webcam detected.\n");
+                       PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
                        name = "Visionite VCS-UM100";
                        type_id = 730; /* CMOS sensor */
                        break;
@@ -1861,15 +1638,15 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
 
        memset(serial_number, 0, 30);
        usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
-       Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number);
+       PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
 
        if (udev->descriptor.bNumConfigurations > 1)
-               Info("Warning: more than 1 configuration available.\n");
+               PWC_WARNING("Warning: more than 1 configuration available.\n");
 
        /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
        pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
        if (pdev == NULL) {
-               Err("Oops, could not allocate memory for pwc_device.\n");
+               PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
                return -ENOMEM;
        }
        pdev->type = type_id;
@@ -1900,17 +1677,18 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pdev->vdev = video_device_alloc();
        if (pdev->vdev == 0)
        {
-               Err("Err, cannot allocate video_device struture. Failing probe.");
+               PWC_ERROR("Err, cannot allocate video_device struture. Failing probe.");
                kfree(pdev);
                return -ENOMEM;
        }
        memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
+       pdev->vdev->dev = &(udev->dev);
        strcpy(pdev->vdev->name, name);
        pdev->vdev->owner = THIS_MODULE;
        video_set_drvdata(pdev->vdev, pdev);
 
        pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
-       Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
+       PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
 
        /* Now search device_hint[] table for a match, so we can hint a node number. */
        for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
@@ -1918,10 +1696,10 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
                     (device_hint[hint].pdev == NULL)) {
                        /* so far, so good... try serial number */
                        if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
-                               /* match! */
-                               video_nr = device_hint[hint].device_node;
-                               Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr);
-                               break;
+                               /* match! */
+                               video_nr = device_hint[hint].device_node;
+                               PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
+                               break;
                        }
                }
        }
@@ -1929,21 +1707,27 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pdev->vdev->release = video_device_release;
        i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
        if (i < 0) {
-               Err("Failed to register as video device (%d).\n", i);
+               PWC_ERROR("Failed to register as video device (%d).\n", i);
                video_device_release(pdev->vdev); /* Drip... drip... drip... */
                kfree(pdev); /* Oops, no memory leaks please */
                return -EIO;
        }
        else {
-               Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
+               PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
        }
 
        /* occupy slot */
        if (hint < MAX_DEV_HINTS)
                device_hint[hint].pdev = pdev;
 
-       Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
+       PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
        usb_set_intfdata (intf, pdev);
+       pwc_create_sysfs_files(pdev->vdev);
+
+       /* Set the leds off */
+       pwc_set_leds(pdev, 0, 0);
+       pwc_camera_power(pdev, 0);
+
        return 0;
 }
 
@@ -1957,27 +1741,21 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
        pdev = usb_get_intfdata (intf);
        usb_set_intfdata (intf, NULL);
        if (pdev == NULL) {
-               Err("pwc_disconnect() Called without private pointer.\n");
+               PWC_ERROR("pwc_disconnect() Called without private pointer.\n");
                goto disconnect_out;
        }
        if (pdev->udev == NULL) {
-               Err("pwc_disconnect() already called for %p\n", pdev);
+               PWC_ERROR("pwc_disconnect() already called for %p\n", pdev);
                goto disconnect_out;
        }
        if (pdev->udev != interface_to_usbdev(intf)) {
-               Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
-               goto disconnect_out;
-       }
-#ifdef PWC_MAGIC
-       if (pdev->magic != PWC_MAGIC) {
-               Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
+               PWC_ERROR("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
                goto disconnect_out;
        }
-#endif
 
        /* We got unplugged; this is signalled by an EPIPE error code */
        if (pdev->vopen) {
-               Info("Disconnected while webcam is in use!\n");
+               PWC_INFO("Disconnected while webcam is in use!\n");
                pdev->error_status = EPIPE;
        }
 
@@ -1987,7 +1765,8 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
        while (pdev->vopen)
                schedule();
        /* Device is now closed, so we can safely unregister it */
-       Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");
+       PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
+       pwc_remove_sysfs_files(pdev->vdev);
        video_unregister_device(pdev->vdev);
 
        /* Free memory (don't set pdev to 0 just yet) */
@@ -2021,58 +1800,64 @@ static int pwc_atoi(const char *s)
  * Initialization code & module stuff
  */
 
-static char size[10];
-static int fps = 0;
-static int fbufs = 0;
-static int mbufs = 0;
-static int trace = -1;
+static char *size;
+static int fps;
+static int fbufs;
+static int mbufs;
 static int compression = -1;
 static int leds[2] = { -1, -1 };
-static char *dev_hint[MAX_DEV_HINTS] = { };
+static int leds_nargs;
+static char *dev_hint[MAX_DEV_HINTS];
+static int dev_hint_nargs;
+
+module_param(size, charp, 0444);
+module_param(fps, int, 0444);
+module_param(fbufs, int, 0444);
+module_param(mbufs, int, 0444);
+#if CONFIG_PWC_DEBUG
+module_param_named(trace, pwc_trace, int, 0644);
+#endif
+module_param(power_save, int, 0444);
+module_param(compression, int, 0444);
+module_param_array(leds, int, &leds_nargs, 0444);
+module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
 
-module_param_string(size, size, sizeof(size), 0);
 MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
-module_param(fps, int, 0000);
 MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
-module_param(fbufs, int, 0000);
 MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
-module_param(mbufs, int, 0000);
 MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
-module_param(trace, int, 0000);
 MODULE_PARM_DESC(trace, "For debugging purposes");
-module_param(power_save, bool, 0000);
 MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
-module_param(compression, int, 0000);
 MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
-module_param_array(leds, int, NULL, 0000);
 MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-module_param_array(dev_hint, charp, NULL, 0000);
 MODULE_PARM_DESC(dev_hint, "Device node hints");
 
 MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
 MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("pwcx");
+MODULE_VERSION( PWC_VERSION );
 
 static int __init usb_pwc_init(void)
 {
        int i, sz;
        char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
 
-       Info("Philips webcam module version " PWC_VERSION " loaded.\n");
-       Info("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
-       Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
-       Info("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
+       PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
+       PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
+       PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
+       PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
 
        if (fps) {
                if (fps < 4 || fps > 30) {
-                       Err("Framerate out of bounds (4-30).\n");
+                       PWC_ERROR("Framerate out of bounds (4-30).\n");
                        return -EINVAL;
                }
                default_fps = fps;
-               Info("Default framerate set to %d.\n", default_fps);
+               PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
        }
 
-       if (size[0]) {
+       if (size) {
                /* string; try matching with array */
                for (sz = 0; sz < PSZ_MAX; sz++) {
                        if (!strcmp(sizenames[sz], size)) { /* Found! */
@@ -2081,41 +1866,42 @@ static int __init usb_pwc_init(void)
                        }
                }
                if (sz == PSZ_MAX) {
-                       Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
+                       PWC_ERROR("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
                        return -EINVAL;
                }
-               Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
+               PWC_DEBUG_MODULE("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
        }
        if (mbufs) {
                if (mbufs < 1 || mbufs > MAX_IMAGES) {
-                       Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
+                       PWC_ERROR("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
                        return -EINVAL;
                }
-               default_mbufs = mbufs;
-               Info("Number of image buffers set to %d.\n", default_mbufs);
+               pwc_mbufs = mbufs;
+               PWC_DEBUG_MODULE("Number of image buffers set to %d.\n", pwc_mbufs);
        }
        if (fbufs) {
                if (fbufs < 2 || fbufs > MAX_FRAMES) {
-                       Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
+                       PWC_ERROR("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
                        return -EINVAL;
                }
                default_fbufs = fbufs;
-               Info("Number of frame buffers set to %d.\n", default_fbufs);
+               PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs);
        }
-       if (trace >= 0) {
-               Info("Trace options: 0x%04x\n", trace);
-               pwc_trace = trace;
+#if CONFIG_PWC_DEBUG
+       if (pwc_trace >= 0) {
+               PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
        }
+#endif
        if (compression >= 0) {
                if (compression > 3) {
-                       Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
+                       PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
                        return -EINVAL;
                }
                pwc_preferred_compression = compression;
-               Info("Preferred compression set to %d.\n", pwc_preferred_compression);
+               PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
        }
        if (power_save)
-               Info("Enabling power save on open/close.\n");
+               PWC_DEBUG_MODULE("Enabling power save on open/close.\n");
        if (leds[0] >= 0)
                led_on = leds[0];
        if (leds[1] >= 0)
@@ -2146,14 +1932,14 @@ static int __init usb_pwc_init(void)
                                dot++;
                        /* Few sanity checks */
                        if (*dot != '\0' && dot > colon) {
-                               Err("Malformed camera hint: the colon must be after the dot.\n");
+                               PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
                                return -EINVAL;
                        }
 
                        if (*colon == '\0') {
                                /* No colon */
                                if (*dot != '\0') {
-                                       Err("Malformed camera hint: no colon + device node given.\n");
+                                       PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
                                        return -EINVAL;
                                }
                                else {
@@ -2178,28 +1964,27 @@ static int __init usb_pwc_init(void)
                                        device_hint[i].serial_number[k] = '\0';
                                }
                        }
-#if PWC_DEBUG
-                       Debug("device_hint[%d]:\n", i);
-                       Debug("  type    : %d\n", device_hint[i].type);
-                       Debug("  serial# : %s\n", device_hint[i].serial_number);
-                       Debug("  node    : %d\n", device_hint[i].device_node);
-#endif
+                       PWC_TRACE("device_hint[%d]:\n", i);
+                       PWC_TRACE("  type    : %d\n", device_hint[i].type);
+                       PWC_TRACE("  serial# : %s\n", device_hint[i].serial_number);
+                       PWC_TRACE("  node    : %d\n", device_hint[i].device_node);
                }
                else
                        device_hint[i].type = 0; /* not filled */
        } /* ..for MAX_DEV_HINTS */
 
-       Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
+       PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
        return usb_register(&pwc_driver);
 }
 
 static void __exit usb_pwc_exit(void)
 {
-       Trace(TRACE_MODULE, "Deregistering driver.\n");
+       PWC_DEBUG_MODULE("Deregistering driver.\n");
        usb_deregister(&pwc_driver);
-       Info("Philips webcam module removed.\n");
+       PWC_INFO("Philips webcam module removed.\n");
 }
 
 module_init(usb_pwc_init);
 module_exit(usb_pwc_exit);
 
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index 4c96037f7be5f71b140cd7b188797ab9311fcf06..fec39cc5a9f1c93eec4b71e7459eebff3e10a099 100644 (file)
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -316,3 +316,576 @@ const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
    },
 };
 
+
+/*
+ * Rom table for kiara chips
+ *
+ * 32 roms tables (one for each resolution ?)
+ *  2 tables per roms (one for each passes) (Y, and U&V)
+ * 128 bytes per passes
+ */
+
+const unsigned int KiaraRomTable [8][2][16][8] =
+{
+ { /* version 0 */
+  { /* version 0, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009292,0x00009292,0x00009493,0x000124db},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x0000a493,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x000124db,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 0, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000001,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009292,
+    0x00009492,0x00009493,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000126dc,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 1 */
+  { /* version 1, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 1, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000049,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 2 */
+  { /* version 2, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x0000a49b},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 2, passes 1 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x0000a49b,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 3 */
+  { /* version 3, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 3, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 4 */
+  { /* version 4, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 4, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 5 */
+  { /* version 5, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 5, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x00009252,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 6 */
+  { /* version 6, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 6, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 7 */
+  { /* version 7, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 7, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ }
+};
+
index 12929abbb1f0c54ba1ed1c9e9b20de93b7c02d0b..0bdb22547d866e2f1d0778173350422b9a729125 100644 (file)
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -27,7 +27,7 @@
 #ifndef PWC_KIARA_H
 #define PWC_KIARA_H
 
-#include "pwc-ioctl.h"
+#include <media/pwc-ioctl.h>
 
 struct Kiara_table_entry
 {
@@ -37,8 +37,8 @@ struct Kiara_table_entry
        unsigned char mode[12];         /* precomputed mode settings for cam */
 };
 
-const extern struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4];
-const extern unsigned int KiaraRomTable[8][2][16][8];
+extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4];
+extern const unsigned int KiaraRomTable[8][2][16][8];
 
 #endif
 
index 58fe7974799261ceb45198b4d4e4dc624043a8e4..589c687439da3dc7e992f0758b5eb8616e72448c 100644 (file)
@@ -1,7 +1,7 @@
 /* Linux driver for Philips webcam
    Various miscellaneous functions and tables.
    (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-#include <linux/slab.h>
 
 #include "pwc.h"
 
-struct pwc_coord pwc_image_sizes[PSZ_MAX] =
+const struct pwc_coord pwc_image_sizes[PSZ_MAX] =
 {
-       { 128,  96, 0 },
-       { 160, 120, 0 },
-       { 176, 144, 0 },
-       { 320, 240, 0 },
-       { 352, 288, 0 },
-       { 640, 480, 0 },
+       { 128,  96, 0 }, /* sqcif */
+       { 160, 120, 0 }, /* qsif */
+       { 176, 144, 0 }, /* qcif */
+       { 320, 240, 0 }, /* sif */
+       { 352, 288, 0 }, /* cif */
+       { 640, 480, 0 }, /* vga */
 };
 
 /* x,y -> PSZ_ */
@@ -52,7 +51,7 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
        {
                if (width > pdev->abs_max.x || height > pdev->abs_max.y)
                {
-                       Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
+                       PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
                        return -1;
                }
        }
@@ -60,7 +59,7 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
        {
                if (width > pdev->view_max.x || height > pdev->view_max.y)
                {
-                       Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n");
+                       PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n");
                        return -1;
                }
        }
@@ -81,9 +80,8 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
 /* initialize variables depending on type and decompressor*/
 void pwc_construct(struct pwc_device *pdev)
 {
-       switch(pdev->type) {
-       case 645:
-       case 646:
+       if (DEVICE_USE_CODEC1(pdev->type)) {
+
                pdev->view_min.x = 128;
                pdev->view_min.y =  96;
                pdev->view_max.x = 352;
@@ -95,10 +93,23 @@ void pwc_construct(struct pwc_device *pdev)
                pdev->vendpoint = 4;
                pdev->frame_header_size = 0;
                pdev->frame_trailer_size = 0;
-               break;
-       case 675:
-       case 680:
-       case 690:
+
+       } else if (DEVICE_USE_CODEC3(pdev->type)) {
+
+               pdev->view_min.x = 160;
+               pdev->view_min.y = 120;
+               pdev->view_max.x = 640;
+               pdev->view_max.y = 480;
+               pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+               pdev->abs_max.x = 640;
+               pdev->abs_max.y = 480;
+               pdev->vcinterface = 3;
+               pdev->vendpoint = 5;
+               pdev->frame_header_size = TOUCAM_HEADER_SIZE;
+               pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
+
+       } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ {
+
                pdev->view_min.x = 128;
                pdev->view_min.y =  96;
                /* Anthill bug #38: PWC always reports max size, even without PWCX */
@@ -111,30 +122,12 @@ void pwc_construct(struct pwc_device *pdev)
                pdev->vendpoint = 4;
                pdev->frame_header_size = 0;
                pdev->frame_trailer_size = 0;
-               break;
-       case 720:
-       case 730:
-       case 740:
-       case 750:
-               pdev->view_min.x = 160;
-               pdev->view_min.y = 120;
-               pdev->view_max.x = 640;
-               pdev->view_max.y = 480;
-               pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
-               pdev->abs_max.x = 640;
-               pdev->abs_max.y = 480;
-               pdev->vcinterface = 3;
-               pdev->vendpoint = 5;
-               pdev->frame_header_size = TOUCAM_HEADER_SIZE;
-               pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
-               break;
        }
-       Debug("type = %d\n",pdev->type);
        pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */
        pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
        pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
        /* length of image, in YUV format; always allocate enough memory. */
-       pdev->len_per_image = (pdev->abs_max.x * pdev->abs_max.y * 3) / 2;
+       pdev->len_per_image = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
 }
 
 
index 175250d089cfccedffbf256a8e335249e4c9a2d3..be65bdcd195b4100a438ecc7fd0c541d5578c9d1 100644 (file)
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -314,3 +314,1133 @@ const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
    },
 };
 
+/*
+ * 16 versions:
+ *   2 tables  (one for Y, and one for U&V)
+ *   16 levels of details per tables
+ *   8 blocs
+ */
+
+const unsigned int TimonRomTable [16][2][16][8] =
+{
+ { /* version 0 */
+  { /* version 0, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000001,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000001,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 0, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000001,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000001,
+    0x00000001,0x00000009,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000009,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000009,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 1 */
+  { /* version 1, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 1, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000001,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000049,0x00000249,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 2 */
+  { /* version 2, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 2, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000049,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 3 */
+  { /* version 3, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009292,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 3, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00000049,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009292,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 4 */
+  { /* version 4, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x0000a49b},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 4, passes 1 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x0000a49b,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 5 */
+  { /* version 5, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 5, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x000124db,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009493,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 6 */
+  { /* version 6, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 6, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 7 */
+  { /* version 7, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x0002496e},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0002496d,0x00025bb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 7, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001b724,0x0001b925,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 8 */
+  { /* version 8, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x00024b76,0x00024b77},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x00024b76,0x00025bbf},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001c92d,0x00024b76,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 8, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0002496d,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 9 */
+  { /* version 9, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 9, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 10 */
+  { /* version 10, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0002496d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 10, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x00009493,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009493,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 11 */
+  { /* version 11, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 11, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x00009252,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 12 */
+  { /* version 12, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 12, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 13 */
+  { /* version 13, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 13, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 14 */
+  { /* version 14, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0002496d,0x00024b76,0x00024b77},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 14, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000136e4,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 15 */
+  { /* version 15, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0002496d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x00024b6d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 15, passes 1 */
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009292,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000124db,0x0001b724,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x0001b724,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x0001b724,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x0001b724,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001c924,0x0001b724,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001c924,0x0001b724,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002496d,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ }
+};
index a86b3782a081fa9600f8bc752a8d6b604babe1c2..eef9e2cd4320b6c141ac010225776714611c5c77 100644 (file)
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -42,7 +42,7 @@
 #ifndef PWC_TIMON_H
 #define PWC_TIMON_H
 
-#include "pwc-ioctl.h"
+#include <media/pwc-ioctl.h>
 
 struct Timon_table_entry
 {
@@ -52,8 +52,8 @@ struct Timon_table_entry
        unsigned char mode[13];         /* precomputed mode settings for cam */
 };
 
-const extern struct Timon_table_entry Timon_table[PSZ_MAX][6][4];
-const extern unsigned int TimonRomTable [16][2][16][8];
+extern const struct Timon_table_entry Timon_table[PSZ_MAX][6][4];
+extern const unsigned int TimonRomTable [16][2][16][8];
 
 
 #endif
index b37a89a163f98ad2db2d0340e74dc74c0c993fab..5d82028ef94229acc69f326128acefe08882af7b 100644 (file)
@@ -1,7 +1,7 @@
 /* Linux driver for Philips webcam
    Decompression frontend.
    (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -22,6 +22,8 @@
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+   vim: set ts=8:
 */
 
 #include <asm/current.h>
@@ -29,6 +31,8 @@
 
 #include "pwc.h"
 #include "pwc-uncompress.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
 
 int pwc_decompress(struct pwc_device *pdev)
 {
@@ -40,107 +44,95 @@ int pwc_decompress(struct pwc_device *pdev)
 
        if (pdev == NULL)
                return -EFAULT;
-#if defined(__KERNEL__) && defined(PWC_MAGIC)
-       if (pdev->magic != PWC_MAGIC) {
-               Err("pwc_decompress(): magic failed.\n");
-               return -EFAULT;
-       }
-#endif
 
        fbuf = pdev->read_frame;
        if (fbuf == NULL)
                return -EFAULT;
-       image = pdev->image_ptr[pdev->fill_image];
-       if (!image)
-               return -EFAULT;
+       image  = pdev->image_data;
+       image += pdev->images[pdev->fill_image].offset;
 
        yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
 
        /* Raw format; that's easy... */
        if (pdev->vpalette == VIDEO_PALETTE_RAW)
        {
-               memcpy(image, yuv, pdev->frame_size);
+               struct pwc_raw_frame *raw_frame = image;
+               raw_frame->type = cpu_to_le16(pdev->type);
+               raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength);
+                       /* cmd_buf is always 4 bytes, but sometimes, only the
+                        * first 3 bytes is filled (Nala case). We can
+                        * determine this using the type of the webcam */
+               memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
+               memcpy(raw_frame+1, yuv, pdev->frame_size);
                return 0;
        }
 
        if (pdev->vbandlength == 0) {
-               /* Uncompressed mode. We copy the data into the output buffer,
-                  using the viewport size (which may be larger than the image
-                  size). Unfortunately we have to do a bit of byte stuffing
-                  to get the desired output format/size.
+               /* Uncompressed mode.
+                * We copy the data into the output buffer, using the viewport
+                * size (which may be larger than the image size).
+                * Unfortunately we have to do a bit of byte stuffing to get
+                * the desired output format/size.
+                *
+                * We do some byte shuffling here to go from the
+                * native format to YUV420P.
                 */
-                       /*
-                        * We do some byte shuffling here to go from the
-                        * native format to YUV420P.
-                        */
-                       src = (u16 *)yuv;
-                       n = pdev->view.x * pdev->view.y;
-
-                       /* offset in Y plane */
-                       stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
-                       dsty = (u16 *)(image + stride);
-
-                       /* offsets in U/V planes */
-                       stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
-                       dstu = (u16 *)(image + n +         stride);
-                       dstv = (u16 *)(image + n + n / 4 + stride);
-
-                       /* increment after each line */
-                       stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
-
-                       for (line = 0; line < pdev->image.y; line++) {
-                               for (col = 0; col < pdev->image.x; col += 4) {
-                                       *dsty++ = *src++;
-                                       *dsty++ = *src++;
-                                       if (line & 1)
-                                               *dstv++ = *src++;
-                                       else
-                                               *dstu++ = *src++;
-                               }
-                               dsty += stride;
+               src = (u16 *)yuv;
+               n = pdev->view.x * pdev->view.y;
+
+               /* offset in Y plane */
+               stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
+               dsty = (u16 *)(image + stride);
+
+               /* offsets in U/V planes */
+               stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
+               dstu = (u16 *)(image + n +         stride);
+               dstv = (u16 *)(image + n + n / 4 + stride);
+
+               /* increment after each line */
+               stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
+
+               for (line = 0; line < pdev->image.y; line++) {
+                       for (col = 0; col < pdev->image.x; col += 4) {
+                               *dsty++ = *src++;
+                               *dsty++ = *src++;
                                if (line & 1)
-                                       dstv += (stride >> 1);
+                                       *dstv++ = *src++;
                                else
-                                       dstu += (stride >> 1);
+                                       *dstu++ = *src++;
                        }
+                       dsty += stride;
+                       if (line & 1)
+                               dstv += (stride >> 1);
+                       else
+                               dstu += (stride >> 1);
+               }
+
+               return 0;
        }
-       else {
-               /* Compressed; the decompressor routines will write the data
-                  in planar format immediately.
-                */
-               int flags;
-
-               flags = PWCX_FLAG_PLANAR;
-               if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
-                {
-                  printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n");
-                  flags |= PWCX_FLAG_BAYER;
-                  return -ENXIO; /* No such device or address: missing decompressor */
-                }
-
-#if 0
-               switch (pdev->type)
-                {
-                 case 675:
-                 case 680:
-                 case 690:
-                 case 720:
-                 case 730:
-                 case 740:
-                 case 750:
-                   pwc_dec23_decompress(&pdev->image, &pdev->view,
-                               &pdev->offset, yuv, image, flags,
-                               pdev->decompress_data, pdev->vbandlength);
-                   break;
-                 case 645:
-                 case 646:
-                   /* TODO & FIXME */
-                   return -ENXIO; /* Missing decompressor */
-                   break;
-                }
-#endif
+
+       /*
+        * Compressed;
+        * the decompressor routines will write the data in planar format
+        * immediately.
+        */
+       if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) {
+               PWC_ERROR("Mode Bayer is not supported for now\n");
+               /* flags |= PWCX_FLAG_BAYER; */
+               return -ENXIO; /* No such device or address: missing decompressor */
+       }
+
+       if (DEVICE_USE_CODEC1(pdev->type)) {
+
+               /* TODO & FIXME */
+               PWC_ERROR("This chipset is not supported for now\n");
+               return -ENXIO; /* No such device or address: missing decompressor */
+
+       } else {
+               pwc_dec23_decompress(pdev, yuv, image, PWCX_FLAG_PLANAR);
        }
        return 0;
 }
 
 
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index f75e1b6cbe19d8831c196fc25e3cbce3485ff78e..041227f6524691d5f42971acbe00bf9acdd7df0c 100644 (file)
@@ -1,5 +1,5 @@
 /* (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -32,7 +32,7 @@
 
 #include <linux/config.h>
 
-#include "pwc-ioctl.h"
+#include <media/pwc-ioctl.h>
 
 /* from pwc-dec.h */
 #define PWCX_FLAG_PLANAR        0x0001
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
new file mode 100644 (file)
index 0000000..b7eb3ce
--- /dev/null
@@ -0,0 +1,1202 @@
+/* Linux driver for Philips webcam
+   USB and Video4Linux interface part.
+   (C) 1999-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+
+static struct v4l2_queryctrl pwc_controls[] = {
+       {
+           .id      = V4L2_CID_BRIGHTNESS,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Brightness",
+           .minimum = 0,
+           .maximum = 128,
+           .step    = 1,
+           .default_value = 64,
+       },
+       {
+           .id      = V4L2_CID_CONTRAST,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Contrast",
+           .minimum = 0,
+           .maximum = 64,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_SATURATION,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Saturation",
+           .minimum = -100,
+           .maximum = 100,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_GAMMA,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Gamma",
+           .minimum = 0,
+           .maximum = 32,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_RED_BALANCE,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Red Gain",
+           .minimum = 0,
+           .maximum = 256,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_BLUE_BALANCE,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Blue Gain",
+           .minimum = 0,
+           .maximum = 256,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_AUTO_WHITE_BALANCE,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Auto White Balance",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_EXPOSURE,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Shutter Speed (Exposure)",
+           .minimum = 0,
+           .maximum = 256,
+           .step    = 1,
+           .default_value = 200,
+       },
+       {
+           .id      = V4L2_CID_AUTOGAIN,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Auto Gain Enabled",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 1,
+       },
+       {
+           .id      = V4L2_CID_GAIN,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Gain Level",
+           .minimum = 0,
+           .maximum = 256,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_SAVE_USER,
+           .type    = V4L2_CTRL_TYPE_BUTTON,
+           .name    = "Save User Settings",
+           .minimum = 0,
+           .maximum = 0,
+           .step    = 0,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_RESTORE_USER,
+           .type    = V4L2_CTRL_TYPE_BUTTON,
+           .name    = "Restore User Settings",
+           .minimum = 0,
+           .maximum = 0,
+           .step    = 0,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_RESTORE_FACTORY,
+           .type    = V4L2_CTRL_TYPE_BUTTON,
+           .name    = "Restore Factory Settings",
+           .minimum = 0,
+           .maximum = 0,
+           .step    = 0,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_COLOUR_MODE,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Colour mode",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_AUTOCONTOUR,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Auto contour",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_CONTOUR,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Contour",
+           .minimum = 0,
+           .maximum = 63,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_BACKLIGHT,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Backlight compensation",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+         .id      = V4L2_CID_PRIVATE_FLICKERLESS,
+           .type    = V4L2_CTRL_TYPE_BOOLEAN,
+           .name    = "Flickerless",
+           .minimum = 0,
+           .maximum = 1,
+           .step    = 1,
+           .default_value = 0,
+       },
+       {
+           .id      = V4L2_CID_PRIVATE_NOISE_REDUCTION,
+           .type    = V4L2_CTRL_TYPE_INTEGER,
+           .name    = "Noise reduction",
+           .minimum = 0,
+           .maximum = 3,
+           .step    = 1,
+           .default_value = 0,
+       },
+};
+
+
+static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f)
+{
+       memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+       f->fmt.pix.width        = pdev->view.x;
+       f->fmt.pix.height       = pdev->view.y;
+       f->fmt.pix.field        = V4L2_FIELD_NONE;
+       if (pdev->vpalette == VIDEO_PALETTE_YUV420P) {
+               f->fmt.pix.pixelformat  = V4L2_PIX_FMT_YUV420;
+               f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;
+               f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+       } else {
+               /* vbandlength contains 4 lines ...  */
+               f->fmt.pix.bytesperline = pdev->vbandlength/4;
+               f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame);
+               if (DEVICE_USE_CODEC1(pdev->type))
+                       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC1;
+               else
+                       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC2;
+       }
+       PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
+                       "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
+                       f->fmt.pix.width,
+                       f->fmt.pix.height,
+                       f->fmt.pix.bytesperline,
+                       f->fmt.pix.sizeimage,
+                       (f->fmt.pix.pixelformat)&255,
+                       (f->fmt.pix.pixelformat>>8)&255,
+                       (f->fmt.pix.pixelformat>>16)&255,
+                       (f->fmt.pix.pixelformat>>24)&255);
+}
+
+/* ioctl(VIDIOC_TRY_FMT) */
+static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+{
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+               return -EINVAL;
+       }
+
+       switch (f->fmt.pix.pixelformat) {
+               case V4L2_PIX_FMT_YUV420:
+                       break;
+               case V4L2_PIX_FMT_PWC1:
+                       if (DEVICE_USE_CODEC23(pdev->type)) {
+                               PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n");
+                               return -EINVAL;
+                       }
+                       break;
+               case V4L2_PIX_FMT_PWC2:
+                       if (DEVICE_USE_CODEC1(pdev->type)) {
+                               PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n");
+                               return -EINVAL;
+                       }
+                       break;
+               default:
+                       PWC_DEBUG_IOCTL("Unsupported pixel format\n");
+                       return -EINVAL;
+
+       }
+
+       if (f->fmt.pix.width > pdev->view_max.x)
+               f->fmt.pix.width = pdev->view_max.x;
+       else if (f->fmt.pix.width < pdev->view_min.x)
+               f->fmt.pix.width = pdev->view_min.x;
+
+       if (f->fmt.pix.height > pdev->view_max.y)
+               f->fmt.pix.height = pdev->view_max.y;
+       else if (f->fmt.pix.height < pdev->view_min.y)
+               f->fmt.pix.height = pdev->view_min.y;
+
+       return 0;
+}
+
+/* ioctl(VIDIOC_SET_FMT) */
+static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+{
+       int ret, fps, snapshot, compression, pixelformat;
+
+       ret = pwc_vidioc_try_fmt(pdev, f);
+       if (ret<0)
+               return ret;
+
+       pixelformat = f->fmt.pix.pixelformat;
+       compression = pdev->vcompression;
+       snapshot = 0;
+       fps = pdev->vframes;
+       if (f->fmt.pix.priv) {
+               compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT;
+               snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT);
+               fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+               if (fps == 0)
+                       fps = pdev->vframes;
+       }
+
+       if (pixelformat == V4L2_PIX_FMT_YUV420)
+               pdev->vpalette = VIDEO_PALETTE_YUV420P;
+       else
+               pdev->vpalette = VIDEO_PALETTE_RAW;
+
+       PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d "
+                       "compression=%d snapshot=%d format=%c%c%c%c\n",
+                       f->fmt.pix.width, f->fmt.pix.height, fps,
+                       compression, snapshot,
+                       (pixelformat)&255,
+                       (pixelformat>>8)&255,
+                       (pixelformat>>16)&255,
+                       (pixelformat>>24)&255);
+
+       ret = pwc_try_video_mode(pdev,
+                                f->fmt.pix.width,
+                                f->fmt.pix.height,
+                                fps,
+                                compression,
+                                snapshot);
+
+       PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret);
+
+       if (ret)
+               return ret;
+
+       pwc_vidioc_fill_fmt(pdev, f);
+
+       return 0;
+
+}
+
+int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+                      unsigned int cmd, void *arg)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct pwc_device *pdev;
+       DECLARE_WAITQUEUE(wait, current);
+
+       if (vdev == NULL)
+               return -EFAULT;
+       pdev = vdev->priv;
+       if (pdev == NULL)
+               return -EFAULT;
+
+#if CONFIG_PWC_DEBUG
+       if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
+               v4l_printk_ioctl(cmd);
+#endif
+
+
+       switch (cmd) {
+               /* Query cabapilities */
+               case VIDIOCGCAP:
+               {
+                       struct video_capability *caps = arg;
+
+                       strcpy(caps->name, vdev->name);
+                       caps->type = VID_TYPE_CAPTURE;
+                       caps->channels = 1;
+                       caps->audios = 1;
+                       caps->minwidth  = pdev->view_min.x;
+                       caps->minheight = pdev->view_min.y;
+                       caps->maxwidth  = pdev->view_max.x;
+                       caps->maxheight = pdev->view_max.y;
+                       break;
+               }
+
+               /* Channel functions (simulate 1 channel) */
+               case VIDIOCGCHAN:
+               {
+                       struct video_channel *v = arg;
+
+                       if (v->channel != 0)
+                               return -EINVAL;
+                       v->flags = 0;
+                       v->tuners = 0;
+                       v->type = VIDEO_TYPE_CAMERA;
+                       strcpy(v->name, "Webcam");
+                       return 0;
+               }
+
+               case VIDIOCSCHAN:
+               {
+                       /* The spec says the argument is an integer, but
+                          the bttv driver uses a video_channel arg, which
+                          makes sense becasue it also has the norm flag.
+                        */
+                       struct video_channel *v = arg;
+                       if (v->channel != 0)
+                               return -EINVAL;
+                       return 0;
+               }
+
+
+               /* Picture functions; contrast etc. */
+               case VIDIOCGPICT:
+               {
+                       struct video_picture *p = arg;
+                       int val;
+
+                       val = pwc_get_brightness(pdev);
+                       if (val >= 0)
+                               p->brightness = (val<<9);
+                       else
+                               p->brightness = 0xffff;
+                       val = pwc_get_contrast(pdev);
+                       if (val >= 0)
+                               p->contrast = (val<<10);
+                       else
+                               p->contrast = 0xffff;
+                       /* Gamma, Whiteness, what's the difference? :) */
+                       val = pwc_get_gamma(pdev);
+                       if (val >= 0)
+                               p->whiteness = (val<<11);
+                       else
+                               p->whiteness = 0xffff;
+                       if (pwc_get_saturation(pdev, &val)<0)
+                               p->colour = 0xffff;
+                       else
+                               p->colour = 32768 + val * 327;
+                       p->depth = 24;
+                       p->palette = pdev->vpalette;
+                       p->hue = 0xFFFF; /* N/A */
+                       break;
+               }
+
+               case VIDIOCSPICT:
+               {
+                       struct video_picture *p = arg;
+                       /*
+                        *      FIXME:  Suppose we are mid read
+                               ANSWER: No problem: the firmware of the camera
+                                       can handle brightness/contrast/etc
+                                       changes at _any_ time, and the palette
+                                       is used exactly once in the uncompress
+                                       routine.
+                        */
+                       pwc_set_brightness(pdev, p->brightness);
+                       pwc_set_contrast(pdev, p->contrast);
+                       pwc_set_gamma(pdev, p->whiteness);
+                       pwc_set_saturation(pdev, (p->colour-32768)/327);
+                       if (p->palette && p->palette != pdev->vpalette) {
+                               switch (p->palette) {
+                                       case VIDEO_PALETTE_YUV420P:
+                                       case VIDEO_PALETTE_RAW:
+                                               pdev->vpalette = p->palette;
+                                               return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+                                               break;
+                                       default:
+                                               return -EINVAL;
+                                               break;
+                               }
+                       }
+                       break;
+               }
+
+               /* Window/size parameters */
+               case VIDIOCGWIN:
+               {
+                       struct video_window *vw = arg;
+
+                       vw->x = 0;
+                       vw->y = 0;
+                       vw->width = pdev->view.x;
+                       vw->height = pdev->view.y;
+                       vw->chromakey = 0;
+                       vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
+                                  (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
+                       break;
+               }
+
+               case VIDIOCSWIN:
+               {
+                       struct video_window *vw = arg;
+                       int fps, snapshot, ret;
+
+                       fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+                       snapshot = vw->flags & PWC_FPS_SNAPSHOT;
+                       if (fps == 0)
+                               fps = pdev->vframes;
+                       if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
+                               return 0;
+                       ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
+                       if (ret)
+                               return ret;
+                       break;
+               }
+
+               /* We don't have overlay support (yet) */
+               case VIDIOCGFBUF:
+               {
+                       struct video_buffer *vb = arg;
+
+                       memset(vb,0,sizeof(*vb));
+                       break;
+               }
+
+               /* mmap() functions */
+               case VIDIOCGMBUF:
+               {
+                       /* Tell the user program how much memory is needed for a mmap() */
+                       struct video_mbuf *vm = arg;
+                       int i;
+
+                       memset(vm, 0, sizeof(*vm));
+                       vm->size = pwc_mbufs * pdev->len_per_image;
+                       vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */
+                       for (i = 0; i < pwc_mbufs; i++)
+                               vm->offsets[i] = i * pdev->len_per_image;
+                       break;
+               }
+
+               case VIDIOCMCAPTURE:
+               {
+                       /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
+                       struct video_mmap *vm = arg;
+
+                       PWC_DEBUG_READ("VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
+                       if (vm->frame < 0 || vm->frame >= pwc_mbufs)
+                               return -EINVAL;
+
+                       /* xawtv is nasty. It probes the available palettes
+                          by setting a very small image size and trying
+                          various palettes... The driver doesn't support
+                          such small images, so I'm working around it.
+                        */
+                       if (vm->format)
+                       {
+                               switch (vm->format)
+                               {
+                                       case VIDEO_PALETTE_YUV420P:
+                                       case VIDEO_PALETTE_RAW:
+                                               break;
+                                       default:
+                                               return -EINVAL;
+                                               break;
+                               }
+                       }
+
+                       if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
+                           (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
+                               int ret;
+
+                               PWC_DEBUG_OPEN("VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
+                               ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+                               if (ret)
+                                       return ret;
+                       } /* ... size mismatch */
+
+                       /* FIXME: should we lock here? */
+                       if (pdev->image_used[vm->frame])
+                               return -EBUSY;  /* buffer wasn't available. Bummer */
+                       pdev->image_used[vm->frame] = 1;
+
+                       /* Okay, we're done here. In the SYNC call we wait until a
+                          frame comes available, then expand image into the given
+                          buffer.
+                          In contrast to the CPiA cam the Philips cams deliver a
+                          constant stream, almost like a grabber card. Also,
+                          we have separate buffers for the rawdata and the image,
+                          meaning we can nearly always expand into the requested buffer.
+                        */
+                       PWC_DEBUG_READ("VIDIOCMCAPTURE done.\n");
+                       break;
+               }
+
+               case VIDIOCSYNC:
+               {
+                       /* The doc says: "Whenever a buffer is used it should
+                          call VIDIOCSYNC to free this frame up and continue."
+
+                          The only odd thing about this whole procedure is
+                          that MCAPTURE flags the buffer as "in use", and
+                          SYNC immediately unmarks it, while it isn't
+                          after SYNC that you know that the buffer actually
+                          got filled! So you better not start a CAPTURE in
+                          the same frame immediately (use double buffering).
+                          This is not a problem for this cam, since it has
+                          extra intermediate buffers, but a hardware
+                          grabber card will then overwrite the buffer
+                          you're working on.
+                        */
+                       int *mbuf = arg;
+                       int ret;
+
+                       PWC_DEBUG_READ("VIDIOCSYNC called (%d).\n", *mbuf);
+
+                       /* bounds check */
+                       if (*mbuf < 0 || *mbuf >= pwc_mbufs)
+                               return -EINVAL;
+                       /* check if this buffer was requested anyway */
+                       if (pdev->image_used[*mbuf] == 0)
+                               return -EINVAL;
+
+                       /* Add ourselves to the frame wait-queue.
+
+                          FIXME: needs auditing for safety.
+                          QUESTION: In what respect? I think that using the
+                                    frameq is safe now.
+                        */
+                       add_wait_queue(&pdev->frameq, &wait);
+                       while (pdev->full_frames == NULL) {
+                               /* Check for unplugged/etc. here */
+                               if (pdev->error_status) {
+                                       remove_wait_queue(&pdev->frameq, &wait);
+                                       set_current_state(TASK_RUNNING);
+                                       return -pdev->error_status;
+                               }
+
+                               if (signal_pending(current)) {
+                                       remove_wait_queue(&pdev->frameq, &wait);
+                                       set_current_state(TASK_RUNNING);
+                                       return -ERESTARTSYS;
+                               }
+                               schedule();
+                               set_current_state(TASK_INTERRUPTIBLE);
+                       }
+                       remove_wait_queue(&pdev->frameq, &wait);
+                       set_current_state(TASK_RUNNING);
+
+                       /* The frame is ready. Expand in the image buffer
+                          requested by the user. I don't care if you
+                          mmap() 5 buffers and request data in this order:
+                          buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
+                          Grabber hardware may not be so forgiving.
+                        */
+                       PWC_DEBUG_READ("VIDIOCSYNC: frame ready.\n");
+                       pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
+                       /* Decompress, etc */
+                       ret = pwc_handle_frame(pdev);
+                       pdev->image_used[*mbuf] = 0;
+                       if (ret)
+                               return -EFAULT;
+                       break;
+               }
+
+               case VIDIOCGAUDIO:
+               {
+                       struct video_audio *v = arg;
+
+                       strcpy(v->name, "Microphone");
+                       v->audio = -1; /* unknown audio minor */
+                       v->flags = 0;
+                       v->mode = VIDEO_SOUND_MONO;
+                       v->volume = 0;
+                       v->bass = 0;
+                       v->treble = 0;
+                       v->balance = 0x8000;
+                       v->step = 1;
+                       break;
+               }
+
+               case VIDIOCSAUDIO:
+               {
+                       /* Dummy: nothing can be set */
+                       break;
+               }
+
+               case VIDIOCGUNIT:
+               {
+                       struct video_unit *vu = arg;
+
+                       vu->video = pdev->vdev->minor & 0x3F;
+                       vu->audio = -1; /* not known yet */
+                       vu->vbi = -1;
+                       vu->radio = -1;
+                       vu->teletext = -1;
+                       break;
+               }
+
+               /* V4L2 Layer */
+               case VIDIOC_QUERYCAP:
+               {
+                   struct v4l2_capability *cap = arg;
+
+                   PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application "\
+                                      "try to use the v4l2 layer\n");
+                   strcpy(cap->driver,PWC_NAME);
+                   strlcpy(cap->card, vdev->name, sizeof(cap->card));
+                   usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info));
+                   cap->version = PWC_VERSION_CODE;
+                   cap->capabilities =
+                       V4L2_CAP_VIDEO_CAPTURE  |
+                       V4L2_CAP_STREAMING      |
+                       V4L2_CAP_READWRITE;
+                   return 0;
+               }
+
+               case VIDIOC_ENUMINPUT:
+               {
+                   struct v4l2_input *i = arg;
+
+                   if ( i->index )     /* Only one INPUT is supported */
+                         return -EINVAL;
+
+                   memset(i, 0, sizeof(struct v4l2_input));
+                   strcpy(i->name, "usb");
+                   return 0;
+               }
+
+               case VIDIOC_G_INPUT:
+               {
+                   int *i = arg;
+                   *i = 0;     /* Only one INPUT is supported */
+                   return 0;
+               }
+               case VIDIOC_S_INPUT:
+               {
+                       int *i = arg;
+
+                       if ( *i ) {     /* Only one INPUT is supported */
+                               PWC_DEBUG_IOCTL("Only one input source is"\
+                                       " supported with this webcam.\n");
+                               return -EINVAL;
+                       }
+                       return 0;
+               }
+
+               /* TODO: */
+               case VIDIOC_QUERYCTRL:
+               {
+                       struct v4l2_queryctrl *c = arg;
+                       int i;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id);
+                       for (i=0; i<sizeof(pwc_controls)/sizeof(struct v4l2_queryctrl); i++) {
+                               if (pwc_controls[i].id == c->id) {
+                                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
+                                       memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl));
+                                       return 0;
+                               }
+                       }
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n");
+
+                       return -EINVAL;
+               }
+               case VIDIOC_G_CTRL:
+               {
+                       struct v4l2_control *c = arg;
+                       int ret;
+
+                       switch (c->id)
+                       {
+                               case V4L2_CID_BRIGHTNESS:
+                                       c->value = pwc_get_brightness(pdev);
+                                       if (c->value<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_CONTRAST:
+                                       c->value = pwc_get_contrast(pdev);
+                                       if (c->value<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_SATURATION:
+                                       ret = pwc_get_saturation(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_GAMMA:
+                                       c->value = pwc_get_gamma(pdev);
+                                       if (c->value<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_RED_BALANCE:
+                                       ret = pwc_get_red_gain(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       c->value >>= 8;
+                                       return 0;
+                               case V4L2_CID_BLUE_BALANCE:
+                                       ret = pwc_get_blue_gain(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       c->value >>= 8;
+                                       return 0;
+                               case V4L2_CID_AUTO_WHITE_BALANCE:
+                                       ret = pwc_get_awb(pdev);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       c->value = (ret == PWC_WB_MANUAL)?0:1;
+                                       return 0;
+                               case V4L2_CID_GAIN:
+                                       ret = pwc_get_agc(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       c->value >>= 8;
+                                       return 0;
+                               case V4L2_CID_AUTOGAIN:
+                                       ret = pwc_get_agc(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       c->value = (c->value < 0)?1:0;
+                                       return 0;
+                               case V4L2_CID_EXPOSURE:
+                                       ret = pwc_get_shutter_speed(pdev, &c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_COLOUR_MODE:
+                                       ret = pwc_get_colour_mode(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_AUTOCONTOUR:
+                                       ret = pwc_get_contour(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       c->value=(c->value == -1?1:0);
+                                       return 0;
+                               case V4L2_CID_PRIVATE_CONTOUR:
+                                       ret = pwc_get_contour(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       c->value >>= 10;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_BACKLIGHT:
+                                       ret = pwc_get_backlight(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_FLICKERLESS:
+                                       ret = pwc_get_flicker(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       c->value=(c->value?1:0);
+                                       return 0;
+                               case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+                                       ret = pwc_get_dynamic_noise(pdev, &c->value);
+                                       if (ret < 0)
+                                               return -EINVAL;
+                                       return 0;
+
+                               case V4L2_CID_PRIVATE_SAVE_USER:
+                               case V4L2_CID_PRIVATE_RESTORE_USER:
+                               case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+                                       return -EINVAL;
+                       }
+                       return -EINVAL;
+               }
+               case VIDIOC_S_CTRL:
+               {
+                       struct v4l2_control *c = arg;
+                       int ret;
+
+                       switch (c->id)
+                       {
+                               case V4L2_CID_BRIGHTNESS:
+                                       c->value <<= 9;
+                                       ret = pwc_set_brightness(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_CONTRAST:
+                                       c->value <<= 10;
+                                       ret = pwc_set_contrast(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_SATURATION:
+                                       ret = pwc_set_saturation(pdev, c->value);
+                                       if (ret<0)
+                                         return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_GAMMA:
+                                       c->value <<= 11;
+                                       ret = pwc_set_gamma(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_RED_BALANCE:
+                                       c->value <<= 8;
+                                       ret = pwc_set_red_gain(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_BLUE_BALANCE:
+                                       c->value <<= 8;
+                                       ret = pwc_set_blue_gain(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_AUTO_WHITE_BALANCE:
+                                       c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO;
+                                       ret = pwc_set_awb(pdev, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_EXPOSURE:
+                                       c->value <<= 8;
+                                       ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_AUTOGAIN:
+                                       /* autogain off means nothing without a gain */
+                                       if (c->value == 0)
+                                               return 0;
+                                       ret = pwc_set_agc(pdev, c->value, 0);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_GAIN:
+                                       c->value <<= 8;
+                                       ret = pwc_set_agc(pdev, 0, c->value);
+                                       if (ret<0)
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_SAVE_USER:
+                                       if (pwc_save_user(pdev))
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_RESTORE_USER:
+                                       if (pwc_restore_user(pdev))
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+                                       if (pwc_restore_factory(pdev))
+                                               return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_COLOUR_MODE:
+                                       ret = pwc_set_colour_mode(pdev, c->value);
+                                       if (ret < 0)
+                                         return -EINVAL;
+                                       return 0;
+                               case V4L2_CID_PRIVATE_AUTOCONTOUR:
+                                 c->value=(c->value == 1)?-1:0;
+                                 ret = pwc_set_contour(pdev, c->value);
+                                 if (ret < 0)
+                                   return -EINVAL;
+                                 return 0;
+                               case V4L2_CID_PRIVATE_CONTOUR:
+                                 c->value <<= 10;
+                                 ret = pwc_set_contour(pdev, c->value);
+                                 if (ret < 0)
+                                   return -EINVAL;
+                                 return 0;
+                               case V4L2_CID_PRIVATE_BACKLIGHT:
+                                 ret = pwc_set_backlight(pdev, c->value);
+                                 if (ret < 0)
+                                   return -EINVAL;
+                                 return 0;
+                               case V4L2_CID_PRIVATE_FLICKERLESS:
+                                 ret = pwc_set_flicker(pdev, c->value);
+                                 if (ret < 0)
+                                   return -EINVAL;
+                               case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+                                 ret = pwc_set_dynamic_noise(pdev, c->value);
+                                 if (ret < 0)
+                                   return -EINVAL;
+                                 return 0;
+
+                       }
+                       return -EINVAL;
+               }
+
+               case VIDIOC_ENUM_FMT:
+               {
+                       struct v4l2_fmtdesc *f = arg;
+                       int index;
+
+                       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                             return -EINVAL;
+
+                       /* We only support two format: the raw format, and YUV */
+                       index = f->index;
+                       memset(f,0,sizeof(struct v4l2_fmtdesc));
+                       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                       f->index = index;
+                       switch(index)
+                       {
+                               case 0:
+                                       /* RAW format */
+                                       f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2;
+                                       f->flags = V4L2_FMT_FLAG_COMPRESSED;
+                                       strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description));
+                                       break;
+                               case 1:
+                                       f->pixelformat = V4L2_PIX_FMT_YUV420;
+                                       strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description));
+                                       break;
+                               default:
+                                       return -EINVAL;
+                       }
+                       return 0;
+               }
+
+               case VIDIOC_G_FMT:
+               {
+                       struct v4l2_format *f = arg;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y);
+                       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                             return -EINVAL;
+
+                       pwc_vidioc_fill_fmt(pdev, f);
+
+                       return 0;
+               }
+
+               case VIDIOC_TRY_FMT:
+                       return pwc_vidioc_try_fmt(pdev, arg);
+
+               case VIDIOC_S_FMT:
+                       return pwc_vidioc_set_fmt(pdev, arg);
+
+               case VIDIOC_G_STD:
+               {
+                       v4l2_std_id *std = arg;
+                       *std = V4L2_STD_UNKNOWN;
+                       return 0;
+               }
+
+               case VIDIOC_S_STD:
+               {
+                       v4l2_std_id *std = arg;
+                       if (*std != V4L2_STD_UNKNOWN)
+                               return -EINVAL;
+                       return 0;
+               }
+
+               case VIDIOC_ENUMSTD:
+               {
+                       struct v4l2_standard *std = arg;
+                       if (std->index != 0)
+                               return -EINVAL;
+                       std->id = V4L2_STD_UNKNOWN;
+                       strncpy(std->name, "webcam", sizeof(std->name));
+                       return 0;
+               }
+
+               case VIDIOC_REQBUFS:
+               {
+                       struct v4l2_requestbuffers *rb = arg;
+                       int nbuffers;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count);
+                       if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               return -EINVAL;
+                       if (rb->memory != V4L2_MEMORY_MMAP)
+                               return -EINVAL;
+
+                       nbuffers = rb->count;
+                       if (nbuffers < 2)
+                               nbuffers = 2;
+                       else if (nbuffers > pwc_mbufs)
+                               nbuffers = pwc_mbufs;
+                       /* Force to use our # of buffers */
+                       rb->count = pwc_mbufs;
+                       return 0;
+               }
+
+               case VIDIOC_QUERYBUF:
+               {
+                       struct v4l2_buffer *buf = arg;
+                       int index;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index);
+                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n");
+                               return -EINVAL;
+                       }
+                       if (buf->memory != V4L2_MEMORY_MMAP) {
+                               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad memory type\n");
+                               return -EINVAL;
+                       }
+                       index = buf->index;
+                       if (index < 0 || index >= pwc_mbufs) {
+                               PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
+                               return -EINVAL;
+                       }
+
+                       memset(buf, 0, sizeof(struct v4l2_buffer));
+                       buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                       buf->index = index;
+                       buf->m.offset = index * pdev->len_per_image;
+                       if (pdev->vpalette == VIDEO_PALETTE_RAW)
+                               buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+                       else
+                               buf->bytesused = pdev->view.size;
+                       buf->field = V4L2_FIELD_NONE;
+                       buf->memory = V4L2_MEMORY_MMAP;
+                       //buf->flags = V4L2_BUF_FLAG_MAPPED;
+                       buf->length = pdev->len_per_image;
+
+                       PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index);
+                       PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset);
+                       PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused);
+
+                       return 0;
+               }
+
+               case VIDIOC_QBUF:
+               {
+                       struct v4l2_buffer *buf = arg;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index);
+                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               return -EINVAL;
+                       if (buf->memory != V4L2_MEMORY_MMAP)
+                               return -EINVAL;
+                       if (buf->index < 0 || buf->index >= pwc_mbufs)
+                               return -EINVAL;
+
+                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
+                       buf->flags &= ~V4L2_BUF_FLAG_DONE;
+
+                       return 0;
+               }
+
+               case VIDIOC_DQBUF:
+               {
+                       struct v4l2_buffer *buf = arg;
+                       int ret;
+
+                       PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
+
+                       if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                               return -EINVAL;
+
+                       /* Add ourselves to the frame wait-queue.
+
+                          FIXME: needs auditing for safety.
+                          QUESTION: In what respect? I think that using the
+                                    frameq is safe now.
+                        */
+                       add_wait_queue(&pdev->frameq, &wait);
+                       while (pdev->full_frames == NULL) {
+                               if (pdev->error_status) {
+                                       remove_wait_queue(&pdev->frameq, &wait);
+                                       set_current_state(TASK_RUNNING);
+                                       return -pdev->error_status;
+                               }
+
+                               if (signal_pending(current)) {
+                                       remove_wait_queue(&pdev->frameq, &wait);
+                                       set_current_state(TASK_RUNNING);
+                                       return -ERESTARTSYS;
+                               }
+                               schedule();
+                               set_current_state(TASK_INTERRUPTIBLE);
+                       }
+                       remove_wait_queue(&pdev->frameq, &wait);
+                       set_current_state(TASK_RUNNING);
+
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n");
+                       /* Decompress data in pdev->images[pdev->fill_image] */
+                       ret = pwc_handle_frame(pdev);
+                       if (ret)
+                               return -EFAULT;
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
+
+                       buf->index = pdev->fill_image;
+                       if (pdev->vpalette == VIDEO_PALETTE_RAW)
+                               buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+                       else
+                               buf->bytesused = pdev->view.size;
+                       buf->flags = V4L2_BUF_FLAG_MAPPED;
+                       buf->field = V4L2_FIELD_NONE;
+                       do_gettimeofday(&buf->timestamp);
+                       buf->sequence = 0;
+                       buf->memory = V4L2_MEMORY_MMAP;
+                       buf->m.offset = pdev->fill_image * pdev->len_per_image;
+                       buf->length = buf->bytesused;
+                       pwc_next_image(pdev);
+
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index);
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n",buf->length);
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset);
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused);
+                       PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n");
+                       return 0;
+
+               }
+
+               case VIDIOC_STREAMON:
+               {
+                       /* WARNING: pwc_try_video_mode() called pwc_isoc_init */
+                       pwc_isoc_init(pdev);
+                       return 0;
+               }
+
+               case VIDIOC_STREAMOFF:
+               {
+                       pwc_isoc_cleanup(pdev);
+                       return 0;
+               }
+
+               default:
+                       return pwc_ioctl(pdev, cmd, arg);
+       } /* ..switch */
+       return 0;
+}
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index 1b0ee0ced0ed385e87a660fb8a41a3bc9818d8fe..629f79e44fb6ac940d4dad4ccd4aad11988bcd9b 100644 (file)
@@ -1,5 +1,5 @@
 /* (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/spinlock.h>
-#include <linux/videodev.h>
 #include <linux/wait.h>
 #include <linux/smp_lock.h>
+#include <linux/version.h>
 #include <asm/semaphore.h>
 #include <asm/errno.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
 
 #include "pwc-uncompress.h"
-#include "pwc-ioctl.h"
-
-/* Defines and structures for the Philips webcam */
-/* Used for checking memory corruption/pointer validation */
-#define PWC_MAGIC 0x89DC10ABUL
-#undef PWC_MAGIC
+#include <media/pwc-ioctl.h>
 
 /* Turn some debugging options on/off */
-#define PWC_DEBUG 0
+#ifndef CONFIG_PWC_DEBUG
+#define CONFIG_PWC_DEBUG 1
+#endif
+
+/* Version block */
+#define PWC_MAJOR      10
+#define PWC_MINOR      0
+#define PWC_EXTRAMINOR 12
+#define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR)
+#define PWC_VERSION    "10.0.12"
+#define PWC_NAME       "pwc"
+#define PFX            PWC_NAME ": "
+
 
 /* Trace certain actions in the driver */
-#define TRACE_MODULE   0x0001
-#define TRACE_PROBE    0x0002
-#define TRACE_OPEN     0x0004
-#define TRACE_READ     0x0008
-#define TRACE_MEMORY   0x0010
-#define TRACE_FLOW     0x0020
-#define TRACE_SIZE     0x0040
-#define TRACE_PWCX     0x0080
-#define TRACE_SEQUENCE 0x1000
-
-#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A)
-#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A)
-#define Info(A...)  printk(KERN_INFO  PWC_NAME " " A)
-#define Err(A...)   printk(KERN_ERR   PWC_NAME " " A)
+#define PWC_DEBUG_LEVEL_MODULE (1<<0)
+#define PWC_DEBUG_LEVEL_PROBE  (1<<1)
+#define PWC_DEBUG_LEVEL_OPEN   (1<<2)
+#define PWC_DEBUG_LEVEL_READ   (1<<3)
+#define PWC_DEBUG_LEVEL_MEMORY (1<<4)
+#define PWC_DEBUG_LEVEL_FLOW   (1<<5)
+#define PWC_DEBUG_LEVEL_SIZE   (1<<6)
+#define PWC_DEBUG_LEVEL_IOCTL  (1<<7)
+#define PWC_DEBUG_LEVEL_TRACE  (1<<8)
+
+#define PWC_DEBUG_MODULE(fmt, args...) PWC_DEBUG(MODULE, fmt, ##args)
+#define PWC_DEBUG_PROBE(fmt, args...) PWC_DEBUG(PROBE, fmt, ##args)
+#define PWC_DEBUG_OPEN(fmt, args...) PWC_DEBUG(OPEN, fmt, ##args)
+#define PWC_DEBUG_READ(fmt, args...) PWC_DEBUG(READ, fmt, ##args)
+#define PWC_DEBUG_MEMORY(fmt, args...) PWC_DEBUG(MEMORY, fmt, ##args)
+#define PWC_DEBUG_FLOW(fmt, args...) PWC_DEBUG(FLOW, fmt, ##args)
+#define PWC_DEBUG_SIZE(fmt, args...) PWC_DEBUG(SIZE, fmt, ##args)
+#define PWC_DEBUG_IOCTL(fmt, args...) PWC_DEBUG(IOCTL, fmt, ##args)
+#define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
+
+
+#if CONFIG_PWC_DEBUG
+
+#define PWC_DEBUG_LEVEL        (PWC_DEBUG_LEVEL_MODULE)
+
+#define PWC_DEBUG(level, fmt, args...) do {\
+         if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \
+            printk(KERN_DEBUG PFX fmt, ##args); \
+         } while(0)
+
+#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
+#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
+#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
+#define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
+
+#else /* if ! CONFIG_PWC_DEBUG */
+
+#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
+#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
+#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
+#define PWC_TRACE(fmt, args...) do { } while(0)
+#define PWC_DEBUG(level, fmt, args...) do { } while(0)
+
+#define pwc_trace 0
 
+#endif
 
 /* Defines for ToUCam cameras */
 #define TOUCAM_HEADER_SIZE             8
 #define TOUCAM_TRAILER_SIZE            4
 
 #define FEATURE_MOTOR_PANTILT          0x0001
-
-/* Version block */
-#define PWC_MAJOR      9
-#define PWC_MINOR      0
-#define PWC_VERSION    "9.0.2-unofficial"
-#define PWC_NAME       "pwc"
+#define FEATURE_CODEC1                 0x0002
+#define FEATURE_CODEC2                 0x0004
 
 /* Turn certain features on/off */
 #define PWC_INT_PIPE 0
 /* Absolute maximum number of buffers available for mmap() */
 #define MAX_IMAGES             10
 
+/* Some macros to quickly find the type of a webcam */
+#define DEVICE_USE_CODEC1(x) ((x)<675)
+#define DEVICE_USE_CODEC2(x) ((x)>=675 && (x)<700)
+#define DEVICE_USE_CODEC3(x) ((x)>=700)
+#define DEVICE_USE_CODEC23(x) ((x)>=675)
+
+
+#ifndef V4L2_PIX_FMT_PWC1
+#define V4L2_PIX_FMT_PWC1      v4l2_fourcc('P','W','C','1')
+#define V4L2_PIX_FMT_PWC2      v4l2_fourcc('P','W','C','2')
+#endif
+
 /* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
 struct pwc_iso_buf
 {
@@ -110,17 +158,19 @@ struct pwc_frame_buf
    void *data;
    volatile int filled;                /* number of bytes filled */
    struct pwc_frame_buf *next; /* list */
-#if PWC_DEBUG
-   int sequence;               /* Sequence number */
-#endif
+};
+
+/* additionnal informations used when dealing image between kernel and userland */
+struct pwc_imgbuf
+{
+       unsigned long offset;   /* offset of this buffer in the big array of image_data */
+       int   vma_use_count;    /* count the number of time this memory is mapped */
 };
 
 struct pwc_device
 {
    struct video_device *vdev;
-#ifdef PWC_MAGIC
-   int magic;
-#endif
+
    /* Pointer to our usb_device */
    struct usb_device *udev;
 
@@ -177,12 +227,8 @@ struct pwc_device
    int frame_size;
    int frame_total_size; /* including header & trailer */
    int drop_frames;
-#if PWC_DEBUG
-   int sequence;                       /* Debugging aid */
-#endif
 
    /* 3: decompression */
-   struct pwc_decompressor *decompressor;      /* function block with decompression routines */
    void *decompress_data;              /* private data for decompression engine */
 
    /* 4: image */
@@ -198,7 +244,7 @@ struct pwc_device
    struct pwc_coord offset;            /* offset within the viewport */
 
    void *image_data;                   /* total buffer, which is subdivided into ... */
-   void *image_ptr[MAX_IMAGES];                /* ...several images... */
+   struct pwc_imgbuf images[MAX_IMAGES];/* ...several images... */
    int fill_image;                     /* ...which are rotated. */
    int len_per_image;                  /* length per image */
    int image_read_pos;                 /* In case we read data in pieces, keep track of were we are in the imagebuffer */
@@ -211,6 +257,7 @@ struct pwc_device
    struct pwc_mpt_range angle_range;
    int pan_angle;                      /* in degrees * 100 */
    int tilt_angle;                     /* absolute angle; 0,0 is home position */
+   int snapshot_button_status;         /* set to 1 when the user push the button, reset to 0 when this value is read */
 
    /*** Misc. data ***/
    wait_queue_head_t frameq;           /* When waiting for a frame to finish... */
@@ -219,20 +266,26 @@ struct pwc_device
 #endif
 };
 
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* Global variable */
+/* Global variables */
+#if CONFIG_PWC_DEBUG
 extern int pwc_trace;
+#endif
+extern int pwc_mbufs;
 
 /** functions in pwc-if.c */
 int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
+int pwc_handle_frame(struct pwc_device *pdev);
+void pwc_next_image(struct pwc_device *pdev);
+int pwc_isoc_init(struct pwc_device *pdev);
+void pwc_isoc_cleanup(struct pwc_device *pdev);
 
 /** Functions in pwc-misc.c */
 /* sizes in pixels */
-extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
+extern const struct pwc_coord pwc_image_sizes[PSZ_MAX];
 
 int pwc_decode_size(struct pwc_device *pdev, int width, int height);
 void pwc_construct(struct pwc_device *pdev);
@@ -240,6 +293,9 @@ void pwc_construct(struct pwc_device *pdev);
 /** Functions in pwc-ctrl.c */
 /* Request a certain video mode. Returns < 0 if not possible */
 extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
+/* Calculate the number of bytes per image (not frame) */
+extern int pwc_mpt_reset(struct pwc_device *pdev, int flags);
+extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt);
 
 /* Various controls; should be obvious. Value 0..65535, or < 0 on error */
 extern int pwc_get_brightness(struct pwc_device *pdev);
@@ -248,10 +304,36 @@ extern int pwc_get_contrast(struct pwc_device *pdev);
 extern int pwc_set_contrast(struct pwc_device *pdev, int value);
 extern int pwc_get_gamma(struct pwc_device *pdev);
 extern int pwc_set_gamma(struct pwc_device *pdev, int value);
-extern int pwc_get_saturation(struct pwc_device *pdev);
+extern int pwc_get_saturation(struct pwc_device *pdev, int *value);
 extern int pwc_set_saturation(struct pwc_device *pdev, int value);
 extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
 extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
+extern int pwc_restore_user(struct pwc_device *pdev);
+extern int pwc_save_user(struct pwc_device *pdev);
+extern int pwc_restore_factory(struct pwc_device *pdev);
+
+/* exported for use by v4l2 controls */
+extern int pwc_get_red_gain(struct pwc_device *pdev, int *value);
+extern int pwc_set_red_gain(struct pwc_device *pdev, int value);
+extern int pwc_get_blue_gain(struct pwc_device *pdev, int *value);
+extern int pwc_set_blue_gain(struct pwc_device *pdev, int value);
+extern int pwc_get_awb(struct pwc_device *pdev);
+extern int pwc_set_awb(struct pwc_device *pdev, int mode);
+extern int pwc_set_agc(struct pwc_device *pdev, int mode, int value);
+extern int pwc_get_agc(struct pwc_device *pdev, int *value);
+extern int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value);
+extern int pwc_get_shutter_speed(struct pwc_device *pdev, int *value);
+
+extern int pwc_set_colour_mode(struct pwc_device *pdev, int colour);
+extern int pwc_get_colour_mode(struct pwc_device *pdev, int *colour);
+extern int pwc_set_contour(struct pwc_device *pdev, int contour);
+extern int pwc_get_contour(struct pwc_device *pdev, int *contour);
+extern int pwc_set_backlight(struct pwc_device *pdev, int backlight);
+extern int pwc_get_backlight(struct pwc_device *pdev, int *backlight);
+extern int pwc_set_flicker(struct pwc_device *pdev, int flicker);
+extern int pwc_get_flicker(struct pwc_device *pdev, int *flicker);
+extern int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise);
+extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise);
 
 /* Power down or up the camera; not supported by all models */
 extern int pwc_camera_power(struct pwc_device *pdev, int power);
@@ -259,6 +341,9 @@ extern int pwc_camera_power(struct pwc_device *pdev, int power);
 /* Private ioctl()s; see pwc-ioctl.h */
 extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
 
+/** Functions in pwc-v4l.c */
+extern int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+                             unsigned int cmd, void *arg);
 
 /** pwc-uncompress.c */
 /* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
@@ -270,3 +355,4 @@ extern int pwc_decompress(struct pwc_device *pdev);
 
 
 #endif
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
index dd830e0e5e96f112ff7b2181df9f771a5dfdf1b8..59a187272c831007de3dba1745759abeb0c04653 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/i2c.h>
 #include <linux/videotext.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 #include "saa5246a.h"
index 531e9461cb66d4fdbc7ab03f6941e4af2d8d43a9..19a8d65699f84892be0149e1cacedb48e18a0fdb 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/i2c.h>
 #include <linux/videotext.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 
index 41d951db6ec0f34c731644d6dfa74b71dc8b8519..676b9970eb2e2cd6d1d596064b6940e47528c78e 100644 (file)
@@ -43,6 +43,7 @@ MODULE_LICENSE("GPL");
 #define I2C_NAME(s) (s)->name
 
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/video_decoder.h>
 
 static int debug = 0;
index dceebc0b1250afbbf7f541d69a4488a958d75b12..b59c1171727351a52beb6b77286fb977f5c27903 100644 (file)
@@ -72,6 +72,10 @@ struct saa7115_state {
        int sat;
        enum v4l2_chip_ident ident;
        u32 audclk_freq;
+       u32 crystal_freq;
+       u8 ucgc;
+       u8 cgcdiv;
+       u8 apll;
 };
 
 /* ----------------------------------------------------------------------- */
@@ -375,10 +379,6 @@ static const unsigned char saa7113_init_auto_input[] = {
 };
 
 static const unsigned char saa7115_init_misc[] = {
-       0x38, 0x03,             /* audio stuff */
-       0x39, 0x10,
-       0x3a, 0x08,
-
        0x81, 0x01,             /* reg 0x15,0x16 define blanking window */
        0x82, 0x00,
        0x83, 0x01,             /* I port settings */
@@ -584,6 +584,7 @@ static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
        u32 acni;
        u32 hz;
        u64 f;
+       u8 acc = 0;     /* reg 0x3a, audio clock control */
 
        v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
 
@@ -591,18 +592,34 @@ static int saa7115_set_audio_clock_freq(struct i2c_client *client, u32 freq)
        if (freq < 32000 || freq > 48000)
                return -EINVAL;
 
+       /* The saa7113 has no audio clock */
+       if (state->ident == V4L2_IDENT_SAA7113)
+               return 0;
+
        /* hz is the refresh rate times 100 */
        hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
        /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
        acpf = (25600 * freq) / hz;
        /* acni = (256 * freq * 2^23) / crystal_frequency =
                  (freq * 2^(8+23)) / crystal_frequency =
-                 (freq << 31) / 32.11 MHz */
+                 (freq << 31) / crystal_frequency */
        f = freq;
        f = f << 31;
-       do_div(f, 32110000);
+       do_div(f, state->crystal_freq);
        acni = f;
+       if (state->ucgc) {
+               acpf = acpf * state->cgcdiv / 16;
+               acni = acni * state->cgcdiv / 16;
+               acc = 0x80;
+               if (state->cgcdiv == 3)
+                       acc |= 0x40;
+       }
+       if (state->apll)
+               acc |= 0x08;
 
+       saa7115_write(client, 0x38, 0x03);
+       saa7115_write(client, 0x39, 0x10);
+       saa7115_write(client, 0x3a, acc);
        saa7115_write(client, 0x30, acpf & 0xff);
        saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
        saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
@@ -1073,48 +1090,6 @@ static void saa7115_decode_vbi_line(struct i2c_client *client,
 
 /* ============ SAA7115 AUDIO settings (end) ============= */
 
-static struct v4l2_queryctrl saa7115_qctrl[] = {
-       {
-               .id            = V4L2_CID_BRIGHTNESS,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Brightness",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 1,
-               .default_value = 128,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_CONTRAST,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Contrast",
-               .minimum       = 0,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 64,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_SATURATION,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Saturation",
-               .minimum       = 0,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 64,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_HUE,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Hue",
-               .minimum       = -128,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 0,
-               .flags         = 0,
-       },
-};
-
-/* ----------------------------------------------------------------------- */
-
 static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
        struct saa7115_state *state = i2c_get_clientdata(client);
@@ -1158,14 +1133,16 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
        case VIDIOC_QUERYCTRL:
        {
                struct v4l2_queryctrl *qc = arg;
-               int i;
 
-               for (i = 0; i < ARRAY_SIZE(saa7115_qctrl); i++)
-                       if (qc->id && qc->id == saa7115_qctrl[i].id) {
-                               memcpy(qc, &saa7115_qctrl[i], sizeof(*qc));
-                               return 0;
-                       }
-               return -EINVAL;
+               switch (qc->id) {
+                       case V4L2_CID_BRIGHTNESS:
+                       case V4L2_CID_CONTRAST:
+                       case V4L2_CID_SATURATION:
+                       case V4L2_CID_HUE:
+                               return v4l2_ctrl_query_fill_std(qc);
+                       default:
+                               return -EINVAL;
+               }
        }
 
        case VIDIOC_G_STD:
@@ -1221,34 +1198,6 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
                break;
        }
 
-       case VIDIOC_G_INPUT:
-               *(int *)arg = state->input;
-               break;
-
-       case VIDIOC_S_INPUT:
-               v4l_dbg(1, debug, client, "decoder set input %d\n", *iarg);
-               /* inputs from 0-9 are available */
-               if (*iarg < 0 || *iarg > 9) {
-                       return -EINVAL;
-               }
-
-               if (state->input == *iarg)
-                       break;
-               v4l_dbg(1, debug, client, "now setting %s input\n",
-                       *iarg >= 6 ? "S-Video" : "Composite");
-               state->input = *iarg;
-
-               /* select mode */
-               saa7115_write(client, 0x02,
-                             (saa7115_read(client, 0x02) & 0xf0) |
-                              state->input);
-
-               /* bypass chrominance trap for modes 6..9 */
-               saa7115_write(client, 0x09,
-                             (saa7115_read(client, 0x09) & 0x7f) |
-                              (state->input < 6 ? 0x0 : 0x80));
-               break;
-
        case VIDIOC_STREAMON:
        case VIDIOC_STREAMOFF:
                v4l_dbg(1, debug, client, "%s output\n",
@@ -1260,6 +1209,21 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
                }
                break;
 
+       case VIDIOC_INT_S_CRYSTAL_FREQ:
+       {
+               struct v4l2_crystal_freq *freq = arg;
+
+               if (freq->freq != SAA7115_FREQ_32_11_MHZ &&
+                   freq->freq != SAA7115_FREQ_24_576_MHZ)
+                       return -EINVAL;
+               state->crystal_freq = freq->freq;
+               state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
+               state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
+               state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
+               saa7115_set_audio_clock_freq(client, state->audclk_freq);
+               break;
+       }
+
        case VIDIOC_INT_DECODE_VBI_LINE:
                saa7115_decode_vbi_line(client, arg);
                break;
@@ -1401,10 +1365,13 @@ static int saa7115_attach(struct i2c_adapter *adapter, int address, int kind)
        v4l_dbg(1, debug, client, "writing init values\n");
 
        /* init to 60hz/48khz */
-       if (state->ident == V4L2_IDENT_SAA7113)
+       if (state->ident == V4L2_IDENT_SAA7113) {
+               state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
                saa7115_writeregs(client, saa7113_init_auto_input);
-       else
+       } else {
+               state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
                saa7115_writeregs(client, saa7115_init_auto_input);
+       }
        saa7115_writeregs(client, saa7115_init_misc);
        saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
        saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
index c271e2e14105721e953da48d2dc2ad564370e27a..ad401bdefeaf39f30b566bffd8510f49f052925a 100644 (file)
@@ -270,7 +270,7 @@ static const char * const wss_strs[] = {
        "letterbox 16:9 top",
        "invalid",
        "invalid",
-       "16:9 full format anamorphic"
+       "16:9 full format anamorphic",
        "4:3 full format",
        "invalid",
        "invalid",
index 0e0ba50946e8923e9dc230cad0d046cc46cebe5f..de7b9e6e932a9b70aec1e53e2ff5d3ff985369c9 100644 (file)
@@ -39,6 +39,23 @@ enum saa6752hs_videoformat {
        SAA6752HS_VF_UNKNOWN,
 };
 
+struct saa6752hs_mpeg_params {
+       /* transport streams */
+       __u16                           ts_pid_pmt;
+       __u16                           ts_pid_audio;
+       __u16                           ts_pid_video;
+       __u16                           ts_pid_pcr;
+
+       /* audio */
+       enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate;
+
+       /* video */
+       enum v4l2_mpeg_video_aspect     vi_aspect;
+       enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode;
+       __u32                           vi_bitrate;
+       __u32                           vi_bitrate_peak;
+};
+
 static const struct v4l2_format v4l2_format_table[] =
 {
        [SAA6752HS_VF_D1] =
@@ -55,18 +72,19 @@ static const struct v4l2_format v4l2_format_table[] =
 
 struct saa6752hs_state {
        struct i2c_client             client;
-       struct v4l2_mpeg_compression  params;
+       struct v4l2_mpeg_compression  old_params;
+       struct saa6752hs_mpeg_params  params;
        enum saa6752hs_videoformat    video_format;
        v4l2_std_id                   standard;
 };
 
 enum saa6752hs_command {
        SAA6752HS_COMMAND_RESET = 0,
-       SAA6752HS_COMMAND_STOP = 1,
-       SAA6752HS_COMMAND_START = 2,
-       SAA6752HS_COMMAND_PAUSE = 3,
-       SAA6752HS_COMMAND_RECONFIGURE = 4,
-       SAA6752HS_COMMAND_SLEEP = 5,
+       SAA6752HS_COMMAND_STOP = 1,
+       SAA6752HS_COMMAND_START = 2,
+       SAA6752HS_COMMAND_PAUSE = 3,
+       SAA6752HS_COMMAND_RECONFIGURE = 4,
+       SAA6752HS_COMMAND_SLEEP = 5,
        SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,
 
        SAA6752HS_COMMAND_MAX
@@ -129,7 +147,22 @@ static u8 PMT[] = {
        0x00, 0x00, 0x00, 0x00 /* CRC32 */
 };
 
-static struct v4l2_mpeg_compression param_defaults =
+static struct saa6752hs_mpeg_params param_defaults =
+{
+       .ts_pid_pmt      = 16,
+       .ts_pid_video    = 260,
+       .ts_pid_audio    = 256,
+       .ts_pid_pcr      = 259,
+
+       .vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
+       .vi_bitrate      = 4000,
+       .vi_bitrate_peak = 6000,
+       .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+
+       .au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+};
+
+static struct v4l2_mpeg_compression old_param_defaults =
 {
        .st_type         = V4L2_MPEG_TS_2,
        .st_bitrate      = {
@@ -228,45 +261,57 @@ static int saa6752hs_chip_command(struct i2c_client* client,
 
 
 static int saa6752hs_set_bitrate(struct i2c_client* client,
-                                struct v4l2_mpeg_compression* params)
+                                struct saa6752hs_mpeg_params* params)
 {
        u8 buf[3];
+       int tot_bitrate;
 
        /* set the bitrate mode */
        buf[0] = 0x71;
-       buf[1] = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? 0 : 1;
+       buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1;
        i2c_master_send(client, buf, 2);
 
        /* set the video bitrate */
-       if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) {
+       if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
                /* set the target bitrate */
                buf[0] = 0x80;
-               buf[1] = params->vi_bitrate.target >> 8;
-               buf[2] = params->vi_bitrate.target & 0xff;
+               buf[1] = params->vi_bitrate >> 8;
+               buf[2] = params->vi_bitrate & 0xff;
                i2c_master_send(client, buf, 3);
 
                /* set the max bitrate */
                buf[0] = 0x81;
-               buf[1] = params->vi_bitrate.max >> 8;
-               buf[2] = params->vi_bitrate.max & 0xff;
+               buf[1] = params->vi_bitrate_peak >> 8;
+               buf[2] = params->vi_bitrate_peak & 0xff;
                i2c_master_send(client, buf, 3);
+               tot_bitrate = params->vi_bitrate_peak;
        } else {
                /* set the target bitrate (no max bitrate for CBR) */
                buf[0] = 0x81;
-               buf[1] = params->vi_bitrate.target >> 8;
-               buf[2] = params->vi_bitrate.target & 0xff;
+               buf[1] = params->vi_bitrate >> 8;
+               buf[2] = params->vi_bitrate & 0xff;
                i2c_master_send(client, buf, 3);
+               tot_bitrate = params->vi_bitrate;
        }
 
        /* set the audio bitrate */
        buf[0] = 0x94;
-       buf[1] = (256 == params->au_bitrate.target) ? 0 : 1;
+       buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1;
        i2c_master_send(client, buf, 2);
+       tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384;
+
+       /* Note: the total max bitrate is determined by adding the video and audio
+          bitrates together and also adding an extra 768kbit/s to stay on the
+          safe side. If more control should be required, then an extra MPEG control
+          should be added. */
+       tot_bitrate += 768;
+       if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX)
+               tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
 
        /* set the total bitrate */
        buf[0] = 0xb1;
-       buf[1] = params->st_bitrate.target >> 8;
-       buf[2] = params->st_bitrate.target & 0xff;
+       buf[1] = tot_bitrate >> 8;
+       buf[2] = tot_bitrate & 0xff;
        i2c_master_send(client, buf, 3);
 
        return 0;
@@ -318,50 +363,188 @@ static void saa6752hs_set_subsampling(struct i2c_client* client,
 }
 
 
-static void saa6752hs_set_params(struct i2c_client* client,
+static void saa6752hs_old_set_params(struct i2c_client* client,
                                 struct v4l2_mpeg_compression* params)
 {
        struct saa6752hs_state *h = i2c_get_clientdata(client);
 
        /* check PIDs */
-       if (params->ts_pid_pmt <= MPEG_PID_MAX)
+       if (params->ts_pid_pmt <= MPEG_PID_MAX) {
+               h->old_params.ts_pid_pmt = params->ts_pid_pmt;
                h->params.ts_pid_pmt = params->ts_pid_pmt;
-       if (params->ts_pid_pcr <= MPEG_PID_MAX)
+       }
+       if (params->ts_pid_pcr <= MPEG_PID_MAX) {
+               h->old_params.ts_pid_pcr = params->ts_pid_pcr;
                h->params.ts_pid_pcr = params->ts_pid_pcr;
-       if (params->ts_pid_video <= MPEG_PID_MAX)
+       }
+       if (params->ts_pid_video <= MPEG_PID_MAX) {
+               h->old_params.ts_pid_video = params->ts_pid_video;
                h->params.ts_pid_video = params->ts_pid_video;
-       if (params->ts_pid_audio <= MPEG_PID_MAX)
+       }
+       if (params->ts_pid_audio <= MPEG_PID_MAX) {
+               h->old_params.ts_pid_audio = params->ts_pid_audio;
                h->params.ts_pid_audio = params->ts_pid_audio;
+       }
 
        /* check bitrate parameters */
        if ((params->vi_bitrate.mode == V4L2_BITRATE_CBR) ||
-           (params->vi_bitrate.mode == V4L2_BITRATE_VBR))
-               h->params.vi_bitrate.mode = params->vi_bitrate.mode;
+           (params->vi_bitrate.mode == V4L2_BITRATE_VBR)) {
+               h->old_params.vi_bitrate.mode = params->vi_bitrate.mode;
+               h->params.vi_bitrate_mode = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ?
+                      V4L2_MPEG_VIDEO_BITRATE_MODE_VBR : V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+       }
        if (params->vi_bitrate.mode != V4L2_BITRATE_NONE)
-               h->params.st_bitrate.target = params->st_bitrate.target;
+               h->old_params.st_bitrate.target = params->st_bitrate.target;
        if (params->vi_bitrate.mode != V4L2_BITRATE_NONE)
-               h->params.vi_bitrate.target = params->vi_bitrate.target;
+               h->old_params.vi_bitrate.target = params->vi_bitrate.target;
        if (params->vi_bitrate.mode == V4L2_BITRATE_VBR)
-               h->params.vi_bitrate.max = params->vi_bitrate.max;
+               h->old_params.vi_bitrate.max = params->vi_bitrate.max;
        if (params->au_bitrate.mode != V4L2_BITRATE_NONE)
-               h->params.au_bitrate.target = params->au_bitrate.target;
+               h->old_params.au_bitrate.target = params->au_bitrate.target;
 
        /* aspect ratio */
        if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3 ||
-           params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9)
-               h->params.vi_aspect_ratio = params->vi_aspect_ratio;
+           params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9) {
+               h->old_params.vi_aspect_ratio = params->vi_aspect_ratio;
+               if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3)
+                       h->params.vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3;
+               else
+                       h->params.vi_aspect = V4L2_MPEG_VIDEO_ASPECT_16x9;
+       }
 
        /* range checks */
-       if (h->params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX)
-               h->params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX;
-       if (h->params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX)
-               h->params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX;
-       if (h->params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX)
-               h->params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX;
-       if (h->params.au_bitrate.target <= 256)
-               h->params.au_bitrate.target = 256;
+       if (h->old_params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX)
+               h->old_params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX;
+       if (h->old_params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX)
+               h->old_params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX;
+       if (h->old_params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX)
+               h->old_params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX;
+       h->params.vi_bitrate = params->vi_bitrate.target;
+       h->params.vi_bitrate_peak = params->vi_bitrate.max;
+       if (h->old_params.au_bitrate.target <= 256) {
+               h->old_params.au_bitrate.target = 256;
+               h->params.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
+       }
+       else {
+               h->old_params.au_bitrate.target = 384;
+               h->params.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
+       }
+}
+
+static int handle_ctrl(struct saa6752hs_mpeg_params *params,
+               struct v4l2_ext_control *ctrl, int cmd)
+{
+       int old = 0, new;
+       int set = cmd == VIDIOC_S_EXT_CTRLS;
+
+       new = ctrl->value;
+       switch (ctrl->id) {
+               case V4L2_CID_MPEG_STREAM_TYPE:
+                       old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
+                       if (set && new != old)
+                               return -ERANGE;
+                       new = old;
+                       break;
+               case V4L2_CID_MPEG_STREAM_PID_PMT:
+                       old = params->ts_pid_pmt;
+                       if (set && new > MPEG_PID_MAX)
+                               return -ERANGE;
+                       if (new > MPEG_PID_MAX)
+                               new = MPEG_PID_MAX;
+                       params->ts_pid_pmt = new;
+                       break;
+               case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+                       old = params->ts_pid_audio;
+                       if (set && new > MPEG_PID_MAX)
+                               return -ERANGE;
+                       if (new > MPEG_PID_MAX)
+                               new = MPEG_PID_MAX;
+                       params->ts_pid_audio = new;
+                       break;
+               case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+                       old = params->ts_pid_video;
+                       if (set && new > MPEG_PID_MAX)
+                               return -ERANGE;
+                       if (new > MPEG_PID_MAX)
+                               new = MPEG_PID_MAX;
+                       params->ts_pid_video = new;
+                       break;
+               case V4L2_CID_MPEG_STREAM_PID_PCR:
+                       old = params->ts_pid_pcr;
+                       if (set && new > MPEG_PID_MAX)
+                               return -ERANGE;
+                       if (new > MPEG_PID_MAX)
+                               new = MPEG_PID_MAX;
+                       params->ts_pid_pcr = new;
+                       break;
+               case V4L2_CID_MPEG_AUDIO_ENCODING:
+                       old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
+                       if (set && new != old)
+                               return -ERANGE;
+                       new = old;
+                       break;
+               case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+                       old = params->au_l2_bitrate;
+                       if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K &&
+                                  new != V4L2_MPEG_AUDIO_L2_BITRATE_384K)
+                               return -ERANGE;
+                       if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K)
+                               new = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
+                       else
+                               new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
+                       params->au_l2_bitrate = new;
+                       break;
+               case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+                       old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
+                       if (set && new != old)
+                               return -ERANGE;
+                       new = old;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_ENCODING:
+                       old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+                       if (set && new != old)
+                               return -ERANGE;
+                       new = old;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_ASPECT:
+                       old = params->vi_aspect;
+                       if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 &&
+                                  new != V4L2_MPEG_VIDEO_ASPECT_4x3)
+                               return -ERANGE;
+                       if (new != V4L2_MPEG_VIDEO_ASPECT_16x9)
+                               new = V4L2_MPEG_VIDEO_ASPECT_4x3;
+                       params->vi_aspect = new;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_BITRATE:
+                       old = params->vi_bitrate * 1000;
+                       new = 1000 * (new / 1000);
+                       if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+                               return -ERANGE;
+                       if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+                               new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
+                       params->vi_bitrate = new / 1000;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+                       old = params->vi_bitrate_peak * 1000;
+                       new = 1000 * (new / 1000);
+                       if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+                               return -ERANGE;
+                       if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+                               new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
+                       params->vi_bitrate_peak = new / 1000;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+                       old = params->vi_bitrate_mode;
+                       params->vi_bitrate_mode = new;
+                       break;
+               default:
+                       return -EINVAL;
+       }
+       if (cmd == VIDIOC_G_EXT_CTRLS)
+               ctrl->value = old;
        else
-               h->params.au_bitrate.target = 384;
+               ctrl->value = new;
+       return 0;
 }
 
 static int saa6752hs_init(struct i2c_client* client)
@@ -395,22 +578,22 @@ static int saa6752hs_init(struct i2c_client* client)
        buf[2] = 0x0D;
        i2c_master_send(client,buf,3);
 
-       /* Set minimum Q-scale {4} */
+       /* Set minimum Q-scale {4} */
        buf[0] = 0x82;
        buf[1] = 0x04;
        i2c_master_send(client,buf,2);
 
-       /* Set maximum Q-scale {12} */
+       /* Set maximum Q-scale {12} */
        buf[0] = 0x83;
        buf[1] = 0x0C;
        i2c_master_send(client,buf,2);
 
-       /* Set Output Protocol */
+       /* Set Output Protocol */
        buf[0] = 0xD0;
        buf[1] = 0x81;
        i2c_master_send(client,buf,2);
 
-       /* Set video output stream format {TS} */
+       /* Set video output stream format {TS} */
        buf[0] = 0xB0;
        buf[1] = 0x05;
        i2c_master_send(client,buf,2);
@@ -441,7 +624,7 @@ static int saa6752hs_init(struct i2c_client* client)
        localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
        localPMT[sizeof(PMT) - 1] = crc & 0xFF;
 
-       /* Set Audio PID */
+       /* Set Audio PID */
        buf[0] = 0xC1;
        buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF;
        buf[2] = h->params.ts_pid_audio & 0xFF;
@@ -489,11 +672,11 @@ static int saa6752hs_init(struct i2c_client* client)
        buf[3] = 0x82;
        buf[4] = 0xB0;
        buf[5] = buf2[0];
-       switch(h->params.vi_aspect_ratio) {
-       case V4L2_MPEG_ASPECT_16_9:
+       switch(h->params.vi_aspect) {
+       case V4L2_MPEG_VIDEO_ASPECT_16x9:
                buf[6] = buf2[1] | 0x40;
                break;
-       case V4L2_MPEG_ASPECT_4_3:
+       case V4L2_MPEG_VIDEO_ASPECT_4x3:
        default:
                buf[6] = buf2[1] & 0xBF;
                break;
@@ -515,6 +698,7 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind)
                return -ENOMEM;
        h->client = client_template;
        h->params = param_defaults;
+       h->old_params = old_param_defaults;
        h->client.adapter = adap;
        h->client.addr = addr;
 
@@ -550,20 +734,45 @@ static int
 saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
        struct saa6752hs_state *h = i2c_get_clientdata(client);
-       struct v4l2_mpeg_compression *params = arg;
+       struct v4l2_ext_controls *ctrls = arg;
+       struct v4l2_mpeg_compression *old_params = arg;
+       struct saa6752hs_mpeg_params params;
        int err = 0;
+       int i;
 
        switch (cmd) {
        case VIDIOC_S_MPEGCOMP:
-               if (NULL == params) {
+               if (NULL == old_params) {
                        /* apply settings and start encoder */
                        saa6752hs_init(client);
                        break;
                }
-               saa6752hs_set_params(client, params);
+               saa6752hs_old_set_params(client, old_params);
                /* fall through */
        case VIDIOC_G_MPEGCOMP:
-               *params = h->params;
+               *old_params = h->old_params;
+               break;
+       case VIDIOC_S_EXT_CTRLS:
+               if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+                       return -EINVAL;
+               if (ctrls->count == 0) {
+                       /* apply settings and start encoder */
+                       saa6752hs_init(client);
+                       break;
+               }
+               /* fall through */
+       case VIDIOC_TRY_EXT_CTRLS:
+       case VIDIOC_G_EXT_CTRLS:
+               if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+                       return -EINVAL;
+               params = h->params;
+               for (i = 0; i < ctrls->count; i++) {
+                       if ((err = handle_ctrl(&params, ctrls->controls + i, cmd))) {
+                               ctrls->error_idx = i;
+                               return err;
+                       }
+               }
+               h->params = params;
                break;
        case VIDIOC_G_FMT:
        {
index bb3e0ba946d34b2eb2b854a25b8b44f1a4a06e55..d77e6a8d9432db4aba09eb8b0977893f098eee00 100644 (file)
@@ -818,7 +818,7 @@ static int snd_saa7134_capsrc_put(struct snd_kcontrol * kcontrol,
                                break;
                }
 
-               /* output xbar always main channel */
+               /* output xbar always main channel */
                saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10);
 
                if (left || right) { // We've got data, turn the input on
index 86eae3528330bb415316ffb6247de54d6fc0492a..927413aded10c120cedbfbddcf57970d48dceca4 100644 (file)
@@ -2160,7 +2160,7 @@ struct saa7134_board saa7134_boards[] = {
                .radio = {
                          .name = name_radio,
                          .amux = LINE2,
-               },
+               },
        },
        [SAA7134_BOARD_GOTVIEW_7135] = {
                /* Mike Baikov <mike@baikov.com> */
@@ -2842,6 +2842,55 @@ struct saa7134_board saa7134_boards[] = {
                        .gpio = 0x000000,       /* GPIO21=Low for FM radio antenna */
                },
        },
+       [SAA7134_BOARD_FLYVIDEO3000_NTSC] = {
+               /* "Zac Bowling" <zac@zacbowling.com> */
+               .name           = "LifeView FlyVIDEO3000 (NTSC)",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+
+               .gpiomask       = 0xe000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x8000,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x2000,
+               },
+                       .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x8000,
+               },
+       },
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -2898,6 +2947,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x153b,
                .subdevice    = 0x1162,
                .driver_data  = SAA7134_BOARD_CINERGY400_CARDBUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5169,
+               .subdevice    = 0x0138,
+               .driver_data  = SAA7134_BOARD_FLYVIDEO3000_NTSC,
        },{
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3459,6 +3514,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        switch (dev->board) {
        case SAA7134_BOARD_FLYVIDEO2000:
        case SAA7134_BOARD_FLYVIDEO3000:
+       case SAA7134_BOARD_FLYVIDEO3000_NTSC:
                dev->has_remote = SAA7134_REMOTE_GPIO;
                board_flyvideo(dev);
                break;
index 222a36c3891756489c20ca9b1a0c1553ed2298f2..279828b8f299bf45598b92af8d6e4b3f2b9d775d 100644 (file)
@@ -132,9 +132,8 @@ static int mt352_aver777_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int mt352_pinnacle_pll_set(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters* params,
-                                 u8* pllbuf)
+static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
+                                          struct dvb_frontend_parameters* params)
 {
        u8 off[] = { 0x00, 0xf1};
        u8 on[]  = { 0x00, 0x71};
@@ -147,30 +146,31 @@ static int mt352_pinnacle_pll_set(struct dvb_frontend* fe,
        f.tuner     = 0;
        f.type      = V4L2_TUNER_DIGITAL_TV;
        f.frequency = params->frequency / 1000 * 16 / 1000;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &msg, 1);
        saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f);
        msg.buf = on;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &msg, 1);
 
        pinnacle_antenna_pwr(dev, antenna_pwr);
 
        /* mt352 setup */
-       mt352_pinnacle_init(fe);
-       pllbuf[0] = 0xc2;
-       pllbuf[1] = 0x00;
-       pllbuf[2] = 0x00;
-       pllbuf[3] = 0x80;
-       pllbuf[4] = 0x00;
-       return 0;
+       return mt352_pinnacle_init(fe);
 }
 
-static int mt352_aver777_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf)
+static int mt352_aver777_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
 {
-       pllbuf[0] = 0xc2;
+       if (buf_len < 5)
+               return -EINVAL;
+
+       pllbuf[0] = 0x61;
        dvb_pll_configure(&dvb_pll_philips_td1316, pllbuf+1,
                          params->frequency,
                          params->u.ofdm.bandwidth);
-       return 0;
+       return 5;
 }
 
 static struct mt352_config pinnacle_300i = {
@@ -179,13 +179,11 @@ static struct mt352_config pinnacle_300i = {
        .if2           = 36150,
        .no_tuner      = 1,
        .demod_init    = mt352_pinnacle_init,
-       .pll_set       = mt352_pinnacle_pll_set,
 };
 
 static struct mt352_config avermedia_777 = {
        .demod_address = 0xf,
        .demod_init    = mt352_aver777_init,
-       .pll_set       = mt352_aver777_pll_set,
 };
 #endif
 
@@ -268,6 +266,8 @@ static int philips_tda6651_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb_
        tuner_buf[2] = 0xca;
        tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
        msleep(1);
@@ -281,6 +281,8 @@ static int philips_tda6651_pll_init(u8 addr, struct dvb_frontend *fe)
        struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
 
        /* setup PLL configuration */
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
        msleep(1);
@@ -290,12 +292,12 @@ static int philips_tda6651_pll_init(u8 addr, struct dvb_frontend *fe)
 
 /* ------------------------------------------------------------------ */
 
-static int philips_tu1216_pll_60_init(struct dvb_frontend *fe)
+static int philips_tu1216_tuner_60_init(struct dvb_frontend *fe)
 {
        return philips_tda6651_pll_init(0x60, fe);
 }
 
-static int philips_tu1216_pll_60_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        return philips_tda6651_pll_set(0x60, fe, params);
 }
@@ -315,20 +317,17 @@ static struct tda1004x_config philips_tu1216_60_config = {
        .xtal_freq     = TDA10046_XTAL_4M,
        .agc_config    = TDA10046_AGC_DEFAULT,
        .if_freq       = TDA10046_FREQ_3617,
-       .pll_init      = philips_tu1216_pll_60_init,
-       .pll_set       = philips_tu1216_pll_60_set,
-       .pll_sleep     = NULL,
        .request_firmware = philips_tu1216_request_firmware,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int philips_tu1216_pll_61_init(struct dvb_frontend *fe)
+static int philips_tu1216_tuner_61_init(struct dvb_frontend *fe)
 {
        return philips_tda6651_pll_init(0x61, fe);
 }
 
-static int philips_tu1216_pll_61_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tu1216_tuner_61_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        return philips_tda6651_pll_set(0x61, fe, params);
 }
@@ -341,21 +340,20 @@ static struct tda1004x_config philips_tu1216_61_config = {
        .xtal_freq     = TDA10046_XTAL_4M,
        .agc_config    = TDA10046_AGC_DEFAULT,
        .if_freq       = TDA10046_FREQ_3617,
-       .pll_init      = philips_tu1216_pll_61_init,
-       .pll_set       = philips_tu1216_pll_61_set,
-       .pll_sleep     = NULL,
        .request_firmware = philips_tu1216_request_firmware,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int philips_europa_pll_init(struct dvb_frontend *fe)
+static int philips_europa_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab };
        struct i2c_msg init_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) };
 
        /* setup PLL configuration */
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
                return -EIO;
        msleep(1);
@@ -365,18 +363,20 @@ static int philips_europa_pll_init(struct dvb_frontend *fe)
        init_msg.len  = 0x02;
        msg[0] = 0x00;
        msg[1] = 0x40;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
                return -EIO;
 
        return 0;
 }
 
-static int philips_td1316_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        return philips_tda6651_pll_set(0x61, fe, params);
 }
 
-static void philips_europa_analog(struct dvb_frontend *fe)
+static int philips_europa_tuner_sleep(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        /* this message actually turns the tuner back to analog mode */
@@ -391,7 +391,20 @@ static void philips_europa_analog(struct dvb_frontend *fe)
        analog_msg.len  = 0x02;
        msg[0] = 0x00;
        msg[1] = 0x14;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
+       return 0;
+}
+
+static int philips_europa_demod_sleep(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+
+       if (dev->original_demod_sleep)
+               dev->original_demod_sleep(fe);
+       fe->ops.i2c_gate_ctrl(fe, 1);
+       return 0;
 }
 
 static struct tda1004x_config philips_europa_config = {
@@ -402,21 +415,20 @@ static struct tda1004x_config philips_europa_config = {
        .xtal_freq     = TDA10046_XTAL_4M,
        .agc_config    = TDA10046_AGC_IFO_AUTO_POS,
        .if_freq       = TDA10046_FREQ_052,
-       .pll_init      = philips_europa_pll_init,
-       .pll_set       = philips_td1316_pll_set,
-       .pll_sleep     = philips_europa_analog,
        .request_firmware = NULL,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
+static int philips_fmd1216_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        /* this message is to set up ATC and ALC */
        static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
        struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) };
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
        msleep(1);
@@ -424,22 +436,27 @@ static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
        return 0;
 }
 
-static void philips_fmd1216_analog(struct dvb_frontend *fe)
+static int philips_fmd1216_tuner_sleep(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        /* this message actually turns the tuner back to analog mode */
        static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0x60 };
        struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) };
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
        msleep(1);
        fmd1216_init[2] = 0x86;
        fmd1216_init[3] = 0x54;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
        msleep(1);
+       return 0;
 }
 
-static int philips_fmd1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_fmd1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        u8 tuner_buf[4];
@@ -516,6 +533,8 @@ static int philips_fmd1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
        tuner_buf[2] = 0x80 | (cp << 6) | (mode  << 3) | 4;
        tuner_buf[3] = 0x40 | band;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
        return 0;
@@ -528,9 +547,6 @@ static struct tda1004x_config medion_cardbus = {
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_IFO_AUTO_NEG,
        .if_freq       = TDA10046_FREQ_3613,
-       .pll_init      = philips_fmd1216_pll_init,
-       .pll_set       = philips_fmd1216_pll_set,
-       .pll_sleep         = philips_fmd1216_analog,
        .request_firmware = NULL,
 };
 
@@ -578,12 +594,12 @@ static struct tda827x_data tda827x_dvbt[] = {
        { .lomax =         0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
 };
 
-static int philips_tda827x_pll_init(struct dvb_frontend *fe)
+static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
 {
        return 0;
 }
 
-static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tda827x_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        u8 tuner_buf[14];
@@ -630,6 +646,8 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
        tuner_buf[13] = 0x40;
 
        tuner_msg.len = 14;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
                return -EIO;
 
@@ -638,18 +656,23 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_
        tuner_buf[0] = 0x30;
        tuner_buf[1] = 0x50 + tda827x_dvbt[i].cp;
        tuner_msg.len = 2;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
 
        return 0;
 }
 
-static void philips_tda827x_pll_sleep(struct dvb_frontend *fe)
+static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        static u8 tda827x_sleep[] = { 0x30, 0xd0};
        struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep,
                                    .len = sizeof(tda827x_sleep) };
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
+       return 0;
 }
 
 static struct tda1004x_config tda827x_lifeview_config = {
@@ -659,9 +682,6 @@ static struct tda1004x_config tda827x_lifeview_config = {
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_TDA827X,
        .if_freq       = TDA10046_FREQ_045,
-       .pll_init      = philips_tda827x_pll_init,
-       .pll_set       = philips_tda827x_pll_set,
-       .pll_sleep         = philips_tda827x_pll_sleep,
        .request_firmware = NULL,
 };
 
@@ -753,6 +773,8 @@ static int philips_tda827xa_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb
        tuner_buf[12] = 0x00;
        tuner_buf[13] = 0x39;  // lpsel
        msg.len = 14;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
                return -EIO;
 
@@ -760,10 +782,14 @@ static int philips_tda827xa_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb
        msg.len = 2;
        reg2[0] = 0x60;
        reg2[1] = 0x3c;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &msg, 1);
 
        reg2[0] = 0xa0;
        reg2[1] = 0x40;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &msg, 1);
 
        msleep(2);
@@ -771,36 +797,43 @@ static int philips_tda827xa_pll_set(u8 addr, struct dvb_frontend *fe, struct dvb
        reg2[0] = 0x30;
        reg2[1] = 0x10 + tda827xa_dvbt[i].scr;
        msg.len = 2;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &msg, 1);
 
        msleep(550);
        reg2[0] = 0x50;
        reg2[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4);
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &msg, 1);
 
        return 0;
 
 }
 
-static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe)
+static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        static u8 tda827xa_sleep[] = { 0x30, 0x90};
        struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep,
                                    .len = sizeof(tda827xa_sleep) };
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
-
+       return 0;
 }
 
 /* ------------------------------------------------------------------ */
 
-static int philips_tiger_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        int ret;
        struct saa7134_dev *dev = fe->dvb->priv;
        static u8 tda8290_close[] = { 0x21, 0xc0};
        static u8 tda8290_open[]  = { 0x21, 0x80};
        struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2};
+
        /* close tda8290 i2c bridge */
        tda8290_msg.buf = tda8290_close;
        ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
@@ -816,7 +849,7 @@ static int philips_tiger_pll_set(struct dvb_frontend *fe, struct dvb_frontend_pa
        return ret;
 }
 
-static int philips_tiger_dvb_mode(struct dvb_frontend *fe)
+static int philips_tiger_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        static u8 data[] = { 0x3c, 0x33, 0x6a};
@@ -827,14 +860,15 @@ static int philips_tiger_dvb_mode(struct dvb_frontend *fe)
        return 0;
 }
 
-static void philips_tiger_analog_mode(struct dvb_frontend *fe)
+static int philips_tiger_tuner_sleep(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        static u8 data[] = { 0x3c, 0x33, 0x68};
        struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
 
        i2c_transfer(&dev->i2c_adap, &msg, 1);
-       philips_tda827xa_pll_sleep( 0x61, fe);
+       philips_tda827xa_tuner_sleep( 0x61, fe);
+       return 0;
 }
 
 static struct tda1004x_config philips_tiger_config = {
@@ -844,15 +878,12 @@ static struct tda1004x_config philips_tiger_config = {
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_TDA827X,
        .if_freq       = TDA10046_FREQ_045,
-       .pll_init      = philips_tiger_dvb_mode,
-       .pll_set       = philips_tiger_pll_set,
-       .pll_sleep     = philips_tiger_analog_mode,
        .request_firmware = NULL,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int lifeview_trio_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int lifeview_trio_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        int ret;
 
@@ -860,16 +891,12 @@ static int lifeview_trio_pll_set(struct dvb_frontend *fe, struct dvb_frontend_pa
        return ret;
 }
 
-static int lifeview_trio_dvb_mode(struct dvb_frontend *fe)
+static int lifeview_trio_tuner_sleep(struct dvb_frontend *fe)
 {
+       philips_tda827xa_tuner_sleep(0x60, fe);
        return 0;
 }
 
-static void lifeview_trio_analog_mode(struct dvb_frontend *fe)
-{
-       philips_tda827xa_pll_sleep(0x60, fe);
-}
-
 static struct tda1004x_config lifeview_trio_config = {
        .demod_address = 0x09,
        .invert        = 1,
@@ -877,15 +904,12 @@ static struct tda1004x_config lifeview_trio_config = {
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_TDA827X_GPL,
        .if_freq       = TDA10046_FREQ_045,
-       .pll_init      = lifeview_trio_dvb_mode,
-       .pll_set       = lifeview_trio_pll_set,
-       .pll_sleep     = lifeview_trio_analog_mode,
        .request_firmware = NULL,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int ads_duo_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int ads_duo_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        int ret;
 
@@ -893,7 +917,7 @@ static int ads_duo_pll_set(struct dvb_frontend *fe, struct dvb_frontend_paramete
        return ret;
 }
 
-static int ads_duo_dvb_mode(struct dvb_frontend *fe)
+static int ads_duo_tuner_init(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        /* route TDA8275a AGC input to the channel decoder */
@@ -901,12 +925,13 @@ static int ads_duo_dvb_mode(struct dvb_frontend *fe)
        return 0;
 }
 
-static void ads_duo_analog_mode(struct dvb_frontend *fe)
+static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
 {
        struct saa7134_dev *dev = fe->dvb->priv;
        /* route TDA8275a AGC input to the analog IF chip*/
        saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x20);
-       philips_tda827xa_pll_sleep( 0x61, fe);
+       philips_tda827xa_tuner_sleep( 0x61, fe);
+       return 0;
 }
 
 static struct tda1004x_config ads_tech_duo_config = {
@@ -916,31 +941,24 @@ static struct tda1004x_config ads_tech_duo_config = {
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_TDA827X_GPL,
        .if_freq       = TDA10046_FREQ_045,
-       .pll_init      = ads_duo_dvb_mode,
-       .pll_set       = ads_duo_pll_set,
-       .pll_sleep     = ads_duo_analog_mode,
        .request_firmware = NULL,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int tevion_dvb220rf_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int tevion_dvb220rf_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
        int ret;
        ret = philips_tda827xa_pll_set(0x60, fe, params);
        return ret;
 }
 
-static int tevion_dvb220rf_pll_init(struct dvb_frontend *fe)
+static int tevion_dvb220rf_tuner_sleep(struct dvb_frontend *fe)
 {
+       philips_tda827xa_tuner_sleep( 0x61, fe);
        return 0;
 }
 
-static void tevion_dvb220rf_pll_sleep(struct dvb_frontend *fe)
-{
-       philips_tda827xa_pll_sleep( 0x61, fe);
-}
-
 static struct tda1004x_config tevion_dvbt220rf_config = {
        .demod_address = 0x08,
        .invert        = 1,
@@ -948,9 +966,6 @@ static struct tda1004x_config tevion_dvbt220rf_config = {
        .xtal_freq     = TDA10046_XTAL_16M,
        .agc_config    = TDA10046_AGC_TDA827X,
        .if_freq       = TDA10046_FREQ_045,
-       .pll_init      = tevion_dvb220rf_pll_init,
-       .pll_set       = tevion_dvb220rf_pll_set,
-       .pll_sleep     = tevion_dvb220rf_pll_sleep,
        .request_firmware = NULL,
 };
 
@@ -961,8 +976,6 @@ static struct tda1004x_config tevion_dvbt220rf_config = {
 #ifdef HAVE_NXT200X
 static struct nxt200x_config avertvhda180 = {
        .demod_address    = 0x0a,
-       .pll_address      = 0x61,
-       .pll_desc         = &dvb_pll_tdhu2,
 };
 
 static int nxt200x_set_pll_input(u8 *buf, int input)
@@ -976,8 +989,6 @@ static int nxt200x_set_pll_input(u8 *buf, int input)
 
 static struct nxt200x_config kworldatsc110 = {
        .demod_address    = 0x0a,
-       .pll_address      = 0x61,
-       .pll_desc         = &dvb_pll_tuv1236d,
        .set_pll_input    = nxt200x_set_pll_input,
 };
 #endif
@@ -1003,78 +1014,158 @@ static int dvb_init(struct saa7134_dev *dev)
                printk("%s: pinnacle 300i dvb setup\n",dev->name);
                dev->dvb.frontend = mt352_attach(&pinnacle_300i,
                                                 &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
+               }
                break;
 
        case SAA7134_BOARD_AVERMEDIA_777:
                printk("%s: avertv 777 dvb setup\n",dev->name);
                dev->dvb.frontend = mt352_attach(&avermedia_777,
                                                 &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.calc_regs = mt352_aver777_tuner_calc_regs;
+               }
                break;
 #endif
 #ifdef HAVE_TDA1004X
        case SAA7134_BOARD_MD7134:
                dev->dvb.frontend = tda10046_attach(&medion_cardbus,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_PHILIPS_TOUGH:
                dev->dvb.frontend = tda10046_attach(&philips_tu1216_60_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_60_init;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_60_set_params;
+               }
                break;
        case SAA7134_BOARD_FLYDVBTDUO:
                dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
                dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_PHILIPS_EUROPA:
                dev->dvb.frontend = tda10046_attach(&philips_europa_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
+                       dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
                dev->dvb.frontend = tda10046_attach(&philips_europa_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_200:
                dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_61_init;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_61_set_params;
+               }
                break;
        case SAA7134_BOARD_PHILIPS_TIGER:
                dev->dvb.frontend = tda10046_attach(&philips_tiger_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
                dev->dvb.frontend = tda10046_attach(&philips_tiger_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_FLYDVBT_LR301:
                dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_FLYDVB_TRIO:
                dev->dvb.frontend = tda10046_attach(&lifeview_trio_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
                dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_TEVION_DVBT_220RF:
                dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.sleep = tevion_dvb220rf_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = tevion_dvb220rf_tuner_set_params;
+               }
                break;
        case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
                dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
                                                    &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init;
+                       dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep;
+                       dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params;
+               }
                break;
 #endif
 #ifdef HAVE_NXT200X
        case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
                dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tdhu2);
+               }
                break;
        case SAA7134_BOARD_KWORLD_ATSC110:
                dev->dvb.frontend = nxt200x_attach(&kworldatsc110, &dev->i2c_adap);
+               if (dev->dvb.frontend) {
+                       dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tuv1236d);
+               }
                break;
 #endif
        default:
@@ -1088,7 +1179,7 @@ static int dvb_init(struct saa7134_dev *dev)
        }
 
        /* register everything else */
-       return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
+       return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
 }
 
 static int dvb_fini(struct saa7134_dev *dev)
index 1d972edb3be6b2cbb3e9c167e24754c5c27cf02f..65d044086ce953b9459b377b53c880aef657f29c 100644 (file)
@@ -64,8 +64,10 @@ static void ts_reset_encoder(struct saa7134_dev* dev)
 
 static int ts_init_encoder(struct saa7134_dev* dev)
 {
+       struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 };
+
        ts_reset_encoder(dev);
-       saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL);
+       saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls);
        dev->empress_started = 1;
        return 0;
 }
@@ -162,6 +164,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file,
                       unsigned int cmd, void *arg)
 {
        struct saa7134_dev *dev = file->private_data;
+       struct v4l2_ext_controls *ctrls = arg;
 
        if (debug > 1)
                v4l_print_ioctl(dev->name,cmd);
@@ -278,12 +281,31 @@ static int ts_do_ioctl(struct inode *inode, struct file *file,
                return saa7134_common_ioctl(dev, cmd, arg);
 
        case VIDIOC_S_MPEGCOMP:
+               printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
+                                   "Replace with VIDIOC_S_EXT_CTRLS!");
                saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg);
                ts_init_encoder(dev);
                return 0;
        case VIDIOC_G_MPEGCOMP:
+               printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
+                                   "Replace with VIDIOC_G_EXT_CTRLS!");
                saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg);
                return 0;
+       case VIDIOC_S_EXT_CTRLS:
+               /* count == 0 is abused in saa6752hs.c, so that special
+                  case is handled here explicitly. */
+               if (ctrls->count == 0)
+                       return 0;
+               if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+                       return -EINVAL;
+               saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, arg);
+               ts_init_encoder(dev);
+               return 0;
+       case VIDIOC_G_EXT_CTRLS:
+               if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+                       return -EINVAL;
+               saa7134_i2c_call_clients(dev, VIDIOC_G_EXT_CTRLS, arg);
+               return 0;
 
        default:
                return -ENOIOCTLCMD;
index 1426e4c8602faa00a519e2e6a9a2c1e47d6860bf..7c595492c56b1719cc3059e03030f60573366723 100644 (file)
@@ -37,6 +37,10 @@ static unsigned int ir_debug = 0;
 module_param(ir_debug, int, 0644);
 MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
 
+static int pinnacle_remote = 0;
+module_param(pinnacle_remote, int, 0644);    /* Choose Pinnacle PCTV remote */
+MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
+
 #define dprintk(fmt, arg...)   if (ir_debug) \
        printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
 #define i2cdprintk(fmt, arg...)    if (ir_debug) \
@@ -316,8 +320,13 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
        switch (dev->board) {
        case SAA7134_BOARD_PINNACLE_PCTV_110i:
                snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
-               ir->get_key   = get_key_pinnacle;
-               ir->ir_codes  = ir_codes_pinnacle;
+               if (pinnacle_remote == 0) {
+                       ir->get_key   = get_key_pinnacle_color;
+                       ir->ir_codes = ir_codes_pinnacle_color;
+               } else {
+                       ir->get_key   = get_key_pinnacle_grey;
+                       ir->ir_codes = ir_codes_pinnacle_grey;
+               }
                break;
        case SAA7134_BOARD_UPMOST_PURPLE_TV:
                snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV");
index 353af3a8b766b7a868e7a71e0eaf81c4a2b460be..d5ee99c574ccbefa17c617d50594d7bfc8077ab2 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <asm/io.h>
 
+#include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include <media/ir-common.h>
 #include <media/ir-kbd-i2c.h>
@@ -221,6 +222,7 @@ struct saa7134_format {
 #define SAA7134_BOARD_AVERMEDIA_A169_B1 92
 #define SAA7134_BOARD_MD7134_BRIDGE_2     93
 #define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94
+#define SAA7134_BOARD_FLYVIDEO3000_NTSC 95
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
@@ -531,6 +533,7 @@ struct saa7134_dev {
 
        /* SAA7134_MPEG_DVB only */
        struct videobuf_dvb        dvb;
+       int (*original_demod_sleep)(struct dvb_frontend* fe);
 };
 
 /* ----------------------------------------------------------- */
index a7a216bd4413cb4554e9ab656bff86c40363dabb..c0891b3e0018efd404cd585b28624a2a7cdc655d 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
 
index ea4394dc9415a84f53c324cb4803878ed13fdc17..48d138a7c7235c6c1197afa6c9d9d0010cdd191a 100644 (file)
@@ -2608,11 +2608,9 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_G_CTRL:
                return sn9c102_vidioc_g_ctrl(cam, arg);
 
-       case VIDIOC_S_CTRL_OLD:
        case VIDIOC_S_CTRL:
                return sn9c102_vidioc_s_ctrl(cam, arg);
 
-       case VIDIOC_CROPCAP_OLD:
        case VIDIOC_CROPCAP:
                return sn9c102_vidioc_cropcap(cam, arg);
 
@@ -2659,7 +2657,6 @@ static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_G_PARM:
                return sn9c102_vidioc_g_parm(cam, arg);
 
-       case VIDIOC_S_PARM_OLD:
        case VIDIOC_S_PARM:
                return sn9c102_vidioc_s_parm(cam, arg);
 
index 07476c71174a70d05a77164c6f4aa39afd7d59fa..6be9c1131e1fc19898c74e9406e932b0e252a3f3 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 
 #include "saa7146.h"
 #include "saa7146reg.h"
index b38bda83a7c5454ce37dcb09484e4d7202554b33..351b182d921f22856edb5f48236db02185cf4f9d 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/pagemap.h>
 #include <linux/errno.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 
index 103ccb91929260353df41e36a2e0be86ae882dc2..827633b3bb4325239ed282e96c44aac306bbbc5d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/init.h>
@@ -163,7 +164,7 @@ static void do_tda9875_init(struct i2c_client *client)
        struct tda9875 *t = i2c_get_clientdata(client);
        dprintk("In tda9875_init\n");
        tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/
-       tda9875_write(client, TDA9875_MSR, 0x03 );    /* Monitor 0b00000XXX*/
+       tda9875_write(client, TDA9875_MSR, 0x03 );    /* Monitor 0b00000XXX*/
        tda9875_write(client, TDA9875_C1MSB, 0x00 );  /*Car1(FM) MSB XMHz*/
        tda9875_write(client, TDA9875_C1MIB, 0x00 );  /*Car1(FM) MIB XMHz*/
        tda9875_write(client, TDA9875_C1LSB, 0x00 );  /*Car1(FM) LSB XMHz*/
index 0d54f6c1982bc9e66adce1d68bc2981b20e09608..b6ae969563b2ba9e3d6cefde6e51bcd21b7cbc43 100644 (file)
    TDA9886 (PAL, SECAM, NTSC)
    TDA9887 (PAL, SECAM, NTSC, FM Radio)
 
-   found on:
-   - Pinnacle PCTV (Jul.2002 Version with MT2032, bttv)
-      TDA9887 (world), TDA9885 (USA)
-      Note: OP2 of tda988x must be set to 1, else MT2032 is disabled!
-   - KNC One TV-Station RDS (saa7134)
-   - Hauppauge PVR-150/500 (possibly more)
+   Used as part of several tuners
 */
 
+#define tda9887_info(fmt, arg...) do {\
+       printk(KERN_INFO "%s %d-%04x (tda9887): " fmt, t->i2c.name, \
+                       i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
+#define tda9887_dbg(fmt, arg...) do {\
+       if (tuner_debug) \
+               printk(KERN_INFO "%s %d-%04x (tda9887): " fmt, t->i2c.name, \
+                       i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {
-       0x84 >>1,
-       0x86 >>1,
-       0x96 >>1,
-       I2C_CLIENT_END,
-};
-I2C_CLIENT_INSMOD;
-
-/* insmod options */
-static unsigned int debug = 0;
-module_param(debug, int, 0644);
-MODULE_LICENSE("GPL");
 
 /* ---------------------------------------------------------------------- */
 
 #define UNSET       (-1U)
-#define tda9887_info(fmt, arg...) do {\
-       printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \
-                       i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0)
-#define tda9887_dbg(fmt, arg...) do {\
-       if (debug) \
-               printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \
-                       i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0)
-
-struct tda9887 {
-       struct i2c_client  client;
-       v4l2_std_id        std;
-       enum tuner_mode    mode;
-       unsigned int       config;
-       unsigned int       using_v4l2;
-       unsigned int       radio_mode;
-       unsigned char      data[4];
-};
 
 struct tvnorm {
        v4l2_std_id       std;
@@ -70,9 +42,6 @@ struct tvnorm {
        unsigned char     e;
 };
 
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
 /* ---------------------------------------------------------------------- */
 
 //
@@ -281,7 +250,7 @@ static struct tvnorm radio_mono = {
 
 /* ---------------------------------------------------------------------- */
 
-static void dump_read_message(struct tda9887 *t, unsigned char *buf)
+static void dump_read_message(struct tuner *t, unsigned char *buf)
 {
        static char *afc[16] = {
                "- 12.5 kHz",
@@ -309,7 +278,7 @@ static void dump_read_message(struct tda9887 *t, unsigned char *buf)
        tda9887_info("  vfi level      : %s\n", (buf[0] & 0x80) ? "high" : "low");
 }
 
-static void dump_write_message(struct tda9887 *t, unsigned char *buf)
+static void dump_write_message(struct tuner *t, unsigned char *buf)
 {
        static char *sound[4] = {
                "AM/TV",
@@ -405,13 +374,13 @@ static void dump_write_message(struct tda9887 *t, unsigned char *buf)
 
 /* ---------------------------------------------------------------------- */
 
-static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
+static int tda9887_set_tvnorm(struct tuner *t, char *buf)
 {
        struct tvnorm *norm = NULL;
        int i;
 
-       if (t->mode == T_RADIO) {
-               if (t->radio_mode == V4L2_TUNER_MODE_MONO)
+       if (t->mode == V4L2_TUNER_RADIO) {
+               if (t->audmode == V4L2_TUNER_MODE_MONO)
                        norm = &radio_mono;
                else
                        norm = &radio_stereo;
@@ -445,7 +414,7 @@ module_param(port2, int, 0644);
 module_param(qss, int, 0644);
 module_param(adjust, int, 0644);
 
-static int tda9887_set_insmod(struct tda9887 *t, char *buf)
+static int tda9887_set_insmod(struct tuner *t, char *buf)
 {
        if (UNSET != port1) {
                if (port1)
@@ -474,27 +443,27 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf)
        return 0;
 }
 
-static int tda9887_set_config(struct tda9887 *t, char *buf)
+static int tda9887_set_config(struct tuner *t, char *buf)
 {
-       if (t->config & TDA9887_PORT1_ACTIVE)
+       if (t->tda9887_config & TDA9887_PORT1_ACTIVE)
                buf[1] &= ~cOutputPort1Inactive;
-       if (t->config & TDA9887_PORT1_INACTIVE)
+       if (t->tda9887_config & TDA9887_PORT1_INACTIVE)
                buf[1] |= cOutputPort1Inactive;
-       if (t->config & TDA9887_PORT2_ACTIVE)
+       if (t->tda9887_config & TDA9887_PORT2_ACTIVE)
                buf[1] &= ~cOutputPort2Inactive;
-       if (t->config & TDA9887_PORT2_INACTIVE)
+       if (t->tda9887_config & TDA9887_PORT2_INACTIVE)
                buf[1] |= cOutputPort2Inactive;
 
-       if (t->config & TDA9887_QSS)
+       if (t->tda9887_config & TDA9887_QSS)
                buf[1] |= cQSS;
-       if (t->config & TDA9887_INTERCARRIER)
+       if (t->tda9887_config & TDA9887_INTERCARRIER)
                buf[1] &= ~cQSS;
 
-       if (t->config & TDA9887_AUTOMUTE)
+       if (t->tda9887_config & TDA9887_AUTOMUTE)
                buf[1] |= cAutoMuteFmActive;
-       if (t->config & TDA9887_DEEMPHASIS_MASK) {
+       if (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) {
                buf[2] &= ~0x60;
-               switch (t->config & TDA9887_DEEMPHASIS_MASK) {
+               switch (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) {
                case TDA9887_DEEMPHASIS_NONE:
                        buf[2] |= cDeemphasisOFF;
                        break;
@@ -506,153 +475,36 @@ static int tda9887_set_config(struct tda9887 *t, char *buf)
                        break;
                }
        }
-       if (t->config & TDA9887_TOP_SET) {
+       if (t->tda9887_config & TDA9887_TOP_SET) {
                buf[2] &= ~cTopMask;
-               buf[2] |= (t->config >> 8) & cTopMask;
+               buf[2] |= (t->tda9887_config >> 8) & cTopMask;
        }
-       if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
+       if ((t->tda9887_config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
                buf[1] &= ~cQSS;
        return 0;
 }
 
 /* ---------------------------------------------------------------------- */
 
-static char pal[] = "--";
-static char secam[] = "--";
-static char ntsc[] = "-";
-
-module_param_string(pal, pal, sizeof(pal), 0644);
-module_param_string(secam, secam, sizeof(secam), 0644);
-module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
-
-static int tda9887_fixup_std(struct tda9887 *t)
-{
-       /* get more precise norm info from insmod option */
-       if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
-               switch (pal[0]) {
-               case 'b':
-               case 'B':
-               case 'g':
-               case 'G':
-               case 'h':
-               case 'H':
-               case 'n':
-               case 'N':
-                       if (pal[1] == 'c' || pal[1] == 'C') {
-                               tda9887_dbg("insmod fixup: PAL => PAL-Nc\n");
-                               t->std = V4L2_STD_PAL_Nc;
-                       } else {
-                               tda9887_dbg("insmod fixup: PAL => PAL-BGHN\n");
-                               t->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N;
-                       }
-                       break;
-               case 'i':
-               case 'I':
-                       tda9887_dbg("insmod fixup: PAL => PAL-I\n");
-                       t->std = V4L2_STD_PAL_I;
-                       break;
-               case 'd':
-               case 'D':
-               case 'k':
-               case 'K':
-                       tda9887_dbg("insmod fixup: PAL => PAL-DK\n");
-                       t->std = V4L2_STD_PAL_DK;
-                       break;
-               case 'm':
-               case 'M':
-                       tda9887_dbg("insmod fixup: PAL => PAL-M\n");
-                       t->std = V4L2_STD_PAL_M;
-                       break;
-               case '-':
-                       /* default parameter, do nothing */
-                       break;
-               default:
-                       tda9887_info("pal= argument not recognised\n");
-                       break;
-               }
-       }
-       if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
-               switch (secam[0]) {
-               case 'b':
-               case 'B':
-               case 'g':
-               case 'G':
-               case 'h':
-               case 'H':
-                       tda9887_dbg("insmod fixup: SECAM => SECAM-BGH\n");
-                       t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
-                       break;
-               case 'd':
-               case 'D':
-               case 'k':
-               case 'K':
-                       tda9887_dbg("insmod fixup: SECAM => SECAM-DK\n");
-                       t->std = V4L2_STD_SECAM_DK;
-                       break;
-               case 'l':
-               case 'L':
-                       if (secam[1] == 'c' || secam[1] == 'C') {
-                               tda9887_dbg("insmod fixup: SECAM => SECAM-L'\n");
-                               t->std = V4L2_STD_SECAM_LC;
-                       } else {
-                               tda9887_dbg("insmod fixup: SECAM => SECAM-L\n");
-                               t->std = V4L2_STD_SECAM_L;
-                       }
-                       break;
-               case '-':
-                       /* default parameter, do nothing */
-                       break;
-               default:
-                       tda9887_info("secam= argument not recognised\n");
-                       break;
-               }
-       }
-       if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
-               switch (ntsc[0]) {
-               case 'm':
-               case 'M':
-                       tda9887_dbg("insmod fixup: NTSC => NTSC-M\n");
-                       t->std = V4L2_STD_NTSC_M;
-                       break;
-               case 'j':
-               case 'J':
-                       tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
-                       t->std = V4L2_STD_NTSC_M_JP;
-                       break;
-               case 'k':
-               case 'K':
-                       tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
-                       t->std = V4L2_STD_NTSC_M_KR;
-                       break;
-               case '-':
-                       /* default parameter, do nothing */
-                       break;
-               default:
-                       tda9887_info("ntsc= argument not recognised\n");
-                       break;
-               }
-       }
-       return 0;
-}
-
-static int tda9887_status(struct tda9887 *t)
+static int tda9887_status(struct tuner *t)
 {
        unsigned char buf[1];
        int rc;
 
        memset(buf,0,sizeof(buf));
-       if (1 != (rc = i2c_master_recv(&t->client,buf,1)))
+       if (1 != (rc = i2c_master_recv(&t->i2c,buf,1)))
                tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc);
        dump_read_message(t, buf);
        return 0;
 }
 
-static int tda9887_configure(struct tda9887 *t)
+static void tda9887_configure(struct i2c_client *client)
 {
+       struct tuner *t = i2c_get_clientdata(client);
        int rc;
 
-       memset(t->data,0,sizeof(t->data));
-       tda9887_set_tvnorm(t,t->data);
+       memset(t->tda9887_data,0,sizeof(t->tda9887_data));
+       tda9887_set_tvnorm(t,t->tda9887_data);
 
        /* A note on the port settings:
           These settings tend to depend on the specifics of the board.
@@ -667,249 +519,84 @@ static int tda9887_configure(struct tda9887 *t)
           the ports should be set to active (0), but, again, that may
           differ depending on the precise hardware configuration.
         */
-       t->data[1] |= cOutputPort1Inactive;
-       t->data[1] |= cOutputPort2Inactive;
+       t->tda9887_data[1] |= cOutputPort1Inactive;
+       t->tda9887_data[1] |= cOutputPort2Inactive;
 
-       tda9887_set_config(t,t->data);
-       tda9887_set_insmod(t,t->data);
+       tda9887_set_config(t,t->tda9887_data);
+       tda9887_set_insmod(t,t->tda9887_data);
 
        if (t->mode == T_STANDBY) {
-               t->data[1] |= cForcedMuteAudioON;
+               t->tda9887_data[1] |= cForcedMuteAudioON;
        }
 
        tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
-               t->data[1],t->data[2],t->data[3]);
-       if (debug > 1)
-               dump_write_message(t, t->data);
+               t->tda9887_data[1],t->tda9887_data[2],t->tda9887_data[3]);
+       if (tuner_debug > 1)
+               dump_write_message(t, t->tda9887_data);
 
-       if (4 != (rc = i2c_master_send(&t->client,t->data,4)))
+       if (4 != (rc = i2c_master_send(&t->i2c,t->tda9887_data,4)))
                tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc);
 
-       if (debug > 2) {
+       if (tuner_debug > 2) {
                msleep_interruptible(1000);
                tda9887_status(t);
        }
-       return 0;
 }
 
 /* ---------------------------------------------------------------------- */
 
-static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
+static void tda9887_tuner_status(struct i2c_client *client)
 {
-       struct tda9887 *t;
-
-       client_template.adapter = adap;
-       client_template.addr    = addr;
-
-       if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL)))
-               return -ENOMEM;
-
-       t->client      = client_template;
-       t->std         = 0;
-       t->radio_mode = V4L2_TUNER_MODE_STEREO;
-
-       tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name);
-
-       i2c_set_clientdata(&t->client, t);
-       i2c_attach_client(&t->client);
-
-       return 0;
+       struct tuner *t = i2c_get_clientdata(client);
+       tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->tda9887_data[1], t->tda9887_data[2], t->tda9887_data[3]);
 }
 
-static int tda9887_probe(struct i2c_adapter *adap)
+static int tda9887_get_afc(struct i2c_client *client)
 {
-       if (adap->class & I2C_CLASS_TV_ANALOG)
-               return i2c_probe(adap, &addr_data, tda9887_attach);
-       return 0;
-}
+       struct tuner *t = i2c_get_clientdata(client);
+       static int AFC_BITS_2_kHz[] = {
+               -12500,  -37500,  -62500,  -97500,
+               -112500, -137500, -162500, -187500,
+               187500,  162500,  137500,  112500,
+               97500 ,  62500,   37500 ,  12500
+       };
+       int afc=0;
+       __u8 reg = 0;
 
-static int tda9887_detach(struct i2c_client *client)
-{
-       struct tda9887 *t = i2c_get_clientdata(client);
+       if (1 == i2c_master_recv(&t->i2c,&reg,1))
+               afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
 
-       i2c_detach_client(client);
-       kfree(t);
-       return 0;
+       return afc;
 }
 
-#define SWITCH_V4L2    if (!t->using_v4l2 && debug) \
-                         tda9887_info("switching to v4l2\n"); \
-                         t->using_v4l2 = 1;
-#define CHECK_V4L2     if (t->using_v4l2) { if (debug) \
-                         tda9887_info("ignore v4l1 call\n"); \
-                         return 0; }
-
-static int
-tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
+static void tda9887_standby(struct i2c_client *client)
 {
-       struct tda9887 *t = i2c_get_clientdata(client);
-
-       switch (cmd) {
-
-       /* --- configuration --- */
-       case AUDC_SET_RADIO:
-       {
-               t->mode = T_RADIO;
-               tda9887_configure(t);
-               break;
-       }
-       case TUNER_SET_STANDBY:
-       {
-               t->mode = T_STANDBY;
-               tda9887_configure(t);
-               break;
-       }
-       case TDA9887_SET_CONFIG:
-       {
-               int *i = arg;
-
-               t->config = *i;
-               tda9887_configure(t);
-               break;
-       }
-       /* --- v4l ioctls --- */
-       /* take care: bttv does userspace copying, we'll get a
-          kernel pointer here... */
-       case VIDIOCSCHAN:
-       {
-               static const v4l2_std_id map[] = {
-                       [ VIDEO_MODE_PAL   ] = V4L2_STD_PAL,
-                       [ VIDEO_MODE_NTSC  ] = V4L2_STD_NTSC_M,
-                       [ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM,
-                       [ 4 /* bttv */     ] = V4L2_STD_PAL_M,
-                       [ 5 /* bttv */     ] = V4L2_STD_PAL_N,
-                       [ 6 /* bttv */     ] = V4L2_STD_NTSC_M_JP,
-               };
-               struct video_channel *vc = arg;
-
-               CHECK_V4L2;
-               t->mode = T_ANALOG_TV;
-               if (vc->norm < ARRAY_SIZE(map))
-                       t->std = map[vc->norm];
-               tda9887_fixup_std(t);
-               tda9887_configure(t);
-               break;
-       }
-       case VIDIOC_S_STD:
-       {
-               v4l2_std_id *id = arg;
-
-               SWITCH_V4L2;
-               t->mode = T_ANALOG_TV;
-               t->std   = *id;
-               tda9887_fixup_std(t);
-               tda9887_configure(t);
-               break;
-       }
-       case VIDIOC_S_FREQUENCY:
-       {
-               struct v4l2_frequency *f = arg;
-
-               SWITCH_V4L2;
-               if (V4L2_TUNER_ANALOG_TV == f->type) {
-                       if (t->mode == T_ANALOG_TV)
-                               return 0;
-                       t->mode = T_ANALOG_TV;
-               }
-               if (V4L2_TUNER_RADIO == f->type) {
-                       if (t->mode == T_RADIO)
-                               return 0;
-                       t->mode = T_RADIO;
-               }
-               tda9887_configure(t);
-               break;
-       }
-       case VIDIOC_G_TUNER:
-       {
-               static int AFC_BITS_2_kHz[] = {
-                       -12500,  -37500,  -62500,  -97500,
-                       -112500, -137500, -162500, -187500,
-                       187500,  162500,  137500,  112500,
-                       97500 ,  62500,   37500 ,  12500
-               };
-               struct v4l2_tuner* tuner = arg;
-
-               if (t->mode == T_RADIO) {
-                       __u8 reg = 0;
-                       tuner->afc=0;
-                       if (1 == i2c_master_recv(&t->client,&reg,1))
-                               tuner->afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
-               }
-               break;
-       }
-       case VIDIOC_S_TUNER:
-       {
-               struct v4l2_tuner* tuner = arg;
-
-               if (t->mode == T_RADIO) {
-                       t->radio_mode = tuner->audmode;
-                       tda9887_configure (t);
-               }
-               break;
-       }
-       case VIDIOC_LOG_STATUS:
-       {
-               tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1], t->data[2], t->data[3]);
-               break;
-       }
-       default:
-               /* nothing */
-               break;
-       }
-       return 0;
+       tda9887_configure(client);
 }
 
-static int tda9887_suspend(struct device * dev, pm_message_t state)
+static void tda9887_set_freq(struct i2c_client *client, unsigned int freq)
 {
-       struct i2c_client *c = container_of(dev, struct i2c_client, dev);
-       struct tda9887 *t = i2c_get_clientdata(c);
-
-       tda9887_dbg("suspend\n");
-       return 0;
+       tda9887_configure(client);
 }
 
-static int tda9887_resume(struct device * dev)
+int tda9887_tuner_init(struct i2c_client *c)
 {
-       struct i2c_client *c = container_of(dev, struct i2c_client, dev);
-       struct tda9887 *t = i2c_get_clientdata(c);
+       struct tuner *t = i2c_get_clientdata(c);
 
-       tda9887_dbg("resume\n");
-       tda9887_configure(t);
-       return 0;
-}
+       strlcpy(c->name, "tda9887", sizeof(c->name));
 
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_driver driver = {
-       .id             = I2C_DRIVERID_TDA9887,
-       .attach_adapter = tda9887_probe,
-       .detach_client  = tda9887_detach,
-       .command        = tda9887_command,
-       .driver = {
-               .name    = "tda9887",
-               .suspend = tda9887_suspend,
-               .resume  = tda9887_resume,
-       },
-};
-static struct i2c_client client_template =
-{
-       .name      = "tda9887",
-       .driver    = &driver,
-};
+       tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr,
+                                               t->i2c.driver->driver.name);
 
-static int __init tda9887_init_module(void)
-{
-       return i2c_add_driver(&driver);
-}
+       t->set_tv_freq = tda9887_set_freq;
+       t->set_radio_freq = tda9887_set_freq;
+       t->standby = tda9887_standby;
+       t->tuner_status=tda9887_tuner_status;
+       t->get_afc=tda9887_get_afc;
 
-static void __exit tda9887_cleanup_module(void)
-{
-       i2c_del_driver(&driver);
+       return 0;
 }
 
-module_init(tda9887_init_module);
-module_exit(tda9887_cleanup_module);
-
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * ---------------------------------------------------------------------------
index c2b98f81c19214e9b9ab464741c3c6ca319bf8da..d1c41781ccc47dd3dd00ea8d7d5d15f3a6dd5cda 100644 (file)
@@ -3,7 +3,7 @@
  * I2C address is allways 0xC0.
  *
  *
- * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
+ * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@infradead.org)
  * This code is placed under the terms of the GNU General Public License
  *
  * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa
diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c
new file mode 100644 (file)
index 0000000..76b2e96
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * tlv320aic23b - driver version 0.0.1
+ *
+ * Copyright (C) 2006 Scott Alfter <salfter@ssai.us>
+ *
+ * Based on wm8775 driver
+ *
+ * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to>
+ * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("tlv320aic23b driver");
+MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+/* ----------------------------------------------------------------------- */
+
+struct tlv320aic23b_state {
+       u8 muted;
+};
+
+static int tlv320aic23b_write(struct i2c_client *client, int reg, u16 val)
+{
+       int i;
+
+       if ((reg < 0 || reg > 9) && (reg != 15)) {
+               v4l_err(client, "Invalid register R%d\n", reg);
+               return -1;
+       }
+
+       for (i = 0; i < 3; i++) {
+               if (i2c_smbus_write_byte_data(client, (reg << 1) |
+                                       (val >> 8), val & 0xff) == 0) {
+                       return 0;
+               }
+       }
+       v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg);
+       return -1;
+}
+
+static int tlv320aic23b_command(struct i2c_client *client, unsigned int cmd,
+                         void *arg)
+{
+       struct tlv320aic23b_state *state = i2c_get_clientdata(client);
+       struct v4l2_control *ctrl = arg;
+       u32* freq = arg;
+
+       switch (cmd) {
+       case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+               switch (*freq) {
+                       case 32000: /* set sample rate to 32 kHz */
+                               tlv320aic23b_write(client, 8, 0x018);
+                               break;
+                       case 44100: /* set sample rate to 44.1 kHz */
+                               tlv320aic23b_write(client, 8, 0x022);
+                               break;
+                       case 48000: /* set sample rate to 48 kHz */
+                               tlv320aic23b_write(client, 8, 0x000);
+                               break;
+                       default:
+                               return -EINVAL;
+               }
+               break;
+
+       case VIDIOC_G_CTRL:
+               if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+                       return -EINVAL;
+               ctrl->value = state->muted;
+               break;
+
+       case VIDIOC_S_CTRL:
+               if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+                       return -EINVAL;
+               state->muted = ctrl->value;
+               tlv320aic23b_write(client, 0, 0x180); /* mute both channels */
+               /* set gain on both channels to +3.0 dB */
+               if (!state->muted)
+                       tlv320aic23b_write(client, 0, 0x119);
+               break;
+
+       case VIDIOC_LOG_STATUS:
+               v4l_info(client, "Input: %s\n",
+                           state->muted ? "muted" : "active");
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+static struct i2c_driver i2c_driver;
+
+static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+       struct i2c_client *client;
+       struct tlv320aic23b_state *state;
+
+       /* Check if the adapter supports the needed features */
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return 0;
+
+       client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+       if (client == 0)
+               return -ENOMEM;
+
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &i2c_driver;
+       snprintf(client->name, sizeof(client->name) - 1, "tlv320aic23b");
+
+       v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+       state = kmalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL);
+       if (state == NULL) {
+               kfree(client);
+               return -ENOMEM;
+       }
+       state->muted = 0;
+       i2c_set_clientdata(client, state);
+
+       /* initialize tlv320aic23b */
+       tlv320aic23b_write(client, 15, 0x000);  /* RESET */
+       tlv320aic23b_write(client, 6, 0x00A);   /* turn off DAC & mic input */
+       tlv320aic23b_write(client, 7, 0x049);   /* left-justified, 24-bit, master mode */
+       tlv320aic23b_write(client, 0, 0x119);   /* set gain on both channels to +3.0 dB */
+       tlv320aic23b_write(client, 8, 0x000);   /* set sample rate to 48 kHz */
+       tlv320aic23b_write(client, 9, 0x001);   /* activate digital interface */
+
+       i2c_attach_client(client);
+
+       return 0;
+}
+
+static int tlv320aic23b_probe(struct i2c_adapter *adapter)
+{
+       if (adapter->class & I2C_CLASS_TV_ANALOG)
+               return i2c_probe(adapter, &addr_data, tlv320aic23b_attach);
+       return 0;
+}
+
+static int tlv320aic23b_detach(struct i2c_client *client)
+{
+       int err;
+
+       err = i2c_detach_client(client);
+       if (err) {
+               return err;
+       }
+       kfree(client);
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+       .driver = {
+               .name = "tlv320aic23b",
+       },
+       .id             = I2C_DRIVERID_TLV320AIC23B,
+       .attach_adapter = tlv320aic23b_probe,
+       .detach_client  = tlv320aic23b_detach,
+       .command        = tlv320aic23b_command,
+};
+
+
+static int __init tlv320aic23b_init_module(void)
+{
+       return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit tlv320aic23b_cleanup_module(void)
+{
+       i2c_del_driver(&i2c_driver);
+}
+
+module_init(tlv320aic23b_init_module);
+module_exit(tlv320aic23b_cleanup_module);
index 74ab48c09c6a448a745f3469ae08cdc9c1adf373..bdf506e6ae279a8fd296e2096f80eb75319b6ba8 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/i2c.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 
 #include <media/tuner.h>
 
index 1013b4de89a278c21ebf017a452e7cf73716b226..e95792fd70f8a3193e081a8a611438f032c9bb55 100644 (file)
@@ -199,7 +199,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
                i2c_master_send(c, buffer, 4);
                default_tuner_init(c);
                break;
-       case TUNER_LG_TDVS_H062F:
+       case TUNER_LG_TDVS_H06XF:
                /* Set the Auxiliary Byte. */
                buffer[2] &= ~0x20;
                buffer[2] |= 0x18;
@@ -215,6 +215,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
                i2c_master_send(c,buffer,4);
                default_tuner_init(c);
                break;
+       case TUNER_TDA9887:
+               tda9887_tuner_init(c);
+               break;
        default:
                default_tuner_init(c);
                break;
@@ -241,6 +244,8 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
 {
        struct tuner *t = i2c_get_clientdata(c);
 
+       tuner_dbg("set addr for type %i\n", t->type);
+
        if ( t->type == UNSET && ((tun_setup->addr == ADDR_UNSET &&
                (t->mode_mask & tun_setup->mode_mask)) ||
                tun_setup->addr == c->addr)) {
@@ -436,6 +441,7 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
        t->radio_if2 = 10700 * 1000;    /* 10.7MHz - FM radio */
        t->audmode = V4L2_TUNER_MODE_STEREO;
        t->mode_mask = T_UNINITIALIZED;
+       t->tuner_status = tuner_status;
        if (tuner_debug_old) {
                tuner_debug = tuner_debug_old;
                printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n");
@@ -462,10 +468,14 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
                case 0x4b:
                        /* If chip is not tda8290, don't register.
                           since it can be tda9887*/
-                       if (tda8290_probe(&t->i2c) != 0) {
-                               tuner_dbg("chip at addr %x is not a tda8290\n", addr);
-                               kfree(t);
-                               return 0;
+                       if (tda8290_probe(&t->i2c) == 0) {
+                               tuner_dbg("chip at addr %x is a tda8290\n", addr);
+                       } else {
+                               /* Default is being tda9887 */
+                               t->type = TUNER_TDA9887;
+                               t->mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
+                               t->mode = T_STANDBY;
+                               goto register_client;
                        }
                        break;
                case 0x60:
@@ -592,6 +602,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
        case TUNER_SET_STANDBY:
                if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
                        return 0;
+               t->mode = T_STANDBY;
                if (t->standby)
                        t->standby (client);
                break;
@@ -604,6 +615,14 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                /* Should be implemented, since bttv calls it */
                tuner_dbg("VIDIOCSAUDIO not implemented.\n");
                break;
+       case TDA9887_SET_CONFIG:
+       {
+               int *i = arg;
+
+               t->tda9887_config = *i;
+               set_freq(client, t->tv_freq);
+               break;
+       }
        /* --- v4l ioctls --- */
        /* take care: bttv does userspace copying, we'll get a
           kernel pointer here... */
@@ -744,6 +763,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        switch_v4l2();
 
                        tuner->type = t->mode;
+                       if (t->get_afc)
+                               tuner->afc=t->get_afc(client);
                        if (t->mode == V4L2_TUNER_ANALOG_TV)
                                tuner->capability |= V4L2_TUNER_CAP_NORM;
                        if (t->mode != V4L2_TUNER_RADIO) {
@@ -787,7 +808,8 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
                        break;
                }
        case VIDIOC_LOG_STATUS:
-               tuner_status(client);
+               if (t->tuner_status)
+                       t->tuner_status(client);
                break;
        }
 
index 5d7abed71674f179ee6797a21b33ab89ee4ea5ff..6da6f82b8c885960b671a0aadf3b4f6140496073 100644 (file)
@@ -105,7 +105,7 @@ static int tuner_stereo(struct i2c_client *c)
 
        switch (t->type) {
                case TUNER_PHILIPS_FM1216ME_MK3:
-               case TUNER_PHILIPS_FM1236_MK3:
+               case TUNER_PHILIPS_FM1236_MK3:
                case TUNER_PHILIPS_FM1256_IH3:
                        stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
                        break;
index a1ae036b44ec9cd362d452697122f06e0db83dee..9d9226cb6393c389d481c502d09e32fb179582b4 100644 (file)
@@ -874,7 +874,7 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
 };
 
 
-/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */
+/* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */
 
 static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
        { 16 * 165.00 /*MHz*/, 0x8e, 0x01 },
@@ -883,7 +883,7 @@ static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
 };
 
 
-static struct tuner_params tuner_tua6034_params[] = {
+static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
        {
                .type   = TUNER_PARAM_TYPE_NTSC,
                .ranges = tuner_tua6034_ntsc_ranges,
@@ -1024,6 +1024,22 @@ static struct tuner_params tuner_thomson_fe6600_params[] = {
        },
 };
 
+/* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */
+
+static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = {
+       { 16 * 146.25 /*MHz*/, 0xce, 0x01, },
+       { 16 * 428.50 /*MHz*/, 0xce, 0x02, },
+       { 16 * 999.99        , 0xce, 0x08, },
+};
+
+static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
+       {
+               .type   = TUNER_PARAM_TYPE_PAL,
+               .ranges = tuner_samsung_tcpg_6121p30a_pal_ranges,
+               .count  = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_pal_ranges),
+       },
+};
+
 /* --------------------------------------------------------------------- */
 
 struct tunertype tuners[] = {
@@ -1354,10 +1370,10 @@ struct tunertype tuners[] = {
                .params = tuner_philips_fmd1216me_mk3_params,
                .count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params),
        },
-       [TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */
-               .name   = "LG TDVS-H062F/TUA6034",
-               .params = tuner_tua6034_params,
-               .count  = ARRAY_SIZE(tuner_tua6034_params),
+       [TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */
+               .name   = "LG TDVS-H06xF", /* H061F, H062F & H064F */
+               .params = tuner_lg_tdvs_h06xf_params,
+               .count  = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params),
        },
        [TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
                .name   = "Ymec TVF66T5-B/DFF",
@@ -1400,6 +1416,16 @@ struct tunertype tuners[] = {
                .params = tuner_thomson_fe6600_params,
                .count  = ARRAY_SIZE(tuner_thomson_fe6600_params),
        },
+       [TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */
+               .name   = "Samsung TCPG 6121P30A",
+               .params = tuner_samsung_tcpg_6121p30a_params,
+               .count  = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_params),
+       },
+       [TUNER_TDA9887] = { /* Philips TDA 9887 IF PLL Demodulator.
+                               This chip is part of some modern tuners */
+               .name   = "Philips TDA988[5,6,7] IF PLL Demodulator",
+               /* see tda9887.c for details */
+       },
 };
 
 unsigned const int tuner_count = ARRAY_SIZE(tuners);
index b463e996961adbb5ee5b6c62db3a045402343adb..30f8d80ddcaa9c688ec817befb8872fcd156e5fd 100644 (file)
@@ -200,7 +200,7 @@ hauppauge_tuner[] =
        { TUNER_ABSENT,        "Philips FQ1286A MK4"},
        { TUNER_ABSENT,        "Philips FQ1216ME MK5"},
        { TUNER_ABSENT,        "Philips FQ1236 MK5"},
-       { TUNER_ABSENT,        "Samsung TCPG_6121P30A"},
+       { TUNER_SAMSUNG_TCPG_6121P30A, "Samsung TCPG 6121P30A"},
        { TUNER_TCL_2002MB,    "TCL 2002MB_3H"},
        { TUNER_ABSENT,        "TCL 2002MI_3H"},
        { TUNER_TCL_2002N,     "TCL 2002N 5H"},
index 9e86caeb96a7b530da89b05e18a0cb44d53d7865..1654576de10e9cd5596178d86f342dd385101ffd 100644 (file)
@@ -198,10 +198,6 @@ static int tvmixer_open(struct inode *inode, struct file *file)
 
        /* lock bttv in memory while the mixer is in use  */
        file->private_data = mix;
-#ifndef I2C_PEC
-       if (client->adapter->inc_use)
-               client->adapter->inc_use(client->adapter);
-#endif
        if (client->adapter->owner)
                try_module_get(client->adapter->owner);
        return 0;
@@ -217,10 +213,6 @@ static int tvmixer_release(struct inode *inode, struct file *file)
                return -ENODEV;
        }
 
-#ifndef I2C_PEC
-       if (client->adapter->dec_use)
-               client->adapter->dec_use(client->adapter);
-#endif
        if (client->adapter->owner)
                module_put(client->adapter->owner);
        return 0;
index dab4973bcf8261f4e5cd3eac842bec218e76f388..b167ffab25202106da0bc956b8304430a48634e8 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/delay.h>
 #include <linux/video_decoder.h>
 #include <media/v4l2-common.h>
+#include <media/tvp5150.h>
 
 #include "tvp5150_reg.h"
 
@@ -89,7 +90,7 @@ struct tvp5150 {
        struct i2c_client *client;
 
        v4l2_std_id norm;       /* Current set standard */
-       int input;
+       struct v4l2_routing route;
        int enable;
        int bright;
        int contrast;
@@ -283,29 +284,26 @@ static void dump_reg(struct i2c_client *c)
 /****************************************************************************
                        Basic functions
  ****************************************************************************/
-enum tvp5150_input {
-       TVP5150_ANALOG_CH0 = 0,
-       TVP5150_SVIDEO = 1,
-       TVP5150_ANALOG_CH1 = 2,
-       TVP5150_BLACK_SCREEN = 8
-};
 
-static inline void tvp5150_selmux(struct i2c_client *c,
-                                 enum tvp5150_input input)
+static inline void tvp5150_selmux(struct i2c_client *c)
 {
        int opmode=0;
-
        struct tvp5150 *decoder = i2c_get_clientdata(c);
+       int input = 0;
 
-       if (!decoder->enable)
-               input |= TVP5150_BLACK_SCREEN;
+       if ((decoder->route.output & TVP5150_BLACK_SCREEN) || !decoder->enable)
+               input = 8;
 
        switch (input) {
-       case TVP5150_ANALOG_CH0:
-       case TVP5150_ANALOG_CH1:
+       case TVP5150_COMPOSITE1:
+               input |= 2;
+               /* fall through */
+       case TVP5150_COMPOSITE0:
                opmode=0x30;            /* TV Mode */
                break;
+       case TVP5150_SVIDEO:
        default:
+               input |= 1;
                opmode=0;               /* Auto Mode */
                break;
        }
@@ -790,7 +788,7 @@ static inline void tvp5150_reset(struct i2c_client *c)
        tvp5150_vdp_init(c, vbi_ram_default);
 
        /* Selects decoder input */
-       tvp5150_selmux(c, decoder->input);
+       tvp5150_selmux(c);
 
        /* Initializes TVP5150 to stream enabled values */
        tvp5150_write_inittab(c, tvp5150_init_enable);
@@ -860,6 +858,21 @@ static int tvp5150_command(struct i2c_client *c,
        case VIDIOC_INT_RESET:
                tvp5150_reset(c);
                break;
+       case VIDIOC_INT_G_VIDEO_ROUTING:
+       {
+               struct v4l2_routing *route = arg;
+
+               *route = decoder->route;
+               break;
+       }
+       case VIDIOC_INT_S_VIDEO_ROUTING:
+       {
+               struct v4l2_routing *route = arg;
+
+               decoder->route = *route;
+               tvp5150_selmux(c);
+               break;
+       }
        case VIDIOC_S_STD:
                if (decoder->norm == *(v4l2_std_id *)arg)
                        break;
@@ -1063,7 +1076,7 @@ static int tvp5150_detect_client(struct i2c_adapter *adapter,
        rv = i2c_attach_client(c);
 
        core->norm = V4L2_STD_ALL;      /* Default is autodetect */
-       core->input = 2;
+       core->route.input = TVP5150_COMPOSITE1;
        core->enable = 1;
        core->bright = 32768;
        core->contrast = 32768;
index 39269a2c5635912abcbc8b4f252a50d92a265887..59fb899f31f3548ce1b1c1a72f088a799977c6ed 100644 (file)
@@ -36,3 +36,15 @@ config USB_KONICAWC
 
          To compile this driver as a module, choose M here: the
          module will be called konicawc.
+
+config USB_QUICKCAM_MESSENGER
+       tristate "USB Logitech Quickcam Messenger"
+       depends on USB && VIDEO_DEV
+       select VIDEO_USBVIDEO
+       ---help---
+         Say Y or M here to enable support for the USB Logitech Quickcam
+         Messenger webcam.
+
+         To compile this driver as a module, choose M here: the
+         module will be called quickcam_messenger.
+
index bb52eb8dc2f9c1b501484c117772ae5ed511017f..4a1b144bee4df9f449bea41024f43f1a36a5b320 100644 (file)
@@ -2,3 +2,4 @@ obj-$(CONFIG_VIDEO_USBVIDEO)    += usbvideo.o
 obj-$(CONFIG_USB_IBMCAM)        += ibmcam.o ultracam.o
 obj-$(CONFIG_USB_KONICAWC)      += konicawc.o
 obj-$(CONFIG_USB_VICAM)         += vicam.o
+obj-$(CONFIG_USB_QUICKCAM_MESSENGER)   += quickcam_messenger.o
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
new file mode 100644 (file)
index 0000000..3f3182a
--- /dev/null
@@ -0,0 +1,1120 @@
+/*
+ * Driver for Logitech Quickcam Messenger usb video camera
+ * Copyright (C) Jaya Kumar
+ *
+ * This work was sponsored by CIS(M) Sdn Bhd.
+ * History:
+ * 05/08/2006 - Jaya Kumar
+ * I wrote this based on the konicawc by Simon Evans.
+ * -
+ * Full credit for reverse engineering and creating an initial
+ * working linux driver for the VV6422 goes to the qce-ga project by
+ * Tuukka Toivonen, Jochen Hoenicke, Peter McConnell,
+ * Cristiano De Michele, Georg Acher, Jean-Frederic Clere as well as
+ * others.
+ * ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/usb_input.h>
+
+#include "usbvideo.h"
+#include "quickcam_messenger.h"
+
+/*
+ * Version Information
+ */
+
+#ifdef CONFIG_USB_DEBUG
+static int debug;
+#define DEBUG(n, format, arg...) \
+       if (n <= debug) {        \
+               printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
+       }
+#else
+#define DEBUG(n, arg...)
+static const int debug = 0;
+#endif
+
+#define DRIVER_VERSION "v0.01"
+#define DRIVER_DESC "Logitech Quickcam Messenger USB"
+
+#define USB_LOGITECH_VENDOR_ID 0x046D
+#define USB_QCM_PRODUCT_ID     0x08F0
+
+#define MAX_CAMERAS    1
+
+#define MAX_COLOUR     32768
+#define MAX_HUE                32768
+#define MAX_BRIGHTNESS 32768
+#define MAX_CONTRAST   32768
+#define MAX_WHITENESS  32768
+
+static int size = SIZE_320X240;
+static int colour = MAX_COLOUR;
+static int hue = MAX_HUE;
+static int brightness =        MAX_BRIGHTNESS;
+static int contrast =  MAX_CONTRAST;
+static int whiteness = MAX_WHITENESS;
+
+static struct usbvideo *cams;
+
+static struct usb_device_id qcm_table [] = {
+       { USB_DEVICE(USB_LOGITECH_VENDOR_ID, USB_QCM_PRODUCT_ID) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, qcm_table);
+
+#ifdef CONFIG_INPUT
+static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
+{
+       struct input_dev *input_dev;
+
+       usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
+       strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
+
+       cam->input = input_dev = input_allocate_device();
+       if (!input_dev) {
+               warn("insufficient mem for cam input device");
+               return;
+       }
+
+       input_dev->name = "QCM button";
+       input_dev->phys = cam->input_physname;
+       usb_to_input_id(dev, &input_dev->id);
+       input_dev->cdev.dev = &dev->dev;
+
+       input_dev->evbit[0] = BIT(EV_KEY);
+       input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+
+       input_dev->private = cam;
+
+       input_register_device(cam->input);
+}
+
+static void qcm_unregister_input(struct qcm *cam)
+{
+       if (cam->input) {
+               input_unregister_device(cam->input);
+               cam->input = NULL;
+       }
+}
+
+static void qcm_report_buttonstat(struct qcm *cam)
+{
+       if (cam->input) {
+               input_report_key(cam->input, BTN_0, cam->button_sts);
+               input_sync(cam->input);
+       }
+}
+
+static void qcm_int_irq(struct urb *urb, struct pt_regs *regs)
+{
+       int ret;
+       struct uvd *uvd = urb->context;
+       struct qcm *cam;
+
+       if (!CAMERA_IS_OPERATIONAL(uvd))
+               return;
+
+       if (!uvd->streaming)
+               return;
+
+       uvd->stats.urb_count++;
+
+       if (urb->status < 0)
+               uvd->stats.iso_err_count++;
+       else {
+               if (urb->actual_length > 0 ) {
+                       cam = (struct qcm *) uvd->user_data;
+                       if (cam->button_sts_buf == 0x88)
+                               cam->button_sts = 0x0;
+                       else if (cam->button_sts_buf == 0x80)
+                               cam->button_sts = 0x1;
+                       qcm_report_buttonstat(cam);
+               }
+       }
+
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+       if (ret < 0)
+               err("usb_submit_urb error (%d)", ret);
+}
+
+static int qcm_setup_input_int(struct qcm *cam, struct uvd *uvd)
+{
+       int errflag;
+       usb_fill_int_urb(cam->button_urb, uvd->dev,
+                       usb_rcvintpipe(uvd->dev, uvd->video_endp + 1),
+                       &cam->button_sts_buf,
+                       1,
+                       qcm_int_irq,
+                       uvd, 16);
+
+       errflag = usb_submit_urb(cam->button_urb, GFP_KERNEL);
+       if (errflag)
+               err ("usb_submit_int ret %d", errflag);
+       return errflag;
+}
+
+static void qcm_stop_int_data(struct qcm *cam)
+{
+       usb_kill_urb(cam->button_urb);
+}
+
+static int qcm_alloc_int_urb(struct qcm *cam)
+{
+       cam->button_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+       if (!cam->button_urb)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void qcm_free_int(struct qcm *cam)
+{
+       if (cam->button_urb)
+               usb_free_urb(cam->button_urb);
+}
+#endif /* CONFIG_INPUT */
+
+static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val)
+{
+       int ret;
+
+       /* we'll wait up to 3 slices but no more */
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+               reg, 0, &val, 1, 3*HZ);
+       return ret;
+}
+
+static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val)
+{
+       int ret;
+
+       /* we'll wait up to 3 slices but no more */
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+               reg, 0, &val, 2, 3*HZ);
+       return ret;
+}
+
+static int qcm_stv_getw(struct usb_device *dev, unsigned short reg,
+                                                       __le16 *val)
+{
+       int ret;
+
+       /* we'll wait up to 3 slices but no more */
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               0x04, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
+               reg, 0, val, 2, 3*HZ);
+       return ret;
+}
+
+static int qcm_camera_on(struct uvd *uvd)
+{
+       int ret;
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x01));
+       return 0;
+}
+
+static int qcm_camera_off(struct uvd *uvd)
+{
+       int ret;
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00));
+       return 0;
+}
+
+static void qcm_hsv2rgb(u16 hue, u16 sat, u16 val, u16 *r, u16 *g, u16 *b)
+{
+       unsigned int segment, valsat;
+       signed int   h = (signed int) hue;
+       unsigned int s = (sat - 32768) * 2;     /* rescale */
+       unsigned int v = val;
+       unsigned int p;
+
+       /*
+       the registers controling gain are 8 bit of which
+       we affect only the last 4 bits with our gain.
+       we know that if saturation is 0, (unsaturated) then
+       we're grayscale (center axis of the colour cone) so
+       we set rgb=value. we use a formula obtained from
+       wikipedia to map the cone to the RGB plane. it's
+       as follows for the human value case of h=0..360,
+       s=0..1, v=0..1
+       h_i = h/60 % 6 , f = h/60 - h_i , p = v(1-s)
+       q = v(1 - f*s) , t = v(1 - (1-f)s)
+       h_i==0 => r=v , g=t, b=p
+       h_i==1 => r=q , g=v, b=p
+       h_i==2 => r=p , g=v, b=t
+       h_i==3 => r=p , g=q, b=v
+       h_i==4 => r=t , g=p, b=v
+       h_i==5 => r=v , g=p, b=q
+       the bottom side (the point) and the stuff just up
+       of that is black so we simplify those two cases.
+       */
+       if (sat < 32768) {
+               /* anything less than this is unsaturated */
+               *r = val;
+               *g = val;
+               *b = val;
+               return;
+       }
+       if (val <= (0xFFFF/8)) {
+               /* anything less than this is black */
+               *r = 0;
+               *g = 0;
+               *b = 0;
+               return;
+       }
+
+       /* the rest of this code is copying tukkat's
+       implementation of the hsv2rgb conversion as taken
+       from qc-usb-messenger code. the 10923 is 0xFFFF/6
+       to divide the cone into 6 sectors.  */
+
+       segment = (h + 10923) & 0xFFFF;
+       segment = segment*3 >> 16;              /* 0..2: 0=R, 1=G, 2=B */
+       hue -= segment * 21845;                 /* -10923..10923 */
+       h = hue;
+       h *= 3;
+       valsat = v*s >> 16;                     /* 0..65534 */
+       p = v - valsat;
+       if (h >= 0) {
+               unsigned int t = v - (valsat * (32769 - h) >> 15);
+               switch (segment) {
+               case 0: /* R-> */
+                       *r = v;
+                       *g = t;
+                       *b = p;
+                       break;
+               case 1: /* G-> */
+                       *r = p;
+                       *g = v;
+                       *b = t;
+                       break;
+               case 2: /* B-> */
+                       *r = t;
+                       *g = p;
+                       *b = v;
+                       break;
+               }
+       } else {
+               unsigned int q = v - (valsat * (32769 + h) >> 15);
+               switch (segment) {
+               case 0: /* ->R */
+                       *r = v;
+                       *g = p;
+                       *b = q;
+                       break;
+               case 1: /* ->G */
+                       *r = q;
+                       *g = v;
+                       *b = p;
+                       break;
+               case 2: /* ->B */
+                       *r = p;
+                       *g = q;
+                       *b = v;
+                       break;
+               }
+       }
+}
+
+static int qcm_sensor_set_gains(struct uvd *uvd, u16 hue,
+       u16 saturation, u16 value)
+{
+       int ret;
+       u16 r=0,g=0,b=0;
+
+       /* this code is based on qc-usb-messenger */
+       qcm_hsv2rgb(hue, saturation, value, &r, &g, &b);
+
+       r >>= 12;
+       g >>= 12;
+       b >>= 12;
+
+       /* min val is 8 */
+       r = max((u16) 8, r);
+       g = max((u16) 8, g);
+       b = max((u16) 8, b);
+
+       r |= 0x30;
+       g |= 0x30;
+       b |= 0x30;
+
+       /* set the r,g,b gain registers */
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x0509, r));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050A, g));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050B, b));
+
+       /* doing as qc-usb did */
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050C, 0x2A));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050D, 0x01));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
+
+       return 0;
+}
+
+static int qcm_sensor_set_exposure(struct uvd *uvd, int exposure)
+{
+       int ret;
+       int formedval;
+
+       /* calculation was from qc-usb-messenger driver */
+       formedval = ( exposure >> 12 );
+
+       /* max value for formedval is 14 */
+       formedval = min(formedval, 14);
+
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev,
+                       0x143A, 0xF0 | formedval));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
+       return 0;
+}
+
+static int qcm_sensor_setlevels(struct uvd *uvd, int brightness, int contrast,
+                                       int hue, int colour)
+{
+       int ret;
+       /* brightness is exposure, contrast is gain, colour is saturation */
+       CHECK_RET(ret,
+               qcm_sensor_set_exposure(uvd, brightness));
+       CHECK_RET(ret, qcm_sensor_set_gains(uvd, hue, colour, contrast));
+
+       return 0;
+}
+
+static int qcm_sensor_setsize(struct uvd *uvd, u8 size)
+{
+       int ret;
+
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x1505, size));
+       return 0;
+}
+
+static int qcm_sensor_set_shutter(struct uvd *uvd, int whiteness)
+{
+       int ret;
+       /* some rescaling as done by the qc-usb-messenger code */
+       if (whiteness > 0xC000)
+               whiteness = 0xC000 + (whiteness & 0x3FFF)*8;
+
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143D,
+                               (whiteness >> 8) & 0xFF));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143E,
+                               (whiteness >> 16) & 0x03));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
+
+       return 0;
+}
+
+static int qcm_sensor_init(struct uvd *uvd)
+{
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+       int ret;
+       int i;
+
+       for (i=0; i < sizeof(regval_table)/sizeof(regval_table[0]) ; i++) {
+               CHECK_RET(ret, qcm_stv_setb(uvd->dev,
+                                       regval_table[i].reg,
+                                       regval_table[i].val));
+       }
+
+       CHECK_RET(ret, qcm_stv_setw(uvd->dev, 0x15c1,
+                               cpu_to_le16(ISOC_PACKET_SIZE)));
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x15c3, 0x08));
+       CHECK_RET(ret, ret = qcm_stv_setb(uvd->dev, 0x143f, 0x01));
+
+       CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00));
+
+       CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
+
+       CHECK_RET(ret, qcm_sensor_setlevels(uvd, uvd->vpic.brightness,
+                       uvd->vpic.contrast, uvd->vpic.hue, uvd->vpic.colour));
+
+       CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness));
+       CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
+
+       return 0;
+}
+
+static int qcm_set_camera_size(struct uvd *uvd)
+{
+       int ret;
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+
+       CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
+       cam->width = camera_sizes[cam->size].width;
+       cam->height = camera_sizes[cam->size].height;
+       uvd->videosize = VIDEOSIZE(cam->width, cam->height);
+
+       return 0;
+}
+
+static int qcm_setup_on_open(struct uvd *uvd)
+{
+       int ret;
+
+       CHECK_RET(ret, qcm_sensor_set_gains(uvd, uvd->vpic.hue,
+                               uvd->vpic.colour, uvd->vpic.contrast));
+       CHECK_RET(ret, qcm_sensor_set_exposure(uvd, uvd->vpic.brightness));
+       CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness));
+       CHECK_RET(ret, qcm_set_camera_size(uvd));
+       CHECK_RET(ret, qcm_camera_on(uvd));
+       return 0;
+}
+
+static void qcm_adjust_picture(struct uvd *uvd)
+{
+       int ret;
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+
+       ret = qcm_camera_off(uvd);
+       if (ret) {
+               err("can't turn camera off. abandoning pic adjustment");
+               return;
+       }
+
+       /* if there's been a change in contrast, hue, or
+       colour then we need to recalculate hsv in order
+       to update gains */
+       if ((cam->contrast != uvd->vpic.contrast) ||
+               (cam->hue != uvd->vpic.hue) ||
+               (cam->colour != uvd->vpic.colour)) {
+               cam->contrast = uvd->vpic.contrast;
+               cam->hue = uvd->vpic.hue;
+               cam->colour = uvd->vpic.colour;
+               ret = qcm_sensor_set_gains(uvd, cam->hue, cam->colour,
+                                               cam->contrast);
+               if (ret) {
+                       err("can't set gains. abandoning pic adjustment");
+                       return;
+               }
+       }
+
+       if (cam->brightness != uvd->vpic.brightness) {
+               cam->brightness = uvd->vpic.brightness;
+               ret = qcm_sensor_set_exposure(uvd, cam->brightness);
+               if (ret) {
+                       err("can't set exposure. abandoning pic adjustment");
+                       return;
+               }
+       }
+
+       if (cam->whiteness != uvd->vpic.whiteness) {
+               cam->whiteness = uvd->vpic.whiteness;
+               qcm_sensor_set_shutter(uvd, cam->whiteness);
+               if (ret) {
+                       err("can't set shutter. abandoning pic adjustment");
+                       return;
+               }
+       }
+
+       ret = qcm_camera_on(uvd);
+       if (ret) {
+               err("can't reenable camera. pic adjustment failed");
+               return;
+       }
+}
+
+static int qcm_process_frame(struct uvd *uvd, u8 *cdata, int framelen)
+{
+       int datalen;
+       int totaldata;
+       struct framehdr {
+               __be16 id;
+               __be16 len;
+       };
+       struct framehdr *fhdr;
+
+       totaldata = 0;
+       while (framelen) {
+               fhdr = (struct framehdr *) cdata;
+               datalen = be16_to_cpu(fhdr->len);
+               framelen -= 4;
+               cdata += 4;
+
+               if ((fhdr->id) == cpu_to_be16(0x8001)) {
+                       RingQueue_Enqueue(&uvd->dp, marker, 4);
+                       totaldata += 4;
+                       continue;
+               }
+               if ((fhdr->id & cpu_to_be16(0xFF00)) == cpu_to_be16(0x0200)) {
+                       RingQueue_Enqueue(&uvd->dp, cdata, datalen);
+                       totaldata += datalen;
+               }
+               framelen -= datalen;
+               cdata += datalen;
+       }
+       return totaldata;
+}
+
+static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb)
+{
+       int totlen;
+       int i;
+       unsigned char *cdata;
+
+       totlen=0;
+       for (i = 0; i < dataurb->number_of_packets; i++) {
+               int n = dataurb->iso_frame_desc[i].actual_length;
+               int st = dataurb->iso_frame_desc[i].status;
+
+               cdata = dataurb->transfer_buffer +
+                       dataurb->iso_frame_desc[i].offset;
+
+               if (st < 0) {
+                       warn("Data error: packet=%d. len=%d. status=%d.",
+                             i, n, st);
+                       uvd->stats.iso_err_count++;
+                       continue;
+               }
+               if (!n)
+                       continue;
+
+               totlen += qcm_process_frame(uvd, cdata, n);
+       }
+       return totlen;
+}
+
+static void resubmit_urb(struct uvd *uvd, struct urb *urb)
+{
+       int ret;
+
+       urb->dev = uvd->dev;
+       ret = usb_submit_urb(urb, GFP_ATOMIC);
+       if (ret)
+               err("usb_submit_urb error (%d)", ret);
+}
+
+static void qcm_isoc_irq(struct urb *urb, struct pt_regs *regs)
+{
+       int len;
+       struct uvd *uvd = urb->context;
+
+       if (!CAMERA_IS_OPERATIONAL(uvd))
+               return;
+
+       if (!uvd->streaming)
+               return;
+
+       uvd->stats.urb_count++;
+
+       if (!urb->actual_length) {
+               resubmit_urb(uvd, urb);
+               return;
+       }
+
+       len = qcm_compress_iso(uvd, urb);
+       resubmit_urb(uvd, urb);
+       uvd->stats.urb_length = len;
+       uvd->stats.data_count += len;
+       if (len)
+               RingQueue_WakeUpInterruptible(&uvd->dp);
+}
+
+static int qcm_start_data(struct uvd *uvd)
+{
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+       int i;
+       int errflag;
+       int pktsz;
+       int err;
+
+       pktsz = uvd->iso_packet_len;
+       if (!CAMERA_IS_OPERATIONAL(uvd)) {
+               err("Camera is not operational");
+               return -EFAULT;
+       }
+
+       err = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltActive);
+       if (err < 0) {
+               err("usb_set_interface error");
+               uvd->last_error = err;
+               return -EBUSY;
+       }
+
+       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+               int j, k;
+               struct urb *urb = uvd->sbuf[i].urb;
+               urb->dev = uvd->dev;
+               urb->context = uvd;
+               urb->pipe = usb_rcvisocpipe(uvd->dev, uvd->video_endp);
+               urb->interval = 1;
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_buffer = uvd->sbuf[i].data;
+               urb->complete = qcm_isoc_irq;
+               urb->number_of_packets = FRAMES_PER_DESC;
+               urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC;
+               for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length = pktsz;
+               }
+       }
+
+       uvd->streaming = 1;
+       uvd->curframe = -1;
+       for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+               errflag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
+               if (errflag)
+                       err ("usb_submit_isoc(%d) ret %d", i, errflag);
+       }
+
+       CHECK_RET(err, qcm_setup_input_int(cam, uvd));
+       CHECK_RET(err, qcm_camera_on(uvd));
+       return 0;
+}
+
+static void qcm_stop_data(struct uvd *uvd)
+{
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+       int i, j;
+       int ret;
+
+       if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
+               return;
+
+       ret = qcm_camera_off(uvd);
+       if (ret)
+               warn("couldn't turn the cam off.");
+
+       uvd->streaming = 0;
+
+       /* Unschedule all of the iso td's */
+       for (i=0; i < USBVIDEO_NUMSBUF; i++)
+               usb_kill_urb(uvd->sbuf[i].urb);
+
+       qcm_stop_int_data(cam);
+
+       if (!uvd->remove_pending) {
+               /* Set packet size to 0 */
+               j = usb_set_interface(uvd->dev, uvd->iface,
+                                       uvd->ifaceAltInactive);
+               if (j < 0) {
+                       err("usb_set_interface() error %d.", j);
+                       uvd->last_error = j;
+               }
+       }
+}
+
+static void qcm_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
+{
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+       int x;
+       struct rgb *rgbL0;
+       struct rgb *rgbL1;
+       struct bayL0 *bayL0;
+       struct bayL1 *bayL1;
+       int hor,ver,hordel,verdel;
+       assert(frame != NULL);
+
+       switch (cam->size) {
+       case SIZE_160X120:
+               hor = 162; ver = 124; hordel = 1; verdel = 2;
+               break;
+       case SIZE_320X240:
+       default:
+               hor = 324; ver = 248; hordel = 2; verdel = 4;
+               break;
+       }
+
+       if (frame->scanstate == ScanState_Scanning) {
+               while (RingQueue_GetLength(&uvd->dp) >=
+                        4 + (hor*verdel + hordel)) {
+                       if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
+                           (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&
+                           (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&
+                           (RING_QUEUE_PEEK(&uvd->dp, 3) == 0xff)) {
+                               frame->curline = 0;
+                               frame->scanstate = ScanState_Lines;
+                               frame->frameState = FrameState_Grabbing;
+                               RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);
+                       /*
+                       * if we're starting, we need to discard the first
+                       * 4 lines of y bayer data
+                       * and the first 2 gr elements of x bayer data
+                       */
+                               RING_QUEUE_DEQUEUE_BYTES(&uvd->dp,
+                                                       (hor*verdel + hordel));
+                               break;
+                       }
+                       RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
+               }
+       }
+
+       if (frame->scanstate == ScanState_Scanning)
+               return;
+
+       /* now we can start processing bayer data so long as we have at least
+       * 2 lines worth of data. this is the simplest demosaicing method that
+       * I could think of. I use each 2x2 bayer element without interpolation
+       * to generate 4 rgb pixels.
+       */
+       while ( frame->curline < cam->height &&
+               (RingQueue_GetLength(&uvd->dp) >= hor*2)) {
+               /* get 2 lines of bayer for demosaicing
+                * into 2 lines of RGB */
+               RingQueue_Dequeue(&uvd->dp, cam->scratch, hor*2);
+               bayL0 = (struct bayL0 *) cam->scratch;
+               bayL1 = (struct bayL1 *) (cam->scratch + hor);
+               /* frame->curline is the rgb y line */
+               rgbL0 = (struct rgb *)
+                               ( frame->data + (cam->width*3*frame->curline));
+               /* w/2 because we're already doing 2 pixels */
+               rgbL1 = rgbL0 + (cam->width/2);
+
+               for (x=0; x < cam->width; x+=2) {
+                       rgbL0->r = bayL0->r;
+                       rgbL0->g = bayL0->g;
+                       rgbL0->b = bayL1->b;
+
+                       rgbL0->r2 = bayL0->r;
+                       rgbL0->g2 = bayL1->g;
+                       rgbL0->b2 = bayL1->b;
+
+                       rgbL1->r = bayL0->r;
+                       rgbL1->g = bayL1->g;
+                       rgbL1->b = bayL1->b;
+
+                       rgbL1->r2 = bayL0->r;
+                       rgbL1->g2 = bayL1->g;
+                       rgbL1->b2 = bayL1->b;
+
+                       rgbL0++;
+                       rgbL1++;
+
+                       bayL0++;
+                       bayL1++;
+               }
+
+               frame->seqRead_Length += cam->width*3*2;
+               frame->curline += 2;
+       }
+       /* See if we filled the frame */
+       if (frame->curline == cam->height) {
+               frame->frameState = FrameState_Done_Hold;
+               frame->curline = 0;
+               uvd->curframe = -1;
+               uvd->stats.frame_num++;
+       }
+}
+
+/* taken from konicawc */
+static int qcm_set_video_mode(struct uvd *uvd, struct video_window *vw)
+{
+       int ret;
+       int newsize;
+       int oldsize;
+       int x = vw->width;
+       int y = vw->height;
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+
+       if (x > 0 && y > 0) {
+               DEBUG(2, "trying to find size %d,%d", x, y);
+               for (newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) {
+                       if ((camera_sizes[newsize].width == x) &&
+                               (camera_sizes[newsize].height == y))
+                               break;
+               }
+       } else
+               newsize = cam->size;
+
+       if (newsize > MAX_FRAME_SIZE) {
+               DEBUG(1, "couldn't find size %d,%d", x, y);
+               return -EINVAL;
+       }
+
+       if (newsize == cam->size) {
+               DEBUG(1, "Nothing to do");
+               return 0;
+       }
+
+       qcm_stop_data(uvd);
+
+       if (cam->size != newsize) {
+               oldsize = cam->size;
+               cam->size = newsize;
+               ret = qcm_set_camera_size(uvd);
+               if (ret) {
+                       err("Couldn't set camera size, err=%d",ret);
+                       /* restore the original size */
+                       cam->size = oldsize;
+                       return ret;
+               }
+       }
+
+       /* Flush the input queue and clear any current frame in progress */
+
+       RingQueue_Flush(&uvd->dp);
+       if (uvd->curframe != -1) {
+               uvd->frame[uvd->curframe].curline = 0;
+               uvd->frame[uvd->curframe].seqRead_Length = 0;
+               uvd->frame[uvd->curframe].seqRead_Index = 0;
+       }
+
+       CHECK_RET(ret, qcm_start_data(uvd));
+       return 0;
+}
+
+static int qcm_configure_video(struct uvd *uvd)
+{
+       int ret;
+       memset(&uvd->vpic, 0, sizeof(uvd->vpic));
+       memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
+
+       uvd->vpic.colour = colour;
+       uvd->vpic.hue = hue;
+       uvd->vpic.brightness = brightness;
+       uvd->vpic.contrast = contrast;
+       uvd->vpic.whiteness = whiteness;
+       uvd->vpic.depth = 24;
+       uvd->vpic.palette = VIDEO_PALETTE_RGB24;
+
+       memset(&uvd->vcap, 0, sizeof(uvd->vcap));
+       strcpy(uvd->vcap.name, "QCM USB Camera");
+       uvd->vcap.type = VID_TYPE_CAPTURE;
+       uvd->vcap.channels = 1;
+       uvd->vcap.audios = 0;
+
+       uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width;
+       uvd->vcap.minheight = camera_sizes[SIZE_160X120].height;
+       uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width;
+       uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height;
+
+       memset(&uvd->vchan, 0, sizeof(uvd->vchan));
+       uvd->vchan.flags = 0 ;
+       uvd->vchan.tuners = 0;
+       uvd->vchan.channel = 0;
+       uvd->vchan.type = VIDEO_TYPE_CAMERA;
+       strcpy(uvd->vchan.name, "Camera");
+
+       CHECK_RET(ret, qcm_sensor_init(uvd));
+       return 0;
+}
+
+static int qcm_probe(struct usb_interface *intf,
+                       const struct usb_device_id *devid)
+{
+       int err;
+       struct uvd *uvd;
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct qcm *cam;
+       size_t buffer_size;
+       unsigned char video_ep;
+       struct usb_host_interface *interface;
+       struct usb_endpoint_descriptor *endpoint;
+       int i,j;
+       unsigned int ifacenum, ifacenum_inact=0;
+       __le16 sensor_id;
+
+       /* we don't support multiconfig cams */
+       if (dev->descriptor.bNumConfigurations != 1)
+               return -ENODEV;
+
+       /* first check for the video interface and not
+       * the audio interface */
+       interface = &intf->cur_altsetting[0];
+       if ((interface->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
+               || (interface->desc.bInterfaceSubClass !=
+                       USB_CLASS_VENDOR_SPEC))
+               return -ENODEV;
+
+       /*
+       walk through each endpoint in each setting in the interface
+       stop when we find the one that's an isochronous IN endpoint.
+       */
+       for (i=0; i < intf->num_altsetting; i++) {
+               interface = &intf->cur_altsetting[i];
+               ifacenum = interface->desc.bAlternateSetting;
+               /* walk the end points */
+               for (j=0; j < interface->desc.bNumEndpoints; j++) {
+                       endpoint = &interface->endpoint[j].desc;
+
+                       if ((endpoint->bEndpointAddress &
+                               USB_ENDPOINT_DIR_MASK) != USB_DIR_IN)
+                               continue; /* not input then not good */
+
+                       buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+                       if (!buffer_size) {
+                               ifacenum_inact = ifacenum;
+                               continue; /* 0 pkt size is not what we want */
+                       }
+
+                       if ((endpoint->bmAttributes &
+                               USB_ENDPOINT_XFERTYPE_MASK) ==
+                               USB_ENDPOINT_XFER_ISOC) {
+                               video_ep = endpoint->bEndpointAddress;
+                               /* break out of the search */
+                               goto good_videoep;
+                       }
+               }
+       }
+       /* failed out since nothing useful was found */
+       err("No suitable endpoint was found\n");
+       return -ENODEV;
+
+good_videoep:
+       /* disable isochronous stream before doing anything else */
+       err = qcm_stv_setb(dev, STV_ISO_ENABLE, 0);
+       if (err < 0) {
+               err("Failed to disable sensor stream");
+               return -EIO;
+       }
+
+       /*
+       Check that this is the same unknown sensor that is known to work. This
+       sensor is suspected to be the ST VV6422C001. I'll check the same value
+       that the qc-usb driver checks. This value is probably not even the
+       sensor ID since it matches the USB dev ID. Oh well. If it doesn't
+       match, it's probably a diff sensor so exit and apologize.
+       */
+       err = qcm_stv_getw(dev, CMOS_SENSOR_IDREV, &sensor_id);
+       if (err < 0) {
+               err("Couldn't read sensor values. Err %d\n",err);
+               return err;
+       }
+       if (sensor_id != cpu_to_le16(0x08F0)) {
+               err("Sensor ID %x != %x. Unsupported. Sorry\n",
+                       le16_to_cpu(sensor_id), (0x08F0));
+               return -ENODEV;
+       }
+
+       uvd = usbvideo_AllocateDevice(cams);
+       if (!uvd)
+               return -ENOMEM;
+
+       cam = (struct qcm *) uvd->user_data;
+
+       /* buf for doing demosaicing */
+       cam->scratch = kmalloc(324*2, GFP_KERNEL);
+       if (!cam->scratch) /* uvd freed in dereg */
+               return -ENOMEM;
+
+       /* yes, if we fail after here, cam->scratch gets freed
+       by qcm_free_uvd */
+
+       err = qcm_alloc_int_urb(cam);
+       if (err < 0)
+               return err;
+
+       /* yes, if we fail after here, int urb gets freed
+       by qcm_free_uvd */
+
+       RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240);
+       cam->width = camera_sizes[size].width;
+       cam->height = camera_sizes[size].height;
+       cam->size = size;
+
+       uvd->debug = debug;
+       uvd->flags = 0;
+       uvd->dev = dev;
+       uvd->iface = intf->altsetting->desc.bInterfaceNumber;
+       uvd->ifaceAltActive = ifacenum;
+       uvd->ifaceAltInactive = ifacenum_inact;
+       uvd->video_endp = video_ep;
+       uvd->iso_packet_len = buffer_size;
+       uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
+       uvd->defaultPalette = VIDEO_PALETTE_RGB24;
+       uvd->canvas = VIDEOSIZE(320, 240);
+       uvd->videosize = VIDEOSIZE(cam->width, cam->height);
+       err = qcm_configure_video(uvd);
+       if (err) {
+               err("failed to configure video settings");
+               return err;
+       }
+
+       err = usbvideo_RegisterVideoDevice(uvd);
+       if (err) { /* the uvd gets freed in Deregister */
+               err("usbvideo_RegisterVideoDevice() failed.");
+               return err;
+       }
+
+       uvd->max_frame_size = (320 * 240 * 3);
+       qcm_register_input(cam, dev);
+       usb_set_intfdata(intf, uvd);
+       return 0;
+}
+
+static void qcm_free_uvd(struct uvd *uvd)
+{
+       struct qcm *cam = (struct qcm *) uvd->user_data;
+
+       kfree(cam->scratch);
+       qcm_unregister_input(cam);
+       qcm_free_int(cam);
+}
+
+static struct usbvideo_cb qcm_driver = {
+       .probe =                qcm_probe,
+       .setupOnOpen =          qcm_setup_on_open,
+       .processData =          qcm_process_isoc,
+       .setVideoMode =         qcm_set_video_mode,
+       .startDataPump =        qcm_start_data,
+       .stopDataPump =         qcm_stop_data,
+       .adjustPicture =        qcm_adjust_picture,
+       .userFree =             qcm_free_uvd
+};
+
+static int __init qcm_init(void)
+{
+       info(DRIVER_DESC " " DRIVER_VERSION);
+
+       return usbvideo_register(
+               &cams,
+               MAX_CAMERAS,
+               sizeof(struct qcm),
+               "QCM",
+               &qcm_driver,
+               THIS_MODULE,
+               qcm_table);
+}
+
+static void __exit qcm_exit(void)
+{
+       usbvideo_Deregister(&cams);
+}
+
+module_param(size, int, 0);
+MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 320x240");
+module_param(colour, int, 0);
+MODULE_PARM_DESC(colour, "Initial colour");
+module_param(hue, int, 0);
+MODULE_PARM_DESC(hue, "Initial hue");
+module_param(brightness, int, 0);
+MODULE_PARM_DESC(brightness, "Initial brightness");
+module_param(contrast, int, 0);
+MODULE_PARM_DESC(contrast, "Initial contrast");
+module_param(whiteness, int, 0);
+MODULE_PARM_DESC(whiteness, "Initial whiteness");
+
+#ifdef CONFIG_USB_DEBUG
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
+#endif
+
+module_init(qcm_init);
+module_exit(qcm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_DESCRIPTION("QCM USB Camera");
+MODULE_SUPPORTED_DEVICE("QCM USB Camera");
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.h b/drivers/media/video/usbvideo/quickcam_messenger.h
new file mode 100644 (file)
index 0000000..baab9c0
--- /dev/null
@@ -0,0 +1,126 @@
+#ifndef quickcam_messenger_h
+#define quickcam_messenger_h
+
+#ifndef CONFIG_INPUT
+/* if we're not using input we dummy out these functions */
+#define qcm_register_input(...)
+#define qcm_unregister_input(...)
+#define qcm_report_buttonstat(...)
+#define qcm_setup_input_int(...) 0
+#define qcm_stop_int_data(...)
+#define qcm_alloc_int_urb(...) 0
+#define qcm_free_int(...)
+#endif
+
+
+#define CHECK_RET(ret, expr) \
+       if ((ret = expr) < 0) return ret
+
+/* Control Registers for the STVV6422 ASIC
+ * - this define is taken from the qc-usb-messenger code
+ */
+#define STV_ISO_ENABLE         0x1440
+#define ISOC_PACKET_SIZE       1023
+
+/* Chip identification number including revision indicator */
+#define CMOS_SENSOR_IDREV      0xE00A
+
+struct rgb {
+       u8 b;
+       u8 g;
+       u8 r;
+       u8 b2;
+       u8 g2;
+       u8 r2;
+};
+
+struct bayL0 {
+#ifdef __BIG_ENDIAN
+       u8 r;
+       u8 g;
+#elif __LITTLE_ENDIAN
+       u8 g;
+       u8 r;
+#else
+#error not byte order defined
+#endif
+};
+
+struct bayL1 {
+#ifdef __BIG_ENDIAN
+       u8 g;
+       u8 b;
+#elif __LITTLE_ENDIAN
+       u8 b;
+       u8 g;
+#else
+#error not byte order defined
+#endif
+};
+
+struct cam_size {
+       u16     width;
+       u16     height;
+       u8      cmd;
+};
+
+static const struct cam_size camera_sizes[] = {
+       { 160, 120, 0xf },
+       { 320, 240, 0x2 },
+};
+
+enum frame_sizes {
+       SIZE_160X120    = 0,
+       SIZE_320X240    = 1,
+};
+
+#define MAX_FRAME_SIZE SIZE_320X240
+
+struct qcm {
+       u16 colour;
+       u16 hue;
+       u16 brightness;
+       u16 contrast;
+       u16 whiteness;
+
+       u8 size;
+       int height;
+       int width;
+       u8 *scratch;
+       struct urb *button_urb;
+       u8 button_sts;
+       u8 button_sts_buf;
+
+#ifdef CONFIG_INPUT
+       struct input_dev *input;
+       char input_physname[64];
+#endif
+};
+
+struct regval {
+       u16 reg;
+       u8 val;
+};
+/* this table is derived from the
+qc-usb-messenger code */
+static const struct regval regval_table[] = {
+       { STV_ISO_ENABLE, 0x00 },
+       { 0x1436, 0x00 }, { 0x1432, 0x03 },
+       { 0x143a, 0xF9 }, { 0x0509, 0x38 },
+       { 0x050a, 0x38 }, { 0x050b, 0x38 },
+       { 0x050c, 0x2A }, { 0x050d, 0x01 },
+       { 0x1431, 0x00 }, { 0x1433, 0x34 },
+       { 0x1438, 0x18 }, { 0x1439, 0x00 },
+       { 0x143b, 0x05 }, { 0x143c, 0x00 },
+       { 0x143e, 0x01 }, { 0x143d, 0x00 },
+       { 0x1442, 0xe2 }, { 0x1500, 0xd0 },
+       { 0x1500, 0xd0 }, { 0x1500, 0x50 },
+       { 0x1501, 0xaf }, { 0x1502, 0xc2 },
+       { 0x1503, 0x45 }, { 0x1505, 0x02 },
+       { 0x150e, 0x8e }, { 0x150f, 0x37 },
+       { 0x15c0, 0x00 },
+};
+
+static const unsigned char marker[] = { 0x00, 0xff, 0x00, 0xFF };
+
+#endif /* quickcam_messenger_h */
index 3cbf4fc499a337c263fd34833f04f6fe0e9219dd..49dbee5f5628b49a38a299385e0da4d64b17eccd 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <linux/config.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 
index 474a29bc1760d9feedc2bf8beb6b7d8907666783..19d3c20dc7efd73a4f1cf3b58376dbf953584011 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
index d330fa985bcc2049e4fbba5d16dc6af496583789..14e523471354b160c4d8a078d3c90791d118ca5f 100644 (file)
@@ -59,6 +59,7 @@
 #include <asm/io.h>
 #include <asm/div64.h>
 #include <linux/video_decoder.h>
+#define __OLD_VIDIOC_ /* To allow fixing old calls*/
 #include <media/v4l2-common.h>
 
 #ifdef CONFIG_KMOD
@@ -293,7 +294,10 @@ static const char *v4l2_ioctls[] = {
 #if 1
        [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
 #endif
-       [_IOC_NR(VIDIOC_LOG_STATUS)]       = "VIDIOC_LOG_STATUS"
+       [_IOC_NR(VIDIOC_LOG_STATUS)]       = "VIDIOC_LOG_STATUS",
+       [_IOC_NR(VIDIOC_G_EXT_CTRLS)]      = "VIDIOC_G_EXT_CTRLS",
+       [_IOC_NR(VIDIOC_S_EXT_CTRLS)]      = "VIDIOC_S_EXT_CTRLS",
+       [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)]    = "VIDIOC_TRY_EXT_CTRLS"
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
@@ -331,7 +335,8 @@ static const char *v4l2_int_ioctls[] = {
        [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)]  = "VIDIOC_INT_S_AUDIO_ROUTING",
        [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)]  = "VIDIOC_INT_G_AUDIO_ROUTING",
        [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)]  = "VIDIOC_INT_S_VIDEO_ROUTING",
-       [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)]  = "VIDIOC_INT_G_VIDEO_ROUTING"
+       [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)]  = "VIDIOC_INT_G_VIDEO_ROUTING",
+       [_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)]   = "VIDIOC_INT_S_CRYSTAL_FREQ"
 };
 #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
 
@@ -423,7 +428,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
        case TUNER_SET_TYPE_ADDR:
        case TUNER_SET_STANDBY:
        case TDA9887_SET_CONFIG:
+#ifdef __OLD_VIDIOC_
        case VIDIOC_OVERLAY_OLD:
+#endif
        case VIDIOC_STREAMOFF:
        case VIDIOC_G_OUTPUT:
        case VIDIOC_S_OUTPUT:
@@ -439,7 +446,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
        case VIDIOC_G_AUDIO:
        case VIDIOC_S_AUDIO:
        case VIDIOC_ENUMAUDIO:
+#ifdef __OLD_VIDIOC_
        case VIDIOC_G_AUDIO_OLD:
+#endif
        {
                struct v4l2_audio *p=arg;
 
@@ -450,7 +459,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
        case VIDIOC_G_AUDOUT:
        case VIDIOC_S_AUDOUT:
        case VIDIOC_ENUMAUDOUT:
+#ifdef __OLD_VIDIOC_
        case VIDIOC_G_AUDOUT_OLD:
+#endif
        {
                struct v4l2_audioout *p=arg;
                printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", s,
@@ -478,9 +489,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
                                prt_names(p->memory,v4l2_memory_names),
                                p->m.userptr);
                printk ("%s: timecode= %02d:%02d:%02d type=%d, "
-                       "flags=0x%08x, frames=%d, userbits=0x%p\n",
+                       "flags=0x%08x, frames=%d, userbits=0x%08x\n",
                                s,tc->hours,tc->minutes,tc->seconds,
-                               tc->type, tc->flags, tc->frames, tc->userbits);
+                               tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits);
                break;
        }
        case VIDIOC_QUERYCAP:
@@ -495,12 +506,31 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
        }
        case VIDIOC_G_CTRL:
        case VIDIOC_S_CTRL:
+#ifdef __OLD_VIDIOC_
        case VIDIOC_S_CTRL_OLD:
+#endif
        {
                struct v4l2_control *p=arg;
                printk ("%s: id=%d, value=%d\n", s, p->id, p->value);
                break;
        }
+       case VIDIOC_G_EXT_CTRLS:
+       case VIDIOC_S_EXT_CTRLS:
+       case VIDIOC_TRY_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *p = arg;
+               int i;
+
+               printk("%s: ctrl_class=%d, count=%d\n", s, p->ctrl_class, p->count);
+               for (i = 0; i < p->count; i++) {
+                       struct v4l2_ext_control *c = &p->controls[i];
+                       if (cmd == VIDIOC_G_EXT_CTRLS)
+                               printk("%s: id=%d\n", s, c->id);
+                       else
+                               printk("%s: id=%d, value=%d\n", s, c->id, c->value);
+               }
+               break;
+       }
        case VIDIOC_G_CROP:
        case VIDIOC_S_CROP:
        {
@@ -510,7 +540,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
                break;
        }
        case VIDIOC_CROPCAP:
+#ifdef __OLD_VIDIOC_
        case VIDIOC_CROPCAP_OLD:
+#endif
        {
                struct v4l2_cropcap *p=arg;
                /*FIXME: Should also show rect structs */
@@ -667,6 +699,12 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
                printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output);
                break;
        }
+       case VIDIOC_INT_S_CRYSTAL_FREQ:
+       {
+               struct v4l2_crystal_freq *p=arg;
+               printk ("%s: freq=%u, flags=0x%x\n", s, p->freq, p->flags);
+               break;
+       }
        case VIDIOC_G_SLICED_VBI_CAP:
        {
                struct v4l2_sliced_vbi_cap *p=arg;
@@ -696,7 +734,9 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
        }
        case VIDIOC_G_PARM:
        case VIDIOC_S_PARM:
+#ifdef __OLD_VIDIOC_
        case VIDIOC_S_PARM_OLD:
+#endif
        {
                struct v4l2_streamparm *p=arg;
                printk ("%s: type=%d\n", s, p->type);
@@ -915,6 +955,484 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg)
 
 /* ----------------------------------------------------------------- */
 
+/* Helper functions for control handling                            */
+
+/* Check for correctness of the ctrl's value based on the data from
+   struct v4l2_queryctrl and the available menu items. Note that
+   menu_items may be NULL, in that case it is ignored. */
+int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
+               const char **menu_items)
+{
+       if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)
+               return -EINVAL;
+       if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
+               return -EBUSY;
+       if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
+           qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
+           qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
+               return 0;
+       if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum)
+               return -ERANGE;
+       if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) {
+               if (menu_items[ctrl->value] == NULL ||
+                   menu_items[ctrl->value][0] == '\0')
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+/* Returns NULL or a character pointer array containing the menu for
+   the given control ID. The pointer array ends with a NULL pointer.
+   An empty string signifies a menu entry that is invalid. This allows
+   drivers to disable certain options if it is not supported. */
+const char **v4l2_ctrl_get_menu(u32 id)
+{
+       static const char *mpeg_audio_sampling_freq[] = {
+               "44.1 kHz",
+               "48 kHz",
+               "32 kHz",
+               NULL
+       };
+       static const char *mpeg_audio_encoding[] = {
+               "Layer I",
+               "Layer II",
+               "Layer III",
+               NULL
+       };
+       static const char *mpeg_audio_l1_bitrate[] = {
+               "32 kbps",
+               "64 kbps",
+               "96 kbps",
+               "128 kbps",
+               "160 kbps",
+               "192 kbps",
+               "224 kbps",
+               "256 kbps",
+               "288 kbps",
+               "320 kbps",
+               "352 kbps",
+               "384 kbps",
+               "416 kbps",
+               "448 kbps",
+               NULL
+       };
+       static const char *mpeg_audio_l2_bitrate[] = {
+               "32 kbps",
+               "48 kbps",
+               "56 kbps",
+               "64 kbps",
+               "80 kbps",
+               "96 kbps",
+               "112 kbps",
+               "128 kbps",
+               "160 kbps",
+               "192 kbps",
+               "224 kbps",
+               "256 kbps",
+               "320 kbps",
+               "384 kbps",
+               NULL
+       };
+       static const char *mpeg_audio_l3_bitrate[] = {
+               "32 kbps",
+               "40 kbps",
+               "48 kbps",
+               "56 kbps",
+               "64 kbps",
+               "80 kbps",
+               "96 kbps",
+               "112 kbps",
+               "128 kbps",
+               "160 kbps",
+               "192 kbps",
+               "224 kbps",
+               "256 kbps",
+               "320 kbps",
+               NULL
+       };
+       static const char *mpeg_audio_mode[] = {
+               "Stereo",
+               "Joint Stereo",
+               "Dual",
+               "Mono",
+               NULL
+       };
+       static const char *mpeg_audio_mode_extension[] = {
+               "Bound 4",
+               "Bound 8",
+               "Bound 12",
+               "Bound 16",
+               NULL
+       };
+       static const char *mpeg_audio_emphasis[] = {
+               "No Emphasis",
+               "50/15 us",
+               "CCITT J17",
+               NULL
+       };
+       static const char *mpeg_audio_crc[] = {
+               "No CRC",
+               "16-bit CRC",
+               NULL
+       };
+       static const char *mpeg_video_encoding[] = {
+               "MPEG-1",
+               "MPEG-2",
+               NULL
+       };
+       static const char *mpeg_video_aspect[] = {
+               "1x1",
+               "4x3",
+               "16x9",
+               "2.21x1",
+               NULL
+       };
+       static const char *mpeg_video_bitrate_mode[] = {
+               "Variable Bitrate",
+               "Constant Bitrate",
+               NULL
+       };
+       static const char *mpeg_stream_type[] = {
+               "MPEG-2 Program Stream",
+               "MPEG-2 Transport Stream",
+               "MPEG-1 System Stream",
+               "MPEG-2 DVD-compatible Stream",
+               "MPEG-1 VCD-compatible Stream",
+               "MPEG-2 SVCD-compatible Stream",
+               NULL
+       };
+
+       switch (id) {
+               case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+                       return mpeg_audio_sampling_freq;
+               case V4L2_CID_MPEG_AUDIO_ENCODING:
+                       return mpeg_audio_encoding;
+               case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+                       return mpeg_audio_l1_bitrate;
+               case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+                       return mpeg_audio_l2_bitrate;
+               case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+                       return mpeg_audio_l3_bitrate;
+               case V4L2_CID_MPEG_AUDIO_MODE:
+                       return mpeg_audio_mode;
+               case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+                       return mpeg_audio_mode_extension;
+               case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+                       return mpeg_audio_emphasis;
+               case V4L2_CID_MPEG_AUDIO_CRC:
+                       return mpeg_audio_crc;
+               case V4L2_CID_MPEG_VIDEO_ENCODING:
+                       return mpeg_video_encoding;
+               case V4L2_CID_MPEG_VIDEO_ASPECT:
+                       return mpeg_video_aspect;
+               case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+                       return mpeg_video_bitrate_mode;
+               case V4L2_CID_MPEG_STREAM_TYPE:
+                       return mpeg_stream_type;
+               default:
+                       return NULL;
+       }
+}
+
+/* Fill in a struct v4l2_queryctrl */
+int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+{
+       const char *name;
+
+       qctrl->flags = 0;
+       switch (qctrl->id) {
+       /* USER controls */
+       case V4L2_CID_USER_CLASS:       name = "User Controls"; break;
+       case V4L2_CID_AUDIO_VOLUME:     name = "Volume"; break;
+       case V4L2_CID_AUDIO_MUTE:       name = "Mute"; break;
+       case V4L2_CID_AUDIO_BALANCE:    name = "Balance"; break;
+       case V4L2_CID_AUDIO_BASS:       name = "Bass"; break;
+       case V4L2_CID_AUDIO_TREBLE:     name = "Treble"; break;
+       case V4L2_CID_AUDIO_LOUDNESS:   name = "Loudness"; break;
+       case V4L2_CID_BRIGHTNESS:       name = "Brightness"; break;
+       case V4L2_CID_CONTRAST:         name = "Contrast"; break;
+       case V4L2_CID_SATURATION:       name = "Saturation"; break;
+       case V4L2_CID_HUE:              name = "Hue"; break;
+
+       /* MPEG controls */
+       case V4L2_CID_MPEG_CLASS:               name = "MPEG Encoder Controls"; break;
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: name = "Audio Sampling Frequency"; break;
+       case V4L2_CID_MPEG_AUDIO_ENCODING:      name = "Audio Encoding Layer"; break;
+       case V4L2_CID_MPEG_AUDIO_L1_BITRATE:    name = "Audio Layer I Bitrate"; break;
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:    name = "Audio Layer II Bitrate"; break;
+       case V4L2_CID_MPEG_AUDIO_L3_BITRATE:    name = "Audio Layer III Bitrate"; break;
+       case V4L2_CID_MPEG_AUDIO_MODE:          name = "Audio Stereo Mode"; break;
+       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: name = "Audio Stereo Mode Extension"; break;
+       case V4L2_CID_MPEG_AUDIO_EMPHASIS:      name = "Audio Emphasis"; break;
+       case V4L2_CID_MPEG_AUDIO_CRC:           name = "Audio CRC"; break;
+       case V4L2_CID_MPEG_VIDEO_ENCODING:      name = "Video Encoding"; break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:        name = "Video Aspect"; break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:      name = "Video B Frames"; break;
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:      name = "Video GOP Size"; break;
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:   name = "Video GOP Closure"; break;
+       case V4L2_CID_MPEG_VIDEO_PULLDOWN:      name = "Video Pulldown"; break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:  name = "Video Bitrate Mode"; break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:       name = "Video Bitrate"; break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:  name = "Video Peak Bitrate"; break;
+       case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: name = "Video Temporal Decimation"; break;
+       case V4L2_CID_MPEG_STREAM_TYPE:         name = "Stream Type"; break;
+       case V4L2_CID_MPEG_STREAM_PID_PMT:      name = "Stream PMT Program ID"; break;
+       case V4L2_CID_MPEG_STREAM_PID_AUDIO:    name = "Stream Audio Program ID"; break;
+       case V4L2_CID_MPEG_STREAM_PID_VIDEO:    name = "Stream Video Program ID"; break;
+       case V4L2_CID_MPEG_STREAM_PID_PCR:      name = "Stream PCR Program ID"; break;
+       case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: name = "Stream PES Audio ID"; break;
+       case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: name = "Stream PES Video ID"; break;
+
+       default:
+               return -EINVAL;
+       }
+       switch (qctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+       case V4L2_CID_AUDIO_LOUDNESS:
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+       case V4L2_CID_MPEG_VIDEO_PULLDOWN:
+               qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
+               min = 0;
+               max = step = 1;
+               break;
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+       case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+       case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+       case V4L2_CID_MPEG_AUDIO_MODE:
+       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+       case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+       case V4L2_CID_MPEG_AUDIO_CRC:
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               qctrl->type = V4L2_CTRL_TYPE_MENU;
+               step = 1;
+               break;
+       case V4L2_CID_USER_CLASS:
+       case V4L2_CID_MPEG_CLASS:
+               qctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS;
+               qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+               min = max = step = def = 0;
+               break;
+       default:
+               qctrl->type = V4L2_CTRL_TYPE_INTEGER;
+               break;
+       }
+       switch (qctrl->id) {
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+       case V4L2_CID_MPEG_AUDIO_MODE:
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+       case V4L2_CID_BRIGHTNESS:
+       case V4L2_CID_CONTRAST:
+       case V4L2_CID_SATURATION:
+       case V4L2_CID_HUE:
+               qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+               break;
+       }
+       qctrl->minimum = min;
+       qctrl->maximum = max;
+       qctrl->step = step;
+       qctrl->default_value = def;
+       qctrl->reserved[0] = qctrl->reserved[1] = 0;
+       snprintf(qctrl->name, sizeof(qctrl->name), name);
+       return 0;
+}
+
+/* Fill in a struct v4l2_queryctrl with standard values based on
+   the control ID. */
+int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
+{
+       switch (qctrl->id) {
+       /* USER controls */
+       case V4L2_CID_USER_CLASS:
+       case V4L2_CID_MPEG_CLASS:
+               return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
+       case V4L2_CID_AUDIO_VOLUME:
+               return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 58880);
+       case V4L2_CID_AUDIO_MUTE:
+       case V4L2_CID_AUDIO_LOUDNESS:
+               return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+               return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 32768);
+       case V4L2_CID_BRIGHTNESS:
+               return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128);
+       case V4L2_CID_CONTRAST:
+       case V4L2_CID_SATURATION:
+               return v4l2_ctrl_query_fill(qctrl, 0, 127, 1, 64);
+       case V4L2_CID_HUE:
+               return v4l2_ctrl_query_fill(qctrl, -128, 127, 1, 0);
+
+       /* MPEG controls */
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
+                               V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,
+                               V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_ENCODING_LAYER_1,
+                               V4L2_MPEG_AUDIO_ENCODING_LAYER_3, 1,
+                               V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+       case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_L1_BITRATE_32K,
+                               V4L2_MPEG_AUDIO_L1_BITRATE_448K, 1,
+                               V4L2_MPEG_AUDIO_L1_BITRATE_256K);
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_32K,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_224K);
+       case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_L3_BITRATE_32K,
+                               V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1,
+                               V4L2_MPEG_AUDIO_L3_BITRATE_192K);
+       case V4L2_CID_MPEG_AUDIO_MODE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_MODE_STEREO,
+                               V4L2_MPEG_AUDIO_MODE_MONO, 1,
+                               V4L2_MPEG_AUDIO_MODE_STEREO);
+       case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
+                               V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,
+                               V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
+       case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_EMPHASIS_NONE,
+                               V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,
+                               V4L2_MPEG_AUDIO_EMPHASIS_NONE);
+       case V4L2_CID_MPEG_AUDIO_CRC:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_CRC_NONE,
+                               V4L2_MPEG_AUDIO_CRC_CRC16, 1,
+                               V4L2_MPEG_AUDIO_CRC_NONE);
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
+                               V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
+                               V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_VIDEO_ASPECT_1x1,
+                               V4L2_MPEG_VIDEO_ASPECT_221x100, 1,
+                               V4L2_MPEG_VIDEO_ASPECT_4x3);
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, 12);
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+               return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
+       case V4L2_CID_MPEG_VIDEO_PULLDOWN:
+               return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+                               V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
+                               V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
+       case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+               return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+                               V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,
+                               V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
+       case V4L2_CID_MPEG_STREAM_PID_PMT:
+               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16);
+       case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260);
+       case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256);
+       case V4L2_CID_MPEG_STREAM_PID_PCR:
+               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259);
+       case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO:
+               return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+       case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO:
+               return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+       default:
+               return -EINVAL;
+       }
+}
+
+/* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and
+   the menu. The qctrl pointer may be NULL, in which case it is ignored. */
+int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl,
+              const char **menu_items)
+{
+       int i;
+
+       if (menu_items == NULL ||
+           (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum)))
+               return -EINVAL;
+       for (i = 0; i < qmenu->index && menu_items[i]; i++) ;
+       if (menu_items[i] == NULL || menu_items[i][0] == '\0')
+               return -EINVAL;
+       snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]);
+       qmenu->reserved = 0;
+       return 0;
+}
+
+/* ctrl_classes points to an array of u32 pointers, the last element is
+   a NULL pointer. Each u32 array is a 0-terminated array of control IDs.
+   Each array must be sorted low to high and belong to the same control
+   class. The array of u32 pointer must also be sorted, from low class IDs
+   to high class IDs.
+
+   This function returns the first ID that follows after the given ID.
+   When no more controls are available 0 is returned. */
+u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
+{
+       u32 ctrl_class;
+       const u32 *pctrl;
+
+       /* if no query is desired, then just return the control ID */
+       if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0)
+               return id;
+       if (ctrl_classes == NULL)
+               return 0;
+       id &= V4L2_CTRL_ID_MASK;
+       ctrl_class = V4L2_CTRL_ID2CLASS(id);
+       id++;   /* select next control */
+       /* find first class that matches (or is greater than) the class of
+          the ID */
+       while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) < ctrl_class)
+               ctrl_classes++;
+       /* no more classes */
+       if (*ctrl_classes == NULL)
+               return 0;
+       pctrl = *ctrl_classes;
+       /* find first ctrl within the class that is >= ID */
+       while (*pctrl && *pctrl < id) pctrl++;
+       if (*pctrl)
+               return *pctrl;
+       /* we are at the end of the controls of the current class. */
+       /* continue with next class if available */
+       ctrl_classes++;
+       if (*ctrl_classes == NULL)
+               return 0;
+       return **ctrl_classes;
+}
+
+/* ----------------------------------------------------------------- */
+
 EXPORT_SYMBOL(v4l2_video_std_construct);
 
 EXPORT_SYMBOL(v4l2_prio_init);
@@ -929,6 +1447,13 @@ EXPORT_SYMBOL(v4l2_type_names);
 EXPORT_SYMBOL(v4l_printk_ioctl);
 EXPORT_SYMBOL(v4l_printk_ioctl_arg);
 
+EXPORT_SYMBOL(v4l2_ctrl_next);
+EXPORT_SYMBOL(v4l2_ctrl_check);
+EXPORT_SYMBOL(v4l2_ctrl_get_menu);
+EXPORT_SYMBOL(v4l2_ctrl_query_menu);
+EXPORT_SYMBOL(v4l2_ctrl_query_fill);
+EXPORT_SYMBOL(v4l2_ctrl_query_fill_std);
+
 /*
  * Local variables:
  * c-basic-offset: 8
index caf3e7e2f21989cac195c23e88d07beb53194a64..7ee8a53cd336f1702a35b2532071b1955d9af3f2 100644 (file)
@@ -135,14 +135,15 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed)
 
 int videobuf_dvb_register(struct videobuf_dvb *dvb,
                          struct module *module,
-                         void *adapter_priv)
+                         void *adapter_priv,
+                         struct device *device)
 {
        int result;
 
        mutex_init(&dvb->lock);
 
        /* register adapter */
-       result = dvb_register_adapter(&dvb->adapter, dvb->name, module);
+       result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device);
        if (result < 0) {
                printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
                       dvb->name, result);
index 5f87dd5f1d0b7fe28af648e26d10f142aa2cfab9..2dfa7f23d0ca28f7e08a2fa7167184789c32cc29 100644 (file)
@@ -1,20 +1,31 @@
 /*
- * Video capture interface for Linux
+ * Video capture interface for Linux version 2
  *
- *             A generic video device interface for the LINUX operating system
- *             using a set of device structures/vectors for low level operations.
+ *     A generic video device interface for the LINUX operating system
+ *     using a set of device structures/vectors for low level operations.
  *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
  *
- * Author:     Alan Cox, <alan@redhat.com>
+ * Authors:    Alan Cox, <alan@redhat.com> (version 1)
+ *              Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
  *
  * Fixes:      20000516  Claudio Matsuoka <claudio@conectiva.com>
  *             - Added procfs support
  */
 
+#define dbgarg(cmd, fmt, arg...) \
+               if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)                  \
+                       printk (KERN_DEBUG "%s: ",  vfd->name);         \
+                       v4l_printk_ioctl(cmd);                          \
+                       printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
+
+#define dbgarg2(fmt, arg...) \
+               if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)                  \
+                       printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#define __OLD_VIDIOC_ /* To allow fixing old calls*/
+#include <linux/videodev2.h>
+
+#ifdef CONFIG_VIDEO_V4L1
 #include <linux/videodev.h>
+#endif
+#include <media/v4l2-common.h>
 
 #define VIDEO_NUM_DEVICES      256
 #define VIDEO_NAME              "video4linux"
@@ -41,7 +58,8 @@
 
 static ssize_t show_name(struct class_device *cd, char *buf)
 {
-       struct video_device *vfd = container_of(cd, struct video_device, class_dev);
+       struct video_device *vfd = container_of(cd, struct video_device,
+                                                               class_dev);
        return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name);
 }
 
@@ -62,7 +80,8 @@ void video_device_release(struct video_device *vfd)
 
 static void video_release(struct class_device *cd)
 {
-       struct video_device *vfd = container_of(cd, struct video_device, class_dev);
+       struct video_device *vfd = container_of(cd, struct video_device,
+                                                               class_dev);
 
 #if 1
        /* needed until all drivers are fixed */
@@ -90,7 +109,7 @@ struct video_device* video_devdata(struct file *file)
 }
 
 /*
- *     Open a video device.
+ *     Open a video device - FIXME: Obsoleted
  */
 static int video_open(struct inode *inode, struct file *file)
 {
@@ -130,6 +149,7 @@ static int video_open(struct inode *inode, struct file *file)
  * helper function -- handles userspace copying for ioctl arguments
  */
 
+#ifdef __OLD_VIDIOC_
 static unsigned int
 video_fix_command(unsigned int cmd)
 {
@@ -155,7 +175,11 @@ video_fix_command(unsigned int cmd)
        }
        return cmd;
 }
+#endif
 
+/*
+ * Obsolete usercopy function - Should be removed soon
+ */
 int
 video_usercopy(struct inode *inode, struct file *file,
               unsigned int cmd, unsigned long arg,
@@ -166,8 +190,15 @@ video_usercopy(struct inode *inode, struct file *file,
        void    *mbuf = NULL;
        void    *parg = NULL;
        int     err  = -EINVAL;
+       int     is_ext_ctrl;
+       size_t  ctrls_size = 0;
+       void __user *user_ptr = NULL;
 
+#ifdef __OLD_VIDIOC_
        cmd = video_fix_command(cmd);
+#endif
+       is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
+                      cmd == VIDIOC_TRY_EXT_CTRLS);
 
        /*  Copy arguments into temp kernel buffer  */
        switch (_IOC_DIR(cmd)) {
@@ -193,14 +224,43 @@ video_usercopy(struct inode *inode, struct file *file,
                                goto out;
                break;
        }
+       if (is_ext_ctrl) {
+               struct v4l2_ext_controls *p = parg;
+
+               /* In case of an error, tell the caller that it wasn't
+                  a specific control that caused it. */
+               p->error_idx = p->count;
+               user_ptr = (void __user *)p->controls;
+               if (p->count) {
+                       ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
+                       /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
+                       mbuf = kmalloc(ctrls_size, GFP_KERNEL);
+                       err = -ENOMEM;
+                       if (NULL == mbuf)
+                               goto out_ext_ctrl;
+                       err = -EFAULT;
+                       if (copy_from_user(mbuf, user_ptr, ctrls_size))
+                               goto out_ext_ctrl;
+                       p->controls = mbuf;
+               }
+       }
 
        /* call driver */
        err = func(inode, file, cmd, parg);
        if (err == -ENOIOCTLCMD)
                err = -EINVAL;
+       if (is_ext_ctrl) {
+               struct v4l2_ext_controls *p = parg;
+
+               p->controls = (void *)user_ptr;
+               if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
+                       err = -EFAULT;
+               goto out_ext_ctrl;
+       }
        if (err < 0)
                goto out;
 
+out_ext_ctrl:
        /*  Copy results into user buffer  */
        switch (_IOC_DIR(cmd))
        {
@@ -218,6 +278,7 @@ out:
 
 /*
  * open/release helper functions -- handle exclusive opens
+ * Should be removed soon
  */
 int video_exclusive_open(struct inode *inode, struct file *file)
 {
@@ -242,6 +303,1184 @@ int video_exclusive_release(struct inode *inode, struct file *file)
        return 0;
 }
 
+static char *v4l2_memory_names[] = {
+       [V4L2_MEMORY_MMAP]    = "mmap",
+       [V4L2_MEMORY_USERPTR] = "userptr",
+       [V4L2_MEMORY_OVERLAY] = "overlay",
+};
+
+
+/* FIXME: Those stuff are replicated also on v4l2-common.c */
+static char *v4l2_type_names_FIXME[] = {
+       [V4L2_BUF_TYPE_VIDEO_CAPTURE]      = "video-cap",
+       [V4L2_BUF_TYPE_VIDEO_OVERLAY]      = "video-over",
+       [V4L2_BUF_TYPE_VIDEO_OUTPUT]       = "video-out",
+       [V4L2_BUF_TYPE_VBI_CAPTURE]        = "vbi-cap",
+       [V4L2_BUF_TYPE_VBI_OUTPUT]         = "vbi-out",
+       [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "sliced-vbi-out",
+       [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-capture",
+       [V4L2_BUF_TYPE_PRIVATE]            = "private",
+};
+
+static char *v4l2_field_names_FIXME[] = {
+       [V4L2_FIELD_ANY]        = "any",
+       [V4L2_FIELD_NONE]       = "none",
+       [V4L2_FIELD_TOP]        = "top",
+       [V4L2_FIELD_BOTTOM]     = "bottom",
+       [V4L2_FIELD_INTERLACED] = "interlaced",
+       [V4L2_FIELD_SEQ_TB]     = "seq-tb",
+       [V4L2_FIELD_SEQ_BT]     = "seq-bt",
+       [V4L2_FIELD_ALTERNATE]  = "alternate",
+};
+
+#define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown"
+
+static void dbgbuf(unsigned int cmd, struct video_device *vfd,
+                                       struct v4l2_buffer *p)
+{
+       struct v4l2_timecode *tc=&p->timecode;
+
+       dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
+               "bytesused=%d, flags=0x%08d, "
+               "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n",
+                       (p->timestamp.tv_sec/3600),
+                       (int)(p->timestamp.tv_sec/60)%60,
+                       (int)(p->timestamp.tv_sec%60),
+                       p->timestamp.tv_usec,
+                       p->index,
+                       prt_names(p->type,v4l2_type_names_FIXME),
+                       p->bytesused,p->flags,
+                       p->field,p->sequence,
+                       prt_names(p->memory,v4l2_memory_names),
+                       p->m.userptr);
+       dbgarg2 ("timecode= %02d:%02d:%02d type=%d, "
+               "flags=0x%08d, frames=%d, userbits=0x%08x\n",
+                       tc->hours,tc->minutes,tc->seconds,
+                       tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits);
+}
+
+static inline void dbgrect(struct video_device *vfd, char *s,
+                                                       struct v4l2_rect *r)
+{
+       dbgarg2 ("%sRect start at %dx%d, size= %dx%d\n", s, r->left, r->top,
+                                               r->width, r->height);
+};
+
+static inline void v4l_print_pix_fmt (struct video_device *vfd,
+                                               struct v4l2_pix_format *fmt)
+{
+       dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, "
+               "bytesperline=%d sizeimage=%d, colorspace=%d\n",
+               fmt->width,fmt->height,fmt->pixelformat,
+               prt_names(fmt->field,v4l2_field_names_FIXME),
+               fmt->bytesperline,fmt->sizeimage,fmt->colorspace);
+};
+
+
+static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type)
+{
+       switch (type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               if (vfd->vidioc_try_fmt_cap)
+                       return (0);
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+               if (vfd->vidioc_try_fmt_overlay)
+                       return (0);
+               break;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               if (vfd->vidioc_try_fmt_vbi)
+                       return (0);
+               break;
+       case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+               if (vfd->vidioc_try_fmt_vbi_output)
+                       return (0);
+               break;
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+               if (vfd->vidioc_try_fmt_vbi_capture)
+                       return (0);
+               break;
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               if (vfd->vidioc_try_fmt_video_output)
+                       return (0);
+               break;
+       case V4L2_BUF_TYPE_VBI_OUTPUT:
+               if (vfd->vidioc_try_fmt_vbi_output)
+                       return (0);
+               break;
+       case V4L2_BUF_TYPE_PRIVATE:
+               if (vfd->vidioc_try_fmt_type_private)
+                       return (0);
+               break;
+       }
+       return (-EINVAL);
+}
+
+static int __video_do_ioctl(struct inode *inode, struct file *file,
+               unsigned int cmd, void *arg)
+{
+       struct video_device *vfd = video_devdata(file);
+       void                 *fh = file->private_data;
+       int                  ret = -EINVAL;
+
+       if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
+                               !(vfd->debug | V4L2_DEBUG_IOCTL_ARG)) {
+               v4l_print_ioctl(vfd->name, cmd);
+       }
+
+       switch(cmd) {
+       /* --- capabilities ------------------------------------------ */
+       case VIDIOC_QUERYCAP:
+       {
+               struct v4l2_capability *cap = (struct v4l2_capability*)arg;
+               memset(cap, 0, sizeof(*cap));
+
+               if (!vfd->vidioc_querycap)
+                       break;
+
+               ret=vfd->vidioc_querycap(file, fh, cap);
+               if (!ret)
+                       dbgarg (cmd, "driver=%s, card=%s, bus=%s, "
+                                       "version=0x%08x, "
+                                       "capabilities=0x%08x\n",
+                                       cap->driver,cap->card,cap->bus_info,
+                                       cap->version,
+                                       cap->capabilities);
+               break;
+       }
+
+       /* --- priority ------------------------------------------ */
+       case VIDIOC_G_PRIORITY:
+       {
+               enum v4l2_priority *p=arg;
+
+               if (!vfd->vidioc_g_priority)
+                       break;
+               ret=vfd->vidioc_g_priority(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "priority is %d\n", *p);
+               break;
+       }
+       case VIDIOC_S_PRIORITY:
+       {
+               enum v4l2_priority *p=arg;
+
+               if (!vfd->vidioc_s_priority)
+                       break;
+               dbgarg(cmd, "setting priority to %d\n", *p);
+               ret=vfd->vidioc_s_priority(file, fh, *p);
+               break;
+       }
+
+       /* --- capture ioctls ---------------------------------------- */
+       case VIDIOC_ENUM_FMT:
+       {
+               struct v4l2_fmtdesc *f = arg;
+               enum v4l2_buf_type type;
+               unsigned int index;
+
+               index = f->index;
+               type  = f->type;
+               memset(f,0,sizeof(*f));
+               f->index = index;
+               f->type  = type;
+
+               switch (type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       if (vfd->vidioc_enum_fmt_cap)
+                               ret=vfd->vidioc_enum_fmt_cap(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       if (vfd->vidioc_enum_fmt_overlay)
+                               ret=vfd->vidioc_enum_fmt_overlay(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_CAPTURE:
+                       if (vfd->vidioc_enum_fmt_vbi)
+                               ret=vfd->vidioc_enum_fmt_vbi(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+                       if (vfd->vidioc_enum_fmt_vbi_output)
+                               ret=vfd->vidioc_enum_fmt_vbi_output(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+                       if (vfd->vidioc_enum_fmt_vbi_capture)
+                               ret=vfd->vidioc_enum_fmt_vbi_capture(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                       if (vfd->vidioc_enum_fmt_video_output)
+                               ret=vfd->vidioc_enum_fmt_video_output(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_OUTPUT:
+                       if (vfd->vidioc_enum_fmt_vbi_output)
+                               ret=vfd->vidioc_enum_fmt_vbi_output(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_PRIVATE:
+                       if (vfd->vidioc_enum_fmt_type_private)
+                               ret=vfd->vidioc_enum_fmt_type_private(file,
+                                                               fh, f);
+                       break;
+               }
+               if (!ret)
+                       dbgarg (cmd, "index=%d, type=%d, flags=%d, "
+                                       "description=%s,"
+                                       " pixelformat=0x%8x\n",
+                                       f->index, f->type, f->flags,
+                                       f->description,
+                                       f->pixelformat);
+
+               break;
+       }
+       case VIDIOC_G_FMT:
+       {
+               struct v4l2_format *f = (struct v4l2_format *)arg;
+               enum v4l2_buf_type type=f->type;
+
+               memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
+               f->type=type;
+
+               /* FIXME: Should be one dump per type */
+               dbgarg (cmd, "type=%s\n", prt_names(type,
+                                       v4l2_type_names_FIXME));
+
+               switch (type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       if (vfd->vidioc_g_fmt_cap)
+                               ret=vfd->vidioc_g_fmt_cap(file, fh, f);
+                       if (!ret)
+                               v4l_print_pix_fmt(vfd,&f->fmt.pix);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       if (vfd->vidioc_g_fmt_overlay)
+                               ret=vfd->vidioc_g_fmt_overlay(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_CAPTURE:
+                       if (vfd->vidioc_g_fmt_vbi)
+                               ret=vfd->vidioc_g_fmt_vbi(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+                       if (vfd->vidioc_g_fmt_vbi_output)
+                               ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+                       if (vfd->vidioc_g_fmt_vbi_capture)
+                               ret=vfd->vidioc_g_fmt_vbi_capture(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                       if (vfd->vidioc_g_fmt_video_output)
+                               ret=vfd->vidioc_g_fmt_video_output(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_OUTPUT:
+                       if (vfd->vidioc_g_fmt_vbi_output)
+                               ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_PRIVATE:
+                       if (vfd->vidioc_g_fmt_type_private)
+                               ret=vfd->vidioc_g_fmt_type_private(file,
+                                                               fh, f);
+                       break;
+               }
+
+               break;
+       }
+       case VIDIOC_S_FMT:
+       {
+               struct v4l2_format *f = (struct v4l2_format *)arg;
+
+               /* FIXME: Should be one dump per type */
+               dbgarg (cmd, "type=%s\n", prt_names(f->type,
+                                       v4l2_type_names_FIXME));
+
+               switch (f->type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       v4l_print_pix_fmt(vfd,&f->fmt.pix);
+                       if (vfd->vidioc_s_fmt_cap)
+                               ret=vfd->vidioc_s_fmt_cap(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       if (vfd->vidioc_s_fmt_overlay)
+                               ret=vfd->vidioc_s_fmt_overlay(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_CAPTURE:
+                       if (vfd->vidioc_s_fmt_vbi)
+                               ret=vfd->vidioc_s_fmt_vbi(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+                       if (vfd->vidioc_s_fmt_vbi_output)
+                               ret=vfd->vidioc_s_fmt_vbi_output(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+                       if (vfd->vidioc_s_fmt_vbi_capture)
+                               ret=vfd->vidioc_s_fmt_vbi_capture(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                       if (vfd->vidioc_s_fmt_video_output)
+                               ret=vfd->vidioc_s_fmt_video_output(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_OUTPUT:
+                       if (vfd->vidioc_s_fmt_vbi_output)
+                               ret=vfd->vidioc_s_fmt_vbi_output(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_PRIVATE:
+                       if (vfd->vidioc_s_fmt_type_private)
+                               ret=vfd->vidioc_s_fmt_type_private(file,
+                                                               fh, f);
+                       break;
+               }
+               break;
+       }
+       case VIDIOC_TRY_FMT:
+       {
+               struct v4l2_format *f = (struct v4l2_format *)arg;
+
+               /* FIXME: Should be one dump per type */
+               dbgarg (cmd, "type=%s\n", prt_names(f->type,
+                                               v4l2_type_names_FIXME));
+               switch (f->type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       if (vfd->vidioc_try_fmt_cap)
+                               ret=vfd->vidioc_try_fmt_cap(file, fh, f);
+                       if (!ret)
+                               v4l_print_pix_fmt(vfd,&f->fmt.pix);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       if (vfd->vidioc_try_fmt_overlay)
+                               ret=vfd->vidioc_try_fmt_overlay(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_CAPTURE:
+                       if (vfd->vidioc_try_fmt_vbi)
+                               ret=vfd->vidioc_try_fmt_vbi(file, fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+                       if (vfd->vidioc_try_fmt_vbi_output)
+                               ret=vfd->vidioc_try_fmt_vbi_output(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+                       if (vfd->vidioc_try_fmt_vbi_capture)
+                               ret=vfd->vidioc_try_fmt_vbi_capture(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+                       if (vfd->vidioc_try_fmt_video_output)
+                               ret=vfd->vidioc_try_fmt_video_output(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_VBI_OUTPUT:
+                       if (vfd->vidioc_try_fmt_vbi_output)
+                               ret=vfd->vidioc_try_fmt_vbi_output(file,
+                                                               fh, f);
+                       break;
+               case V4L2_BUF_TYPE_PRIVATE:
+                       if (vfd->vidioc_try_fmt_type_private)
+                               ret=vfd->vidioc_try_fmt_type_private(file,
+                                                               fh, f);
+                       break;
+               }
+
+               break;
+       }
+       /* FIXME: Those buf reqs could be handled here,
+          with some changes on videobuf to allow its header to be included at
+          videodev2.h or being merged at videodev2.
+        */
+       case VIDIOC_REQBUFS:
+       {
+               struct v4l2_requestbuffers *p=arg;
+
+               if (!vfd->vidioc_reqbufs)
+                       break;
+               ret = check_fmt (vfd, p->type);
+               if (ret)
+                       break;
+
+               ret=vfd->vidioc_reqbufs(file, fh, p);
+               dbgarg (cmd, "count=%d, type=%s, memory=%s\n",
+                               p->count,
+                               prt_names(p->type,v4l2_type_names_FIXME),
+                               prt_names(p->memory,v4l2_memory_names));
+               break;
+       }
+       case VIDIOC_QUERYBUF:
+       {
+               struct v4l2_buffer *p=arg;
+
+               if (!vfd->vidioc_querybuf)
+                       break;
+               ret = check_fmt (vfd, p->type);
+               if (ret)
+                       break;
+
+               ret=vfd->vidioc_querybuf(file, fh, p);
+               if (!ret)
+                       dbgbuf(cmd,vfd,p);
+               break;
+       }
+       case VIDIOC_QBUF:
+       {
+               struct v4l2_buffer *p=arg;
+
+               if (!vfd->vidioc_qbuf)
+                       break;
+               ret = check_fmt (vfd, p->type);
+               if (ret)
+                       break;
+
+               ret=vfd->vidioc_qbuf(file, fh, p);
+               if (!ret)
+                       dbgbuf(cmd,vfd,p);
+               break;
+       }
+       case VIDIOC_DQBUF:
+       {
+               struct v4l2_buffer *p=arg;
+               if (!vfd->vidioc_qbuf)
+                       break;
+               ret = check_fmt (vfd, p->type);
+               if (ret)
+                       break;
+
+               ret=vfd->vidioc_qbuf(file, fh, p);
+               if (!ret)
+                       dbgbuf(cmd,vfd,p);
+               break;
+       }
+       case VIDIOC_OVERLAY:
+       {
+               int *i = arg;
+
+               if (!vfd->vidioc_overlay)
+                       break;
+               dbgarg (cmd, "value=%d\n",*i);
+               ret=vfd->vidioc_overlay(file, fh, *i);
+               break;
+       }
+#ifdef HAVE_V4L1
+       /* --- streaming capture ------------------------------------- */
+       case VIDIOCGMBUF:
+       {
+               struct video_mbuf *p=arg;
+
+               memset(p,0,sizeof(p));
+
+               if (!vfd->vidiocgmbuf)
+                       break;
+               ret=vfd->vidiocgmbuf(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
+                                               p->size, p->frames,
+                                               (unsigned long)p->offsets);
+               break;
+       }
+#endif
+       case VIDIOC_G_FBUF:
+       {
+               struct v4l2_framebuffer *p=arg;
+               if (!vfd->vidioc_g_fbuf)
+                       break;
+               ret=vfd->vidioc_g_fbuf(file, fh, arg);
+               if (!ret) {
+                       dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n",
+                                       p->capability,p->flags,
+                                       (unsigned long)p->base);
+                       v4l_print_pix_fmt (vfd, &p->fmt);
+               }
+               break;
+       }
+       case VIDIOC_S_FBUF:
+       {
+               struct v4l2_framebuffer *p=arg;
+               if (!vfd->vidioc_s_fbuf)
+                       break;
+
+               dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n",
+                               p->capability,p->flags,(unsigned long)p->base);
+               v4l_print_pix_fmt (vfd, &p->fmt);
+               ret=vfd->vidioc_s_fbuf(file, fh, arg);
+
+               break;
+       }
+       case VIDIOC_STREAMON:
+       {
+               enum v4l2_buf_type i = *(int *)arg;
+               if (!vfd->vidioc_streamon)
+                       break;
+               dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME));
+               ret=vfd->vidioc_streamon(file, fh,i);
+               break;
+       }
+       case VIDIOC_STREAMOFF:
+       {
+               enum v4l2_buf_type i = *(int *)arg;
+
+               if (!vfd->vidioc_streamoff)
+                       break;
+               dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME));
+               ret=vfd->vidioc_streamoff(file, fh, i);
+               break;
+       }
+       /* ---------- tv norms ---------- */
+       case VIDIOC_ENUMSTD:
+       {
+               struct v4l2_standard *p = arg;
+               unsigned int index = p->index;
+
+               if (!vfd->tvnormsize) {
+                       printk (KERN_WARNING "%s: no TV norms defined!\n",
+                                               vfd->name);
+                       break;
+               }
+
+               if (index<=0 || index >= vfd->tvnormsize) {
+                       ret=-EINVAL;
+                       break;
+               }
+               v4l2_video_std_construct(p, vfd->tvnorms[p->index].id,
+                                        vfd->tvnorms[p->index].name);
+               p->index = index;
+
+               dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
+                               "framelines=%d\n", p->index,
+                               (unsigned long long)p->id, p->name,
+                               p->frameperiod.numerator,
+                               p->frameperiod.denominator,
+                               p->framelines);
+
+               ret=0;
+               break;
+       }
+       case VIDIOC_G_STD:
+       {
+               v4l2_std_id *id = arg;
+
+               *id = vfd->current_norm;
+
+               dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
+
+               ret=0;
+               break;
+       }
+       case VIDIOC_S_STD:
+       {
+               v4l2_std_id *id = arg;
+               unsigned int i;
+
+               if (!vfd->tvnormsize) {
+                       printk (KERN_WARNING "%s: no TV norms defined!\n",
+                                               vfd->name);
+                       break;
+               }
+
+               dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
+
+               /* First search for exact match */
+               for (i = 0; i < vfd->tvnormsize; i++)
+                       if (*id == vfd->tvnorms[i].id)
+                               break;
+               /* Then for a generic video std that contains desired std */
+               if (i == vfd->tvnormsize)
+                       for (i = 0; i < vfd->tvnormsize; i++)
+                               if (*id & vfd->tvnorms[i].id)
+                                       break;
+               if (i == vfd->tvnormsize) {
+                       break;
+               }
+
+               /* Calls the specific handler */
+               if (vfd->vidioc_s_std)
+                       ret=vfd->vidioc_s_std(file, fh, i);
+               else
+                       ret=-EINVAL;
+
+               /* Updates standard information */
+               if (!ret)
+                       vfd->current_norm=*id;
+
+               break;
+       }
+       case VIDIOC_QUERYSTD:
+       {
+               v4l2_std_id *p=arg;
+
+               if (!vfd->vidioc_querystd)
+                       break;
+               ret=vfd->vidioc_querystd(file, fh, arg);
+               if (!ret)
+                       dbgarg (cmd, "detected std=%Lu\n",
+                                               (unsigned long long)*p);
+               break;
+       }
+       /* ------ input switching ---------- */
+       /* FIXME: Inputs can be handled inside videodev2 */
+       case VIDIOC_ENUMINPUT:
+       {
+               struct v4l2_input *p=arg;
+               int i=p->index;
+
+               if (!vfd->vidioc_enum_input)
+                       break;
+               memset(p, 0, sizeof(*p));
+               p->index=i;
+
+               ret=vfd->vidioc_enum_input(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "index=%d, name=%s, type=%d, "
+                                       "audioset=%d, "
+                                       "tuner=%d, std=%Ld, status=%d\n",
+                                       p->index,p->name,p->type,p->audioset,
+                                       p->tuner,
+                                       (unsigned long long)p->std,
+                                       p->status);
+               break;
+       }
+       case VIDIOC_G_INPUT:
+       {
+               unsigned int *i = arg;
+
+               if (!vfd->vidioc_g_input)
+                       break;
+               ret=vfd->vidioc_g_input(file, fh, i);
+               if (!ret)
+                       dbgarg (cmd, "value=%d\n",*i);
+               break;
+       }
+       case VIDIOC_S_INPUT:
+       {
+               unsigned int *i = arg;
+
+               if (!vfd->vidioc_s_input)
+                       break;
+               dbgarg (cmd, "value=%d\n",*i);
+               ret=vfd->vidioc_s_input(file, fh, *i);
+               break;
+       }
+
+       /* ------ output switching ---------- */
+       case VIDIOC_G_OUTPUT:
+       {
+               unsigned int *i = arg;
+
+               if (!vfd->vidioc_g_output)
+                       break;
+               ret=vfd->vidioc_g_output(file, fh, i);
+               if (!ret)
+                       dbgarg (cmd, "value=%d\n",*i);
+               break;
+       }
+       case VIDIOC_S_OUTPUT:
+       {
+               unsigned int *i = arg;
+
+               if (!vfd->vidioc_s_output)
+                       break;
+               dbgarg (cmd, "value=%d\n",*i);
+               ret=vfd->vidioc_s_output(file, fh, *i);
+               break;
+       }
+
+       /* --- controls ---------------------------------------------- */
+       case VIDIOC_QUERYCTRL:
+       {
+               struct v4l2_queryctrl *p=arg;
+
+               if (!vfd->vidioc_queryctrl)
+                       break;
+               ret=vfd->vidioc_queryctrl(file, fh, p);
+
+               if (!ret)
+                       dbgarg (cmd, "id=%d, type=%d, name=%s, "
+                                       "min/max=%d/%d,"
+                                       " step=%d, default=%d, flags=0x%08x\n",
+                                       p->id,p->type,p->name,p->minimum,
+                                       p->maximum,p->step,p->default_value,
+                                       p->flags);
+               break;
+       }
+       case VIDIOC_G_CTRL:
+       {
+               struct v4l2_control *p = arg;
+
+               if (!vfd->vidioc_g_ctrl)
+                       break;
+               dbgarg(cmd, "Enum for index=%d\n", p->id);
+
+               ret=vfd->vidioc_g_ctrl(file, fh, p);
+               if (!ret)
+                       dbgarg2 ( "id=%d, value=%d\n", p->id, p->value);
+               break;
+       }
+       case VIDIOC_S_CTRL:
+       {
+               struct v4l2_control *p = arg;
+
+               if (!vfd->vidioc_s_ctrl)
+                       break;
+               dbgarg (cmd, "id=%d, value=%d\n", p->id, p->value);
+
+               ret=vfd->vidioc_s_ctrl(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *p = arg;
+
+               if (vfd->vidioc_g_ext_ctrls) {
+                       dbgarg(cmd, "count=%d\n", p->count);
+
+                       ret=vfd->vidioc_g_ext_ctrls(file, fh, p);
+               }
+               break;
+       }
+       case VIDIOC_S_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *p = arg;
+
+               if (vfd->vidioc_s_ext_ctrls) {
+                       dbgarg(cmd, "count=%d\n", p->count);
+
+                       ret=vfd->vidioc_s_ext_ctrls(file, fh, p);
+               }
+               break;
+       }
+       case VIDIOC_TRY_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *p = arg;
+
+               if (vfd->vidioc_try_ext_ctrls) {
+                       dbgarg(cmd, "count=%d\n", p->count);
+
+                       ret=vfd->vidioc_try_ext_ctrls(file, fh, p);
+               }
+               break;
+       }
+       case VIDIOC_QUERYMENU:
+       {
+               struct v4l2_querymenu *p=arg;
+               if (!vfd->vidioc_querymenu)
+                       break;
+               ret=vfd->vidioc_querymenu(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "id=%d, index=%d, name=%s\n",
+                                               p->id,p->index,p->name);
+               break;
+       }
+       /* --- audio ---------------------------------------------- */
+       case VIDIOC_ENUMAUDIO:
+       {
+               struct v4l2_audio *p=arg;
+
+               if (!vfd->vidioc_enumaudio)
+                       break;
+               dbgarg(cmd, "Enum for index=%d\n", p->index);
+               ret=vfd->vidioc_enumaudio(file, fh, p);
+               if (!ret)
+                       dbgarg2("index=%d, name=%s, capability=%d, "
+                                       "mode=%d\n",p->index,p->name,
+                                       p->capability, p->mode);
+               break;
+       }
+       case VIDIOC_G_AUDIO:
+       {
+               struct v4l2_audio *p=arg;
+
+               if (!vfd->vidioc_g_audio)
+                       break;
+               dbgarg(cmd, "Get for index=%d\n", p->index);
+               ret=vfd->vidioc_g_audio(file, fh, p);
+               if (!ret)
+                       dbgarg2("index=%d, name=%s, capability=%d, "
+                                       "mode=%d\n",p->index,
+                                       p->name,p->capability, p->mode);
+               break;
+       }
+       case VIDIOC_S_AUDIO:
+       {
+               struct v4l2_audio *p=arg;
+
+               if (!vfd->vidioc_s_audio)
+                       break;
+               dbgarg(cmd, "index=%d, name=%s, capability=%d, "
+                                       "mode=%d\n", p->index, p->name,
+                                       p->capability, p->mode);
+               ret=vfd->vidioc_s_audio(file, fh, p);
+               break;
+       }
+       case VIDIOC_ENUMAUDOUT:
+       {
+               struct v4l2_audioout *p=arg;
+
+               if (!vfd->vidioc_enumaudout)
+                       break;
+               dbgarg(cmd, "Enum for index=%d\n", p->index);
+               ret=vfd->vidioc_enumaudout(file, fh, p);
+               if (!ret)
+                       dbgarg2("index=%d, name=%s, capability=%d, "
+                                       "mode=%d\n", p->index, p->name,
+                                       p->capability,p->mode);
+               break;
+       }
+       case VIDIOC_G_AUDOUT:
+       {
+               struct v4l2_audioout *p=arg;
+
+               if (!vfd->vidioc_g_audout)
+                       break;
+               dbgarg(cmd, "Enum for index=%d\n", p->index);
+               ret=vfd->vidioc_g_audout(file, fh, p);
+               if (!ret)
+                       dbgarg2("index=%d, name=%s, capability=%d, "
+                                       "mode=%d\n", p->index, p->name,
+                                       p->capability,p->mode);
+               break;
+       }
+       case VIDIOC_S_AUDOUT:
+       {
+               struct v4l2_audioout *p=arg;
+
+               if (!vfd->vidioc_s_audout)
+                       break;
+               dbgarg(cmd, "index=%d, name=%s, capability=%d, "
+                                       "mode=%d\n", p->index, p->name,
+                                       p->capability,p->mode);
+
+               ret=vfd->vidioc_s_audout(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_MODULATOR:
+       {
+               struct v4l2_modulator *p=arg;
+               if (!vfd->vidioc_g_modulator)
+                       break;
+               ret=vfd->vidioc_g_modulator(file, fh, p);
+               if (!ret)
+                       dbgarg(cmd, "index=%d, name=%s, "
+                                       "capability=%d, rangelow=%d,"
+                                       " rangehigh=%d, txsubchans=%d\n",
+                                       p->index, p->name,p->capability,
+                                       p->rangelow, p->rangehigh,
+                                       p->txsubchans);
+               break;
+       }
+       case VIDIOC_S_MODULATOR:
+       {
+               struct v4l2_modulator *p=arg;
+               if (!vfd->vidioc_s_modulator)
+                       break;
+               dbgarg(cmd, "index=%d, name=%s, capability=%d, "
+                               "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
+                               p->index, p->name,p->capability,p->rangelow,
+                               p->rangehigh,p->txsubchans);
+                       ret=vfd->vidioc_s_modulator(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_CROP:
+       {
+               struct v4l2_crop *p=arg;
+               if (!vfd->vidioc_g_crop)
+                       break;
+               ret=vfd->vidioc_g_crop(file, fh, p);
+               if (!ret) {
+                       dbgarg(cmd, "type=%d\n", p->type);
+                       dbgrect(vfd, "", &p->c);
+               }
+               break;
+       }
+       case VIDIOC_S_CROP:
+       {
+               struct v4l2_crop *p=arg;
+               if (!vfd->vidioc_s_crop)
+                       break;
+               dbgarg(cmd, "type=%d\n", p->type);
+               dbgrect(vfd, "", &p->c);
+               ret=vfd->vidioc_s_crop(file, fh, p);
+               break;
+       }
+       case VIDIOC_CROPCAP:
+       {
+               struct v4l2_cropcap *p=arg;
+               /*FIXME: Should also show v4l2_fract pixelaspect */
+               if (!vfd->vidioc_cropcap)
+                       break;
+               dbgarg(cmd, "type=%d\n", p->type);
+               dbgrect(vfd, "bounds ", &p->bounds);
+               dbgrect(vfd, "defrect ", &p->defrect);
+               ret=vfd->vidioc_cropcap(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_MPEGCOMP:
+       {
+               struct v4l2_mpeg_compression *p=arg;
+
+               /*FIXME: Several fields not shown */
+               if (!vfd->vidioc_g_mpegcomp)
+                       break;
+               ret=vfd->vidioc_g_mpegcomp(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d,"
+                                       " ts_pid_video=%d, ts_pid_pcr=%d, "
+                                       "ps_size=%d, au_sample_rate=%d, "
+                                       "au_pesid=%c, vi_frame_rate=%d, "
+                                       "vi_frames_per_gop=%d, "
+                                       "vi_bframes_count=%d, vi_pesid=%c\n",
+                                       p->ts_pid_pmt,p->ts_pid_audio,
+                                       p->ts_pid_video,p->ts_pid_pcr,
+                                       p->ps_size, p->au_sample_rate,
+                                       p->au_pesid, p->vi_frame_rate,
+                                       p->vi_frames_per_gop,
+                                       p->vi_bframes_count, p->vi_pesid);
+               break;
+       }
+       case VIDIOC_S_MPEGCOMP:
+       {
+               struct v4l2_mpeg_compression *p=arg;
+               /*FIXME: Several fields not shown */
+               if (!vfd->vidioc_s_mpegcomp)
+                       break;
+               dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d, "
+                               "ts_pid_video=%d, ts_pid_pcr=%d, ps_size=%d, "
+                               "au_sample_rate=%d, au_pesid=%c, "
+                               "vi_frame_rate=%d, vi_frames_per_gop=%d, "
+                               "vi_bframes_count=%d, vi_pesid=%c\n",
+                               p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video,
+                               p->ts_pid_pcr, p->ps_size, p->au_sample_rate,
+                               p->au_pesid, p->vi_frame_rate,
+                               p->vi_frames_per_gop, p->vi_bframes_count,
+                               p->vi_pesid);
+               ret=vfd->vidioc_s_mpegcomp(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_JPEGCOMP:
+       {
+               struct v4l2_jpegcompression *p=arg;
+               if (!vfd->vidioc_g_jpegcomp)
+                       break;
+               ret=vfd->vidioc_g_jpegcomp(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "quality=%d, APPn=%d, "
+                                               "APP_len=%d, COM_len=%d, "
+                                               "jpeg_markers=%d\n",
+                                               p->quality,p->APPn,p->APP_len,
+                                               p->COM_len,p->jpeg_markers);
+               break;
+       }
+       case VIDIOC_S_JPEGCOMP:
+       {
+               struct v4l2_jpegcompression *p=arg;
+               if (!vfd->vidioc_g_jpegcomp)
+                       break;
+               dbgarg (cmd, "quality=%d, APPn=%d, APP_len=%d, "
+                                       "COM_len=%d, jpeg_markers=%d\n",
+                                       p->quality,p->APPn,p->APP_len,
+                                       p->COM_len,p->jpeg_markers);
+                       ret=vfd->vidioc_s_jpegcomp(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_PARM:
+       {
+               struct v4l2_streamparm *p=arg;
+               if (!vfd->vidioc_g_parm)
+                       break;
+               ret=vfd->vidioc_g_parm(file, fh, p);
+               dbgarg (cmd, "type=%d\n", p->type);
+               break;
+       }
+       case VIDIOC_S_PARM:
+       {
+               struct v4l2_streamparm *p=arg;
+               if (!vfd->vidioc_s_parm)
+                       break;
+               dbgarg (cmd, "type=%d\n", p->type);
+               ret=vfd->vidioc_s_parm(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_TUNER:
+       {
+               struct v4l2_tuner *p=arg;
+               if (!vfd->vidioc_g_tuner)
+                       break;
+               ret=vfd->vidioc_g_tuner(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "index=%d, name=%s, type=%d, "
+                                       "capability=%d, rangelow=%d, "
+                                       "rangehigh=%d, signal=%d, afc=%d, "
+                                       "rxsubchans=%d, audmode=%d\n",
+                                       p->index, p->name, p->type,
+                                       p->capability, p->rangelow,
+                                       p->rangehigh, p->rxsubchans,
+                                       p->audmode, p->signal, p->afc);
+               break;
+       }
+       case VIDIOC_S_TUNER:
+       {
+               struct v4l2_tuner *p=arg;
+               if (!vfd->vidioc_s_tuner)
+                       break;
+               dbgarg (cmd, "index=%d, name=%s, type=%d, "
+                               "capability=%d, rangelow=%d, rangehigh=%d, "
+                               "signal=%d, afc=%d, rxsubchans=%d, "
+                               "audmode=%d\n",p->index, p->name, p->type,
+                               p->capability, p->rangelow,p->rangehigh,
+                               p->rxsubchans, p->audmode, p->signal,
+                               p->afc);
+               ret=vfd->vidioc_s_tuner(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_FREQUENCY:
+       {
+               struct v4l2_frequency *p=arg;
+               if (!vfd->vidioc_g_frequency)
+                       break;
+               ret=vfd->vidioc_g_frequency(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
+                                               p->tuner,p->type,p->frequency);
+               break;
+       }
+       case VIDIOC_S_FREQUENCY:
+       {
+               struct v4l2_frequency *p=arg;
+               if (!vfd->vidioc_s_frequency)
+                       break;
+               dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
+                               p->tuner,p->type,p->frequency);
+               ret=vfd->vidioc_s_frequency(file, fh, p);
+               break;
+       }
+       case VIDIOC_G_SLICED_VBI_CAP:
+       {
+               struct v4l2_sliced_vbi_cap *p=arg;
+               if (!vfd->vidioc_g_sliced_vbi_cap)
+                       break;
+               ret=vfd->vidioc_g_sliced_vbi_cap(file, fh, p);
+               if (!ret)
+                       dbgarg (cmd, "service_set=%d\n", p->service_set);
+               break;
+       }
+       case VIDIOC_LOG_STATUS:
+       {
+               if (!vfd->vidioc_log_status)
+                       break;
+               ret=vfd->vidioc_log_status(file, fh);
+               break;
+       }
+
+       /* --- Others --------------------------------------------- */
+
+       default:
+               ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl);
+       }
+
+       if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
+               if (ret<0) {
+                       printk ("%s: err:\n", vfd->name);
+                       v4l_print_ioctl(vfd->name, cmd);
+               }
+       }
+
+       return ret;
+}
+
+int video_ioctl2 (struct inode *inode, struct file *file,
+              unsigned int cmd, unsigned long arg)
+{
+       char    sbuf[128];
+       void    *mbuf = NULL;
+       void    *parg = NULL;
+       int     err  = -EINVAL;
+       int     is_ext_ctrl;
+       size_t  ctrls_size = 0;
+       void __user *user_ptr = NULL;
+
+#ifdef __OLD_VIDIOC_
+       cmd = video_fix_command(cmd);
+#endif
+       is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
+                      cmd == VIDIOC_TRY_EXT_CTRLS);
+
+       /*  Copy arguments into temp kernel buffer  */
+       switch (_IOC_DIR(cmd)) {
+       case _IOC_NONE:
+               parg = NULL;
+               break;
+       case _IOC_READ:
+       case _IOC_WRITE:
+       case (_IOC_WRITE | _IOC_READ):
+               if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
+                       parg = sbuf;
+               } else {
+                       /* too big to allocate from stack */
+                       mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
+                       if (NULL == mbuf)
+                               return -ENOMEM;
+                       parg = mbuf;
+               }
+
+               err = -EFAULT;
+               if (_IOC_DIR(cmd) & _IOC_WRITE)
+                       if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
+                               goto out;
+               break;
+       }
+
+       if (is_ext_ctrl) {
+               struct v4l2_ext_controls *p = parg;
+
+               /* In case of an error, tell the caller that it wasn't
+                  a specific control that caused it. */
+               p->error_idx = p->count;
+               user_ptr = (void __user *)p->controls;
+               if (p->count) {
+                       ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
+                       /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
+                       mbuf = kmalloc(ctrls_size, GFP_KERNEL);
+                       err = -ENOMEM;
+                       if (NULL == mbuf)
+                               goto out_ext_ctrl;
+                       err = -EFAULT;
+                       if (copy_from_user(mbuf, user_ptr, ctrls_size))
+                               goto out_ext_ctrl;
+                       p->controls = mbuf;
+               }
+       }
+
+       /* Handles IOCTL */
+       err = __video_do_ioctl(inode, file, cmd, parg);
+       if (err == -ENOIOCTLCMD)
+               err = -EINVAL;
+       if (is_ext_ctrl) {
+               struct v4l2_ext_controls *p = parg;
+
+               p->controls = (void *)user_ptr;
+               if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
+                       err = -EFAULT;
+               goto out_ext_ctrl;
+       }
+       if (err < 0)
+               goto out;
+
+out_ext_ctrl:
+       /*  Copy results into user buffer  */
+       switch (_IOC_DIR(cmd))
+       {
+       case _IOC_READ:
+       case (_IOC_WRITE | _IOC_READ):
+               if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
+                       err = -EFAULT;
+               break;
+       }
+
+out:
+       kfree(mbuf);
+       return err;
+}
+
+
 static struct file_operations video_fops;
 
 /**
@@ -371,7 +1610,9 @@ void video_unregister_device(struct video_device *vfd)
        mutex_unlock(&videodev_lock);
 }
 
-
+/*
+ * Video fs operations
+ */
 static struct file_operations video_fops=
 {
        .owner          = THIS_MODULE,
@@ -387,7 +1628,7 @@ static int __init videodev_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "Linux video capture interface: v1.00\n");
+       printk(KERN_INFO "Linux video capture interface: v2.00\n");
        if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) {
                printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR);
                return -EIO;
@@ -418,11 +1659,12 @@ EXPORT_SYMBOL(video_devdata);
 EXPORT_SYMBOL(video_usercopy);
 EXPORT_SYMBOL(video_exclusive_open);
 EXPORT_SYMBOL(video_exclusive_release);
+EXPORT_SYMBOL(video_ioctl2);
 EXPORT_SYMBOL(video_device_alloc);
 EXPORT_SYMBOL(video_device_release);
 
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("Device registrar for Video4Linux drivers");
+MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2");
 MODULE_LICENSE("GPL");
 
 
index a8c101494cf575f947fd804eccdde524140bb1ec..268e69fdefc6f3194fdcdc3cc2902fffbd642c3b 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/i2c-algo-sgi.h>
 
 #include <linux/videodev.h>
-#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
 #include <linux/video_decoder.h>
 #include <linux/mutex.h>
 
index 779db26771c03b5cf4cb8223dbc3a615c2f3a2ab..41d23c8acbd8b41fd283f4d39b7aaf4ebd88c849 100644 (file)
 
 #include "font.h"
 
-#ifndef kzalloc
-#define kzalloc(size, flags)                            \
-({                                                      \
-       void *__ret = kmalloc(size, flags);             \
-       if (__ret)                                      \
-               memset(__ret, 0, size);                 \
-       __ret;                                          \
-})
-#endif
-
-MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
-MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
-MODULE_LICENSE("Dual BSD/GPL");
-
 #define VIVI_MAJOR_VERSION 0
 #define VIVI_MINOR_VERSION 4
 #define VIVI_RELEASE 0
 #define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
 
-static int video_nr = -1;        /* /dev/videoN, -1 for autodetect */
-module_param(video_nr, int, 0);
-
-static int debug = 0;
-module_param(debug, int, 0);
-
-static unsigned int vid_limit = 16;
-module_param(vid_limit,int,0644);
-MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+/* Declare static vars that will be used as parameters */
+static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
+static struct video_device vivi;       /* Video device */
+static int video_nr = -1;              /* /dev/videoN, -1 for autodetect */
 
 /* supported controls */
 static struct v4l2_queryctrl vivi_qctrl[] = {
@@ -129,10 +110,10 @@ static struct v4l2_queryctrl vivi_qctrl[] = {
 
 static int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
 
-#define dprintk(level,fmt, arg...)                          \
-       do {                                                 \
-               if (debug >= (level))                        \
-                       printk(KERN_DEBUG "vivi: " fmt , ## arg);    \
+#define dprintk(level,fmt, arg...)                                     \
+       do {                                                            \
+               if (vivi.debug >= (level))                              \
+                       printk(KERN_DEBUG "vivi: " fmt , ## arg);       \
        } while (0)
 
 /* ------------------------------------------------------------------
@@ -190,7 +171,7 @@ struct vivi_dev {
 
        /* various device info */
        unsigned int               resources;
-       struct video_device        video_dev;
+       struct video_device        vfd;
 
        struct vivi_dmaqueue       vidq;
 
@@ -248,7 +229,8 @@ static u8 bars[8][3] = {
 #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
 #define TSTAMP_MIN_X 64
 
-void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb)
+static void prep_to_addr(struct sg_to_addr to_addr[],
+                        struct videobuf_buffer *vb)
 {
        int i, pos=0;
 
@@ -259,7 +241,7 @@ void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb)
        }
 }
 
-inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[])
+static int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[])
 {
        int p1=0,p2=pages-1,p3=pages/2;
 
@@ -280,8 +262,8 @@ inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[])
        return (p1);
 }
 
-void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
-                                       int hmax, int line, char *timestr)
+static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
+                    int hmax, int line, char *timestr)
 {
        int  w,i,j,pos=inipos,pgpos,oldpg,y;
        char *p,*s,*basep;
@@ -491,7 +473,7 @@ static void vivi_thread_tick(struct vivi_dmaqueue  *dma_q)
                dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
 }
 
-void vivi_sleep(struct vivi_dmaqueue  *dma_q)
+static void vivi_sleep(struct vivi_dmaqueue  *dma_q)
 {
        int timeout;
        DECLARE_WAITQUEUE(wait, current);
@@ -526,7 +508,7 @@ void vivi_sleep(struct vivi_dmaqueue  *dma_q)
        try_to_freeze();
 }
 
-int vivi_thread(void *data)
+static int vivi_thread(void *data)
 {
        struct vivi_dmaqueue  *dma_q=data;
 
@@ -542,7 +524,7 @@ int vivi_thread(void *data)
        return 0;
 }
 
-int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
+static int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
 {
        dma_q->frame=0;
        dma_q->ini_jiffies=jiffies;
@@ -560,7 +542,7 @@ int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
        return 0;
 }
 
-void vivi_stop_thread(struct vivi_dmaqueue  *dma_q)
+static void vivi_stop_thread(struct vivi_dmaqueue  *dma_q)
 {
        dprintk(1,"%s\n",__FUNCTION__);
        /* shutdown control thread */
@@ -666,8 +648,7 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
        return 0;
 }
 
-void
-free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
+static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
 {
        dprintk(1,"%s\n",__FUNCTION__);
 
@@ -791,8 +772,8 @@ static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb
        free_buffer(vq,buf);
 }
 
-int vivi_map_sg (void *dev, struct scatterlist *sg, int nents,
-          int direction)
+static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents,
+                      int direction)
 {
        int i;
 
@@ -808,15 +789,15 @@ int vivi_map_sg (void *dev, struct scatterlist *sg, int nents,
        return nents;
 }
 
-int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages,
-                                       int direction)
+static int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages,
+                        int direction)
 {
        dprintk(1,"%s\n",__FUNCTION__);
        return 0;
 }
 
-int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist,int nr_pages,
-                                       int direction)
+static int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist, int nr_pages,
+                           int direction)
 {
 //     dprintk(1,"%s\n",__FUNCTION__);
 
@@ -840,7 +821,80 @@ static struct videobuf_queue_ops vivi_video_qops = {
        IOCTL handling
    ------------------------------------------------------------------*/
 
-static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh,
+
+static int res_get(struct vivi_dev *dev, struct vivi_fh *fh)
+{
+       /* is it free? */
+       down(&dev->lock);
+       if (dev->resources) {
+               /* no, someone else uses it */
+               up(&dev->lock);
+               return 0;
+       }
+       /* it's free, grab it */
+       dev->resources =1;
+       dprintk(1,"res: get\n");
+       up(&dev->lock);
+       return 1;
+}
+
+static int res_locked(struct vivi_dev *dev)
+{
+       return (dev->resources);
+}
+
+static void res_free(struct vivi_dev *dev, struct vivi_fh *fh)
+{
+       down(&dev->lock);
+       dev->resources = 0;
+       dprintk(1,"res: put\n");
+       up(&dev->lock);
+}
+
+/* ------------------------------------------------------------------
+       IOCTL vidioc handling
+   ------------------------------------------------------------------*/
+static int vidioc_querycap (struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
+{
+       strcpy(cap->driver, "vivi");
+       strcpy(cap->card, "vivi");
+       cap->version = VIVI_VERSION;
+       cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
+                               V4L2_CAP_STREAMING     |
+                               V4L2_CAP_READWRITE;
+       return 0;
+}
+
+static int vidioc_enum_fmt_cap (struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (f->index > 0)
+               return -EINVAL;
+
+       strlcpy(f->description,format.name,sizeof(f->description));
+       f->pixelformat = format.fourcc;
+       return 0;
+}
+
+static int vidioc_g_fmt_cap (struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct vivi_fh  *fh=priv;
+
+       f->fmt.pix.width        = fh->width;
+       f->fmt.pix.height       = fh->height;
+       f->fmt.pix.field        = fh->vb_vidq.field;
+       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fh->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return (0);
+}
+
+static int vidioc_try_fmt_cap (struct file *file, void *priv,
                        struct v4l2_format *f)
 {
        struct vivi_fmt *fmt;
@@ -848,7 +902,8 @@ static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh,
        unsigned int maxw, maxh;
 
        if (format.fourcc != f->fmt.pix.pixelformat) {
-               dprintk(1,"Fourcc format invalid.\n");
+               dprintk(1,"Fourcc format (0x%08x) invalid. Driver accepts "
+                       "only 0x%08x\n",f->fmt.pix.pixelformat,format.fourcc);
                return -EINVAL;
        }
        fmt=&format;
@@ -884,356 +939,196 @@ static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh,
        return 0;
 }
 
-static int res_get(struct vivi_dev *dev, struct vivi_fh *fh)
+/*FIXME: This seems to be generic enough to be at videodev2 */
+static int vidioc_s_fmt_cap (struct file *file, void *priv,
+                                       struct v4l2_format *f)
 {
-       /* is it free? */
-       down(&dev->lock);
-       if (dev->resources) {
-               /* no, someone else uses it */
-               up(&dev->lock);
-               return 0;
-       }
-       /* it's free, grab it */
-       dev->resources =1;
-       dprintk(1,"res: get\n");
-       up(&dev->lock);
-       return 1;
+       struct vivi_fh  *fh=priv;
+       int ret = vidioc_try_fmt_cap(file,fh,f);
+       if (ret < 0)
+               return (ret);
+
+       fh->fmt           = &format;
+       fh->width         = f->fmt.pix.width;
+       fh->height        = f->fmt.pix.height;
+       fh->vb_vidq.field = f->fmt.pix.field;
+       fh->type          = f->type;
+
+       return (0);
 }
 
-static inline int res_locked(struct vivi_dev *dev)
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
 {
-       return (dev->resources);
-}
+       struct vivi_fh  *fh=priv;
 
-static void res_free(struct vivi_dev *dev, struct vivi_fh *fh)
-{
-       down(&dev->lock);
-       dev->resources = 0;
-       dprintk(1,"res: put\n");
-       up(&dev->lock);
+       return (videobuf_reqbufs(&fh->vb_vidq, p));
 }
 
-static int vivi_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
 {
-       struct vivi_fh  *fh     = file->private_data;
-       struct vivi_dev *dev    = fh->dev;
-       int ret=0;
+       struct vivi_fh  *fh=priv;
 
-       if (debug) {
-               if (_IOC_DIR(cmd) & _IOC_WRITE)
-                       v4l_printk_ioctl_arg("vivi(w)",cmd, arg);
-               else if (!_IOC_DIR(cmd) & _IOC_READ) {
-                       v4l_print_ioctl("vivi", cmd);
-               }
-       }
+       return (videobuf_querybuf(&fh->vb_vidq, p));
+}
 
-       switch(cmd) {
-       /* --- capabilities ------------------------------------------ */
-       case VIDIOC_QUERYCAP:
-       {
-               struct v4l2_capability *cap = (struct v4l2_capability*)arg;
-
-               memset(cap, 0, sizeof(*cap));
-
-               strcpy(cap->driver, "vivi");
-               strcpy(cap->card, "vivi");
-               cap->version = VIVI_VERSION;
-               cap->capabilities =
-                                       V4L2_CAP_VIDEO_CAPTURE |
-                                       V4L2_CAP_STREAMING     |
-                                       V4L2_CAP_READWRITE;
-               break;
-       }
-       /* --- capture ioctls ---------------------------------------- */
-       case VIDIOC_ENUM_FMT:
-       {
-               struct v4l2_fmtdesc *f = arg;
-               enum v4l2_buf_type type;
-               unsigned int index;
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct vivi_fh  *fh=priv;
 
-               index = f->index;
-               type  = f->type;
+       return (videobuf_qbuf(&fh->vb_vidq, p));
+}
 
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       ret=-EINVAL;
-                       break;
-               }
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct vivi_fh  *fh=priv;
 
-               switch (type) {
-               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-                       if (index > 0){
-                               ret=-EINVAL;
-                               break;
-                       }
-                       memset(f,0,sizeof(*f));
+       return (videobuf_dqbuf(&fh->vb_vidq, p,
+                               file->f_flags & O_NONBLOCK));
+}
 
-                       f->index = index;
-                       f->type  = type;
-                       strlcpy(f->description,format.name,sizeof(f->description));
-                       f->pixelformat = format.fourcc;
-                       break;
-               default:
-                       ret=-EINVAL;
-               }
-               break;
+#ifdef HAVE_V4L1
+static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
+{
+       struct vivi_fh  *fh=priv;
+       struct videobuf_queue *q=&fh->vb_vidq;
+       struct v4l2_requestbuffers req;
+       unsigned int i, ret;
+
+       req.type   = q->type;
+       req.count  = 8;
+       req.memory = V4L2_MEMORY_MMAP;
+       ret = videobuf_reqbufs(q,&req);
+       if (ret < 0)
+               return (ret);
+
+       mbuf->frames = req.count;
+       mbuf->size   = 0;
+       for (i = 0; i < mbuf->frames; i++) {
+               mbuf->offsets[i]  = q->bufs[i]->boff;
+               mbuf->size       += q->bufs[i]->bsize;
        }
-       case VIDIOC_G_FMT:
-       {
-               struct v4l2_format *f = (struct v4l2_format *)arg;
+       return (0);
+}
+#endif
 
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       ret=-EINVAL;
-                       break;
-               }
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct vivi_fh  *fh=priv;
+       struct vivi_dev *dev    = fh->dev;
 
-               memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
-               f->fmt.pix.width        = fh->width;
-               f->fmt.pix.height       = fh->height;
-               f->fmt.pix.field        = fh->vb_vidq.field;
-               f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-               f->fmt.pix.bytesperline =
-                       (f->fmt.pix.width * fh->fmt->depth) >> 3;
-               f->fmt.pix.sizeimage =
-                       f->fmt.pix.height * f->fmt.pix.bytesperline;
-               break;
-       }
-       case VIDIOC_S_FMT:
-       {
-               struct v4l2_format *f = arg;
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (i != fh->type)
+               return -EINVAL;
 
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       dprintk(1,"Only capture supported.\n");
-                       ret=-EINVAL;
-                       break;
-               }
+       if (!res_get(dev,fh))
+               return -EBUSY;
+       return (videobuf_streamon(&fh->vb_vidq));
+}
 
-               ret = vivi_try_fmt(dev,fh,f);
-               if (ret < 0)
-                       break;
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct vivi_fh  *fh=priv;
+       struct vivi_dev *dev    = fh->dev;
 
-               fh->fmt           = &format;
-               fh->width         = f->fmt.pix.width;
-               fh->height        = f->fmt.pix.height;
-               fh->vb_vidq.field = f->fmt.pix.field;
-               fh->type          = f->type;
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (i != fh->type)
+               return -EINVAL;
 
-               break;
-       }
-       case VIDIOC_TRY_FMT:
-       {
-               struct v4l2_format *f = arg;
-               if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       ret=-EINVAL;
-                       break;
-               }
+       videobuf_streamoff(&fh->vb_vidq);
+       res_free(dev,fh);
 
-               ret=vivi_try_fmt(dev,fh,f);
-               break;
-       }
-       case VIDIOC_REQBUFS:
-               if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       ret=-EINVAL;
-                       break;
-               }
-               ret=videobuf_reqbufs(&fh->vb_vidq, arg);
-               break;
-       case VIDIOC_QUERYBUF:
-               if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       ret=-EINVAL;
-                       break;
-               }
-               ret=videobuf_querybuf(&fh->vb_vidq, arg);
-               break;
-       case VIDIOC_QBUF:
-               if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       ret=-EINVAL;
-                       break;
-               }
-               ret=videobuf_qbuf(&fh->vb_vidq, arg);
-               break;
-       case VIDIOC_DQBUF:
-               if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       ret=-EINVAL;
-                       break;
-               }
-               ret=videobuf_dqbuf(&fh->vb_vidq, arg,
-                                       file->f_flags & O_NONBLOCK);
-               break;
-#ifdef HAVE_V4L1
-       /* --- streaming capture ------------------------------------- */
-       case VIDIOCGMBUF:
-       {
-               struct video_mbuf *mbuf = arg;
-               struct videobuf_queue *q=&fh->vb_vidq;
-               struct v4l2_requestbuffers req;
-               unsigned int i;
-
-               memset(&req,0,sizeof(req));
-               req.type   = q->type;
-               req.count  = 8;
-               req.memory = V4L2_MEMORY_MMAP;
-               ret = videobuf_reqbufs(q,&req);
-               if (ret < 0)
-                       break;
-               memset(mbuf,0,sizeof(*mbuf));
-               mbuf->frames = req.count;
-               mbuf->size   = 0;
-               for (i = 0; i < mbuf->frames; i++) {
-                       mbuf->offsets[i]  = q->bufs[i]->boff;
-                       mbuf->size       += q->bufs[i]->bsize;
-               }
-               break;
-       }
-#endif
-       case VIDIOC_STREAMON:
-       {
-               if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       return -EINVAL;
-               if (!res_get(dev,fh))
-                       return -EBUSY;
-               ret=videobuf_streamon(&fh->vb_vidq);
-               break;
-       }
-       case VIDIOC_STREAMOFF:
+       return (0);
+}
+
+static struct v4l2_tvnorm tvnorms[] = {
        {
-               if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       ret=-EINVAL;
-                       break;
-               }
-               ret = videobuf_streamoff(&fh->vb_vidq);
-               if (ret < 0)
-                       break;
-               res_free(dev,fh);
-               break;
+               .name      = "NTSC-M",
+               .id        = V4L2_STD_NTSC_M,
        }
-       /* ---------- tv norms ---------- */
-       case VIDIOC_ENUMSTD:
-       {
-               struct v4l2_standard *e = arg;
+};
 
-               if (e->index>0) {
-                       ret=-EINVAL;
-                       break;
-               }
-               ret = v4l2_video_std_construct(e, V4L2_STD_NTSC_M, "NTSC-M");
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a)
+{
 
-               /* Allows vivi to use different fps from video std */
-               e->frameperiod.numerator = WAKE_NUMERATOR;
-               e->frameperiod.denominator = WAKE_DENOMINATOR;
+       return 0;
+}
 
-               break;
-       }
-       case VIDIOC_G_STD:
-       {
-               v4l2_std_id *id = arg;
+/* only one input in this sample driver */
+static int vidioc_enum_input (struct file *file, void *priv,
+                               struct v4l2_input *inp)
+{
+       if (inp->index != 0)
+               return -EINVAL;
 
-               *id = V4L2_STD_NTSC_M;
-               break;
-       }
-       case VIDIOC_S_STD:
-       {
-               break;
-       }
-       /* ------ input switching ---------- */
-       case VIDIOC_ENUMINPUT:
-       { /* only one input in this sample driver */
-               struct v4l2_input *inp = arg;
+       inp->type = V4L2_INPUT_TYPE_CAMERA;
+       inp->std = V4L2_STD_NTSC_M;
+       strcpy(inp->name,"Camera");
 
-               if (inp->index != 0) {
-                       ret=-EINVAL;
-                       break;
-               }
-               memset(inp, 0, sizeof(*inp));
+       return (0);
+}
 
-               inp->index = 0;
-               inp->type = V4L2_INPUT_TYPE_CAMERA;
-               inp->std = V4L2_STD_NTSC_M;
-               strcpy(inp->name,"Camera");
-               break;
-       }
-       case VIDIOC_G_INPUT:
-       {
-               unsigned int *i = arg;
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+{
+       *i = 0;
 
-               *i = 0;
-               break;
-       }
-       case VIDIOC_S_INPUT:
-       {
-               unsigned int *i = arg;
+       return (0);
+}
+static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+{
+       if (i > 0)
+               return -EINVAL;
 
-               if (*i > 0)
-                       ret=-EINVAL;
-               break;
-       }
+       return (0);
+}
 
        /* --- controls ---------------------------------------------- */
-       case VIDIOC_QUERYCTRL:
-       {
-               struct v4l2_queryctrl *qc = arg;
-               int i;
-
-               for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
-                       if (qc->id && qc->id == vivi_qctrl[i].id) {
-                               memcpy(qc, &(vivi_qctrl[i]),
-                                       sizeof(*qc));
-                               break;
-                       }
+static int vidioc_queryctrl (struct file *file, void *priv,
+                               struct v4l2_queryctrl *qc)
+{
+       int i;
 
-               ret=-EINVAL;
-               break;
-       }
-       case VIDIOC_G_CTRL:
-       {
-               struct v4l2_control *ctrl = arg;
-               int i;
+       for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+               if (qc->id && qc->id == vivi_qctrl[i].id) {
+                       memcpy(qc, &(vivi_qctrl[i]),
+                               sizeof(*qc));
+                       return (0);
+               }
 
-               for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
-                       if (ctrl->id == vivi_qctrl[i].id) {
-                               ctrl->value=qctl_regs[i];
-                               break;
-                       }
+       return -EINVAL;
+}
 
-               ret=-EINVAL;
-               break;
-       }
-       case VIDIOC_S_CTRL:
-       {
-               struct v4l2_control *ctrl = arg;
-               int i;
-               for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
-                       if (ctrl->id == vivi_qctrl[i].id) {
-                               if (ctrl->value <
-                                       vivi_qctrl[i].minimum
-                                       || ctrl->value >
-                                       vivi_qctrl[i].maximum) {
-                                               ret=-ERANGE;
-                                               break;
-                                       }
-                               qctl_regs[i]=ctrl->value;
-                               break;
-                       }
-               ret=-EINVAL;
-               break;
-       }
-       default:
-               ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,vivi_do_ioctl);
-       }
+static int vidioc_g_ctrl (struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       int i;
 
-       if (debug) {
-               if (ret<0) {
-                       v4l_print_ioctl("vivi(err)", cmd);
-                       dprintk(1,"errcode=%d\n",ret);
-               } else if (_IOC_DIR(cmd) & _IOC_READ)
-                       v4l_printk_ioctl_arg("vivi(r)",cmd, arg);
-       }
+       for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+               if (ctrl->id == vivi_qctrl[i].id) {
+                       ctrl->value=qctl_regs[i];
+                       return (0);
+               }
 
-       return ret;
+       return -EINVAL;
 }
-
-static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int vidioc_s_ctrl (struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
 {
-       return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+               if (ctrl->id == vivi_qctrl[i].id) {
+                       if (ctrl->value <
+                               vivi_qctrl[i].minimum
+                               || ctrl->value >
+                               vivi_qctrl[i].maximum) {
+                                       return (-ERANGE);
+                               }
+                       qctl_regs[i]=ctrl->value;
+                       return (0);
+               }
+       return -EINVAL;
 }
 
 /* ------------------------------------------------------------------
@@ -1255,7 +1150,7 @@ static int vivi_open(struct inode *inode, struct file *file)
 
        list_for_each(list,&vivi_devlist) {
                h = list_entry(list, struct vivi_dev, vivi_devlist);
-               if (h->video_dev.minor == minor) {
+               if (h->vfd.minor == minor) {
                        dev  = h;
                        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                }
@@ -1264,6 +1159,7 @@ static int vivi_open(struct inode *inode, struct file *file)
                return -ENODEV;
 
 
+
        /* If more than one user, mutex should be added */
        dev->users++;
 
@@ -1279,6 +1175,7 @@ static int vivi_open(struct inode *inode, struct file *file)
 
        file->private_data = fh;
        fh->dev      = dev;
+
        fh->type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        fh->fmt      = &format;
        fh->width    = 640;
@@ -1314,7 +1211,7 @@ static int vivi_open(struct inode *inode, struct file *file)
 static ssize_t
 vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 {
-       struct vivi_fh *fh = file->private_data;
+       struct vivi_fh        *fh = file->private_data;
 
        if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) {
                if (res_locked(fh->dev))
@@ -1328,8 +1225,8 @@ vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 static unsigned int
 vivi_poll(struct file *file, struct poll_table_struct *wait)
 {
-       struct vivi_fh *fh = file->private_data;
-       struct vivi_buffer *buf;
+       struct vivi_fh        *fh = file->private_data;
+       struct vivi_buffer    *buf;
 
        dprintk(1,"%s\n",__FUNCTION__);
 
@@ -1358,8 +1255,8 @@ vivi_poll(struct file *file, struct poll_table_struct *wait)
 
 static int vivi_release(struct inode *inode, struct file *file)
 {
-       struct vivi_fh  *fh     = file->private_data;
-       struct vivi_dev *dev    = fh->dev;
+       struct vivi_fh         *fh = file->private_data;
+       struct vivi_dev *dev       = fh->dev;
        struct vivi_dmaqueue *vidq = &dev->vidq;
 
        int minor = iminor(inode);
@@ -1379,7 +1276,7 @@ static int vivi_release(struct inode *inode, struct file *file)
 static int
 vivi_mmap(struct file *file, struct vm_area_struct * vma)
 {
-       struct vivi_fh *fh = file->private_data;
+       struct vivi_fh        *fh = file->private_data;
        int ret;
 
        dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma);
@@ -1400,20 +1297,44 @@ static struct file_operations vivi_fops = {
        .release        = vivi_release,
        .read           = vivi_read,
        .poll           = vivi_poll,
-       .ioctl          = vivi_ioctl,
+       .ioctl          = video_ioctl2, /* V4L2 ioctl handler */
        .mmap           = vivi_mmap,
        .llseek         = no_llseek,
 };
 
 static struct video_device vivi = {
-       .name           = "VTM Virtual Video Capture Board",
+       .name           = "vivi",
        .type           = VID_TYPE_CAPTURE,
        .hardware       = 0,
        .fops           = &vivi_fops,
        .minor          = -1,
 //     .release        = video_device_release,
+
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_fmt_cap  = vidioc_enum_fmt_cap,
+       .vidioc_g_fmt_cap     = vidioc_g_fmt_cap,
+       .vidioc_try_fmt_cap   = vidioc_try_fmt_cap,
+       .vidioc_s_fmt_cap     = vidioc_s_fmt_cap,
+       .vidioc_reqbufs       = vidioc_reqbufs,
+       .vidioc_querybuf      = vidioc_querybuf,
+       .vidioc_qbuf          = vidioc_qbuf,
+       .vidioc_dqbuf         = vidioc_dqbuf,
+       .vidioc_s_std         = vidioc_s_std,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_queryctrl     = vidioc_queryctrl,
+       .vidioc_g_ctrl        = vidioc_g_ctrl,
+       .vidioc_s_ctrl        = vidioc_s_ctrl,
+       .vidioc_streamon      = vidioc_streamon,
+       .vidioc_streamoff     = vidioc_streamoff,
+#ifdef HAVE_V4L1
+       .vidiocgmbuf          = vidiocgmbuf,
+#endif
+       .tvnorms              = tvnorms,
+       .tvnormsize           = ARRAY_SIZE(tvnorms),
 };
-/* ------------------------------------------------------------------
+/* -----------------------------------------------------------------
        Initialization and module stuff
    ------------------------------------------------------------------*/
 
@@ -1457,3 +1378,16 @@ static void __exit vivi_exit(void)
 
 module_init(vivi_init);
 module_exit(vivi_exit);
+
+MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
+MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
+MODULE_LICENSE("Dual BSD/GPL");
+
+module_param(video_nr, int, 0);
+
+module_param_named(debug,vivi.debug, int, 0644);
+MODULE_PARM_DESC(debug,"activates debug info");
+
+module_param(vid_limit,int,0644);
+MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+
index 40b205b91481e495812c727da02baee30017834e..1eca7e65d235e570fcb36ce5dcf7312b759c56ea 100644 (file)
@@ -34,6 +34,7 @@
 #define I2C_NAME(x) (x)->name
 
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/video_decoder.h>
 
 #define I2C_VPX3220        0x86
index 80ef8a1b8f632ddb83656626dabdc26b5722d0a3..4bdc886abc4c69e5afa2ece884d5be8977392ce8 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/parport.h>
 
 //#define DEBUG                                // Undef me for production
index 115833e4f4dd3b421832a0a1d81a8aabd39330ee..a859a6920189e5cc62d64e864b6cfc79d995ca2d 100644 (file)
@@ -1,9 +1,9 @@
 config USB_ZC0301
-       tristate "USB ZC0301 Image Processor and Control Chip support"
+       tristate "USB ZC0301[P] Image Processor and Control Chip support"
        depends on USB && VIDEO_V4L1
        ---help---
-         Say Y here if you want support for cameras based on the ZC0301
-         Image Processor and Control Chip.
+         Say Y here if you want support for cameras based on the ZC0301 or
+         ZC0301P Image Processors and Control Chips.
 
          See <file:Documentation/video4linux/zc0301.txt> for more info.
 
index d749199d8f06f670d20c65c3bade098a52d4a15f..d9e6d97fade640271aae639ddd933b328a8a0a10 100644 (file)
@@ -1,3 +1,3 @@
-zc0301-objs     := zc0301_core.o zc0301_pas202bcb.o
+zc0301-objs     := zc0301_core.o zc0301_pb0330.o zc0301_pas202bcb.o
 
 obj-$(CONFIG_USB_ZC0301)        += zc0301.o
index 0fad39754f7a68f2c5aa4432c2f229ca2f2ea832..1b2be2d2a3ec50c7e3fa50ba34ed3dc7a7bf2c8e 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- * Video4Linux2 driver for ZC0301 Image Processor and Control Chip         *
+ * Video4Linux2 driver for ZC0301[P] Image Processor and Control Chip      *
  *                                                                         *
  * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
  *                                                                         *
 
 /*****************************************************************************/
 
-#define ZC0301_MODULE_NAME    "V4L2 driver for ZC0301 "                       \
+#define ZC0301_MODULE_NAME    "V4L2 driver for ZC0301[P] "                    \
                              "Image Processor and Control Chip"
 #define ZC0301_MODULE_AUTHOR  "(C) 2006 Luca Risolia"
 #define ZC0301_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
 #define ZC0301_MODULE_LICENSE "GPL"
-#define ZC0301_MODULE_VERSION "1:1.03"
-#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 3)
+#define ZC0301_MODULE_VERSION "1:1.05"
+#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 5)
 
 /*****************************************************************************/
 
@@ -427,10 +427,11 @@ resubmit_urb:
 static int zc0301_start_transfer(struct zc0301_device* cam)
 {
        struct usb_device *udev = cam->usbdev;
+       struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
+                                                    usb_ifnum_to_if(udev, 0),
+                                                    ZC0301_ALTERNATE_SETTING);
+       const unsigned int psz = altsetting->endpoint[0].desc.wMaxPacketSize;
        struct urb* urb;
-       const unsigned int wMaxPacketSize[] = {0, 128, 192, 256, 384,
-                                              512, 768, 1023};
-       const unsigned int psz = wMaxPacketSize[ZC0301_ALTERNATE_SETTING];
        s8 i, j;
        int err = 0;
 
@@ -1772,11 +1773,9 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_G_CTRL:
                return zc0301_vidioc_g_ctrl(cam, arg);
 
-       case VIDIOC_S_CTRL_OLD:
        case VIDIOC_S_CTRL:
                return zc0301_vidioc_s_ctrl(cam, arg);
 
-       case VIDIOC_CROPCAP_OLD:
        case VIDIOC_CROPCAP:
                return zc0301_vidioc_cropcap(cam, arg);
 
@@ -1823,7 +1822,6 @@ static int zc0301_ioctl_v4l2(struct inode* inode, struct file* filp,
        case VIDIOC_G_PARM:
                return zc0301_vidioc_g_parm(cam, arg);
 
-       case VIDIOC_S_PARM_OLD:
        case VIDIOC_S_PARM:
                return zc0301_vidioc_s_parm(cam, arg);
 
@@ -1914,7 +1912,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 
        mutex_init(&cam->dev_mutex);
 
-       DBG(2, "ZC0301 Image Processor and Control Chip detected "
+       DBG(2, "ZC0301[P] Image Processor and Control Chip detected "
               "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct);
 
        for  (i = 0; zc0301_sensor_table[i]; i++) {
@@ -1936,7 +1934,7 @@ zc0301_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
                cam->state |= DEV_MISCONFIGURED;
        }
 
-       strcpy(cam->v4ldev->name, "ZC0301 PC Camera");
+       strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera");
        cam->v4ldev->owner = THIS_MODULE;
        cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
        cam->v4ldev->hardware = 0;
index eaadf0252049c4b17a5627c76b82f3d05de4a2ba..ecfd39a56df18814f766a46886e95e29d06cc9c7 100644 (file)
@@ -1,10 +1,10 @@
 /***************************************************************************
- * Plug-in for PAS202BCB image sensor connected to the ZC030! Image        *
+ * Plug-in for PAS202BCB image sensor connected to the ZC0301[P] Image     *
  * Processor and Control Chip                                              *
  *                                                                         *
  * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
  *                                                                         *
- * Initialization values of the ZC0301 have been taken from the SPCA5XX    *
+ * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
  * driver maintained by Michel Xhaard <mxhaard@magic.fr>                   *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c
new file mode 100644 (file)
index 0000000..ed8542e
--- /dev/null
@@ -0,0 +1,187 @@
+/***************************************************************************
+ * Plug-in for PB-0330 image sensor connected to the ZC0301[P] Image       *
+ * Processor and Control Chip                                              *
+ *                                                                         *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
+ * driver maintained by Michel Xhaard <mxhaard@magic.fr>                   *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#include <linux/delay.h>
+#include "zc0301_sensor.h"
+
+
+static struct zc0301_sensor pb0330;
+
+
+static int pb0330_init(struct zc0301_device* cam)
+{
+       int err = 0;
+
+       err += zc0301_write_reg(cam, 0x0000, 0x01);
+       err += zc0301_write_reg(cam, 0x0008, 0x03);
+       err += zc0301_write_reg(cam, 0x0010, 0x0A);
+       err += zc0301_write_reg(cam, 0x0002, 0x00);
+       err += zc0301_write_reg(cam, 0x0003, 0x02);
+       err += zc0301_write_reg(cam, 0x0004, 0x80);
+       err += zc0301_write_reg(cam, 0x0005, 0x01);
+       err += zc0301_write_reg(cam, 0x0006, 0xE0);
+       err += zc0301_write_reg(cam, 0x0001, 0x01);
+       err += zc0301_write_reg(cam, 0x0012, 0x05);
+       err += zc0301_write_reg(cam, 0x0012, 0x07);
+       err += zc0301_write_reg(cam, 0x0098, 0x00);
+       err += zc0301_write_reg(cam, 0x009A, 0x00);
+       err += zc0301_write_reg(cam, 0x011A, 0x00);
+       err += zc0301_write_reg(cam, 0x011C, 0x00);
+       err += zc0301_write_reg(cam, 0x0012, 0x05);
+
+       err += zc0301_i2c_write(cam, 0x01, 0x0006);
+       err += zc0301_i2c_write(cam, 0x02, 0x0011);
+       err += zc0301_i2c_write(cam, 0x03, 0x01E7);
+       err += zc0301_i2c_write(cam, 0x04, 0x0287);
+       err += zc0301_i2c_write(cam, 0x06, 0x0003);
+       err += zc0301_i2c_write(cam, 0x07, 0x3002);
+       err += zc0301_i2c_write(cam, 0x20, 0x1100);
+       err += zc0301_i2c_write(cam, 0x2F, 0xF7B0);
+       err += zc0301_i2c_write(cam, 0x30, 0x0005);
+       err += zc0301_i2c_write(cam, 0x31, 0x0000);
+       err += zc0301_i2c_write(cam, 0x34, 0x0100);
+       err += zc0301_i2c_write(cam, 0x35, 0x0060);
+       err += zc0301_i2c_write(cam, 0x3D, 0x068F);
+       err += zc0301_i2c_write(cam, 0x40, 0x01E0);
+       err += zc0301_i2c_write(cam, 0x58, 0x0078);
+       err += zc0301_i2c_write(cam, 0x62, 0x0411);
+
+       err += zc0301_write_reg(cam, 0x0087, 0x10);
+       err += zc0301_write_reg(cam, 0x0101, 0x37);
+       err += zc0301_write_reg(cam, 0x0012, 0x05);
+       err += zc0301_write_reg(cam, 0x0100, 0x0D);
+       err += zc0301_write_reg(cam, 0x0189, 0x06);
+       err += zc0301_write_reg(cam, 0x01AD, 0x00);
+       err += zc0301_write_reg(cam, 0x01C5, 0x03);
+       err += zc0301_write_reg(cam, 0x01CB, 0x13);
+       err += zc0301_write_reg(cam, 0x0250, 0x08);
+       err += zc0301_write_reg(cam, 0x0301, 0x08);
+       err += zc0301_write_reg(cam, 0x01A8, 0x60);
+       err += zc0301_write_reg(cam, 0x018D, 0x6C);
+       err += zc0301_write_reg(cam, 0x01AD, 0x09);
+       err += zc0301_write_reg(cam, 0x01AE, 0x15);
+       err += zc0301_write_reg(cam, 0x010A, 0x50);
+       err += zc0301_write_reg(cam, 0x010B, 0xF8);
+       err += zc0301_write_reg(cam, 0x010C, 0xF8);
+       err += zc0301_write_reg(cam, 0x010D, 0xF8);
+       err += zc0301_write_reg(cam, 0x010E, 0x50);
+       err += zc0301_write_reg(cam, 0x010F, 0xF8);
+       err += zc0301_write_reg(cam, 0x0110, 0xF8);
+       err += zc0301_write_reg(cam, 0x0111, 0xF8);
+       err += zc0301_write_reg(cam, 0x0112, 0x50);
+       err += zc0301_write_reg(cam, 0x0008, 0x03);
+       err += zc0301_write_reg(cam, 0x01C6, 0x08);
+       err += zc0301_write_reg(cam, 0x01CB, 0x0F);
+       err += zc0301_write_reg(cam, 0x010A, 0x50);
+       err += zc0301_write_reg(cam, 0x010B, 0xF8);
+       err += zc0301_write_reg(cam, 0x010C, 0xF8);
+       err += zc0301_write_reg(cam, 0x010D, 0xF8);
+       err += zc0301_write_reg(cam, 0x010E, 0x50);
+       err += zc0301_write_reg(cam, 0x010F, 0xF8);
+       err += zc0301_write_reg(cam, 0x0110, 0xF8);
+       err += zc0301_write_reg(cam, 0x0111, 0xF8);
+       err += zc0301_write_reg(cam, 0x0112, 0x50);
+       err += zc0301_write_reg(cam, 0x0180, 0x00);
+       err += zc0301_write_reg(cam, 0x0019, 0x00);
+
+       err += zc0301_i2c_write(cam, 0x05, 0x0066);
+       err += zc0301_i2c_write(cam, 0x09, 0x02B2);
+       err += zc0301_i2c_write(cam, 0x10, 0x0002);
+
+       err += zc0301_write_reg(cam, 0x011D, 0x60);
+       err += zc0301_write_reg(cam, 0x0190, 0x00);
+       err += zc0301_write_reg(cam, 0x0191, 0x07);
+       err += zc0301_write_reg(cam, 0x0192, 0x8C);
+       err += zc0301_write_reg(cam, 0x0195, 0x00);
+       err += zc0301_write_reg(cam, 0x0196, 0x00);
+       err += zc0301_write_reg(cam, 0x0197, 0x8A);
+       err += zc0301_write_reg(cam, 0x018C, 0x10);
+       err += zc0301_write_reg(cam, 0x018F, 0x20);
+       err += zc0301_write_reg(cam, 0x01A9, 0x14);
+       err += zc0301_write_reg(cam, 0x01AA, 0x24);
+       err += zc0301_write_reg(cam, 0x001D, 0xD7);
+       err += zc0301_write_reg(cam, 0x001E, 0xF0);
+       err += zc0301_write_reg(cam, 0x001F, 0xF8);
+       err += zc0301_write_reg(cam, 0x0020, 0xFF);
+       err += zc0301_write_reg(cam, 0x01AD, 0x09);
+       err += zc0301_write_reg(cam, 0x01AE, 0x15);
+       err += zc0301_write_reg(cam, 0x0180, 0x40);
+       err += zc0301_write_reg(cam, 0x0180, 0x42);
+
+       msleep(100);
+
+       return err;
+}
+
+
+static struct zc0301_sensor pb0330 = {
+       .name = "PB-0330",
+       .init = &pb0330_init,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_JPEG,
+               .priv = 8,
+       },
+};
+
+
+int zc0301_probe_pb0330(struct zc0301_device* cam)
+{
+       int r0, err = 0;
+
+       err += zc0301_write_reg(cam, 0x0000, 0x01);
+       err += zc0301_write_reg(cam, 0x0010, 0x0a);
+       err += zc0301_write_reg(cam, 0x0001, 0x01);
+       err += zc0301_write_reg(cam, 0x0012, 0x03);
+       err += zc0301_write_reg(cam, 0x0012, 0x01);
+
+       msleep(10);
+
+       r0 = zc0301_i2c_read(cam, 0x00, 2);
+
+       if (r0 < 0 || err)
+               return -EIO;
+
+       if (r0 != 0x8243)
+               return -ENODEV;
+
+       zc0301_attach_sensor(cam, &pb0330);
+
+       return 0;
+}
index 1f95c28b101520a8e8c27a41b2c161e49d7a7fd6..4363a915b1f41d085b60383cd4a205bed8bab01a 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- * API for image sensors connected to the ZC030! Image Processor and       *
+ * API for image sensors connected to the ZC0301 Image Processor and       *
  * Control Chip                                                            *
  *                                                                         *
  * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
@@ -35,11 +35,13 @@ struct zc0301_sensor;
 /*****************************************************************************/
 
 extern int zc0301_probe_pas202bcb(struct zc0301_device* cam);
+extern int zc0301_probe_pb0330(struct zc0301_device* cam);
 
 #define ZC0301_SENSOR_TABLE                                                   \
 /* Weak detections must go at the end of the list */                          \
 static int (*zc0301_sensor_table[])(struct zc0301_device*) = {                \
        &zc0301_probe_pas202bcb,                                              \
+       &zc0301_probe_pb0330,                                                 \
        NULL,                                                                 \
 };
 
@@ -58,14 +60,28 @@ zc0301_attach_sensor(struct zc0301_device* cam, struct zc0301_sensor* sensor);
 
 #define ZC0301_ID_TABLE                                                       \
 static const struct usb_device_id zc0301_id_table[] =  {                      \
-       { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), },                         \
+       { ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, /* ICM105 */            \
        { ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */            \
-       { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131B */           \
+       { ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131 */            \
+       { ZC0301_USB_DEVICE(0x041e, 0x401f, 0xff), }, /* TAS5130 */           \
+       { ZC0301_USB_DEVICE(0x041e, 0x4022, 0xff), },                         \
        { ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */            \
        { ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */            \
-       { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */         \
+       { ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */            \
+       { ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */            \
+       { ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */           \
+       { ZC0301_USB_DEVICE(0x0458, 0x700C, 0xff), }, /* TAS5130 */           \
+       { ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */           \
+       { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */            \
+       { ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */           \
+       { ZC0301_USB_DEVICE(0x055f, 0xd004, 0xff), }, /* TAS5130 */           \
+       { ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */            \
        { ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), },                         \
-       { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */          \
+       { ZC0301_USB_DEVICE(0x0ac8, 0x301b, 0xff), }, /* PB-0330/HV7131 */    \
+       { ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */           \
+       { ZC0301_USB_DEVICE(0x10fd, 0x0128, 0xff), }, /* TAS5130 */           \
+       { ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130 */           \
+       { ZC0301_USB_DEVICE(0x10fd, 0x804e, 0xff), }, /* TAS5130 */           \
        { }                                                                   \
 };
 
index 0166f555a5ca1b37c5399d85b95137dd0c1705ed..ffcda95ed9d4720eba3dcfb16f1e6a473cd29e86 100644 (file)
@@ -159,7 +159,7 @@ Private IOCTL to set up for displaying MJPEG
 #define BUZ_MAX_FRAME     256  /* Must be a power of 2 */
 #define BUZ_MASK_FRAME    255  /* Must be BUZ_MAX_FRAME-1 */
 
-#define BUZ_MAX_INPUT       8
+#define BUZ_MAX_INPUT       16
 
 #if VIDEO_MAX_FRAME <= 32
 #   define   V4L_MAX_FRAME   32
@@ -191,6 +191,9 @@ enum card_type {
        /* Iomega */
        BUZ,
 
+       /* AverMedia */
+       AVS6EYES,
+
        /* total number of cards */
        NUM_CARDS
 };
@@ -379,6 +382,9 @@ struct card_info {
        /* is the /GWS line conected? */
        u8 gws_not_connected;
 
+       /* avs6eyes mux setting */
+       u8 input_mux;
+
        void (*init) (struct zoran * zr);
 };
 
index 0a85c9e7fb4824803abdf0801268bfbb9ac695bd..958c1e6fc8529a7a9e6b8d53111ac707ef692c62 100644 (file)
@@ -27,6 +27,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/delay.h>
+
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -38,6 +40,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/spinlock.h>
 #include <linux/sem.h>
 #include <linux/kmod.h>
@@ -93,6 +96,11 @@ module_param(default_input, int, 0);
 MODULE_PARM_DESC(default_input,
                 "Default input (0=Composite, 1=S-Video, 2=Internal)");
 
+static int default_mux = 1;    /* 6 Eyes input selection */
+module_param(default_mux, int, 0);
+MODULE_PARM_DESC(default_mux,
+                "Default 6 Eyes mux setting (Input selection)");
+
 static int default_norm = 0;   /* 0=PAL, 1=NTSC 2=SECAM */
 module_param(default_norm, int, 0);
 MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
@@ -301,6 +309,30 @@ lml33_init (struct zoran *zr)
        GPIO(zr, 2, 1);         // Set Composite input/output
 }
 
+static void
+avs6eyes_init (struct zoran *zr)
+{
+       // AverMedia 6-Eyes original driver by Christer Weinigel
+
+       // Lifted straight from Christer's old driver and
+       // modified slightly by Martin Samuelsson.
+
+       int mux = default_mux; /* 1 = BT866, 7 = VID1 */
+
+       GPIO(zr, 4, 1); /* Bt866 SLEEP on */
+       udelay(2);
+
+       GPIO(zr, 0, 1); /* ZR36060 /RESET on */
+       GPIO(zr, 1, 0); /* ZR36060 /SLEEP on */
+       GPIO(zr, 2, mux & 1);   /* MUX S0 */
+       GPIO(zr, 3, 0); /* /FRAME on */
+       GPIO(zr, 4, 0); /* Bt866 SLEEP off */
+       GPIO(zr, 5, mux & 2);   /* MUX S1 */
+       GPIO(zr, 6, 0); /* ? */
+       GPIO(zr, 7, mux & 4);   /* MUX S2 */
+
+}
+
 static char *
 i2cid_to_modulename (u16 i2c_id)
 {
@@ -391,6 +423,14 @@ static struct tvnorm f60sqpixel_dc10 = { 780, 640, 0, 716, 525, 480, 12 };
 static struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74+54, 804, 625, 576, 18 };
 static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 };
 
+/* FIXME: The ks0127 seem incapable of swapping U and V, too, which is why I
+ * copy Maxim's left shift hack for the 6 Eyes.
+ *
+ * Christer's driver used the unshifted norms, though...
+ * /Sam  */
+static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 };
+static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 };
+
 static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
        {
                .type = DC10_old,
@@ -419,6 +459,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
                .gpcs = { -1, 0 },
                .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
                .gws_not_connected = 0,
+               .input_mux = 0,
                .init = &dc10_init,
        }, {
                .type = DC10_new,
@@ -445,6 +486,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
                .gpcs = { -1, 1},
                .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
                .gws_not_connected = 0,
+               .input_mux = 0,
                .init = &dc10plus_init,
        }, {
                .type = DC10plus,
@@ -474,6 +516,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
                .gpcs = { -1, 1 },
                .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
                .gws_not_connected = 0,
+               .input_mux = 0,
                .init = &dc10plus_init,
        }, {
                .type = DC30,
@@ -502,6 +545,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
                .gpcs = { -1, 0 },
                .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
                .gws_not_connected = 0,
+               .input_mux = 0,
                .init = &dc10_init,
        }, {
                .type = DC30plus,
@@ -532,6 +576,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
                .gpcs = { -1, 0 },
                .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
                .gws_not_connected = 0,
+               .input_mux = 0,
                .init = &dc10_init,
        }, {
                .type = LML33,
@@ -558,6 +603,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
                .gpcs = { 3, 1 },
                .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
                .gws_not_connected = 1,
+               .input_mux = 0,
                .init = &lml33_init,
        }, {
                .type = LML33R10,
@@ -586,6 +632,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
                .gpcs = { 3, 1 },
                .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
                .gws_not_connected = 1,
+               .input_mux = 0,
                .init = &lml33_init,
        }, {
                .type = BUZ,
@@ -614,8 +661,49 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
                .gpcs = { 3, 1 },
                .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
                .gws_not_connected = 1,
+               .input_mux = 0,
                .init = &buz_init,
+       }, {
+               .type = AVS6EYES,
+               .name = "6-Eyes",
+               /* AverMedia chose not to brand the 6-Eyes. Thus it
+                  can't be autodetected, and requires card=x. */
+               .vendor_id = -1,
+               .device_id = -1,
+               .i2c_decoder = I2C_DRIVERID_KS0127,
+               .i2c_encoder = I2C_DRIVERID_BT866,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 10,
+               .input = {
+                       { 0, "Composite 1" },
+                       { 1, "Composite 2" },
+                       { 2, "Composite 3" },
+                       { 4, "Composite 4" },
+                       { 5, "Composite 5" },
+                       { 6, "Composite 6" },
+                       { 8, "S-Video 1" },
+                       { 9, "S-Video 2" },
+                       {10, "S-Video 3" },
+                       {15, "YCbCr" }
+               },
+               .norms = 2,
+               .tvn = {
+                       &f50ccir601_avs6eyes,
+                       &f60ccir601_avs6eyes,
+                       NULL
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ1,
+               .vsync_int = ZR36057_ISR_GIRQ0,
+               .gpio = { 1, 0, 3, -1, -1, -1, -1, -1 },// Validity unknown /Sam
+               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, // Validity unknown /Sam
+               .gpcs = { 3, 1 },                       // Validity unknown /Sam
+               .vfe_pol = { 1, 0, 0, 0, 0, 1, 0, 0 },  // Validity unknown /Sam
+               .gws_not_connected = 1,
+               .input_mux = 1,
+               .init = &avs6eyes_init,
        }
+
 };
 
 /*
index c690b2ee880a4fe8f44f6496177d345703962329..02168d9c218796a8c74b7f3cdf3baf921e31078b 100644 (file)
@@ -536,7 +536,7 @@ zr36057_overlay (struct zoran *zr,
                 * All error messages are internal driver checking only! */
 
                /* video display top and bottom registers */
-               reg = (u32) zr->buffer.base +
+               reg = (long) zr->buffer.base +
                    zr->overlay_settings.x *
                    ((zr->overlay_settings.format->depth + 7) / 8) +
                    zr->overlay_settings.y *
index b5a576a37fd26d909dc0e2f492dcc27c93255c03..9711f6248ef75a0ba5001dabec60a58cf8207e86 100644 (file)
@@ -73,6 +73,7 @@
                             )
 
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include "videocodec.h"
 
 #include <asm/io.h>
@@ -2047,7 +2048,7 @@ zoran_do_ioctl (struct inode *inode,
                dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr));
 
                memset(vcap, 0, sizeof(struct video_capability));
-               strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name));
+               strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)-1);
                vcap->type = ZORAN_VID_TYPE;
 
                vcap->channels = zr->card.inputs;
@@ -2689,8 +2690,8 @@ zoran_do_ioctl (struct inode *inode,
                dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr));
 
                memset(cap, 0, sizeof(*cap));
-               strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
-               strncpy(cap->driver, "zoran", sizeof(cap->driver));
+               strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1);
+               strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
                snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
                         pci_name(zr->pci_dev));
                cap->version =
@@ -2742,7 +2743,7 @@ zoran_do_ioctl (struct inode *inode,
                memset(fmt, 0, sizeof(*fmt));
                fmt->index = index;
                fmt->type = type;
-               strncpy(fmt->description, zoran_formats[i].name, 31);
+               strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1);
                fmt->pixelformat = zoran_formats[i].fourcc;
                if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
                        fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
@@ -3566,16 +3567,16 @@ zoran_do_ioctl (struct inode *inode,
 
                switch (ctrl->id) {
                case V4L2_CID_BRIGHTNESS:
-                       strncpy(ctrl->name, "Brightness", 31);
+                       strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1);
                        break;
                case V4L2_CID_CONTRAST:
-                       strncpy(ctrl->name, "Contrast", 31);
+                       strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1);
                        break;
                case V4L2_CID_SATURATION:
-                       strncpy(ctrl->name, "Saturation", 31);
+                       strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1);
                        break;
                case V4L2_CID_HUE:
-                       strncpy(ctrl->name, "Hue", 31);
+                       strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1);
                        break;
                }
 
@@ -3693,7 +3694,7 @@ zoran_do_ioctl (struct inode *inode,
                                        &caps);
                        if (caps.flags & VIDEO_DECODER_AUTO) {
                                std->id = V4L2_STD_ALL;
-                               strncpy(std->name, "Autodetect", 31);
+                               strncpy(std->name, "Autodetect", sizeof(std->name)-1);
                                return 0;
                        } else
                                return -EINVAL;
@@ -3701,21 +3702,21 @@ zoran_do_ioctl (struct inode *inode,
                switch (std->index) {
                case 0:
                        std->id = V4L2_STD_PAL;
-                       strncpy(std->name, "PAL", 31);
+                       strncpy(std->name, "PAL", sizeof(std->name)-1);
                        std->frameperiod.numerator = 1;
                        std->frameperiod.denominator = 25;
                        std->framelines = zr->card.tvn[0]->Ht;
                        break;
                case 1:
                        std->id = V4L2_STD_NTSC;
-                       strncpy(std->name, "NTSC", 31);
+                       strncpy(std->name, "NTSC", sizeof(std->name)-1);
                        std->frameperiod.numerator = 1001;
                        std->frameperiod.denominator = 30000;
                        std->framelines = zr->card.tvn[1]->Ht;
                        break;
                case 2:
                        std->id = V4L2_STD_SECAM;
-                       strncpy(std->name, "SECAM", 31);
+                       strncpy(std->name, "SECAM", sizeof(std->name)-1);
                        std->frameperiod.numerator = 1;
                        std->frameperiod.denominator = 25;
                        std->framelines = zr->card.tvn[2]->Ht;
@@ -3871,7 +3872,7 @@ zoran_do_ioctl (struct inode *inode,
                memset(outp, 0, sizeof(*outp));
                outp->index = 0;
                outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
-               strncpy(outp->name, "Autodetect", 31);
+               strncpy(outp->name, "Autodetect", sizeof(outp->name)-1);
 
                return 0;
        }
index a00fae90229a84c2236c5bde5346c5778b5ba6d2..f4ffe79bdc5b710fd446694ad3b2fc9e7f77df7b 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/seq_file.h>
 
 #include <linux/ctype.h>
+#include <linux/poll.h>
 #include <asm/io.h>
 
 #include "videocodec.h"
index 23c1827b2d0bb22d5e54545dbfad49e76e364185..f4ddd3431f179055e54b12118162c26b40cf2278 100644 (file)
 #include <linux/config.h>
 #include <linux/version.h>
 
+#define __OLD_VIDIOC_
+
 #include "matroxfb_base.h"
 #include "matroxfb_misc.h"
 #include "matroxfb_accel.h"
@@ -158,9 +160,9 @@ static void update_crtc2(WPMINFO unsigned int pos) {
 
        /* Make sure that displays are compatible */
        if (info && (info->fbcon.var.bits_per_pixel == ACCESS_FBINFO(fbcon).var.bits_per_pixel)
-                && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual)
-                && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length)
-                ) {
+                && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual)
+                && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length)
+                ) {
                switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
                        case 16:
                        case 32:
@@ -224,7 +226,7 @@ static irqreturn_t matrox_irq(int irq, void *dev_id, struct pt_regs *fp)
 
 int matroxfb_enable_irq(WPMINFO int reenable) {
        u_int32_t bm;
-       
+
        if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400)
                bm = 0x220;
        else
@@ -241,7 +243,7 @@ int matroxfb_enable_irq(WPMINFO int reenable) {
                mga_outl(M_IEN, mga_inl(M_IEN) | bm);
        } else if (reenable) {
                u_int32_t ien;
-               
+
                ien = mga_inl(M_IEN);
                if ((ien & bm) != bm) {
                        printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien);
@@ -347,7 +349,7 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
                mga_setr(M_EXTVGA_INDEX, 0x00, p2);
        }
        matroxfb_DAC_unlock_irqrestore(flags);
-       
+
        update_crtc2(PMINFO pos);
 
        CRITEND
@@ -390,7 +392,7 @@ static void matroxfb_remove(WPMINFO int dummy) {
 static int matroxfb_open(struct fb_info *info, int user)
 {
        MINFO_FROM_INFO(info);
-       
+
        DBG_LOOP(__FUNCTION__)
 
        if (ACCESS_FBINFO(dead)) {
@@ -406,7 +408,7 @@ static int matroxfb_open(struct fb_info *info, int user)
 static int matroxfb_release(struct fb_info *info, int user)
 {
        MINFO_FROM_INFO(info);
-       
+
        DBG_LOOP(__FUNCTION__)
 
        if (user) {
@@ -854,7 +856,7 @@ static int matroxfb_get_vblank(WPMINFO struct fb_vblank *vblank)
                vblank->flags |= FB_VBLANK_VBLANKING;
        if (test_bit(0, &ACCESS_FBINFO(irq_flags))) {
                vblank->flags |= FB_VBLANK_HAVE_COUNT;
-               /* Only one writer, aligned int value... 
+               /* Only one writer, aligned int value...
                   it should work without lock and without atomic_t */
                vblank->count = ACCESS_FBINFO(crtc1).vsync.cnt;
        }
@@ -870,7 +872,7 @@ static int matroxfb_ioctl(struct fb_info *info,
 {
        void __user *argp = (void __user *)arg;
        MINFO_FROM_INFO(info);
-       
+
        DBG(__FUNCTION__)
 
        if (ACCESS_FBINFO(dead)) {
@@ -1081,7 +1083,7 @@ static int matroxfb_ioctl(struct fb_info *info,
                case VIDIOC_QUERYCAP:
                        {
                                struct v4l2_capability r;
-                               
+
                                memset(&r, 0, sizeof(r));
                                strcpy(r.driver, "matroxfb");
                                strcpy(r.card, "Matrox");
@@ -1091,7 +1093,7 @@ static int matroxfb_ioctl(struct fb_info *info,
                                if (copy_to_user(argp, &r, sizeof(r)))
                                        return -EFAULT;
                                return 0;
-                               
+
                        }
                case VIDIOC_QUERYCTRL:
                        {
@@ -1690,8 +1692,8 @@ static int initMatrox2(WPMINFO struct board* b){
                pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, &cmd);
                mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
                mga_option |= MX_OPTION_BSWAP;
-                /* disable palette snooping */
-                cmd &= ~PCI_COMMAND_VGA_PALETTE;
+               /* disable palette snooping */
+               cmd &= ~PCI_COMMAND_VGA_PALETTE;
                if (pci_dev_present(intel_82437)) {
                        if (!(mga_option & 0x20000000) && !ACCESS_FBINFO(devflags.nopciretry)) {
                                printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
@@ -1809,12 +1811,12 @@ static int initMatrox2(WPMINFO struct board* b){
 
                if (fv) {
                        tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres
-                                 + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
+                                 + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
                        if ((tmp < fh) || (fh == 0)) fh = tmp;
                }
                if (fh) {
                        tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres
-                                 + vesafb_defined.right_margin + vesafb_defined.hsync_len);
+                                 + vesafb_defined.right_margin + vesafb_defined.hsync_len);
                        if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
                }
                tmp = (maxclk + 499) / 500;
@@ -1890,14 +1892,14 @@ static int initMatrox2(WPMINFO struct board* b){
 
        /* there is no console on this fb... but we have to initialize hardware
         * until someone tells me what is proper thing to do */
-       if (!ACCESS_FBINFO(initialized)) {
-               printk(KERN_INFO "fb%d: initializing hardware\n",
-                      ACCESS_FBINFO(fbcon.node));
-               /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
-                * already before, so register_framebuffer works correctly. */
-               vesafb_defined.activate |= FB_ACTIVATE_FORCE;
-               fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined);
-       }
+       if (!ACCESS_FBINFO(initialized)) {
+               printk(KERN_INFO "fb%d: initializing hardware\n",
+                      ACCESS_FBINFO(fbcon.node));
+               /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
+                * already before, so register_framebuffer works correctly. */
+               vesafb_defined.activate |= FB_ACTIVATE_FORCE;
+               fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined);
+       }
 
        return 0;
 failVideoIO:;
@@ -2356,7 +2358,7 @@ static int __init matroxfb_setup(char *options) {
                else if (!strncmp(this_opt, "dfp:", 4)) {
                        dfp_type = simple_strtoul(this_opt+4, NULL, 0);
                        dfp = 1;
-               }       
+               }
 #ifdef CONFIG_PPC_PMAC
                else if (!strncmp(this_opt, "vmode:", 6)) {
                        unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
index d2c38875ab296e45741c5dcf966da56ec51d8f96..9eb9824dd3323a1a0680653ef92a598efc76a287 100644 (file)
@@ -205,38 +205,6 @@ static int do_ext3_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
        return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
 }
 
-struct compat_dmx_event {
-       dmx_event_t     event;
-       compat_time_t   timeStamp;
-       union
-       {
-               dmx_scrambling_status_t scrambling;
-       } u;
-};
-
-static int do_dmx_get_event(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       struct dmx_event kevent;
-       mm_segment_t old_fs = get_fs();
-       int err;
-
-       set_fs(KERNEL_DS);
-       err = sys_ioctl(fd, cmd, (unsigned long) &kevent);
-       set_fs(old_fs);
-
-       if (!err) {
-               struct compat_dmx_event __user *up = compat_ptr(arg);
-
-               err  = put_user(kevent.event, &up->event);
-               err |= put_user(kevent.timeStamp, &up->timeStamp);
-               err |= put_user(kevent.u.scrambling, &up->u.scrambling);
-               if (err)
-                       err = -EFAULT;
-       }
-
-       return err;
-}
-
 struct compat_video_event {
        int32_t         type;
        compat_time_t   timestamp;
@@ -2964,7 +2932,6 @@ HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata)
 #endif
 
 /* dvb */
-HANDLE_IOCTL(DMX_GET_EVENT, do_dmx_get_event)
 HANDLE_IOCTL(VIDEO_GET_EVENT, do_video_get_event)
 HANDLE_IOCTL(VIDEO_STILLPICTURE, do_video_stillpicture)
 HANDLE_IOCTL(VIDEO_SET_SPU_PALETTE, do_video_set_spu_palette)
index 2787b8a22ff1b772e2bc42cddeff33f6512de2fa..c6a2353c4e68f2831db0007fcc9d9070da1202ae 100644 (file)
@@ -88,20 +88,6 @@ typedef enum
 #define DMX_PES_PCR      DMX_PES_PCR0
 
 
-typedef enum
-{
-       DMX_SCRAMBLING_EV,
-       DMX_FRONTEND_EV
-} dmx_event_t;
-
-
-typedef enum
-{
-       DMX_SCRAMBLING_OFF,
-       DMX_SCRAMBLING_ON
-} dmx_scrambling_status_t;
-
-
 typedef struct dmx_filter
 {
        __u8  filter[DMX_FILTER_SIZE];
@@ -132,17 +118,6 @@ struct dmx_pes_filter_params
        __u32          flags;
 };
 
-
-struct dmx_event
-{
-       dmx_event_t         event;
-       time_t              timeStamp;
-       union
-       {
-               dmx_scrambling_status_t scrambling;
-       } u;
-};
-
 typedef struct dmx_caps {
        __u32 caps;
        int num_decoders;
@@ -171,7 +146,6 @@ struct dmx_stc {
 #define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
 #define DMX_SET_PES_FILTER       _IOW('o', 44, struct dmx_pes_filter_params)
 #define DMX_SET_BUFFER_SIZE      _IO('o', 45)
-#define DMX_GET_EVENT            _IOR('o', 46, struct dmx_event)
 #define DMX_GET_PES_PIDS         _IOR('o', 47, __u16[5])
 #define DMX_GET_CAPS             _IOR('o', 48, dmx_caps_t)
 #define DMX_SET_SOURCE           _IOW('o', 49, dmx_source_t)
index c8b81f419fd8e49aa6f42d6994204ab96884c4c5..21338bb3441d6b9387e327e9ec208fdaab2ec391 100644 (file)
 #define I2C_DRIVERID_X1205     82      /* Xicor/Intersil X1205 RTC     */
 #define I2C_DRIVERID_PCF8563   83      /* Philips PCF8563 RTC          */
 #define I2C_DRIVERID_RS5C372   84      /* Ricoh RS5C372 RTC            */
+#define I2C_DRIVERID_BT866     85      /* Conexant bt866 video encoder */
+#define I2C_DRIVERID_KS0127    86      /* Samsung ks0127 video decoder */
+#define I2C_DRIVERID_TLV320AIC23B 87   /* TI TLV320AIC23B audio codec  */
 
 #define I2C_DRIVERID_I2CDEV    900
 #define I2C_DRIVERID_ARP        902    /* SMBus ARP Client              */
index 91140091ced2f2b510a3ac2bf05d79d738078f0e..41bc7e9603cdf690debf168fc936252e9dad798e 100644 (file)
@@ -1,49 +1,21 @@
+/*
+ *     Video for Linux version 1 - OBSOLETE
+ *
+ *     Header file for v4l1 drivers and applications, for
+ *     Linux kernels 2.2.x or 2.4.x.
+ *
+ *     Provides header for legacy drivers and applications
+ *
+ *     See http://linuxtv.org for more info
+ *
+ */
 #ifndef __LINUX_VIDEODEV_H
 #define __LINUX_VIDEODEV_H
 
-#include <linux/types.h>
-
 #define HAVE_V4L1 1
 
 #include <linux/videodev2.h>
 
-#ifdef __KERNEL__
-
-#include <linux/mm.h>
-
-extern struct video_device* video_devdata(struct file*);
-
-#define to_video_device(cd) container_of(cd, struct video_device, class_dev)
-static inline void
-video_device_create_file(struct video_device *vfd,
-                        struct class_device_attribute *attr)
-{
-       class_device_create_file(&vfd->class_dev, attr);
-}
-static inline void
-video_device_remove_file(struct video_device *vfd,
-                        struct class_device_attribute *attr)
-{
-       class_device_remove_file(&vfd->class_dev, attr);
-}
-
-#if OBSOLETE_OWNER /* to be removed in 2.6.15 */
-/* helper functions to access driver private data. */
-static inline void *video_get_drvdata(struct video_device *dev)
-{
-       return dev->priv;
-}
-
-static inline void video_set_drvdata(struct video_device *dev, void *data)
-{
-       dev->priv = data;
-}
-#endif
-
-extern int video_exclusive_open(struct inode *inode, struct file *file);
-extern int video_exclusive_release(struct inode *inode, struct file *file);
-#endif /* __KERNEL__ */
-
 struct video_capability
 {
        char name[32];
@@ -363,6 +335,7 @@ struct video_code
 #define VID_HARDWARE_SAA7114H   37
 #define VID_HARDWARE_SN9C102   38
 #define VID_HARDWARE_ARV       39
+
 #endif /* __LINUX_VIDEODEV_H */
 
 /*
index ad7fa9c86c1008157211021ce5f23829368d6ff0..4f428547ec090ac7752d80b86b792538d5d491c3 100644 (file)
@@ -1,35 +1,33 @@
-#ifndef __LINUX_VIDEODEV2_H
-#define __LINUX_VIDEODEV2_H
 /*
  *     Video for Linux Two
  *
- *     Header file for v4l or V4L2 drivers and applications, for
- *     Linux kernels 2.2.x or 2.4.x.
+ *     Header file for v4l or V4L2 drivers and applications
+ * with public API.
+ * All kernel-specific stuff were moved to media/v4l2-dev.h, so
+ * no #if __KERNEL tests are allowed here
  *
- *     See http://bytesex.org/v4l/ for API specs and other
- *     v4l2 documentation.
+ *     See http://linuxtv.org for more info
  *
  *     Author: Bill Dirks <bdirks@pacbell.net>
  *             Justin Schoeman
  *             et al.
  */
+#ifndef __LINUX_VIDEODEV2_H
+#define __LINUX_VIDEODEV2_H
 #ifdef __KERNEL__
-#include <linux/time.h> /* need struct timeval */
-#include <linux/poll.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#endif
+#include <linux/time.h>     /* need struct timeval */
 #include <linux/compiler.h> /* need __user */
+#else
+#define __user
+#endif
+#include <linux/types.h>
 
-
-#define OBSOLETE_OWNER 1 /* It will be removed for 2.6.17 */
 #define HAVE_V4L2 1
 
 /*
  * Common stuff for both V4L1 and V4L2
  * Moved from videodev.h
  */
-
 #define VIDEO_MAX_FRAME               32
 
 #define VID_TYPE_CAPTURE       1       /* Can capture */
 #define VID_TYPE_MJPEG_DECODER 4096    /* Can decode MJPEG streams */
 #define VID_TYPE_MJPEG_ENCODER 8192    /* Can encode MJPEG streams */
 
-#ifdef __KERNEL__
-
-/* Minor device allocation */
-#define MINOR_VFL_TYPE_GRABBER_MIN   0
-#define MINOR_VFL_TYPE_GRABBER_MAX  63
-#define MINOR_VFL_TYPE_RADIO_MIN    64
-#define MINOR_VFL_TYPE_RADIO_MAX   127
-#define MINOR_VFL_TYPE_VTX_MIN     192
-#define MINOR_VFL_TYPE_VTX_MAX     223
-#define MINOR_VFL_TYPE_VBI_MIN     224
-#define MINOR_VFL_TYPE_VBI_MAX     255
-
-#define VFL_TYPE_GRABBER       0
-#define VFL_TYPE_VBI           1
-#define VFL_TYPE_RADIO         2
-#define VFL_TYPE_VTX           3
-
-struct video_device
-{
-       /* device info */
-       struct device *dev;
-       char name[32];
-       int type;       /* v4l1 */
-       int type2;      /* v4l2 */
-       int hardware;
-       int minor;
-
-       /* device ops + callbacks */
-       const struct file_operations *fops;
-       void (*release)(struct video_device *vfd);
-
-
-#if OBSOLETE_OWNER /* to be removed in 2.6.15 */
-       /* obsolete -- fops->owner is used instead */
-       struct module *owner;
-       /* dev->driver_data will be used instead some day.
-        * Use the video_{get|set}_drvdata() helper functions,
-        * so the switch over will be transparent for you.
-        * Or use {pci|usb}_{get|set}_drvdata() directly. */
-       void *priv;
-#endif
-
-       /* for videodev.c intenal usage -- please don't touch */
-       int users;                     /* video_exclusive_{open|close} ... */
-       struct mutex lock;             /* ... helper function uses these   */
-       char devfs_name[64];           /* devfs */
-       struct class_device class_dev; /* sysfs */
-};
-
-#define VIDEO_MAJOR    81
-
-extern int video_register_device(struct video_device *, int type, int nr);
-extern void video_unregister_device(struct video_device *);
-extern int video_usercopy(struct inode *inode, struct file *file,
-                         unsigned int cmd, unsigned long arg,
-                         int (*func)(struct inode *inode, struct file *file,
-                                     unsigned int cmd, void *arg));
-
-/* helper functions to alloc / release struct video_device, the
-   later can be used for video_device->release() */
-struct video_device *video_device_alloc(void);
-void video_device_release(struct video_device *vfd);
-
-#endif
-
 /*
  *     M I S C E L L A N E O U S
  */
@@ -172,6 +105,8 @@ enum v4l2_ctrl_type {
        V4L2_CTRL_TYPE_BOOLEAN       = 2,
        V4L2_CTRL_TYPE_MENU          = 3,
        V4L2_CTRL_TYPE_BUTTON        = 4,
+       V4L2_CTRL_TYPE_INTEGER64     = 5,
+       V4L2_CTRL_TYPE_CTRL_CLASS    = 6,
 };
 
 enum v4l2_tuner_type {
@@ -270,7 +205,6 @@ struct v4l2_capability
 /*
  *     V I D E O   I M A G E   F O R M A T
  */
-
 struct v4l2_pix_format
 {
        __u32                   width;
@@ -283,7 +217,7 @@ struct v4l2_pix_format
        __u32                   priv;           /* private data, depends on pixelformat */
 };
 
-/*           Pixel format    FOURCC                  depth  Description   */
+/*      Pixel format         FOURCC                        depth  Description  */
 #define V4L2_PIX_FMT_RGB332  v4l2_fourcc('R','G','B','1') /*  8  RGB-3-3-2     */
 #define V4L2_PIX_FMT_RGB555  v4l2_fourcc('R','G','B','O') /* 16  RGB-5-5-5     */
 #define V4L2_PIX_FMT_RGB565  v4l2_fourcc('R','G','B','P') /* 16  RGB-5-6-5     */
@@ -319,7 +253,7 @@ struct v4l2_pix_format
 #define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M','J','P','G') /* Motion-JPEG   */
 #define V4L2_PIX_FMT_JPEG     v4l2_fourcc('J','P','E','G') /* JFIF JPEG     */
 #define V4L2_PIX_FMT_DV       v4l2_fourcc('d','v','s','d') /* 1394          */
-#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M','P','E','G') /* MPEG          */
+#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M','P','E','G') /* MPEG-1/2/4    */
 
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_WNVA     v4l2_fourcc('W','N','V','A') /* Winnov hw compress */
@@ -343,7 +277,6 @@ struct v4l2_fmtdesc
 
 #define V4L2_FMT_FLAG_COMPRESSED 0x0001
 
-
 /*
  *     T I M E C O D E
  */
@@ -373,16 +306,15 @@ struct v4l2_timecode
 #define V4L2_TC_USERBITS_8BITCHARS     0x0008
 /* The above is based on SMPTE timecodes */
 
-
+#ifdef __KERNEL__
 /*
  *     M P E G   C O M P R E S S I O N   P A R A M E T E R S
  *
- *  ### WARNING: this is still work-in-progress right now, most likely
- *  ###          there will be some incompatible changes.
+ *  ### WARNING: This experimental MPEG compression API is obsolete.
+ *  ###          It is replaced by the MPEG controls API.
+ *  ###          This old API will disappear in the near future!
  *
  */
-
-
 enum v4l2_bitrate_mode {
        V4L2_BITRATE_NONE = 0,  /* not specified */
        V4L2_BITRATE_CBR,       /* constant bitrate */
@@ -460,6 +392,7 @@ struct v4l2_mpeg_compression {
        /* I don't expect the above being perfect yet ;) */
        __u32                           reserved_5[8];
 };
+#endif
 
 struct v4l2_jpegcompression
 {
@@ -491,7 +424,6 @@ struct v4l2_jpegcompression
                                        * allways use APP0 */
 };
 
-
 /*
  *     M E M O R Y - M A P P I N G   B U F F E R S
  */
@@ -573,7 +505,6 @@ struct v4l2_window
        void                    __user *bitmap;
 };
 
-
 /*
  *     C A P T U R E   P A R A M E T E R S
  */
@@ -586,6 +517,7 @@ struct v4l2_captureparm
        __u32              readbuffers;   /*  # of buffers for read */
        __u32              reserved[4];
 };
+
 /*  Flags for 'capability' and 'capturemode' fields */
 #define V4L2_MODE_HIGHQUALITY  0x0001  /*  High quality imaging mode */
 #define V4L2_CAP_TIMEPERFRAME  0x1000  /*  timeperframe field is supported */
@@ -603,7 +535,6 @@ struct v4l2_outputparm
 /*
  *     I N P U T   I M A G E   C R O P P I N G
  */
-
 struct v4l2_cropcap {
        enum v4l2_buf_type      type;
        struct v4l2_rect        bounds;
@@ -710,7 +641,6 @@ struct v4l2_standard
        __u32                reserved[4];
 };
 
-
 /*
  *     V I D E O   I N P U T S
  */
@@ -725,6 +655,7 @@ struct v4l2_input
        __u32        status;
        __u32        reserved[4];
 };
+
 /*  Values for the 'type' field */
 #define V4L2_INPUT_TYPE_TUNER          1
 #define V4L2_INPUT_TYPE_CAMERA         2
@@ -775,6 +706,34 @@ struct v4l2_control
        __s32                value;
 };
 
+struct v4l2_ext_control
+{
+       __u32 id;
+       __u32 reserved2[2];
+       union {
+               __s32 value;
+               __s64 value64;
+               void *reserved;
+       };
+};
+
+struct v4l2_ext_controls
+{
+       __u32 ctrl_class;
+       __u32 count;
+       __u32 error_idx;
+       __u32 reserved[2];
+       struct v4l2_ext_control *controls;
+};
+
+/*  Values for ctrl_class field */
+#define V4L2_CTRL_CLASS_USER 0x00980000        /* Old-style 'user' controls */
+#define V4L2_CTRL_CLASS_MPEG 0x00990000        /* MPEG-compression controls */
+
+#define V4L2_CTRL_ID_MASK                (0x0fffffff)
+#define V4L2_CTRL_ID2CLASS(id)    ((id) & 0x0fff0000UL)
+#define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000)
+
 /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
 struct v4l2_queryctrl
 {
@@ -801,12 +760,21 @@ struct v4l2_querymenu
 /*  Control flags  */
 #define V4L2_CTRL_FLAG_DISABLED                0x0001
 #define V4L2_CTRL_FLAG_GRABBED         0x0002
+#define V4L2_CTRL_FLAG_READ_ONLY       0x0004
+#define V4L2_CTRL_FLAG_UPDATE          0x0008
+#define V4L2_CTRL_FLAG_INACTIVE        0x0010
+#define V4L2_CTRL_FLAG_SLIDER          0x0020
+
+/*  Query flag, to be ORed with the control ID */
+#define V4L2_CTRL_FLAG_NEXT_CTRL       0x80000000
 
-/*  Control IDs defined by V4L2 */
-#define V4L2_CID_BASE                  0x00980900
+/*  User-class control IDs defined by V4L2 */
+#define V4L2_CID_BASE                  (V4L2_CTRL_CLASS_USER | 0x900)
+#define V4L2_CID_USER_BASE             V4L2_CID_BASE
 /*  IDs reserved for driver specific controls */
 #define V4L2_CID_PRIVATE_BASE          0x08000000
 
+#define V4L2_CID_USER_CLASS            (V4L2_CTRL_CLASS_USER | 1)
 #define V4L2_CID_BRIGHTNESS            (V4L2_CID_BASE+0)
 #define V4L2_CID_CONTRAST              (V4L2_CID_BASE+1)
 #define V4L2_CID_SATURATION            (V4L2_CID_BASE+2)
@@ -833,6 +801,183 @@ struct v4l2_querymenu
 #define V4L2_CID_VCENTER               (V4L2_CID_BASE+23)
 #define V4L2_CID_LASTP1                        (V4L2_CID_BASE+24) /* last CID + 1 */
 
+/*  MPEG-class control IDs defined by V4L2 */
+#define V4L2_CID_MPEG_BASE                     (V4L2_CTRL_CLASS_MPEG | 0x900)
+#define V4L2_CID_MPEG_CLASS                    (V4L2_CTRL_CLASS_MPEG | 1)
+
+/*  MPEG streams */
+#define V4L2_CID_MPEG_STREAM_TYPE              (V4L2_CID_MPEG_BASE+0)
+enum v4l2_mpeg_stream_type {
+       V4L2_MPEG_STREAM_TYPE_MPEG2_PS   = 0, /* MPEG-2 program stream */
+       V4L2_MPEG_STREAM_TYPE_MPEG2_TS   = 1, /* MPEG-2 transport stream */
+       V4L2_MPEG_STREAM_TYPE_MPEG1_SS   = 2, /* MPEG-1 system stream */
+       V4L2_MPEG_STREAM_TYPE_MPEG2_DVD  = 3, /* MPEG-2 DVD-compatible stream */
+       V4L2_MPEG_STREAM_TYPE_MPEG1_VCD  = 4, /* MPEG-1 VCD-compatible stream */
+       V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */
+};
+#define V4L2_CID_MPEG_STREAM_PID_PMT           (V4L2_CID_MPEG_BASE+1)
+#define V4L2_CID_MPEG_STREAM_PID_AUDIO                 (V4L2_CID_MPEG_BASE+2)
+#define V4L2_CID_MPEG_STREAM_PID_VIDEO                 (V4L2_CID_MPEG_BASE+3)
+#define V4L2_CID_MPEG_STREAM_PID_PCR           (V4L2_CID_MPEG_BASE+4)
+#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO      (V4L2_CID_MPEG_BASE+5)
+#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO      (V4L2_CID_MPEG_BASE+6)
+
+/*  MPEG audio */
+#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ      (V4L2_CID_MPEG_BASE+100)
+enum v4l2_mpeg_audio_sampling_freq {
+       V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0,
+       V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1,
+       V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2,
+};
+#define V4L2_CID_MPEG_AUDIO_ENCODING           (V4L2_CID_MPEG_BASE+101)
+enum v4l2_mpeg_audio_encoding {
+       V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0,
+       V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1,
+       V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2,
+};
+#define V4L2_CID_MPEG_AUDIO_L1_BITRATE                 (V4L2_CID_MPEG_BASE+102)
+enum v4l2_mpeg_audio_l1_bitrate {
+       V4L2_MPEG_AUDIO_L1_BITRATE_32K  = 0,
+       V4L2_MPEG_AUDIO_L1_BITRATE_64K  = 1,
+       V4L2_MPEG_AUDIO_L1_BITRATE_96K  = 2,
+       V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3,
+       V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4,
+       V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5,
+       V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6,
+       V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7,
+       V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8,
+       V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9,
+       V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10,
+       V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11,
+       V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12,
+       V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13,
+};
+#define V4L2_CID_MPEG_AUDIO_L2_BITRATE                 (V4L2_CID_MPEG_BASE+103)
+enum v4l2_mpeg_audio_l2_bitrate {
+       V4L2_MPEG_AUDIO_L2_BITRATE_32K  = 0,
+       V4L2_MPEG_AUDIO_L2_BITRATE_48K  = 1,
+       V4L2_MPEG_AUDIO_L2_BITRATE_56K  = 2,
+       V4L2_MPEG_AUDIO_L2_BITRATE_64K  = 3,
+       V4L2_MPEG_AUDIO_L2_BITRATE_80K  = 4,
+       V4L2_MPEG_AUDIO_L2_BITRATE_96K  = 5,
+       V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6,
+       V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7,
+       V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8,
+       V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9,
+       V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10,
+       V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11,
+       V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12,
+       V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13,
+};
+#define V4L2_CID_MPEG_AUDIO_L3_BITRATE                 (V4L2_CID_MPEG_BASE+104)
+enum v4l2_mpeg_audio_l3_bitrate {
+       V4L2_MPEG_AUDIO_L3_BITRATE_32K  = 0,
+       V4L2_MPEG_AUDIO_L3_BITRATE_40K  = 1,
+       V4L2_MPEG_AUDIO_L3_BITRATE_48K  = 2,
+       V4L2_MPEG_AUDIO_L3_BITRATE_56K  = 3,
+       V4L2_MPEG_AUDIO_L3_BITRATE_64K  = 4,
+       V4L2_MPEG_AUDIO_L3_BITRATE_80K  = 5,
+       V4L2_MPEG_AUDIO_L3_BITRATE_96K  = 6,
+       V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7,
+       V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8,
+       V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9,
+       V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10,
+       V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11,
+       V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12,
+       V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13,
+};
+#define V4L2_CID_MPEG_AUDIO_MODE               (V4L2_CID_MPEG_BASE+105)
+enum v4l2_mpeg_audio_mode {
+       V4L2_MPEG_AUDIO_MODE_STEREO       = 0,
+       V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1,
+       V4L2_MPEG_AUDIO_MODE_DUAL         = 2,
+       V4L2_MPEG_AUDIO_MODE_MONO         = 3,
+};
+#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION     (V4L2_CID_MPEG_BASE+106)
+enum v4l2_mpeg_audio_mode_extension {
+       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4  = 0,
+       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8  = 1,
+       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2,
+       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3,
+};
+#define V4L2_CID_MPEG_AUDIO_EMPHASIS           (V4L2_CID_MPEG_BASE+107)
+enum v4l2_mpeg_audio_emphasis {
+       V4L2_MPEG_AUDIO_EMPHASIS_NONE         = 0,
+       V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1,
+       V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17    = 2,
+};
+#define V4L2_CID_MPEG_AUDIO_CRC                (V4L2_CID_MPEG_BASE+108)
+enum v4l2_mpeg_audio_crc {
+       V4L2_MPEG_AUDIO_CRC_NONE  = 0,
+       V4L2_MPEG_AUDIO_CRC_CRC16 = 1,
+};
+
+/*  MPEG video */
+#define V4L2_CID_MPEG_VIDEO_ENCODING           (V4L2_CID_MPEG_BASE+200)
+enum v4l2_mpeg_video_encoding {
+       V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0,
+       V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_ASPECT             (V4L2_CID_MPEG_BASE+201)
+enum v4l2_mpeg_video_aspect {
+       V4L2_MPEG_VIDEO_ASPECT_1x1     = 0,
+       V4L2_MPEG_VIDEO_ASPECT_4x3     = 1,
+       V4L2_MPEG_VIDEO_ASPECT_16x9    = 2,
+       V4L2_MPEG_VIDEO_ASPECT_221x100 = 3,
+};
+#define V4L2_CID_MPEG_VIDEO_B_FRAMES           (V4L2_CID_MPEG_BASE+202)
+#define V4L2_CID_MPEG_VIDEO_GOP_SIZE           (V4L2_CID_MPEG_BASE+203)
+#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE        (V4L2_CID_MPEG_BASE+204)
+#define V4L2_CID_MPEG_VIDEO_PULLDOWN           (V4L2_CID_MPEG_BASE+205)
+#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE       (V4L2_CID_MPEG_BASE+206)
+enum v4l2_mpeg_video_bitrate_mode {
+       V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0,
+       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_BITRATE            (V4L2_CID_MPEG_BASE+207)
+#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK       (V4L2_CID_MPEG_BASE+208)
+#define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209)
+
+/*  MPEG-class control IDs specific to the CX2584x driver as defined by V4L2 */
+#define V4L2_CID_MPEG_CX2341X_BASE                             (V4L2_CTRL_CLASS_MPEG | 0x1000)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE        (V4L2_CID_MPEG_CX2341X_BASE+0)
+enum v4l2_mpeg_cx2341x_video_spatial_filter_mode {
+       V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0,
+       V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO   = 1,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER             (V4L2_CID_MPEG_CX2341X_BASE+1)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE   (V4L2_CID_MPEG_CX2341X_BASE+2)
+enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type {
+       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF                  = 0,
+       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR               = 1,
+       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT              = 2,
+       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE      = 3,
+       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE         (V4L2_CID_MPEG_CX2341X_BASE+3)
+enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type {
+       V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF    = 0,
+       V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE       (V4L2_CID_MPEG_CX2341X_BASE+4)
+enum v4l2_mpeg_cx2341x_video_temporal_filter_mode {
+       V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0,
+       V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO   = 1,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER            (V4L2_CID_MPEG_CX2341X_BASE+5)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE                 (V4L2_CID_MPEG_CX2341X_BASE+6)
+enum v4l2_mpeg_cx2341x_video_median_filter_type {
+       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF      = 0,
+       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR      = 1,
+       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT     = 2,
+       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3,
+       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG     = 4,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM  (V4L2_CID_MPEG_CX2341X_BASE+7)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP     (V4L2_CID_MPEG_CX2341X_BASE+8)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM        (V4L2_CID_MPEG_CX2341X_BASE+9)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP   (V4L2_CID_MPEG_CX2341X_BASE+10)
+
 /*
  *     T U N I N G
  */
@@ -904,6 +1049,7 @@ struct v4l2_audio
        __u32   mode;
        __u32   reserved[2];
 };
+
 /*  Flags for the 'capability' field */
 #define V4L2_AUDCAP_STEREO             0x00001
 #define V4L2_AUDCAP_AVL                        0x00002
@@ -927,7 +1073,6 @@ struct v4l2_audioout
  */
 
 /* Raw VBI */
-
 struct v4l2_vbi_format
 {
        __u32   sampling_rate;          /* in 1 Hz */
@@ -1034,8 +1179,6 @@ struct v4l2_streamparm
        } parm;
 };
 
-
-
 /*
  *     I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
@@ -1045,8 +1188,10 @@ struct v4l2_streamparm
 #define VIDIOC_ENUM_FMT         _IOWR ('V',  2, struct v4l2_fmtdesc)
 #define VIDIOC_G_FMT           _IOWR ('V',  4, struct v4l2_format)
 #define VIDIOC_S_FMT           _IOWR ('V',  5, struct v4l2_format)
+#ifdef __KERNEL__
 #define VIDIOC_G_MPEGCOMP       _IOR  ('V',  6, struct v4l2_mpeg_compression)
 #define VIDIOC_S_MPEGCOMP      _IOW  ('V',  7, struct v4l2_mpeg_compression)
+#endif
 #define VIDIOC_REQBUFS         _IOWR ('V',  8, struct v4l2_requestbuffers)
 #define VIDIOC_QUERYBUF                _IOWR ('V',  9, struct v4l2_buffer)
 #define VIDIOC_G_FBUF          _IOR  ('V', 10, struct v4l2_framebuffer)
@@ -1096,7 +1241,11 @@ struct v4l2_streamparm
 #define VIDIOC_G_SLICED_VBI_CAP _IOR  ('V', 69, struct v4l2_sliced_vbi_cap)
 #endif
 #define VIDIOC_LOG_STATUS       _IO   ('V', 70)
+#define VIDIOC_G_EXT_CTRLS     _IOWR ('V', 71, struct v4l2_ext_controls)
+#define VIDIOC_S_EXT_CTRLS     _IOWR ('V', 72, struct v4l2_ext_controls)
+#define VIDIOC_TRY_EXT_CTRLS   _IOWR ('V', 73, struct v4l2_ext_controls)
 
+#ifdef __OLD_VIDIOC_
 /* for compatibility, will go away some day */
 #define VIDIOC_OVERLAY_OLD             _IOWR ('V', 14, int)
 #define VIDIOC_S_PARM_OLD              _IOW  ('V', 22, struct v4l2_streamparm)
@@ -1104,57 +1253,10 @@ struct v4l2_streamparm
 #define VIDIOC_G_AUDIO_OLD             _IOWR ('V', 33, struct v4l2_audio)
 #define VIDIOC_G_AUDOUT_OLD            _IOWR ('V', 49, struct v4l2_audioout)
 #define VIDIOC_CROPCAP_OLD             _IOR  ('V', 58, struct v4l2_cropcap)
-
-#define BASE_VIDIOC_PRIVATE    192             /* 192-255 are private */
-
-
-#ifdef __KERNEL__
-/*
- *
- *     V 4 L 2   D R I V E R   H E L P E R   A P I
- *
- *     Some commonly needed functions for drivers (v4l2-common.o module)
- */
-#include <linux/fs.h>
-
-/*  Video standard functions  */
-extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
-extern int v4l2_video_std_construct(struct v4l2_standard *vs,
-                                   int id, char *name);
-
-/* prority handling */
-struct v4l2_prio_state {
-       atomic_t prios[4];
-};
-int v4l2_prio_init(struct v4l2_prio_state *global);
-int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
-                    enum v4l2_priority new);
-int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local);
-int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local);
-enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global);
-int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
-
-/* names for fancy debug output */
-extern char *v4l2_field_names[];
-extern char *v4l2_type_names[];
-
-/*  Compatibility layer interface  --  v4l1-compat module */
-typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
-                          unsigned int cmd, void *arg);
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
-                              int cmd, void *arg, v4l2_kioctl driver_ioctl);
-#else
-#define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL
 #endif
 
-/* 32 Bits compatibility layer for 64 bits processors */
-extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
-                               unsigned long arg);
-
+#define BASE_VIDIOC_PRIVATE    192             /* 192-255 are private */
 
-#endif /* __KERNEL__ */
 #endif /* __LINUX_VIDEODEV2_H */
 
 /*
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h
new file mode 100644 (file)
index 0000000..51fb06b
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+    cx23415/6 header containing common defines.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef CX2341X_H
+#define CX2341X_H
+
+enum cx2341x_port {
+       CX2341X_PORT_MEMORY    = 0,
+       CX2341X_PORT_STREAMING = 1,
+       CX2341X_PORT_SERIAL    = 2
+};
+
+struct cx2341x_mpeg_params {
+       /* misc */
+       enum cx2341x_port port;
+       u16 width;
+       u16 height;
+       u16 is_50hz;
+
+       /* stream */
+       enum v4l2_mpeg_stream_type stream_type;
+
+       /* audio */
+       enum v4l2_mpeg_audio_sampling_freq audio_sampling_freq;
+       enum v4l2_mpeg_audio_encoding audio_encoding;
+       enum v4l2_mpeg_audio_l2_bitrate audio_l2_bitrate;
+       enum v4l2_mpeg_audio_mode audio_mode;
+       enum v4l2_mpeg_audio_mode_extension audio_mode_extension;
+       enum v4l2_mpeg_audio_emphasis audio_emphasis;
+       enum v4l2_mpeg_audio_crc audio_crc;
+       u8 audio_properties;
+
+       /* video */
+       enum v4l2_mpeg_video_encoding video_encoding;
+       enum v4l2_mpeg_video_aspect video_aspect;
+       u16 video_b_frames;
+       u16 video_gop_size;
+       u16 video_gop_closure;
+       u16 video_pulldown;
+       enum v4l2_mpeg_video_bitrate_mode video_bitrate_mode;
+       u32 video_bitrate;
+       u32 video_bitrate_peak;
+       u16 video_temporal_decimation;
+
+       /* encoding filters */
+       enum v4l2_mpeg_cx2341x_video_spatial_filter_mode video_spatial_filter_mode;
+       u16 video_spatial_filter;
+       enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type video_luma_spatial_filter_type;
+       enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type video_chroma_spatial_filter_type;
+       enum v4l2_mpeg_cx2341x_video_temporal_filter_mode video_temporal_filter_mode;
+       u16 video_temporal_filter;
+       enum v4l2_mpeg_cx2341x_video_median_filter_type video_median_filter_type;
+       u16 video_luma_median_filter_top;
+       u16 video_luma_median_filter_bottom;
+       u16 video_chroma_median_filter_top;
+       u16 video_chroma_median_filter_bottom;
+};
+
+#define CX2341X_MBOX_MAX_DATA 16
+
+extern const u32 cx2341x_mpeg_ctrls[];
+typedef int (*cx2341x_mbox_func)(void *priv, int cmd, int in, int out,
+               u32 data[CX2341X_MBOX_MAX_DATA]);
+int cx2341x_update(void *priv, cx2341x_mbox_func func,
+               const struct cx2341x_mpeg_params *old,
+               const struct cx2341x_mpeg_params *new);
+int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
+               struct v4l2_queryctrl *qctrl);
+const char **cx2341x_ctrl_get_menu(u32 id);
+int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
+               struct v4l2_ext_controls *ctrls, int cmd);
+void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p);
+void cx2341x_log_status(struct cx2341x_mpeg_params *p, int cardid);
+
+/* Firmware names */
+#define CX2341X_FIRM_ENC_FILENAME "v4l-cx2341x-enc.fw"
+/* Decoder firmware for the cx23415 only */
+#define CX2341X_FIRM_DEC_FILENAME "v4l-cx2341x-dec.fw"
+
+/* Firmware API commands */
+
+/* MPEG decoder API, specific to the cx23415 */
+#define CX2341X_DEC_PING_FW                    0x00
+#define CX2341X_DEC_START_PLAYBACK             0x01
+#define CX2341X_DEC_STOP_PLAYBACK              0x02
+#define CX2341X_DEC_SET_PLAYBACK_SPEED                 0x03
+#define CX2341X_DEC_STEP_VIDEO                         0x05
+#define CX2341X_DEC_SET_DMA_BLOCK_SIZE                 0x08
+#define CX2341X_DEC_GET_XFER_INFO              0x09
+#define CX2341X_DEC_GET_DMA_STATUS             0x0a
+#define CX2341X_DEC_SCHED_DMA_FROM_HOST                0x0b
+#define CX2341X_DEC_PAUSE_PLAYBACK             0x0d
+#define CX2341X_DEC_HALT_FW                    0x0e
+#define CX2341X_DEC_SET_STANDARD               0x10
+#define CX2341X_DEC_GET_VERSION                        0x11
+#define CX2341X_DEC_SET_STREAM_INPUT           0x14
+#define CX2341X_DEC_GET_TIMING_INFO            0x15
+#define CX2341X_DEC_SET_AUDIO_MODE             0x16
+#define CX2341X_DEC_SET_EVENT_NOTIFICATION     0x17
+#define CX2341X_DEC_SET_DISPLAY_BUFFERS                0x18
+#define CX2341X_DEC_EXTRACT_VBI                0x19
+#define CX2341X_DEC_SET_DECODER_SOURCE                 0x1a
+#define CX2341X_DEC_SET_AUDIO_OUTPUT           0x1b
+#define CX2341X_DEC_SET_AV_DELAY               0x1c
+#define CX2341X_DEC_SET_PREBUFFERING           0x1e
+
+/* MPEG encoder API */
+#define CX2341X_ENC_PING_FW                    0x80
+#define CX2341X_ENC_START_CAPTURE              0x81
+#define CX2341X_ENC_STOP_CAPTURE               0x82
+#define CX2341X_ENC_SET_AUDIO_ID               0x89
+#define CX2341X_ENC_SET_VIDEO_ID               0x8b
+#define CX2341X_ENC_SET_PCR_ID                         0x8d
+#define CX2341X_ENC_SET_FRAME_RATE             0x8f
+#define CX2341X_ENC_SET_FRAME_SIZE             0x91
+#define CX2341X_ENC_SET_BIT_RATE               0x95
+#define CX2341X_ENC_SET_GOP_PROPERTIES                 0x97
+#define CX2341X_ENC_SET_ASPECT_RATIO           0x99
+#define CX2341X_ENC_SET_DNR_FILTER_MODE        0x9b
+#define CX2341X_ENC_SET_DNR_FILTER_PROPS       0x9d
+#define CX2341X_ENC_SET_CORING_LEVELS          0x9f
+#define CX2341X_ENC_SET_SPATIAL_FILTER_TYPE    0xa1
+#define CX2341X_ENC_SET_3_2_PULLDOWN           0xb1
+#define CX2341X_ENC_SET_VBI_LINE               0xb7
+#define CX2341X_ENC_SET_STREAM_TYPE            0xb9
+#define CX2341X_ENC_SET_OUTPUT_PORT            0xbb
+#define CX2341X_ENC_SET_AUDIO_PROPERTIES       0xbd
+#define CX2341X_ENC_HALT_FW                    0xc3
+#define CX2341X_ENC_GET_VERSION                        0xc4
+#define CX2341X_ENC_SET_GOP_CLOSURE            0xc5
+#define CX2341X_ENC_GET_SEQ_END                0xc6
+#define CX2341X_ENC_SET_PGM_INDEX_INFO                 0xc7
+#define CX2341X_ENC_SET_VBI_CONFIG             0xc8
+#define CX2341X_ENC_SET_DMA_BLOCK_SIZE                 0xc9
+#define CX2341X_ENC_GET_PREV_DMA_INFO_MB_10    0xca
+#define CX2341X_ENC_GET_PREV_DMA_INFO_MB_9     0xcb
+#define CX2341X_ENC_SCHED_DMA_TO_HOST          0xcc
+#define CX2341X_ENC_INITIALIZE_INPUT           0xcd
+#define CX2341X_ENC_SET_FRAME_DROP_RATE        0xd0
+#define CX2341X_ENC_PAUSE_ENCODER              0xd2
+#define CX2341X_ENC_REFRESH_INPUT              0xd3
+#define CX2341X_ENC_SET_COPYRIGHT              0xd4
+#define CX2341X_ENC_SET_EVENT_NOTIFICATION     0xd5
+#define CX2341X_ENC_SET_NUM_VSYNC_LINES        0xd6
+#define CX2341X_ENC_SET_PLACEHOLDER            0xd7
+#define CX2341X_ENC_MUTE_VIDEO                         0xd9
+#define CX2341X_ENC_MUTE_AUDIO                         0xda
+#define CX2341X_ENC_UNKNOWN                    0xdb
+#define CX2341X_ENC_MISC                       0xdc
+
+/* OSD API, specific to the cx23415 */
+#define CX2341X_OSD_GET_FRAMEBUFFER            0x41
+#define CX2341X_OSD_GET_PIXEL_FORMAT           0x42
+#define CX2341X_OSD_SET_PIXEL_FORMAT           0x43
+#define CX2341X_OSD_GET_STATE                  0x44
+#define CX2341X_OSD_SET_STATE                  0x45
+#define CX2341X_OSD_GET_OSD_COORDS             0x46
+#define CX2341X_OSD_SET_OSD_COORDS             0x47
+#define CX2341X_OSD_GET_SCREEN_COORDS          0x48
+#define CX2341X_OSD_SET_SCREEN_COORDS          0x49
+#define CX2341X_OSD_GET_GLOBAL_ALPHA           0x4a
+#define CX2341X_OSD_SET_GLOBAL_ALPHA           0x4b
+#define CX2341X_OSD_SET_BLEND_COORDS           0x4c
+#define CX2341X_OSD_GET_FLICKER_STATE          0x4f
+#define CX2341X_OSD_SET_FLICKER_STATE          0x50
+#define CX2341X_OSD_BLT_COPY                   0x52
+#define CX2341X_OSD_BLT_FILL                   0x53
+#define CX2341X_OSD_BLT_TEXT                   0x54
+#define CX2341X_OSD_SET_FRAMEBUFFER_WINDOW     0x56
+#define CX2341X_OSD_SET_CHROMA_KEY             0x60
+#define CX2341X_OSD_GET_ALPHA_CONTENT_INDEX    0x61
+#define CX2341X_OSD_SET_ALPHA_CONTENT_INDEX    0x62
+
+#endif /* CX2341X_H */
index 302d5b3946e704f37a41d1d68c53b340cbd854f4..7bab09b0ed451ae2f1f1569ceeaeb3ce2b8ab52a 100644 (file)
@@ -73,7 +73,7 @@ extern IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE];
-extern IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE];
@@ -87,8 +87,9 @@ extern IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE];
-extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE];
 
 #endif
 
index 730f21ed91db18aa28b705147da6e377c517ac14..a455f7ce5ee8cbfdf423d4e5d0409b57954b7eb1 100644 (file)
@@ -20,5 +20,6 @@ struct IR_i2c {
        int                    (*get_key)(struct IR_i2c*, u32*, u32*);
 };
 
-int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
+int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
+int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
 #endif
index 8138983adcedd57f3db7f905f1c6e8074c6e9763..0f43451f8bb3599db431e12789cd498b71ecc168 100644 (file)
@@ -15,6 +15,7 @@
 #define __LINUX_OVCAMCHIP_H
 
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/i2c.h>
 
 /* --------------------------------- */
diff --git a/include/media/pwc-ioctl.h b/include/media/pwc-ioctl.h
new file mode 100644 (file)
index 0000000..adc1254
--- /dev/null
@@ -0,0 +1,325 @@
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* (C) 2001-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* This is pwc-ioctl.h belonging to PWC 10.0.10
+   It contains structures and defines to communicate from user space
+   directly to the driver.
+ */
+
+/*
+   Changes
+   2001/08/03  Alvarado   Added ioctl constants to access methods for
+                         changing white balance and red/blue gains
+   2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
+   2003/12/13  Nemosft Unv. Some modifications to make interfacing to
+              PWCX easier
+   2006/01/01  Luc Saillard Add raw format definition
+ */
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+   They contain functions not found in other webcams, and settings not
+   specified in the Video4Linux API.
+
+   The #define names are built up like follows:
+   VIDIOC              VIDeo IOCtl prefix
+        PWC            Philps WebCam
+           G           optional: Get
+           S           optional: Set
+            ...        the function
+ */
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+
+ /* Enumeration of image sizes */
+#define PSZ_SQCIF      0x00
+#define PSZ_QSIF       0x01
+#define PSZ_QCIF       0x02
+#define PSZ_SIF                0x03
+#define PSZ_CIF                0x04
+#define PSZ_VGA                0x05
+#define PSZ_MAX                6
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+   the upper 16 bits, since some flags are defined nowadays. The following
+   defines provide a mask and shift to filter out this value.
+   This value can also be passing using the private flag when using v4l2 and
+   VIDIOC_S_FMT ioctl.
+
+   In 'Snapshot' mode the camera freezes its automatic exposure and colour
+   balance controls.
+ */
+#define PWC_FPS_SHIFT          16
+#define PWC_FPS_MASK           0x00FF0000
+#define PWC_FPS_FRMASK         0x003F0000
+#define PWC_FPS_SNAPSHOT       0x00400000
+#define PWC_QLT_MASK           0x03000000
+#define PWC_QLT_SHIFT          24
+
+
+/* structure for transferring x & y coordinates */
+struct pwc_coord
+{
+       int x, y;               /* guess what */
+       int size;               /* size, or offset */
+};
+
+
+/* Used with VIDIOCPWCPROBE */
+struct pwc_probe
+{
+       char name[32];
+       int type;
+};
+
+struct pwc_serial
+{
+       char serial[30];        /* String with serial number. Contains terminating 0 */
+};
+
+/* pwc_whitebalance.mode values */
+#define PWC_WB_INDOOR          0
+#define PWC_WB_OUTDOOR         1
+#define PWC_WB_FL              2
+#define PWC_WB_MANUAL          3
+#define PWC_WB_AUTO            4
+
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
+   Set mode to one of the PWC_WB_* values above.
+   *red and *blue are the respective gains of these colour components inside
+   the camera; range 0..65535
+   When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
+   otherwise undefined.
+   'read_red' and 'read_blue' are read-only.
+*/
+struct pwc_whitebalance
+{
+       int mode;
+       int manual_red, manual_blue;    /* R/W */
+       int read_red, read_blue;        /* R/O */
+};
+
+/*
+   'control_speed' and 'control_delay' are used in automatic whitebalance mode,
+   and tell the camera how fast it should react to changes in lighting, and
+   with how much delay. Valid values are 0..65535.
+*/
+struct pwc_wb_speed
+{
+       int control_speed;
+       int control_delay;
+
+};
+
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+       int led_on;                     /* Led on-time; range = 0..25000 */
+       int led_off;                    /* Led off-time; range = 0..25000  */
+};
+
+/* Image size (used with GREALSIZE) */
+struct pwc_imagesize
+{
+       int width;
+       int height;
+};
+
+/* Defines and structures for Motorized Pan & Tilt */
+#define PWC_MPT_PAN            0x01
+#define PWC_MPT_TILT           0x02
+#define PWC_MPT_TIMEOUT                0x04 /* for status */
+
+/* Set angles; when absolute != 0, the angle is absolute and the
+   driver calculates the relative offset for you. This can only
+   be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
+   absolute angles.
+ */
+struct pwc_mpt_angles
+{
+       int absolute;           /* write-only */
+       int pan;                /* degrees * 100 */
+       int tilt;               /* degress * 100 */
+};
+
+/* Range of angles of the camera, both horizontally and vertically.
+ */
+struct pwc_mpt_range
+{
+       int pan_min, pan_max;           /* degrees * 100 */
+       int tilt_min, tilt_max;
+};
+
+struct pwc_mpt_status
+{
+       int status;
+       int time_pan;
+       int time_tilt;
+};
+
+
+/* This is used for out-of-kernel decompression. With it, you can get
+   all the necessary information to initialize and use the decompressor
+   routines in standalone applications.
+ */
+struct pwc_video_command
+{
+       int type;               /* camera type (645, 675, 730, etc.) */
+       int release;            /* release number */
+
+       int size;               /* one of PSZ_* */
+       int alternate;
+       int command_len;        /* length of USB video command */
+       unsigned char command_buf[13];  /* Actual USB video command */
+       int bandlength;         /* >0 = compressed */
+       int frame_size;         /* Size of one (un)compressed frame */
+};
+
+/* Flags for PWCX subroutines. Not all modules honour all flags. */
+#define PWCX_FLAG_PLANAR       0x0001
+#define PWCX_FLAG_BAYER                0x0008
+
+
+/* IOCTL definitions */
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER         _IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER         _IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY       _IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+    means use uncompressed modes when available; 1 is low compression, 2 is
+    medium and 3 is high compression preferred. Of course, the higher the
+    compression, the lower the bandwidth used but more chance of artefacts
+    in the image. The driver automatically chooses a higher compression when
+    the preferred mode is not available.
+  */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL                _IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL                _IOR('v', 195, int)
+
+
+/* Retrieve serial number of camera */
+#define VIDIOCPWCGSERIAL       _IOR('v', 198, struct pwc_serial)
+
+ /* This is a probe function; since so many devices are supported, it
+    becomes difficult to include all the names in programs that want to
+    check for the enhanced Philips stuff. So in stead, try this PROBE;
+    it returns a structure with the original name, and the corresponding
+    Philips type.
+    To use, fill the structure with zeroes, call PROBE and if that succeeds,
+    compare the name with that returned from VIDIOCGCAP; they should be the
+    same. If so, you can be assured it is a Philips (OEM) cam and the type
+    is valid.
+ */
+#define VIDIOCPWCPROBE         _IOR('v', 199, struct pwc_probe)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC          _IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC          _IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER      _IOW('v', 201, int)
+
+ /* Color compensation (Auto White Balance) */
+#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
+#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
+
+ /* Auto WB speed */
+#define VIDIOCPWCSAWBSPEED     _IOW('v', 203, struct pwc_wb_speed)
+#define VIDIOCPWCGAWBSPEED     _IOR('v', 203, struct pwc_wb_speed)
+
+ /* LEDs on/off/blink; int range 0..65535 */
+#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
+#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
+
+  /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
+#define VIDIOCPWCSCONTOUR      _IOW('v', 206, int)
+#define VIDIOCPWCGCONTOUR      _IOR('v', 206, int)
+
+  /* Backlight compensation; 0 = off, otherwise on */
+#define VIDIOCPWCSBACKLIGHT    _IOW('v', 207, int)
+#define VIDIOCPWCGBACKLIGHT    _IOR('v', 207, int)
+
+  /* Flickerless mode; = 0 off, otherwise on */
+#define VIDIOCPWCSFLICKER      _IOW('v', 208, int)
+#define VIDIOCPWCGFLICKER      _IOR('v', 208, int)
+
+  /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
+#define VIDIOCPWCSDYNNOISE     _IOW('v', 209, int)
+#define VIDIOCPWCGDYNNOISE     _IOR('v', 209, int)
+
+ /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
+#define VIDIOCPWCGREALSIZE     _IOR('v', 210, struct pwc_imagesize)
+
+ /* Motorized pan & tilt functions */
+#define VIDIOCPWCMPTRESET      _IOW('v', 211, int)
+#define VIDIOCPWCMPTGRANGE     _IOR('v', 211, struct pwc_mpt_range)
+#define VIDIOCPWCMPTSANGLE     _IOW('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTGANGLE     _IOR('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTSTATUS     _IOR('v', 213, struct pwc_mpt_status)
+
+ /* Get the USB set-video command; needed for initializing libpwcx */
+#define VIDIOCPWCGVIDCMD       _IOR('v', 215, struct pwc_video_command)
+struct pwc_table_init_buffer {
+   int len;
+   char *buffer;
+
+};
+#define VIDIOCPWCGVIDTABLE     _IOR('v', 216, struct pwc_table_init_buffer)
+
+/*
+ * This is private command used when communicating with v4l2.
+ * In the future all private ioctl will be remove/replace to
+ * use interface offer by v4l2.
+ */
+
+#define V4L2_CID_PRIVATE_SAVE_USER       (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PRIVATE_RESTORE_USER    (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PRIVATE_COLOUR_MODE     (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_AUTOCONTOUR     (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_PRIVATE_CONTOUR         (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_PRIVATE_BACKLIGHT       (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_PRIVATE_FLICKERLESS     (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)
+
+struct pwc_raw_frame {
+   __le16 type;                /* type of the webcam */
+   __le16 vbandlength; /* Size of 4lines compressed (used by the decompressor) */
+   __u8   cmd[4];      /* the four byte of the command (in case of nala,
+                          only the first 3 bytes is filled) */
+   __u8   rawframe[0]; /* frame_size = H/4*vbandlength */
+} __attribute__ ((packed));
+
+
+#endif
index 6b4836f3f057280782aa0b78947eceb86322ad91..9f0e2285a099f0c63765477ea417670ac827abad 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    saa7115.h - definition for saa7113/4/5 inputs
+    saa7115.h - definition for saa7113/4/5 inputs and frequency flags
 
     Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
 
 #define SAA7115_SVIDEO2    8
 #define SAA7115_SVIDEO3    9
 
+/* SAA7115 v4l2_crystal_freq frequency values */
+#define SAA7115_FREQ_32_11_MHZ  32110000   /* 32.11 MHz crystal, SAA7114/5 only */
+#define SAA7115_FREQ_24_576_MHZ 24576000   /* 24.576 MHz crystal */
+
+/* SAA7115 v4l2_crystal_freq audio clock control flags */
+#define SAA7115_FREQ_FL_UCGC   (1 << 0)           /* SA 3A[7], UCGC, SAA7115 only */
+#define SAA7115_FREQ_FL_CGCDIV (1 << 1)           /* SA 3A[6], CGCDIV, SAA7115 only */
+#define SAA7115_FREQ_FL_APLL   (1 << 2)           /* SA 3A[3], APLL, SAA7114/5 only */
+
 #endif
 
index 4507cb61ae9379e9e3c4715859854630c7b8c45d..83fe2e3d1e25a43d1c3fefcab1255baf1194ea30 100644 (file)
@@ -2,7 +2,7 @@
 #define __SAA7146_VV__
 
 #include <linux/videodev.h>
-
+#include <media/v4l2-common.h>
 #include <media/saa7146.h>
 #include <media/video-buf.h>
 
index 017fed7d5e4d24fee81d3b7a3994ab24d401939e..2f7b00b08e8817224c5827ab09e7f13bd376d883 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/videodev2.h>
 #include <media/tuner-types.h>
 
+extern int tuner_debug;
+
 #define ADDR_UNSET (255)
 
 #define TUNER_TEMIC_PAL                        0        /* 4002 FH5 (3X 7756, 9483) */
 #define TUNER_TEA5767                  62      /* Only FM Radio Tuner */
 #define TUNER_PHILIPS_FMD1216ME_MK3    63
 
-#define TUNER_LG_TDVS_H062F            64      /* DViCO FusionHDTV 5 */
+#define TUNER_LG_TDVS_H06XF            64      /* TDVS H061F, H062F, H064F */
 #define TUNER_YMEC_TVF66T5_B_DFF       65      /* Acorp Y878F */
 #define TUNER_LG_TALN                  66
 #define TUNER_PHILIPS_TD1316           67
 #define TUNER_XCEIVE_XC3028            71
 
 #define TUNER_THOMSON_FE6600           72      /* DViCO FusionHDTV DVB-T Hybrid */
+#define TUNER_SAMSUNG_TCPG_6121P30A     73     /* Hauppauge PVR-500 PAL */
+#define TUNER_TDA9887                   74      /* This tuner should be used only internally */
 
 /* tv card specific */
 #define TDA9887_PRESENT                (1<<0)
@@ -190,6 +194,10 @@ struct tuner {
 
        int          using_v4l2;
 
+       /* used by tda9887 */
+       unsigned int       tda9887_config;
+       unsigned char      tda9887_data[4];
+
        /* used by MT2032 */
        unsigned int xogc;
        unsigned int radio_if2;
@@ -206,6 +214,8 @@ struct tuner {
        void (*set_radio_freq)(struct i2c_client *c, unsigned int freq);
        int  (*has_signal)(struct i2c_client *c);
        int  (*is_stereo)(struct i2c_client *c);
+       int  (*get_afc)(struct i2c_client *c);
+       void (*tuner_status)(struct i2c_client *c);
        void (*standby)(struct i2c_client *c);
 };
 
@@ -218,6 +228,7 @@ extern int tda8290_probe(struct i2c_client *c);
 extern int tea5767_tuner_init(struct i2c_client *c);
 extern int default_tuner_init(struct i2c_client *c);
 extern int tea5767_autodetection(struct i2c_client *c);
+extern int tda9887_tuner_init(struct i2c_client *c);
 
 #define tuner_warn(fmt, arg...) do {\
        printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \
diff --git a/include/media/tvp5150.h b/include/media/tvp5150.h
new file mode 100644 (file)
index 0000000..72bd2a2
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+    tvp5150.h - definition for tvp5150 inputs
+
+    Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _TVP5150_H_
+#define _TVP5150_H_
+
+/* TVP5150 HW inputs */
+#define TVP5150_COMPOSITE0 0
+#define TVP5150_COMPOSITE1 1
+#define TVP5150_SVIDEO     2
+
+/* TVP5150 HW outputs */
+#define TVP5150_NORMAL       0
+#define TVP5150_BLACK_SCREEN 1
+
+#endif
+
index 642520acdfa7b41da7a77cd78206b7a1b5d7ce77..5564db13c0d5f1d1897dadb20309c1d06219480a 100644 (file)
 #ifndef V4L2_COMMON_H_
 #define V4L2_COMMON_H_
 
+#include <media/v4l2-dev.h>
+
 /* v4l debugging and diagnostics */
 
+/* Debug bitmask flags to be used on V4L2 */
+#define V4L2_DEBUG_IOCTL     0x01
+#define V4L2_DEBUG_IOCTL_ARG 0x02
+
 /* Common printk constucts for v4l-i2c drivers. These macros create a unique
    prefix consisting of the driver name, the adapter number and the i2c
    address. */
@@ -78,6 +84,19 @@ extern void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg);
 
 /* ------------------------------------------------------------------------- */
 
+/* Control helper functions */
+
+int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
+               const char **menu_items);
+const char **v4l2_ctrl_get_menu(u32 id);
+int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def);
+int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl);
+int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu,
+               struct v4l2_queryctrl *qctrl, const char **menu_items);
+u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
+
+/* ------------------------------------------------------------------------- */
+
 /* Internal ioctls */
 
 /* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */
@@ -112,6 +131,8 @@ enum v4l2_chip_ident {
        V4L2_IDENT_SAA7129 = 159,
 
        /* module cx25840: reserved range 200-249 */
+       V4L2_IDENT_CX25836 = 236,
+       V4L2_IDENT_CX25837 = 237,
        V4L2_IDENT_CX25840 = 240,
        V4L2_IDENT_CX25841 = 241,
        V4L2_IDENT_CX25842 = 242,
@@ -211,4 +232,15 @@ struct v4l2_routing {
 #define        VIDIOC_INT_S_VIDEO_ROUTING      _IOW ('d', 111, struct v4l2_routing)
 #define        VIDIOC_INT_G_VIDEO_ROUTING      _IOR ('d', 112, struct v4l2_routing)
 
+struct v4l2_crystal_freq {
+       u32 freq;       /* frequency in Hz of the crystal */
+       u32 flags;      /* device specific flags */
+};
+
+/* Sets the frequency of the crystal used to generate the clocks.
+   An extra flags field allows device specific configuration regarding
+   clock frequency dividers, etc. If not used, then set flags to 0.
+   If the frequency is not supported, then -EINVAL is returned. */
+#define VIDIOC_INT_S_CRYSTAL_FREQ      _IOW ('d', 113, struct v4l2_crystal_freq)
+
 #endif /* V4L2_COMMON_H_ */
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
new file mode 100644 (file)
index 0000000..a1b4731
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ *
+ *     V 4 L 2   D R I V E R   H E L P E R   A P I
+ *
+ * Moved from videodev2.h
+ *
+ *     Some commonly needed functions for drivers (v4l2-common.o module)
+ */
+#ifndef _V4L2_DEV_H
+#define _V4L2_DEV_H
+
+#define OBSOLETE_OWNER 1 /* to be removed soon */
+
+#include <linux/poll.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/compiler.h> /* need __user */
+#ifdef CONFIG_VIDEO_V4L1
+#include <linux/videodev.h>
+#else
+#include <linux/videodev2.h>
+#endif
+
+#include <linux/fs.h>
+
+#define VIDEO_MAJOR    81
+/* Minor device allocation */
+#define MINOR_VFL_TYPE_GRABBER_MIN   0
+#define MINOR_VFL_TYPE_GRABBER_MAX  63
+#define MINOR_VFL_TYPE_RADIO_MIN    64
+#define MINOR_VFL_TYPE_RADIO_MAX   127
+#define MINOR_VFL_TYPE_VTX_MIN     192
+#define MINOR_VFL_TYPE_VTX_MAX     223
+#define MINOR_VFL_TYPE_VBI_MIN     224
+#define MINOR_VFL_TYPE_VBI_MAX     255
+
+#define VFL_TYPE_GRABBER       0
+#define VFL_TYPE_VBI           1
+#define VFL_TYPE_RADIO         2
+#define VFL_TYPE_VTX           3
+
+/*  Video standard functions  */
+extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
+extern int v4l2_video_std_construct(struct v4l2_standard *vs,
+                                   int id, char *name);
+
+/* prority handling */
+struct v4l2_prio_state {
+       atomic_t prios[4];
+};
+int v4l2_prio_init(struct v4l2_prio_state *global);
+int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
+                    enum v4l2_priority new);
+int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local);
+int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local);
+enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global);
+int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
+
+/* names for fancy debug output */
+extern char *v4l2_field_names[];
+extern char *v4l2_type_names[];
+
+/*  Compatibility layer interface  --  v4l1-compat module */
+typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
+                          unsigned int cmd, void *arg);
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
+                              int cmd, void *arg, v4l2_kioctl driver_ioctl);
+#else
+#define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL
+#endif
+
+/* 32 Bits compatibility layer for 64 bits processors */
+extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
+                               unsigned long arg);
+
+/*
+ * Newer version of video_device, handled by videodev2.c
+ *     This version moves redundant code from video device code to
+ *     the common handler
+ */
+struct v4l2_tvnorm {
+       char          *name;
+       v4l2_std_id   id;
+
+       void          *priv_data;
+};
+
+struct video_device
+{
+       /* device ops */
+       const struct file_operations *fops;
+
+       /* device info */
+       struct device *dev;
+       char name[32];
+       int type;       /* v4l1 */
+       int type2;      /* v4l2 */
+       int hardware;
+       int minor;
+
+       int debug;      /* Activates debug level*/
+
+       /* Video standard vars */
+       int tvnormsize; /* Size of tvnorm array */
+       v4l2_std_id current_norm; /* Current tvnorm */
+       struct v4l2_tvnorm *tvnorms;
+
+       /* callbacks */
+       void (*release)(struct video_device *vfd);
+
+       /* ioctl callbacks */
+
+       /* VIDIOC_QUERYCAP handler */
+       int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap);
+
+       /* Priority handling */
+       int (*vidioc_g_priority)   (struct file *file, void *fh,
+                                   enum v4l2_priority *p);
+       int (*vidioc_s_priority)   (struct file *file, void *fh,
+                                   enum v4l2_priority p);
+
+       /* VIDIOC_ENUM_FMT handlers */
+       int (*vidioc_enum_fmt_cap)         (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_overlay)     (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_vbi)         (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_vbi_capture) (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_video_output)(struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_vbi_output)  (struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+       int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f);
+
+       /* VIDIOC_G_FMT handlers */
+       int (*vidioc_g_fmt_cap)        (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_overlay)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vbi)        (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vbi_output) (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_vbi_capture)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_video_output)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+
+       /* VIDIOC_S_FMT handlers */
+       int (*vidioc_s_fmt_cap)        (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+
+       int (*vidioc_s_fmt_overlay)    (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vbi)        (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vbi_output) (struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_vbi_capture)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_video_output)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+       int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
+                                       struct v4l2_format *f);
+
+       /* VIDIOC_TRY_FMT handlers */
+       int (*vidioc_try_fmt_cap)        (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_overlay)    (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vbi)        (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vbi_output) (struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_vbi_capture)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_video_output)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+       int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
+                                         struct v4l2_format *f);
+
+       /* Buffer handlers */
+       int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
+       int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
+       int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
+       int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
+
+
+       int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
+#ifdef HAVE_V4L1
+                       /* buffer type is struct vidio_mbuf * */
+       int (*vidiocgmbuf)  (struct file *file, void *fh, struct video_mbuf *p);
+#endif
+       int (*vidioc_g_fbuf)   (struct file *file, void *fh,
+                               struct v4l2_framebuffer *a);
+       int (*vidioc_s_fbuf)   (struct file *file, void *fh,
+                               struct v4l2_framebuffer *a);
+
+               /* Stream on/off */
+       int (*vidioc_streamon) (struct file *file, void *fh, enum v4l2_buf_type i);
+       int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);
+
+               /* Standard handling
+                       G_STD and ENUMSTD are handled by videodev.c
+                */
+       int (*vidioc_s_std)    (struct file *file, void *fh, v4l2_std_id a);
+       int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
+
+               /* Input handling */
+       int (*vidioc_enum_input)(struct file *file, void *fh,
+                                struct v4l2_input *inp);
+       int (*vidioc_g_input)   (struct file *file, void *fh, unsigned int *i);
+       int (*vidioc_s_input)   (struct file *file, void *fh, unsigned int i);
+
+               /* Output handling */
+       int (*vidioc_enumoutput) (struct file *file, void *fh,
+                                 struct v4l2_output *a);
+       int (*vidioc_g_output)   (struct file *file, void *fh, unsigned int *i);
+       int (*vidioc_s_output)   (struct file *file, void *fh, unsigned int i);
+
+               /* Control handling */
+       int (*vidioc_queryctrl)        (struct file *file, void *fh,
+                                       struct v4l2_queryctrl *a);
+       int (*vidioc_g_ctrl)           (struct file *file, void *fh,
+                                       struct v4l2_control *a);
+       int (*vidioc_s_ctrl)           (struct file *file, void *fh,
+                                       struct v4l2_control *a);
+       int (*vidioc_g_ext_ctrls)      (struct file *file, void *fh,
+                                       struct v4l2_ext_controls *a);
+       int (*vidioc_s_ext_ctrls)      (struct file *file, void *fh,
+                                       struct v4l2_ext_controls *a);
+       int (*vidioc_try_ext_ctrls)    (struct file *file, void *fh,
+                                       struct v4l2_ext_controls *a);
+       int (*vidioc_querymenu)        (struct file *file, void *fh,
+                                       struct v4l2_querymenu *a);
+
+       /* Audio ioctls */
+       int (*vidioc_enumaudio)        (struct file *file, void *fh,
+                                       struct v4l2_audio *a);
+       int (*vidioc_g_audio)          (struct file *file, void *fh,
+                                       struct v4l2_audio *a);
+       int (*vidioc_s_audio)          (struct file *file, void *fh,
+                                       struct v4l2_audio *a);
+
+       /* Audio out ioctls */
+       int (*vidioc_enumaudout)       (struct file *file, void *fh,
+                                       struct v4l2_audioout *a);
+       int (*vidioc_g_audout)         (struct file *file, void *fh,
+                                       struct v4l2_audioout *a);
+       int (*vidioc_s_audout)         (struct file *file, void *fh,
+                                       struct v4l2_audioout *a);
+       int (*vidioc_g_modulator)      (struct file *file, void *fh,
+                                       struct v4l2_modulator *a);
+       int (*vidioc_s_modulator)      (struct file *file, void *fh,
+                                       struct v4l2_modulator *a);
+       /* Crop ioctls */
+       int (*vidioc_cropcap)          (struct file *file, void *fh,
+                                       struct v4l2_cropcap *a);
+       int (*vidioc_g_crop)           (struct file *file, void *fh,
+                                       struct v4l2_crop *a);
+       int (*vidioc_s_crop)           (struct file *file, void *fh,
+                                       struct v4l2_crop *a);
+       /* Compression ioctls */
+       int (*vidioc_g_mpegcomp)       (struct file *file, void *fh,
+                                       struct v4l2_mpeg_compression *a);
+       int (*vidioc_s_mpegcomp)       (struct file *file, void *fh,
+                                       struct v4l2_mpeg_compression *a);
+       int (*vidioc_g_jpegcomp)       (struct file *file, void *fh,
+                                       struct v4l2_jpegcompression *a);
+       int (*vidioc_s_jpegcomp)       (struct file *file, void *fh,
+                                       struct v4l2_jpegcompression *a);
+
+       /* Stream type-dependent parameter ioctls */
+       int (*vidioc_g_parm)           (struct file *file, void *fh,
+                                       struct v4l2_streamparm *a);
+       int (*vidioc_s_parm)           (struct file *file, void *fh,
+                                       struct v4l2_streamparm *a);
+
+       /* Tuner ioctls */
+       int (*vidioc_g_tuner)          (struct file *file, void *fh,
+                                       struct v4l2_tuner *a);
+       int (*vidioc_s_tuner)          (struct file *file, void *fh,
+                                       struct v4l2_tuner *a);
+       int (*vidioc_g_frequency)      (struct file *file, void *fh,
+                                       struct v4l2_frequency *a);
+       int (*vidioc_s_frequency)      (struct file *file, void *fh,
+                                       struct v4l2_frequency *a);
+
+       /* Sliced VBI cap */
+       int (*vidioc_g_sliced_vbi_cap) (struct file *file, void *fh,
+                                       struct v4l2_sliced_vbi_cap *a);
+
+       /* Log status ioctl */
+       int (*vidioc_log_status)       (struct file *file, void *fh);
+
+
+#ifdef OBSOLETE_OWNER /* to be removed soon */
+/* obsolete -- fops->owner is used instead */
+struct module *owner;
+/* dev->driver_data will be used instead some day.
+       * Use the video_{get|set}_drvdata() helper functions,
+       * so the switch over will be transparent for you.
+       * Or use {pci|usb}_{get|set}_drvdata() directly. */
+void *priv;
+#endif
+
+       /* for videodev.c intenal usage -- please don't touch */
+       int users;                     /* video_exclusive_{open|close} ... */
+       struct mutex lock;             /* ... helper function uses these   */
+       char devfs_name[64];           /* devfs */
+       struct class_device class_dev; /* sysfs */
+};
+
+/* Version 2 functions */
+extern int video_register_device(struct video_device *vfd, int type, int nr);
+void video_unregister_device(struct video_device *);
+extern int video_ioctl2(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg);
+
+/* helper functions to alloc / release struct video_device, the
+   later can be used for video_device->release() */
+struct video_device *video_device_alloc(void);
+void video_device_release(struct video_device *vfd);
+
+/* Include support for obsoleted stuff */
+extern int video_usercopy(struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg,
+                         int (*func)(struct inode *inode, struct file *file,
+                                     unsigned int cmd, void *arg));
+
+
+#ifdef HAVE_V4L1
+#include <linux/mm.h>
+
+extern struct video_device* video_devdata(struct file*);
+
+#define to_video_device(cd) container_of(cd, struct video_device, class_dev)
+static inline void
+video_device_create_file(struct video_device *vfd,
+                        struct class_device_attribute *attr)
+{
+       class_device_create_file(&vfd->class_dev, attr);
+}
+static inline void
+video_device_remove_file(struct video_device *vfd,
+                        struct class_device_attribute *attr)
+{
+       class_device_remove_file(&vfd->class_dev, attr);
+}
+
+#ifdef OBSOLETE_OWNER /* to be removed soon */
+/* helper functions to access driver private data. */
+static inline void *video_get_drvdata(struct video_device *dev)
+{
+       return dev->priv;
+}
+
+static inline void video_set_drvdata(struct video_device *dev, void *data)
+{
+       dev->priv = data;
+}
+#endif
+
+extern int video_exclusive_open(struct inode *inode, struct file *file);
+extern int video_exclusive_release(struct inode *inode, struct file *file);
+#endif /* HAVE_V4L1 */
+
+#endif /* _V4L2_DEV_H */
index b78d90fe629fb0b816f336015e07126116ce6af8..8233cafdeef6de74970ed18f752294e42005c525 100644 (file)
@@ -26,7 +26,8 @@ struct videobuf_dvb {
 
 int videobuf_dvb_register(struct videobuf_dvb *dvb,
                          struct module *module,
-                         void *adapter_priv);
+                         void *adapter_priv,
+                         struct device *device);
 void videobuf_dvb_unregister(struct videobuf_dvb *dvb);
 
 /*
index fff3fd0fbf94056248c1921a0fc057512b7b7c26..1115a256969f0468e6ec079567aa6d32e6c338d5 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <linux/videodev2.h>
+#include <linux/poll.h>
 
 #define UNSET (-1U)
 
index a4f5545201975da167e6b3dddb0eba96766d1c78..b5067d3c2387c469d7b86672b51d018948d1d7f8 100644 (file)
  *   along with this program; if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
- */      
+ */
 
 #include <linux/videodev.h>
+#include <media/v4l2-dev.h>
 
 struct snd_tea575x;