Merge git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 21 Jul 2008 04:14:42 +0000 (21:14 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 21 Jul 2008 04:14:42 +0000 (21:14 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (277 commits)
  V4L/DVB (8415): gspca: Infinite loop in i2c_w() of etoms.
  V4L/DVB (8414): videodev/cx18: fix get_index bug and error-handling lock-ups
  V4L/DVB (8411): videobuf-dma-contig.c: fix 64-bit build for pre-2.6.24 kernels
  V4L/DVB (8410): sh_mobile_ceu_camera: fix 64-bit compiler warnings
  V4L/DVB (8397): video: convert select VIDEO_ZORAN_ZR36060 into depends on
  V4L/DVB (8396): video: Fix Kbuild dependency for VIDEO_IR_I2C
  V4L/DVB (8395): saa7134: Fix Kbuild dependency of ir-kbd-i2c
  V4L/DVB (8394): ir-common: CodingStyle fix: move EXPORT_SYMBOL_GPL to their proper places
  V4L/DVB (8393): media/video: Fix depencencies for VIDEOBUF
  V4L/DVB (8392): media/Kconfig: Convert V4L1_COMPAT select into "depends on"
  V4L/DVB (8390): videodev: add comment and remove magic number.
  V4L/DVB (8389): videodev: simplify get_index()
  V4L/DVB (8387): Some cosmetic changes
  V4L/DVB (8381): ov7670: fix compile warnings
  V4L/DVB (8380): saa7115: use saa7115_auto instead of saa711x as the autodetect driver name.
  V4L/DVB (8379): saa7127: Make device detection optional
  V4L/DVB (8378): cx18: move cx18_av_vbi_setup to av-core.c and rename to cx18_av_std_setup
  V4L/DVB (8377): ivtv/cx18: ensure the default control values are correct
  V4L/DVB (8376): cx25840: move cx25840_vbi_setup to core.c and rename to cx25840_std_setup
  V4L/DVB (8374): gspca: No conflict of 0c45:6011 with the sn9c102 driver.
  ...

290 files changed:
Documentation/video4linux/CARDLIST.cx23885
Documentation/video4linux/CARDLIST.em28xx
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/cx18.txt
Documentation/video4linux/gspca.txt [new file with mode: 0644]
drivers/media/Kconfig
drivers/media/common/ir-functions.c
drivers/media/common/saa7146_core.c
drivers/media/common/saa7146_hlp.c
drivers/media/common/saa7146_i2c.c
drivers/media/common/saa7146_video.c
drivers/media/common/tuners/Kconfig
drivers/media/common/tuners/tda18271-maps.c
drivers/media/common/tuners/tuner-xc2028.c
drivers/media/common/tuners/xc5000.c
drivers/media/dvb/Kconfig
drivers/media/dvb/Makefile
drivers/media/dvb/bt8xx/bt878.h
drivers/media/dvb/dvb-core/demux.h
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_net.c
drivers/media/dvb/dvb-core/dvb_ringbuffer.c
drivers/media/dvb/dvb-core/dvb_ringbuffer.h
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/dvb-usb/anysee.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/anysee.h [new file with mode: 0644]
drivers/media/dvb/dvb-usb/au6610.c
drivers/media/dvb/dvb-usb/au6610.h
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/cxusb.h
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/gl861.c
drivers/media/dvb/dvb-usb/gl861.h
drivers/media/dvb/frontends/au8522.c
drivers/media/dvb/frontends/dvb-pll.c
drivers/media/dvb/frontends/dvb-pll.h
drivers/media/dvb/frontends/lgdt330x.c
drivers/media/dvb/frontends/s5h1409.c
drivers/media/dvb/frontends/s5h1411.c
drivers/media/dvb/frontends/tda10023.c
drivers/media/dvb/frontends/tda1002x.h
drivers/media/dvb/pluto2/pluto2.c
drivers/media/dvb/siano/Kconfig [new file with mode: 0644]
drivers/media/dvb/siano/Makefile [new file with mode: 0644]
drivers/media/dvb/siano/sms-cards.c [new file with mode: 0644]
drivers/media/dvb/siano/sms-cards.h [new file with mode: 0644]
drivers/media/dvb/siano/smscoreapi.c [new file with mode: 0644]
drivers/media/dvb/siano/smscoreapi.h [new file with mode: 0644]
drivers/media/dvb/siano/smsdvb.c [new file with mode: 0644]
drivers/media/dvb/siano/smsusb.c [new file with mode: 0644]
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/Makefile
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110.h
drivers/media/dvb/ttpci/av7110_av.c
drivers/media/dvb/ttpci/av7110_ca.c
drivers/media/dvb/ttpci/av7110_hw.h
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/ttusb-budget/dvb-ttusb-budget.c
drivers/media/radio/radio-si470x.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/bt819.c
drivers/media/video/bt8xx/bt832.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-i2c.c
drivers/media/video/bt8xx/bttv-vbi.c
drivers/media/video/bt8xx/bttv.h
drivers/media/video/bt8xx/bttvp.h
drivers/media/video/cafe_ccic.c
drivers/media/video/compat_ioctl32.c
drivers/media/video/cs5345.c
drivers/media/video/cs53l32a.c
drivers/media/video/cx18/cx18-audio.c
drivers/media/video/cx18/cx18-av-audio.c
drivers/media/video/cx18/cx18-av-core.c
drivers/media/video/cx18/cx18-av-core.h
drivers/media/video/cx18/cx18-av-firmware.c
drivers/media/video/cx18/cx18-av-vbi.c
drivers/media/video/cx18/cx18-cards.c
drivers/media/video/cx18/cx18-cards.h
drivers/media/video/cx18/cx18-controls.c
drivers/media/video/cx18/cx18-controls.h
drivers/media/video/cx18/cx18-driver.c
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-firmware.c
drivers/media/video/cx18/cx18-gpio.c
drivers/media/video/cx18/cx18-gpio.h
drivers/media/video/cx18/cx18-i2c.c
drivers/media/video/cx18/cx18-ioctl.c
drivers/media/video/cx18/cx18-ioctl.h
drivers/media/video/cx18/cx18-mailbox.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx18/cx23418.h
drivers/media/video/cx2341x.c
drivers/media/video/cx23885/Kconfig
drivers/media/video/cx23885/cx23885-417.c
drivers/media/video/cx23885/cx23885-cards.c
drivers/media/video/cx23885/cx23885-core.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23885.h
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/cx88-alsa.c
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88-vp3054-i2c.c
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-dvb.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/gspca/Kconfig [new file with mode: 0644]
drivers/media/video/gspca/Makefile [new file with mode: 0644]
drivers/media/video/gspca/conex.c [new file with mode: 0644]
drivers/media/video/gspca/etoms.c [new file with mode: 0644]
drivers/media/video/gspca/gspca.c [new file with mode: 0644]
drivers/media/video/gspca/gspca.h [new file with mode: 0644]
drivers/media/video/gspca/jpeg.h [new file with mode: 0644]
drivers/media/video/gspca/mars.c [new file with mode: 0644]
drivers/media/video/gspca/ov519.c [new file with mode: 0644]
drivers/media/video/gspca/pac207.c [new file with mode: 0644]
drivers/media/video/gspca/pac7311.c [new file with mode: 0644]
drivers/media/video/gspca/sonixb.c [new file with mode: 0644]
drivers/media/video/gspca/sonixj.c [new file with mode: 0644]
drivers/media/video/gspca/spca500.c [new file with mode: 0644]
drivers/media/video/gspca/spca501.c [new file with mode: 0644]
drivers/media/video/gspca/spca505.c [new file with mode: 0644]
drivers/media/video/gspca/spca506.c [new file with mode: 0644]
drivers/media/video/gspca/spca508.c [new file with mode: 0644]
drivers/media/video/gspca/spca561.c [new file with mode: 0644]
drivers/media/video/gspca/stk014.c [new file with mode: 0644]
drivers/media/video/gspca/sunplus.c [new file with mode: 0644]
drivers/media/video/gspca/t613.c [new file with mode: 0644]
drivers/media/video/gspca/tv8532.c [new file with mode: 0644]
drivers/media/video/gspca/vc032x.c [new file with mode: 0644]
drivers/media/video/gspca/zc3xx-reg.h [new file with mode: 0644]
drivers/media/video/gspca/zc3xx.c [new file with mode: 0644]
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/ivtv/ivtv-cards.c
drivers/media/video/ivtv/ivtv-cards.h
drivers/media/video/ivtv/ivtv-controls.c
drivers/media/video/ivtv/ivtv-controls.h
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-gpio.c
drivers/media/video/ivtv/ivtv-i2c.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-ioctl.h
drivers/media/video/ivtv/ivtv-streams.c
drivers/media/video/ivtv/ivtvfb.c
drivers/media/video/m52790.c
drivers/media/video/meye.c
drivers/media/video/msp3400-driver.c
drivers/media/video/msp3400-kthreads.c
drivers/media/video/mt9v022.c
drivers/media/video/ov7670.c
drivers/media/video/ovcamchip/ovcamchip_core.c
drivers/media/video/pvrusb2/pvrusb2-audio.c
drivers/media/video/pvrusb2/pvrusb2-audio.h
drivers/media/video/pvrusb2/pvrusb2-context.c
drivers/media/video/pvrusb2/pvrusb2-context.h
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
drivers/media/video/pvrusb2/pvrusb2-ctrl.h
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
drivers/media/video/pvrusb2/pvrusb2-debug.h
drivers/media/video/pvrusb2/pvrusb2-debugifc.c
drivers/media/video/pvrusb2/pvrusb2-debugifc.h
drivers/media/video/pvrusb2/pvrusb2-devattr.c
drivers/media/video/pvrusb2/pvrusb2-devattr.h
drivers/media/video/pvrusb2/pvrusb2-eeprom.c
drivers/media/video/pvrusb2/pvrusb2-eeprom.h
drivers/media/video/pvrusb2/pvrusb2-encoder.c
drivers/media/video/pvrusb2/pvrusb2-encoder.h
drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-hdw.h
drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
drivers/media/video/pvrusb2/pvrusb2-io.c
drivers/media/video/pvrusb2/pvrusb2-io.h
drivers/media/video/pvrusb2/pvrusb2-ioread.c
drivers/media/video/pvrusb2/pvrusb2-ioread.h
drivers/media/video/pvrusb2/pvrusb2-main.c
drivers/media/video/pvrusb2/pvrusb2-std.c
drivers/media/video/pvrusb2/pvrusb2-std.h
drivers/media/video/pvrusb2/pvrusb2-sysfs.c
drivers/media/video/pvrusb2/pvrusb2-sysfs.h
drivers/media/video/pvrusb2/pvrusb2-tuner.c
drivers/media/video/pvrusb2/pvrusb2-tuner.h
drivers/media/video/pvrusb2/pvrusb2-util.h
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.h
drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
drivers/media/video/pvrusb2/pvrusb2-wm8775.c
drivers/media/video/pvrusb2/pvrusb2-wm8775.h
drivers/media/video/pvrusb2/pvrusb2.h
drivers/media/video/pwc/pwc-ctrl.c
drivers/media/video/pwc/pwc-ioctl.h
drivers/media/video/pxa_camera.c
drivers/media/video/s2255drv.c [new file with mode: 0644]
drivers/media/video/saa5246a.c
drivers/media/video/saa5249.c
drivers/media/video/saa6588.c
drivers/media/video/saa7115.c
drivers/media/video/saa711x.c [deleted file]
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-core.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134-reg.h
drivers/media/video/saa7134/saa7134-tvaudio.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/sh_mobile_ceu_camera.c [new file with mode: 0644]
drivers/media/video/sn9c102/sn9c102_devtable.h
drivers/media/video/soc_camera.c
drivers/media/video/soc_camera_platform.c [new file with mode: 0644]
drivers/media/video/stk-webcam.c
drivers/media/video/tcm825x.c
drivers/media/video/tcm825x.h
drivers/media/video/tda7432.c
drivers/media/video/tda9840.c
drivers/media/video/tda9875.c
drivers/media/video/tea6415c.c
drivers/media/video/tea6420.c
drivers/media/video/tlv320aic23b.c
drivers/media/video/tuner-core.c
drivers/media/video/tvaudio.c
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-i2c.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/uvc/Kconfig [new file with mode: 0644]
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_driver.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/uvc/uvc_status.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvc_video.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/videobuf-dma-contig.c [new file with mode: 0644]
drivers/media/video/videobuf-dma-sg.c
drivers/media/video/videobuf-dvb.c
drivers/media/video/videobuf-vmalloc.c
drivers/media/video/videodev.c
drivers/media/video/vivi.c
drivers/media/video/vp27smpx.c
drivers/media/video/wm8739.c
drivers/media/video/wm8775.c
drivers/media/video/zoran_card.c
drivers/media/video/zoran_driver.c
drivers/media/video/zr364xx.c
include/linux/i2c-id.h
include/linux/videodev2.h
include/media/cx2341x.h
include/media/ir-kbd-i2c.h
include/media/pwc-ioctl.h
include/media/saa7146.h
include/media/sh_mobile_ceu.h [new file with mode: 0644]
include/media/soc_camera.h
include/media/soc_camera_platform.h [new file with mode: 0644]
include/media/v4l2-dev.h
include/media/v4l2-i2c-drv-legacy.h
include/media/videobuf-dma-contig.h [new file with mode: 0644]
include/media/videobuf-dma-sg.h
include/media/videobuf-vmalloc.h

index 191194e..f0e613b 100644 (file)
@@ -8,3 +8,4 @@
   7 -> Hauppauge WinTV-HVR1200                             [0070:71d1,0070:71d3]
   8 -> Hauppauge WinTV-HVR1700                             [0070:8101]
   9 -> Hauppauge WinTV-HVR1400                             [0070:8010]
+ 10 -> DViCO FusionHDTV7 Dual Express                      [18ac:d618]
index 1d6a245..1059146 100644 (file)
@@ -8,10 +8,13 @@
   7 -> Leadtek Winfast USB II                   (em2800)
   8 -> Kworld USB2800                           (em2800)
   9 -> Pinnacle Dazzle DVC 90/DVC 100           (em2820/em2840) [2304:0207,2304:021a]
- 10 -> Hauppauge WinTV HVR 900                  (em2880)        [2040:6500,2040:6502]
+ 10 -> Hauppauge WinTV HVR 900                  (em2880)        [2040:6500]
  11 -> Terratec Hybrid XS                       (em2880)        [0ccd:0042]
  12 -> Kworld PVR TV 2800 RF                    (em2820/em2840)
  13 -> Terratec Prodigy XS                      (em2880)        [0ccd:0047]
  14 -> Pixelview Prolink PlayTV USB 2.0         (em2820/em2840)
  15 -> V-Gear PocketTV                          (em2800)
  16 -> Hauppauge WinTV HVR 950                  (em2880)        [2040:6513,2040:6517,2040:651b,2040:651f]
+ 17 -> Pinnacle PCTV HD Pro Stick               (em2880)        [2304:0227]
+ 18 -> Hauppauge WinTV HVR 900 (R2)             (em2880)        [2040:6502]
+ 19 -> PointNix Intra-Oral Camera               (em2860)
index 67937df..39868af 100644 (file)
@@ -37,7 +37,7 @@
  36 -> UPMOST PURPLE TV                         [12ab:0800]
  37 -> Items MuchTV Plus / IT-005
  38 -> Terratec Cinergy 200 TV                  [153b:1152]
- 39 -> LifeView FlyTV Platinum Mini             [5168:0212,4e42:0212]
+ 39 -> LifeView FlyTV Platinum Mini             [5168:0212,4e42:0212,5169:1502]
  40 -> Compro VideoMate TV PVR/FM               [185b:c100]
  41 -> Compro VideoMate TV Gold+                [185b:c100]
  42 -> Sabrent SBT-TVFM (saa7130)
 127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090]
 128 -> Beholder BeholdTV Columbus TVFM          [0000:5201]
 129 -> Beholder BeholdTV 607 / BeholdTV 609     [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093]
-130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193,5ace:6191]
+130 -> Beholder BeholdTV M6                     [5ace:6190]
 131 -> Twinhan Hybrid DTV-DVB 3056 PCI          [1822:0022]
 132 -> Genius TVGO AM11MCE
 133 -> NXP Snake DVB-S reference design
 140 -> Avermedia DVB-S Pro A700                 [1461:a7a1]
 141 -> Avermedia DVB-S Hybrid+FM A700           [1461:a7a2]
 142 -> Beholder BeholdTV H6                     [5ace:6290]
+143 -> Beholder BeholdTV M63                    [5ace:6191]
+144 -> Beholder BeholdTV M6 Extra               [5ace:6193]
+145 -> AVerMedia MiniPCI DVB-T Hybrid M103      [1461:f636]
+146 -> ASUSTeK P7131 Analog
index 6842c26..914cb7e 100644 (file)
@@ -1,36 +1,30 @@
 Some notes regarding the cx18 driver for the Conexant CX23418 MPEG
 encoder chip:
 
-1) The only hardware currently supported is the Hauppauge HVR-1600
-   card and the Compro VideoMate H900 (note that this card only
-   supports analog input, it has no digital tuner!).
+1) Currently supported are:
 
-2) Some people have problems getting the i2c bus to work. Cause unknown.
-   The symptom is that the eeprom cannot be read and the card is
-   unusable.
+       - Hauppauge HVR-1600
+       - Compro VideoMate H900
+       - Yuan MPC718
+       - Conexant Raptor PAL/SECAM devkit
 
-3) The audio from the analog tuner is mono only. Probably caused by
-   incorrect audio register information in the datasheet. We are
-   waiting for updated information from Conexant.
+2) Some people have problems getting the i2c bus to work.
+   The symptom is that the eeprom cannot be read and the card is
+   unusable. This is probably fixed, but if you have problems
+   then post to the video4linux or ivtv-users mailinglist.
 
-4) VBI (raw or sliced) has not yet been implemented.
+3) VBI (raw or sliced) has not yet been implemented.
 
-5) MPEG indexing is not yet implemented.
+4) MPEG indexing is not yet implemented.
 
-6) The driver is still a bit rough around the edges, this should
+5) The driver is still a bit rough around the edges, this should
    improve over time.
 
 
 Firmware:
 
-The firmware needs to be extracted from the Windows Hauppauge HVR-1600
-driver, available here:
-
-http://hauppauge.lightpath.net/software/install_cd/hauppauge_cd_3.4d1.zip
+You can obtain the firmware files here:
 
-Unzip, then copy the following files to the firmware directory
-and rename them as follows:
+http://dl.ivtvdriver.org/ivtv/firmware/cx18-firmware.tar.gz
 
-Drivers/Driver18/hcw18apu.rom -> v4l-cx23418-apu.fw
-Drivers/Driver18/hcw18enc.rom -> v4l-cx23418-cpu.fw
-Drivers/Driver18/hcw18mlC.rom -> v4l-cx23418-dig.fw
+Untar and copy the .fw files to your firmware directory.
diff --git a/Documentation/video4linux/gspca.txt b/Documentation/video4linux/gspca.txt
new file mode 100644 (file)
index 0000000..0c4880a
--- /dev/null
@@ -0,0 +1,243 @@
+List of the webcams know by gspca.
+
+The modules are:
+       gspca_main      main driver
+       gspca_xxxx      subdriver module with xxxx as follows
+
+xxxx           vend:prod
+----
+spca501                0000:0000       MystFromOri Unknow Camera
+spca501                040a:0002       Kodak DVC-325
+spca500                040a:0300       Kodak EZ200
+zc3xx          041e:041e       Creative WebCam Live!
+spca500                041e:400a       Creative PC-CAM 300
+sunplus                041e:400b       Creative PC-CAM 600
+sunplus                041e:4012       PC-Cam350
+sunplus                041e:4013       Creative Pccam750
+zc3xx          041e:4017       Creative Webcam Mobile PD1090
+spca508                041e:4018       Creative Webcam Vista (PD1100)
+spca561                041e:401a       Creative Webcam Vista (PD1100)
+zc3xx          041e:401c       Creative NX
+spca505                041e:401d       Creative Webcam NX ULTRA
+zc3xx          041e:401e       Creative Nx Pro
+zc3xx          041e:401f       Creative Webcam Notebook PD1171
+pac207         041e:4028       Creative Webcam Vista Plus
+zc3xx          041e:4029       Creative WebCam Vista Pro
+zc3xx          041e:4034       Creative Instant P0620
+zc3xx          041e:4035       Creative Instant P0620D
+zc3xx          041e:4036       Creative Live !
+zc3xx          041e:403a       Creative Nx Pro 2
+spca561                041e:403b       Creative Webcam Vista (VF0010)
+zc3xx          041e:4051       Creative Live!Cam Notebook Pro (VF0250)
+ov519          041e:4052       Creative Live! VISTA IM
+zc3xx          041e:4053       Creative Live!Cam Video IM
+ov519          041e:405f       Creative Live! VISTA VF0330
+ov519          041e:4060       Creative Live! VISTA VF0350
+ov519          041e:4061       Creative Live! VISTA VF0400
+ov519          041e:4064       Creative Live! VISTA VF0420
+ov519          041e:4068       Creative Live! VISTA VF0470
+spca561                0458:7004       Genius VideoCAM Express V2
+sunplus                0458:7006       Genius Dsc 1.3 Smart
+zc3xx          0458:7007       Genius VideoCam V2
+zc3xx          0458:700c       Genius VideoCam V3
+zc3xx          0458:700f       Genius VideoCam Web V2
+sonixj         0458:7025       Genius Eye 311Q
+sonixj         045e:00f5       MicroSoft VX3000
+sonixj         045e:00f7       MicroSoft VX1000
+ov519          045e:028c       Micro$oft xbox cam
+spca508                0461:0815       Micro Innovation IC200
+sunplus                0461:0821       Fujifilm MV-1
+zc3xx          0461:0a00       MicroInnovation WebCam320
+spca500                046d:0890       Logitech QuickCam traveler
+vc032x         046d:0892       Logitech Orbicam
+vc032x         046d:0896       Logitech Orbicam
+zc3xx          046d:08a0       Logitech QC IM
+zc3xx          046d:08a1       Logitech QC IM 0x08A1 +sound
+zc3xx          046d:08a2       Labtec Webcam Pro
+zc3xx          046d:08a3       Logitech QC Chat
+zc3xx          046d:08a6       Logitech QCim
+zc3xx          046d:08a7       Logitech QuickCam Image
+zc3xx          046d:08a9       Logitech Notebook Deluxe
+zc3xx          046d:08aa       Labtec Webcam  Notebook
+zc3xx          046d:08ac       Logitech QuickCam Cool
+zc3xx          046d:08ad       Logitech QCCommunicate STX
+zc3xx          046d:08ae       Logitech QuickCam for Notebooks
+zc3xx          046d:08af       Logitech QuickCam Cool
+zc3xx          046d:08b9       Logitech QC IM ???
+zc3xx          046d:08d7       Logitech QCam STX
+zc3xx          046d:08d9       Logitech QuickCam IM/Connect
+zc3xx          046d:08d8       Logitech Notebook Deluxe
+zc3xx          046d:08da       Logitech QuickCam Messenger
+zc3xx          046d:08dd       Logitech QuickCam for Notebooks
+spca500                046d:0900       Logitech Inc. ClickSmart 310
+spca500                046d:0901       Logitech Inc. ClickSmart 510
+sunplus                046d:0905       Logitech ClickSmart 820
+tv8532         046d:0920       QC Express
+tv8532         046d:0921       Labtec Webcam
+spca561                046d:0928       Logitech QC Express Etch2
+spca561                046d:0929       Labtec Webcam Elch2
+spca561                046d:092a       Logitech QC for Notebook
+spca561                046d:092b       Labtec Webcam Plus
+spca561                046d:092c       Logitech QC chat Elch2
+spca561                046d:092d       Logitech QC Elch2
+spca561                046d:092e       Logitech QC Elch2
+spca561                046d:092f       Logitech QC Elch2
+sunplus                046d:0960       Logitech ClickSmart 420
+sunplus                0471:0322       Philips DMVC1300K
+zc3xx          0471:0325       Philips SPC 200 NC
+zc3xx          0471:0326       Philips SPC 300 NC
+sonixj         0471:0327       Philips SPC 600 NC
+sonixj         0471:0328       Philips SPC 700 NC
+zc3xx          0471:032d       Philips spc210nc
+zc3xx          0471:032e       Philips spc315nc
+sonixj         0471:0330       Philips SPC 710NC
+spca501                0497:c001       Smile International
+sunplus                04a5:3003       Benq DC 1300
+sunplus                04a5:3008       Benq DC 1500
+sunplus                04a5:300a       Benq DC3410
+spca500                04a5:300c       Benq DC1016
+sunplus                04f1:1001       JVC GC A50
+spca561                04fc:0561       Flexcam 100
+sunplus                04fc:500c       Sunplus CA500C
+sunplus                04fc:504a       Aiptek Mini PenCam 1.3
+sunplus                04fc:504b       Maxell MaxPocket LE 1.3
+sunplus                04fc:5330       Digitrex 2110
+sunplus                04fc:5360       Sunplus Generic
+spca500                04fc:7333       PalmPixDC85
+sunplus                04fc:ffff       Pure DigitalDakota
+spca501                0506:00df       3Com HomeConnect Lite
+sunplus                052b:1513       Megapix V4
+tv8532         0545:808b       Veo Stingray
+tv8532         0545:8333       Veo Stingray
+sunplus                0546:3155       Polaroid PDC3070
+sunplus                0546:3191       Polaroid Ion 80
+sunplus                0546:3273       Polaroid PDC2030
+ov519          054c:0154       Sonny toy4
+ov519          054c:0155       Sonny toy5
+zc3xx          055f:c005       Mustek Wcam300A
+spca500                055f:c200       Mustek Gsmart 300
+sunplus                055f:c211       Kowa Bs888e Microcamera
+spca500                055f:c220       Gsmart Mini
+sunplus                055f:c230       Mustek Digicam 330K
+sunplus                055f:c232       Mustek MDC3500
+sunplus                055f:c360       Mustek DV4000 Mpeg4
+sunplus                055f:c420       Mustek gSmart Mini 2
+sunplus                055f:c430       Mustek Gsmart LCD 2
+sunplus                055f:c440       Mustek DV 3000
+sunplus                055f:c520       Mustek gSmart Mini 3
+sunplus                055f:c530       Mustek Gsmart LCD 3
+sunplus                055f:c540       Gsmart D30
+sunplus                055f:c630       Mustek MDC4000
+sunplus                055f:c650       Mustek MDC5500Z
+zc3xx          055f:d003       Mustek WCam300A
+zc3xx          055f:d004       Mustek WCam300 AN
+conex          0572:0041       Creative Notebook cx11646
+ov519          05a9:0519       OmniVision
+ov519          05a9:0530       OmniVision
+ov519          05a9:4519       OmniVision
+ov519          05a9:8519       OmniVision
+sunplus                05da:1018       Digital Dream Enigma 1.3
+stk014         05e1:0893       Syntek DV4000
+spca561                060b:a001       Maxell Compact Pc PM3
+zc3xx          0698:2003       CTX M730V built in
+spca500                06bd:0404       Agfa CL20
+spca500                06be:0800       Optimedia
+sunplus                06d6:0031       Trust 610 LCD PowerC@m Zoom
+spca506                06e1:a190       ADS Instant VCD
+spca508                0733:0110       ViewQuest VQ110
+spca508                0130:0130       Clone Digital Webcam 11043
+spca501                0733:0401       Intel Create and Share
+spca501                0733:0402       ViewQuest M318B
+spca505                0733:0430       Intel PC Camera Pro
+sunplus                0733:1311       Digital Dream Epsilon 1.3
+sunplus                0733:1314       Mercury 2.1MEG Deluxe Classic Cam
+sunplus                0733:2211       Jenoptik jdc 21 LCD
+sunplus                0733:2221       Mercury Digital Pro 3.1p
+sunplus                0733:3261       Concord 3045 spca536a
+sunplus                0733:3281       Cyberpix S550V
+spca506                0734:043b       3DeMon USB Capture aka
+spca500                084d:0003       D-Link DSC-350
+spca500                08ca:0103       Aiptek PocketDV
+sunplus                08ca:0104       Aiptek PocketDVII 1.3
+sunplus                08ca:0106       Aiptek Pocket DV3100+
+sunplus                08ca:2008       Aiptek Mini PenCam 2 M
+sunplus                08ca:2010       Aiptek PocketCam 3M
+sunplus                08ca:2016       Aiptek PocketCam 2 Mega
+sunplus                08ca:2018       Aiptek Pencam SD 2M
+sunplus                08ca:2020       Aiptek Slim 3000F
+sunplus                08ca:2022       Aiptek Slim 3200
+sunplus                08ca:2024       Aiptek DV3500 Mpeg4
+sunplus                08ca:2028       Aiptek PocketCam4M
+sunplus                08ca:2040       Aiptek PocketDV4100M
+sunplus                08ca:2042       Aiptek PocketDV5100
+sunplus                08ca:2050       Medion MD 41437
+sunplus                08ca:2060       Aiptek PocketDV5300
+tv8532         0923:010f       ICM532 cams
+mars           093a:050f       Mars-Semi Pc-Camera
+pac207         093a:2460       PAC207 Qtec Webcam 100
+pac207         093a:2463       Philips spc200nc pac207
+pac207         093a:2464       Labtec Webcam 1200
+pac207         093a:2468       PAC207
+pac207         093a:2470       Genius GF112
+pac207         093a:2471       PAC207 Genius VideoCam ge111
+pac207         093a:2472       PAC207 Genius VideoCam ge110
+pac7311                093a:2600       PAC7311 Typhoon
+pac7311                093a:2601       PAC7311 Phillips SPC610NC
+pac7311                093a:2603       PAC7312
+pac7311                093a:2608       PAC7311 Trust WB-3300p
+pac7311                093a:260e       PAC7311 Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
+pac7311                093a:260f       PAC7311 SnakeCam
+pac7311                093a:2621       PAC731x
+zc3xx          0ac8:0302       Z-star Vimicro zc0302
+vc032x         0ac8:0321       Vimicro generic vc0321
+vc032x         0ac8:0323       Vimicro Vc0323
+vc032x         0ac8:0328       A4Tech PK-130MG
+zc3xx          0ac8:301b       Z-Star zc301b
+zc3xx          0ac8:303b       Vimicro 0x303b
+zc3xx          0ac8:305b       Z-star Vimicro zc0305b
+zc3xx          0ac8:307b       Ldlc VC302+Ov7620
+vc032x         0ac8:c001       Sony embedded vimicro
+vc032x         0ac8:c002       Sony embedded vimicro
+spca508                0af9:0010       Hama USB Sightcam 100
+spca508                0af9:0011       Hama USB Sightcam 100
+sonixb         0c45:6001       Genius VideoCAM NB
+sonixb         0c45:6005       Microdia Sweex Mini Webcam
+sonixb         0c45:6007       Sonix sn9c101 + Tas5110D
+sonixb         0c45:6009       spcaCam@120
+sonixb         0c45:600d       spcaCam@120
+sonixb         0c45:6011       Microdia PC Camera (SN9C102)
+sonixb         0c45:6019       Generic Sonix OV7630
+sonixb         0c45:6024       Generic Sonix Tas5130c
+sonixb         0c45:6025       Xcam Shanga
+sonixb         0c45:6028       Sonix Btc Pc380
+sonixb         0c45:6029       spcaCam@150
+sonixb         0c45:602c       Generic Sonix OV7630
+sonixb         0c45:602d       LIC-200 LG
+sonixb         0c45:602e       Genius VideoCam Messenger
+sonixj         0c45:6040       Speed NVC 350K
+sonixj         0c45:607c       Sonix sn9c102p Hv7131R
+sonixj         0c45:60c0       Sangha Sn535
+sonixj         0c45:60ec       SN9C105+MO4000
+sonixj         0c45:60fb       Surfer NoName
+sonixj         0c45:60fc       LG-LIC300
+sonixj         0c45:612a       Avant Camera
+sonixj         0c45:612c       Typhoon Rasy Cam 1.3MPix
+sonixj         0c45:6130       Sonix Pccam
+sonixj         0c45:6138       Sn9c120 Mo4000
+sonixj         0c45:613b       Surfer SN-206
+sonixj         0c45:613c       Sonix Pccam168
+sunplus                0d64:0303       Sunplus FashionCam DXG
+etoms          102c:6151       Qcam Sangha CIF
+etoms          102c:6251       Qcam xxxxxx VGA
+zc3xx          10fd:0128       Typhoon Webshot II USB 300k 0x0128
+spca561                10fd:7e50       FlyCam Usb 100
+zc3xx          10fd:8050       Typhoon Webshot II USB 300k
+spca501                1776:501c       Arowana 300K CMOS Camera
+t613           17a1:0128       T613/TAS5130A
+vc032x         17ef:4802       Lenovo Vc0323+MI1310_SOC
+pac207         2001:f115       D-Link DSB-C120
+spca500                2899:012c       Toptro Industrial
+spca508                8086:0110       Intel Easy PC Camera
+spca500                8086:0630       Intel Pocket PC Camera
+spca506                99fa:8988       Grandtec V.cap
+spca561                abcd:cdee       Petcam
index 7a7803b..93ea201 100644 (file)
@@ -38,7 +38,6 @@ config VIDEO_ALLOW_V4L1
        bool "Enable Video For Linux API 1 (DEPRECATED)"
        depends on VIDEO_DEV && VIDEO_V4L2_COMMON
        default VIDEO_DEV && VIDEO_V4L2_COMMON
-       select VIDEO_V4L1_COMPAT
        ---help---
          Enables drivers based on the legacy V4L1 API.
 
@@ -49,9 +48,9 @@ config VIDEO_ALLOW_V4L1
          If you are unsure as to whether this is required, answer Y.
 
 config VIDEO_V4L1_COMPAT
-       bool "Enable Video For Linux API 1 compatible Layer"
+       bool "Enable Video For Linux API 1 compatible Layer" if !VIDEO_ALLOW_V4L1
        depends on VIDEO_DEV
-       default VIDEO_DEV
+       default y
        ---help---
          Enables a compatibility API used by most V4L2 devices to allow
          its usage with legacy applications that supports only V4L1 api.
index 2665052..16792a6 100644 (file)
@@ -66,7 +66,6 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
        if (ir_codes)
                memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes));
 
-
        dev->keycode     = ir->ir_codes;
        dev->keycodesize = sizeof(IR_KEYTAB_TYPE);
        dev->keycodemax  = IR_KEYTAB_SIZE;
@@ -78,6 +77,7 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
        if (repeat)
                set_bit(EV_REP, dev->evbit);
 }
+EXPORT_SYMBOL_GPL(ir_input_init);
 
 void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
 {
@@ -86,6 +86,7 @@ void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
                ir_input_key_event(dev,ir);
        }
 }
+EXPORT_SYMBOL_GPL(ir_input_nokey);
 
 void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
                      u32 ir_key, u32 ir_raw)
@@ -104,6 +105,7 @@ void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
                ir_input_key_event(dev,ir);
        }
 }
+EXPORT_SYMBOL_GPL(ir_input_keydown);
 
 /* -------------------------------------------------------------------------- */
 /* extract mask bits out of data and pack them into the result */
@@ -122,6 +124,7 @@ u32 ir_extract_bits(u32 data, u32 mask)
 
        return value;
 }
+EXPORT_SYMBOL_GPL(ir_extract_bits);
 
 static int inline getbit(u32 *samples, int bit)
 {
@@ -146,6 +149,7 @@ int ir_dump_samples(u32 *samples, int count)
        printk("\n");
        return 0;
 }
+EXPORT_SYMBOL_GPL(ir_dump_samples);
 
 /* decode raw samples, pulse distance coding used by NEC remotes */
 int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
@@ -212,6 +216,7 @@ int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
 
        return value;
 }
+EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
 
 /* decode raw samples, biphase coding, used by rc5 for example */
 int ir_decode_biphase(u32 *samples, int count, int low, int high)
@@ -253,6 +258,7 @@ int ir_decode_biphase(u32 *samples, int count, int low, int high)
        }
        return value;
 }
+EXPORT_SYMBOL_GPL(ir_decode_biphase);
 
 /* RC5 decoding stuff, moved from bttv-input.c to share it with
  * saa7134 */
@@ -353,6 +359,7 @@ void ir_rc5_timer_end(unsigned long data)
                }
        }
 }
+EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
 
 void ir_rc5_timer_keyup(unsigned long data)
 {
@@ -361,21 +368,4 @@ void ir_rc5_timer_keyup(unsigned long data)
        dprintk(1, "ir-common: key released\n");
        ir_input_nokey(ir->dev, &ir->ir);
 }
-
-EXPORT_SYMBOL_GPL(ir_input_init);
-EXPORT_SYMBOL_GPL(ir_input_nokey);
-EXPORT_SYMBOL_GPL(ir_input_keydown);
-
-EXPORT_SYMBOL_GPL(ir_extract_bits);
-EXPORT_SYMBOL_GPL(ir_dump_samples);
-EXPORT_SYMBOL_GPL(ir_decode_biphase);
-EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
-
-EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
 EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
index 89c7660..d01965e 100644 (file)
@@ -233,7 +233,7 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
 
 int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
 {
-       u32          *cpu;
+       __le32       *cpu;
        dma_addr_t   dma_addr;
 
        cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr);
@@ -250,7 +250,7 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
 int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
        struct scatterlist *list, int sglen  )
 {
-       u32 *ptr, fill;
+       __le32 *ptr, fill;
        int nr_pages = 0;
        int i,p;
 
index 9c90539..05bde9c 100644 (file)
@@ -338,7 +338,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
        struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field)
 {
        struct saa7146_vv *vv = dev->vv_data;
-       u32 *clipping = vv->d_clipping.cpu_addr;
+       __le32 *clipping = vv->d_clipping.cpu_addr;
 
        int width = fh->ov.win.w.width;
        int height =  fh->ov.win.w.height;
index 35b01ec..c11da4d 100644 (file)
@@ -24,7 +24,7 @@ static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
    sent through the saa7146. have a look at the specifications p. 122 ff
    to understand this. it returns the number of u32s to send, or -1
    in case of an error. */
-static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
+static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, __le32 *op)
 {
        int h1, h2;
        int i, j, addr;
@@ -47,7 +47,7 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
        }
 
        /* be careful: clear out the i2c-mem first */
-       memset(op,0,sizeof(u32)*mem);
+       memset(op,0,sizeof(__le32)*mem);
 
        /* loop through all messages */
        for(i = 0; i < num; i++) {
@@ -57,16 +57,16 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
                   so we have to perform a translation */
                addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0);
                h1 = op_count/3; h2 = op_count%3;
-               op[h1] |= (         (u8)addr << ((3-h2)*8));
-               op[h1] |= (SAA7146_I2C_START << ((3-h2)*2));
+               op[h1] |= cpu_to_le32(      (u8)addr << ((3-h2)*8));
+               op[h1] |= cpu_to_le32(SAA7146_I2C_START << ((3-h2)*2));
                op_count++;
 
                /* loop through all bytes of message i */
                for(j = 0; j < m[i].len; j++) {
                        /* insert the data bytes */
                        h1 = op_count/3; h2 = op_count%3;
-                       op[h1] |= ( (u32)((u8)m[i].buf[j]) << ((3-h2)*8));
-                       op[h1] |= (       SAA7146_I2C_CONT << ((3-h2)*2));
+                       op[h1] |= cpu_to_le32( (u32)((u8)m[i].buf[j]) << ((3-h2)*8));
+                       op[h1] |= cpu_to_le32(       SAA7146_I2C_CONT << ((3-h2)*2));
                        op_count++;
                }
 
@@ -75,9 +75,9 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
        /* have a look at the last byte inserted:
          if it was: ...CONT change it to ...STOP */
        h1 = (op_count-1)/3; h2 = (op_count-1)%3;
-       if ( SAA7146_I2C_CONT == (0x3 & (op[h1] >> ((3-h2)*2))) ) {
-               op[h1] &= ~(0x2 << ((3-h2)*2));
-               op[h1] |= (SAA7146_I2C_STOP << ((3-h2)*2));
+       if ( SAA7146_I2C_CONT == (0x3 & (le32_to_cpu(op[h1]) >> ((3-h2)*2))) ) {
+               op[h1] &= ~cpu_to_le32(0x2 << ((3-h2)*2));
+               op[h1] |= cpu_to_le32(SAA7146_I2C_STOP << ((3-h2)*2));
        }
 
        /* return the number of u32s to send */
@@ -88,7 +88,7 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
    which bytes were read through the adapter and write them back to the corresponding
    i2c-message. but instead, we simply write back all bytes.
    fixme: this could be improved. */
-static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op)
+static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, __le32 *op)
 {
        int i, j;
        int op_count = 0;
@@ -101,7 +101,7 @@ static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op)
                /* loop throgh all bytes of message i */
                for(j = 0; j < m[i].len; j++) {
                        /* write back all bytes that could have been read */
-                       m[i].buf[j] = (op[op_count/3] >> ((3-(op_count%3))*8));
+                       m[i].buf[j] = (le32_to_cpu(op[op_count/3]) >> ((3-(op_count%3))*8));
                        op_count++;
                }
        }
@@ -174,7 +174,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
 /* this functions writes out the data-byte 'dword' to the i2c-device.
    it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
    failed badly (e.g. address error) */
-static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_delay)
+static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int short_delay)
 {
        u32 status = 0, mc2 = 0;
        int trial = 0;
@@ -186,7 +186,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
        if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
 
                saa7146_write(dev, I2C_STATUS,   dev->i2c_bitrate);
-               saa7146_write(dev, I2C_TRANSFER, *dword);
+               saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword));
 
                dev->i2c_op = 1;
                SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
@@ -209,7 +209,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
                status = saa7146_read(dev, I2C_STATUS);
        } else {
                saa7146_write(dev, I2C_STATUS,   dev->i2c_bitrate);
-               saa7146_write(dev, I2C_TRANSFER, *dword);
+               saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword));
                saa7146_write(dev, MC2, (MASK_00 | MASK_16));
 
                /* do not poll for i2c-status before upload is complete */
@@ -282,7 +282,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
        }
 
        /* read back data, just in case we were reading ... */
-       *dword = saa7146_read(dev, I2C_TRANSFER);
+       *dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER));
 
        DEB_I2C(("after: 0x%08x\n",*dword));
        return 0;
@@ -291,7 +291,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
 static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
 {
        int i = 0, count = 0;
-       u32* buffer = dev->d_i2c.cpu_addr;
+       __le32 *buffer = dev->d_i2c.cpu_addr;
        int err = 0;
        int address_err = 0;
        int short_delay = 0;
@@ -376,7 +376,7 @@ out:
        /* another bug in revision 0: the i2c-registers get uploaded randomly by other
           uploads, so we better clear them out before continueing */
        if( 0 == dev->revision ) {
-               u32 zero = 0;
+               __le32 zero = 0;
                saa7146_i2c_reset(dev);
                if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
                        INFO(("revision 0 error. this should never happen.\n"));
index 3cbc6eb..a5e6275 100644 (file)
@@ -605,8 +605,8 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
                struct saa7146_pgtable *pt1 = &buf->pt[0];
                struct saa7146_pgtable *pt2 = &buf->pt[1];
                struct saa7146_pgtable *pt3 = &buf->pt[2];
-               u32  *ptr1, *ptr2, *ptr3;
-               u32 fill;
+               __le32  *ptr1, *ptr2, *ptr3;
+               __le32 fill;
 
                int size = buf->fmt->width*buf->fmt->height;
                int i,p,m1,m2,m3,o1,o2;
index 8548296..850d568 100644 (file)
@@ -34,6 +34,7 @@ config MEDIA_TUNER
 menuconfig MEDIA_TUNER_CUSTOMIZE
        bool "Customize analog and hybrid tuner modules to build"
        depends on MEDIA_TUNER
+       default n
        help
          This allows the user to deselect tuner drivers unnecessary
          for their hardware from the build. Use this option with care
index 83e7561..ab14ceb 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    tda18271-tables.c - driver for the Philips / NXP TDA18271 silicon tuner
+    tda18271-maps.c - driver for the Philips / NXP TDA18271 silicon tuner
 
     Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
 
index 30eb07b..4dd1d24 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <media/tuner.h>
 #include <linux/mutex.h>
+#include <asm/unaligned.h>
 #include "tuner-i2c.h"
 #include "tuner-xc2028.h"
 #include "tuner-xc2028-types.h"
@@ -292,10 +293,10 @@ static int load_all_firmwares(struct dvb_frontend *fe)
        name[sizeof(name) - 1] = 0;
        p += sizeof(name) - 1;
 
-       priv->firm_version = le16_to_cpu(*(__u16 *) p);
+       priv->firm_version = get_unaligned_le16(p);
        p += 2;
 
-       n_array = le16_to_cpu(*(__u16 *) p);
+       n_array = get_unaligned_le16(p);
        p += 2;
 
        tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
@@ -324,26 +325,26 @@ static int load_all_firmwares(struct dvb_frontend *fe)
                }
 
                /* Checks if there's enough bytes to read */
-               if (p + sizeof(type) + sizeof(id) + sizeof(size) > endp) {
-                       tuner_err("Firmware header is incomplete!\n");
-                       goto corrupt;
-               }
+               if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
+                       goto header;
 
-               type = le32_to_cpu(*(__u32 *) p);
+               type = get_unaligned_le32(p);
                p += sizeof(type);
 
-               id = le64_to_cpu(*(v4l2_std_id *) p);
+               id = get_unaligned_le64(p);
                p += sizeof(id);
 
                if (type & HAS_IF) {
-                       int_freq = le16_to_cpu(*(__u16 *) p);
+                       int_freq = get_unaligned_le16(p);
                        p += sizeof(int_freq);
+                       if (endp - p < sizeof(size))
+                               goto header;
                }
 
-               size = le32_to_cpu(*(__u32 *) p);
+               size = get_unaligned_le32(p);
                p += sizeof(size);
 
-               if ((!size) || (size + p > endp)) {
+               if (!size || size > endp - p) {
                        tuner_err("Firmware type ");
                        dump_firm_type(type);
                        printk("(%x), id %llx is corrupted "
@@ -382,6 +383,8 @@ static int load_all_firmwares(struct dvb_frontend *fe)
 
        goto done;
 
+header:
+       tuner_err("Firmware header is incomplete!\n");
 corrupt:
        rc = -EINVAL;
        tuner_err("Error: firmware file is corrupted!\n");
index 4878d64..5f99de0 100644 (file)
@@ -36,6 +36,10 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
+static int xc5000_load_fw_on_attach;
+module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644);
+MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
+
 #define dprintk(level,fmt, arg...) if (debug >= level) \
        printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
 
@@ -972,6 +976,9 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 
        fe->tuner_priv = priv;
 
+       if (xc5000_load_fw_on_attach)
+               xc5000_init(fe);
+
        return fe;
 }
 EXPORT_SYMBOL(xc5000_attach);
index 7b21b49..8bc1445 100644 (file)
@@ -21,6 +21,7 @@ source "drivers/media/dvb/dvb-usb/Kconfig"
 source "drivers/media/dvb/ttusb-budget/Kconfig"
 source "drivers/media/dvb/ttusb-dec/Kconfig"
 source "drivers/media/dvb/cinergyT2/Kconfig"
+source "drivers/media/dvb/siano/Kconfig"
 
 comment "Supported FlexCopII (B2C2) Adapters"
        depends on DVB_CORE && (PCI || USB) && I2C
index a7ad084..d6ba4d1 100644 (file)
@@ -2,4 +2,4 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/
+obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/ pluto2/ siano/
index 375fd28..d19b592 100644 (file)
@@ -128,7 +128,7 @@ struct bt878 {
        dma_addr_t buf_dma;
 
        u32 risc_size;
-       u32 *risc_cpu;
+       __le32 *risc_cpu;
        dma_addr_t risc_dma;
        u32 risc_pos;
 
index b0d347d..eb91fd8 100644 (file)
@@ -247,7 +247,7 @@ struct dmx_demux {
        void* priv;                  /* Pointer to private data of the API client */
        int (*open) (struct dmx_demux* demux);
        int (*close) (struct dmx_demux* demux);
-       int (*write) (struct dmx_demux* demux, const charbuf, size_t count);
+       int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
        int (*allocate_ts_feed) (struct dmx_demux* demux,
                                 struct dmx_ts_feed** feed,
                                 dmx_ts_cb callback);
index df5bef6..1cf9fcb 100644 (file)
@@ -96,7 +96,7 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
                if (avail > todo)
                        avail = todo;
 
-               ret = dvb_ringbuffer_read(src, (u8 *)buf, avail, 1);
+               ret = dvb_ringbuffer_read_user(src, buf, avail);
                if (ret < 0)
                        break;
 
index 588fbe1..8e5dd7b 100644 (file)
@@ -1357,7 +1357,7 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca,
 
                idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
                while (idx != -1) {
-                       dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
+                       dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
                        if (connection_id == -1)
                                connection_id = hdr[0];
                        if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) {
@@ -1438,7 +1438,7 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
                        goto exit;
                }
 
-               dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
+               dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
                if (connection_id == -1)
                        connection_id = hdr[0];
                if (hdr[0] == connection_id) {
@@ -1449,8 +1449,8 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
                                        fraglen -= 2;
                                }
 
-                               if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2,
-                                                                     (u8 *)buf + pktlen, fraglen, 1)) < 0) {
+                               if ((status = dvb_ringbuffer_pkt_read_user(&ca->slot_info[slot].rx_buffer, idx, 2,
+                                                                     buf + pktlen, fraglen)) < 0) {
                                        goto exit;
                                }
                                pktlen += fraglen;
index 934e15f..e2eca0b 100644 (file)
@@ -1056,16 +1056,27 @@ static int dvbdmx_close(struct dmx_demux *demux)
        return 0;
 }
 
-static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count)
+static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t count)
 {
        struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+       void *p;
 
        if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
                return -EINVAL;
 
-       if (mutex_lock_interruptible(&dvbdemux->mutex))
+       p = kmalloc(count, GFP_USER);
+       if (!p)
+               return -ENOMEM;
+       if (copy_from_user(p, buf, count)) {
+               kfree(p);
+               return -EFAULT;
+       }
+       if (mutex_lock_interruptible(&dvbdemux->mutex)) {
+               kfree(p);
                return -ERESTARTSYS;
-       dvb_dmx_swfilter(dvbdemux, (u8 *)buf, count);
+       }
+       dvb_dmx_swfilter(dvbdemux, p, count);
+       kfree(p);
        mutex_unlock(&dvbdemux->mutex);
 
        if (signal_pending(current))
index c2c0337..c93019c 100644 (file)
@@ -606,7 +606,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
                        if (priv->ule_dbit) {
                                /* Set D-bit for CRC32 verification,
                                 * if it was set originally. */
-                               ulen |= 0x0080;
+                               ulen |= htons(0x8000);
                        }
 
                        ule_crc = iov_crc32(ule_crc, iov, 3);
index 872985b..584bbd1 100644 (file)
@@ -107,35 +107,43 @@ void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
        wake_up(&rbuf->queue);
 }
 
-
-
-ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, int usermem)
+ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len)
 {
        size_t todo = len;
        size_t split;
 
        split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
        if (split > 0) {
-               if (!usermem)
-                       memcpy(buf, rbuf->data+rbuf->pread, split);
-               else
-                       if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
-                               return -EFAULT;
+               if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
+                       return -EFAULT;
                buf += split;
                todo -= split;
                rbuf->pread = 0;
        }
-       if (!usermem)
-               memcpy(buf, rbuf->data+rbuf->pread, todo);
-       else
-               if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
-                       return -EFAULT;
+       if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
+               return -EFAULT;
 
        rbuf->pread = (rbuf->pread + todo) % rbuf->size;
 
        return len;
 }
 
+void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
+{
+       size_t todo = len;
+       size_t split;
+
+       split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
+       if (split > 0) {
+               memcpy(buf, rbuf->data+rbuf->pread, split);
+               buf += split;
+               todo -= split;
+               rbuf->pread = 0;
+       }
+       memcpy(buf, rbuf->data+rbuf->pread, todo);
+
+       rbuf->pread = (rbuf->pread + todo) % rbuf->size;
+}
 
 
 ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len)
@@ -171,8 +179,8 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le
        return status;
 }
 
-ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
-                               int offset, u8* buf, size_t len, int usermem)
+ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
+                               int offset, u8 __user *buf, size_t len)
 {
        size_t todo;
        size_t split;
@@ -187,21 +195,40 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
        todo = len;
        split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
        if (split > 0) {
-               if (!usermem)
-                       memcpy(buf, rbuf->data+idx, split);
-               else
-                       if (copy_to_user(buf, rbuf->data+idx, split))
-                               return -EFAULT;
+               if (copy_to_user(buf, rbuf->data+idx, split))
+                       return -EFAULT;
                buf += split;
                todo -= split;
                idx = 0;
        }
-       if (!usermem)
-               memcpy(buf, rbuf->data+idx, todo);
-       else
-               if (copy_to_user(buf, rbuf->data+idx, todo))
-                       return -EFAULT;
+       if (copy_to_user(buf, rbuf->data+idx, todo))
+               return -EFAULT;
+
+       return len;
+}
 
+ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
+                               int offset, u8* buf, size_t len)
+{
+       size_t todo;
+       size_t split;
+       size_t pktlen;
+
+       pktlen = rbuf->data[idx] << 8;
+       pktlen |= rbuf->data[(idx + 1) % rbuf->size];
+       if (offset > pktlen) return -EINVAL;
+       if ((offset + len) > pktlen) len = pktlen - offset;
+
+       idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
+       todo = len;
+       split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
+       if (split > 0) {
+               memcpy(buf, rbuf->data+idx, split);
+               buf += split;
+               todo -= split;
+               idx = 0;
+       }
+       memcpy(buf, rbuf->data+idx, todo);
        return len;
 }
 
@@ -266,5 +293,6 @@ EXPORT_SYMBOL(dvb_ringbuffer_empty);
 EXPORT_SYMBOL(dvb_ringbuffer_free);
 EXPORT_SYMBOL(dvb_ringbuffer_avail);
 EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
+EXPORT_SYMBOL(dvb_ringbuffer_read_user);
 EXPORT_SYMBOL(dvb_ringbuffer_read);
 EXPORT_SYMBOL(dvb_ringbuffer_write);
index 8908262..41f04da 100644 (file)
@@ -61,7 +61,7 @@ struct dvb_ringbuffer {
 **     *** read min. 1000, max. <bufsize> bytes ***
 **     avail = dvb_ringbuffer_avail(rbuf);
 **     if (avail >= 1000)
-**         count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize), 0);
+**         count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
 **     else
 **         ...
 **
@@ -114,8 +114,10 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
 ** <usermem> specifies whether <buf> resides in user space
 ** returns number of bytes transferred or -EFAULT
 */
-extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
-                                  size_t len, int usermem);
+extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf,
+                                  u8 __user *buf, size_t len);
+extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
+                                  u8 *buf, size_t len);
 
 
 /* write routines & macros */
@@ -157,8 +159,10 @@ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
  * <usermem> Set to 1 if <buf> is in userspace.
  * returns Number of bytes read, or -EFAULT.
  */
+extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
+                                      int offset, u8 __user *buf, size_t len);
 extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
-                                      int offset, u8* buf, size_t len, int usermem);
+                                      int offset, u8 *buf, size_t len);
 
 /**
  * Dispose of a packet in the ring buffer.
index f00a0eb..a577c0f 100644 (file)
@@ -76,6 +76,7 @@ config DVB_USB_DIB0700
        select DVB_DIB3000MC
        select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
        select DVB_TUNER_DIB0070
        help
          Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
@@ -107,6 +108,8 @@ config DVB_USB_CXUSB
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Conexant USB2.0 hybrid reference design.
          Currently, only DVB and ATSC modes are supported, analog mode
@@ -120,6 +123,8 @@ config DVB_USB_M920X
        depends on DVB_USB
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
+       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
          Currently, only devices with a product id of
@@ -241,3 +246,13 @@ config DVB_USB_AF9005_REMOTE
          Say Y here to support the default remote control decoding for the
          Afatech AF9005 based receiver.
 
+config DVB_USB_ANYSEE
+       tristate "Anysee DVB-T/C USB2.0 support"
+       depends on DVB_USB
+       select DVB_PLL if !DVB_FE_CUSTOMISE
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+       help
+         Say Y here to support the Anysee E30, Anysee E30 Plus or
+         Anysee E30 C Plus DVB USB2.0 receiver.
index c6511a6..44c11e4 100644 (file)
@@ -61,6 +61,9 @@ obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o
 dvb-usb-af9005-remote-objs = af9005-remote.o
 obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
 
+dvb-usb-anysee-objs = anysee.o
+obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
+
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 # due to tuner-xc3028
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
new file mode 100644 (file)
index 0000000..adfd4fc
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    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.
+ *
+ * TODO:
+ * - add smart card reader support for Conditional Access (CA)
+ *
+ * Card reader in Anysee is nothing more than ISO 7816 card reader.
+ * There is no hardware CAM in any Anysee device sold.
+ * In my understanding it should be implemented by making own module
+ * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This
+ * module registers serial interface that can be used to communicate
+ * with any ISO 7816 smart card.
+ *
+ * Any help according to implement serial smart card reader support
+ * is highly welcome!
+ */
+
+#include "anysee.h"
+#include "tda1002x.h"
+#include "mt352.h"
+#include "mt352_priv.h"
+#include "zl10353.h"
+
+/* debug */
+static int dvb_usb_anysee_debug;
+module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct mutex anysee_usb_mutex;
+
+static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
+       u8 *rbuf, u8 rlen)
+{
+       struct anysee_state *state = d->priv;
+       int act_len, ret;
+       u8 buf[64];
+
+       if (slen > sizeof(buf))
+               slen = sizeof(buf);
+       memcpy(&buf[0], sbuf, slen);
+       buf[60] = state->seq++;
+
+       if (mutex_lock_interruptible(&anysee_usb_mutex) < 0)
+               return -EAGAIN;
+
+       /* We need receive one message more after dvb_usb_generic_rw due
+          to weird transaction flow, which is 1 x send + 2 x receive. */
+       ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
+
+       if (!ret) {
+               /* receive 2nd answer */
+               ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
+                       d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf),
+                       &act_len, 2000);
+               if (ret)
+                       err("%s: recv bulk message failed: %d", __func__, ret);
+               else {
+                       deb_xfer("<<< ");
+                       debug_dump(buf, act_len, deb_xfer);
+               }
+       }
+
+       /* read request, copy returned data to return buf */
+       if (!ret && rbuf && rlen)
+               memcpy(rbuf, buf, rlen);
+
+       mutex_unlock(&anysee_usb_mutex);
+
+       return ret;
+}
+
+static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
+{
+       u8 buf[] = {CMD_REG_READ, reg >> 8, reg & 0xff, 0x01};
+       int ret;
+       ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1);
+       deb_info("%s: reg:%04x val:%02x\n", __func__, reg, *val);
+       return ret;
+}
+
+static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val)
+{
+       u8 buf[] = {CMD_REG_WRITE, reg >> 8, reg & 0xff, 0x01, val};
+       deb_info("%s: reg:%04x val:%02x\n", __func__, reg, val);
+       return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
+{
+       u8 buf[] = {CMD_GET_HW_INFO};
+       return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3);
+}
+
+static int anysee_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+       u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00};
+       deb_info("%s: onoff:%02x\n", __func__, onoff);
+       return anysee_ctrl_msg(adap->dev, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval)
+{
+       u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval};
+       deb_info("%s: state:%02x interval:%02x\n", __func__, mode, interval);
+       return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff)
+{
+       u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff};
+       deb_info("%s: onoff:%02x\n", __func__, onoff);
+       return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+}
+
+static int anysee_init(struct dvb_usb_device *d)
+{
+       int ret;
+       /* LED light */
+       ret = anysee_led_ctrl(d, 0x01, 0x03);
+       if (ret)
+               return ret;
+
+       /* enable IR */
+       ret = anysee_ir_ctrl(d, 1);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+/* I2C */
+static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+       int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int ret, inc, i = 0;
+
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       while (i < num) {
+               if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+                       u8 buf[6];
+                       buf[0] = CMD_I2C_READ;
+                       buf[1] = msg[i].addr + 1;
+                       buf[2] = msg[i].buf[0];
+                       buf[3] = 0x00;
+                       buf[4] = 0x00;
+                       buf[5] = 0x01;
+                       ret = anysee_ctrl_msg(d, buf, sizeof(buf), msg[i+1].buf,
+                               msg[i+1].len);
+                       inc = 2;
+               } else {
+                       u8 buf[4+msg[i].len];
+                       buf[0] = CMD_I2C_WRITE;
+                       buf[1] = msg[i].addr;
+                       buf[2] = msg[i].len;
+                       buf[3] = 0x01;
+                       memcpy(&buf[4], msg[i].buf, msg[i].len);
+                       ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
+                       inc = 1;
+               }
+               if (ret)
+                       return ret;
+
+               i += inc;
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+
+       return i;
+}
+
+static u32 anysee_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm anysee_i2c_algo = {
+       .master_xfer   = anysee_master_xfer,
+       .functionality = anysee_i2c_func,
+};
+
+static int anysee_mt352_demod_init(struct dvb_frontend *fe)
+{
+       static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x28 };
+       static u8 reset []         = { RESET,      0x80 };
+       static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+       static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };
+       static u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
+       static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+       mt352_write(fe, clock_config,   sizeof(clock_config));
+       udelay(200);
+       mt352_write(fe, reset,          sizeof(reset));
+       mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+
+       mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+       mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+       return 0;
+}
+
+/* Callbacks for DVB USB */
+static struct tda10023_config anysee_tda10023_config = {
+       .demod_address = 0x1a,
+       .invert = 0,
+       .xtal   = 16000000,
+       .pll_m  = 11,
+       .pll_p  = 3,
+       .pll_n  = 1,
+       .output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C,
+       .deltaf = 0xfeeb,
+};
+
+static struct mt352_config anysee_mt352_config = {
+       .demod_address = 0x1e,
+       .demod_init    = anysee_mt352_demod_init,
+};
+
+static struct zl10353_config anysee_zl10353_config = {
+       .demod_address = 0x1e,
+       .parallel_ts = 1,
+};
+
+static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       int ret;
+       struct anysee_state *state = adap->dev->priv;
+       u8 hw_info[3];
+       u8 io_d; /* IO port D */
+
+       /* check which hardware we have
+          We must do this call two times to get reliable values (hw bug). */
+       ret = anysee_get_hw_info(adap->dev, hw_info);
+       if (ret)
+               return ret;
+       ret = anysee_get_hw_info(adap->dev, hw_info);
+       if (ret)
+               return ret;
+
+       /* Meaning of these info bytes are guessed. */
+       info("firmware version:%d.%d.%d hardware id:%d",
+               0, hw_info[1], hw_info[2], hw_info[0]);
+
+       ret = anysee_read_reg(adap->dev, 0xb0, &io_d); /* IO port D */
+       if (ret)
+               return ret;
+       deb_info("%s: IO port D:%02x\n", __func__, io_d);
+
+       /* Select demod using trial and error method. */
+
+       /* Try to attach demodulator in following order:
+             model      demod     hw  firmware
+          1. E30        MT352     02  0.2.1
+          2. E30        ZL10353   02  0.2.1
+          3. E30 Plus   ZL10353   06  0.1.0
+          4. E30C Plus  TDA10023  0a  0.1.0    rev 0.2
+          4. E30C Plus  TDA10023  0f  0.1.2    rev 0.4
+       */
+
+       /* Zarlink MT352 DVB-T demod inside of Samsung DNOS404ZH102A NIM */
+       adap->fe = dvb_attach(mt352_attach, &anysee_mt352_config,
+                             &adap->dev->i2c_adap);
+       if (adap->fe != NULL) {
+               state->tuner = DVB_PLL_THOMSON_DTT7579;
+               return 0;
+       }
+
+       /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
+       adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+                             &adap->dev->i2c_adap);
+       if (adap->fe != NULL) {
+               state->tuner = DVB_PLL_THOMSON_DTT7579;
+               return 0;
+       }
+
+       /* connect demod on IO port D for TDA10023 & ZL10353 */
+       ret = anysee_write_reg(adap->dev, 0xb0, 0x25);
+       if (ret)
+               return ret;
+
+       /* Zarlink ZL10353 DVB-T demod inside of Samsung DNOS404ZH103A NIM */
+       adap->fe = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+                             &adap->dev->i2c_adap);
+       if (adap->fe != NULL) {
+               state->tuner = DVB_PLL_THOMSON_DTT7579;
+               return 0;
+       }
+
+       /* IO port E - E30C rev 0.4 board requires this */
+       ret = anysee_write_reg(adap->dev, 0xb1, 0xa7);
+       if (ret)
+               return ret;
+
+       /* Philips TDA10023 DVB-C demod */
+       adap->fe = dvb_attach(tda10023_attach, &anysee_tda10023_config,
+                             &adap->dev->i2c_adap, 0x48);
+       if (adap->fe != NULL) {
+               state->tuner = DVB_PLL_SAMSUNG_DTOS403IH102A;
+               return 0;
+       }
+
+       /* return IO port D to init value for safe */
+       ret = anysee_write_reg(adap->dev, 0xb0, io_d);
+       if (ret)
+               return ret;
+
+       err("Unkown Anysee version: %02x %02x %02x. "\
+           "Please report the <linux-dvb@linuxtv.org>.",
+           hw_info[0], hw_info[1], hw_info[2]);
+
+       return -ENODEV;
+}
+
+static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct anysee_state *state = adap->dev->priv;
+       deb_info("%s: \n", __func__);
+
+       switch (state->tuner) {
+       case DVB_PLL_THOMSON_DTT7579:
+               /* Thomson dtt7579 (not sure) PLL inside of:
+                  Samsung DNOS404ZH102A NIM
+                  Samsung DNOS404ZH103A NIM */
+               dvb_attach(dvb_pll_attach, adap->fe, 0x61,
+                          NULL, DVB_PLL_THOMSON_DTT7579);
+               break;
+       case DVB_PLL_SAMSUNG_DTOS403IH102A:
+               /* Unknown PLL inside of Samsung DTOS403IH102A tuner module */
+               dvb_attach(dvb_pll_attach, adap->fe, 0xc0,
+                          &adap->dev->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+               break;
+       }
+
+       return 0;
+}
+
+static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+       u8 buf[] = {CMD_GET_IR_CODE};
+       struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+       u8 ircode[2];
+       int i, ret;
+
+       ret = anysee_ctrl_msg(d, buf, sizeof(buf), &ircode[0], 2);
+       if (ret)
+               return ret;
+
+       *event = 0;
+       *state = REMOTE_NO_KEY_PRESSED;
+
+       for (i = 0; i < d->props.rc_key_map_size; i++) {
+               if (keymap[i].custom == ircode[0] &&
+                   keymap[i].data == ircode[1]) {
+                       *event = keymap[i].event;
+                       *state = REMOTE_KEY_PRESSED;
+                       return 0;
+               }
+       }
+       return 0;
+}
+
+static struct dvb_usb_rc_key anysee_rc_keys[] = {
+       { 0x01, 0x00, KEY_0 },
+       { 0x01, 0x01, KEY_1 },
+       { 0x01, 0x02, KEY_2 },
+       { 0x01, 0x03, KEY_3 },
+       { 0x01, 0x04, KEY_4 },
+       { 0x01, 0x05, KEY_5 },
+       { 0x01, 0x06, KEY_6 },
+       { 0x01, 0x07, KEY_7 },
+       { 0x01, 0x08, KEY_8 },
+       { 0x01, 0x09, KEY_9 },
+       { 0x01, 0x0a, KEY_POWER },
+       { 0x01, 0x0b, KEY_DOCUMENTS },    /* * */
+       { 0x01, 0x19, KEY_FAVORITES },
+       { 0x01, 0x20, KEY_SLEEP },
+       { 0x01, 0x21, KEY_MODE },         /* 4:3 / 16:9 select */
+       { 0x01, 0x22, KEY_ZOOM },
+       { 0x01, 0x47, KEY_TEXT },
+       { 0x01, 0x16, KEY_TV },           /* TV / radio select */
+       { 0x01, 0x1e, KEY_LANGUAGE },     /* Second Audio Program */
+       { 0x01, 0x1a, KEY_SUBTITLE },
+       { 0x01, 0x1b, KEY_CAMERA },       /* screenshot */
+       { 0x01, 0x42, KEY_MUTE },
+       { 0x01, 0x0e, KEY_MENU },
+       { 0x01, 0x0f, KEY_EPG },
+       { 0x01, 0x17, KEY_INFO },
+       { 0x01, 0x10, KEY_EXIT },
+       { 0x01, 0x13, KEY_VOLUMEUP },
+       { 0x01, 0x12, KEY_VOLUMEDOWN },
+       { 0x01, 0x11, KEY_CHANNELUP },
+       { 0x01, 0x14, KEY_CHANNELDOWN },
+       { 0x01, 0x15, KEY_OK },
+       { 0x01, 0x1d, KEY_RED },
+       { 0x01, 0x1f, KEY_GREEN },
+       { 0x01, 0x1c, KEY_YELLOW },
+       { 0x01, 0x44, KEY_BLUE },
+       { 0x01, 0x0c, KEY_SHUFFLE },      /* snapshot */
+       { 0x01, 0x48, KEY_STOP },
+       { 0x01, 0x50, KEY_PLAY },
+       { 0x01, 0x51, KEY_PAUSE },
+       { 0x01, 0x49, KEY_RECORD },
+       { 0x01, 0x18, KEY_PREVIOUS },     /* |<< */
+       { 0x01, 0x0d, KEY_NEXT },         /* >>| */
+       { 0x01, 0x24, KEY_PROG1 },        /* F1 */
+       { 0x01, 0x25, KEY_PROG2 },        /* F2 */
+};
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties anysee_properties;
+
+static int anysee_probe(struct usb_interface *intf,
+                       const struct usb_device_id *id)
+{
+       struct dvb_usb_device *d;
+       struct usb_host_interface *alt;
+       int ret;
+
+       mutex_init(&anysee_usb_mutex);
+
+       /* There is one interface with two alternate settings.
+          Alternate setting 0 is for bulk transfer.
+          Alternate setting 1 is for isochronous transfer.
+          We use bulk transfer (alternate setting 0). */
+       if (intf->num_altsetting < 1)
+               return -ENODEV;
+
+       ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d,
+               adapter_nr);
+       if (ret)
+               return ret;
+
+       alt = usb_altnum_to_altsetting(intf, 0);
+       if (alt == NULL) {
+               deb_info("%s: no alt found!\n", __func__);
+               return -ENODEV;
+       }
+
+       ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
+               alt->desc.bAlternateSetting);
+       if (ret)
+               return ret;
+
+       if (d)
+               ret = anysee_init(d);
+
+       return ret;
+}
+
+static struct usb_device_id anysee_table [] = {
+       { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) },
+       { USB_DEVICE(USB_VID_AMT,     USB_PID_ANYSEE) },
+       { }             /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, anysee_table);
+
+static struct dvb_usb_device_properties anysee_properties = {
+       .caps             = DVB_USB_IS_AN_I2C_ADAPTER,
+
+       .usb_ctrl         = DEVICE_SPECIFIC,
+
+       .size_of_priv     = sizeof(struct anysee_state),
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .streaming_ctrl   = anysee_streaming_ctrl,
+                       .frontend_attach  = anysee_frontend_attach,
+                       .tuner_attach     = anysee_tuner_attach,
+                       .stream = {
+                               .type = USB_BULK,
+                               .count = 8,
+                               .endpoint = 0x82,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 512,
+                                       }
+                               }
+                       },
+               }
+       },
+
+       .rc_key_map       = anysee_rc_keys,
+       .rc_key_map_size  = ARRAY_SIZE(anysee_rc_keys),
+       .rc_query         = anysee_rc_query,
+       .rc_interval      = 200,  /* windows driver uses 500ms */
+
+       .i2c_algo         = &anysee_i2c_algo,
+
+       .generic_bulk_ctrl_endpoint = 1,
+
+       .num_device_descs = 1,
+       .devices = {
+               {
+                       .name = "Anysee DVB USB2.0",
+                       .cold_ids = {NULL},
+                       .warm_ids = {&anysee_table[0],
+                                    &anysee_table[1], NULL},
+               },
+       }
+};
+
+static struct usb_driver anysee_driver = {
+       .name       = "dvb_usb_anysee",
+       .probe      = anysee_probe,
+       .disconnect = dvb_usb_device_exit,
+       .id_table   = anysee_table,
+};
+
+/* module stuff */
+static int __init anysee_module_init(void)
+{
+       int ret;
+
+       ret = usb_register(&anysee_driver);
+       if (ret)
+               err("%s: usb_register failed. Error number %d", __func__, ret);
+
+       return ret;
+}
+
+static void __exit anysee_module_exit(void)
+{
+       /* deregister this driver from the USB subsystem */
+       usb_deregister(&anysee_driver);
+}
+
+module_init(anysee_module_init);
+module_exit(anysee_module_exit);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h
new file mode 100644 (file)
index 0000000..7ca01ff
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    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.
+ *
+ * TODO:
+ * - add smart card reader support for Conditional Access (CA)
+ *
+ * Card reader in Anysee is nothing more than ISO 7816 card reader.
+ * There is no hardware CAM in any Anysee device sold.
+ * In my understanding it should be implemented by making own module
+ * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This
+ * module registers serial interface that can be used to communicate
+ * with any ISO 7816 smart card.
+ *
+ * Any help according to implement serial smart card reader support
+ * is highly welcome!
+ */
+
+#ifndef _DVB_USB_ANYSEE_H_
+#define _DVB_USB_ANYSEE_H_
+
+#define DVB_USB_LOG_PREFIX "anysee"
+#include "dvb-usb.h"
+
+#define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args)
+#define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args)
+#define deb_rc(args...)   dprintk(dvb_usb_anysee_debug, 0x04, args)
+#define deb_reg(args...)  dprintk(dvb_usb_anysee_debug, 0x08, args)
+#define deb_i2c(args...)  dprintk(dvb_usb_anysee_debug, 0x10, args)
+#define deb_fw(args...)   dprintk(dvb_usb_anysee_debug, 0x20, args)
+
+enum cmd {
+       CMD_I2C_READ            = 0x33,
+       CMD_I2C_WRITE           = 0x31,
+       CMD_REG_READ            = 0xb0,
+       CMD_REG_WRITE           = 0xb1,
+       CMD_STREAMING_CTRL      = 0x12,
+       CMD_LED_AND_IR_CTRL     = 0x16,
+       CMD_GET_IR_CODE         = 0x41,
+       CMD_GET_HW_INFO         = 0x19,
+       CMD_SMARTCARD           = 0x34,
+};
+
+struct anysee_state {
+       u8 tuner;
+       u8 seq;
+};
+
+#endif
+
+/***************************************************************************
+ * USB API description (reverse engineered)
+ ***************************************************************************
+
+Transaction flow:
+=================
+BULK[00001] >>> REQUEST PACKET 64 bytes
+BULK[00081] <<< REPLY PACKET #1 64 bytes (PREVIOUS TRANSACTION REPLY)
+BULK[00081] <<< REPLY PACKET #2 64 bytes (CURRENT TRANSACTION REPLY)
+
+General reply packet(s) are always used if not own reply defined.
+
+============================================================================
+| 00-63 | GENERAL REPLY PACKET #1 (PREVIOUS REPLY)
+============================================================================
+|    00 | reply data (if any) from previous transaction
+|       | Just same reply packet as returned during previous transaction.
+|       | Needed only if reply is missed in previous transaction.
+|       | Just skip normally.
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | GENERAL REPLY PACKET #2 (CURRENT REPLY)
+============================================================================
+|    00 | reply data (if any)
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | I2C WRITE REQUEST PACKET
+============================================================================
+|    00 | 0x31 I2C write command
+----------------------------------------------------------------------------
+|    01 | i2c address
+----------------------------------------------------------------------------
+|    02 | data length
+|       | 0x02 (for typical I2C reg / val pair)
+----------------------------------------------------------------------------
+|    03 | 0x01
+----------------------------------------------------------------------------
+| 04-   | data
+----------------------------------------------------------------------------
+|   -59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | I2C READ REQUEST PACKET
+============================================================================
+|    00 | 0x33 I2C read command
+----------------------------------------------------------------------------
+|    01 | i2c address + 1
+----------------------------------------------------------------------------
+|    02 | register
+----------------------------------------------------------------------------
+|    03 | 0x00
+----------------------------------------------------------------------------
+|    04 | 0x00
+----------------------------------------------------------------------------
+|    05 | 0x01
+----------------------------------------------------------------------------
+| 06-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | USB CONTROLLER REGISTER WRITE REQUEST PACKET
+============================================================================
+|    00 | 0xb1 register write command
+----------------------------------------------------------------------------
+| 01-02 | register
+----------------------------------------------------------------------------
+|    03 | 0x01
+----------------------------------------------------------------------------
+|    04 | value
+----------------------------------------------------------------------------
+| 05-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | USB CONTROLLER REGISTER READ REQUEST PACKET
+============================================================================
+|    00 | 0xb0 register read command
+----------------------------------------------------------------------------
+| 01-02 | register
+----------------------------------------------------------------------------
+|    03 | 0x01
+----------------------------------------------------------------------------
+| 04-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | LED CONTROL REQUEST PACKET
+============================================================================
+|    00 | 0x16 LED and IR control command
+----------------------------------------------------------------------------
+|    01 | 0x01 (LED)
+----------------------------------------------------------------------------
+|    03 | 0x00 blink
+|       | 0x01 lights continuously
+----------------------------------------------------------------------------
+|    04 | blink interval
+|       | 0x00 fastest (looks like LED lights continuously)
+|       | 0xff slowest
+----------------------------------------------------------------------------
+| 05-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | IR CONTROL REQUEST PACKET
+============================================================================
+|    00 | 0x16 LED and IR control command
+----------------------------------------------------------------------------
+|    01 | 0x02 (IR)
+----------------------------------------------------------------------------
+|    03 | 0x00 IR disabled
+|       | 0x01 IR enabled
+----------------------------------------------------------------------------
+| 04-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | STREAMING CONTROL REQUEST PACKET
+============================================================================
+|    00 | 0x12 streaming control command
+----------------------------------------------------------------------------
+|    01 | 0x00 streaming disabled
+|       | 0x01 streaming enabled
+----------------------------------------------------------------------------
+|    02 | 0x00
+----------------------------------------------------------------------------
+| 03-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | REMOTE CONTROL REQUEST PACKET
+============================================================================
+|    00 | 0x41 remote control command
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | REMOTE CONTROL REPLY PACKET
+============================================================================
+|    00 | 0x00 code not received
+|       | 0x01 code received
+----------------------------------------------------------------------------
+|    01 | remote control code
+----------------------------------------------------------------------------
+| 02-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | GET HARDWARE INFO REQUEST PACKET
+============================================================================
+|    00 | 0x19 get hardware info command
+----------------------------------------------------------------------------
+| 01-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | GET HARDWARE INFO REPLY PACKET
+============================================================================
+|    00 | hardware id
+----------------------------------------------------------------------------
+| 01-02 | firmware version
+----------------------------------------------------------------------------
+| 03-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+============================================================================
+| 00-63 | SMART CARD READER PACKET
+============================================================================
+|    00 | 0x34 smart card reader command
+----------------------------------------------------------------------------
+|    xx |
+----------------------------------------------------------------------------
+| xx-59 | don't care
+----------------------------------------------------------------------------
+|    60 | packet sequence number
+----------------------------------------------------------------------------
+| 61-63 | don't care
+----------------------------------------------------------------------------
+
+*/
index 2ccb90f..eb34cc3 100644 (file)
@@ -1,24 +1,31 @@
-/* DVB USB compliant linux driver for Sigmatek DVB-110 DVB-T USB2.0 receiver
+/*
+ * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0.
  *
  * Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
  *
- *     This program is free software; you can redistribute it and/or modify it
- *     under the terms of the GNU General Public License as published by the Free
- *     Software Foundation, version 2.
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
  *
- * see Documentation/dvb/README.dvb-usb for more information
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You 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 "au6610.h"
-
 #include "zl10353.h"
 #include "qt1010.h"
 
 /* debug */
 static int dvb_usb_au6610_debug;
 module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
-
+MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
@@ -42,9 +49,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
        }
 
        ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
-                             USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index, usb_buf,
-                             sizeof(usb_buf), AU6610_USB_TIMEOUT);
-
+                             USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index,
+                             usb_buf, sizeof(usb_buf), AU6610_USB_TIMEOUT);
        if (ret < 0)
                return ret;
 
@@ -116,15 +122,6 @@ static struct i2c_algorithm au6610_i2c_algo = {
 };
 
 /* Callbacks for DVB USB */
-static int au6610_identify_state(struct usb_device *udev,
-                                struct dvb_usb_device_properties *props,
-                                struct dvb_usb_device_description **desc,
-                                int *cold)
-{
-       *cold = 0;
-       return 0;
-}
-
 static struct zl10353_config au6610_zl10353_config = {
        .demod_address = 0x0f,
        .no_tuner = 1,
@@ -133,12 +130,12 @@ static struct zl10353_config au6610_zl10353_config = {
 
 static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       if ((adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
-                                  &adap->dev->i2c_adap)) != NULL) {
-               return 0;
-       }
+       adap->fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
+               &adap->dev->i2c_adap);
+       if (adap->fe == NULL)
+               return -ENODEV;
 
-       return -EIO;
+       return 0;
 }
 
 static struct qt1010_config au6610_qt1010_config = {
@@ -171,7 +168,7 @@ static int au6610_probe(struct usb_interface *intf,
                alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
 
                if (alt == NULL) {
-                       deb_rc("no alt found!\n");
+                       deb_info("%s: no alt found!\n", __func__);
                        return -ENODEV;
                }
                ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
@@ -181,18 +178,19 @@ static int au6610_probe(struct usb_interface *intf,
        return ret;
 }
 
-
 static struct usb_device_id au6610_table [] = {
        { USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) },
        { }             /* Terminating entry */
 };
-MODULE_DEVICE_TABLE (usb, au6610_table);
+MODULE_DEVICE_TABLE(usb, au6610_table);
 
 static struct dvb_usb_device_properties au6610_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
        .usb_ctrl = DEVICE_SPECIFIC,
-       .size_of_priv     = 0,
-       .identify_state   = au6610_identify_state,
+
+       .size_of_priv = 0,
+
        .num_adapters = 1,
        .adapter = {
                {
@@ -206,20 +204,22 @@ static struct dvb_usb_device_properties au6610_properties = {
                                .u = {
                                        .isoc = {
                                                .framesperurb = 40,
-                                               .framesize = 942,   /* maximum packet size */
-                                               .interval = 1.25,   /* 125 us */
+                                               .framesize = 942,
+                                               .interval = 1,
                                        }
                                }
                        },
                }
        },
+
        .i2c_algo = &au6610_i2c_algo,
+
        .num_device_descs = 1,
        .devices = {
                {
-                       "Sigmatek DVB-110 DVB-T USB2.0",
-                       { &au6610_table[0], NULL },
-                       { NULL },
+                       .name = "Sigmatek DVB-110 DVB-T USB2.0",
+                       .cold_ids = {NULL},
+                       .warm_ids = {&au6610_table[0], NULL},
                },
        }
 };
@@ -236,12 +236,11 @@ static int __init au6610_module_init(void)
 {
        int ret;
 
-       if ((ret = usb_register(&au6610_driver))) {
+       ret = usb_register(&au6610_driver);
+       if (ret)
                err("usb_register failed. Error number %d", ret);
-               return ret;
-       }
 
-       return 0;
+       return ret;
 }
 
 static void __exit au6610_module_exit(void)
@@ -250,10 +249,10 @@ static void __exit au6610_module_exit(void)
        usb_deregister(&au6610_driver);
 }
 
-module_init (au6610_module_init);
-module_exit (au6610_module_exit);
+module_init(au6610_module_init);
+module_exit(au6610_module_exit);
 
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Driver Sigmatek DVB-110 DVB-T USB2.0 / AU6610");
+MODULE_DESCRIPTION("Driver for Alcor Micro AU6610 DVB-T USB2.0");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
index 4161b05..7849abe 100644 (file)
@@ -1,10 +1,30 @@
+/*
+ * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0.
+ *
+ * Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    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 _DVB_USB_AU6610_H_
 #define _DVB_USB_AU6610_H_
 
 #define DVB_USB_LOG_PREFIX "au6610"
 #include "dvb-usb.h"
 
-#define deb_rc(args...)   dprintk(dvb_usb_au6610_debug,0x01,args)
+#define deb_info(args...)   dprintk(dvb_usb_au6610_debug, 0x01, args)
 
 #define AU6610_REQ_I2C_WRITE   0x14
 #define AU6610_REQ_I2C_READ    0x13
index 0286156..578afce 100644 (file)
@@ -35,6 +35,7 @@
 #include "zl10353.h"
 #include "tuner-xc2028.h"
 #include "tuner-simple.h"
+#include "mxl5005s.h"
 
 /* debug */
 static int dvb_usb_cxusb_debug;
@@ -43,9 +44,8 @@ MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_ST
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-#define deb_info(args...)   dprintk(dvb_usb_cxusb_debug,0x01,args)
-#define deb_i2c(args...)    if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
-                               dprintk(dvb_usb_cxusb_debug,0x01,args)
+#define deb_info(args...)   dprintk(dvb_usb_cxusb_debug, 0x03, args)
+#define deb_i2c(args...)    dprintk(dvb_usb_cxusb_debug, 0x02, args)
 
 static int cxusb_ctrl_msg(struct dvb_usb_device *d,
                          u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
@@ -202,6 +202,46 @@ static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
                return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
 }
 
+static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       int ret;
+       if (!onoff)
+               return cxusb_ctrl_msg(d, CMD_POWER_OFF, NULL, 0, NULL, 0);
+       if (d->state == DVB_USB_STATE_INIT &&
+           usb_set_interface(d->udev, 0, 0) < 0)
+               err("set interface failed");
+       do; while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
+                  !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) &&
+                  !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0);
+       if (!ret) {
+               /* FIXME: We don't know why, but we need to configure the
+                * lgdt3303 with the register settings below on resume */
+               int i;
+               u8 buf, bufs[] = {
+                       0x0e, 0x2, 0x00, 0x7f,
+                       0x0e, 0x2, 0x02, 0xfe,
+                       0x0e, 0x2, 0x02, 0x01,
+                       0x0e, 0x2, 0x00, 0x03,
+                       0x0e, 0x2, 0x0d, 0x40,
+                       0x0e, 0x2, 0x0e, 0x87,
+                       0x0e, 0x2, 0x0f, 0x8e,
+                       0x0e, 0x2, 0x10, 0x01,
+                       0x0e, 0x2, 0x14, 0xd7,
+                       0x0e, 0x2, 0x47, 0x88,
+               };
+               msleep(20);
+               for (i = 0; i < sizeof(bufs)/sizeof(u8); i += 4/sizeof(u8)) {
+                       ret = cxusb_ctrl_msg(d, CMD_I2C_WRITE,
+                                            bufs+i, 4, &buf, 1);
+                       if (ret)
+                               break;
+                       if (buf != 0x8)
+                               return -EREMOTEIO;
+               }
+       }
+       return ret;
+}
+
 static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
        u8 b = 0;
@@ -233,6 +273,16 @@ static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
        return 0;
 }
 
+static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+       if (onoff)
+               cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_ON, NULL, 0, NULL, 0);
+       else
+               cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_OFF,
+                              NULL, 0, NULL, 0);
+       return 0;
+}
+
 static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
        struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
@@ -423,6 +473,12 @@ static struct lgdt330x_config cxusb_lgdt3303_config = {
        .demod_chip    = LGDT3303,
 };
 
+static struct lgdt330x_config cxusb_aver_lgdt3303_config = {
+       .demod_address       = 0x0e,
+       .demod_chip          = LGDT3303,
+       .clock_polarity_flip = 2,
+};
+
 static struct mt352_config cxusb_dee1601_config = {
        .demod_address = 0x0f,
        .demod_init    = cxusb_dee1601_demod_init,
@@ -453,6 +509,24 @@ static struct mt352_config cxusb_mt352_xc3028_config = {
        .demod_init = cxusb_mt352_demod_init,
 };
 
+/* FIXME: needs tweaking */
+static struct mxl5005s_config aver_a868r_tuner = {
+       .i2c_address     = 0x63,
+       .if_freq         = 6000000UL,
+       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
+       .agc_mode        = MXL_SINGLE_AGC,
+       .tracking_filter = MXL_TF_C,
+       .rssi_enable     = MXL_RSSI_ENABLE,
+       .cap_select      = MXL_CAP_SEL_ENABLE,
+       .div_out         = MXL_DIV_OUT_4,
+       .clock_out       = MXL_CLOCK_OUT_DISABLE,
+       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+       .top             = MXL5005S_TOP_25P2,
+       .mod_mode        = MXL_DIGITAL_MODE,
+       .if_mode         = MXL_ZERO_IF,
+       .AgcMasterByte   = 0x00,
+};
+
 /* Callbacks for DVB USB */
 static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
 {
@@ -533,6 +607,13 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
        return 0;
 }
 
+static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       dvb_attach(mxl5005s_attach, adap->fe,
+                  &adap->dev->i2c_adap, &aver_a868r_tuner);
+       return 0;
+}
+
 static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
 {
        u8 b;
@@ -562,6 +643,16 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
        return -EIO;
 }
 
+static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       adap->fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
+                             &adap->dev->i2c_adap);
+       if (adap->fe != NULL)
+               return 0;
+
+       return -EIO;
+}
+
 static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 {
        /* used in both lgz201 and th7579 */
@@ -736,6 +827,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
 static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
 static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
 static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
+static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
 
 static int cxusb_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
@@ -756,7 +848,10 @@ static int cxusb_probe(struct usb_interface *intf,
                                     THIS_MODULE, NULL, adapter_nr) ||
            0 == dvb_usb_device_init(intf,
                                &cxusb_bluebird_nano2_needsfirmware_properties,
-                                    THIS_MODULE, NULL, adapter_nr))
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties,
+                                    THIS_MODULE, NULL, adapter_nr) ||
+           0)
                return 0;
 
        return -EINVAL;
@@ -779,6 +874,7 @@ static struct usb_device_id cxusb_table [] = {
        { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
        { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
        { USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
+       { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) },
        {}              /* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -1182,6 +1278,48 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
        }
 };
 
+static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+       .usb_ctrl         = CYPRESS_FX2,
+
+       .size_of_priv     = sizeof(struct cxusb_state),
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .streaming_ctrl   = cxusb_aver_streaming_ctrl,
+                       .frontend_attach  = cxusb_aver_lgdt3303_frontend_attach,
+                       .tuner_attach     = cxusb_mxl5003s_tuner_attach,
+                       /* parameter for the MPEG2-data transfer */
+                       .stream = {
+                               .type = USB_BULK,
+                               .count = 5,
+                               .endpoint = 0x04,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 8192,
+                                       }
+                               }
+                       },
+
+               },
+       },
+       .power_ctrl       = cxusb_aver_power_ctrl,
+
+       .i2c_algo         = &cxusb_i2c_algo,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       .num_device_descs = 1,
+       .devices = {
+               {   "AVerMedia AVerTVHD Volar (A868R)",
+                       { NULL },
+                       { &cxusb_table[16], NULL },
+               },
+       }
+};
+
 static struct usb_driver cxusb_driver = {
        .name           = "dvb_usb_cxusb",
        .probe          = cxusb_probe,
index 4768a2c..1a51eaf 100644 (file)
@@ -20,6 +20,9 @@
 #define CMD_STREAMING_ON  0x36
 #define CMD_STREAMING_OFF 0x37
 
+#define CMD_AVER_STREAM_ON  0x18
+#define CMD_AVER_STREAM_OFF 0x19
+
 #define CMD_GET_IR_CODE   0x47
 
 #define CMD_ANALOG        0x50
index c4d40fe..3dd20bf 100644 (file)
@@ -1117,6 +1117,7 @@ struct usb_device_id dib0700_usb_id_table[] = {
        { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_HT_EXPRESS) },
        { USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_T_XXS) },
        { USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
+       { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) },
        { 0 }           /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1372,7 +1373,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        }
                },
 
-               .num_device_descs = 2,
+               .num_device_descs = 3,
                .devices = {
                        {   "DiBcom STK7070PD reference design",
                                { &dib0700_usb_id_table[17], NULL },
@@ -1381,6 +1382,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
                        {   "Pinnacle PCTV Dual DVB-T Diversity Stick",
                                { &dib0700_usb_id_table[18], NULL },
                                { NULL },
+                       },
+                       {   "Hauppauge Nova-TD Stick (52009)",
+                               { &dib0700_usb_id_table[35], NULL },
+                               { NULL },
                        }
                }
        }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
index 23428cd..326f760 100644 (file)
@@ -20,11 +20,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
        }
 
        strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
-       d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
-#else
        d->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
-#endif
        d->i2c_adap.algo      = d->props.i2c_algo;
        d->i2c_adap.algo_data = NULL;
        d->i2c_adap.dev.parent = &d->udev->dev;
index 34245d1..e5238b3 100644 (file)
@@ -14,6 +14,7 @@
 #define USB_VID_AFATECH                                0x15a4
 #define USB_VID_ALCOR_MICRO                    0x058f
 #define USB_VID_ALINK                          0x05e3
+#define USB_VID_AMT                            0x1c73
 #define USB_VID_ANCHOR                         0x0547
 #define USB_VID_ANSONIC                                0x10b9
 #define USB_VID_ANUBIS_ELECTRONIC              0x10fd
@@ -57,6 +58,7 @@
 #define USB_PID_AFATECH_AF9005                         0x9020
 #define USB_VID_ALINK_DTU                              0xf170
 #define USB_PID_ANSONIC_DVBT_USB                       0x6000
+#define USB_PID_ANYSEE                                 0x861f
 #define USB_PID_AVERMEDIA_DVBT_USB_COLD                        0x0001
 #define USB_PID_AVERMEDIA_DVBT_USB_WARM                        0x0002
 #define USB_PID_AVERMEDIA_DVBT_USB2_COLD               0xa800
 #define USB_PID_HAUPPAUGE_NOVA_T_STICK_3               0x7070
 #define USB_PID_HAUPPAUGE_MYTV_T                       0x7080
 #define USB_PID_HAUPPAUGE_NOVA_TD_STICK                        0x9580
+#define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009          0x5200
 #define USB_PID_AVERMEDIA_EXPRESS                      0xb568
 #define USB_PID_AVERMEDIA_VOLAR                                0xa807
 #define USB_PID_AVERMEDIA_VOLAR_2                      0xb808
+#define USB_PID_AVERMEDIA_VOLAR_A868R                  0xa868
+#define USB_PID_AVERMEDIA_MCE_USB_M038                 0x1228
+#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R       0x0039
+#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC  0x1039
+#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT  0x2039
 #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY       0x005a
 #define USB_PID_TERRATEC_CINERGY_HT_USB_XE             0x0058
index 037f7ff..6f596ed 100644 (file)
@@ -1,8 +1,8 @@
 /* DVB USB compliant linux driver for GL861 USB2.0 devices.
  *
  *     This program is free software; you can redistribute it and/or modify it
- *     under the terms of the GNU General Public License as published by the Free
- *     Software Foundation, version 2.
+ *     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
  */
@@ -13,9 +13,9 @@
 
 /* debug */
 static int dvb_usb_gl861_debug;
-module_param_named(debug,dvb_usb_gl861_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
-
+module_param_named(debug, dvb_usb_gl861_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))."
+       DVB_USB_DEBUG_STATUS);
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
@@ -70,7 +70,7 @@ static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                /* write/read request */
                if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
                        if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
-                                         msg[i].len, msg[i+1].buf, msg[i+1].len) < 0)
+                               msg[i].len, msg[i+1].buf, msg[i+1].len) < 0)
                                break;
                        i++;
                } else
@@ -102,12 +102,13 @@ static struct zl10353_config gl861_zl10353_config = {
 
 static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       if ((adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
-                                  &adap->dev->i2c_adap)) != NULL) {
-               return 0;
-       }
 
-       return -EIO;
+       adap->fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
+               &adap->dev->i2c_adap);
+       if (adap->fe == NULL)
+               return -EIO;
+
+       return 0;
 }
 
 static struct qt1010_config gl861_qt1010_config = {
@@ -156,7 +157,7 @@ static struct usb_device_id gl861_table [] = {
                { USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) },
                { }             /* Terminating entry */
 };
-MODULE_DEVICE_TABLE (usb, gl861_table);
+MODULE_DEVICE_TABLE(usb, gl861_table);
 
 static struct dvb_usb_device_properties gl861_properties = {
        .caps = DVB_USB_IS_AN_I2C_ADAPTER,
@@ -180,7 +181,7 @@ static struct dvb_usb_device_properties gl861_properties = {
                                }
                        }
                },
-       }},
+       } },
        .i2c_algo         = &gl861_i2c_algo,
 
        .num_device_descs = 2,
@@ -210,12 +211,11 @@ static int __init gl861_module_init(void)
 {
        int ret;
 
-       if ((ret = usb_register(&gl861_driver))) {
+       ret = usb_register(&gl861_driver);
+       if (ret)
                err("usb_register failed. Error number %d", ret);
-               return ret;
-       }
 
-       return 0;
+       return ret;
 }
 
 static void __exit gl861_module_exit(void)
@@ -224,8 +224,8 @@ static void __exit gl861_module_exit(void)
        usb_deregister(&gl861_driver);
 }
 
-module_init (gl861_module_init);
-module_exit (gl861_module_exit);
+module_init(gl861_module_init);
+module_exit(gl861_module_exit);
 
 MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>");
 MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861");
index 72a51af..c54855e 100644 (file)
@@ -4,7 +4,7 @@
 #define DVB_USB_LOG_PREFIX "gl861"
 #include "dvb-usb.h"
 
-#define deb_rc(args...)   dprintk(dvb_usb_gl861_debug,0x01,args)
+#define deb_rc(args...)   dprintk(dvb_usb_gl861_debug, 0x01, args)
 
 #define GL861_WRITE            0x40
 #define GL861_READ             0xc0
index 03900d2..f7b7165 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include "dvb_frontend.h"
-#include "dvb-pll.h"
 #include "au8522.h"
 
 struct au8522_state {
index a054894..ea05815 100644 (file)
@@ -343,6 +343,52 @@ static struct dvb_pll_desc dvb_pll_opera1 = {
        }
 };
 
+static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf,
+                      const struct dvb_frontend_parameters *params)
+{
+       struct dvb_pll_priv *priv = fe->tuner_priv;
+       struct i2c_msg msg = {
+               .addr = priv->pll_i2c_address,
+               .flags = 0,
+               .buf = buf,
+               .len = 4
+       };
+       int result;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       result = i2c_transfer(priv->i2c, &msg, 1);
+       if (result != 1)
+               printk(KERN_ERR "%s: i2c_transfer failed:%d",
+                       __func__, result);
+
+       buf[2] = 0x9e;
+       buf[3] = 0x90;
+
+       return;
+}
+
+/* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
+static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
+       .name   = "Samsung DTOS403IH102A",
+       .min    =  44250000,
+       .max    = 858000000,
+       .iffreq =  36125000,
+       .count  = 8,
+       .set    = samsung_dtos403ih102a_set,
+       .entries = {
+               { 135000000, 62500, 0xbe, 0x01 },
+               { 177000000, 62500, 0xf6, 0x01 },
+               { 370000000, 62500, 0xbe, 0x02 },
+               { 450000000, 62500, 0xf6, 0x02 },
+               { 466000000, 62500, 0xfe, 0x02 },
+               { 538000000, 62500, 0xbe, 0x08 },
+               { 826000000, 62500, 0xf6, 0x08 },
+               { 999999999, 62500, 0xfe, 0x08 },
+       }
+};
+
 /* ----------------------------------------------------------- */
 
 static struct dvb_pll_desc *pll_list[] = {
@@ -360,6 +406,7 @@ static struct dvb_pll_desc *pll_list[] = {
        [DVB_PLL_SAMSUNG_TBMV]           = &dvb_pll_samsung_tbmv,
        [DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
        [DVB_PLL_OPERA1]                 = &dvb_pll_opera1,
+       [DVB_PLL_SAMSUNG_DTOS403IH102A]  = &dvb_pll_samsung_dtos403ih102a,
 };
 
 /* ----------------------------------------------------------- */
index 872ca29..05239f5 100644 (file)
@@ -22,6 +22,7 @@
 #define DVB_PLL_SAMSUNG_TBMV           11
 #define DVB_PLL_PHILIPS_SD1878_TDA8261 12
 #define DVB_PLL_OPERA1                 13
+#define DVB_PLL_SAMSUNG_DTOS403IH102A  14
 
 /**
  * Attach a dvb-pll to the supplied frontend structure.
index f0195c8..056387b 100644 (file)
@@ -226,11 +226,16 @@ static int lgdt330x_init(struct dvb_frontend* fe)
                0x4c, 0x14
        };
 
-       static u8 flip_lgdt3303_init_data[] = {
+       static u8 flip_1_lgdt3303_init_data[] = {
                0x4c, 0x14,
                0x87, 0xf3
        };
 
+       static u8 flip_2_lgdt3303_init_data[] = {
+               0x4c, 0x14,
+               0x87, 0xda
+       };
+
        struct lgdt330x_state* state = fe->demodulator_priv;
        char  *chip_name;
        int    err;
@@ -243,10 +248,19 @@ static int lgdt330x_init(struct dvb_frontend* fe)
                break;
        case LGDT3303:
                chip_name = "LGDT3303";
-               if (state->config->clock_polarity_flip) {
-                       err = i2c_write_demod_bytes(state, flip_lgdt3303_init_data,
-                                                   sizeof(flip_lgdt3303_init_data));
-               } else {
+               switch (state->config->clock_polarity_flip) {
+               case 2:
+                       err = i2c_write_demod_bytes(state,
+                                       flip_2_lgdt3303_init_data,
+                                       sizeof(flip_2_lgdt3303_init_data));
+                       break;
+               case 1:
+                       err = i2c_write_demod_bytes(state,
+                                       flip_1_lgdt3303_init_data,
+                                       sizeof(flip_1_lgdt3303_init_data));
+                       break;
+               case 0:
+               default:
                        err = i2c_write_demod_bytes(state, lgdt3303_init_data,
                                                    sizeof(lgdt3303_init_data));
                }
index b999ec4..5ddb2dc 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include "dvb_frontend.h"
-#include "dvb-pll.h"
 #include "s5h1409.h"
 
 struct s5h1409_state {
index eb5bfc9..cff360c 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include "dvb_frontend.h"
-#include "dvb-pll.h"
 #include "s5h1411.h"
 
 struct s5h1411_state {
index c6ff5b8..a3c34ee 100644 (file)
 #include "dvb_frontend.h"
 #include "tda1002x.h"
 
+#define REG0_INIT_VAL 0x23
 
 struct tda10023_state {
        struct i2c_adapter* i2c;
        /* configuration settings */
-       const struct tda1002x_config* config;
+       const struct tda10023_config *config;
        struct dvb_frontend frontend;
 
        u8 pwm;
        u8 reg0;
-};
 
+       /* clock settings */
+       u32 xtal;
+       u8 pll_m;
+       u8 pll_p;
+       u8 pll_n;
+       u32 sysclk;
+};
 
 #define dprintk(x...)
 
 static int verbose;
 
-#define XTAL   28920000UL
-#define PLL_M  8UL
-#define PLL_P  4UL
-#define PLL_N  1UL
-#define SYSCLK (XTAL*PLL_M/(PLL_N*PLL_P))  // -> 57840000
-
-static u8 tda10023_inittab[]={
-       // reg mask val
-       0x2a,0xff,0x02,  // PLL3, Bypass, Power Down
-       0xff,0x64,0x00,  // Sleep 100ms
-       0x2a,0xff,0x03,  // PLL3, Bypass, Power Down
-       0xff,0x64,0x00,  // Sleep 100ms
-       0x28,0xff,PLL_M-1,  // PLL1 M=8
-       0x29,0xff,((PLL_P-1)<<6)|(PLL_N-1),  // PLL2
-       0x00,0xff,0x23,  // GPR FSAMPLING=1
-       0x2a,0xff,0x08,  // PLL3 PSACLK=1
-       0xff,0x64,0x00,  // Sleep 100ms
-       0x1f,0xff,0x00,  // RESET
-       0xff,0x64,0x00,  // Sleep 100ms
-       0xe6,0x0c,0x04,  // RSCFG_IND
-       0x10,0xc0,0x80,  // DECDVBCFG1 PBER=1
-
-       0x0e,0xff,0x82,  // GAIN1
-       0x03,0x08,0x08,  // CLKCONF DYN=1
-       0x2e,0xbf,0x30,  // AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1 PPWMTUN=0 PPWMIF=0
-       0x01,0xff,0x30,  // AGCREF
-       0x1e,0x84,0x84,  // CONTROL SACLK_ON=1
-       0x1b,0xff,0xc8,  // ADC TWOS=1
-       0x3b,0xff,0xff,  // IFMAX
-       0x3c,0xff,0x00,  // IFMIN
-       0x34,0xff,0x00,  // PWMREF
-       0x35,0xff,0xff,  // TUNMAX
-       0x36,0xff,0x00,  // TUNMIN
-       0x06,0xff,0x7f,  // EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1    // 0x77
-       0x1c,0x30,0x30,  // EQCONF2 STEPALGO=SGNALGO=1
-       0x37,0xff,0xf6,  // DELTAF_LSB
-       0x38,0xff,0xff,  // DELTAF_MSB
-       0x02,0xff,0x93,  // AGCCONF1  IFS=1 KAGCIF=2 KAGCTUN=3
-       0x2d,0xff,0xf6,  // SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2
-       0x04,0x10,0x00,   // SWRAMP=1
-       0x12,0xff,0xa1,  // INTP1 POCLKP=1 FEL=1 MFS=0
-       0x2b,0x01,0xa1,  // INTS1
-       0x20,0xff,0x04,  // INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=?
-       0x2c,0xff,0x0d,  // INTP/S TRIP=0 TRIS=0
-       0xc4,0xff,0x00,
-       0xc3,0x30,0x00,
-       0xb5,0xff,0x19,  // ERAGC_THD
-       0x00,0x03,0x01,  // GPR, CLBS soft reset
-       0x00,0x03,0x03,  // GPR, CLBS soft reset
-       0xff,0x64,0x00,  // Sleep 100ms
-       0xff,0xff,0xff
-};
-
 static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
 {
        u8 b0 [] = { reg };
@@ -219,30 +173,34 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
        s16 SFIL=0;
        u16 NDEC = 0;
 
-       if (sr < (u32)(SYSCLK/98.40)) {
+       /* avoid floating point operations multiplying syscloc and divider
+          by 10 */
+       u32 sysclk_x_10 = state->sysclk * 10;
+
+       if (sr < (u32)(sysclk_x_10/984)) {
                NDEC=3;
                SFIL=1;
-       } else if (sr<(u32)(SYSCLK/64.0)) {
+       } else if (sr < (u32)(sysclk_x_10/640)) {
                NDEC=3;
                SFIL=0;
-       } else if (sr<(u32)(SYSCLK/49.2)) {
+       } else if (sr < (u32)(sysclk_x_10/492)) {
                NDEC=2;
                SFIL=1;
-       } else if (sr<(u32)(SYSCLK/32.0)) {
+       } else if (sr < (u32)(sysclk_x_10/320)) {
                NDEC=2;
                SFIL=0;
-       } else if (sr<(u32)(SYSCLK/24.6)) {
+       } else if (sr < (u32)(sysclk_x_10/246)) {
                NDEC=1;
                SFIL=1;
-       } else if (sr<(u32)(SYSCLK/16.0)) {
+       } else if (sr < (u32)(sysclk_x_10/160)) {
                NDEC=1;
                SFIL=0;
-       } else if (sr<(u32)(SYSCLK/12.3)) {
+       } else if (sr < (u32)(sysclk_x_10/123)) {
                NDEC=0;
                SFIL=1;
        }
 
-       BDRI=SYSCLK*16;
+       BDRI = (state->sysclk)*16;
        BDRI>>=NDEC;
        BDRI +=sr/2;
        BDRI /=sr;
@@ -255,11 +213,12 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
 
                BDRX=1<<(24+NDEC);
                BDRX*=sr;
-               do_div(BDRX,SYSCLK);    // BDRX/=SYSCLK;
+               do_div(BDRX, state->sysclk);    /* BDRX/=SYSCLK; */
 
                BDR=(s32)BDRX;
        }
-//     printk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",sr,BDR,BDRI,NDEC);
+       dprintk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",
+               sr, BDR, BDRI, NDEC);
        tda10023_writebit (state, 0x03, 0xc0, NDEC<<6);
        tda10023_writereg (state, 0x0a, BDR&255);
        tda10023_writereg (state, 0x0b, (BDR>>8)&255);
@@ -272,8 +231,67 @@ static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
 static int tda10023_init (struct dvb_frontend *fe)
 {
        struct tda10023_state* state = fe->demodulator_priv;
+       u8 tda10023_inittab[] = {
+/*        reg  mask val */
+/* 000 */ 0x2a, 0xff, 0x02,  /* PLL3, Bypass, Power Down */
+/* 003 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
+/* 006 */ 0x2a, 0xff, 0x03,  /* PLL3, Bypass, Power Down */
+/* 009 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
+                          /* PLL1 */
+/* 012 */ 0x28, 0xff, (state->pll_m-1),
+                          /* PLL2 */
+/* 015 */ 0x29, 0xff, ((state->pll_p-1)<<6)|(state->pll_n-1),
+                          /* GPR FSAMPLING=1 */
+/* 018 */ 0x00, 0xff, REG0_INIT_VAL,
+/* 021 */ 0x2a, 0xff, 0x08,  /* PLL3 PSACLK=1 */
+/* 024 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
+/* 027 */ 0x1f, 0xff, 0x00,  /* RESET */
+/* 030 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
+/* 033 */ 0xe6, 0x0c, 0x04,  /* RSCFG_IND */
+/* 036 */ 0x10, 0xc0, 0x80,  /* DECDVBCFG1 PBER=1 */
+
+/* 039 */ 0x0e, 0xff, 0x82,  /* GAIN1 */
+/* 042 */ 0x03, 0x08, 0x08,  /* CLKCONF DYN=1 */
+/* 045 */ 0x2e, 0xbf, 0x30,  /* AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1
+                                      PPWMTUN=0 PPWMIF=0 */
+/* 048 */ 0x01, 0xff, 0x30,  /* AGCREF */
+/* 051 */ 0x1e, 0x84, 0x84,  /* CONTROL SACLK_ON=1 */
+/* 054 */ 0x1b, 0xff, 0xc8,  /* ADC TWOS=1 */
+/* 057 */ 0x3b, 0xff, 0xff,  /* IFMAX */
+/* 060 */ 0x3c, 0xff, 0x00,  /* IFMIN */
+/* 063 */ 0x34, 0xff, 0x00,  /* PWMREF */
+/* 066 */ 0x35, 0xff, 0xff,  /* TUNMAX */
+/* 069 */ 0x36, 0xff, 0x00,  /* TUNMIN */
+/* 072 */ 0x06, 0xff, 0x7f,  /* EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 */
+/* 075 */ 0x1c, 0x30, 0x30,  /* EQCONF2 STEPALGO=SGNALGO=1 */
+/* 078 */ 0x37, 0xff, 0xf6,  /* DELTAF_LSB */
+/* 081 */ 0x38, 0xff, 0xff,  /* DELTAF_MSB */
+/* 084 */ 0x02, 0xff, 0x93,  /* AGCCONF1  IFS=1 KAGCIF=2 KAGCTUN=3 */
+/* 087 */ 0x2d, 0xff, 0xf6,  /* SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2 */
+/* 090 */ 0x04, 0x10, 0x00,  /* SWRAMP=1 */
+/* 093 */ 0x12, 0xff, TDA10023_OUTPUT_MODE_PARALLEL_B, /*
+                               INTP1 POCLKP=1 FEL=1 MFS=0 */
+/* 096 */ 0x2b, 0x01, 0xa1,  /* INTS1 */
+/* 099 */ 0x20, 0xff, 0x04,  /* INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=? */
+/* 102 */ 0x2c, 0xff, 0x0d,  /* INTP/S TRIP=0 TRIS=0 */
+/* 105 */ 0xc4, 0xff, 0x00,
+/* 108 */ 0xc3, 0x30, 0x00,
+/* 111 */ 0xb5, 0xff, 0x19,  /* ERAGC_THD */
+/* 114 */ 0x00, 0x03, 0x01,  /* GPR, CLBS soft reset */
+/* 117 */ 0x00, 0x03, 0x03,  /* GPR, CLBS soft reset */
+/* 120 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
+/* 123 */ 0xff, 0xff, 0xff
+};
+       dprintk("DVB: TDA10023(%d): init chip\n", fe->dvb->num);
+
+       /* override default values if set in config */
+       if (state->config->deltaf) {
+               tda10023_inittab[80] = (state->config->deltaf & 0xff);
+               tda10023_inittab[83] = (state->config->deltaf >> 8);
+       }
 
-       dprintk("DVB: TDA10023(%d): init chip\n", fe->adapter->num);
+       if (state->config->output_mode)
+               tda10023_inittab[95] = state->config->output_mode;
 
        tda10023_writetab(state, tda10023_inittab);
 
@@ -460,12 +478,11 @@ static void tda10023_release(struct dvb_frontend* fe)
 
 static struct dvb_frontend_ops tda10023_ops;
 
-struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
-                                    struct i2c_adapteri2c,
+struct dvb_frontend *tda10023_attach(const struct tda10023_config *config,
+                                    struct i2c_adapter *i2c,
                                     u8 pwm)
 {
        struct tda10023_state* state = NULL;
-       int i;
 
        /* allocate memory for the internal state */
        state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL);
@@ -474,22 +491,40 @@ struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
-       state->pwm = pwm;
-       for (i=0; i < ARRAY_SIZE(tda10023_inittab);i+=3) {
-               if (tda10023_inittab[i] == 0x00) {
-                       state->reg0 = tda10023_inittab[i+2];
-                       break;
-               }
-       }
 
-       // Wakeup if in standby
+       /* wakeup if in standby */
        tda10023_writereg (state, 0x00, 0x33);
        /* check if the demod is there */
        if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
 
        /* create dvb_frontend */
        memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
+       state->pwm = pwm;
+       state->reg0 = REG0_INIT_VAL;
+       if (state->config->xtal) {
+               state->xtal  = state->config->xtal;
+               state->pll_m = state->config->pll_m;
+               state->pll_p = state->config->pll_p;
+               state->pll_n = state->config->pll_n;
+       } else {
+               /* set default values if not defined in config */
+               state->xtal  = 28920000;
+               state->pll_m = 8;
+               state->pll_p = 4;
+               state->pll_n = 1;
+       }
+
+       /* calc sysclk */
+       state->sysclk = (state->xtal * state->pll_m / \
+                       (state->pll_n * state->pll_p));
+
+       state->frontend.ops.info.symbol_rate_min = (state->sysclk/2)/64;
+       state->frontend.ops.info.symbol_rate_max = (state->sysclk/2)/4;
+
+       dprintk("DVB: TDA10023 %s: xtal:%d pll_m:%d pll_p:%d pll_n:%d\n",
+               __func__, state->xtal, state->pll_m, state->pll_p,
+               state->pll_n);
+
        state->frontend.demodulator_priv = state;
        return &state->frontend;
 
@@ -504,10 +539,10 @@ static struct dvb_frontend_ops tda10023_ops = {
                .name = "Philips TDA10023 DVB-C",
                .type = FE_QAM,
                .frequency_stepsize = 62500,
-               .frequency_min = 47000000,
+               .frequency_min =  47000000,
                .frequency_max = 862000000,
-               .symbol_rate_min = (SYSCLK/2)/64,     /* SACLK/64 == (SYSCLK/2)/64 */
-               .symbol_rate_max = (SYSCLK/2)/4,      /* SACLK/4 */
+               .symbol_rate_min = 0,  /* set in tda10023_attach */
+               .symbol_rate_max = 0,  /* set in tda10023_attach */
                .caps = 0x400 | //FE_CAN_QAM_4
                        FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
                        FE_CAN_QAM_128 | FE_CAN_QAM_256 |
index 1bcc0d4..04d1941 100644 (file)
 
 #include <linux/dvb/frontend.h>
 
-struct tda1002x_config
-{
+struct tda1002x_config {
        /* the demodulator's i2c address */
        u8 demod_address;
        u8 invert;
 };
 
+enum tda10023_output_mode {
+       TDA10023_OUTPUT_MODE_PARALLEL_A = 0xe0,
+       TDA10023_OUTPUT_MODE_PARALLEL_B = 0xa1,
+       TDA10023_OUTPUT_MODE_PARALLEL_C = 0xa0,
+       TDA10023_OUTPUT_MODE_SERIAL, /* TODO: not implemented */
+};
+
+struct tda10023_config {
+       /* the demodulator's i2c address */
+       u8 demod_address;
+       u8 invert;
+
+       /* clock settings */
+       u32 xtal; /* defaults: 28920000 */
+       u8 pll_m; /* defaults: 8 */
+       u8 pll_p; /* defaults: 4 */
+       u8 pll_n; /* defaults: 1 */
+
+       /* MPEG2 TS output mode */
+       u8 output_mode;
+
+       /* input freq offset + baseband conversion type */
+       u16 deltaf;
+};
+
 #if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE))
 extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
                                            struct i2c_adapter* i2c, u8 pwm);
@@ -45,12 +69,15 @@ static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config*
 }
 #endif // CONFIG_DVB_TDA10021
 
-#if defined(CONFIG_DVB_TDA10023) || (defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE))
-extern struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
-                                           struct i2c_adapter* i2c, u8 pwm);
+#if defined(CONFIG_DVB_TDA10023) || \
+       (defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10023_attach(
+       const struct tda10023_config *config,
+       struct i2c_adapter *i2c, u8 pwm);
 #else
-static inline struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config,
-                                           struct i2c_adapter* i2c, u8 pwm)
+static inline struct dvb_frontend *tda10023_attach(
+       const struct tda10023_config *config,
+       struct i2c_adapter *i2c, u8 pwm)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
index 960ed57..1360403 100644 (file)
@@ -234,7 +234,7 @@ static void pluto_reset_ts(struct pluto *pluto, int reenable)
 
 static void pluto_set_dma_addr(struct pluto *pluto)
 {
-       pluto_writereg(pluto, REG_PCAR, cpu_to_le32(pluto->dma_addr));
+       pluto_writereg(pluto, REG_PCAR, pluto->dma_addr);
 }
 
 static int __devinit pluto_dma_map(struct pluto *pluto)
diff --git a/drivers/media/dvb/siano/Kconfig b/drivers/media/dvb/siano/Kconfig
new file mode 100644 (file)
index 0000000..dd863f2
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# Siano Mobile Silicon Digital TV device configuration
+#
+
+config DVB_SIANO_SMS1XXX
+       tristate "Siano SMS1XXX USB dongle support"
+       depends on DVB_CORE && USB
+       ---help---
+         Choose Y here if you have a USB dongle with a SMS1XXX chipset.
+
+         To compile this driver as a module, choose M here: the
+         module will be called sms1xxx.
+
+config DVB_SIANO_SMS1XXX_SMS_IDS
+       bool "Enable support for Siano Mobile Silicon default USB IDs"
+       depends on DVB_SIANO_SMS1XXX
+       default y
+       ---help---
+         Choose Y here if you have a USB dongle with a SMS1XXX chipset
+         that uses Siano Mobile Silicon's default usb vid:pid.
+
+         Choose N here if you would prefer to use Siano's external driver.
+
+         Further documentation on this driver can be found on the WWW at
+         <http://www.siano-ms.com/>.
+
diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile
new file mode 100644 (file)
index 0000000..ee0737a
--- /dev/null
@@ -0,0 +1,8 @@
+sms1xxx-objs := smscoreapi.o smsusb.o smsdvb.o sms-cards.o
+
+obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
+
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
new file mode 100644 (file)
index 0000000..e7a8ac0
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *  Card-specific functions for the Siano SMS1xxx USB dongle
+ *
+ *  Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation;
+ *
+ *  Software distributed under the License is distributed on an "AS IS"
+ *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ *  See the GNU General Public License for more details.
+ *
+ *  You 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 "sms-cards.h"
+
+struct usb_device_id smsusb_id_table[] = {
+#ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS
+       { USB_DEVICE(0x187f, 0x0010),
+               .driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
+       { USB_DEVICE(0x187f, 0x0100),
+               .driver_info = SMS1XXX_BOARD_SIANO_STELLAR },
+       { USB_DEVICE(0x187f, 0x0200),
+               .driver_info = SMS1XXX_BOARD_SIANO_NOVA_A },
+       { USB_DEVICE(0x187f, 0x0201),
+               .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B },
+       { USB_DEVICE(0x187f, 0x0300),
+               .driver_info = SMS1XXX_BOARD_SIANO_VEGA },
+#endif
+       { USB_DEVICE(0x2040, 0x1700),
+               .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT },
+       { USB_DEVICE(0x2040, 0x1800),
+               .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A },
+       { USB_DEVICE(0x2040, 0x1801),
+               .driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
+       { USB_DEVICE(0x2040, 0x5500),
+               .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+       { USB_DEVICE(0x2040, 0x5580),
+               .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+       { USB_DEVICE(0x2040, 0x5590),
+               .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+       { }             /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, smsusb_id_table);
+
+static struct sms_board sms_boards[] = {
+       [SMS_BOARD_UNKNOWN] = {
+               .name   = "Unknown board",
+       },
+       [SMS1XXX_BOARD_SIANO_STELLAR] = {
+               .name   = "Siano Stellar Digital Receiver",
+               .type   = SMS_STELLAR,
+               .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
+       },
+       [SMS1XXX_BOARD_SIANO_NOVA_A] = {
+               .name   = "Siano Nova A Digital Receiver",
+               .type   = SMS_NOVA_A0,
+               .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
+       },
+       [SMS1XXX_BOARD_SIANO_NOVA_B] = {
+               .name   = "Siano Nova B Digital Receiver",
+               .type   = SMS_NOVA_B0,
+               .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
+       },
+       [SMS1XXX_BOARD_SIANO_VEGA] = {
+               .name   = "Siano Vega Digital Receiver",
+               .type   = SMS_VEGA,
+       },
+       [SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = {
+               .name   = "Hauppauge Catamount",
+               .type   = SMS_STELLAR,
+               .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
+       },
+       [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = {
+               .name   = "Hauppauge Okemo-A",
+               .type   = SMS_NOVA_A0,
+               .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
+       },
+       [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = {
+               .name   = "Hauppauge Okemo-B",
+               .type   = SMS_NOVA_B0,
+               .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
+       },
+       [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
+               .name   = "Hauppauge WinTV-Nova-T-MiniStick",
+               .type   = SMS_NOVA_B0,
+               .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw",
+       },
+};
+
+struct sms_board *sms_get_board(int id)
+{
+       BUG_ON(id >= ARRAY_SIZE(sms_boards));
+
+       return &sms_boards[id];
+}
+
diff --git a/drivers/media/dvb/siano/sms-cards.h b/drivers/media/dvb/siano/sms-cards.h
new file mode 100644 (file)
index 0000000..83b39bc
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  Card-specific functions for the Siano SMS1xxx USB dongle
+ *
+ *  Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation;
+ *
+ *  Software distributed under the License is distributed on an "AS IS"
+ *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ *  See the GNU General Public License for more details.
+ *
+ *  You 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 __SMS_CARDS_H__
+#define __SMS_CARDS_H__
+
+#include <linux/usb.h>
+#include "smscoreapi.h"
+
+#define SMS_BOARD_UNKNOWN 0
+#define SMS1XXX_BOARD_SIANO_STELLAR 1
+#define SMS1XXX_BOARD_SIANO_NOVA_A  2
+#define SMS1XXX_BOARD_SIANO_NOVA_B  3
+#define SMS1XXX_BOARD_SIANO_VEGA    4
+#define SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT 5
+#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A 6
+#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B 7
+#define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8
+
+struct sms_board {
+       enum sms_device_type_st type;
+       char *name, *fw[DEVICE_MODE_MAX];
+};
+
+struct sms_board *sms_get_board(int id);
+
+extern struct usb_device_id smsusb_id_table[];
+
+#endif /* __SMS_CARDS_H__ */
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c
new file mode 100644 (file)
index 0000000..b4b8ed7
--- /dev/null
@@ -0,0 +1,1251 @@
+/*
+ *  Siano core API module
+ *
+ *  This file contains implementation for the interface to sms core component
+ *
+ *  author: Anatoly Greenblat
+ *
+ *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation;
+ *
+ *  Software distributed under the License is distributed on an "AS IS"
+ *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ *  See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <linux/firmware.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+int sms_debug;
+module_param_named(debug, sms_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
+
+struct smscore_device_notifyee_t {
+       struct list_head entry;
+       hotplug_t hotplug;
+};
+
+struct smscore_idlist_t {
+       struct list_head entry;
+       int             id;
+       int             data_type;
+};
+
+struct smscore_client_t {
+       struct list_head entry;
+       struct smscore_device_t *coredev;
+       void                    *context;
+       struct list_head        idlist;
+       onresponse_t    onresponse_handler;
+       onremove_t              onremove_handler;
+};
+
+struct smscore_device_t {
+       struct list_head entry;
+
+       struct list_head clients;
+       struct list_head subclients;
+       spinlock_t              clientslock;
+
+       struct list_head buffers;
+       spinlock_t              bufferslock;
+       int                             num_buffers;
+
+       void                    *common_buffer;
+       int                             common_buffer_size;
+       dma_addr_t              common_buffer_phys;
+
+       void                    *context;
+       struct device   *device;
+
+       char                    devpath[32];
+       unsigned long   device_flags;
+
+       setmode_t               setmode_handler;
+       detectmode_t    detectmode_handler;
+       sendrequest_t   sendrequest_handler;
+       preload_t               preload_handler;
+       postload_t              postload_handler;
+
+       int                             mode, modes_supported;
+
+       struct completion version_ex_done, data_download_done, trigger_done;
+       struct completion init_device_done, reload_start_done, resume_done;
+
+       int board_id;
+};
+
+void smscore_set_board_id(struct smscore_device_t *core, int id)
+{
+       core->board_id = id;
+}
+
+int smscore_get_board_id(struct smscore_device_t *core)
+{
+       return core->board_id;
+}
+
+struct smscore_registry_entry_t {
+       struct list_head entry;
+       char                    devpath[32];
+       int                             mode;
+       enum sms_device_type_st type;
+};
+
+struct list_head g_smscore_notifyees;
+struct list_head g_smscore_devices;
+struct mutex g_smscore_deviceslock;
+
+struct list_head g_smscore_registry;
+struct mutex g_smscore_registrylock;
+
+static int default_mode = 4;
+
+module_param(default_mode, int, 0644);
+MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
+
+static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
+{
+       struct smscore_registry_entry_t *entry;
+       struct list_head *next;
+
+       kmutex_lock(&g_smscore_registrylock);
+       for (next = g_smscore_registry.next;
+            next != &g_smscore_registry;
+            next = next->next) {
+               entry = (struct smscore_registry_entry_t *) next;
+               if (!strcmp(entry->devpath, devpath)) {
+                       kmutex_unlock(&g_smscore_registrylock);
+                       return entry;
+               }
+       }
+       entry = (struct smscore_registry_entry_t *)
+                       kmalloc(sizeof(struct smscore_registry_entry_t),
+                               GFP_KERNEL);
+       if (entry) {
+               entry->mode = default_mode;
+               strcpy(entry->devpath, devpath);
+               list_add(&entry->entry, &g_smscore_registry);
+       } else
+               sms_err("failed to create smscore_registry.");
+       kmutex_unlock(&g_smscore_registrylock);
+       return entry;
+}
+
+int smscore_registry_getmode(char *devpath)
+{
+       struct smscore_registry_entry_t *entry;
+
+       entry = smscore_find_registry(devpath);
+       if (entry)
+               return entry->mode;
+       else
+               sms_err("No registry found.");
+
+       return default_mode;
+}
+
+static enum sms_device_type_st smscore_registry_gettype(char *devpath)
+{
+       struct smscore_registry_entry_t *entry;
+
+       entry = smscore_find_registry(devpath);
+       if (entry)
+               return entry->type;
+       else
+               sms_err("No registry found.");
+
+       return -1;
+}
+
+void smscore_registry_setmode(char *devpath, int mode)
+{
+       struct smscore_registry_entry_t *entry;
+
+       entry = smscore_find_registry(devpath);
+       if (entry)
+               entry->mode = mode;
+       else
+               sms_err("No registry found.");
+}
+
+static void smscore_registry_settype(char *devpath,
+                                    enum sms_device_type_st type)
+{
+       struct smscore_registry_entry_t *entry;
+
+       entry = smscore_find_registry(devpath);
+       if (entry)
+               entry->type = type;
+       else
+               sms_err("No registry found.");
+}
+
+
+static void list_add_locked(struct list_head *new, struct list_head *head,
+                           spinlock_t *lock)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(lock, flags);
+
+       list_add(new, head);
+
+       spin_unlock_irqrestore(lock, flags);
+}
+
+/**
+ * register a client callback that called when device plugged in/unplugged
+ * NOTE: if devices exist callback is called immediately for each device
+ *
+ * @param hotplug callback
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_hotplug(hotplug_t hotplug)
+{
+       struct smscore_device_notifyee_t *notifyee;
+       struct list_head *next, *first;
+       int rc = 0;
+
+       kmutex_lock(&g_smscore_deviceslock);
+
+       notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
+                          GFP_KERNEL);
+       if (notifyee) {
+               /* now notify callback about existing devices */
+               first = &g_smscore_devices;
+               for (next = first->next;
+                    next != first && !rc;
+                    next = next->next) {
+                       struct smscore_device_t *coredev =
+                               (struct smscore_device_t *) next;
+                       rc = hotplug(coredev, coredev->device, 1);
+               }
+
+               if (rc >= 0) {
+                       notifyee->hotplug = hotplug;
+                       list_add(&notifyee->entry, &g_smscore_notifyees);
+               } else
+                       kfree(notifyee);
+       } else
+               rc = -ENOMEM;
+
+       kmutex_unlock(&g_smscore_deviceslock);
+
+       return rc;
+}
+
+/**
+ * unregister a client callback that called when device plugged in/unplugged
+ *
+ * @param hotplug callback
+ *
+ */
+void smscore_unregister_hotplug(hotplug_t hotplug)
+{
+       struct list_head *next, *first;
+
+       kmutex_lock(&g_smscore_deviceslock);
+
+       first = &g_smscore_notifyees;
+
+       for (next = first->next; next != first;) {
+               struct smscore_device_notifyee_t *notifyee =
+                       (struct smscore_device_notifyee_t *) next;
+               next = next->next;
+
+               if (notifyee->hotplug == hotplug) {
+                       list_del(&notifyee->entry);
+                       kfree(notifyee);
+               }
+       }
+
+       kmutex_unlock(&g_smscore_deviceslock);
+}
+
+static void smscore_notify_clients(struct smscore_device_t *coredev)
+{
+       struct smscore_client_t *client;
+
+       /* the client must call smscore_unregister_client from remove handler */
+       while (!list_empty(&coredev->clients)) {
+               client = (struct smscore_client_t *) coredev->clients.next;
+               client->onremove_handler(client->context);
+       }
+}
+
+static int smscore_notify_callbacks(struct smscore_device_t *coredev,
+                                   struct device *device, int arrival)
+{
+       struct list_head *next, *first;
+       int rc = 0;
+
+       /* note: must be called under g_deviceslock */
+
+       first = &g_smscore_notifyees;
+
+       for (next = first->next; next != first; next = next->next) {
+               rc = ((struct smscore_device_notifyee_t *) next)->
+                               hotplug(coredev, device, arrival);
+               if (rc < 0)
+                       break;
+       }
+
+       return rc;
+}
+
+static struct
+smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
+                                      dma_addr_t common_buffer_phys)
+{
+       struct smscore_buffer_t *cb =
+               kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
+       if (!cb) {
+               sms_info("kmalloc(...) failed");
+               return NULL;
+       }
+
+       cb->p = buffer;
+       cb->offset_in_common = buffer - (u8 *) common_buffer;
+       cb->phys = common_buffer_phys + cb->offset_in_common;
+
+       return cb;
+}
+
+/**
+ * creates coredev object for a device, prepares buffers,
+ * creates buffer mappings, notifies registered hotplugs about new device.
+ *
+ * @param params device pointer to struct with device specific parameters
+ *               and handlers
+ * @param coredev pointer to a value that receives created coredev object
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_device(struct smsdevice_params_t *params,
+                           struct smscore_device_t **coredev)
+{
+       struct smscore_device_t *dev;
+       u8 *buffer;
+
+       dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
+       if (!dev) {
+               sms_info("kzalloc(...) failed");
+               return -ENOMEM;
+       }
+
+       /* init list entry so it could be safe in smscore_unregister_device */
+       INIT_LIST_HEAD(&dev->entry);
+
+       /* init queues */
+       INIT_LIST_HEAD(&dev->clients);
+       INIT_LIST_HEAD(&dev->buffers);
+
+       /* init locks */
+       spin_lock_init(&dev->clientslock);
+       spin_lock_init(&dev->bufferslock);
+
+       /* init completion events */
+       init_completion(&dev->version_ex_done);
+       init_completion(&dev->data_download_done);
+       init_completion(&dev->trigger_done);
+       init_completion(&dev->init_device_done);
+       init_completion(&dev->reload_start_done);
+       init_completion(&dev->resume_done);
+
+       /* alloc common buffer */
+       dev->common_buffer_size = params->buffer_size * params->num_buffers;
+       dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
+                                               &dev->common_buffer_phys,
+                                               GFP_KERNEL | GFP_DMA);
+       if (!dev->common_buffer) {
+               smscore_unregister_device(dev);
+               return -ENOMEM;
+       }
+
+       /* prepare dma buffers */
+       for (buffer = dev->common_buffer;
+            dev->num_buffers < params->num_buffers;
+            dev->num_buffers++, buffer += params->buffer_size) {
+               struct smscore_buffer_t *cb =
+                       smscore_createbuffer(buffer, dev->common_buffer,
+                                            dev->common_buffer_phys);
+               if (!cb) {
+                       smscore_unregister_device(dev);
+                       return -ENOMEM;
+               }
+
+               smscore_putbuffer(dev, cb);
+       }
+
+       sms_info("allocated %d buffers", dev->num_buffers);
+
+       dev->mode = DEVICE_MODE_NONE;
+       dev->context = params->context;
+       dev->device = params->device;
+       dev->setmode_handler = params->setmode_handler;
+       dev->detectmode_handler = params->detectmode_handler;
+       dev->sendrequest_handler = params->sendrequest_handler;
+       dev->preload_handler = params->preload_handler;
+       dev->postload_handler = params->postload_handler;
+
+       dev->device_flags = params->flags;
+       strcpy(dev->devpath, params->devpath);
+
+       smscore_registry_settype(dev->devpath, params->device_type);
+
+       /* add device to devices list */
+       kmutex_lock(&g_smscore_deviceslock);
+       list_add(&dev->entry, &g_smscore_devices);
+       kmutex_unlock(&g_smscore_deviceslock);
+
+       *coredev = dev;
+
+       sms_info("device %p created", dev);
+
+       return 0;
+}
+
+/**
+ * sets initial device mode and notifies client hotplugs that device is ready
+ *
+ * @param coredev pointer to a coredev object returned by
+ *               smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_start_device(struct smscore_device_t *coredev)
+{
+       int rc = smscore_set_device_mode(
+                       coredev, smscore_registry_getmode(coredev->devpath));
+       if (rc < 0) {
+               sms_info("set device mode faile , rc %d", rc);
+               return rc;
+       }
+
+       kmutex_lock(&g_smscore_deviceslock);
+
+       rc = smscore_notify_callbacks(coredev, coredev->device, 1);
+
+       sms_info("device %p started, rc %d", coredev, rc);
+
+       kmutex_unlock(&g_smscore_deviceslock);
+
+       return rc;
+}
+
+static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
+                                       void *buffer, size_t size,
+                                       struct completion *completion)
+{
+       int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
+       if (rc < 0) {
+               sms_info("sendrequest returned error %d", rc);
+               return rc;
+       }
+
+       return wait_for_completion_timeout(completion,
+                                          msecs_to_jiffies(10000)) ?
+                                               0 : -ETIME;
+}
+
+static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
+                                        void *buffer, size_t size)
+{
+       struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
+       struct SmsMsgHdr_ST *msg;
+       u32 mem_address = firmware->StartAddress;
+       u8 *payload = firmware->Payload;
+       int rc = 0;
+
+       sms_info("loading FW to addr 0x%x size %d",
+                mem_address, firmware->Length);
+       if (coredev->preload_handler) {
+               rc = coredev->preload_handler(coredev->context);
+               if (rc < 0)
+                       return rc;
+       }
+
+       /* PAGE_SIZE buffer shall be enough and dma aligned */
+       msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+       if (!msg)
+               return -ENOMEM;
+
+       if (coredev->mode != DEVICE_MODE_NONE) {
+               sms_debug("sending reload command.");
+               SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
+                            sizeof(struct SmsMsgHdr_ST));
+               rc = smscore_sendrequest_and_wait(coredev, msg,
+                                                 msg->msgLength,
+                                                 &coredev->reload_start_done);
+               mem_address = *(u32 *) &payload[20];
+       }
+
+       while (size && rc >= 0) {
+               struct SmsDataDownload_ST *DataMsg =
+                       (struct SmsDataDownload_ST *) msg;
+               int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
+
+               SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
+                            (u16)(sizeof(struct SmsMsgHdr_ST) +
+                                     sizeof(u32) + payload_size));
+
+               DataMsg->MemAddr = mem_address;
+               memcpy(DataMsg->Payload, payload, payload_size);
+
+               if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
+                   (coredev->mode == DEVICE_MODE_NONE))
+                       rc = coredev->sendrequest_handler(
+                               coredev->context, DataMsg,
+                               DataMsg->xMsgHeader.msgLength);
+               else
+                       rc = smscore_sendrequest_and_wait(
+                               coredev, DataMsg,
+                               DataMsg->xMsgHeader.msgLength,
+                               &coredev->data_download_done);
+
+               payload += payload_size;
+               size -= payload_size;
+               mem_address += payload_size;
+       }
+
+       if (rc >= 0) {
+               if (coredev->mode == DEVICE_MODE_NONE) {
+                       struct SmsMsgData_ST *TriggerMsg =
+                               (struct SmsMsgData_ST *) msg;
+
+                       SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
+                                    sizeof(struct SmsMsgHdr_ST) +
+                                    sizeof(u32) * 5);
+
+                       TriggerMsg->msgData[0] = firmware->StartAddress;
+                                               /* Entry point */
+                       TriggerMsg->msgData[1] = 5; /* Priority */
+                       TriggerMsg->msgData[2] = 0x200; /* Stack size */
+                       TriggerMsg->msgData[3] = 0; /* Parameter */
+                       TriggerMsg->msgData[4] = 4; /* Task ID */
+
+                       if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
+                               rc = coredev->sendrequest_handler(
+                                       coredev->context, TriggerMsg,
+                                       TriggerMsg->xMsgHeader.msgLength);
+                               msleep(100);
+                       } else
+                               rc = smscore_sendrequest_and_wait(
+                                       coredev, TriggerMsg,
+                                       TriggerMsg->xMsgHeader.msgLength,
+                                       &coredev->trigger_done);
+               } else {
+                       SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
+                                    sizeof(struct SmsMsgHdr_ST));
+
+                       rc = coredev->sendrequest_handler(coredev->context,
+                                                         msg, msg->msgLength);
+               }
+               msleep(500);
+       }
+
+       sms_debug("rc=%d, postload=%p ", rc,
+                 coredev->postload_handler);
+
+       kfree(msg);
+
+       return ((rc >= 0) && coredev->postload_handler) ?
+               coredev->postload_handler(coredev->context) :
+               rc;
+}
+
+/**
+ * loads specified firmware into a buffer and calls device loadfirmware_handler
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param filename null-terminated string specifies firmware file name
+ * @param loadfirmware_handler device handler that loads firmware
+ *
+ * @return 0 on success, <0 on error.
+ */
+static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
+                                          char *filename,
+                                          loadfirmware_t loadfirmware_handler)
+{
+       int rc = -ENOENT;
+       const struct firmware *fw;
+       u8 *fw_buffer;
+
+       if (loadfirmware_handler == NULL && !(coredev->device_flags &
+                                             SMS_DEVICE_FAMILY2))
+               return -EINVAL;
+
+       rc = request_firmware(&fw, filename, coredev->device);
+       if (rc < 0) {
+               sms_info("failed to open \"%s\"", filename);
+               return rc;
+       }
+       sms_info("read FW %s, size=%zd", filename, fw->size);
+       fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
+                           GFP_KERNEL | GFP_DMA);
+       if (fw_buffer) {
+               memcpy(fw_buffer, fw->data, fw->size);
+
+               rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
+                     smscore_load_firmware_family2(coredev,
+                                                   fw_buffer,
+                                                   fw->size) :
+                     loadfirmware_handler(coredev->context,
+                                          fw_buffer, fw->size);
+
+               kfree(fw_buffer);
+       } else {
+               sms_info("failed to allocate firmware buffer");
+               rc = -ENOMEM;
+       }
+
+       release_firmware(fw);
+
+       return rc;
+}
+
+/**
+ * notifies all clients registered with the device, notifies hotplugs,
+ * frees all buffers and coredev object
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+void smscore_unregister_device(struct smscore_device_t *coredev)
+{
+       struct smscore_buffer_t *cb;
+       int num_buffers = 0;
+       int retry = 0;
+
+       kmutex_lock(&g_smscore_deviceslock);
+
+       smscore_notify_clients(coredev);
+       smscore_notify_callbacks(coredev, NULL, 0);
+
+       /* at this point all buffers should be back
+        * onresponse must no longer be called */
+
+       while (1) {
+               while ((cb = smscore_getbuffer(coredev))) {
+                       kfree(cb);
+                       num_buffers++;
+               }
+               if (num_buffers == coredev->num_buffers)
+                       break;
+               if (++retry > 10) {
+                       sms_info("exiting although "
+                                "not all buffers released.");
+                       break;
+               }
+
+               sms_info("waiting for %d buffer(s)",
+                        coredev->num_buffers - num_buffers);
+               msleep(100);
+       }
+
+       sms_info("freed %d buffers", num_buffers);
+
+       if (coredev->common_buffer)
+               dma_free_coherent(NULL, coredev->common_buffer_size,
+                                 coredev->common_buffer,
+                                 coredev->common_buffer_phys);
+
+       list_del(&coredev->entry);
+       kfree(coredev);
+
+       kmutex_unlock(&g_smscore_deviceslock);
+
+       sms_info("device %p destroyed", coredev);
+}
+
+static int smscore_detect_mode(struct smscore_device_t *coredev)
+{
+       void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
+                              GFP_KERNEL | GFP_DMA);
+       struct SmsMsgHdr_ST *msg =
+               (struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
+       int rc;
+
+       if (!buffer)
+               return -ENOMEM;
+
+       SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
+                    sizeof(struct SmsMsgHdr_ST));
+
+       rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
+                                         &coredev->version_ex_done);
+       if (rc == -ETIME) {
+               sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
+
+               if (wait_for_completion_timeout(&coredev->resume_done,
+                                               msecs_to_jiffies(5000))) {
+                       rc = smscore_sendrequest_and_wait(
+                               coredev, msg, msg->msgLength,
+                               &coredev->version_ex_done);
+                       if (rc < 0)
+                               sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
+                                       "second try, rc %d", rc);
+               } else
+                       rc = -ETIME;
+       }
+
+       kfree(buffer);
+
+       return rc;
+}
+
+static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
+       /*Stellar               NOVA A0         Nova B0         VEGA*/
+       /*DVBT*/
+       {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+       /*DVBH*/
+       {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+       /*TDMB*/
+       {"none", "tdmb_nova_12mhz.inp", "none", "none"},
+       /*DABIP*/
+       {"none", "none", "none", "none"},
+       /*BDA*/
+       {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+       /*ISDBT*/
+       {"none", "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp", "none"},
+       /*ISDBTBDA*/
+       {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
+       /*CMMB*/
+       {"none", "none", "none", "cmmb_vega_12mhz.inp"}
+};
+
+static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
+                                   int mode, enum sms_device_type_st type)
+{
+       char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
+       return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
+}
+
+/**
+ * calls device handler to change mode of operation
+ * NOTE: stellar/usb may disconnect when changing mode
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param mode requested mode of operation
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
+{
+       void *buffer;
+       int rc = 0;
+       enum sms_device_type_st type;
+
+       sms_debug("set device mode to %d", mode);
+       if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
+               if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) {
+                       sms_err("invalid mode specified %d", mode);
+                       return -EINVAL;
+               }
+
+               smscore_registry_setmode(coredev->devpath, mode);
+
+               if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
+                       rc = smscore_detect_mode(coredev);
+                       if (rc < 0) {
+                               sms_err("mode detect failed %d", rc);
+                               return rc;
+                       }
+               }
+
+               if (coredev->mode == mode) {
+                       sms_info("device mode %d already set", mode);
+                       return 0;
+               }
+
+               if (!(coredev->modes_supported & (1 << mode))) {
+                       char *fw_filename;
+
+                       type = smscore_registry_gettype(coredev->devpath);
+                       fw_filename = sms_get_fw_name(coredev, mode, type);
+
+                       rc = smscore_load_firmware_from_file(coredev,
+                                                            fw_filename, NULL);
+                       if (rc < 0) {
+                               sms_warn("error %d loading firmware: %s, "
+                                        "trying again with default firmware",
+                                        rc, fw_filename);
+
+                               /* try again with the default firmware */
+                               fw_filename = smscore_fw_lkup[mode][type];
+                               rc = smscore_load_firmware_from_file(coredev,
+                                                            fw_filename, NULL);
+
+                               if (rc < 0) {
+                                       sms_warn("error %d loading "
+                                                "firmware: %s", rc,
+                                                fw_filename);
+                                       return rc;
+                               }
+                       }
+                       sms_log("firmware download success: %s", fw_filename);
+               } else
+                       sms_info("mode %d supported by running "
+                                "firmware", mode);
+
+               buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
+                                SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
+               if (buffer) {
+                       struct SmsMsgData_ST *msg =
+                               (struct SmsMsgData_ST *)
+                                       SMS_ALIGN_ADDRESS(buffer);
+
+                       SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
+                                    sizeof(struct SmsMsgData_ST));
+                       msg->msgData[0] = mode;
+
+                       rc = smscore_sendrequest_and_wait(
+                               coredev, msg, msg->xMsgHeader.msgLength,
+                               &coredev->init_device_done);
+
+                       kfree(buffer);
+               } else {
+                       sms_err("Could not allocate buffer for "
+                               "init device message.");
+                       rc = -ENOMEM;
+               }
+       } else {
+               if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
+                       sms_err("invalid mode specified %d", mode);
+                       return -EINVAL;
+               }
+
+               smscore_registry_setmode(coredev->devpath, mode);
+
+               if (coredev->detectmode_handler)
+                       coredev->detectmode_handler(coredev->context,
+                                                   &coredev->mode);
+
+               if (coredev->mode != mode && coredev->setmode_handler)
+                       rc = coredev->setmode_handler(coredev->context, mode);
+       }
+
+       if (rc >= 0) {
+               coredev->mode = mode;
+               coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
+       }
+
+       if (rc != 0)
+               sms_err("return error code %d.", rc);
+       return rc;
+}
+
+/**
+ * calls device handler to get current mode of operation
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ *
+ * @return current mode
+ */
+int smscore_get_device_mode(struct smscore_device_t *coredev)
+{
+       return coredev->mode;
+}
+
+/**
+ * find client by response id & type within the clients list.
+ * return client handle or NULL.
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param data_type client data type (SMS_DONT_CARE for all types)
+ * @param id client id (SMS_DONT_CARE for all id)
+ *
+ */
+static struct
+smscore_client_t *smscore_find_client(struct smscore_device_t *coredev,
+                                     int data_type, int id)
+{
+       struct smscore_client_t *client = NULL;
+       struct list_head *next, *first;
+       unsigned long flags;
+       struct list_head *firstid, *nextid;
+
+
+       spin_lock_irqsave(&coredev->clientslock, flags);
+       first = &coredev->clients;
+       for (next = first->next;
+            (next != first) && !client;
+            next = next->next) {
+               firstid = &((struct smscore_client_t *)next)->idlist;
+               for (nextid = firstid->next;
+                    nextid != firstid;
+                    nextid = nextid->next) {
+                       if ((((struct smscore_idlist_t *)nextid)->id == id) &&
+                           (((struct smscore_idlist_t *)nextid)->data_type == data_type ||
+                           (((struct smscore_idlist_t *)nextid)->data_type == 0))) {
+                               client = (struct smscore_client_t *) next;
+                               break;
+                       }
+               }
+       }
+       spin_unlock_irqrestore(&coredev->clientslock, flags);
+       return client;
+}
+
+/**
+ * find client by response id/type, call clients onresponse handler
+ * return buffer to pool on error
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param cb pointer to response buffer descriptor
+ *
+ */
+void smscore_onresponse(struct smscore_device_t *coredev,
+                       struct smscore_buffer_t *cb)
+{
+       struct SmsMsgHdr_ST *phdr =
+               (struct SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset);
+       struct smscore_client_t *client =
+               smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
+       int rc = -EBUSY;
+
+       static unsigned long last_sample_time; /* = 0; */
+       static int data_total; /* = 0; */
+       unsigned long time_now = jiffies_to_msecs(jiffies);
+
+       if (!last_sample_time)
+               last_sample_time = time_now;
+
+       if (time_now - last_sample_time > 10000) {
+               sms_debug("\ndata rate %d bytes/secs",
+                         (int)((data_total * 1000) /
+                               (time_now - last_sample_time)));
+
+               last_sample_time = time_now;
+               data_total = 0;
+       }
+
+       data_total += cb->size;
+       /* If no client registered for type & id,
+        * check for control client where type is not registered */
+       if (client)
+               rc = client->onresponse_handler(client->context, cb);
+
+       if (rc < 0) {
+               switch (phdr->msgType) {
+               case MSG_SMS_GET_VERSION_EX_RES:
+               {
+                       struct SmsVersionRes_ST *ver =
+                               (struct SmsVersionRes_ST *) phdr;
+                       sms_debug("MSG_SMS_GET_VERSION_EX_RES "
+                                 "id %d prots 0x%x ver %d.%d",
+                                 ver->FirmwareId, ver->SupportedProtocols,
+                                 ver->RomVersionMajor, ver->RomVersionMinor);
+
+                       coredev->mode = ver->FirmwareId == 255 ?
+                               DEVICE_MODE_NONE : ver->FirmwareId;
+                       coredev->modes_supported = ver->SupportedProtocols;
+
+                       complete(&coredev->version_ex_done);
+                       break;
+               }
+               case MSG_SMS_INIT_DEVICE_RES:
+                       sms_debug("MSG_SMS_INIT_DEVICE_RES");
+                       complete(&coredev->init_device_done);
+                       break;
+               case MSG_SW_RELOAD_START_RES:
+                       sms_debug("MSG_SW_RELOAD_START_RES");
+                       complete(&coredev->reload_start_done);
+                       break;
+               case MSG_SMS_DATA_DOWNLOAD_RES:
+                       complete(&coredev->data_download_done);
+                       break;
+               case MSG_SW_RELOAD_EXEC_RES:
+                       sms_debug("MSG_SW_RELOAD_EXEC_RES");
+                       break;
+               case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
+                       sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
+                       complete(&coredev->trigger_done);
+                       break;
+               case MSG_SMS_SLEEP_RESUME_COMP_IND:
+                       complete(&coredev->resume_done);
+                       break;
+               default:
+                       break;
+               }
+               smscore_putbuffer(coredev, cb);
+       }
+}
+
+/**
+ * return pointer to next free buffer descriptor from core pool
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ *
+ * @return pointer to descriptor on success, NULL on error.
+ */
+struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
+{
+       struct smscore_buffer_t *cb = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&coredev->bufferslock, flags);
+
+       if (!list_empty(&coredev->buffers)) {
+               cb = (struct smscore_buffer_t *) coredev->buffers.next;
+               list_del(&cb->entry);
+       }
+
+       spin_unlock_irqrestore(&coredev->bufferslock, flags);
+
+       return cb;
+}
+
+/**
+ * return buffer descriptor to a pool
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param cb pointer buffer descriptor
+ *
+ */
+void smscore_putbuffer(struct smscore_device_t *coredev,
+                      struct smscore_buffer_t *cb)
+{
+       list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
+}
+
+static int smscore_validate_client(struct smscore_device_t *coredev,
+                                  struct smscore_client_t *client,
+                                  int data_type, int id)
+{
+       struct smscore_idlist_t *listentry;
+       struct smscore_client_t *registered_client;
+
+       if (!client) {
+               sms_err("bad parameter.");
+               return -EFAULT;
+       }
+       registered_client = smscore_find_client(coredev, data_type, id);
+       if (registered_client == client)
+               return 0;
+
+       if (registered_client) {
+               sms_err("The msg ID already registered to another client.");
+               return -EEXIST;
+       }
+       listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
+       if (!listentry) {
+               sms_err("Can't allocate memory for client id.");
+               return -ENOMEM;
+       }
+       listentry->id = id;
+       listentry->data_type = data_type;
+       list_add_locked(&listentry->entry, &client->idlist,
+                       &coredev->clientslock);
+       return 0;
+}
+
+/**
+ * creates smsclient object, check that id is taken by another client
+ *
+ * @param coredev pointer to a coredev object from clients hotplug
+ * @param initial_id all messages with this id would be sent to this client
+ * @param data_type all messages of this type would be sent to this client
+ * @param onresponse_handler client handler that is called to
+ *                           process incoming messages
+ * @param onremove_handler client handler that is called when device is removed
+ * @param context client-specific context
+ * @param client pointer to a value that receives created smsclient object
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_client(struct smscore_device_t *coredev,
+                           struct smsclient_params_t *params,
+                           struct smscore_client_t **client)
+{
+       struct smscore_client_t *newclient;
+       /* check that no other channel with same parameters exists */
+       if (smscore_find_client(coredev, params->data_type,
+                               params->initial_id)) {
+               sms_err("Client already exist.");
+               return -EEXIST;
+       }
+
+       newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
+       if (!newclient) {
+               sms_err("Failed to allocate memory for client.");
+               return -ENOMEM;
+       }
+
+       INIT_LIST_HEAD(&newclient->idlist);
+       newclient->coredev = coredev;
+       newclient->onresponse_handler = params->onresponse_handler;
+       newclient->onremove_handler = params->onremove_handler;
+       newclient->context = params->context;
+       list_add_locked(&newclient->entry, &coredev->clients,
+                       &coredev->clientslock);
+       smscore_validate_client(coredev, newclient, params->data_type,
+                               params->initial_id);
+       *client = newclient;
+       sms_debug("%p %d %d", params->context, params->data_type,
+                 params->initial_id);
+
+       return 0;
+}
+
+/**
+ * frees smsclient object and all subclients associated with it
+ *
+ * @param client pointer to smsclient object returned by
+ *               smscore_register_client
+ *
+ */
+void smscore_unregister_client(struct smscore_client_t *client)
+{
+       struct smscore_device_t *coredev = client->coredev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&coredev->clientslock, flags);
+
+
+       while (!list_empty(&client->idlist)) {
+               struct smscore_idlist_t *identry =
+                       (struct smscore_idlist_t *) client->idlist.next;
+               list_del(&identry->entry);
+               kfree(identry);
+       }
+
+       sms_info("%p", client->context);
+
+       list_del(&client->entry);
+       kfree(client);
+
+       spin_unlock_irqrestore(&coredev->clientslock, flags);
+}
+
+/**
+ * verifies that source id is not taken by another client,
+ * calls device handler to send requests to the device
+ *
+ * @param client pointer to smsclient object returned by
+ *               smscore_register_client
+ * @param buffer pointer to a request buffer
+ * @param size size (in bytes) of request buffer
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smsclient_sendrequest(struct smscore_client_t *client,
+                         void *buffer, size_t size)
+{
+       struct smscore_device_t *coredev;
+       struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
+       int rc;
+
+       if (client == NULL) {
+               sms_err("Got NULL client");
+               return -EINVAL;
+       }
+
+       coredev = client->coredev;
+
+       /* check that no other channel with same id exists */
+       if (coredev == NULL) {
+               sms_err("Got NULL coredev");
+               return -EINVAL;
+       }
+
+       rc = smscore_validate_client(client->coredev, client, 0,
+                                    phdr->msgSrcId);
+       if (rc < 0)
+               return rc;
+
+       return coredev->sendrequest_handler(coredev->context, buffer, size);
+}
+
+
+int smscore_module_init(void)
+{
+       int rc = 0;
+
+       INIT_LIST_HEAD(&g_smscore_notifyees);
+       INIT_LIST_HEAD(&g_smscore_devices);
+       kmutex_init(&g_smscore_deviceslock);
+
+       INIT_LIST_HEAD(&g_smscore_registry);
+       kmutex_init(&g_smscore_registrylock);
+
+       /* USB Register */
+       rc = smsusb_register();
+
+       /* DVB Register */
+       rc = smsdvb_register();
+
+       sms_debug("rc %d", rc);
+
+       return rc;
+}
+
+void smscore_module_exit(void)
+{
+
+       kmutex_lock(&g_smscore_deviceslock);
+       while (!list_empty(&g_smscore_notifyees)) {
+               struct smscore_device_notifyee_t *notifyee =
+                       (struct smscore_device_notifyee_t *)
+                               g_smscore_notifyees.next;
+
+               list_del(&notifyee->entry);
+               kfree(notifyee);
+       }
+       kmutex_unlock(&g_smscore_deviceslock);
+
+       kmutex_lock(&g_smscore_registrylock);
+       while (!list_empty(&g_smscore_registry)) {
+               struct smscore_registry_entry_t *entry =
+                       (struct smscore_registry_entry_t *)
+                               g_smscore_registry.next;
+
+               list_del(&entry->entry);
+               kfree(entry);
+       }
+       kmutex_unlock(&g_smscore_registrylock);
+
+       /* DVB UnRegister */
+       smsdvb_unregister();
+
+       /* Unregister USB */
+       smsusb_unregister();
+
+       sms_debug("");
+}
+
+module_init(smscore_module_init);
+module_exit(smscore_module_exit);
+
+MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle");
+MODULE_AUTHOR("Siano Mobile Silicon,,, (doronc@siano-ms.com)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h
new file mode 100644 (file)
index 0000000..c1f8f1d
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ *  Driver for the Siano SMS1xxx USB dongle
+ *
+ *  author: Anatoly Greenblat
+ *
+ *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation;
+ *
+ *  Software distributed under the License is distributed on an "AS IS"
+ *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ *  See the GNU General Public License for more details.
+ *
+ *  You 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 __smscoreapi_h__
+#define __smscoreapi_h__
+
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/types.h>
+#include <asm/page.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+
+#include <linux/mutex.h>
+
+#define kmutex_init(_p_) mutex_init(_p_)
+#define kmutex_lock(_p_) mutex_lock(_p_)
+#define kmutex_trylock(_p_) mutex_trylock(_p_)
+#define kmutex_unlock(_p_) mutex_unlock(_p_)
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define SMS_ALLOC_ALIGNMENT                                    128
+#define SMS_DMA_ALIGNMENT                                      16
+#define SMS_ALIGN_ADDRESS(addr) \
+       ((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
+
+#define SMS_DEVICE_FAMILY2                                     1
+#define SMS_ROM_NO_RESPONSE                                    2
+#define SMS_DEVICE_NOT_READY                           0x8000000
+
+enum sms_device_type_st {
+       SMS_STELLAR = 0,
+       SMS_NOVA_A0,
+       SMS_NOVA_B0,
+       SMS_VEGA,
+       SMS_NUM_OF_DEVICE_TYPES
+};
+
+struct smscore_device_t;
+struct smscore_client_t;
+struct smscore_buffer_t;
+
+typedef int (*hotplug_t)(struct smscore_device_t *coredev,
+                        struct device *device, int arrival);
+
+typedef int (*setmode_t)(void *context, int mode);
+typedef void (*detectmode_t)(void *context, int *mode);
+typedef int (*sendrequest_t)(void *context, void *buffer, size_t size);
+typedef int (*loadfirmware_t)(void *context, void *buffer, size_t size);
+typedef int (*preload_t)(void *context);
+typedef int (*postload_t)(void *context);
+
+typedef int (*onresponse_t)(void *context, struct smscore_buffer_t *cb);
+typedef void (*onremove_t)(void *context);
+
+struct smscore_buffer_t {
+       /* public members, once passed to clients can be changed freely */
+       struct list_head entry;
+       int                             size;
+       int                             offset;
+
+       /* private members, read-only for clients */
+       void                    *p;
+       dma_addr_t              phys;
+       unsigned long   offset_in_common;
+};
+
+struct smsdevice_params_t {
+       struct device   *device;
+
+       int                             buffer_size;
+       int                             num_buffers;
+
+       char                    devpath[32];
+       unsigned long   flags;
+
+       setmode_t               setmode_handler;
+       detectmode_t    detectmode_handler;
+       sendrequest_t   sendrequest_handler;
+       preload_t               preload_handler;
+       postload_t              postload_handler;
+
+       void                    *context;
+       enum sms_device_type_st device_type;
+};
+
+struct smsclient_params_t {
+       int                             initial_id;
+       int                             data_type;
+       onresponse_t    onresponse_handler;
+       onremove_t              onremove_handler;
+
+       void                    *context;
+};
+
+/* GPIO definitions for antenna frequency domain control (SMS8021) */
+#define SMS_ANTENNA_GPIO_0                                     1
+#define SMS_ANTENNA_GPIO_1                                     0
+
+#define BW_8_MHZ                                                       0
+#define BW_7_MHZ                                                       1
+#define BW_6_MHZ                                                       2
+#define BW_5_MHZ                                                       3
+#define BW_ISDBT_1SEG                                          4
+#define BW_ISDBT_3SEG                                          5
+
+#define MSG_HDR_FLAG_SPLIT_MSG                         4
+
+#define MAX_GPIO_PIN_NUMBER                                    31
+
+#define HIF_TASK                                                       11
+#define SMS_HOST_LIB                                           150
+#define DVBT_BDA_CONTROL_MSG_ID                                201
+
+#define SMS_MAX_PAYLOAD_SIZE                           240
+#define SMS_TUNE_TIMEOUT                                       500
+
+#define MSG_SMS_GPIO_CONFIG_REQ                                507
+#define MSG_SMS_GPIO_CONFIG_RES                                508
+#define MSG_SMS_GPIO_SET_LEVEL_REQ                     509
+#define MSG_SMS_GPIO_SET_LEVEL_RES                     510
+#define MSG_SMS_GPIO_GET_LEVEL_REQ                     511
+#define MSG_SMS_GPIO_GET_LEVEL_RES                     512
+#define MSG_SMS_RF_TUNE_REQ                                    561
+#define MSG_SMS_RF_TUNE_RES                                    562
+#define MSG_SMS_INIT_DEVICE_REQ                                578
+#define MSG_SMS_INIT_DEVICE_RES                                579
+#define MSG_SMS_ADD_PID_FILTER_REQ                     601
+#define MSG_SMS_ADD_PID_FILTER_RES                     602
+#define MSG_SMS_REMOVE_PID_FILTER_REQ          603
+#define MSG_SMS_REMOVE_PID_FILTER_RES          604
+#define MSG_SMS_DAB_CHANNEL                                    607
+#define MSG_SMS_GET_PID_FILTER_LIST_REQ                608
+#define MSG_SMS_GET_PID_FILTER_LIST_RES                609
+#define MSG_SMS_GET_STATISTICS_REQ                     615
+#define MSG_SMS_GET_STATISTICS_RES                     616
+#define MSG_SMS_SET_ANTENNA_CONFIG_REQ         651
+#define MSG_SMS_SET_ANTENNA_CONFIG_RES         652
+#define MSG_SMS_GET_STATISTICS_EX_REQ          653
+#define MSG_SMS_GET_STATISTICS_EX_RES          654
+#define MSG_SMS_SLEEP_RESUME_COMP_IND          655
+#define MSG_SMS_DATA_DOWNLOAD_REQ                      660
+#define MSG_SMS_DATA_DOWNLOAD_RES                      661
+#define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ         664
+#define MSG_SMS_SWDOWNLOAD_TRIGGER_RES         665
+#define MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ                666
+#define MSG_SMS_SWDOWNLOAD_BACKDOOR_RES                667
+#define MSG_SMS_GET_VERSION_EX_REQ                     668
+#define MSG_SMS_GET_VERSION_EX_RES                     669
+#define MSG_SMS_SET_CLOCK_OUTPUT_REQ           670
+#define MSG_SMS_I2C_SET_FREQ_REQ                       685
+#define MSG_SMS_GENERIC_I2C_REQ                                687
+#define MSG_SMS_GENERIC_I2C_RES                                688
+#define MSG_SMS_DVBT_BDA_DATA                          693
+#define MSG_SW_RELOAD_REQ                                      697
+#define MSG_SMS_DATA_MSG                                       699
+#define MSG_SW_RELOAD_START_REQ                                702
+#define MSG_SW_RELOAD_START_RES                                703
+#define MSG_SW_RELOAD_EXEC_REQ                         704
+#define MSG_SW_RELOAD_EXEC_RES                         705
+#define MSG_SMS_SPI_INT_LINE_SET_REQ           710
+#define MSG_SMS_ISDBT_TUNE_REQ                         776
+#define MSG_SMS_ISDBT_TUNE_RES                         777
+
+#define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
+       (ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
+       (ptr)->msgLength = len; (ptr)->msgFlags = 0; \
+} while (0)
+#define SMS_INIT_MSG(ptr, type, len) \
+       SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len)
+
+enum SMS_DEVICE_MODE {
+       DEVICE_MODE_NONE = -1,
+       DEVICE_MODE_DVBT = 0,
+       DEVICE_MODE_DVBH,
+       DEVICE_MODE_DAB_TDMB,
+       DEVICE_MODE_DAB_TDMB_DABIP,
+       DEVICE_MODE_DVBT_BDA,
+       DEVICE_MODE_ISDBT,
+       DEVICE_MODE_ISDBT_BDA,
+       DEVICE_MODE_CMMB,
+       DEVICE_MODE_RAW_TUNER,
+       DEVICE_MODE_MAX,
+};
+
+struct SmsMsgHdr_ST {
+       u16     msgType;
+       u8      msgSrcId;
+       u8      msgDstId;
+       u16     msgLength; /* Length of entire message, including header */
+       u16     msgFlags;
+};
+
+struct SmsMsgData_ST {
+       struct SmsMsgHdr_ST     xMsgHeader;
+       u32                     msgData[1];
+};
+
+struct SmsDataDownload_ST {
+       struct SmsMsgHdr_ST     xMsgHeader;
+       u32                     MemAddr;
+       u8                      Payload[SMS_MAX_PAYLOAD_SIZE];
+};
+
+struct SmsVersionRes_ST {
+       struct SmsMsgHdr_ST     xMsgHeader;
+
+       u16             ChipModel; /* e.g. 0x1102 for SMS-1102 "Nova" */
+       u8              Step; /* 0 - Step A */
+       u8              MetalFix; /* 0 - Metal 0 */
+
+       u8              FirmwareId; /* 0xFF � ROM, otherwise the
+                                    * value indicated by
+                                    * SMSHOSTLIB_DEVICE_MODES_E */
+       u8              SupportedProtocols; /* Bitwise OR combination of
+                                            * supported protocols */
+
+       u8              VersionMajor;
+       u8              VersionMinor;
+       u8              VersionPatch;
+       u8              VersionFieldPatch;
+
+       u8              RomVersionMajor;
+       u8              RomVersionMinor;
+       u8              RomVersionPatch;
+       u8              RomVersionFieldPatch;
+
+       u8              TextLabel[34];
+};
+
+struct SmsFirmware_ST {
+       u32                     CheckSum;
+       u32                     Length;
+       u32                     StartAddress;
+       u8                      Payload[1];
+};
+
+struct SMSHOSTLIB_STATISTICS_ST {
+       u32 Reserved; /* Reserved */
+
+       /* Common parameters */
+       u32 IsRfLocked; /* 0 - not locked, 1 - locked */
+       u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
+       u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
+
+       /* Reception quality */
+       s32  SNR; /* dB */
+       u32 BER; /* Post Viterbi BER [1E-5] */
+       u32 FIB_CRC;    /* CRC errors percentage, valid only for DAB */
+       u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A,
+                    * valid only for DVB-T/H */
+       u32 MFER; /* DVB-H frame error rate in percentage,
+                  * 0xFFFFFFFF indicate N/A, valid only for DVB-H */
+       s32  RSSI; /* dBm */
+       s32  InBandPwr; /* In band power in dBM */
+       s32  CarrierOffset; /* Carrier Offset in bin/1024 */
+
+       /* Transmission parameters, valid only for DVB-T/H */
+       u32 Frequency; /* Frequency in Hz */
+       u32 Bandwidth; /* Bandwidth in MHz */
+       u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4,
+                              * for DVB-T/H FFT mode carriers in Kilos */
+       u32 ModemState; /* from SMS_DvbModemState_ET */
+       u32 GuardInterval; /* Guard Interval, 1 divided by value */
+       u32 CodeRate; /* Code Rate from SMS_DvbModemState_ET */
+       u32 LPCodeRate; /* Low Priority Code Rate from SMS_DvbModemState_ET */
+       u32 Hierarchy; /* Hierarchy from SMS_Hierarchy_ET */
+       u32 Constellation; /* Constellation from SMS_Constellation_ET */
+
+       /* Burst parameters, valid only for DVB-H */
+       u32 BurstSize; /* Current burst size in bytes */
+       u32 BurstDuration; /* Current burst duration in mSec */
+       u32 BurstCycleTime; /* Current burst cycle time in mSec */
+       u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec,
+                                      * as calculated by demodulator */
+       u32 NumOfRows; /* Number of rows in MPE table */
+       u32 NumOfPaddCols; /* Number of padding columns in MPE table */
+       u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */
+       /* Burst parameters */
+       u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
+       u32 TotalTSPackets; /* Total number of transport-stream packets */
+       u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include
+                               * errors after MPE RS decoding */
+       u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include errors
+                                 * after MPE RS decoding */
+       u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were corrected
+                                   * by MPE RS decoding */
+
+       /* Common params */
+       u32 BERErrorCount; /* Number of errornous SYNC bits. */
+       u32 BERBitCount; /* Total number of SYNC bits. */
+
+       /* Interface information */
+       u32 SmsToHostTxErrors; /* Total number of transmission errors. */
+
+       /* DAB/T-DMB */
+       u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */
+
+       /* DVB-H TPS parameters */
+       u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero;
+                    * if set to 0xFFFFFFFF cell_id not yet recovered */
+
+};
+
+struct SmsMsgStatisticsInfo_ST {
+       u32 RequestResult;
+
+       struct SMSHOSTLIB_STATISTICS_ST Stat;
+
+       /* Split the calc of the SNR in DAB */
+       u32 Signal; /* dB */
+       u32 Noise; /* dB */
+
+};
+
+
+struct smsdvb_client_t {
+       struct list_head entry;
+
+       struct smscore_device_t *coredev;
+       struct smscore_client_t *smsclient;
+
+       struct dvb_adapter      adapter;
+       struct dvb_demux        demux;
+       struct dmxdev           dmxdev;
+       struct dvb_frontend     frontend;
+
+       fe_status_t             fe_status;
+       int                     fe_ber, fe_snr, fe_signal_strength;
+
+       struct completion       tune_done, stat_done;
+
+       /* todo: save freq/band instead whole struct */
+       struct dvb_frontend_parameters fe_params;
+
+};
+
+extern void smscore_registry_setmode(char *devpath, int mode);
+extern int smscore_registry_getmode(char *devpath);
+
+extern int smscore_register_hotplug(hotplug_t hotplug);
+extern void smscore_unregister_hotplug(hotplug_t hotplug);
+
+extern int smscore_register_device(struct smsdevice_params_t *params,
+                                  struct smscore_device_t **coredev);
+extern void smscore_unregister_device(struct smscore_device_t *coredev);
+
+extern int smscore_start_device(struct smscore_device_t *coredev);
+extern int smscore_load_firmware(struct smscore_device_t *coredev,
+                                char *filename,
+                                loadfirmware_t loadfirmware_handler);
+
+extern int smscore_set_device_mode(struct smscore_device_t *coredev, int mode);
+extern int smscore_get_device_mode(struct smscore_device_t *coredev);
+
+extern int smscore_register_client(struct smscore_device_t *coredev,
+                                   struct smsclient_params_t *params,
+                                   struct smscore_client_t **client);
+extern void smscore_unregister_client(struct smscore_client_t *client);
+
+extern int smsclient_sendrequest(struct smscore_client_t *client,
+                                void *buffer, size_t size);
+extern void smscore_onresponse(struct smscore_device_t *coredev,
+                              struct smscore_buffer_t *cb);
+
+
+extern
+struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev);
+extern void smscore_putbuffer(struct smscore_device_t *coredev,
+                             struct smscore_buffer_t *cb);
+
+void smscore_set_board_id(struct smscore_device_t *core, int id);
+int smscore_get_board_id(struct smscore_device_t *core);
+
+/* smsdvb.c */
+int smsdvb_register(void);
+void smsdvb_unregister(void);
+
+/* smsusb.c */
+int smsusb_register(void);
+void smsusb_unregister(void);
+
+/* ------------------------------------------------------------------------ */
+
+extern int sms_debug;
+
+#define DBG_INFO 1
+#define DBG_ADV  2
+
+#define sms_printk(kern, fmt, arg...) \
+       printk(kern "%s: " fmt "\n", __func__, ##arg)
+
+#define dprintk(kern, lvl, fmt, arg...) do {\
+       if (sms_debug & lvl) \
+               sms_printk(kern, fmt, ##arg); } while (0)
+
+#define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
+#define sms_err(fmt, arg...) \
+       sms_printk(KERN_ERR, "line: %d: " fmt, __LINE__, ##arg)
+#define sms_warn(fmt, arg...)  sms_printk(KERN_WARNING, fmt, ##arg)
+#define sms_info(fmt, arg...) \
+       dprintk(KERN_INFO, DBG_INFO, fmt, ##arg)
+#define sms_debug(fmt, arg...) \
+       dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg)
+
+
+#endif /* __smscoreapi_h__ */
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
new file mode 100644 (file)
index 0000000..6f9c185
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ *  Driver for the Siano SMS1xxx USB dongle
+ *
+ *  author: Anatoly Greenblat
+ *
+ *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation;
+ *
+ *  Software distributed under the License is distributed on an "AS IS"
+ *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ *  See the GNU General Public License for more details.
+ *
+ *  You 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 "smscoreapi.h"
+#include "sms-cards.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct list_head g_smsdvb_clients;
+struct mutex g_smsdvb_clientslock;
+
+static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
+{
+       struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
+       struct SmsMsgHdr_ST *phdr =
+               (struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset);
+
+       switch (phdr->msgType) {
+       case MSG_SMS_DVBT_BDA_DATA:
+               dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
+                                cb->size - sizeof(struct SmsMsgHdr_ST));
+               break;
+
+       case MSG_SMS_RF_TUNE_RES:
+               complete(&client->tune_done);
+               break;
+
+       case MSG_SMS_GET_STATISTICS_RES:
+       {
+               struct SmsMsgStatisticsInfo_ST *p =
+                       (struct SmsMsgStatisticsInfo_ST *)(phdr + 1);
+
+               if (p->Stat.IsDemodLocked) {
+                       client->fe_status = FE_HAS_SIGNAL |
+                                           FE_HAS_CARRIER |
+                                           FE_HAS_VITERBI |
+                                           FE_HAS_SYNC |
+                                           FE_HAS_LOCK;
+
+                       client->fe_snr = p->Stat.SNR;
+                       client->fe_ber = p->Stat.BER;
+
+                       if (p->Stat.InBandPwr < -95)
+                               client->fe_signal_strength = 0;
+                       else if (p->Stat.InBandPwr > -29)
+                               client->fe_signal_strength = 100;
+                       else
+                               client->fe_signal_strength =
+                                       (p->Stat.InBandPwr + 95) * 3 / 2;
+               } else {
+                       client->fe_status = 0;
+                       client->fe_snr =
+                       client->fe_ber =
+                       client->fe_signal_strength = 0;
+               }
+
+               complete(&client->stat_done);
+               break;
+       } }
+
+       smscore_putbuffer(client->coredev, cb);
+
+       return 0;
+}
+
+static void smsdvb_unregister_client(struct smsdvb_client_t *client)
+{
+       /* must be called under clientslock */
+
+       list_del(&client->entry);
+
+       smscore_unregister_client(client->smsclient);
+       dvb_unregister_frontend(&client->frontend);
+       dvb_dmxdev_release(&client->dmxdev);
+       dvb_dmx_release(&client->demux);
+       dvb_unregister_adapter(&client->adapter);
+       kfree(client);
+}
+
+static void smsdvb_onremove(void *context)
+{
+       kmutex_lock(&g_smsdvb_clientslock);
+
+       smsdvb_unregister_client((struct smsdvb_client_t *) context);
+
+       kmutex_unlock(&g_smsdvb_clientslock);
+}
+
+static int smsdvb_start_feed(struct dvb_demux_feed *feed)
+{
+       struct smsdvb_client_t *client =
+               container_of(feed->demux, struct smsdvb_client_t, demux);
+       struct SmsMsgData_ST PidMsg;
+
+       sms_debug("add pid %d(%x)",
+                 feed->pid, feed->pid);
+
+       PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+       PidMsg.xMsgHeader.msgDstId = HIF_TASK;
+       PidMsg.xMsgHeader.msgFlags = 0;
+       PidMsg.xMsgHeader.msgType  = MSG_SMS_ADD_PID_FILTER_REQ;
+       PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
+       PidMsg.msgData[0] = feed->pid;
+
+       return smsclient_sendrequest(client->smsclient,
+                                    &PidMsg, sizeof(PidMsg));
+}
+
+static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
+{
+       struct smsdvb_client_t *client =
+               container_of(feed->demux, struct smsdvb_client_t, demux);
+       struct SmsMsgData_ST PidMsg;
+
+       sms_debug("remove pid %d(%x)",
+                 feed->pid, feed->pid);
+
+       PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+       PidMsg.xMsgHeader.msgDstId = HIF_TASK;
+       PidMsg.xMsgHeader.msgFlags = 0;
+       PidMsg.xMsgHeader.msgType  = MSG_SMS_REMOVE_PID_FILTER_REQ;
+       PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
+       PidMsg.msgData[0] = feed->pid;
+
+       return smsclient_sendrequest(client->smsclient,
+                                    &PidMsg, sizeof(PidMsg));
+}
+
+static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
+                                       void *buffer, size_t size,
+                                       struct completion *completion)
+{
+       int rc = smsclient_sendrequest(client->smsclient, buffer, size);
+       if (rc < 0)
+               return rc;
+
+       return wait_for_completion_timeout(completion,
+                                          msecs_to_jiffies(2000)) ?
+                                               0 : -ETIME;
+}
+
+static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
+{
+       struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
+                            DVBT_BDA_CONTROL_MSG_ID,
+                            HIF_TASK, sizeof(struct SmsMsgHdr_ST), 0 };
+       return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+                                          &client->stat_done);
+}
+
+static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+       struct smsdvb_client_t *client =
+               container_of(fe, struct smsdvb_client_t, frontend);
+       int rc = smsdvb_send_statistics_request(client);
+
+       if (!rc)
+               *stat = client->fe_status;
+
+       return rc;
+}
+
+static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       struct smsdvb_client_t *client =
+               container_of(fe, struct smsdvb_client_t, frontend);
+       int rc = smsdvb_send_statistics_request(client);
+
+       if (!rc)
+               *ber = client->fe_ber;
+
+       return rc;
+}
+
+static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+       struct smsdvb_client_t *client =
+               container_of(fe, struct smsdvb_client_t, frontend);
+       int rc = smsdvb_send_statistics_request(client);
+
+       if (!rc)
+               *strength = client->fe_signal_strength;
+
+       return rc;
+}
+
+static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+       struct smsdvb_client_t *client =
+               container_of(fe, struct smsdvb_client_t, frontend);
+       int rc = smsdvb_send_statistics_request(client);
+
+       if (!rc)
+               *snr = client->fe_snr;
+
+       return rc;
+}
+
+static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
+                                   struct dvb_frontend_tune_settings *tune)
+{
+       sms_debug("");
+
+       tune->min_delay_ms = 400;
+       tune->step_size = 250000;
+       tune->max_drift = 0;
+       return 0;
+}
+
+static int smsdvb_set_frontend(struct dvb_frontend *fe,
+                              struct dvb_frontend_parameters *fep)
+{
+       struct smsdvb_client_t *client =
+               container_of(fe, struct smsdvb_client_t, frontend);
+
+       struct {
+               struct SmsMsgHdr_ST     Msg;
+               u32             Data[3];
+       } Msg;
+
+       Msg.Msg.msgSrcId  = DVBT_BDA_CONTROL_MSG_ID;
+       Msg.Msg.msgDstId  = HIF_TASK;
+       Msg.Msg.msgFlags  = 0;
+       Msg.Msg.msgType   = MSG_SMS_RF_TUNE_REQ;
+       Msg.Msg.msgLength = sizeof(Msg);
+       Msg.Data[0] = fep->frequency;
+       Msg.Data[2] = 12000000;
+
+       sms_debug("freq %d band %d",
+                 fep->frequency, fep->u.ofdm.bandwidth);
+
+       switch (fep->u.ofdm.bandwidth) {
+       case BANDWIDTH_8_MHZ: Msg.Data[1] = BW_8_MHZ; break;
+       case BANDWIDTH_7_MHZ: Msg.Data[1] = BW_7_MHZ; break;
+       case BANDWIDTH_6_MHZ: Msg.Data[1] = BW_6_MHZ; break;
+       case BANDWIDTH_AUTO: return -EOPNOTSUPP;
+       default: return -EINVAL;
+       }
+
+       return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+                                          &client->tune_done);
+}
+
+static int smsdvb_get_frontend(struct dvb_frontend *fe,
+                              struct dvb_frontend_parameters *fep)
+{
+       struct smsdvb_client_t *client =
+               container_of(fe, struct smsdvb_client_t, frontend);
+
+       sms_debug("");
+
+       /* todo: */
+       memcpy(fep, &client->fe_params,
+              sizeof(struct dvb_frontend_parameters));
+       return 0;
+}
+
+static void smsdvb_release(struct dvb_frontend *fe)
+{
+       /* do nothing */
+}
+
+static struct dvb_frontend_ops smsdvb_fe_ops = {
+       .info = {
+               .name                   = "Siano Mobile Digital SMS1xxx",
+               .type                   = FE_OFDM,
+               .frequency_min          = 44250000,
+               .frequency_max          = 867250000,
+               .frequency_stepsize     = 250000,
+               .caps = FE_CAN_INVERSION_AUTO |
+                       FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                       FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+                       FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+                       FE_CAN_GUARD_INTERVAL_AUTO |
+                       FE_CAN_RECOVER |
+                       FE_CAN_HIERARCHY_AUTO,
+       },
+
+       .release = smsdvb_release,
+
+       .set_frontend = smsdvb_set_frontend,
+       .get_frontend = smsdvb_get_frontend,
+       .get_tune_settings = smsdvb_get_tune_settings,
+
+       .read_status = smsdvb_read_status,
+       .read_ber = smsdvb_read_ber,
+       .read_signal_strength = smsdvb_read_signal_strength,
+       .read_snr = smsdvb_read_snr,
+};
+
+static int smsdvb_hotplug(struct smscore_device_t *coredev,
+                         struct device *device, int arrival)
+{
+       struct smsclient_params_t params;
+       struct smsdvb_client_t *client;
+       int rc;
+
+       /* device removal handled by onremove callback */
+       if (!arrival)
+               return 0;
+
+       if (smscore_get_device_mode(coredev) != 4) {
+               sms_err("SMS Device mode is not set for "
+                       "DVB operation.");
+               return 0;
+       }
+
+       client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
+       if (!client) {
+               sms_err("kmalloc() failed");
+               return -ENOMEM;
+       }
+
+       /* register dvb adapter */
+       rc = dvb_register_adapter(&client->adapter,
+                                 sms_get_board(
+                                       smscore_get_board_id(coredev))->name,
+                                 THIS_MODULE, device, adapter_nr);
+       if (rc < 0) {
+               sms_err("dvb_register_adapter() failed %d", rc);
+               goto adapter_error;
+       }
+
+       /* init dvb demux */
+       client->demux.dmx.capabilities = DMX_TS_FILTERING;
+       client->demux.filternum = 32; /* todo: nova ??? */
+       client->demux.feednum = 32;
+       client->demux.start_feed = smsdvb_start_feed;
+       client->demux.stop_feed = smsdvb_stop_feed;
+
+       rc = dvb_dmx_init(&client->demux);
+       if (rc < 0) {
+               sms_err("dvb_dmx_init failed %d", rc);
+               goto dvbdmx_error;
+       }
+
+       /* init dmxdev */
+       client->dmxdev.filternum = 32;
+       client->dmxdev.demux = &client->demux.dmx;
+       client->dmxdev.capabilities = 0;
+
+       rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
+       if (rc < 0) {
+               sms_err("dvb_dmxdev_init failed %d", rc);
+               goto dmxdev_error;
+       }
+
+       /* init and register frontend */
+       memcpy(&client->frontend.ops, &smsdvb_fe_ops,
+              sizeof(struct dvb_frontend_ops));
+
+       rc = dvb_register_frontend(&client->adapter, &client->frontend);
+       if (rc < 0) {
+               sms_err("frontend registration failed %d", rc);
+               goto frontend_error;
+       }
+
+       params.initial_id = 1;
+       params.data_type = MSG_SMS_DVBT_BDA_DATA;
+       params.onresponse_handler = smsdvb_onresponse;
+       params.onremove_handler = smsdvb_onremove;
+       params.context = client;
+
+       rc = smscore_register_client(coredev, &params, &client->smsclient);
+       if (rc < 0) {
+               sms_err("smscore_register_client() failed %d", rc);
+               goto client_error;
+       }
+
+       client->coredev = coredev;
+
+       init_completion(&client->tune_done);
+       init_completion(&client->stat_done);
+
+       kmutex_lock(&g_smsdvb_clientslock);
+
+       list_add(&client->entry, &g_smsdvb_clients);
+
+       kmutex_unlock(&g_smsdvb_clientslock);
+
+       sms_info("success");
+
+       return 0;
+
+client_error:
+       dvb_unregister_frontend(&client->frontend);
+
+frontend_error:
+       dvb_dmxdev_release(&client->dmxdev);
+
+dmxdev_error:
+       dvb_dmx_release(&client->demux);
+
+dvbdmx_error:
+       dvb_unregister_adapter(&client->adapter);
+
+adapter_error:
+       kfree(client);
+       return rc;
+}
+
+int smsdvb_register(void)
+{
+       int rc;
+
+       INIT_LIST_HEAD(&g_smsdvb_clients);
+       kmutex_init(&g_smsdvb_clientslock);
+
+       rc = smscore_register_hotplug(smsdvb_hotplug);
+
+       sms_debug("");
+
+       return rc;
+}
+
+void smsdvb_unregister(void)
+{
+       smscore_unregister_hotplug(smsdvb_hotplug);
+
+       kmutex_lock(&g_smsdvb_clientslock);
+
+       while (!list_empty(&g_smsdvb_clients))
+              smsdvb_unregister_client(
+                       (struct smsdvb_client_t *) g_smsdvb_clients.next);
+
+       kmutex_unlock(&g_smsdvb_clientslock);
+}
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
new file mode 100644 (file)
index 0000000..c10b184
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ *  Driver for the Siano SMS1xxx USB dongle
+ *
+ *  author: Anatoly Greenblat
+ *
+ *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation;
+ *
+ *  Software distributed under the License is distributed on an "AS IS"
+ *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ *  See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *