Merge ../linux-2.6
Mauro Carvalho Chehab [Sun, 27 Jul 2008 15:25:57 +0000 (12:25 -0300)]
205 files changed:
Documentation/video4linux/CARDLIST.au0828
Documentation/video4linux/CARDLIST.em28xx
Documentation/video4linux/gspca.txt
MAINTAINERS
drivers/media/common/saa7146_fops.c
drivers/media/common/saa7146_video.c
drivers/media/common/tuners/Kconfig
drivers/media/common/tuners/Makefile
drivers/media/common/tuners/mt20xx.c
drivers/media/common/tuners/mxl5007t.c [new file with mode: 0644]
drivers/media/common/tuners/mxl5007t.h [new file with mode: 0644]
drivers/media/common/tuners/tda9887.c
drivers/media/common/tuners/tuner-simple.c
drivers/media/dvb/bt8xx/Kconfig
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/dvb-usb/anysee.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dw2102.c [new file with mode: 0644]
drivers/media/dvb/dvb-usb/dw2102.h [new file with mode: 0644]
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/drx397xD.c [new file with mode: 0644]
drivers/media/dvb/frontends/drx397xD.h [new file with mode: 0644]
drivers/media/dvb/frontends/drx397xD_fw.h [new file with mode: 0644]
drivers/media/dvb/frontends/z0194a.h [new file with mode: 0644]
drivers/media/dvb/siano/smscoreapi.c
drivers/media/dvb/siano/smsdvb.c
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttusb-dec/Kconfig
drivers/media/radio/dsbr100.c
drivers/media/radio/miropcm20-radio.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-si470x.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/arv.c
drivers/media/video/au0828/Kconfig
drivers/media/video/au0828/au0828-cards.c
drivers/media/video/au0828/au0828-cards.h
drivers/media/video/au0828/au0828-dvb.c
drivers/media/video/bt8xx/Kconfig
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-risc.c
drivers/media/video/bt8xx/bttv-vbi.c
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic.c
drivers/media/video/compat_ioctl32.c
drivers/media/video/cpia.c
drivers/media/video/cpia.h
drivers/media/video/cpia2/cpia2_core.c
drivers/media/video/cpia2/cpia2_v4l.c
drivers/media/video/cs5345.c
drivers/media/video/cs53l32a.c
drivers/media/video/cx18/Kconfig
drivers/media/video/cx18/cx18-av-audio.c
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-firmware.c
drivers/media/video/cx18/cx18-ioctl.c
drivers/media/video/cx18/cx18-streams.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-video.c
drivers/media/video/cx25840/Kconfig
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx25840/cx25840-core.h
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-dvb.c
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/gspca/conex.c
drivers/media/video/gspca/etoms.c
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/mars.c
drivers/media/video/gspca/ov519.c
drivers/media/video/gspca/pac207.c
drivers/media/video/gspca/pac7311.c
drivers/media/video/gspca/sonixb.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/gspca/spca500.c
drivers/media/video/gspca/spca501.c
drivers/media/video/gspca/spca505.c
drivers/media/video/gspca/spca506.c
drivers/media/video/gspca/spca508.c
drivers/media/video/gspca/spca561.c
drivers/media/video/gspca/stk014.c
drivers/media/video/gspca/sunplus.c
drivers/media/video/gspca/t613.c
drivers/media/video/gspca/tv8532.c
drivers/media/video/gspca/vc032x.c
drivers/media/video/gspca/zc3xx.c
drivers/media/video/ivtv/Kconfig
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-streams.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/mt9m001.c
drivers/media/video/ov511.c
drivers/media/video/ov511.h
drivers/media/video/planb.c
drivers/media/video/planb.h
drivers/media/video/pms.c
drivers/media/video/pvrusb2/Kconfig
drivers/media/video/pvrusb2/pvrusb2-context.h
drivers/media/video/pvrusb2/pvrusb2-devattr.c
drivers/media/video/pvrusb2/pvrusb2-devattr.h
drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc.h
drivers/media/video/s2255drv.c
drivers/media/video/saa5246a.c
drivers/media/video/saa5249.c
drivers/media/video/saa7134/Kconfig
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134-video.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/saa717x.c
drivers/media/video/saa7196.h
drivers/media/video/se401.c
drivers/media/video/se401.h
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/sn9c102/sn9c102.h
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/soc_camera.c
drivers/media/video/stk-webcam.c
drivers/media/video/stradis.c
drivers/media/video/stv680.c
drivers/media/video/tda7432.c
drivers/media/video/tda9875.c
drivers/media/video/tlv320aic23b.c
drivers/media/video/tuner-core.c
drivers/media/video/tveeprom.c
drivers/media/video/tvp5150.c
drivers/media/video/usbvideo/usbvideo.c
drivers/media/video/usbvideo/usbvideo.h
drivers/media/video/usbvideo/vicam.c
drivers/media/video/usbvision/usbvision-core.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_driver.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/v4l2-dev.c [new file with mode: 0644]
drivers/media/video/v4l2-ioctl.c [new file with mode: 0644]
drivers/media/video/videobuf-dma-contig.c
drivers/media/video/videobuf-vmalloc.c
drivers/media/video/videodev.c
drivers/media/video/vino.c
drivers/media/video/vivi.c
drivers/media/video/vp27smpx.c
drivers/media/video/w9966.c
drivers/media/video/w9968cf.c
drivers/media/video/w9968cf.h
drivers/media/video/wm8739.c
drivers/media/video/wm8775.c
drivers/media/video/zc0301/zc0301.h
drivers/media/video/zc0301/zc0301_core.c
drivers/media/video/zoran_card.c
drivers/media/video/zoran_card.h
drivers/media/video/zoran_driver.c
drivers/media/video/zr364xx.c
include/linux/videodev.h
include/linux/videodev2.h
include/linux/videotext.h
include/media/audiochip.h
include/media/saa7146_vv.h
include/media/tveeprom.h
include/media/v4l2-chip-ident.h
include/media/v4l2-common.h
include/media/v4l2-dev.h
include/media/v4l2-ioctl.h [new file with mode: 0644]
sound/i2c/other/tea575x-tuner.c

index 86d1c8e..eedc399 100644 (file)
@@ -2,3 +2,4 @@
   1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200,2040:7210,2040:7217,2040:721b,2040:721f,2040:7280,0fd9:0008]
   2 -> Hauppauge HVR850                         (au0828)        [2040:7240]
   3 -> DViCO FusionHDTV USB                     (au0828)        [0fe9:d620]
+  4 -> Hauppauge HVR950Q rev xxF8               (au0828)        [2040:7201,2040:7211,2040:7281]
index 1059146..ef0c3dd 100644 (file)
@@ -18,3 +18,4 @@
  17 -> Pinnacle PCTV HD Pro Stick               (em2880)        [2304:0227]
  18 -> Hauppauge WinTV HVR 900 (R2)             (em2880)        [2040:6502]
  19 -> PointNix Intra-Oral Camera               (em2860)
+ 20 -> AMD ATI TV Wonder HD 600                 (em2880)        [0438:b002]
index 0c4880a..bcaf4ab 100644 (file)
@@ -1,4 +1,4 @@
-List of the webcams know by gspca.
+List of the webcams known by gspca.
 
 The modules are:
        gspca_main      main driver
index 03c5d6c..deedc0d 100644 (file)
@@ -3796,6 +3796,12 @@ P:       Ben Nizette
 M:     bn@niasdigital.com
 S:     Maintained
 
+SOC-CAMERA V4L2 SUBSYSTEM
+P:     Guennadi Liakhovetski
+M:     g.liakhovetski@gmx.de
+L:     video4linux-list@redhat.com
+S:     Maintained
+
 SOFTWARE RAID (Multiple Disks) SUPPORT
 P:     Ingo Molnar
 M:     mingo@redhat.com
index 171afe7..cf6a817 100644 (file)
@@ -563,7 +563,7 @@ int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev
 
        DEB_EE(("dev:%p\n",dev));
 
-       if( VFL_TYPE_GRABBER == (*vid)->type ) {
+       if ((*vid)->vfl_type == VFL_TYPE_GRABBER) {
                vv->video_minor = -1;
        } else {
                vv->vbi_minor = -1;
index a5e6275..acaddc1 100644 (file)
@@ -958,21 +958,18 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
        case VIDIOC_ENUM_FMT:
        {
                struct v4l2_fmtdesc *f = arg;
-               int index;
 
                switch (f->type) {
                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               case V4L2_BUF_TYPE_VIDEO_OVERLAY: {
-                       index = f->index;
-                       if (index < 0 || index >= NUM_FORMATS) {
+               case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+                       if (f->index >= NUM_FORMATS)
                                return -EINVAL;
-                       }
-                       memset(f,0,sizeof(*f));
-                       f->index = index;
-                       strlcpy((char *)f->description,formats[index].name,sizeof(f->description));
-                       f->pixelformat = formats[index].pixelformat;
+                       strlcpy((char *)f->description, formats[f->index].name,
+                                       sizeof(f->description));
+                       f->pixelformat = formats[f->index].pixelformat;
+                       f->flags = 0;
+                       memset(f->reserved, 0, sizeof(f->reserved));
                        break;
-               }
                default:
                        return -EINVAL;
                }
index 850d568..6f92bea 100644 (file)
@@ -21,9 +21,8 @@ config MEDIA_TUNER
        tristate
        default VIDEO_MEDIA && I2C
        depends on VIDEO_MEDIA && I2C
-       select FW_LOADER if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
-       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
-       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
+       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
+       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE
        select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE
        select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE
        select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE
@@ -138,8 +137,6 @@ config MEDIA_TUNER_QT1010
 config MEDIA_TUNER_XC2028
        tristate "XCeive xc2028/xc3028 tuners"
        depends on VIDEO_MEDIA && I2C
-       depends on HOTPLUG
-       select FW_LOADER
        default m if MEDIA_TUNER_CUSTOMIZE
        help
          Say Y here to include support for the xc2028/xc3028 tuners.
@@ -147,8 +144,6 @@ config MEDIA_TUNER_XC2028
 config MEDIA_TUNER_XC5000
        tristate "Xceive XC5000 silicon tuner"
        depends on VIDEO_MEDIA && I2C
-       depends on HOTPLUG
-       select FW_LOADER
        default m if DVB_FE_CUSTOMISE
        help
          A driver for the silicon tuner XC5000 from Xceive.
@@ -162,4 +157,11 @@ config MEDIA_TUNER_MXL5005S
        help
          A driver for the silicon tuner MXL5005S from MaxLinear.
 
+config MEDIA_TUNER_MXL5007T
+       tristate "MaxLinear MxL5007T silicon tuner"
+       depends on VIDEO_MEDIA && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A driver for the silicon tuner MxL5007T from MaxLinear.
+
 endif # MEDIA_TUNER_CUSTOMIZE
index 55f7e67..4dfbe5b 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
 obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
 obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
 obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o
+obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
index fbcb282..35b763a 100644 (file)
@@ -148,7 +148,8 @@ static int mt2032_compute_freq(struct dvb_frontend *fe,
        tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
                  rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
 
-       if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
+       if (lo1a > 7 || lo1n < 17 || lo1n > 48 || lo2a > 7 || lo2n < 17 ||
+                       lo2n > 30) {
                tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
                           lo1a, lo1n, lo2a,lo2n);
                return(-1);
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c
new file mode 100644 (file)
index 0000000..cb25e43
--- /dev/null
@@ -0,0 +1,1030 @@
+/*
+ *  mxl5007t.c - driver for the MaxLinear MxL5007T silicon tuner
+ *
+ *  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 as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include "tuner-i2c.h"
+#include "mxl5007t.h"
+
+static DEFINE_MUTEX(mxl5007t_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
+
+static int mxl5007t_debug;
+module_param_named(debug, mxl5007t_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level");
+
+/* ------------------------------------------------------------------------- */
+
+#define mxl_printk(kern, fmt, arg...) \
+       printk(kern "%s: " fmt "\n", __func__, ##arg)
+
+#define mxl_err(fmt, arg...) \
+       mxl_printk(KERN_ERR, "%d: " fmt, __LINE__, ##arg)
+
+#define mxl_warn(fmt, arg...) \
+       mxl_printk(KERN_WARNING, fmt, ##arg)
+
+#define mxl_info(fmt, arg...) \
+       mxl_printk(KERN_INFO, fmt, ##arg)
+
+#define mxl_debug(fmt, arg...)                         \
+({                                                     \
+       if (mxl5007t_debug)                             \
+               mxl_printk(KERN_DEBUG, fmt, ##arg);     \
+})
+
+#define mxl_fail(ret)                                                  \
+({                                                                     \
+       int __ret;                                                      \
+       __ret = (ret < 0);                                              \
+       if (__ret)                                                      \
+               mxl_printk(KERN_ERR, "error %d on line %d",             \
+                          ret, __LINE__);                              \
+       __ret;                                                          \
+})
+
+/* ------------------------------------------------------------------------- */
+
+#define MHz 1000000
+
+enum mxl5007t_mode {
+       MxL_MODE_OTA_DVBT_ATSC        =    0,
+       MxL_MODE_OTA_NTSC_PAL_GH      =    1,
+       MxL_MODE_OTA_PAL_IB           =    2,
+       MxL_MODE_OTA_PAL_D_SECAM_KL   =    3,
+       MxL_MODE_OTA_ISDBT            =    4,
+       MxL_MODE_CABLE_DIGITAL        = 0x10,
+       MxL_MODE_CABLE_NTSC_PAL_GH    = 0x11,
+       MxL_MODE_CABLE_PAL_IB         = 0x12,
+       MxL_MODE_CABLE_PAL_D_SECAM_KL = 0x13,
+       MxL_MODE_CABLE_SCTE40         = 0x14,
+};
+
+enum mxl5007t_chip_version {
+       MxL_UNKNOWN_ID     = 0x00,
+       MxL_5007_V1_F1     = 0x11,
+       MxL_5007_V1_F2     = 0x12,
+       MxL_5007_V2_100_F1 = 0x21,
+       MxL_5007_V2_100_F2 = 0x22,
+       MxL_5007_V2_200_F1 = 0x23,
+       MxL_5007_V2_200_F2 = 0x24,
+};
+
+struct reg_pair_t {
+       u8 reg;
+       u8 val;
+};
+
+/* ------------------------------------------------------------------------- */
+
+static struct reg_pair_t init_tab[] = {
+       { 0x0b, 0x44 }, /* XTAL */
+       { 0x0c, 0x60 }, /* IF */
+       { 0x10, 0x00 }, /* MISC */
+       { 0x12, 0xca }, /* IDAC */
+       { 0x16, 0x90 }, /* MODE */
+       { 0x32, 0x38 }, /* MODE Analog/Digital */
+       { 0xd8, 0x18 }, /* CLK_OUT_ENABLE */
+       { 0x2c, 0x34 }, /* OVERRIDE */
+       { 0x4d, 0x40 }, /* OVERRIDE */
+       { 0x7f, 0x02 }, /* OVERRIDE */
+       { 0x9a, 0x52 }, /* OVERRIDE */
+       { 0x48, 0x5a }, /* OVERRIDE */
+       { 0x76, 0x1a }, /* OVERRIDE */
+       { 0x6a, 0x48 }, /* OVERRIDE */
+       { 0x64, 0x28 }, /* OVERRIDE */
+       { 0x66, 0xe6 }, /* OVERRIDE */
+       { 0x35, 0x0e }, /* OVERRIDE */
+       { 0x7e, 0x01 }, /* OVERRIDE */
+       { 0x83, 0x00 }, /* OVERRIDE */
+       { 0x04, 0x0b }, /* OVERRIDE */
+       { 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
+       { 0, 0 }
+};
+
+static struct reg_pair_t init_tab_cable[] = {
+       { 0x0b, 0x44 }, /* XTAL */
+       { 0x0c, 0x60 }, /* IF */
+       { 0x10, 0x00 }, /* MISC */
+       { 0x12, 0xca }, /* IDAC */
+       { 0x16, 0x90 }, /* MODE */
+       { 0x32, 0x38 }, /* MODE A/D */
+       { 0x71, 0x3f }, /* TOP1 */
+       { 0x72, 0x3f }, /* TOP2 */
+       { 0x74, 0x3f }, /* TOP3 */
+       { 0xd8, 0x18 }, /* CLK_OUT_ENABLE */
+       { 0x2c, 0x34 }, /* OVERRIDE */
+       { 0x4d, 0x40 }, /* OVERRIDE */
+       { 0x7f, 0x02 }, /* OVERRIDE */
+       { 0x9a, 0x52 }, /* OVERRIDE */
+       { 0x48, 0x5a }, /* OVERRIDE */
+       { 0x76, 0x1a }, /* OVERRIDE */
+       { 0x6a, 0x48 }, /* OVERRIDE */
+       { 0x64, 0x28 }, /* OVERRIDE */
+       { 0x66, 0xe6 }, /* OVERRIDE */
+       { 0x35, 0x0e }, /* OVERRIDE */
+       { 0x7e, 0x01 }, /* OVERRIDE */
+       { 0x04, 0x0b }, /* OVERRIDE */
+       { 0x68, 0xb4 }, /* OVERRIDE */
+       { 0x36, 0x00 }, /* OVERRIDE */
+       { 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
+       { 0, 0 }
+};
+
+/* ------------------------------------------------------------------------- */
+
+static struct reg_pair_t reg_pair_rftune[] = {
+       { 0x11, 0x00 }, /* abort tune */
+       { 0x13, 0x15 },
+       { 0x14, 0x40 },
+       { 0x15, 0x0e },
+       { 0x11, 0x02 }, /* start tune */
+       { 0, 0 }
+};
+
+/* ------------------------------------------------------------------------- */
+
+struct mxl5007t_state {
+       struct list_head hybrid_tuner_instance_list;
+       struct tuner_i2c_props i2c_props;
+
+       struct mutex lock;
+
+       struct mxl5007t_config *config;
+
+       enum mxl5007t_chip_version chip_id;
+
+       struct reg_pair_t tab_init[ARRAY_SIZE(init_tab)];
+       struct reg_pair_t tab_init_cable[ARRAY_SIZE(init_tab_cable)];
+       struct reg_pair_t tab_rftune[ARRAY_SIZE(reg_pair_rftune)];
+
+       u32 frequency;
+       u32 bandwidth;
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* called by _init and _rftun to manipulate the register arrays */
+
+static void set_reg_bits(struct reg_pair_t *reg_pair, u8 reg, u8 mask, u8 val)
+{
+       unsigned int i = 0;
+
+       while (reg_pair[i].reg || reg_pair[i].val) {
+               if (reg_pair[i].reg == reg) {
+                       reg_pair[i].val &= ~mask;
+                       reg_pair[i].val |= val;
+               }
+               i++;
+
+       }
+       return;
+}
+
+static void copy_reg_bits(struct reg_pair_t *reg_pair1,
+                         struct reg_pair_t *reg_pair2)
+{
+       unsigned int i, j;
+
+       i = j = 0;
+
+       while (reg_pair1[i].reg || reg_pair1[i].val) {
+               while (reg_pair2[j].reg || reg_pair2[j].reg) {
+                       if (reg_pair1[i].reg != reg_pair2[j].reg) {
+                               j++;
+                               continue;
+                       }
+                       reg_pair2[j].val = reg_pair1[i].val;
+                       break;
+               }
+               i++;
+       }
+       return;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void mxl5007t_set_mode_bits(struct mxl5007t_state *state,
+                                  enum mxl5007t_mode mode,
+                                  s32 if_diff_out_level)
+{
+       switch (mode) {
+       case MxL_MODE_OTA_DVBT_ATSC:
+               set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06);
+               set_reg_bits(state->tab_init, 0x35, 0xff, 0x0e);
+               break;
+       case MxL_MODE_OTA_ISDBT:
+               set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06);
+               set_reg_bits(state->tab_init, 0x35, 0xff, 0x12);
+               break;
+       case MxL_MODE_OTA_NTSC_PAL_GH:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x00);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               break;
+       case MxL_MODE_OTA_PAL_IB:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x10);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               break;
+       case MxL_MODE_OTA_PAL_D_SECAM_KL:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x20);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               break;
+       case MxL_MODE_CABLE_DIGITAL:
+               set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
+               set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+                            8 - if_diff_out_level);
+               set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+               break;
+       case MxL_MODE_CABLE_NTSC_PAL_GH:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x00);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
+               set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+                            8 - if_diff_out_level);
+               set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+               break;
+       case MxL_MODE_CABLE_PAL_IB:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x10);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
+               set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+                            8 - if_diff_out_level);
+               set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+               break;
+       case MxL_MODE_CABLE_PAL_D_SECAM_KL:
+               set_reg_bits(state->tab_init, 0x16, 0x70, 0x20);
+               set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
+               set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
+               set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+                            8 - if_diff_out_level);
+               set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+               break;
+       case MxL_MODE_CABLE_SCTE40:
+               set_reg_bits(state->tab_init_cable, 0x36, 0xff, 0x08);
+               set_reg_bits(state->tab_init_cable, 0x68, 0xff, 0xbc);
+               set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
+               set_reg_bits(state->tab_init_cable, 0x72, 0xff,
+                            8 - if_diff_out_level);
+               set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
+               break;
+       default:
+               mxl_fail(-EINVAL);
+       }
+       return;
+}
+
+static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,
+                                     enum mxl5007t_if_freq if_freq,
+                                     int invert_if)
+{
+       u8 val;
+
+       switch (if_freq) {
+       case MxL_IF_4_MHZ:
+               val = 0x00;
+               break;
+       case MxL_IF_4_5_MHZ:
+               val = 0x20;
+               break;
+       case MxL_IF_4_57_MHZ:
+               val = 0x30;
+               break;
+       case MxL_IF_5_MHZ:
+               val = 0x40;
+               break;
+       case MxL_IF_5_38_MHZ:
+               val = 0x50;
+               break;
+       case MxL_IF_6_MHZ:
+               val = 0x60;
+               break;
+       case MxL_IF_6_28_MHZ:
+               val = 0x70;
+               break;
+       case MxL_IF_9_1915_MHZ:
+               val = 0x80;
+               break;
+       case MxL_IF_35_25_MHZ:
+               val = 0x90;
+               break;
+       case MxL_IF_36_15_MHZ:
+               val = 0xa0;
+               break;
+       case MxL_IF_44_MHZ:
+               val = 0xb0;
+               break;
+       default:
+               mxl_fail(-EINVAL);
+               return;
+       }
+       set_reg_bits(state->tab_init, 0x0c, 0xf0, val);
+
+       /* set inverted IF or normal IF */
+       set_reg_bits(state->tab_init, 0x0c, 0x08, invert_if ? 0x08 : 0x00);
+
+       return;
+}
+
+static void mxl5007t_set_xtal_freq_bits(struct mxl5007t_state *state,
+                                       enum mxl5007t_xtal_freq xtal_freq)
+{
+       u8 val;
+
+       switch (xtal_freq) {
+       case MxL_XTAL_16_MHZ:
+               val = 0x00; /* select xtal freq & Ref Freq */
+               break;
+       case MxL_XTAL_20_MHZ:
+               val = 0x11;
+               break;
+       case MxL_XTAL_20_25_MHZ:
+               val = 0x22;
+               break;
+       case MxL_XTAL_20_48_MHZ:
+               val = 0x33;
+               break;
+       case MxL_XTAL_24_MHZ:
+               val = 0x44;
+               break;
+       case MxL_XTAL_25_MHZ:
+               val = 0x55;
+               break;
+       case MxL_XTAL_25_14_MHZ:
+               val = 0x66;
+               break;
+       case MxL_XTAL_27_MHZ:
+               val = 0x77;
+               break;
+       case MxL_XTAL_28_8_MHZ:
+               val = 0x88;
+               break;
+       case MxL_XTAL_32_MHZ:
+               val = 0x99;
+               break;
+       case MxL_XTAL_40_MHZ:
+               val = 0xaa;
+               break;
+       case MxL_XTAL_44_MHZ:
+               val = 0xbb;
+               break;
+       case MxL_XTAL_48_MHZ:
+               val = 0xcc;
+               break;
+       case MxL_XTAL_49_3811_MHZ:
+               val = 0xdd;
+               break;
+       default:
+               mxl_fail(-EINVAL);
+               return;
+       }
+       set_reg_bits(state->tab_init, 0x0b, 0xff, val);
+
+       return;
+}
+
+static struct reg_pair_t *mxl5007t_calc_init_regs(struct mxl5007t_state *state,
+                                                 enum mxl5007t_mode mode)
+{
+       struct mxl5007t_config *cfg = state->config;
+
+       memcpy(&state->tab_init, &init_tab, sizeof(init_tab));
+       memcpy(&state->tab_init_cable, &init_tab_cable, sizeof(init_tab_cable));
+
+       mxl5007t_set_mode_bits(state, mode, cfg->if_diff_out_level);
+       mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if);
+       mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz);
+
+       set_reg_bits(state->tab_init, 0x10, 0x40, cfg->loop_thru_enable << 6);
+
+       set_reg_bits(state->tab_init, 0xd8, 0x08, cfg->clk_out_enable << 3);
+
+       set_reg_bits(state->tab_init, 0x10, 0x07, cfg->clk_out_amp);
+
+       /* set IDAC to automatic mode control by AGC */
+       set_reg_bits(state->tab_init, 0x12, 0x80, 0x00);
+
+       if (mode >= MxL_MODE_CABLE_DIGITAL) {
+               copy_reg_bits(state->tab_init, state->tab_init_cable);
+               return state->tab_init_cable;
+       } else
+               return state->tab_init;
+}
+
+/* ------------------------------------------------------------------------- */
+
+enum mxl5007t_bw_mhz {
+       MxL_BW_6MHz = 6,
+       MxL_BW_7MHz = 7,
+       MxL_BW_8MHz = 8,
+};
+
+static void mxl5007t_set_bw_bits(struct mxl5007t_state *state,
+                                enum mxl5007t_bw_mhz bw)
+{
+       u8 val;
+
+       switch (bw) {
+       case MxL_BW_6MHz:
+               val = 0x15; /* set DIG_MODEINDEX, DIG_MODEINDEX_A,
+                            * and DIG_MODEINDEX_CSF */
+               break;
+       case MxL_BW_7MHz:
+               val = 0x21;
+               break;
+       case MxL_BW_8MHz:
+               val = 0x3f;
+               break;
+       default:
+               mxl_fail(-EINVAL);
+               return;
+       }
+       set_reg_bits(state->tab_rftune, 0x13, 0x3f, val);
+
+       return;
+}
+
+static struct
+reg_pair_t *mxl5007t_calc_rf_tune_regs(struct mxl5007t_state *state,
+                                      u32 rf_freq, enum mxl5007t_bw_mhz bw)
+{
+       u32 dig_rf_freq = 0;
+       u32 temp;
+       u32 frac_divider = 1000000;
+       unsigned int i;
+
+       memcpy(&state->tab_rftune, &reg_pair_rftune, sizeof(reg_pair_rftune));
+
+       mxl5007t_set_bw_bits(state, bw);
+
+       /* Convert RF frequency into 16 bits =>
+        * 10 bit integer (MHz) + 6 bit fraction */
+       dig_rf_freq = rf_freq / MHz;
+
+       temp = rf_freq % MHz;
+
+       for (i = 0; i < 6; i++) {
+               dig_rf_freq <<= 1;
+               frac_divider /= 2;
+               if (temp > frac_divider) {
+                       temp -= frac_divider;
+                       dig_rf_freq++;
+               }
+       }
+
+       /* add to have shift center point by 7.8124 kHz */
+       if (temp > 7812)
+               dig_rf_freq++;
+
+       set_reg_bits(state->tab_rftune, 0x14, 0xff, (u8)dig_rf_freq);
+       set_reg_bits(state->tab_rftune, 0x15, 0xff, (u8)(dig_rf_freq >> 8));
+
+       return state->tab_rftune;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_write_reg(struct mxl5007t_state *state, u8 reg, u8 val)
+{
+       u8 buf[] = { reg, val };
+       struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,
+                              .buf = buf, .len = 2 };
+       int ret;
+
+       ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
+       if (ret != 1) {
+               mxl_err("failed!");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+static int mxl5007t_write_regs(struct mxl5007t_state *state,
+                              struct reg_pair_t *reg_pair)
+{
+       unsigned int i = 0;
+       int ret = 0;
+
+       while ((ret == 0) && (reg_pair[i].reg || reg_pair[i].val)) {
+               ret = mxl5007t_write_reg(state,
+                                        reg_pair[i].reg, reg_pair[i].val);
+               i++;
+       }
+       return ret;
+}
+
+static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val)
+{
+       struct i2c_msg msg[] = {
+               { .addr = state->i2c_props.addr, .flags = 0,
+                 .buf = &reg, .len = 1 },
+               { .addr = state->i2c_props.addr, .flags = I2C_M_RD,
+                 .buf = val, .len = 1 },
+       };
+       int ret;
+
+       ret = i2c_transfer(state->i2c_props.adap, msg, 2);
+       if (ret != 2) {
+               mxl_err("failed!");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+static int mxl5007t_soft_reset(struct mxl5007t_state *state)
+{
+       u8 d = 0xff;
+       struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,
+                              .buf = &d, .len = 1 };
+
+       int ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
+
+       if (ret != 1) {
+               mxl_err("failed!");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+static int mxl5007t_tuner_init(struct mxl5007t_state *state,
+                              enum mxl5007t_mode mode)
+{
+       struct reg_pair_t *init_regs;
+       int ret;
+
+       ret = mxl5007t_soft_reset(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       /* calculate initialization reg array */
+       init_regs = mxl5007t_calc_init_regs(state, mode);
+
+       ret = mxl5007t_write_regs(state, init_regs);
+       if (mxl_fail(ret))
+               goto fail;
+       mdelay(1);
+
+       ret = mxl5007t_write_reg(state, 0x2c, 0x35);
+       mxl_fail(ret);
+fail:
+       return ret;
+}
+
+static int mxl5007t_tuner_rf_tune(struct mxl5007t_state *state, u32 rf_freq_hz,
+                                 enum mxl5007t_bw_mhz bw)
+{
+       struct reg_pair_t *rf_tune_regs;
+       int ret;
+
+       /* calculate channel change reg array */
+       rf_tune_regs = mxl5007t_calc_rf_tune_regs(state, rf_freq_hz, bw);
+
+       ret = mxl5007t_write_regs(state, rf_tune_regs);
+       if (mxl_fail(ret))
+               goto fail;
+       msleep(3);
+fail:
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_synth_lock_status(struct mxl5007t_state *state,
+                                     int *rf_locked, int *ref_locked)
+{
+       u8 d;
+       int ret;
+
+       *rf_locked = 0;
+       *ref_locked = 0;
+
+       ret = mxl5007t_read_reg(state, 0xcf, &d);
+       if (mxl_fail(ret))
+               goto fail;
+
+       if ((d & 0x0c) == 0x0c)
+               *rf_locked = 1;
+
+       if ((d & 0x03) == 0x03)
+               *ref_locked = 1;
+fail:
+       return ret;
+}
+
+static int mxl5007t_check_rf_input_power(struct mxl5007t_state *state,
+                                        s32 *rf_input_level)
+{
+       u8 d1, d2;
+       int ret;
+
+       ret = mxl5007t_read_reg(state, 0xb7, &d1);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl5007t_read_reg(state, 0xbf, &d2);
+       if (mxl_fail(ret))
+               goto fail;
+
+       d2 = d2 >> 4;
+       if (d2 > 7)
+               d2 += 0xf0;
+
+       *rf_input_level = (s32)(d1 + d2 - 113);
+fail:
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       int rf_locked, ref_locked;
+       s32 rf_input_level;
+       int ret;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       ret = mxl5007t_synth_lock_status(state, &rf_locked, &ref_locked);
+       if (mxl_fail(ret))
+               goto fail;
+       mxl_debug("%s%s", rf_locked ? "rf locked " : "",
+                 ref_locked ? "ref locked" : "");
+
+       ret = mxl5007t_check_rf_input_power(state, &rf_input_level);
+       if (mxl_fail(ret))
+               goto fail;
+       mxl_debug("rf input power: %d", rf_input_level);
+fail:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_set_params(struct dvb_frontend *fe,
+                              struct dvb_frontend_parameters *params)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       enum mxl5007t_bw_mhz bw;
+       enum mxl5007t_mode mode;
+       int ret;
+       u32 freq = params->frequency;
+
+       if (fe->ops.info.type == FE_ATSC) {
+               switch (params->u.vsb.modulation) {
+               case VSB_8:
+               case VSB_16:
+                       mode = MxL_MODE_OTA_DVBT_ATSC;
+                       break;
+               case QAM_64:
+               case QAM_256:
+                       mode = MxL_MODE_CABLE_DIGITAL;
+                       break;
+               default:
+                       mxl_err("modulation not set!");
+                       return -EINVAL;
+               }
+               bw = MxL_BW_6MHz;
+       } else if (fe->ops.info.type == FE_OFDM) {
+               switch (params->u.ofdm.bandwidth) {
+               case BANDWIDTH_6_MHZ:
+                       bw = MxL_BW_6MHz;
+                       break;
+               case BANDWIDTH_7_MHZ:
+                       bw = MxL_BW_7MHz;
+                       break;
+               case BANDWIDTH_8_MHZ:
+                       bw = MxL_BW_8MHz;
+                       break;
+               default:
+                       mxl_err("bandwidth not set!");
+                       return -EINVAL;
+               }
+               mode = MxL_MODE_OTA_DVBT_ATSC;
+       } else {
+               mxl_err("modulation type not supported!");
+               return -EINVAL;
+       }
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       mutex_lock(&state->lock);
+
+       ret = mxl5007t_tuner_init(state, mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl5007t_tuner_rf_tune(state, freq, bw);
+       if (mxl_fail(ret))
+               goto fail;
+
+       state->frequency = freq;
+       state->bandwidth = (fe->ops.info.type == FE_OFDM) ?
+               params->u.ofdm.bandwidth : 0;
+fail:
+       mutex_unlock(&state->lock);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+static int mxl5007t_set_analog_params(struct dvb_frontend *fe,
+                                     struct analog_parameters *params)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       enum mxl5007t_bw_mhz bw = 0; /* FIXME */
+       enum mxl5007t_mode cbl_mode;
+       enum mxl5007t_mode ota_mode;
+       char *mode_name;
+       int ret;
+       u32 freq = params->frequency * 62500;
+
+#define cable 1
+       if (params->std & V4L2_STD_MN) {
+               cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
+               ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
+               mode_name = "MN";
+       } else if (params->std & V4L2_STD_B) {
+               cbl_mode = MxL_MODE_CABLE_PAL_IB;
+               ota_mode = MxL_MODE_OTA_PAL_IB;
+               mode_name = "B";
+       } else if (params->std & V4L2_STD_GH) {
+               cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
+               ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
+               mode_name = "GH";
+       } else if (params->std & V4L2_STD_PAL_I) {
+               cbl_mode = MxL_MODE_CABLE_PAL_IB;
+               ota_mode = MxL_MODE_OTA_PAL_IB;
+               mode_name = "I";
+       } else if (params->std & V4L2_STD_DK) {
+               cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
+               ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
+               mode_name = "DK";
+       } else if (params->std & V4L2_STD_SECAM_L) {
+               cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
+               ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
+               mode_name = "L";
+       } else if (params->std & V4L2_STD_SECAM_LC) {
+               cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
+               ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
+               mode_name = "L'";
+       } else {
+               mode_name = "xx";
+               /* FIXME */
+               cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
+               ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
+       }
+       mxl_debug("setting mxl5007 to system %s", mode_name);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       mutex_lock(&state->lock);
+
+       ret = mxl5007t_tuner_init(state, cable ? cbl_mode : ota_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl5007t_tuner_rf_tune(state, freq, bw);
+       if (mxl_fail(ret))
+               goto fail;
+
+       state->frequency = freq;
+       state->bandwidth = 0;
+fail:
+       mutex_unlock(&state->lock);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_init(struct dvb_frontend *fe)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       int ret;
+       u8 d;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       ret = mxl5007t_read_reg(state, 0x05, &d);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl5007t_write_reg(state, 0x05, d | 0x01);
+       mxl_fail(ret);
+fail:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+static int mxl5007t_sleep(struct dvb_frontend *fe)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       int ret;
+       u8 d;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       ret = mxl5007t_read_reg(state, 0x05, &d);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl5007t_write_reg(state, 0x05, d & ~0x01);
+       mxl_fail(ret);
+fail:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int mxl5007t_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       *frequency = state->frequency;
+       return 0;
+}
+
+static int mxl5007t_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+       *bandwidth = state->bandwidth;
+       return 0;
+}
+
+static int mxl5007t_release(struct dvb_frontend *fe)
+{
+       struct mxl5007t_state *state = fe->tuner_priv;
+
+       mutex_lock(&mxl5007t_list_mutex);
+
+       if (state)
+               hybrid_tuner_release_state(state);
+
+       mutex_unlock(&mxl5007t_list_mutex);
+
+       fe->tuner_priv = NULL;
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static struct dvb_tuner_ops mxl5007t_tuner_ops = {
+       .info = {
+               .name = "MaxLinear MxL5007T",
+       },
+       .init              = mxl5007t_init,
+       .sleep             = mxl5007t_sleep,
+       .set_params        = mxl5007t_set_params,
+       .set_analog_params = mxl5007t_set_analog_params,
+       .get_status        = mxl5007t_get_status,
+       .get_frequency     = mxl5007t_get_frequency,
+       .get_bandwidth     = mxl5007t_get_bandwidth,
+       .release           = mxl5007t_release,
+};
+
+static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
+{
+       char *name;
+       int ret;
+       u8 id;
+
+       ret = mxl5007t_read_reg(state, 0xd3, &id);
+       if (mxl_fail(ret))
+               goto fail;
+
+       switch (id) {
+       case MxL_5007_V1_F1:
+               name = "MxL5007.v1.f1";
+               break;
+       case MxL_5007_V1_F2:
+               name = "MxL5007.v1.f2";
+               break;
+       case MxL_5007_V2_100_F1:
+               name = "MxL5007.v2.100.f1";
+               break;
+       case MxL_5007_V2_100_F2:
+               name = "MxL5007.v2.100.f2";
+               break;
+       case MxL_5007_V2_200_F1:
+               name = "MxL5007.v2.200.f1";
+               break;
+       case MxL_5007_V2_200_F2:
+               name = "MxL5007.v2.200.f2";
+               break;
+       default:
+               name = "MxL5007T";
+               id = MxL_UNKNOWN_ID;
+       }
+       state->chip_id = id;
+       mxl_info("%s detected @ %d-%04x", name,
+                i2c_adapter_id(state->i2c_props.adap),
+                state->i2c_props.addr);
+       return 0;
+fail:
+       mxl_warn("unable to identify device @ %d-%04x",
+                i2c_adapter_id(state->i2c_props.adap),
+                state->i2c_props.addr);
+
+       state->chip_id = MxL_UNKNOWN_ID;
+       return ret;
+}
+
+struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
+                                    struct i2c_adapter *i2c, u8 addr,
+                                    struct mxl5007t_config *cfg)
+{
+       struct mxl5007t_state *state = NULL;
+       int instance, ret;
+
+       mutex_lock(&mxl5007t_list_mutex);
+       instance = hybrid_tuner_request_state(struct mxl5007t_state, state,
+                                             hybrid_tuner_instance_list,
+                                             i2c, addr, "mxl5007");
+       switch (instance) {
+       case 0:
+               goto fail;
+               break;
+       case 1:
+               /* new tuner instance */
+               state->config = cfg;
+
+               mutex_init(&state->lock);
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 1);
+
+               ret = mxl5007t_get_chip_id(state);
+
+               if (fe->ops.i2c_gate_ctrl)
+                       fe->ops.i2c_gate_ctrl(fe, 0);
+
+               /* check return value of mxl5007t_get_chip_id */
+               if (mxl_fail(ret))
+                       goto fail;
+               break;
+       default:
+               /* existing tuner instance */
+               break;
+       }
+       fe->tuner_priv = state;
+       mutex_unlock(&mxl5007t_list_mutex);
+
+       memcpy(&fe->ops.tuner_ops, &mxl5007t_tuner_ops,
+              sizeof(struct dvb_tuner_ops));
+
+       return fe;
+fail:
+       mutex_unlock(&mxl5007t_list_mutex);
+
+       mxl5007t_release(fe);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(mxl5007t_attach);
+MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/common/tuners/mxl5007t.h b/drivers/media/common/tuners/mxl5007t.h
new file mode 100644 (file)
index 0000000..a1ee362
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ *  mxl5007t.h - driver for the MaxLinear MxL5007T silicon tuner
+ *
+ *  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 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 __MXL5007T_H__
+#define __MXL5007T_H__
+
+#include "dvb_frontend.h"
+
+/* ------------------------------------------------------------------------- */
+
+enum mxl5007t_if_freq {
+       MxL_IF_4_MHZ,      /*  4000000 */
+       MxL_IF_4_5_MHZ,    /*  4500000 */
+       MxL_IF_4_57_MHZ,   /*  4570000 */
+       MxL_IF_5_MHZ,      /*  5000000 */
+       MxL_IF_5_38_MHZ,   /*  5380000 */
+       MxL_IF_6_MHZ,      /*  6000000 */
+       MxL_IF_6_28_MHZ,   /*  6280000 */
+       MxL_IF_9_1915_MHZ, /*  9191500 */
+       MxL_IF_35_25_MHZ,  /* 35250000 */
+       MxL_IF_36_15_MHZ,  /* 36150000 */
+       MxL_IF_44_MHZ,     /* 44000000 */
+};
+
+enum mxl5007t_xtal_freq {
+       MxL_XTAL_16_MHZ,      /* 16000000 */
+       MxL_XTAL_20_MHZ,      /* 20000000 */
+       MxL_XTAL_20_25_MHZ,   /* 20250000 */
+       MxL_XTAL_20_48_MHZ,   /* 20480000 */
+       MxL_XTAL_24_MHZ,      /* 24000000 */
+       MxL_XTAL_25_MHZ,      /* 25000000 */
+       MxL_XTAL_25_14_MHZ,   /* 25140000 */
+       MxL_XTAL_27_MHZ,      /* 27000000 */
+       MxL_XTAL_28_8_MHZ,    /* 28800000 */
+       MxL_XTAL_32_MHZ,      /* 32000000 */
+       MxL_XTAL_40_MHZ,      /* 40000000 */
+       MxL_XTAL_44_MHZ,      /* 44000000 */
+       MxL_XTAL_48_MHZ,      /* 48000000 */
+       MxL_XTAL_49_3811_MHZ, /* 49381100 */
+};
+
+enum mxl5007t_clkout_amp {
+       MxL_CLKOUT_AMP_0_94V = 0,
+       MxL_CLKOUT_AMP_0_53V = 1,
+       MxL_CLKOUT_AMP_0_37V = 2,
+       MxL_CLKOUT_AMP_0_28V = 3,
+       MxL_CLKOUT_AMP_0_23V = 4,
+       MxL_CLKOUT_AMP_0_20V = 5,
+       MxL_CLKOUT_AMP_0_17V = 6,
+       MxL_CLKOUT_AMP_0_15V = 7,
+};
+
+struct mxl5007t_config {
+       s32 if_diff_out_level;
+       enum mxl5007t_clkout_amp clk_out_amp;
+       enum mxl5007t_xtal_freq xtal_freq_hz;
+       enum mxl5007t_if_freq if_freq_hz;
+       unsigned int invert_if:1;
+       unsigned int loop_thru_enable:1;
+       unsigned int clk_out_enable:1;
+};
+
+#define CONFIG_MEDIA_TUNER_MXL5007T
+#if defined(CONFIG_MEDIA_TUNER_MXL5007T) || (defined(CONFIG_MEDIA_TUNER_MXL5007T_MODULE) && defined(MODULE))
+extern struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
+                                           struct i2c_adapter *i2c, u8 addr,
+                                           struct mxl5007t_config *cfg);
+#else
+static inline struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
+                                                  struct i2c_adapter *i2c,
+                                                  u8 addr,
+                                                  struct mxl5007t_config *cfg)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif
+
+#endif /* __MXL5007T_H__ */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
index a0545ba..72abf0b 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include "tuner-i2c.h"
index 266c255..597e47f 100644 (file)
@@ -6,7 +6,7 @@
  */
 #include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/tuner.h>
 #include <media/v4l2-common.h>
 #include <media/tuner-types.h>
index 7588db1..7e9c090 100644 (file)
@@ -1,7 +1,6 @@
 config DVB_BT8XX
        tristate "BT8xx based PCI cards"
        depends on DVB_CORE && PCI && I2C && VIDEO_BT848
-       depends on HOTPLUG      # due to FW_LOADER
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select DVB_SP887X if !DVB_FE_CUSTOMISE
        select DVB_NXT6000 if !DVB_FE_CUSTOMISE
@@ -10,7 +9,6 @@ config DVB_BT8XX
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          Support for PCI cards based on the Bt8xx PCI bridge. Examples are
          the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
index a577c0f..e84152b 100644 (file)
@@ -1,8 +1,6 @@
 config DVB_USB
        tristate "Support for various USB DVB devices"
        depends on DVB_CORE && USB && I2C && INPUT
-       depends on HOTPLUG      # due to FW_LOADER
-       select FW_LOADER
        help
          By enabling this you will be able to choose the various supported
          USB1.1 and USB2.0 DVB devices.
@@ -246,6 +244,14 @@ config DVB_USB_AF9005_REMOTE
          Say Y here to support the default remote control decoding for the
          Afatech AF9005 based receiver.
 
+config DVB_USB_DW2102
+       tristate "DvbWorld 2102 DVB-S USB2.0 receiver"
+       depends on DVB_USB
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_PLL if !DVB_FE_CUSTOMISE
+       help
+          Say Y here to support the DvbWorld 2102 DVB-S USB2.0 receiver.
+
 config DVB_USB_ANYSEE
        tristate "Anysee DVB-T/C USB2.0 support"
        depends on DVB_USB
index 44c11e4..e206f1e 100644 (file)
@@ -64,6 +64,9 @@ 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
 
+dvb-usb-dw2102-objs = dw2102.o
+obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
+
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 # due to tuner-xc3028
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
index adfd4fc..2f408d2 100644 (file)
@@ -43,7 +43,7 @@ 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 struct mutex anysee_usb_mutex;
 
 static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
        u8 *rbuf, u8 rlen)
index e5238b3..029b437 100644 (file)
 #define USB_PID_ASUS_U3000                             0x171f
 #define USB_PID_ASUS_U3100                             0x173f
 #define USB_PID_YUAN_EC372S                            0x1edc
+#define USB_PID_DW2102                                 0x2102
 
 #endif
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
new file mode 100644 (file)
index 0000000..a4d898b
--- /dev/null
@@ -0,0 +1,425 @@
+/* DVB USB framework compliant Linux driver for the DVBWorld DVB-S 2102 Card
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+*      This program is free software; you can redistribute it and/or modify it
+*      under the terms of the GNU General Public License as published by the
+*      Free Software Foundation, version 2.
+*
+* see Documentation/dvb/README.dvb-usb for more information
+*/
+#include <linux/version.h>
+#include "dw2102.h"
+#include "stv0299.h"
+#include "z0194a.h"
+
+#ifndef USB_PID_DW2102
+#define USB_PID_DW2102 0x2102
+#endif
+
+#define DW2102_READ_MSG 0
+#define DW2102_WRITE_MSG 1
+
+#define REG_1F_SYMBOLRATE_BYTE0 0x1f
+#define REG_20_SYMBOLRATE_BYTE1 0x20
+#define REG_21_SYMBOLRATE_BYTE2 0x21
+
+#define DW2102_VOLTAGE_CTRL (0x1800)
+#define DW2102_RC_QUERY (0x1a00)
+
+struct dw2102_state {
+       u32 last_key_pressed;
+};
+struct dw2102_rc_keys {
+       u32 keycode;
+       u32 event;
+};
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int dw2102_op_rw(struct usb_device *dev, u8 request, u16 value,
+               u8 *data, u16 len, int flags)
+{
+       int ret;
+       u8 u8buf[len];
+
+       unsigned int pipe = (flags == DW2102_READ_MSG) ?
+               usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
+       u8 request_type = (flags == DW2102_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
+
+       if (flags == DW2102_WRITE_MSG)
+               memcpy(u8buf, data, len);
+       ret = usb_control_msg(dev, pipe, request,
+               request_type | USB_TYPE_VENDOR, value, 0 , u8buf, len, 2000);
+
+       if (flags == DW2102_READ_MSG)
+               memcpy(data, u8buf, len);
+       return ret;
+}
+
+/* I2C */
+
+static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+               int num)
+{
+struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       int i = 0, ret = 0;
+       u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
+       u8 request;
+       u16 value;
+
+       if (!d)
+               return -ENODEV;
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       switch (num) {
+       case 2:
+               /* read stv0299 register */
+               request = 0xb5;
+               value = msg[0].buf[0];/* register */
+               for (i = 0; i < msg[1].len; i++) {
+                       value = value + i;
+                       ret = dw2102_op_rw(d->udev, 0xb5,
+                               value, buf6, 2, DW2102_READ_MSG);
+                       msg[1].buf[i] = buf6[0];
+
+               }
+               break;
+       case 1:
+               switch (msg[0].addr) {
+               case 0x68:
+                       /* write to stv0299 register */
+                       buf6[0] = 0x2a;
+                       buf6[1] = msg[0].buf[0];
+                       buf6[2] = msg[0].buf[1];
+                       ret = dw2102_op_rw(d->udev, 0xb2,
+                               0, buf6, 3, DW2102_WRITE_MSG);
+                       break;
+               case 0x60:
+                       if (msg[0].flags == 0) {
+                       /* write to tuner pll */
+                               buf6[0] = 0x2c;
+                               buf6[1] = 5;
+                               buf6[2] = 0xc0;
+                               buf6[3] = msg[0].buf[0];
+                               buf6[4] = msg[0].buf[1];
+                               buf6[5] = msg[0].buf[2];
+                               buf6[6] = msg[0].buf[3];
+                               ret = dw2102_op_rw(d->udev, 0xb2,
+                               0, buf6, 7, DW2102_WRITE_MSG);
+                       } else {
+                       /* write to tuner pll */
+                               ret = dw2102_op_rw(d->udev, 0xb5,
+                               0, buf6, 1, DW2102_READ_MSG);
+                               msg[0].buf[0] = buf6[0];
+                       }
+                       break;
+               case (DW2102_RC_QUERY):
+                       ret  = dw2102_op_rw(d->udev, 0xb8,
+                               0, buf6, 2, DW2102_READ_MSG);
+                       msg[0].buf[0] = buf6[0];
+                       msg[0].buf[1] = buf6[1];
+                       break;
+               case (DW2102_VOLTAGE_CTRL):
+                       buf6[0] = 0x30;
+                       buf6[1] = msg[0].buf[0];
+                       ret = dw2102_op_rw(d->udev, 0xb2,
+                               0, buf6, 2, DW2102_WRITE_MSG);
+                       break;
+               }
+
+               break;
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+       return num;
+}
+
+static u32 dw2102_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dw2102_i2c_algo = {
+       .master_xfer = dw2102_i2c_transfer,
+       .functionality = dw2102_i2c_func,
+};
+
+static int dw2102_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       static u8 command_13v[1] = {0x00};
+       static u8 command_18v[1] = {0x01};
+       struct i2c_msg msg[] = {
+               {.addr = DW2102_VOLTAGE_CTRL, .flags = 0,
+                       .buf = command_13v, .len = 1},
+       };
+
+       struct dvb_usb_adapter *udev_adap =
+               (struct dvb_usb_adapter *)(fe->dvb->priv);
+       if (voltage == SEC_VOLTAGE_18)
+               msg[0].buf = command_18v;
+       i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
+       return 0;
+}
+
+static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
+{
+       d->fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
+               &d->dev->i2c_adap);
+       if (d->fe != NULL) {
+               d->fe->ops.set_voltage = dw2102_set_voltage;
+               info("Attached stv0299!\n");
+               return 0;
+       }
+       return -EIO;
+}
+
+static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       dvb_attach(dvb_pll_attach, adap->fe, 0x60,
+               &adap->dev->i2c_adap, DVB_PLL_OPERA1);
+       return 0;
+}
+
+static struct dvb_usb_rc_key dw2102_rc_keys[] = {
+       { 0xf8, 0x0a, KEY_Q },          /*power*/
+       { 0xf8, 0x0c, KEY_M },          /*mute*/
+       { 0xf8, 0x11, KEY_1 },
+       { 0xf8, 0x12, KEY_2 },
+       { 0xf8, 0x13, KEY_3 },
+       { 0xf8, 0x14, KEY_4 },
+       { 0xf8, 0x15, KEY_5 },
+       { 0xf8, 0x16, KEY_6 },
+       { 0xf8, 0x17, KEY_7 },
+       { 0xf8, 0x18, KEY_8 },
+       { 0xf8, 0x19, KEY_9 },
+       { 0xf8, 0x10, KEY_0 },
+       { 0xf8, 0x1c, KEY_PAGEUP },     /*ch+*/
+       { 0xf8, 0x0f, KEY_PAGEDOWN },   /*ch-*/
+       { 0xf8, 0x1a, KEY_O },          /*vol+*/
+       { 0xf8, 0x0e, KEY_Z },          /*vol-*/
+       { 0xf8, 0x04, KEY_R },          /*rec*/
+       { 0xf8, 0x09, KEY_D },          /*fav*/
+       { 0xf8, 0x08, KEY_BACKSPACE },  /*rewind*/
+       { 0xf8, 0x07, KEY_A },          /*fast*/
+       { 0xf8, 0x0b, KEY_P },          /*pause*/
+       { 0xf8, 0x02, KEY_ESC },        /*cancel*/
+       { 0xf8, 0x03, KEY_G },          /*tab*/
+       { 0xf8, 0x00, KEY_UP },         /*up*/
+       { 0xf8, 0x1f, KEY_ENTER },      /*ok*/
+       { 0xf8, 0x01, KEY_DOWN },       /*down*/
+       { 0xf8, 0x05, KEY_C },          /*cap*/
+       { 0xf8, 0x06, KEY_S },          /*stop*/
+       { 0xf8, 0x40, KEY_F },          /*full*/
+       { 0xf8, 0x1e, KEY_W },          /*tvmode*/
+       { 0xf8, 0x1b, KEY_B },          /*recall*/
+
+};
+
+
+
+static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+       struct dw2102_state *st = d->priv;
+       u8 key[2];
+       struct i2c_msg msg[] = {
+               {.addr = DW2102_RC_QUERY, .flags = I2C_M_RD, .buf = key,
+               .len = 2},
+       };
+       int i;
+
+       *state = REMOTE_NO_KEY_PRESSED;
+       if (dw2102_i2c_transfer(&d->i2c_adap, msg, 1) == 1) {
+               for (i = 0; i < ARRAY_SIZE(dw2102_rc_keys); i++) {
+                       if (dw2102_rc_keys[i].data == msg[0].buf[0]) {
+                               *state = REMOTE_KEY_PRESSED;
+                               *event = dw2102_rc_keys[i].event;
+                               st->last_key_pressed =
+                                       dw2102_rc_keys[i].event;
+                               break;
+                       }
+               st->last_key_pressed = 0;
+               }
+       }
+       /* info("key: %x %x\n",key[0],key[1]); */
+       return 0;
+}
+
+static struct usb_device_id dw2102_table[] = {
+       {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
+       {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
+       { }
+};
+
+MODULE_DEVICE_TABLE(usb, dw2102_table);
+
+static int dw2102_load_firmware(struct usb_device *dev,
+                       const struct firmware *frmwr)
+{
+       u8 *b, *p;
+       int ret = 0, i;
+       u8 reset;
+       u8 reset16 [] = {0, 0, 0, 0, 0, 0, 0};
+       const struct firmware *fw;
+       const char *filename = "dvb-usb-dw2101.fw";
+       switch (dev->descriptor.idProduct) {
+       case 0x2101:
+               ret = request_firmware(&fw, filename, &dev->dev);
+               if (ret != 0) {
+                       err("did not find the firmware file. (%s) "
+                       "Please see linux/Documentation/dvb/ for more details "
+                       "on firmware-problems.", filename);
+                       return ret;
+               }
+               break;
+       case USB_PID_DW2102:
+               fw = frmwr;
+               break;
+       }
+       info("start downloading DW2102 firmware");
+       p = kmalloc(fw->size, GFP_KERNEL);
+       reset = 1;
+       /*stop the CPU*/
+       dw2102_op_rw(dev, 0xa0, 0x7f92, &reset, 1, DW2102_WRITE_MSG);
+       dw2102_op_rw(dev, 0xa0, 0xe600, &reset, 1, DW2102_WRITE_MSG);
+
+       if (p != NULL) {
+               memcpy(p, fw->data, fw->size);
+               for (i = 0; i < fw->size; i += 0x40) {
+                       b = (u8 *) p + i;
+                       if (dw2102_op_rw
+                               (dev, 0xa0, i, b , 0x40,
+                                       DW2102_WRITE_MSG) != 0x40
+                               ) {
+                               err("error while transferring firmware");
+                               ret = -EINVAL;
+                               break;
+                       }
+               }
+               /* restart the CPU */
+               reset = 0;
+               if (ret || dw2102_op_rw
+                       (dev, 0xa0, 0x7f92, &reset, 1,
+                       DW2102_WRITE_MSG) != 1) {
+                       err("could not restart the USB controller CPU.");
+                       ret = -EINVAL;
+               }
+               if (ret || dw2102_op_rw
+                       (dev, 0xa0, 0xe600, &reset, 1,
+                       DW2102_WRITE_MSG) != 1) {
+                       err("could not restart the USB controller CPU.");
+                       ret = -EINVAL;
+               }
+               /* init registers */
+               switch (dev->descriptor.idProduct) {
+               case USB_PID_DW2102:
+                       dw2102_op_rw
+                               (dev, 0xbf, 0x0040, &reset, 0,
+                               DW2102_WRITE_MSG);
+                       dw2102_op_rw
+                               (dev, 0xb9, 0x0000, &reset16[0], 2,
+                               DW2102_READ_MSG);
+                       break;
+               case 0x2101:
+                       dw2102_op_rw
+                               (dev, 0xbc, 0x0030, &reset16[0], 2,
+                               DW2102_READ_MSG);
+                       dw2102_op_rw
+                               (dev, 0xba, 0x0000, &reset16[0], 7,
+                               DW2102_READ_MSG);
+                       dw2102_op_rw
+                               (dev, 0xba, 0x0000, &reset16[0], 7,
+                               DW2102_READ_MSG);
+                       dw2102_op_rw
+                               (dev, 0xb9, 0x0000, &reset16[0], 2,
+                               DW2102_READ_MSG);
+                       break;
+               }
+               kfree(p);
+       }
+       return ret;
+}
+
+static struct dvb_usb_device_properties dw2102_properties = {
+       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+       .usb_ctrl = DEVICE_SPECIFIC,
+       .firmware = "dvb-usb-dw2102.fw",
+       .size_of_priv = sizeof(struct dw2102_state),
+       .no_reconnect = 1,
+
+       .i2c_algo = &dw2102_i2c_algo,
+       .rc_key_map = dw2102_rc_keys,
+       .rc_key_map_size = ARRAY_SIZE(dw2102_rc_keys),
+       .rc_interval = 150,
+       .rc_query = dw2102_rc_query,
+
+       .generic_bulk_ctrl_endpoint = 0x81,
+       /* parameter for the MPEG2-data transfer */
+       .num_adapters = 1,
+       .download_firmware = dw2102_load_firmware,
+       .adapter = {
+               {
+                       .frontend_attach = dw2102_frontend_attach,
+                       .streaming_ctrl = NULL,
+                       .tuner_attach = dw2102_tuner_attach,
+                       .stream = {
+                               .type = USB_BULK,
+                               .count = 8,
+                               .endpoint = 0x82,
+                               .u = {
+                                       .bulk = {
+                                               .buffersize = 4096,
+                                       }
+                               }
+                       },
+               }
+       },
+       .num_device_descs = 2,
+       .devices = {
+               {"DVBWorld DVB-S 2102 USB2.0",
+                       {&dw2102_table[0], NULL},
+                       {NULL},
+               },
+               {"DVBWorld DVB-S 2101 USB2.0",
+                       {&dw2102_table[1], NULL},
+                       {NULL},
+               },
+       }
+};
+
+static int dw2102_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       return dvb_usb_device_init(intf, &dw2102_properties,
+               THIS_MODULE, NULL, adapter_nr);
+}
+
+static struct usb_driver dw2102_driver = {
+       .name = "dw2102",
+       .probe = dw2102_probe,
+       .disconnect = dvb_usb_device_exit,
+       .id_table = dw2102_table,
+};
+
+static int __init dw2102_module_init(void)
+{
+       int ret =  usb_register(&dw2102_driver);
+       if (ret)
+               err("usb_register failed. Error number %d", ret);
+
+       return ret;
+}
+
+static void __exit dw2102_module_exit(void)
+{
+       usb_deregister(&dw2102_driver);
+}
+
+module_init(dw2102_module_init);
+module_exit(dw2102_module_exit);
+
+MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
+MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101 2102 USB2.0 device");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h
new file mode 100644 (file)
index 0000000..7a310f9
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _DW2102_H_
+#define _DW2102_H_
+
+#define DVB_USB_LOG_PREFIX "dw2102"
+#include "dvb-usb.h"
+
+extern int dvb_usb_dw2102_debug;
+#define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args)
+#endif
index c20553c..574dffe 100644 (file)
@@ -97,9 +97,8 @@ comment "DVB-T (terrestrial) frontends"
 
 config DVB_SP8870
        tristate "Spase sp8870 based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
@@ -110,9 +109,8 @@ config DVB_SP8870
 
 config DVB_SP887X
        tristate "Spase sp887x based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
@@ -135,6 +133,20 @@ config DVB_CX22702
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
+config DVB_DRX397XD
+       tristate "Micronas DRX3975D/DRX3977D based"
+       depends on DVB_CORE && I2C && HOTPLUG
+       default m if DVB_FE_CUSTOMISE
+       select FW_LOADER
+       help
+         A DVB-T tuner module. Say Y when you want to support this frontend.
+
+         TODO:
+         This driver needs external firmware. Please use the command
+         "<kerneldir>/Documentation/dvb/get_dvb_firmware drx397xD" to
+         download/extract them, and then copy them to /usr/lib/hotplug/firmware
+         or /lib/firmware (depending on configuration of firmware hotplug).
+
 config DVB_L64781
        tristate "LSI L64781"
        depends on DVB_CORE && I2C
@@ -144,9 +156,8 @@ config DVB_L64781
 
 config DVB_TDA1004X
        tristate "Philips TDA10045H/TDA10046H based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
@@ -211,9 +222,8 @@ config DVB_DIB7000P
 
 config DVB_TDA10048
        tristate "Philips TDA10048HN based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
@@ -253,9 +263,8 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
 
 config DVB_NXT200X
        tristate "NxtWave Communications NXT2002/NXT2004 based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
@@ -268,9 +277,8 @@ config DVB_NXT200X
 
 config DVB_OR51211
        tristate "Oren OR51211 based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
 
@@ -281,9 +289,8 @@ config DVB_OR51211
 
 config DVB_OR51132
        tristate "Oren OR51132 based"
-       depends on DVB_CORE && I2C && HOTPLUG
+       depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
@@ -297,9 +304,8 @@ config DVB_OR51132
 
 config DVB_BCM3510
        tristate "Broadcom BCM3510"
-       depends on DVB_CORE && I2C && HOTPLUG
+       depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
          support this frontend.
index a89dc0f..028da55 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
 obj-$(CONFIG_DVB_MT352) += mt352.o
 obj-$(CONFIG_DVB_ZL10353) += zl10353.o
 obj-$(CONFIG_DVB_CX22702) += cx22702.o
+obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o
 obj-$(CONFIG_DVB_TDA10021) += tda10021.o
 obj-$(CONFIG_DVB_TDA10023) += tda10023.o
 obj-$(CONFIG_DVB_STV0297) += stv0297.o
diff --git a/drivers/media/dvb/frontends/drx397xD.c b/drivers/media/dvb/frontends/drx397xD.c
new file mode 100644 (file)
index 0000000..3cbed87
--- /dev/null
@@ -0,0 +1,1504 @@
+/*
+ * Driver for Micronas drx397xD demodulator
+ *
+ * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define DEBUG                  /* uncomment if you want debugging output */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/firmware.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "drx397xD.h"
+
+static const char mod_name[] = "drx397xD";
+
+#define MAX_CLOCK_DRIFT                200     /* maximal 200 PPM allowed */
+
+#define F_SET_0D0h     1
+#define F_SET_0D4h     2
+
+typedef enum fw_ix {
+#define _FW_ENTRY(a, b)                b
+#include "drx397xD_fw.h"
+} fw_ix_t;
+
+/* chip specifics */
+struct drx397xD_state {
+       struct i2c_adapter *i2c;
+       struct dvb_frontend frontend;
+       struct drx397xD_config config;
+       fw_ix_t chip_rev;
+       int flags;
+       u32 bandwidth_parm;     /* internal bandwidth conversions */
+       u32 f_osc;              /* w90: actual osc frequency [Hz] */
+};
+
+/*******************************************************************************
+ * Firmware
+ ******************************************************************************/
+
+static const char *blob_name[] = {
+#define _BLOB_ENTRY(a, b)              a
+#include "drx397xD_fw.h"
+};
+
+typedef enum blob_ix {
+#define _BLOB_ENTRY(a, b)              b
+#include "drx397xD_fw.h"
+} blob_ix_t;
+
+static struct {
+       const char *name;
+       const struct firmware *file;
+       rwlock_t lock;
+       int refcnt;
+       const u8 *data[ARRAY_SIZE(blob_name)];
+} fw[] = {
+#define _FW_ENTRY(a, b)                {                       \
+                       .name   = a,                    \
+                       .file   = 0,                    \
+                       .lock   = RW_LOCK_UNLOCKED,     \
+                       .refcnt = 0,                    \
+                       .data   = { }           }
+#include "drx397xD_fw.h"
+};
+
+/* use only with writer lock aquired */
+static void _drx_release_fw(struct drx397xD_state *s, fw_ix_t ix)
+{
+       memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
+       if (fw[ix].file)
+               release_firmware(fw[ix].file);
+}
+
+static void drx_release_fw(struct drx397xD_state *s)
+{
+       fw_ix_t ix = s->chip_rev;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       write_lock(&fw[ix].lock);
+       if (fw[ix].refcnt) {
+               fw[ix].refcnt--;
+               if (fw[ix].refcnt == 0)
+                       _drx_release_fw(s, ix);
+       }
+       write_unlock(&fw[ix].lock);
+}
+
+static int drx_load_fw(struct drx397xD_state *s, fw_ix_t ix)
+{
+       const u8 *data;
+       size_t size, len;
+       int i = 0, j, rc = -EINVAL;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       if (ix < 0 || ix >= ARRAY_SIZE(fw))
+               return -EINVAL;
+       s->chip_rev = ix;
+
+       write_lock(&fw[ix].lock);
+       if (fw[ix].file) {
+               rc = 0;
+               goto exit_ok;
+       }
+       memset(&fw[ix].data[0], 0, sizeof(fw[0].data));
+
+       if (request_firmware(&fw[ix].file, fw[ix].name, &s->i2c->dev) != 0) {
+               printk(KERN_ERR "%s: Firmware \"%s\" not available\n",
+                      mod_name, fw[ix].name);
+               rc = -ENOENT;
+               goto exit_err;
+       }
+
+       if (!fw[ix].file->data || fw[ix].file->size < 10)
+               goto exit_corrupt;
+
+       data = fw[ix].file->data;
+       size = fw[ix].file->size;
+
+       if (data[i++] != 2)     /* check firmware version */
+               goto exit_corrupt;
+
+       do {
+               switch (data[i++]) {
+               case 0x00:      /* bytecode */
+                       if (i >= size)
+                               break;
+                       i += data[i];
+               case 0x01:      /* reset */
+               case 0x02:      /* sleep */
+                       i++;
+                       break;
+               case 0xfe:      /* name */
+                       len = strnlen(&data[i], size - i);
+                       if (i + len + 1 >= size)
+                               goto exit_corrupt;
+                       if (data[i + len + 1] != 0)
+                               goto exit_corrupt;
+                       for (j = 0; j < ARRAY_SIZE(blob_name); j++) {
+                               if (strcmp(blob_name[j], &data[i]) == 0) {
+                                       fw[ix].data[j] = &data[i + len + 1];
+                                       pr_debug("Loading %s\n", blob_name[j]);
+                               }
+                       }
+                       i += len + 1;
+                       break;
+               case 0xff:      /* file terminator */
+                       if (i == size) {
+                               rc = 0;
+                               goto exit_ok;
+                       }
+               default:
+                       goto exit_corrupt;
+               }
+       } while (i < size);
+      exit_corrupt:
+       printk(KERN_ERR "%s: Firmware is corrupt\n", mod_name);
+      exit_err:
+       _drx_release_fw(s, ix);
+       fw[ix].refcnt--;
+      exit_ok:
+       fw[ix].refcnt++;
+       write_unlock(&fw[ix].lock);
+       return rc;
+}
+
+/*******************************************************************************
+ * i2c bus IO
+ ******************************************************************************/
+
+static int write_fw(struct drx397xD_state *s, blob_ix_t ix)
+{
+       struct i2c_msg msg = {.addr = s->config.demod_address,.flags = 0 };
+       const u8 *data;
+       int len, rc = 0, i = 0;
+
+       if (ix < 0 || ix >= ARRAY_SIZE(blob_name)) {
+               pr_debug("%s drx_fw_ix_t out of range\n", __FUNCTION__);
+               return -EINVAL;
+       }
+       pr_debug("%s %s\n", __FUNCTION__, blob_name[ix]);
+
+       read_lock(&fw[s->chip_rev].lock);
+       data = fw[s->chip_rev].data[ix];
+       if (!data) {
+               rc = -EINVAL;
+               goto exit_rc;
+       }
+
+       for (;;) {
+               switch (data[i++]) {
+               case 0: /* bytecode */
+                       len = data[i++];
+                       msg.len = len;
+                       msg.buf = (__u8 *) &data[i];
+                       if (i2c_transfer(s->i2c, &msg, 1) != 1) {
+                               rc = -EIO;
+                               goto exit_rc;
+                       }
+                       i += len;
+                       break;
+               case 1: /* reset */
+               case 2: /* sleep */
+                       i++;
+                       break;
+               default:
+                       goto exit_rc;
+               }
+       }
+      exit_rc:
+       read_unlock(&fw[s->chip_rev].lock);
+       return 0;
+}
+
+/* Function is not endian safe, use the RD16 wrapper below */
+static int _read16(struct drx397xD_state *s, u32 i2c_adr)
+{
+       int rc;
+       u8 a[4];
+       u16 v;
+       struct i2c_msg msg[2] = {
+               {
+                .addr = s->config.demod_address,
+                .flags = 0,
+                .buf = a,
+                .len = sizeof(a)
+                }
+               , {
+                  .addr = s->config.demod_address,
+                  .flags = I2C_M_RD,
+                  .buf = (u8 *) & v,
+                  .len = sizeof(v)
+                  }
+       };
+
+       *(u32 *) a = i2c_adr;
+
+       rc = i2c_transfer(s->i2c, msg, 2);
+       if (rc != 2)
+               return -EIO;
+
+       return le16_to_cpu(v);
+}
+
+/* Function is not endian safe, use the WR16.. wrappers below */
+static int _write16(struct drx397xD_state *s, u32 i2c_adr, u16 val)
+{
+       u8 a[6];
+       int rc;
+       struct i2c_msg msg = {
+               .addr = s->config.demod_address,
+               .flags = 0,
+               .buf = a,
+               .len = sizeof(a)
+       };
+
+       *(u32 *) a = i2c_adr;
+       *(u16 *) & a[4] = val;
+
+       rc = i2c_transfer(s->i2c, &msg, 1);
+       if (rc != 1)
+               return -EIO;
+       return 0;
+}
+
+#define WR16(ss,adr, val) \
+               _write16(ss, I2C_ADR_C0(adr), cpu_to_le16(val))
+#define WR16_E0(ss,adr, val) \
+               _write16(ss, I2C_ADR_E0(adr), cpu_to_le16(val))
+#define RD16(ss,adr) \
+               _read16(ss, I2C_ADR_C0(adr))
+
+#define EXIT_RC( cmd ) if ( (rc = (cmd)) < 0) goto exit_rc
+
+/*******************************************************************************
+ * Tuner callback
+ ******************************************************************************/
+
+static int PLL_Set(struct drx397xD_state *s,
+                  struct dvb_frontend_parameters *fep, int *df_tuner)
+{
+       struct dvb_frontend *fe = &s->frontend;
+       u32 f_tuner, f = fep->frequency;
+       int rc;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       if ((f > s->frontend.ops.tuner_ops.info.frequency_max) ||
+           (f < s->frontend.ops.tuner_ops.info.frequency_min))
+               return -EINVAL;
+
+       *df_tuner = 0;
+       if (!s->frontend.ops.tuner_ops.set_params ||
+           !s->frontend.ops.tuner_ops.get_frequency)
+               return -ENOSYS;
+
+       rc = s->frontend.ops.tuner_ops.set_params(fe, fep);
+       if (rc < 0)
+               return rc;
+
+       rc = s->frontend.ops.tuner_ops.get_frequency(fe, &f_tuner);
+       if (rc < 0)
+               return rc;
+
+       *df_tuner = f_tuner - f;
+       pr_debug("%s requested %d [Hz] tuner %d [Hz]\n", __FUNCTION__, f,
+                f_tuner);
+
+       return 0;
+}
+
+/*******************************************************************************
+ * Demodulator helper functions
+ ******************************************************************************/
+
+static int SC_WaitForReady(struct drx397xD_state *s)
+{
+       int cnt = 1000;
+       int rc;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       while (cnt--) {
+               rc = RD16(s, 0x820043);
+               if (rc == 0)
+                       return 0;
+       }
+       return -1;
+}
+
+static int SC_SendCommand(struct drx397xD_state *s, int cmd)
+{
+       int rc;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       WR16(s, 0x820043, cmd);
+       SC_WaitForReady(s);
+       rc = RD16(s, 0x820042);
+       if ((rc & 0xffff) == 0xffff)
+               return -1;
+       return 0;
+}
+
+static int HI_Command(struct drx397xD_state *s, u16 cmd)
+{
+       int rc, cnt = 1000;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       rc = WR16(s, 0x420032, cmd);
+       if (rc < 0)
+               return rc;
+
+       do {
+               rc = RD16(s, 0x420032);
+               if (rc == 0) {
+                       rc = RD16(s, 0x420031);
+                       return rc;
+               }
+               if (rc < 0)
+                       return rc;
+       } while (--cnt);
+       return rc;
+}
+
+static int HI_CfgCommand(struct drx397xD_state *s)
+{
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       WR16(s, 0x420033, 0x3973);
+       WR16(s, 0x420034, s->config.w50);       // code 4, log 4
+       WR16(s, 0x420035, s->config.w52);       // code 15,  log 9
+       WR16(s, 0x420036, s->config.demod_address << 1);
+       WR16(s, 0x420037, s->config.w56);       // code (set_i2c ??  initX 1 ), log 1
+//      WR16(s, 0x420033, 0x3973);
+       if ((s->config.w56 & 8) == 0)
+               return HI_Command(s, 3);
+       return WR16(s, 0x420032, 0x3);
+}
+
+static const u8 fastIncrDecLUT_15273[] = {
+       0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14,
+       0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f
+};
+
+static const u8 slowIncrDecLUT_15272[] = {
+       3, 4, 4, 5, 6
+};
+
+static int SetCfgIfAgc(struct drx397xD_state *s, struct drx397xD_CfgIfAgc *agc)
+{
+       u16 w06 = agc->w06;
+       u16 w08 = agc->w08;
+       u16 w0A = agc->w0A;
+       u16 w0C = agc->w0C;
+       int quot, rem, i, rc = -EINVAL;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       if (agc->w04 > 0x3ff)
+               goto exit_rc;
+
+       if (agc->d00 == 1) {
+               EXIT_RC(RD16(s, 0x0c20010));
+               rc &= ~0x10;
+               EXIT_RC(WR16(s, 0x0c20010, rc));
+               return WR16(s, 0x0c20030, agc->w04 & 0x7ff);
+       }
+
+       if (agc->d00 != 0)
+               goto exit_rc;
+       if (w0A < w08)
+               goto exit_rc;
+       if (w0A > 0x3ff)
+               goto exit_rc;
+       if (w0C > 0x3ff)
+               goto exit_rc;
+       if (w06 > 0x3ff)
+               goto exit_rc;
+
+       EXIT_RC(RD16(s, 0x0c20010));
+       rc |= 0x10;
+       EXIT_RC(WR16(s, 0x0c20010, rc));
+
+       EXIT_RC(WR16(s, 0x0c20025, (w06 >> 1) & 0x1ff));
+       EXIT_RC(WR16(s, 0x0c20031, (w0A - w08) >> 1));
+       EXIT_RC(WR16(s, 0x0c20032, ((w0A + w08) >> 1) - 0x1ff));
+
+       quot = w0C / 113;
+       rem = w0C % 113;
+       if (quot <= 8) {
+               quot = 8 - quot;
+       } else {
+               quot = 0;
+               rem += 113;
+       }
+
+       EXIT_RC(WR16(s, 0x0c20024, quot));
+
+       i = fastIncrDecLUT_15273[rem / 8];
+       EXIT_RC(WR16(s, 0x0c2002d, i));
+       EXIT_RC(WR16(s, 0x0c2002e, i));
+
+       i = slowIncrDecLUT_15272[rem / 28];
+       EXIT_RC(WR16(s, 0x0c2002b, i));
+       rc = WR16(s, 0x0c2002c, i);
+      exit_rc:
+       return rc;
+}
+
+static int SetCfgRfAgc(struct drx397xD_state *s, struct drx397xD_CfgRfAgc *agc)
+{
+       u16 w04 = agc->w04;
+       u16 w06 = agc->w06;
+       int rc = -1;
+
+       pr_debug("%s %d 0x%x 0x%x\n", __FUNCTION__, agc->d00, w04, w06);
+
+       if (w04 > 0x3ff)
+               goto exit_rc;
+
+       switch (agc->d00) {
+       case 1:
+               if (w04 == 0x3ff)
+                       w04 = 0x400;
+
+               EXIT_RC(WR16(s, 0x0c20036, w04));
+               s->config.w9C &= ~2;
+               EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+               EXIT_RC(RD16(s, 0x0c20010));
+               rc &= 0xbfdf;
+               EXIT_RC(WR16(s, 0x0c20010, rc));
+               EXIT_RC(RD16(s, 0x0c20013));
+               rc &= ~2;
+               break;
+       case 0:
+               // loc_8000659
+               s->config.w9C &= ~2;
+               EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+               EXIT_RC(RD16(s, 0x0c20010));
+               rc &= 0xbfdf;
+               rc |= 0x4000;
+               EXIT_RC(WR16(s, 0x0c20010, rc));
+               EXIT_RC(WR16(s, 0x0c20051, (w06 >> 4) & 0x3f));
+               EXIT_RC(RD16(s, 0x0c20013));
+               rc &= ~2;
+               break;
+       default:
+               s->config.w9C |= 2;
+               EXIT_RC(WR16(s, 0x0c20015, s->config.w9C));
+               EXIT_RC(RD16(s, 0x0c20010));
+               rc &= 0xbfdf;
+               EXIT_RC(WR16(s, 0x0c20010, rc));
+
+               EXIT_RC(WR16(s, 0x0c20036, 0));
+
+               EXIT_RC(RD16(s, 0x0c20013));
+               rc |= 2;
+       }
+       rc = WR16(s, 0x0c20013, rc);
+      exit_rc:
+       return rc;
+}
+
+static int GetLockStatus(struct drx397xD_state *s, int *lockstat)
+{
+       int rc;
+
+       *lockstat = 0;
+
+       rc = RD16(s, 0x082004b);
+       if (rc < 0)
+               return rc;
+
+       if (s->config.d60 != 2)
+               return 0;
+
+       if ((rc & 7) == 7)
+               *lockstat |= 1;
+       if ((rc & 3) == 3)
+               *lockstat |= 2;
+       if (rc & 1)
+               *lockstat |= 4;
+       return 0;
+}
+
+static int CorrectSysClockDeviation(struct drx397xD_state *s)
+{
+       int rc = -EINVAL;
+       int lockstat;
+       u32 clk, clk_limit;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       if (s->config.d5C == 0) {
+               EXIT_RC(WR16(s, 0x08200e8, 0x010));
+               EXIT_RC(WR16(s, 0x08200e9, 0x113));
+               s->config.d5C = 1;
+               return rc;
+       }
+       if (s->config.d5C != 1)
+               goto exit_rc;
+
+       rc = RD16(s, 0x0820048);
+
+       rc = GetLockStatus(s, &lockstat);
+       if (rc < 0)
+               goto exit_rc;
+       if ((lockstat & 1) == 0)
+               goto exit_rc;
+
+       EXIT_RC(WR16(s, 0x0420033, 0x200));
+       EXIT_RC(WR16(s, 0x0420034, 0xc5));
+       EXIT_RC(WR16(s, 0x0420035, 0x10));
+       EXIT_RC(WR16(s, 0x0420036, 0x1));
+       EXIT_RC(WR16(s, 0x0420037, 0xa));
+       EXIT_RC(HI_Command(s, 6));
+       EXIT_RC(RD16(s, 0x0420040));
+       clk = rc;
+       EXIT_RC(RD16(s, 0x0420041));
+       clk |= rc << 16;
+
+       if (clk <= 0x26ffff)
+               goto exit_rc;
+       if (clk > 0x610000)
+               goto exit_rc;
+
+       if (!s->bandwidth_parm)
+               return -EINVAL;
+
+       /* round & convert to Hz */
+       clk = ((u64) (clk + 0x800000) * s->bandwidth_parm + (1 << 20)) >> 21;
+       clk_limit = s->config.f_osc * MAX_CLOCK_DRIFT / 1000;
+
+       if (clk - s->config.f_osc * 1000 + clk_limit <= 2 * clk_limit) {
+               s->f_osc = clk;
+               pr_debug("%s: osc %d %d [Hz]\n", __FUNCTION__,
+                        s->config.f_osc * 1000, clk - s->config.f_osc * 1000);
+       }
+       rc = WR16(s, 0x08200e8, 0);
+      exit_rc:
+       return rc;
+}
+
+static int ConfigureMPEGOutput(struct drx397xD_state *s, int type)
+{
+       int rc, si, bp;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       si = s->config.wA0;
+       if (s->config.w98 == 0) {
+               si |= 1;
+               bp = 0;
+       } else {
+               si &= ~1;
+               bp = 0x200;
+       }
+       if (s->config.w9A == 0) {
+               si |= 0x80;
+       } else {
+               si &= ~0x80;
+       }
+
+       EXIT_RC(WR16(s, 0x2150045, 0));
+       EXIT_RC(WR16(s, 0x2150010, si));
+       EXIT_RC(WR16(s, 0x2150011, bp));
+       rc = WR16(s, 0x2150012, (type == 0 ? 0xfff : 0));
+      exit_rc:
+       return rc;
+}
+
+static int drx_tune(struct drx397xD_state *s,
+                   struct dvb_frontend_parameters *fep)
+{
+       u16 v22 = 0;
+       u16 v1C = 0;
+       u16 v1A = 0;
+       u16 v18 = 0;
+       u32 edi = 0, ebx = 0, ebp = 0, edx = 0;
+       u16 v20 = 0, v1E = 0, v16 = 0, v14 = 0, v12 = 0, v10 = 0, v0E = 0;
+
+       int rc, df_tuner;
+       int a, b, c, d;
+       pr_debug("%s %d\n", __FUNCTION__, s->config.d60);
+
+       if (s->config.d60 != 2)
+               goto set_tuner;
+       rc = CorrectSysClockDeviation(s);
+       if (rc < 0)
+               goto set_tuner;
+
+       s->config.d60 = 1;
+       rc = ConfigureMPEGOutput(s, 0);
+       if (rc < 0)
+               goto set_tuner;
+      set_tuner:
+
+       rc = PLL_Set(s, fep, &df_tuner);
+       if (rc < 0) {
+               printk(KERN_ERR "Error in pll_set\n");
+               goto exit_rc;
+       }
+       msleep(200);
+
+       a = rc = RD16(s, 0x2150016);
+       if (rc < 0)
+               goto exit_rc;
+       b = rc = RD16(s, 0x2150010);
+       if (rc < 0)
+               goto exit_rc;
+       c = rc = RD16(s, 0x2150034);
+       if (rc < 0)
+               goto exit_rc;
+       d = rc = RD16(s, 0x2150035);
+       if (rc < 0)
+               goto exit_rc;
+       rc = WR16(s, 0x2150014, c);
+       rc = WR16(s, 0x2150015, d);
+       rc = WR16(s, 0x2150010, 0);
+       rc = WR16(s, 0x2150000, 2);
+       rc = WR16(s, 0x2150036, 0x0fff);
+       rc = WR16(s, 0x2150016, a);
+
+       rc = WR16(s, 0x2150010, 2);
+       rc = WR16(s, 0x2150007, 0);
+       rc = WR16(s, 0x2150000, 1);
+       rc = WR16(s, 0x2110000, 0);
+       rc = WR16(s, 0x0800000, 0);
+       rc = WR16(s, 0x2800000, 0);
+       rc = WR16(s, 0x2110010, 0x664);
+
+       rc = write_fw(s, DRXD_ResetECRAM);
+       rc = WR16(s, 0x2110000, 1);
+
+       rc = write_fw(s, DRXD_InitSC);
+       if (rc < 0)
+               goto exit_rc;
+
+       rc = SetCfgIfAgc(s, &s->config.ifagc);
+       if (rc < 0)
+               goto exit_rc;
+
+       rc = SetCfgRfAgc(s, &s->config.rfagc);
+       if (rc < 0)
+               goto exit_rc;
+
+       if (fep->u.ofdm.transmission_mode != TRANSMISSION_MODE_2K)
+               v22 = 1;
+       switch (fep->u.ofdm.transmission_mode) {
+       case TRANSMISSION_MODE_8K:
+               edi = 1;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+
+               rc = WR16(s, 0x2010010, 0);
+               if (rc < 0)
+                       break;
+               v1C = 0x63;
+               v1A = 0x53;
+               v18 = 0x43;
+               break;
+       default:
+               edi = 0;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+
+               rc = WR16(s, 0x2010010, 1);
+               if (rc < 0)
+                       break;
+
+               v1C = 0x61;
+               v1A = 0x47;
+               v18 = 0x41;
+       }
+
+       switch (fep->u.ofdm.guard_interval) {
+       case GUARD_INTERVAL_1_4:
+               edi |= 0x0c;
+               break;
+       case GUARD_INTERVAL_1_8:
+               edi |= 0x08;
+               break;
+       case GUARD_INTERVAL_1_16:
+               edi |= 0x04;
+               break;
+       case GUARD_INTERVAL_1_32:
+               break;
+       default:
+               v22 |= 2;
+       }
+
+       ebx = 0;
+       ebp = 0;
+       v20 = 0;
+       v1E = 0;
+       v16 = 0;
+       v14 = 0;
+       v12 = 0;
+       v10 = 0;
+       v0E = 0;
+
+       switch (fep->u.ofdm.hierarchy_information) {
+       case HIERARCHY_1:
+               edi |= 0x40;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x1c10047, 1);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010012, 1);
+               if (rc < 0)
+                       goto exit_rc;
+               ebx = 0x19f;
+               ebp = 0x1fb;
+               v20 = 0x0c0;
+               v1E = 0x195;
+               v16 = 0x1d6;
+               v14 = 0x1ef;
+               v12 = 4;
+               v10 = 5;
+               v0E = 5;
+               break;
+       case HIERARCHY_2:
+               edi |= 0x80;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x1c10047, 2);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010012, 2);
+               if (rc < 0)
+                       goto exit_rc;
+               ebx = 0x08f;
+               ebp = 0x12f;
+               v20 = 0x0c0;
+               v1E = 0x11e;
+               v16 = 0x1d6;
+               v14 = 0x15e;
+               v12 = 4;
+               v10 = 5;
+               v0E = 5;
+               break;
+       case HIERARCHY_4:
+               edi |= 0xc0;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x1c10047, 3);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010012, 3);
+               if (rc < 0)
+                       goto exit_rc;
+               ebx = 0x14d;
+               ebp = 0x197;
+               v20 = 0x0c0;
+               v1E = 0x1ce;
+               v16 = 0x1d6;
+               v14 = 0x11a;
+               v12 = 4;
+               v10 = 6;
+               v0E = 5;
+               break;
+       default:
+               v22 |= 8;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x1c10047, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010012, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               //              QPSK    QAM16   QAM64
+               ebx = 0x19f;    //                 62
+               ebp = 0x1fb;    //                 15
+               v20 = 0x16a;    //  62
+               v1E = 0x195;    //         62
+               v16 = 0x1bb;    //  15
+               v14 = 0x1ef;    //         15
+               v12 = 5;        //  16
+               v10 = 5;        //         16
+               v0E = 5;        //                 16
+       }
+
+       switch (fep->u.ofdm.constellation) {
+       default:
+               v22 |= 4;
+       case QPSK:
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+
+               rc = WR16(s, 0x1c10046, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010011, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001a, 0x10);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001b, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001c, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10062, v20);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c1002a, v1C);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10015, v16);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10016, v12);
+               if (rc < 0)
+                       goto exit_rc;
+               break;
+       case QAM_16:
+               edi |= 0x10;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+
+               rc = WR16(s, 0x1c10046, 1);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010011, 1);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001a, 0x10);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001b, 4);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001c, 0);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10062, v1E);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c1002a, v1A);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10015, v14);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10016, v10);
+               if (rc < 0)
+                       goto exit_rc;
+               break;
+       case QAM_64:
+               edi |= 0x20;
+               rc = WR16(s, 0x1c10046, 2);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x2010011, 2);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001a, 0x20);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001b, 8);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x201001c, 2);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10062, ebx);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c1002a, v18);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10015, ebp);
+               if (rc < 0)
+                       goto exit_rc;
+               rc = WR16(s, 0x1c10016, v0E);
+               if (rc < 0)
+                       goto exit_rc;
+               break;
+       }
+
+       if (s->config.s20d24 == 1) {
+               rc = WR16(s, 0x2010013, 0);
+       } else {
+               rc = WR16(s, 0x2010013, 1);
+               edi |= 0x1000;
+       }
+
+       switch (fep->u.ofdm.code_rate_HP) {
+       default:
+               v22 |= 0x10;
+       case FEC_1_2:
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x2090011, 0);
+               break;
+       case FEC_2_3:
+               edi |= 0x200;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x2090011, 1);
+               break;
+       case FEC_3_4:
+               edi |= 0x400;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x2090011, 2);
+               break;
+       case FEC_5_6:           /* 5 */
+               edi |= 0x600;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x2090011, 3);
+               break;
+       case FEC_7_8:           /* 7 */
+               edi |= 0x800;
+               if (s->chip_rev == DRXD_FW_B1)
+                       break;
+               rc = WR16(s, 0x2090011, 4);
+               break;
+       };
+       if (rc < 0)
+               goto exit_rc;
+
+       switch (fep->u.ofdm.bandwidth) {
+       default:
+               rc = -EINVAL;
+               goto exit_rc;
+       case BANDWIDTH_8_MHZ:   /* 0 */
+       case BANDWIDTH_AUTO:
+               rc = WR16(s, 0x0c2003f, 0x32);
+               s->bandwidth_parm = ebx = 0x8b8249;     // 9142857
+               edx = 0;
+               break;
+       case BANDWIDTH_7_MHZ:
+               rc = WR16(s, 0x0c2003f, 0x3b);
+               s->bandwidth_parm = ebx = 0x7a1200;     // 8000000
+               edx = 0x4807;
+               break;
+       case BANDWIDTH_6_MHZ:
+               rc = WR16(s, 0x0c2003f, 0x47);
+               s->bandwidth_parm = ebx = 0x68a1b6;     // 6857142
+               edx = 0x0f07;
+               break;
+       };
+
+       if (rc < 0)
+               goto exit_rc;
+
+       rc = WR16(s, 0x08200ec, edx);
+       if (rc < 0)
+               goto exit_rc;
+
+       rc = RD16(s, 0x0820050);
+       if (rc < 0)
+               goto exit_rc;
+       rc = WR16(s, 0x0820050, rc);
+
+       {
+               /* Configure bandwidth specific factor */
+               ebx = div64_u64(((u64) (s->f_osc) << 21) + (ebx >> 1),
+                                    (u64)ebx) - 0x800000;
+               EXIT_RC(WR16(s, 0x0c50010, ebx & 0xffff));
+               EXIT_RC(WR16(s, 0x0c50011, ebx >> 16));
+
+               /* drx397xD oscillator calibration */
+               ebx = div64_u64(((u64) (s->config.f_if + df_tuner) << 28) +
+                                    (s->f_osc >> 1), (u64)s->f_osc);
+       }
+       ebx &= 0xfffffff;
+       if (fep->inversion == INVERSION_ON)
+               ebx = 0x10000000 - ebx;
+
+       EXIT_RC(WR16(s, 0x0c30010, ebx & 0xffff));
+       EXIT_RC(WR16(s, 0x0c30011, ebx >> 16));
+
+       EXIT_RC(WR16(s, 0x0800000, 1));
+       EXIT_RC(RD16(s, 0x0800000));
+
+
+       EXIT_RC(SC_WaitForReady(s));
+       EXIT_RC(WR16(s, 0x0820042, 0));
+       EXIT_RC(WR16(s, 0x0820041, v22));
+       EXIT_RC(WR16(s, 0x0820040, edi));
+       EXIT_RC(SC_SendCommand(s, 3));
+
+       rc = RD16(s, 0x0800000);
+
+       SC_WaitForReady(s);
+       WR16(s, 0x0820042, 0);
+       WR16(s, 0x0820041, 1);
+       WR16(s, 0x0820040, 1);
+       SC_SendCommand(s, 1);
+
+//      rc = WR16(s, 0x2150000, 1);
+//      if (rc < 0) goto exit_rc;
+
+       rc = WR16(s, 0x2150000, 2);
+       rc = WR16(s, 0x2150016, a);
+       rc = WR16(s, 0x2150010, 4);
+       rc = WR16(s, 0x2150036, 0);
+       rc = WR16(s, 0x2150000, 1);
+       s->config.d60 = 2;
+      exit_rc:
+       return rc;
+}
+
+/*******************************************************************************
+ * DVB interface
+ ******************************************************************************/
+
+static int drx397x_init(struct dvb_frontend *fe)
+{
+       struct drx397xD_state *s = fe->demodulator_priv;
+       int rc;
+
+       pr_debug("%s\n", __FUNCTION__);
+
+       s->config.rfagc.d00 = 2;        /* 0x7c */
+       s->config.rfagc.w04 = 0;
+       s->config.rfagc.w06 = 0x3ff;
+
+       s->config.ifagc.d00 = 0;        /* 0x68 */
+       s->config.ifagc.w04 = 0;
+       s->config.ifagc.w06 = 140;
+       s->config.ifagc.w08 = 0;
+       s->config.ifagc.w0A = 0x3ff;
+       s->config.ifagc.w0C = 0x388;
+
+       /* for signal strenght calculations */
+       s->config.ss76 = 820;
+       s->config.ss78 = 2200;
+       s->config.ss7A = 150;
+
+       /* HI_CfgCommand */
+       s->config.w50 = 4;
+       s->config.w52 = 9;      // 0xf;
+
+       s->config.f_if = 42800000;      /* d14: intermediate frequency [Hz]     */
+       s->config.f_osc = 48000;        /* s66 : oscillator frequency [kHz]     */
+       s->config.w92 = 12000;  // 20000;
+
+       s->config.w9C = 0x000e;
+       s->config.w9E = 0x0000;
+
+       /* ConfigureMPEGOutput params */
+       s->config.wA0 = 4;
+       s->config.w98 = 1;      // 0;
+       s->config.w9A = 1;
+
+       /* get chip revision */
+       rc = RD16(s, 0x2410019);
+       if (rc < 0)
+               return -ENODEV;
+
+       if (rc == 0) {
+               printk(KERN_INFO "%s: chip revision A2\n", mod_name);
+               rc = drx_load_fw(s, DRXD_FW_A2);
+       } else {
+
+               rc = (rc >> 12) - 3;
+               switch (rc) {
+               case 1:
+                       s->flags |= F_SET_0D4h;
+               case 0:
+               case 4:
+                       s->flags |= F_SET_0D0h;
+                       break;
+               case 2:
+               case 5:
+                       break;
+               case 3:
+                       s->flags |= F_SET_0D4h;
+                       break;
+               default:
+                       return -ENODEV;
+               };
+               printk(KERN_INFO "%s: chip revision B1.%d\n", mod_name, rc);
+               rc = drx_load_fw(s, DRXD_FW_B1);
+       }
+       if (rc < 0)
+               goto error;
+
+       rc = WR16(s, 0x0420033, 0x3973);
+       if (rc < 0)
+               goto error;
+
+       rc = HI_Command(s, 2);
+
+       msleep(1);
+
+       if (s->chip_rev == DRXD_FW_A2) {
+               rc = WR16(s, 0x043012d, 0x47F);
+               if (rc < 0)
+                       goto error;
+       }
+       rc = WR16_E0(s, 0x0400000, 0);
+       if (rc < 0)
+               goto error;
+
+       if (s->config.w92 > 20000 || s->config.w92 % 4000) {
+               printk(KERN_ERR "%s: invalid osc frequency\n", mod_name);
+               rc = -1;
+               goto error;
+       }
+
+       rc = WR16(s, 0x2410010, 1);
+       if (rc < 0)
+               goto error;
+       rc = WR16(s, 0x2410011, 0x15);
+       if (rc < 0)
+               goto error;
+       rc = WR16(s, 0x2410012, s->config.w92 / 4000);
+       if (rc < 0)
+               goto error;
+#ifdef ORIG_FW
+       rc = WR16(s, 0x2410015, 2);
+       if (rc < 0)
+               goto error;
+#endif
+       rc = WR16(s, 0x2410017, 0x3973);
+       if (rc < 0)
+               goto error;
+
+       s->f_osc = s->config.f_osc * 1000;      /* initial estimator */
+
+       s->config.w56 = 1;
+
+       rc = HI_CfgCommand(s);
+       if (rc < 0)
+               goto error;
+
+       rc = write_fw(s, DRXD_InitAtomicRead);
+       if (rc < 0)
+               goto error;
+
+       if (s->chip_rev == DRXD_FW_A2) {
+               rc = WR16(s, 0x2150013, 0);
+               if (rc < 0)
+                       goto error;
+       }
+
+       rc = WR16_E0(s, 0x0400002, 0);
+       if (rc < 0)
+               goto error;
+       rc = WR16(s, 0x0400002, 0);
+       if (rc < 0)
+               goto error;
+
+       if (s->chip_rev == DRXD_FW_A2) {
+               rc = write_fw(s, DRXD_ResetCEFR);
+               if (rc < 0)
+                       goto error;
+       }
+       rc = write_fw(s, DRXD_microcode);
+       if (rc < 0)
+               goto error;
+
+       s->config.w9C = 0x0e;
+       if (s->flags & F_SET_0D0h) {
+               s->config.w9C = 0;
+               rc = RD16(s, 0x0c20010);
+               if (rc < 0)
+                       goto write_DRXD_InitFE_1;
+
+               rc &= ~0x1000;
+               rc = WR16(s, 0x0c20010, rc);
+               if (rc < 0)
+                       goto write_DRXD_InitFE_1;
+
+               rc = RD16(s, 0x0c20011);
+               if (rc < 0)
+                       goto write_DRXD_InitFE_1;
+
+               rc &= ~0x8;
+               rc = WR16(s, 0x0c20011, rc);
+               if (rc < 0)
+                       goto write_DRXD_InitFE_1;
+
+               rc = WR16(s, 0x0c20012, 1);
+       }
+
+      write_DRXD_InitFE_1:
+
+       rc = write_fw(s, DRXD_InitFE_1);
+       if (rc < 0)
+               goto error;
+
+       rc = 1;
+       if (s->chip_rev == DRXD_FW_B1) {
+               if (s->flags & F_SET_0D0h)
+                       rc = 0;
+       } else {
+               if (s->flags & F_SET_0D0h)
+                       rc = 4;
+       }
+
+       rc = WR16(s, 0x0C20012, rc);
+       if (rc < 0)
+               goto error;
+
+       rc = WR16(s, 0x0C20013, s->config.w9E);
+       if (rc < 0)
+               goto error;
+       rc = WR16(s, 0x0C20015, s->config.w9C);
+       if (rc < 0)
+               goto error;
+
+       rc = write_fw(s, DRXD_InitFE_2);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitFT);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitCP);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitCE);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitEQ);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitEC);
+       if (rc < 0)
+               goto error;
+       rc = write_fw(s, DRXD_InitSC);
+       if (rc < 0)
+               goto error;
+
+       rc = SetCfgIfAgc(s, &s->config.ifagc);
+       if (rc < 0)
+               goto error;
+
+       rc = SetCfgRfAgc(s, &s->config.rfagc);
+       if (rc < 0)
+               goto error;
+
+       rc = ConfigureMPEGOutput(s, 1);
+       rc = WR16(s, 0x08201fe, 0x0017);
+       rc = WR16(s, 0x08201ff, 0x0101);
+
+       s->config.d5C = 0;
+       s->config.d60 = 1;
+       s->config.d48 = 1;
+      error:
+       return rc;
+}
+
+static int drx397x_get_frontend(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *params)
+{
+       return 0;
+}
+
+static int drx397x_set_frontend(struct dvb_frontend *fe,
+                               struct dvb_frontend_parameters *params)
+{
+       struct drx397xD_state *s = fe->demodulator_priv;
+
+       s->config.s20d24 = 1;   // 0;
+       return drx_tune(s, params);
+}
+
+static int drx397x_get_tune_settings(struct dvb_frontend *fe,
+                                    struct dvb_frontend_tune_settings
+                                    *fe_tune_settings)
+{
+       fe_tune_settings->min_delay_ms = 10000;
+       fe_tune_settings->step_size = 0;
+       fe_tune_settings->max_drift = 0;
+       return 0;
+}
+
+static int drx397x_read_status(struct dvb_frontend *fe, fe_status_t * status)
+{
+       struct drx397xD_state *s = fe->demodulator_priv;
+       int lockstat;
+
+       GetLockStatus(s, &lockstat);
+       /* TODO */
+//      if (lockstat & 1)
+//      CorrectSysClockDeviation(s);
+
+       *status = 0;
+       if (lockstat & 2) {
+               CorrectSysClockDeviation(s);
+               ConfigureMPEGOutput(s, 1);
+               *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
+       }
+       if (lockstat & 4) {
+               *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+       }
+
+       return 0;
+}
+
+static int drx397x_read_ber(struct dvb_frontend *fe, unsigned int *ber)
+{
+       *ber = 0;
+       return 0;
+}
+
+static int drx397x_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+       *snr = 0;
+       return 0;
+}
+
+static int drx397x_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+       struct drx397xD_state *s = fe->demodulator_priv;
+       int rc;
+
+       if (s->config.ifagc.d00 == 2) {
+               *strength = 0xffff;
+               return 0;
+       }
+       rc = RD16(s, 0x0c20035);
+       if (rc < 0) {
+               *strength = 0;
+               return 0;
+       }
+       rc &= 0x3ff;
+       /* Signal strength is calculated using the following formula:
+        *
+        * a = 2200 * 150 / (2200 + 150);
+        * a = a * 3300 /  (a + 820);
+        * b = 2200 * 3300 / (2200 + 820);
+        * c = (((b-a) * rc) >> 10  + a) << 4;
+        * strength = ~c & 0xffff;
+        *
+        * The following does the same but with less rounding errors:
+        */
+       *strength = ~(7720 + (rc * 30744 >> 10));
+       return 0;
+}
+
+static int drx397x_read_ucblocks(struct dvb_frontend *fe,
+                                unsigned int *ucblocks)
+{
+       *ucblocks = 0;
+       return 0;
+}
+
+static int drx397x_sleep(struct dvb_frontend *fe)
+{
+       return 0;
+}
+
+static void drx397x_release(struct dvb_frontend *fe)
+{
+       struct drx397xD_state *s = fe->demodulator_priv;
+       printk(KERN_INFO "%s: release demodulator\n", mod_name);
+       if (s) {
+               drx_release_fw(s);
+               kfree(s);
+       }
+
+}
+
+static struct dvb_frontend_ops drx397x_ops = {
+
+       .info = {
+                .name                  = "Micronas DRX397xD DVB-T Frontend",
+                .type                  = FE_OFDM,
+                .frequency_min         = 47125000,
+                .frequency_max         = 855250000,
+                .frequency_stepsize    = 166667,
+                .frequency_tolerance   = 0,
+                .caps =                                        /* 0x0C01B2EAE */
+                        FE_CAN_FEC_1_2                 |       // = 0x2,
+                        FE_CAN_FEC_2_3                 |       // = 0x4,
+                        FE_CAN_FEC_3_4                 |       // = 0x8,
+                        FE_CAN_FEC_5_6                 |       // = 0x20,
+                        FE_CAN_FEC_7_8                 |       // = 0x80,
+                        FE_CAN_FEC_AUTO                |       // = 0x200,
+                        FE_CAN_QPSK                    |       // = 0x400,
+                        FE_CAN_QAM_16                  |       // = 0x800,
+                        FE_CAN_QAM_64                  |       // = 0x2000,
+                        FE_CAN_QAM_AUTO                |       // = 0x10000,
+                        FE_CAN_TRANSMISSION_MODE_AUTO  |       // = 0x20000,
+                        FE_CAN_GUARD_INTERVAL_AUTO     |       // = 0x80000,
+                        FE_CAN_HIERARCHY_AUTO          |       // = 0x100000,
+                        FE_CAN_RECOVER                 |       // = 0x40000000,
+                        FE_CAN_MUTE_TS                         // = 0x80000000
+        },
+
+       .release = drx397x_release,
+       .init = drx397x_init,
+       .sleep = drx397x_sleep,
+
+       .set_frontend = drx397x_set_frontend,
+       .get_tune_settings = drx397x_get_tune_settings,
+       .get_frontend = drx397x_get_frontend,
+
+       .read_status = drx397x_read_status,
+       .read_snr = drx397x_read_snr,
+       .read_signal_strength = drx397x_read_signal_strength,
+       .read_ber = drx397x_read_ber,
+       .read_ucblocks = drx397x_read_ucblocks,
+};
+
+struct dvb_frontend *drx397xD_attach(const struct drx397xD_config *config,
+                                    struct i2c_adapter *i2c)
+{
+       struct drx397xD_state *s = NULL;
+
+       /* allocate memory for the internal state */
+       s = kzalloc(sizeof(struct drx397xD_state), GFP_KERNEL);
+       if (s == NULL)
+               goto error;
+
+       /* setup the state */
+       s->i2c = i2c;
+       memcpy(&s->config, config, sizeof(struct drx397xD_config));
+
+       /* check if the demod is there */
+       if (RD16(s, 0x2410019) < 0)
+               goto error;
+
+       /* create dvb_frontend */
+       memcpy(&s->frontend.ops, &drx397x_ops, sizeof(struct dvb_frontend_ops));
+       s->frontend.demodulator_priv = s;
+
+       return &s->frontend;
+      error:
+       kfree(s);
+       return NULL;
+}
+
+MODULE_DESCRIPTION("Micronas DRX397xD DVB-T Frontend");
+MODULE_AUTHOR("Henk Vergonet");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(drx397xD_attach);
diff --git a/drivers/media/dvb/frontends/drx397xD.h b/drivers/media/dvb/frontends/drx397xD.h
new file mode 100644 (file)
index 0000000..ddc7a07
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ *  Driver for Micronas DVB-T drx397xD demodulator
+ *
+ *  Copyright (C) 2007 Henk vergonet <Henk.Vergonet@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef _DRX397XD_H_INCLUDED
+#define _DRX397XD_H_INCLUDED
+
+#include <linux/dvb/frontend.h>
+
+#define DRX_F_STEPSIZE 166667
+#define DRX_F_OFFSET   36000000
+
+#define I2C_ADR_C0(x) \
+(      (u32)cpu_to_le32( \
+               (u32)( \
+                       (((u32)(x) & (u32)0x000000ffUL)      ) | \
+                       (((u32)(x) & (u32)0x0000ff00UL) << 16) | \
+                       (((u32)(x) & (u32)0x0fff0000UL) >>  8) | \
+                        (           (u32)0x00c00000UL)          \
+                     )) \
+)
+
+#define I2C_ADR_E0(x) \
+(      (u32)cpu_to_le32( \
+               (u32)( \
+                       (((u32)(x) & (u32)0x000000ffUL)      ) | \
+                       (((u32)(x) & (u32)0x0000ff00UL) << 16) | \
+                       (((u32)(x) & (u32)0x0fff0000UL) >>  8) | \
+                        (           (u32)0x00e00000UL)          \
+                     )) \
+)
+
+struct drx397xD_CfgRfAgc       /* 0x7c */
+{
+       int d00;        /* 2 */
+       u16 w04;
+       u16 w06;
+};
+
+struct drx397xD_CfgIfAgc       /* 0x68 */
+{
+       int d00;        /* 0 */
+       u16 w04;        /* 0 */
+       u16 w06;
+       u16 w08;
+       u16 w0A;
+       u16 w0C;
+};
+
+struct drx397xD_s20 {
+       int d04;
+       u32 d18;
+       u32 d1C;
+       u32 d20;
+       u32 d14;
+       u32 d24;
+       u32 d0C;
+       u32 d08;
+};
+
+struct drx397xD_config
+{
+       /* demodulator's I2C address */
+       u8      demod_address;          /* 0x0f */
+
+       struct drx397xD_CfgIfAgc  ifagc;  /* 0x68 */
+       struct drx397xD_CfgRfAgc  rfagc;  /* 0x7c */
+       u32     s20d24;
+
+       /* HI_CfgCommand parameters */
+       u16     w50, w52, /* w54, */ w56;
+
+       int     d5C;
+       int     d60;
+       int     d48;
+       int     d28;
+
+       u32     f_if;   /* d14: intermediate frequency [Hz]             */
+                       /*      36000000 on Cinergy 2400i DT            */
+                       /*      42800000 on Pinnacle Hybrid PRO 330e    */
+
+       u16     f_osc;  /* s66: 48000 oscillator frequency [kHz]        */
+
+       u16     w92;    /* 20000 */
+
+       u16     wA0;
+       u16     w98;
+       u16     w9A;
+
+       u16     w9C;    /* 0xe0 */
+       u16     w9E;    /* 0x00 */
+
+       /* used for signal strength calculations in
+          drx397x_read_signal_strength
+       */
+       u16     ss78;   // 2200
+       u16     ss7A;   // 150
+       u16     ss76;   // 820
+};
+
+#if defined(CONFIG_DVB_DRX397XD) || (defined(CONFIG_DVB_DRX397XD_MODULE) && defined(MODULE))
+extern struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
+                                          struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* drx397xD_attach(const struct drx397xD_config *config,
+                                          struct i2c_adapter *i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif /* CONFIG_DVB_DRX397XD */
+
+#endif /* _DRX397XD_H_INCLUDED */
diff --git a/drivers/media/dvb/frontends/drx397xD_fw.h b/drivers/media/dvb/frontends/drx397xD_fw.h
new file mode 100644 (file)
index 0000000..01de02a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Firmware definitions for Micronas drx397xD
+ *
+ * Copyright (C) 2007 Henk Vergonet <Henk.Vergonet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef _FW_ENTRY
+       _FW_ENTRY("drx397xD.A2.fw",     DRXD_FW_A2 = 0          ),
+       _FW_ENTRY("drx397xD.B1.fw",     DRXD_FW_B1              ),
+#undef _FW_ENTRY
+#endif /* _FW_ENTRY */
+
+#ifdef _BLOB_ENTRY
+       _BLOB_ENTRY("InitAtomicRead",   DRXD_InitAtomicRead = 0 ),
+       _BLOB_ENTRY("InitCE",           DRXD_InitCE             ),
+       _BLOB_ENTRY("InitCP",           DRXD_InitCP             ),
+       _BLOB_ENTRY("InitEC",           DRXD_InitEC             ),
+       _BLOB_ENTRY("InitEQ",           DRXD_InitEQ             ),
+       _BLOB_ENTRY("InitFE_1",         DRXD_InitFE_1           ),
+       _BLOB_ENTRY("InitFE_2",         DRXD_InitFE_2           ),
+       _BLOB_ENTRY("InitFT",           DRXD_InitFT             ),
+       _BLOB_ENTRY("InitSC",           DRXD_InitSC             ),
+       _BLOB_ENTRY("ResetCEFR",        DRXD_ResetCEFR          ),
+       _BLOB_ENTRY("ResetECRAM",       DRXD_ResetECRAM         ),
+       _BLOB_ENTRY("microcode",        DRXD_microcode          ),
+#undef _BLOB_ENTRY
+#endif /* _BLOB_ENTRY */
diff --git a/drivers/media/dvb/frontends/z0194a.h b/drivers/media/dvb/frontends/z0194a.h
new file mode 100644 (file)
index 0000000..d2876d2
--- /dev/null
@@ -0,0 +1,97 @@
+/* z0194a.h Sharp z0194a tuner support
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+*      This program is free software; you can redistribute it and/or modify it
+*      under the terms of the GNU General Public License as published by the
+*      Free Software Foundation, version 2.
+*
+* see Documentation/dvb/README.dvb-usb for more information
+*/
+
+#ifndef Z0194A
+#define Z0194A
+
+static int sharp_z0194a__set_symbol_rate(struct dvb_frontend *fe,
+                                        u32 srate, u32 ratio)
+{
+       u8 aclk = 0;
+       u8 bclk = 0;
+
+       if (srate < 1500000) {
+               aclk = 0xb7; bclk = 0x47; }
+       else if (srate < 3000000) {
+               aclk = 0xb7; bclk = 0x4b; }
+       else if (srate < 7000000) {
+               aclk = 0xb7; bclk = 0x4f; }
+       else if (srate < 14000000) {
+               aclk = 0xb7; bclk = 0x53; }
+       else if (srate < 30000000) {
+               aclk = 0xb6; bclk = 0x53; }
+       else if (srate < 45000000) {
+               aclk = 0xb4; bclk = 0x51; }
+
+       stv0299_writereg(fe, 0x13, aclk);
+       stv0299_writereg(fe, 0x14, bclk);
+       stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+       stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+       stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
+
+       return 0;
+}
+
+static u8 sharp_z0194a__inittab[] = {
+       0x01, 0x15,
+       0x02, 0x00,
+       0x03, 0x00,
+       0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+       0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
+       0x06, 0x40,   /* DAC not used, set to high impendance mode */
+       0x07, 0x00,   /* DAC LSB */
+       0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
+       0x09, 0x00,   /* FIFO */
+       0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+       0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
+       0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
+       0x10, 0x3f,   /* AGC2  0x3d */
+       0x11, 0x84,
+       0x12, 0xb9,
+       0x15, 0xc9,   /* lock detector threshold */
+       0x16, 0x00,
+       0x17, 0x00,
+       0x18, 0x00,
+       0x19, 0x00,
+       0x1a, 0x00,
+       0x1f, 0x50,
+       0x20, 0x00,
+       0x21, 0x00,
+       0x22, 0x00,
+       0x23, 0x00,
+       0x28, 0x00,  /* out imp: normal  out type: parallel FEC mode:0 */
+       0x29, 0x1e,  /* 1/2 threshold */
+       0x2a, 0x14,  /* 2/3 threshold */
+       0x2b, 0x0f,  /* 3/4 threshold */
+       0x2c, 0x09,  /* 5/6 threshold */
+       0x2d, 0x05,  /* 7/8 threshold */
+       0x2e, 0x01,
+       0x31, 0x1f,  /* test all FECs */
+       0x32, 0x19,  /* viterbi and synchro search */
+       0x33, 0xfc,  /* rs control */
+       0x34, 0x93,  /* error control */
+       0x0f, 0x52,
+       0xff, 0xff
+};
+
+static struct stv0299_config sharp_z0194a_config = {
+       .demod_address = 0x68,
+       .inittab = sharp_z0194a__inittab,
+       .mclk = 88000000UL,
+       .invert = 1,
+       .skip_reinit = 0,
+       .lock_output = STV0299_LOCKOUTPUT_1,
+       .volt13_op0_op1 = STV0299_VOLT13_OP1,
+       .min_delay_ms = 100,
+       .set_symbol_rate = sharp_z0194a__set_symbol_rate,
+};
+
+#endif
index b4b8ed7..c5f45fe 100644 (file)
@@ -110,12 +110,12 @@ struct smscore_registry_entry_t {
        enum sms_device_type_st type;
 };
 
-struct list_head g_smscore_notifyees;
-struct list_head g_smscore_devices;
-struct mutex g_smscore_deviceslock;
+static struct list_head g_smscore_notifyees;
+static struct list_head g_smscore_devices;
+static struct mutex g_smscore_deviceslock;
 
-struct list_head g_smscore_registry;
-struct mutex g_smscore_registrylock;
+static struct list_head g_smscore_registry;
+static struct mutex g_smscore_registrylock;
 
 static int default_mode = 4;
 
@@ -1187,7 +1187,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 }
 
 
-int smscore_module_init(void)
+static int __init smscore_module_init(void)
 {
        int rc = 0;
 
@@ -1209,7 +1209,7 @@ int smscore_module_init(void)
        return rc;
 }
 
-void smscore_module_exit(void)
+static void __exit smscore_module_exit(void)
 {
 
        kmutex_lock(&g_smscore_deviceslock);
index 6f9c185..229274a 100644 (file)
@@ -27,8 +27,8 @@
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-struct list_head g_smsdvb_clients;
-struct mutex g_smsdvb_clientslock;
+static struct list_head g_smsdvb_clients;
+static struct mutex g_smsdvb_clientslock;
 
 static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
 {
index 87c973a..41b5a98 100644 (file)
@@ -5,8 +5,6 @@ config TTPCI_EEPROM
 config DVB_AV7110
        tristate "AV7110 cards"
        depends on DVB_CORE && PCI && I2C
-       depends on HOTPLUG
-       select FW_LOADER if !DVB_AV7110_FIRMWARE
        select TTPCI_EEPROM
        select VIDEO_SAA7146_VV
        depends on VIDEO_DEV    # dependencies of VIDEO_SAA7146_VV
@@ -127,14 +125,12 @@ config DVB_BUDGET_AV
        depends on DVB_BUDGET_CORE && I2C
        select VIDEO_SAA7146_VV
        depends on VIDEO_DEV    # dependencies of VIDEO_SAA7146_VV
-       depends on HOTPLUG      # dependency of FW_LOADER
        select DVB_PLL if !DVB_FE_CUSTOMISE
        select DVB_STV0299 if !DVB_FE_CUSTOMISE
        select DVB_TDA1004X if !DVB_FE_CUSTOMISE
        select DVB_TDA10021 if !DVB_FE_CUSTOMISE
        select DVB_TDA10023 if !DVB_FE_CUSTOMISE
        select DVB_TUA6100 if !DVB_FE_CUSTOMISE
-       select FW_LOADER
        help
          Support for simple SAA7146 based DVB cards
          (so called Budget- or Nova-PCI cards) without onboard
index a23cc0a..d5f48a3 100644 (file)
@@ -1,8 +1,6 @@
 config DVB_TTUSB_DEC
        tristate "Technotrend/Hauppauge USB DEC devices"
        depends on DVB_CORE && USB && INPUT
-       depends on HOTPLUG      # due to FW_LOADER
-       select FW_LOADER
        select CRC32
        help
          Support for external USB adapters designed by Technotrend and
index 4e3f83e..1ed88f3 100644 (file)
@@ -85,6 +85,7 @@
 #include <linux/input.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/usb.h>
 
 /*
@@ -444,14 +445,7 @@ static const struct file_operations usb_dsbr100_fops = {
        .llseek         = no_llseek,
 };
 
-/* V4L2 interface */
-static struct video_device dsbr100_videodev_template =
-{
-       .owner          = THIS_MODULE,
-       .name           = "D-Link DSB-R 100",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &usb_dsbr100_fops,
-       .release        = video_device_release,
+static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -466,6 +460,14 @@ static struct video_device dsbr100_videodev_template =
        .vidioc_s_input     = vidioc_s_input,
 };
 
+/* V4L2 interface */
+static struct video_device dsbr100_videodev_template = {
+       .name           = "D-Link DSB-R 100",
+       .fops           = &usb_dsbr100_fops,
+       .ioctl_ops      = &usb_dsbr100_ioctl_ops,
+       .release        = video_device_release,
+};
+
 /* check if the device is present and register with v4l and
 usb if it is */
 static int usb_dsbr100_probe(struct usb_interface *intf,
index 09fe6f1..7fd7ee2 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include "oss/aci.h"
 #include "miropcm20-rds-core.h"
 
@@ -228,9 +229,7 @@ static const struct file_operations pcm20_fops = {
 };
 
 static struct video_device pcm20_radio = {
-       .owner          = THIS_MODULE,
        .name           = "Miro PCM 20 radio",
-       .type           = VID_TYPE_TUNER,
        .fops           = &pcm20_fops,
        .priv           = &pcm20_unit
 };
index 1ec18ed..eba9209 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>     /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
@@ -388,12 +389,7 @@ static const struct file_operations rtrack_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device rtrack_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "RadioTrack radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &rtrack_fops,
+static const struct v4l2_ioctl_ops rtrack_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -408,6 +404,12 @@ static struct video_device rtrack_radio=
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device rtrack_radio = {
+       .name           = "RadioTrack radio",
+       .fops           = &rtrack_fops,
+       .ioctl_ops      = &rtrack_ioctl_ops,
+};
+
 static int __init rtrack_init(void)
 {
        if(io==-1)
index 46cdb54..3fe5504 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
@@ -352,12 +353,7 @@ static const struct file_operations aztech_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device aztech_radio=
-{
-       .owner              = THIS_MODULE,
-       .name               = "Aztech radio",
-       .type               = VID_TYPE_TUNER,
-       .fops               = &aztech_fops,
+static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -372,6 +368,12 @@ static struct video_device aztech_radio=
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device aztech_radio = {
+       .name               = "Aztech radio",
+       .fops               = &aztech_fops,
+       .ioctl_ops          = &aztech_ioctl_ops,
+};
+
 module_param_named(debug,aztech_radio.debug, int, 0644);
 MODULE_PARM_DESC(debug,"activates debug info");
 
index b14db53..6166e72 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* V4L2 API defs                */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/param.h>
 #include <linux/pnp.h>
 
@@ -569,12 +570,7 @@ static const struct file_operations cadet_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device cadet_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "Cadet radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &cadet_fops,
+static const struct v4l2_ioctl_ops cadet_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -589,6 +585,12 @@ static struct video_device cadet_radio=
        .vidioc_s_input     = vidioc_s_input,
 };
 
+static struct video_device cadet_radio = {
+       .name           = "Cadet radio",
+       .fops           = &cadet_fops,
+       .ioctl_ops      = &cadet_ioctl_ops,
+};
+
 #ifdef CONFIG_PNP
 
 static struct pnp_device_id cadet_pnp_devices[] = {
index de49be9..36e754e 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/pci.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/errno.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
@@ -374,11 +375,7 @@ static const struct file_operations gemtek_pci_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device vdev_template = {
-       .owner         = THIS_MODULE,
-       .name          = "Gemtek PCI Radio",
-       .type          = VID_TYPE_TUNER,
-       .fops          = &gemtek_pci_fops,
+static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -393,6 +390,12 @@ static struct video_device vdev_template = {
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device vdev_template = {
+       .name          = "Gemtek PCI Radio",
+       .fops          = &gemtek_pci_fops,
+       .ioctl_ops     = &gemtek_pci_ioctl_ops,
+};
+
 static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci_device_id *pci_id )
 {
        struct gemtek_pci_card *card;
index 81f6aeb..2b1a622 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
+#include <media/v4l2-ioctl.h>
 #include <media/v4l2-common.h>
 #include <linux/spinlock.h>
 
@@ -552,11 +553,7 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
        return 0;
 }
 
-static struct video_device gemtek_radio = {
-       .owner                  = THIS_MODULE,
-       .name                   = "GemTek Radio card",
-       .type                   = VID_TYPE_TUNER,
-       .fops                   = &gemtek_fops,
+static const struct v4l2_ioctl_ops gemtek_ioctl_ops = {
        .vidioc_querycap        = vidioc_querycap,
        .vidioc_g_tuner         = vidioc_g_tuner,
        .vidioc_s_tuner         = vidioc_s_tuner,
@@ -571,6 +568,12 @@ static struct video_device gemtek_radio = {
        .vidioc_s_ctrl          = vidioc_s_ctrl
 };
 
+static struct video_device gemtek_radio = {
+       .name                   = "GemTek Radio card",
+       .fops                   = &gemtek_fops,
+       .ioctl_ops              = &gemtek_ioctl_ops,
+};
+
 /*
  * Initialization / cleanup related stuff.
  */
index bddd3c4..0ada1c6 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/pci.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,6)
@@ -354,10 +355,7 @@ static u16 __devinit radio_power_on(struct radio_device *dev)
        return (ofreq == radio_bits_get(dev));
 }
 
-static struct video_device maestro_radio = {
-       .name           = "Maestro radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &maestro_fops,
+static const struct v4l2_ioctl_ops maestro_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -372,6 +370,12 @@ static struct video_device maestro_radio = {
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device maestro_radio = {
+       .name           = "Maestro radio",
+       .fops           = &maestro_fops,
+       .ioctl_ops      = &maestro_ioctl_ops,
+};
+
 static int __devinit maestro_probe(struct pci_dev *pdev,
        const struct pci_device_id *ent)
 {
index 0133ecf..43c7549 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/pci.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #define DRIVER_VERSION "0.77"
 
@@ -373,13 +374,7 @@ static int vidioc_s_ctrl (struct file *file, void *priv,
        return -EINVAL;
 }
 
-static struct video_device maxiradio_radio =
-{
-       .owner              = THIS_MODULE,
-       .name               = "Maxi Radio FM2000 radio",
-       .type               = VID_TYPE_TUNER,
-       .fops               = &maxiradio_fops,
-
+static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -394,6 +389,12 @@ static struct video_device maxiradio_radio =
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device maxiradio_radio = {
+       .name               = "Maxi Radio FM2000 radio",
+       .fops               = &maxiradio_fops,
+       .ioctl_ops          = &maxiradio_ioctl_ops,
+};
+
 static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        if(!request_region(pci_resource_start(pdev, 0),
index 0708021..e2dde08 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/spinlock.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
@@ -294,12 +295,7 @@ static const struct file_operations rtrack2_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device rtrack2_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "RadioTrack II radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &rtrack2_fops,
+static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -314,6 +310,12 @@ static struct video_device rtrack2_radio=
        .vidioc_s_input     = vidioc_s_input,
 };
 
+static struct video_device rtrack2_radio = {
+       .name           = "RadioTrack II radio",
+       .fops           = &rtrack2_fops,
+       .ioctl_ops      = &rtrack2_ioctl_ops,
+};
+
 static int __init rtrack2_init(void)
 {
        if(io==-1)
index 66e052f..bb5d92f 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/delay.h>       /* udelay                       */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/isapnp.h>
 #include <asm/io.h>            /* outb, outb_p                 */
 #include <asm/uaccess.h>       /* copy to/from user            */
@@ -294,12 +295,7 @@ static const struct file_operations fmi_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device fmi_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "SF16FMx radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &fmi_fops,
+static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -314,6 +310,12 @@ static struct video_device fmi_radio=
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device fmi_radio = {
+       .name           = "SF16FMx radio",
+       .fops           = &fmi_fops,
+       .ioctl_ops      = &fmi_ioctl_ops,
+};
+
 /* ladis: this is my card. does any other types exist? */
 static struct isapnp_device_id id_table[] __devinitdata = {
        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
index b0ccf7c..6290553 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 
 static struct mutex lock;
@@ -410,12 +411,7 @@ static const struct file_operations fmr2_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device fmr2_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "SF16FMR2 radio",
-       . type          = VID_TYPE_TUNER,
-       .fops           = &fmr2_fops,
+static const struct v4l2_ioctl_ops fmr2_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -430,6 +426,12 @@ static struct video_device fmr2_radio=
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device fmr2_radio = {
+       .name           = "SF16FMR2 radio",
+       .fops           = &fmr2_fops,
+       .ioctl_ops      = &fmr2_ioctl_ops,
+};
+
 static int __init fmr2_init(void)
 {
        fmr2_unit.port = io;
index dc93a88..a4984ff 100644 (file)
 #include <linux/videodev2.h>
 #include <linux/mutex.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/rds.h>
 #include <asm/unaligned.h>
 
@@ -1585,15 +1586,7 @@ done:
        return retval;
 }
 
-
-/*
- * si470x_viddev_tamples - video device interface
- */
-static struct video_device si470x_viddev_template = {
-       .fops                   = &si470x_fops,
-       .name                   = DRIVER_NAME,
-       .type                   = VID_TYPE_TUNER,
-       .release                = video_device_release,
+static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
        .vidioc_querycap        = si470x_vidioc_querycap,
        .vidioc_g_input         = si470x_vidioc_g_input,
        .vidioc_s_input         = si470x_vidioc_s_input,
@@ -1607,7 +1600,16 @@ static struct video_device si470x_viddev_template = {
        .vidioc_g_frequency     = si470x_vidioc_g_frequency,
        .vidioc_s_frequency     = si470x_vidioc_s_frequency,
        .vidioc_s_hw_freq_seek  = si470x_vidioc_s_hw_freq_seek,
-       .owner                  = THIS_MODULE,
+};
+
+/*
+ * si470x_viddev_tamples - video device interface
+ */
+static struct video_device si470x_viddev_template = {
+       .fops                   = &si470x_fops,
+       .ioctl_ops              = &si470x_ioctl_ops,
+       .name                   = DRIVER_NAME,
+       .release                = video_device_release,
 };
 
 
index acc3208..cefa44f 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/uaccess.h>       /* copy to/from user            */
 #include <linux/videodev2.h>   /* kernel radio structs         */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/spinlock.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
@@ -366,12 +367,7 @@ static const struct file_operations terratec_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device terratec_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "TerraTec ActiveRadio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &terratec_fops,
+static const struct v4l2_ioctl_ops terratec_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -386,6 +382,12 @@ static struct video_device terratec_radio=
        .vidioc_s_input     = vidioc_s_input,
 };
 
+static struct video_device terratec_radio = {
+       .name           = "TerraTec ActiveRadio",
+       .fops           = &terratec_fops,
+       .ioctl_ops      = &terratec_ioctl_ops,
+};
+
 static int __init terratec_init(void)
 {
        if(io==-1)
index 4ebdfba..d70172d 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/uaccess.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
@@ -346,12 +347,7 @@ static const struct file_operations trust_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device trust_radio=
-{
-       .owner          = THIS_MODULE,
-       .name           = "Trust FM Radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &trust_fops,
+static const struct v4l2_ioctl_ops trust_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -366,6 +362,12 @@ static struct video_device trust_radio=
        .vidioc_s_input     = vidioc_s_input,
 };
 
+static struct video_device trust_radio = {
+       .name           = "Trust FM Radio",
+       .fops           = &trust_fops,
+       .ioctl_ops      = &trust_ioctl_ops,
+};
+
 static int __init trust_init(void)
 {
        if(io == -1) {
index 18f2abd..f8d62cf 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/uaccess.h>       /* copy to/from user              */
 #include <linux/videodev2.h>   /* kernel radio structs           */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,1,1)
@@ -344,12 +345,7 @@ static const struct file_operations typhoon_fops = {
        .llseek         = no_llseek,
 };
 
-static struct video_device typhoon_radio =
-{
-       .owner          = THIS_MODULE,
-       .name           = "Typhoon Radio",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &typhoon_fops,
+static const struct v4l2_ioctl_ops typhoon_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -364,6 +360,12 @@ static struct video_device typhoon_radio =
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device typhoon_radio = {
+       .name           = "Typhoon Radio",
+       .fops           = &typhoon_fops,
+       .ioctl_ops      = &typhoon_ioctl_ops,
+};
+
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
 
 static int typhoon_proc_show(struct seq_file *m, void *v)
index 43773c5..9f17a33 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/uaccess.h>       /* copy to/from user              */
 #include <linux/videodev2.h>   /* kernel radio structs           */
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
 #define RADIO_VERSION KERNEL_VERSION(0,0,2)
@@ -407,12 +408,7 @@ static const struct file_operations zoltrix_fops =
        .llseek         = no_llseek,
 };
 
-static struct video_device zoltrix_radio =
-{
-       .owner          = THIS_MODULE,
-       .name           = "Zoltrix Radio Plus",
-       .type           = VID_TYPE_TUNER,
-       .fops           = &zoltrix_fops,
+static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = {
        .vidioc_querycap    = vidioc_querycap,
        .vidioc_g_tuner     = vidioc_g_tuner,
        .vidioc_s_tuner     = vidioc_s_tuner,
@@ -427,6 +423,12 @@ static struct video_device zoltrix_radio =
        .vidioc_s_ctrl      = vidioc_s_ctrl,
 };
 
+static struct video_device zoltrix_radio = {
+       .name           = "Zoltrix Radio Plus",
+       .fops           = &zoltrix_fops,
+       .ioctl_ops      = &zoltrix_ioctl_ops,
+};
+
 static int __init zoltrix_init(void)
 {
        if (io == -1) {
index f606d29..d4a6e56 100644 (file)
@@ -487,17 +487,6 @@ config VIDEO_PMS
          To compile this driver as a module, choose M here: the
          module will be called pms.
 
-config VIDEO_PLANB
-       tristate "PlanB Video-In on PowerMac"
-       depends on PPC_PMAC && VIDEO_V4L1 && BROKEN
-       help
-         PlanB is the V4L driver for the PowerMac 7x00/8x00 series video
-         input hardware. If you want to experiment with this, say Y.
-         Otherwise, or if you don't understand a word, say N. See
-         <http://www.cpu.lu/~mlan/linux/dev/planb.html> for more info.
-
-         Saying M will compile this driver as a module (planb).
-
 config VIDEO_BWQCAM
        tristate "Quickcam BW Video For Linux"
        depends on PARPORT && VIDEO_V4L1
@@ -806,13 +795,7 @@ menuconfig V4L_USB_DRIVERS
 
 if V4L_USB_DRIVERS && USB
 
-config USB_VIDEO_CLASS
-       tristate "USB Video Class (UVC)"
-       ---help---
-         Support for the USB Video Class (UVC).  Currently only video
-         input devices, such as webcams, are supported.
-
-         For more information see: <http://linux-uvc.berlios.de/>
+source "drivers/media/video/uvc/Kconfig"
 
 source "drivers/media/video/gspca/Kconfig"
 
index 45d5db5..bbc6f8b 100644 (file)
@@ -10,6 +10,8 @@ msp3400-objs  :=      msp3400-driver.o msp3400-kthreads.o
 
 stkwebcam-objs :=      stk-webcam.o stk-sensor.o
 
+videodev-objs  :=      v4l2-dev.o v4l2-ioctl.o
+
 obj-$(CONFIG_VIDEO_DEV) += videodev.o compat_ioctl32.o v4l2-int-device.o
 
 obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
@@ -55,7 +57,6 @@ obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
 obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
 
 obj-$(CONFIG_VIDEO_PMS) += pms.o
-obj-$(CONFIG_VIDEO_PLANB) += planb.o
 obj-$(CONFIG_VIDEO_VINO) += vino.o indycam.o
 obj-$(CONFIG_VIDEO_STRADIS) += stradis.o
 obj-$(CONFIG_VIDEO_CPIA) += cpia.o
index 8c7d195..56ebfd5 100644 (file)
@@ -754,7 +754,6 @@ static const struct file_operations ar_fops = {
 };
 
 static struct video_device ar_template = {
-       .owner          = THIS_MODULE,
        .name           = "Colour AR VGA",
        .type           = VID_TYPE_CAPTURE,
        .fops           = &ar_fops,
index 52b2491..ed9a50f 100644 (file)
@@ -6,6 +6,7 @@ config VIDEO_AU0828
        select VIDEO_TVEEPROM
        select DVB_AU8522 if !DVB_FE_CUSTOMIZE
        select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+       select MEDIA_TUNER_MXL5007T if !DVB_FE_CUSTOMIZE
        ---help---
          This is a video4linux driver for Auvitek's USB device.
 
index 898e123..443e590 100644 (file)
@@ -32,6 +32,9 @@ struct au0828_board au0828_boards[] = {
        [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
                .name   = "Hauppauge HVR950Q",
        },
+       [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = {
+               .name   = "Hauppauge HVR950Q rev xxF8",
+       },
        [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
                .name   = "DViCO FusionHDTV USB",
        },
@@ -49,6 +52,7 @@ int au0828_tuner_callback(void *priv, int command, int arg)
        switch (dev->board) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
        case AU0828_BOARD_DVICO_FUSIONHDTV7:
                if (command == 0) {
                        /* Tuner Reset Command from xc5000 */
@@ -110,6 +114,7 @@ void au0828_card_setup(struct au0828_dev *dev)
        switch (dev->board) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
                if (dev->i2c_rc == 0)
                        hauppauge_eeprom(dev, eeprom+0xa0);
                break;
@@ -128,6 +133,7 @@ void au0828_gpio_setup(struct au0828_dev *dev)
        switch (dev->board) {
        case AU0828_BOARD_HAUPPAUGE_HVR850:
        case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
                /* GPIO's
                 * 4 - CS5340
                 * 5 - AU8522 Demodulator
@@ -193,6 +199,12 @@ struct usb_device_id au0828_usb_id_table [] = {
                .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
        { USB_DEVICE(0x0fd9, 0x0008),
                .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7201),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
+       { USB_DEVICE(0x2040, 0x7211),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
+       { USB_DEVICE(0x2040, 0x7281),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
        { },
 };
 
index e26f54a..c37f5fd 100644 (file)
@@ -23,3 +23,4 @@
 #define AU0828_BOARD_HAUPPAUGE_HVR950Q 1
 #define AU0828_BOARD_HAUPPAUGE_HVR850  2
 #define AU0828_BOARD_DVICO_FUSIONHDTV7 3
+#define AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL     4
index c6d4705..584a83a 100644 (file)
@@ -28,6 +28,7 @@
 #include "au0828.h"
 #include "au8522.h"
 #include "xc5000.h"
+#include "mxl5007t.h"
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -45,6 +46,11 @@ static struct xc5000_config hauppauge_hvr950q_tunerconfig = {
        .tuner_callback   = au0828_tuner_callback
 };
 
+static struct mxl5007t_config mxl5007t_hvr950q_config = {
+       .xtal_freq_hz = MxL_XTAL_24_MHZ,
+       .if_freq_hz = MxL_IF_6_MHZ,
+};
+
 /*-------------------------------------------------------------------*/
 static void urb_completion(struct urb *purb)
 {
@@ -342,6 +348,15 @@ int au0828_dvb_register(struct au0828_dev *dev)
                                &dev->i2c_adap,
                                &hauppauge_hvr950q_tunerconfig, dev);
                break;
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
+               dvb->frontend = dvb_attach(au8522_attach,
+                               &hauppauge_hvr950q_config,
+                               &dev->i2c_adap);
+               if (dvb->frontend != NULL)
+                       dvb_attach(mxl5007t_attach, dvb->frontend,
+                                  &dev->i2c_adap, 0x60,
+                                  &mxl5007t_hvr950q_config);
+               break;
        default:
                printk(KERN_WARNING "The frontend of your DVB/ATSC card "
                       "isn't supported yet\n");
index 24a34fc..ce71e8e 100644 (file)
@@ -1,9 +1,7 @@
 config VIDEO_BT848
        tristate "BT848 Video For Linux"
        depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT
-       depends on HOTPLUG      # due to FW_LOADER
        select I2C_ALGOBIT
-       select FW_LOADER
        select VIDEO_BTCX
        select VIDEOBUF_DMA_SG
        select VIDEO_IR
index 0ea559a..85bf31a 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/kdev_t.h>
 #include "bttvp.h"
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/tvaudio.h>
 #include <media/msp3400.h>
 
@@ -163,8 +164,8 @@ MODULE_LICENSE("GPL");
 static ssize_t show_card(struct device *cd,
                         struct device_attribute *attr, char *buf)
 {
-       struct video_device *vfd = container_of(cd, struct video_device, class_dev);
-       struct bttv *btv = dev_get_drvdata(vfd->dev);
+       struct video_device *vfd = container_of(cd, struct video_device, dev);
+       struct bttv *btv = dev_get_drvdata(vfd->parent);
        return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
 }
 static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
@@ -3357,10 +3358,7 @@ static const struct file_operations bttv_fops =
        .poll     = bttv_poll,
 };
 
-static struct video_device bttv_video_template =
-{
-       .fops     = &bttv_fops,
-       .minor    = -1,
+static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
        .vidioc_querycap                = bttv_querycap,
        .vidioc_enum_fmt_vid_cap        = bttv_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap           = bttv_g_fmt_vid_cap,
@@ -3411,8 +3409,14 @@ static struct video_device bttv_video_template =
        .vidioc_g_register              = bttv_g_register,
        .vidioc_s_register              = bttv_s_register,
 #endif
-       .tvnorms                        = BTTV_NORMS,
-       .current_norm                   = V4L2_STD_PAL,
+};
+
+static struct video_device bttv_video_template = {
+       .fops         = &bttv_fops,
+       .minor        = -1,
+       .ioctl_ops    = &bttv_ioctl_ops,
+       .tvnorms      = BTTV_NORMS,
+       .current_norm = V4L2_STD_PAL,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -3635,10 +3639,7 @@ static const struct file_operations radio_fops =
        .poll     = radio_poll,
 };
 
-static struct video_device radio_template =
-{
-       .fops     = &radio_fops,
-       .minor    = -1,
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
        .vidioc_querycap        = radio_querycap,
        .vidioc_g_tuner         = radio_g_tuner,
        .vidioc_enum_input      = radio_enum_input,
@@ -3655,6 +3656,12 @@ static struct video_device radio_template =
        .vidioc_s_frequency     = bttv_s_frequency,
 };
 
+static struct video_device radio_template = {
+       .fops      = &radio_fops,
+       .minor     = -1,
+       .ioctl_ops = &radio_ioctl_ops,
+};
+
 /* ----------------------------------------------------------------------- */
 /* some debug code                                                         */
 
@@ -4175,8 +4182,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id)
 
 static struct video_device *vdev_init(struct bttv *btv,
                                      const struct video_device *template,
-                                     const char *type_name,
-                                     const int type)
+                                     const char *type_name)
 {
        struct video_device *vfd;
 
@@ -4185,9 +4191,8 @@ static struct video_device *vdev_init(struct bttv *btv,
                return NULL;
        *vfd = *template;
        vfd->minor   = -1;
-       vfd->dev     = &btv->c.pci->dev;
+       vfd->parent  = &btv->c.pci->dev;
        vfd->release = video_device_release;
-       vfd->type    = type;
        vfd->debug   = bttv_debug;
        snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
                 btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
@@ -4223,20 +4228,11 @@ static void bttv_unregister_video(struct bttv *btv)
 /* register video4linux devices */
 static int __devinit bttv_register_video(struct bttv *btv)
 {
-       int video_type = VID_TYPE_CAPTURE |
-                        VID_TYPE_TUNER   |
-                        VID_TYPE_CLIPPING|
-                        VID_TYPE_SCALES;
-
-       if (no_overlay <= 0) {
-               bttv_video_template.type |= VID_TYPE_OVERLAY;
-       } else {
+       if (no_overlay > 0)
                printk("bttv: Overlay support disabled.\n");
-       }
 
        /* video */
-       btv->video_dev = vdev_init(btv, &bttv_video_template,
-                                  "video", video_type);
+       btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
 
        if (NULL == btv->video_dev)
                goto err;
@@ -4244,7 +4240,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
                goto err;
        printk(KERN_INFO "bttv%d: registered device video%d\n",
               btv->c.nr,btv->video_dev->minor & 0x1f);
-       if (device_create_file(&btv->video_dev->class_dev,
+       if (device_create_file(&btv->video_dev->dev,
                                     &dev_attr_card)<0) {
                printk(KERN_ERR "bttv%d: device_create_file 'card' "
                       "failed\n", btv->c.nr);
@@ -4252,8 +4248,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
        }
 
        /* vbi */
-       btv->vbi_dev = vdev_init(btv, &bttv_video_template,
-                                "vbi", VID_TYPE_TUNER | VID_TYPE_TELETEXT);
+       btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
 
        if (NULL == btv->vbi_dev)
                goto err;
@@ -4265,8 +4260,7 @@ static int __devinit bttv_register_video(struct bttv *btv)
        if (!btv->has_radio)
                return 0;
        /* radio */
-       btv->radio_dev = vdev_init(btv, &radio_template,
-                                  "radio", VID_TYPE_TUNER);
+       btv->radio_dev = vdev_init(btv, &radio_template, "radio");
        if (NULL == btv->radio_dev)
                goto err;
        if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0)
index 0af5868..649682a 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/interrupt.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <media/v4l2-ioctl.h>
 
 #include "bttvp.h"
 
index 68f28e5..6819e21 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/kdev_t.h>
+#include <media/v4l2-ioctl.h>
 #include <asm/io.h>
 #include "bttvp.h"
 
index b364ada..d3b3268 100644 (file)
@@ -74,6 +74,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <linux/sched.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 
@@ -906,9 +907,7 @@ static const struct file_operations qcam_fops = {
 };
 static struct video_device qcam_template=
 {
-       .owner          = THIS_MODULE,
        .name           = "Connectix Quickcam",
-       .type           = VID_TYPE_CAPTURE,
        .fops           = &qcam_fops,
 };
 
index fe1e67b..fe9379b 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/sched.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/mutex.h>
 #include <linux/jiffies.h>
 
@@ -701,9 +702,7 @@ static const struct file_operations qcam_fops = {
 
 static struct video_device qcam_template=
 {
-       .owner          = THIS_MODULE,
        .name           = "Colour QuickCam",
-       .type           = VID_TYPE_CAPTURE,
        .fops           = &qcam_fops,
 };
 
index d99453f..c149b7d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/spinlock.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/v4l2-chip-ident.h>
 #include <linux/device.h>
 #include <linux/wait.h>
@@ -1768,17 +1769,7 @@ static const struct file_operations cafe_v4l_fops = {
        .llseek = no_llseek,
 };
 
-static struct video_device cafe_v4l_template = {
-       .name = "cafe",
-       .type = VFL_TYPE_GRABBER,
-       .type2 = VID_TYPE_CAPTURE,
-       .minor = -1, /* Get one dynamically */
-       .tvnorms = V4L2_STD_NTSC_M,
-       .current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */
-
-       .fops = &cafe_v4l_fops,
-       .release = cafe_v4l_dev_release,
-
+static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = {
        .vidioc_querycap        = cafe_vidioc_querycap,
        .vidioc_enum_fmt_vid_cap = cafe_vidioc_enum_fmt_vid_cap,
        .vidioc_try_fmt_vid_cap = cafe_vidioc_try_fmt_vid_cap,
@@ -1801,6 +1792,17 @@ static struct video_device cafe_v4l_template = {
        .vidioc_s_parm          = cafe_vidioc_s_parm,
 };
 
+static struct video_device cafe_v4l_template = {
+       .name = "cafe",
+       .minor = -1, /* Get one dynamically */
+       .tvnorms = V4L2_STD_NTSC_M,
+       .current_norm = V4L2_STD_NTSC_M,  /* make mplayer happy */
+
+       .fops = &cafe_v4l_fops,
+       .ioctl_ops = &cafe_v4l_ioctl_ops,
+       .release = cafe_v4l_dev_release,
+};
+
 
 
 
@@ -2157,7 +2159,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
        cam->v4ldev = cafe_v4l_template;
        cam->v4ldev.debug = 0;
 //     cam->v4ldev.debug = V4L2_DEBUG_IOCTL_ARG;
-       cam->v4ldev.dev = &pdev->dev;
+       cam->v4ldev.parent = &pdev->dev;
        ret = video_register_device(&cam->v4ldev, VFL_TYPE_GRABBER, -1);
        if (ret)
                goto out_smbus;
index 54de0cd..bd5d9de 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/videodev2.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
-#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #ifdef CONFIG_COMPAT
 
index 2a81376..dc8cc61 100644 (file)
@@ -3799,9 +3799,7 @@ static const struct file_operations cpia_fops = {
 };
 
 static struct video_device cpia_template = {
-       .owner          = THIS_MODULE,
        .name           = "CPiA Camera",
-       .type           = VID_TYPE_CAPTURE,
        .fops           = &cpia_fops,
 };
 
index 5096058..8f0cfee 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 
index f2e8b1c..af8b9ec 100644 (file)
@@ -32,6 +32,7 @@
 #include "cpia2.h"
 
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/firmware.h>
 
index 7ce2789..515c8b5 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <media/v4l2-ioctl.h>
 
 #include "cpia2.h"
 #include "cpia2dev.h"
@@ -1935,11 +1936,7 @@ static const struct file_operations fops_template = {
 
 static struct video_device cpia2_template = {
        /* I could not find any place for the old .initialize initializer?? */
-       .owner=         THIS_MODULE,
        .name=          "CPiA2 Camera",
-       .type=          VID_TYPE_CAPTURE,
-       .type2 =        V4L2_CAP_VIDEO_CAPTURE |
-                       V4L2_CAP_STREAMING,
        .minor=         -1,
        .fops=          &fops_template,
        .release=       video_device_release,
index 1c3fa3a..61d14d2 100644 (file)
@@ -111,7 +111,7 @@ static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg)
                if (cmd == VIDIOC_DBG_G_REGISTER)
                        reg->val = cs5345_read(client, reg->reg & 0x1f);
                else
-                       cs5345_write(client, reg->reg & 0x1f, reg->val & 0x1f);
+                       cs5345_write(client, reg->reg & 0x1f, reg->val & 0xff);
                break;
        }
 #endif
index 645b339..e30a589 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-i2c-drv-legacy.h>
index 9aefdc5..ef48565 100644 (file)
@@ -2,9 +2,7 @@ config VIDEO_CX18
        tristate "Conexant cx23418 MPEG encoder support"
        depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
        depends on INPUT        # due to VIDEO_IR
-       depends on HOTPLUG      # due to FW_LOADER
        select I2C_ALGOBIT
-       select FW_LOADER
        select VIDEO_IR
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
index c40a286..0b55837 100644 (file)
@@ -30,7 +30,6 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
        if (freq != 32000 && freq != 44100 && freq != 48000)
                return -EINVAL;
 
-       /* common for all inputs and rates */
        /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
        cx18_av_write(cx, 0x127, 0x50);
 
@@ -38,15 +37,30 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                switch (freq) {
                case 32000:
                        /* VID_PLL and AUX_PLL */
-                       cx18_av_write4(cx, 0x108, 0x1006040f);
+                       cx18_av_write4(cx, 0x108, 0x1408040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x01bb39ee);
+                       /* 0x8.9504318a * 28,636,363.636 / 0x14 = 32000 * 384 */
+                       cx18_av_write4(cx, 0x110, 0x012a0863);
 
-                       /* src3/4/6_ctl = 0x0801f77f */
+                       /* src3/4/6_ctl */
+                       /* 0x1.f77f = (4 * 15734.26) / 32000 */
                        cx18_av_write4(cx, 0x900, 0x0801f77f);
                        cx18_av_write4(cx, 0x904, 0x0801f77f);
                        cx18_av_write4(cx, 0x90c, 0x0801f77f);
+
+                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
+                       cx18_av_write(cx, 0x127, 0x54);
+
+                       /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11202fff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
+                        *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa10d2ef8);
                        break;
 
                case 44100:
@@ -54,12 +68,24 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                        cx18_av_write4(cx, 0x108, 0x1009040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+                       /* 0x9.7635e7 * 28,636,363.63 / 0x10 = 44100 * 384 */
+                       cx18_av_write4(cx, 0x110, 0x00ec6bce);
 
-                       /* src3/4/6_ctl = 0x08016d59 */
+                       /* src3/4/6_ctl */
+                       /* 0x1.6d59 = (4 * 15734.26) / 44100 */
                        cx18_av_write4(cx, 0x900, 0x08016d59);
                        cx18_av_write4(cx, 0x904, 0x08016d59);
                        cx18_av_write4(cx, 0x90c, 0x08016d59);
+
+                       /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x112092ff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
+                        *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa11d4bf8);
                        break;
 
                case 48000:
@@ -67,12 +93,24 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                        cx18_av_write4(cx, 0x108, 0x100a040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x0098d6e5);
+                       /* 0xa.4c6b6ea * 28,636,363.63 / 0x10 = 48000 * 384 */
+                       cx18_av_write4(cx, 0x110, 0x0098d6dd);
 
-                       /* src3/4/6_ctl = 0x08014faa */
+                       /* src3/4/6_ctl */
+                       /* 0x1.4faa = (4 * 15734.26) / 48000 */
                        cx18_av_write4(cx, 0x900, 0x08014faa);
                        cx18_av_write4(cx, 0x904, 0x08014faa);
                        cx18_av_write4(cx, 0x90c, 0x08014faa);
+
+                       /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11205fff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
+                        *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa11193f8);
                        break;
                }
        } else {
@@ -82,18 +120,31 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                        cx18_av_write4(cx, 0x108, 0x1e08040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x012a0869);
+                       /* 0x8.9504318 * 28,636,363.63 / 0x1e = 32000 * 256 */
+                       cx18_av_write4(cx, 0x110, 0x012a0863);
 
-                       /* src1_ctl = 0x08010000 */
+                       /* src1_ctl */
+                       /* 0x1.0000 = 32000/32000 */
                        cx18_av_write4(cx, 0x8f8, 0x08010000);
 
-                       /* src3/4/6_ctl = 0x08020000 */
+                       /* src3/4/6_ctl */
+                       /* 0x2.0000 = 2 * (32000/32000) */
                        cx18_av_write4(cx, 0x900, 0x08020000);
                        cx18_av_write4(cx, 0x904, 0x08020000);
                        cx18_av_write4(cx, 0x90c, 0x08020000);
 
                        /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
                        cx18_av_write(cx, 0x127, 0x54);
+
+                       /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11201fff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
+                        *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa10d2ef8);
                        break;
 
                case 44100:
@@ -101,15 +152,28 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                        cx18_av_write4(cx, 0x108, 0x1809040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+                       /* 0x9.7635e74 * 28,636,363.63 / 0x18 = 44100 * 256 */
+                       cx18_av_write4(cx, 0x110, 0x00ec6bce);
 
-                       /* src1_ctl = 0x08010000 */
+                       /* src1_ctl */
+                       /* 0x1.60cd = 44100/32000 */
                        cx18_av_write4(cx, 0x8f8, 0x080160cd);
 
-                       /* src3/4/6_ctl = 0x08020000 */
+                       /* src3/4/6_ctl */
+                       /* 0x1.7385 = 2 * (32000/44100) */
                        cx18_av_write4(cx, 0x900, 0x08017385);
                        cx18_av_write4(cx, 0x904, 0x08017385);
                        cx18_av_write4(cx, 0x90c, 0x08017385);
+
+                       /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x112061ff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
+                        *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa11d4bf8);
                        break;
 
                case 48000:
@@ -117,15 +181,28 @@ static int set_audclk_freq(struct cx18 *cx, u32 freq)
                        cx18_av_write4(cx, 0x108, 0x180a040f);
 
                        /* AUX_PLL_FRAC */
-                       cx18_av_write4(cx, 0x110, 0x0098d6e5);
+                       /* 0xa.4c6b6ea * 28,636,363.63 / 0x18 = 48000 * 256 */
+                       cx18_av_write4(cx, 0x110, 0x0098d6dd);
 
-                       /* src1_ctl = 0x08010000 */
+                       /* src1_ctl */
+                       /* 0x1.8000 = 48000/32000 */
                        cx18_av_write4(cx, 0x8f8, 0x08018000);
 
-                       /* src3/4/6_ctl = 0x08020000 */
+                       /* src3/4/6_ctl */
+                       /* 0x1.5555 = 2 * (32000/48000) */
                        cx18_av_write4(cx, 0x900, 0x08015555);
                        cx18_av_write4(cx, 0x904, 0x08015555);
                        cx18_av_write4(cx, 0x90c, 0x08015555);
+
+                       /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11203fff);
+
+                       /*
+                        * EN_AV_LOCK = 1
+                        * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
+                        *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa11193f8);
                        break;
                }
        }
index 45e31b0..4801bc7 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/dvb/video.h>
 #include <linux/dvb/audio.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/tuner.h>
 #include "cx18-mailbox.h"
 #include "cx18-av-core.h"
index 2d630d9..78fadd2 100644 (file)
 
 #define CX18_DSP0_INTERRUPT_MASK       0xd0004C
 
-/* Encoder/decoder firmware sizes */
-#define CX18_FW_CPU_SIZE               (158332)
-#define CX18_FW_APU_SIZE               (141200)
-
 #define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
 #define APU_ROM_SYNC2 0x72646548 /* "rdeH" */
 
@@ -100,35 +96,22 @@ struct cx18_apu_rom_seghdr {
        u32 size;
 };
 
-static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx, long size)
+static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
 {
        const struct firmware *fw = NULL;
-       int retries = 3;
        int i, j;
+       unsigned size;
        u32 __iomem *dst = (u32 __iomem *)mem;
        const u32 *src;
 
-retry:
-       if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) {
-               CX18_ERR("Unable to open firmware %s (must be %ld bytes)\n",
-                               fn, size);
+       if (request_firmware(&fw, fn, &cx->dev->dev)) {
+               CX18_ERR("Unable to open firmware %s\n", fn);
                CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
                return -ENOMEM;
        }
 
        src = (const u32 *)fw->data;
 
-       if (fw->size != size) {
-               /* Due to race conditions in firmware loading (esp. with
-                  udev <0.95) the wrong file was sometimes loaded. So we check
-                  filesizes to see if at least the right-sized file was
-                  loaded. If not, then we retry. */
-               CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
-                               fn, size, fw->size);
-               release_firmware(fw);
-               retries--;
-               goto retry;
-       }
        for (i = 0; i < fw->size; i += 4096) {
                setup_page(i);
                for (j = i; j < fw->size && j < i + 4096; j += 4) {
@@ -145,15 +128,16 @@ retry:
        }
        if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
                CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
+       size = fw->size;
        release_firmware(fw);
        return size;
 }
 
-static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, long size)
+static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx)
 {
        const struct firmware *fw = NULL;
-       int retries = 3;
        int i, j;
+       unsigned size;
        const u32 *src;
        struct cx18_apu_rom_seghdr seghdr;
        const u8 *vers;
@@ -161,10 +145,8 @@ static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
        u32 apu_version = 0;
        int sz;
 
-retry:
-       if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) {
-               CX18_ERR("unable to open firmware %s (must be %ld bytes)\n",
-                               fn, size);
+       if (request_firmware(&fw, fn, &cx->dev->dev)) {
+               CX18_ERR("unable to open firmware %s\n", fn);
                CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
                return -ENOMEM;
        }
@@ -173,19 +155,8 @@ retry:
        vers = fw->data + sizeof(seghdr);
        sz = fw->size;
 
-       if (fw->size != size) {
-               /* Due to race conditions in firmware loading (esp. with
-                  udev <0.95) the wrong file was sometimes loaded. So we check
-                  filesizes to see if at least the right-sized file was
-                  loaded. If not, then we retry. */
-               CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
-                              fn, size, fw->size);
-               release_firmware(fw);
-               retries--;
-               goto retry;
-       }
        apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
-       while (offset + sizeof(seghdr) < size) {
+       while (offset + sizeof(seghdr) < fw->size) {
                /* TODO: byteswapping */
                memcpy(&seghdr, src + offset / 4, sizeof(seghdr));
                offset += sizeof(seghdr);
@@ -215,6 +186,7 @@ retry:
        if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
                CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
                                fn, apu_version, fw->size);
+       size = fw->size;
        release_firmware(fw);
        /* Clear bit0 for APU to start from 0 */
        write_reg(read_reg(0xc72030) & ~1, 0xc72030);
@@ -340,7 +312,7 @@ int cx18_firmware_init(struct cx18 *cx)
        /* Only if the processor is not running */
        if (read_reg(CX18_PROC_SOFT_RESET) & 8) {
                int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
-                              cx->enc_mem, cx, CX18_FW_APU_SIZE);
+                              cx->enc_mem, cx);
 
                write_enc(0xE51FF004, 0);
                write_enc(0xa00000, 4);  /* todo: not hardcoded */
@@ -348,7 +320,7 @@ int cx18_firmware_init(struct cx18 *cx)
                cx18_msleep_timeout(500, 0);
 
                sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
-                                       cx->enc_mem, cx, CX18_FW_CPU_SIZE);
+                                       cx->enc_mem, cx);
 
                if (sz > 0) {
                        int retries = 0;
index 0d74e59..a7f8396 100644 (file)
@@ -787,50 +787,54 @@ int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        return res;
 }
 
-void cx18_set_funcs(struct video_device *vdev)
-{
-       vdev->vidioc_querycap                = cx18_querycap;
-       vdev->vidioc_g_priority              = cx18_g_priority;
-       vdev->vidioc_s_priority              = cx18_s_priority;
-       vdev->vidioc_s_audio                 = cx18_s_audio;
-       vdev->vidioc_g_audio                 = cx18_g_audio;
-       vdev->vidioc_enumaudio               = cx18_enumaudio;
-       vdev->vidioc_enum_input              = cx18_enum_input;
-       vdev->vidioc_cropcap                 = cx18_cropcap;
-       vdev->vidioc_s_crop                  = cx18_s_crop;
-       vdev->vidioc_g_crop                  = cx18_g_crop;
-       vdev->vidioc_g_input                 = cx18_g_input;
-       vdev->vidioc_s_input                 = cx18_s_input;
-       vdev->vidioc_g_frequency             = cx18_g_frequency;
-       vdev->vidioc_s_frequency             = cx18_s_frequency;
-       vdev->vidioc_s_tuner                 = cx18_s_tuner;
-       vdev->vidioc_g_tuner                 = cx18_g_tuner;
-       vdev->vidioc_g_enc_index             = cx18_g_enc_index;
-       vdev->vidioc_g_std                   = cx18_g_std;
-       vdev->vidioc_s_std                   = cx18_s_std;
-       vdev->vidioc_log_status              = cx18_log_status;
-       vdev->vidioc_enum_fmt_vid_cap        = cx18_enum_fmt_vid_cap;
-       vdev->vidioc_encoder_cmd             = cx18_encoder_cmd;
-       vdev->vidioc_try_encoder_cmd         = cx18_try_encoder_cmd;
-       vdev->vidioc_g_fmt_vid_cap           = cx18_g_fmt_vid_cap;
-       vdev->vidioc_g_fmt_vbi_cap           = cx18_g_fmt_vbi_cap;
-       vdev->vidioc_g_fmt_sliced_vbi_cap    = cx18_g_fmt_sliced_vbi_cap;
-       vdev->vidioc_s_fmt_vid_cap           = cx18_s_fmt_vid_cap;
-       vdev->vidioc_s_fmt_vbi_cap           = cx18_s_fmt_vbi_cap;
-       vdev->vidioc_s_fmt_sliced_vbi_cap    = cx18_s_fmt_sliced_vbi_cap;
-       vdev->vidioc_try_fmt_vid_cap         = cx18_try_fmt_vid_cap;
-       vdev->vidioc_try_fmt_vbi_cap         = cx18_try_fmt_vbi_cap;
-       vdev->vidioc_try_fmt_sliced_vbi_cap  = cx18_try_fmt_sliced_vbi_cap;
-       vdev->vidioc_g_sliced_vbi_cap        = cx18_g_sliced_vbi_cap;
-       vdev->vidioc_g_chip_ident            = cx18_g_chip_ident;
+static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
+       .vidioc_querycap                = cx18_querycap,
+       .vidioc_g_priority              = cx18_g_priority,
+       .vidioc_s_priority              = cx18_s_priority,
+       .vidioc_s_audio                 = cx18_s_audio,
+       .vidioc_g_audio                 = cx18_g_audio,
+       .vidioc_enumaudio               = cx18_enumaudio,
+       .vidioc_enum_input              = cx18_enum_input,
+       .vidioc_cropcap                 = cx18_cropcap,
+       .vidioc_s_crop                  = cx18_s_crop,
+       .vidioc_g_crop                  = cx18_g_crop,
+       .vidioc_g_input                 = cx18_g_input,
+       .vidioc_s_input                 = cx18_s_input,
+       .vidioc_g_frequency             = cx18_g_frequency,
+       .vidioc_s_frequency             = cx18_s_frequency,
+       .vidioc_s_tuner                 = cx18_s_tuner,
+       .vidioc_g_tuner                 = cx18_g_tuner,
+       .vidioc_g_enc_index             = cx18_g_enc_index,
+       .vidioc_g_std                   = cx18_g_std,
+       .vidioc_s_std                   = cx18_s_std,
+       .vidioc_log_status              = cx18_log_status,
+       .vidioc_enum_fmt_vid_cap        = cx18_enum_fmt_vid_cap,
+       .vidioc_encoder_cmd             = cx18_encoder_cmd,
+       .vidioc_try_encoder_cmd         = cx18_try_encoder_cmd,
+       .vidioc_g_fmt_vid_cap           = cx18_g_fmt_vid_cap,
+       .vidioc_g_fmt_vbi_cap           = cx18_g_fmt_vbi_cap,
+       .vidioc_g_fmt_sliced_vbi_cap    = cx18_g_fmt_sliced_vbi_cap,
+       .vidioc_s_fmt_vid_cap           = cx18_s_fmt_vid_cap,
+       .vidioc_s_fmt_vbi_cap           = cx18_s_fmt_vbi_cap,
+       .vidioc_s_fmt_sliced_vbi_cap    = cx18_s_fmt_sliced_vbi_cap,
+       .vidioc_try_fmt_vid_cap         = cx18_try_fmt_vid_cap,
+       .vidioc_try_fmt_vbi_cap         = cx18_try_fmt_vbi_cap,
+       .vidioc_try_fmt_sliced_vbi_cap  = cx18_try_fmt_sliced_vbi_cap,
+       .vidioc_g_sliced_vbi_cap        = cx18_g_sliced_vbi_cap,
+       .vidioc_g_chip_ident            = cx18_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       vdev->vidioc_g_register              = cx18_g_register;
-       vdev->vidioc_s_register              = cx18_s_register;
+       .vidioc_g_register              = cx18_g_register,
+       .vidioc_s_register              = cx18_s_register,
 #endif
-       vdev->vidioc_default                 = cx18_default;
-       vdev->vidioc_queryctrl               = cx18_queryctrl;
-       vdev->vidioc_querymenu               = cx18_querymenu;
-       vdev->vidioc_g_ext_ctrls             = cx18_g_ext_ctrls;
-       vdev->vidioc_s_ext_ctrls             = cx18_s_ext_ctrls;
-       vdev->vidioc_try_ext_ctrls           = cx18_try_ext_ctrls;
+       .vidioc_default                 = cx18_default,
+       .vidioc_queryctrl               = cx18_queryctrl,
+       .vidioc_querymenu               = cx18_querymenu,
+       .vidioc_g_ext_ctrls             = cx18_g_ext_ctrls,
+       .vidioc_s_ext_ctrls             = cx18_s_ext_ctrls,
+       .vidioc_try_ext_ctrls           = cx18_try_ext_ctrls,
+};
+
+void cx18_set_funcs(struct video_device *vdev)
+{
+       vdev->ioctl_ops = &cx18_ioctl_ops;
 }
index 1728b1d..0da57f5 100644 (file)
@@ -187,14 +187,11 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
                return -ENOMEM;
        }
 
-       s->v4l2dev->type =
-               VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT |
-               VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER;
        snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18-%d",
                        cx->num);
 
        s->v4l2dev->minor = minor;
-       s->v4l2dev->dev = &cx->dev->dev;
+       s->v4l2dev->parent = &cx->dev->dev;
        s->v4l2dev->fops = cx18_stream_info[type].fops;
        s->v4l2dev->release = video_device_release;
        s->v4l2dev->tvnorms = V4L2_STD_ALL;
index 5cfb46b..e60bd31 100644 (file)
@@ -1,9 +1,7 @@
 config VIDEO_CX23885
        tristate "Conexant cx23885 (2388x successor) support"
        depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
-       depends on HOTPLUG      # due to FW_LOADER
        select I2C_ALGOBIT
-       select FW_LOADER
        select VIDEO_BTCX
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
index e7ef093..8118091 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/cx2341x.h>
 
 #include "cx23885.h"
@@ -1699,14 +1700,7 @@ static struct file_operations mpeg_fops = {
        .llseek        = no_llseek,
 };
 
-static struct video_device cx23885_mpeg_template = {
-       .name          = "cx23885",
-       .type          = VID_TYPE_CAPTURE |
-                               VID_TYPE_TUNER |
-                               VID_TYPE_SCALES |
-                               VID_TYPE_MPEG_ENCODER,
-       .fops          = &mpeg_fops,
-       .minor         = -1,
+static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
        .vidioc_s_std            = vidioc_s_std,
        .vidioc_enum_input       = vidioc_enum_input,
        .vidioc_g_input          = vidioc_g_input,
@@ -1735,6 +1729,13 @@ static struct video_device cx23885_mpeg_template = {
        .vidioc_queryctrl        = vidioc_queryctrl,
 };
 
+static struct video_device cx23885_mpeg_template = {
+       .name          = "cx23885",
+       .fops          = &mpeg_fops,
+       .ioctl_ops     = &mpeg_ioctl_ops,
+       .minor         = -1,
+};
+
 void cx23885_417_unregister(struct cx23885_dev *dev)
 {
        dprintk(1, "%s()\n", __func__);
@@ -1766,7 +1767,7 @@ static struct video_device *cx23885_video_dev_alloc(
        vfd->minor   = -1;
        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
                type, cx23885_boards[tsport->dev->board].name);
-       vfd->dev     = &pci->dev;
+       vfd->parent  = &pci->dev;
        vfd->release = video_device_release;
        return vfd;
 }
index fd7112c..a19de85 100644 (file)
@@ -145,6 +145,7 @@ struct cx23885_board cx23885_boards[] = {
        },
        [CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP] = {
                .name           = "DViCO FusionHDTV7 Dual Express",
+               .portb          = CX23885_MPEG_DVB,
                .portc          = CX23885_MPEG_DVB,
        },
 };
@@ -325,25 +326,41 @@ int cx23885_tuner_callback(void *priv, int command, int arg)
 {
        struct cx23885_i2c *bus = priv;
        struct cx23885_dev *dev = bus->dev;
+       u32 bitmask = 0;
+
+       if (command != 0) {
+               printk(KERN_ERR "%s(): Unknown command 0x%x.\n",
+                       __func__, command);
+               return -EINVAL;
+       }
 
        switch(dev->board) {
        case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
-               if(command == 0) {      /* Tuner Reset Command from xc5000 */
-                       /* Drive the tuner into reset and out */
-                       cx_clear(GP0_IO, 0x00000004);
-                       mdelay(200);
-                       cx_set(GP0_IO, 0x00000004);
-                       return 0;
-               }
-               else {
-                       printk(KERN_ERR
-                               "%s(): Unknow command.\n", __func__);
-                       return -EINVAL;
+               /* Tuner Reset Command from xc5000 */
+               if (command == 0)
+                       bitmask = 0x04;
+               break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+               if (command == 0) {
+
+                       /* Two identical tuners on two different i2c buses,
+                        * we need to reset the correct gpio. */
+                       if (bus->nr == 0)
+                               bitmask = 0x01;
+                       else if (bus->nr == 1)
+                               bitmask = 0x04;
                }
                break;
        }
 
-       return 0; /* Should never be here */
+       if (bitmask) {
+               /* Drive the tuner into reset and back out */
+               cx_clear(GP0_IO, bitmask);
+               mdelay(200);
+               cx_set(GP0_IO, bitmask);
+       }
+
+       return 0;
 }
 
 void cx23885_gpio_setup(struct cx23885_dev *dev)
@@ -435,6 +452,19 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                mdelay(20);
                cx_set(GP0_IO, 0x00050005);
                break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+               /* GPIO-0 xc5000 tuner reset i2c bus 0 */
+               /* GPIO-1 s5h1409 demod reset i2c bus 0 */
+               /* GPIO-2 xc5000 tuner reset i2c bus 1 */
+               /* GPIO-3 s5h1409 demod reset i2c bus 0 */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x000f0000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x0000000f);
+               mdelay(20);
+               cx_set(GP0_IO, 0x000f000f);
+               break;
        }
 }
 
index d17343e..6286a9c 100644 (file)
@@ -76,6 +76,117 @@ LIST_HEAD(cx23885_devlist);
  * 0x00010ea0 0x00010xxx Free
  */
 
+static struct sram_channel cx23885_sram_channels[] = {
+       [SRAM_CH01] = {
+               .name           = "VID A",
+               .cmds_start     = 0x10000,
+               .ctrl_start     = 0x10380,
+               .cdt            = 0x104c0,
+               .fifo_start     = 0x40,
+               .fifo_size      = 0x2800,
+               .ptr1_reg       = DMA1_PTR1,
+               .ptr2_reg       = DMA1_PTR2,
+               .cnt1_reg       = DMA1_CNT1,
+               .cnt2_reg       = DMA1_CNT2,
+       },
+       [SRAM_CH02] = {
+               .name           = "ch2",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA2_PTR1,
+               .ptr2_reg       = DMA2_PTR2,
+               .cnt1_reg       = DMA2_CNT1,
+               .cnt2_reg       = DMA2_CNT2,
+       },
+       [SRAM_CH03] = {
+               .name           = "TS1 B",
+               .cmds_start     = 0x100A0,
+               .ctrl_start     = 0x10400,
+               .cdt            = 0x10580,
+               .fifo_start     = 0x5000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA3_PTR1,
+               .ptr2_reg       = DMA3_PTR2,
+               .cnt1_reg       = DMA3_CNT1,
+               .cnt2_reg       = DMA3_CNT2,
+       },
+       [SRAM_CH04] = {
+               .name           = "ch4",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA4_PTR1,
+               .ptr2_reg       = DMA4_PTR2,
+               .cnt1_reg       = DMA4_CNT1,
+               .cnt2_reg       = DMA4_CNT2,
+       },
+       [SRAM_CH05] = {
+               .name           = "ch5",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA5_PTR1,
+               .ptr2_reg       = DMA5_PTR2,
+               .cnt1_reg       = DMA5_CNT1,
+               .cnt2_reg       = DMA5_CNT2,
+       },
+       [SRAM_CH06] = {
+               .name           = "TS2 C",
+               .cmds_start     = 0x10140,
+               .ctrl_start     = 0x10440,
+               .cdt            = 0x105e0,
+               .fifo_start     = 0x6000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA5_PTR1,
+               .ptr2_reg       = DMA5_PTR2,
+               .cnt1_reg       = DMA5_CNT1,
+               .cnt2_reg       = DMA5_CNT2,
+       },
+       [SRAM_CH07] = {
+               .name           = "ch7",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA6_PTR1,
+               .ptr2_reg       = DMA6_PTR2,
+               .cnt1_reg       = DMA6_CNT1,
+               .cnt2_reg       = DMA6_CNT2,
+       },
+       [SRAM_CH08] = {
+               .name           = "ch8",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA7_PTR1,
+               .ptr2_reg       = DMA7_PTR2,
+               .cnt1_reg       = DMA7_CNT1,
+               .cnt2_reg       = DMA7_CNT2,
+       },
+       [SRAM_CH09] = {
+               .name           = "ch9",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA8_PTR1,
+               .ptr2_reg       = DMA8_PTR2,
+               .cnt1_reg       = DMA8_CNT1,
+               .cnt2_reg       = DMA8_CNT2,
+       },
+};
+
 static struct sram_channel cx23887_sram_channels[] = {
        [SRAM_CH01] = {
                .name           = "VID A",
@@ -104,8 +215,8 @@ static struct sram_channel cx23887_sram_channels[] = {
        [SRAM_CH03] = {
                .name           = "TS1 B",
                .cmds_start     = 0x100A0,
-               .ctrl_start     = 0x10780,
-               .cdt            = 0x10400,
+               .ctrl_start     = 0x10630,
+               .cdt            = 0x10870,
                .fifo_start     = 0x5000,
                .fifo_size      = 0x1000,
                .ptr1_reg       = DMA3_PTR1,
@@ -140,7 +251,7 @@ static struct sram_channel cx23887_sram_channels[] = {
        [SRAM_CH06] = {
                .name           = "TS2 C",
                .cmds_start     = 0x10140,
-               .ctrl_start     = 0x10680,
+               .ctrl_start     = 0x10670,
                .cdt            = 0x108d0,
                .fifo_start     = 0x6000,
                .fifo_size      = 0x1000,
@@ -460,6 +571,7 @@ static void cx23885_reset(struct cx23885_dev *dev)
        cx_write(AUDIO_INT_INT_STAT, 0xffffffff);
        cx_write(AUDIO_EXT_INT_STAT, 0xffffffff);
        cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
+       cx_write(PAD_CTRL, 0x00500300);
 
        mdelay(100);
 
@@ -625,7 +737,6 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
        atomic_inc(&dev->refcount);
 
        dev->nr = cx23885_devcount++;
-       dev->sram_channels = cx23887_sram_channels;
        sprintf(dev->name, "cx23885[%d]", dev->nr);
 
        mutex_lock(&devlist);
@@ -637,11 +748,13 @@ static int cx23885_dev_setup(struct cx23885_dev *dev)
                dev->bridge = CX23885_BRIDGE_887;
                /* Apply a sensible clock frequency for the PCIe bridge */
                dev->clk_freq = 25000000;
+               dev->sram_channels = cx23887_sram_channels;
        } else
        if(dev->pci->device == 0x8852) {
                dev->bridge = CX23885_BRIDGE_885;
                /* Apply a sensible clock frequency for the PCIe bridge */
                dev->clk_freq = 28000000;
+               dev->sram_channels = cx23885_sram_channels;
        } else
                BUG();
 
@@ -1010,8 +1123,9 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
                port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
        dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __func__,
                port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
-       dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __func__,
-               port->reg_src_sel, cx_read(port->reg_src_sel));
+       if (port->reg_src_sel)
+               dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __func__,
+                       port->reg_src_sel, cx_read(port->reg_src_sel));
        dprintk(1, "%s() lngth(0x%08X)          0x%08x\n", __func__,
                port->reg_lngth, cx_read(port->reg_lngth));
        dprintk(1, "%s() hw_sop_ctrl(0x%08X)    0x%08x\n", __func__,
@@ -1042,6 +1156,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
        dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
                buf->vb.width, buf->vb.height, buf->vb.field);
 
+       /* Stop the fifo and risc engine for this port */
+       cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+
        /* setup fifo + format */
        cx23885_sram_channel_setup(dev,
                                   &dev->sram_channels[ port->sram_chno ],
@@ -1083,7 +1200,21 @@ static int cx23885_start_dma(struct cx23885_tsport *port,
        cx_write(port->reg_gpcnt_ctl, 3);
        q->count = 1;
 
-       if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
+       /* Set VIDB pins to input */
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+               reg = cx_read(PAD_CTRL);
+               reg &= ~0x3; /* Clear TS1_OE & TS1_SOP_OE */
+               cx_write(PAD_CTRL, reg);
+       }
+
+       /* Set VIDC pins to input */
+       if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
+               reg = cx_read(PAD_CTRL);
+               reg &= ~0x4; /* Clear TS2_SOP_OE */
+               cx_write(PAD_CTRL, reg);
+       }
+
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
 
                reg = cx_read(PAD_CTRL);
                reg = reg & ~0x1;    /* Clear TS1_OE */
@@ -1133,7 +1264,7 @@ static int cx23885_stop_dma(struct cx23885_tsport *port)
        cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);
        cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
 
-       if (cx23885_boards[dev->board].portb & CX23885_MPEG_ENCODER) {
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
 
                reg = cx_read(PAD_CTRL);
 
index 043fc4e..ad2235d 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "cx23885.h"
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
 /* Include V4L1 specific functions. Should be removed soon */
@@ -326,7 +327,7 @@ struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
                return NULL;
        *vfd = *template;
        vfd->minor   = -1;
-       vfd->dev     = &pci->dev;
+       vfd->parent  = &pci->dev;
        vfd->release = video_device_release;
        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
                 dev->name, type, cx23885_boards[dev->board].name);
@@ -1433,12 +1434,7 @@ static const struct file_operations video_fops = {
        .llseek        = no_llseek,
 };
 
-static struct video_device cx23885_vbi_template;
-static struct video_device cx23885_video_template = {
-       .name                 = "cx23885-video",
-       .type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
-       .fops                 = &video_fops,
-       .minor                = -1,
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_querycap      = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
@@ -1471,6 +1467,14 @@ static struct video_device cx23885_video_template = {
        .vidioc_g_register    = vidioc_g_register,
        .vidioc_s_register    = vidioc_s_register,
 #endif
+};
+
+static struct video_device cx23885_vbi_template;
+static struct video_device cx23885_video_template = {
+       .name                 = "cx23885-video",
+       .fops                 = &video_fops,
+       .minor                = -1,
+       .ioctl_ops            = &video_ioctl_ops,
        .tvnorms              = CX23885_NORMS,
        .current_norm         = V4L2_STD_NTSC_M,
 };
@@ -1512,7 +1516,6 @@ int cx23885_video_register(struct cx23885_dev *dev)
        memcpy(&cx23885_vbi_template, &cx23885_video_template,
                sizeof(cx23885_vbi_template));
        strcpy(cx23885_vbi_template.name, "cx23885-vbi");
-       cx23885_vbi_template.type = VID_TYPE_TELETEXT|VID_TYPE_TUNER;
 
        dev->tvnorm = cx23885_video_template.current_norm;
 
index 448f4cd..de515da 100644 (file)
@@ -1,8 +1,6 @@
 config VIDEO_CX25840
        tristate "Conexant CX2584x audio/video decoders"
        depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
-       depends on HOTPLUG # due to FW_LOADER
-       select FW_LOADER
        ---help---
          Support for the Conexant CX2584x audio/video decoders.
 
index e7bf4f4..209d3bc 100644 (file)
@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL");
 
 static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
 
-int cx25840_debug;
+static int cx25840_debug;
 
 module_param_named(debug,cx25840_debug, int, 0644);
 
index 72916ba..b87337e 100644 (file)
@@ -24,8 +24,6 @@
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 
-extern int cx25840_debug;
-
 /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is
    present in Hauppauge PVR-150 (and possibly PVR-500) cards that have
    certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The
index 10e20d8..9dd7bdf 100644 (file)
@@ -33,9 +33,8 @@ config VIDEO_CX88_ALSA
 
 config VIDEO_CX88_BLACKBIRD
        tristate "Blackbird MPEG encoder support (cx2388x + cx23416)"
-       depends on VIDEO_CX88 && HOTPLUG
+       depends on VIDEO_CX88
        select VIDEO_CX2341X
-       select FW_LOADER
        ---help---
          This adds support for MPEG encoder cards based on the
          Blackbird reference design, using the Conexant 2388x
index bfdca58..9a1374a 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 #include <media/cx2341x.h>
 
 #include "cx88.h"
@@ -1174,12 +1175,7 @@ static const struct file_operations mpeg_fops =
        .llseek        = no_llseek,
 };
 
-static struct video_device cx8802_mpeg_template =
-{
-       .name                 = "cx8802",
-       .type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES|VID_TYPE_MPEG_ENCODER,
-       .fops                 = &mpeg_fops,
-       .minor                = -1,
+static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
        .vidioc_querymenu     = vidioc_querymenu,
        .vidioc_querycap      = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
@@ -1207,6 +1203,13 @@ static struct video_device cx8802_mpeg_template =
        .vidioc_g_tuner       = vidioc_g_tuner,
        .vidioc_s_tuner       = vidioc_s_tuner,
        .vidioc_s_std         = vidioc_s_std,
+};
+
+static struct video_device cx8802_mpeg_template = {
+       .name                 = "cx8802",
+       .fops                 = &mpeg_fops,
+       .ioctl_ops            = &mpeg_ioctl_ops,
+       .minor                = -1,
        .tvnorms              = CX88_NORMS,
        .current_norm         = V4L2_STD_NTSC_M,
 };
index fa6d398..de199a2 100644 (file)
@@ -1348,7 +1348,7 @@ static const struct cx88_board cx88_boards[] = {
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
                .tda9887_conf   = TDA9887_PRESENT,
-               .audio_chip     = AUDIO_CHIP_WM8775,
+               .audio_chip     = V4L2_IDENT_WM8775,
                .input          = {{
                        .type   = CX88_VMUX_TELEVISION,
                        .vmux   = 0,
index 60eeda3..d656fec 100644 (file)
@@ -40,6 +40,7 @@
 
 #include "cx88.h"
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -1006,7 +1007,7 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
                return NULL;
        *vfd = *template;
        vfd->minor   = -1;
-       vfd->dev     = &pci->dev;
+       vfd->parent  = &pci->dev;
        vfd->release = video_device_release;
        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
                 core->name, type, core->board.name);
index 0fed5cd..ef4d56e 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "cx88.h"
 #include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
 
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
 /* Include V4L1 specific functions. Should be removed soon */
@@ -447,7 +448,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input)
                   the initialization. Some boards may use different
                   routes for different inputs. HVR-1300 surely does */
                if (core->board.audio_chip &&
-                   core->board.audio_chip == AUDIO_CHIP_WM8775) {
+                   core->board.audio_chip == V4L2_IDENT_WM8775) {
                        struct v4l2_routing route;
 
                        route.input = INPUT(input).audioroute;
@@ -1682,13 +1683,7 @@ static const struct file_operations video_fops =
        .llseek        = no_llseek,
 };
 
-static struct video_device cx8800_vbi_template;
-static struct video_device cx8800_video_template =
-{
-       .name                 = "cx8800-video",
-       .type                 = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_SCALES,
-       .fops                 = &video_fops,
-       .minor                = -1,
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_querycap      = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
        .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
@@ -1721,6 +1716,15 @@ static struct video_device cx8800_video_template =
        .vidioc_g_register    = vidioc_g_register,
        .vidioc_s_register    = vidioc_s_register,
 #endif
+};
+
+static