Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
authorLinus Torvalds <torvalds@g5.osdl.org>
Sat, 30 Sep 2006 16:39:15 +0000 (09:39 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sat, 30 Sep 2006 16:39:15 +0000 (09:39 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (180 commits)
  V4L/DVB (4641): Trivial: use lowercase letters in hex subsystem ids
  V4L/DVB (4639): Cx88: add autodetection for alternate revision of Leadtek PVR
  V4L/DVB (4638): Basic DVB-T and analog TV support for the HVR1300.
  V4L/DVB (4637): Add a default method for VIDIOC_G_PARM
  V4L/DVB (4635): Extend bttv and saa7134 to check for both AGP and PCI PCI failure case
  V4L/DVB (4634): Zr36120: implement pcipci checks
  V4L/DVB (4632): Zoran: Implement pcipci failure check
  V4L/DVB (4631): Av7110: remove V4L2_CAP_VBI_CAPTURE flag
  V4L/DVB (4630): Av7110: FW_LOADER depemdency fixed
  V4L/DVB (4629): Saa7134: add card support for Proteus Pro 2309
  V4L/DVB (4628): Fix VIDIOC_ENUMSTD ioctl in videodev.c
  V4L/DVB (4627): Vivi crashes with mplayer
  V4L/DVB (4626): On saa7111/7113, LUMA_CTRL need a different value
  V4L/DVB (4624): Tvaudio: Replaced kernel_thread() with kthread_run()
  V4L/DVB (4622): Copy-paste bug in videodev.c
  V4L/DVB (4620): Fix AGC configuration for MOD3000P-based boards
  V4L/DVB (4619): Fixes some I2C dependencies on V4L devices
  V4L/DVB (4617): Problem with dibusb-mb.c USB IDs
  V4L/DVB (4616): [PATCH] Nebula DigiTV USB RC support
  V4L/DVB (4614): Export symbol saa7134_tvaudio_setmute from saa7134 for saa7134-alsa
  ...

197 files changed:
Documentation/feature-removal-schedule.txt
Documentation/video4linux/CARDLIST.cx88
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/bttv/Insmod-options
Documentation/video4linux/cx2341x/README.hm12 [new file with mode: 0644]
Documentation/video4linux/cx2341x/README.vbi [new file with mode: 0644]
drivers/media/common/Kconfig
drivers/media/common/ir-keymaps.c
drivers/media/common/saa7146_fops.c
drivers/media/dvb/b2c2/Kconfig
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/bt8xx/Kconfig
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/bt8xx/dst_ca.c
drivers/media/dvb/bt8xx/dst_common.h
drivers/media/dvb/bt8xx/dvb-bt8xx.c
drivers/media/dvb/dvb-core/Kconfig
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_frontend.h
drivers/media/dvb/dvb-core/dvbdev.h
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/a800.c
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dibusb-common.c
drivers/media/dvb/dvb-usb/dibusb-mb.c
drivers/media/dvb/dvb-usb/dibusb-mc.c
drivers/media/dvb/dvb-usb/dibusb.h
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dtt200u.c
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
drivers/media/dvb/dvb-usb/nova-t-usb2.c
drivers/media/dvb/dvb-usb/umt-010.c
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/bcm3510.h
drivers/media/dvb/frontends/cx22700.h
drivers/media/dvb/frontends/cx22702.c
drivers/media/dvb/frontends/cx22702.h
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/cx24110.h
drivers/media/dvb/frontends/cx24123.c
drivers/media/dvb/frontends/cx24123.h
drivers/media/dvb/frontends/dib3000-common.c [deleted file]
drivers/media/dvb/frontends/dib3000-common.h [deleted file]
drivers/media/dvb/frontends/dib3000.h
drivers/media/dvb/frontends/dib3000mb.c
drivers/media/dvb/frontends/dib3000mb_priv.h
drivers/media/dvb/frontends/dib3000mc.c
drivers/media/dvb/frontends/dib3000mc.h [new file with mode: 0644]
drivers/media/dvb/frontends/dib3000mc_priv.h [deleted file]
drivers/media/dvb/frontends/dibx000_common.c [new file with mode: 0644]
drivers/media/dvb/frontends/dibx000_common.h [new file with mode: 0644]
drivers/media/dvb/frontends/dvb-pll.c
drivers/media/dvb/frontends/dvb-pll.h
drivers/media/dvb/frontends/isl6421.c
drivers/media/dvb/frontends/isl6421.h
drivers/media/dvb/frontends/l64781.h
drivers/media/dvb/frontends/lgdt330x.h
drivers/media/dvb/frontends/lnbp21.c
drivers/media/dvb/frontends/lnbp21.h
drivers/media/dvb/frontends/mt2060.c [new file with mode: 0644]
drivers/media/dvb/frontends/mt2060.h [new file with mode: 0644]
drivers/media/dvb/frontends/mt2060_priv.h [new file with mode: 0644]
drivers/media/dvb/frontends/mt312.h
drivers/media/dvb/frontends/mt352.c
drivers/media/dvb/frontends/mt352.h
drivers/media/dvb/frontends/nxt200x.h
drivers/media/dvb/frontends/nxt6000.h
drivers/media/dvb/frontends/or51132.h
drivers/media/dvb/frontends/or51211.h
drivers/media/dvb/frontends/s5h1420.h
drivers/media/dvb/frontends/sp8870.h
drivers/media/dvb/frontends/sp887x.h
drivers/media/dvb/frontends/stv0297.h
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/stv0299.h
drivers/media/dvb/frontends/tda10021.c
drivers/media/dvb/frontends/tda10021.h
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/tda1004x.h
drivers/media/dvb/frontends/tda10086.c [new file with mode: 0644]
drivers/media/dvb/frontends/tda10086.h [new file with mode: 0644]
drivers/media/dvb/frontends/tda8083.h
drivers/media/dvb/frontends/tda826x.c [new file with mode: 0644]
drivers/media/dvb/frontends/tda826x.h [new file with mode: 0644]
drivers/media/dvb/frontends/tua6100.c [new file with mode: 0644]
drivers/media/dvb/frontends/tua6100.h [new file with mode: 0644]
drivers/media/dvb/frontends/ves1820.h
drivers/media/dvb/frontends/ves1x93.h
drivers/media/dvb/frontends/zl10353.c
drivers/media/dvb/frontends/zl10353.h
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110_av.c
drivers/media/dvb/ttpci/av7110_ca.c
drivers/media/dvb/ttpci/av7110_hw.c
drivers/media/dvb/ttpci/av7110_v4l.c
drivers/media/dvb/ttpci/budget-av.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttpci/budget-patch.c
drivers/media/dvb/ttpci/budget.c
drivers/media/dvb/ttusb-budget/Kconfig
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/radio/Kconfig
drivers/media/radio/dsbr100.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-rtrack2.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/radio-terratec.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/bt866.c
drivers/media/video/bt8xx/Kconfig
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv-i2c.c
drivers/media/video/compat_ioctl32.c
drivers/media/video/cx2341x.c
drivers/media/video/cx25840/Kconfig
drivers/media/video/cx25840/cx25840-vbi.c
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/Makefile
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-core.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/cx88/cx88-tvaudio.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/em28xx/Kconfig
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/ks0127.c
drivers/media/video/pvrusb2/Kconfig
drivers/media/video/pvrusb2/Makefile
drivers/media/video/pvrusb2/pvrusb2-ctrl.c
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
drivers/media/video/pvrusb2/pvrusb2-encoder.c
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
drivers/media/video/pvrusb2/pvrusb2-hdw.c
drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
drivers/media/video/pvrusb2/pvrusb2-main.c
drivers/media/video/pvrusb2/pvrusb2-sysfs.c
drivers/media/video/pvrusb2/pvrusb2-v4l2.c
drivers/media/video/saa5246a.c
drivers/media/video/saa5249.c
drivers/media/video/saa7115.c
drivers/media/video/saa711x_regs.h [new file with mode: 0644]
drivers/media/video/saa7134/Kconfig
drivers/media/video/saa7134/Makefile
drivers/media/video/saa7134/saa7134-alsa.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-core.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134-tvaudio.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/tda9887.c
drivers/media/video/tuner-simple.c
drivers/media/video/tuner-types.c
drivers/media/video/tvaudio.c
drivers/media/video/tveeprom.c
drivers/media/video/tvp5150.c
drivers/media/video/usbvideo/konicawc.c
drivers/media/video/usbvideo/vicam.c
drivers/media/video/v4l1-compat.c
drivers/media/video/v4l2-common.c
drivers/media/video/video-buf-dvb.c
drivers/media/video/videodev.c
drivers/media/video/vino.c
drivers/media/video/vivi.c
drivers/media/video/vpx3220.c
drivers/media/video/zoran_card.c
drivers/media/video/zoran_driver.c
drivers/media/video/zr36120.c
include/linux/videodev2.h
include/media/ir-common.h
include/media/tuner-types.h
include/media/tuner.h
include/media/v4l2-common.h
include/media/v4l2-dev.h

index 4ab4c425b856058d88b46bbe1070125e2c2bf3bb..9364f47c711690e4a262ed0c93c1072ff1be181e 100644 (file)
@@ -47,7 +47,7 @@ Who:  Jody McIntyre <scjody@modernduck.com>
 ---------------------------
 
 What:  Video4Linux API 1 ioctls and video_decoder.h from Video devices.
-When:  July 2006
+When:  December 2006
 Why:   V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
        series. The old API have lots of drawbacks and don't provide enough
        means to work with all video and audio standards. The newer API is
index 00d9a1f2a54c05dc01d1ab0b16b3b90f7aad6bf1..669a09aa5bb463934d96c25a76dc0346b8611fe8 100644 (file)
@@ -7,10 +7,10 @@
   6 -> AverTV Studio 303 (M126)                            [1461:000b]
   7 -> MSI TV-@nywhere Master                              [1462:8606]
   8 -> Leadtek Winfast DV2000                              [107d:6620]
-  9 -> Leadtek PVR 2000                                    [107d:663b,107d:663C]
+  9 -> Leadtek PVR 2000                                    [107d:663b,107d:663c,107d:6632]
  10 -> IODATA GV-VCP3/PCI                                  [10fc:d003]
  11 -> Prolink PlayTV PVR
- 12 -> ASUS PVR-416                                        [1043:4823]
+ 12 -> ASUS PVR-416                                        [1043:4823,1461:c111]
  13 -> MSI TV-@nywhere
  14 -> KWorld/VStream XPert DVB-T                          [17de:08a6]
  15 -> DViCO FusionHDTV DVB-T1                             [18ac:db00]
@@ -51,3 +51,7 @@
  50 -> NPG Tech Real TV FM Top 10                          [14f1:0842]
  51 -> WinFast DTV2000 H                                   [107d:665e]
  52 -> Geniatech DVB-S                                     [14f1:0084]
+ 53 -> Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T  [0070:1404]
+ 54 -> Norwood Micro TV Tuner
+ 55 -> Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM  [c180:c980]
+ 56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder   [0070:9600,0070:9601,0070:9602]
index 9068b669f5ee5d34af6dac4ff91a834df623b2f1..94cf695b1378ce8f79dd763448d3303909b76d19 100644 (file)
@@ -58,7 +58,7 @@
  57 -> Avermedia AVerTV GO 007 FM               [1461:f31f]
  58 -> ADS Tech Instant TV (saa7135)            [1421:0350,1421:0351,1421:0370,1421:1370]
  59 -> Kworld/Tevion V-Stream Xpert TV PVR7134
- 60 -> LifeView/Typhoon FlyDVB-T Duo Cardbus    [5168:0502,4e42:0502]
+ 60 -> LifeView/Typhoon/Genius FlyDVB-T Duo Cardbus [5168:0502,4e42:0502,1489:0502]
  61 -> Philips TOUGH DVB-T reference design     [1131:2004]
  62 -> Compro VideoMate TV Gold+II
  63 -> Kworld Xpert TV PVR7134
@@ -83,7 +83,7 @@
  82 -> MSI TV@Anywhere plus                     [1462:6231]
  83 -> Terratec Cinergy 250 PCI TV              [153b:1160]
  84 -> LifeView FlyDVB Trio                     [5168:0319]
- 85 -> AverTV DVB-T 777                         [1461:2c05]
+ 85 -> AverTV DVB-T 777                         [1461:2c05,1461:2c05]
  86 -> LifeView FlyDVB-T / Genius VideoWonder DVB-T [5168:0301,1489:0301]
  87 -> ADS Instant TV Duo Cardbus PTV331        [0331:1421]
  88 -> Tevion/KWorld DVB-T 220RF                [17de:7201]
@@ -94,3 +94,6 @@
  93 -> Medion 7134 Bridge #2                    [16be:0005]
  94 -> LifeView FlyDVB-T Hybrid Cardbus         [5168:3306,5168:3502]
  95 -> LifeView FlyVIDEO3000 (NTSC)             [5169:0138]
+ 96 -> Medion Md8800 Quadro                     [16be:0007,16be:0008]
+ 97 -> LifeView FlyDVB-S /Acorp TV134DS         [5168:0300,4e42:0300]
+ 98 -> Proteus Pro 2309                         [0919:2003]
index fc94ff235ffac51f1f0079bbe673f47c3a460632..bb7c2cac7917e97bd206442747eb6b0e77356c42 100644 (file)
@@ -54,6 +54,12 @@ bttv.o
                                dropouts.
                chroma_agc=0/1  AGC of chroma signal, off by default.
                adc_crush=0/1   Luminance ADC crush, on by default.
+               i2c_udelay=     Allow reduce I2C speed. Default is 5 usecs
+                               (meaning 66,67 Kbps). The default is the
+                               maximum supported speed by kernel bitbang
+                               algoritm. You may use lower numbers, if I2C
+                               messages are lost (16 is known to work on
+                               all supported cards).
 
                bttv_gpio=0/1
                gpiomask=
diff --git a/Documentation/video4linux/cx2341x/README.hm12 b/Documentation/video4linux/cx2341x/README.hm12
new file mode 100644 (file)
index 0000000..0e213ed
--- /dev/null
@@ -0,0 +1,116 @@
+The cx23416 can produce (and the cx23415 can also read) raw YUV output. The
+format of a YUV frame is specific to this chip and is called HM12. 'HM' stands
+for 'Hauppauge Macroblock', which is a misnomer as 'Conexant Macroblock' would
+be more accurate.
+
+The format is YUV 4:2:0 which uses 1 Y byte per pixel and 1 U and V byte per
+four pixels.
+
+The data is encoded as two macroblock planes, the first containing the Y
+values, the second containing UV macroblocks.
+
+The Y plane is divided into blocks of 16x16 pixels from left to right
+and from top to bottom. Each block is transmitted in turn, line-by-line.
+
+So the first 16 bytes are the first line of the top-left block, the
+second 16 bytes are the second line of the top-left block, etc. After
+transmitting this block the first line of the block on the right to the
+first block is transmitted, etc.
+
+The UV plane is divided into blocks of 16x8 UV values going from left
+to right, top to bottom. Each block is transmitted in turn, line-by-line.
+
+So the first 16 bytes are the first line of the top-left block and
+contain 8 UV value pairs (16 bytes in total). The second 16 bytes are the
+second line of 8 UV pairs of the top-left block, etc. After transmitting
+this block the first line of the block on the right to the first block is
+transmitted, etc.
+
+The code below is given as an example on how to convert HM12 to separate
+Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels.
+
+The width of a frame is always 720 pixels, regardless of the actual specified
+width.
+
+--------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static unsigned char frame[576*720*3/2];
+static unsigned char framey[576*720];
+static unsigned char frameu[576*720 / 4];
+static unsigned char framev[576*720 / 4];
+
+static void de_macro_y(unsigned char* dst, unsigned char *src, int dstride, int w, int h)
+{
+    unsigned int y, x, i;
+
+    // descramble Y plane
+    // dstride = 720 = w
+    // The Y plane is divided into blocks of 16x16 pixels
+    // Each block in transmitted in turn, line-by-line.
+    for (y = 0; y < h; y += 16) {
+       for (x = 0; x < w; x += 16) {
+           for (i = 0; i < 16; i++) {
+               memcpy(dst + x + (y + i) * dstride, src, 16);
+               src += 16;
+           }
+       }
+    }
+}
+
+static void de_macro_uv(unsigned char *dstu, unsigned char *dstv, unsigned char *src, int dstride, int w, int h)
+{
+    unsigned int y, x, i;
+
+    // descramble U/V plane
+    // dstride = 720 / 2 = w
+    // The U/V values are interlaced (UVUV...).
+    // Again, the UV plane is divided into blocks of 16x16 UV values.
+    // Each block in transmitted in turn, line-by-line.
+    for (y = 0; y < h; y += 16) {
+       for (x = 0; x < w; x += 8) {
+           for (i = 0; i < 16; i++) {
+               int idx = x + (y + i) * dstride;
+
+               dstu[idx+0] = src[0];  dstv[idx+0] = src[1];
+               dstu[idx+1] = src[2];  dstv[idx+1] = src[3];
+               dstu[idx+2] = src[4];  dstv[idx+2] = src[5];
+               dstu[idx+3] = src[6];  dstv[idx+3] = src[7];
+               dstu[idx+4] = src[8];  dstv[idx+4] = src[9];
+               dstu[idx+5] = src[10]; dstv[idx+5] = src[11];
+               dstu[idx+6] = src[12]; dstv[idx+6] = src[13];
+               dstu[idx+7] = src[14]; dstv[idx+7] = src[15];
+               src += 16;
+           }
+       }
+    }
+}
+
+/*************************************************************************/
+int main(int argc, char **argv)
+{
+    FILE *fin;
+    int i;
+
+    if (argc == 1) fin = stdin;
+    else fin = fopen(argv[1], "r");
+
+    if (fin == NULL) {
+       fprintf(stderr, "cannot open input\n");
+       exit(-1);
+    }
+    while (fread(frame, sizeof(frame), 1, fin) == 1) {
+       de_macro_y(framey, frame, 720, 720, 576);
+       de_macro_uv(frameu, framev, frame + 720 * 576, 720 / 2, 720 / 2, 576 / 2);
+       fwrite(framey, sizeof(framey), 1, stdout);
+       fwrite(framev, sizeof(framev), 1, stdout);
+       fwrite(frameu, sizeof(frameu), 1, stdout);
+    }
+    fclose(fin);
+    return 0;
+}
+
+--------------------------------------------------------------------------
diff --git a/Documentation/video4linux/cx2341x/README.vbi b/Documentation/video4linux/cx2341x/README.vbi
new file mode 100644 (file)
index 0000000..5807cf1
--- /dev/null
@@ -0,0 +1,45 @@
+
+Format of embedded V4L2_MPEG_STREAM_VBI_FMT_IVTV VBI data
+=========================================================
+
+This document describes the V4L2_MPEG_STREAM_VBI_FMT_IVTV format of the VBI data
+embedded in an MPEG-2 program stream. This format is in part dictated by some
+hardware limitations of the ivtv driver (the driver for the Conexant cx23415/6
+chips), in particular a maximum size for the VBI data. Anything longer is cut
+off when the MPEG stream is played back through the cx23415.
+
+The advantage of this format is it is very compact and that all VBI data for
+all lines can be stored while still fitting within the maximum allowed size.
+
+The stream ID of the VBI data is 0xBD. The maximum size of the embedded data is
+4 + 43 * 36, which is 4 bytes for a header and 2 * 18 VBI lines with a 1 byte
+header and a 42 bytes payload each. Anything beyond this limit is cut off by
+the cx23415/6 firmware. Besides the data for the VBI lines we also need 36 bits
+for a bitmask determining which lines are captured and 4 bytes for a magic cookie,
+signifying that this data package contains V4L2_MPEG_STREAM_VBI_FMT_IVTV VBI data.
+If all lines are used, then there is no longer room for the bitmask. To solve this
+two different magic numbers were introduced:
+
+'itv0': After this magic number two unsigned longs follow. Bits 0-17 of the first
+unsigned long denote which lines of the first field are captured. Bits 18-31 of
+the first unsigned long and bits 0-3 of the second unsigned long are used for the
+second field.
+
+'ITV0': This magic number assumes all VBI lines are captured, i.e. it implicitly
+implies that the bitmasks are 0xffffffff and 0xf.
+
+After these magic cookies (and the 8 byte bitmask in case of cookie 'itv0') the
+captured VBI lines start:
+
+For each line the least significant 4 bits of the first byte contain the data type.
+Possible values are shown in the table below. The payload is in the following 42
+bytes.
+
+Here is the list of possible data types:
+
+#define IVTV_SLICED_TYPE_TELETEXT       0x1     // Teletext (uses lines 6-22 for PAL)
+#define IVTV_SLICED_TYPE_CC             0x4     // Closed Captions (line 21 NTSC)
+#define IVTV_SLICED_TYPE_WSS            0x5     // Wide Screen Signal (line 23 PAL)
+#define IVTV_SLICED_TYPE_VPS            0x7     // Video Programming System (PAL) (line 16)
+
+Hans Verkuil <hverkuil@xs4all.nl>
index 1a04db4552da9dc2521867eaff7fd4c5666c7d89..f33e5d973413c2a1c064c66111c7f111383024dd 100644 (file)
@@ -4,7 +4,6 @@ config VIDEO_SAA7146
 
 config VIDEO_SAA7146_VV
        tristate
-       select VIDEO_V4L2
        select VIDEO_BUF
        select VIDEO_VIDEOBUF
        select VIDEO_SAA7146
index ca98d94789476f7c7454dc3a034f2b752e68b990..db753443587acf5a2cf7deddbeafebcb4974f18d 100644 (file)
@@ -32,6 +32,37 @@ IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = {
 
 EXPORT_SYMBOL_GPL(ir_codes_empty);
 
+/* Michal Majchrowicz <mmajchrowicz@gmail.com> */
+IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = {
+       /* numeric */
+       [ 0x00 ] = KEY_0,
+       [ 0x01 ] = KEY_1,
+       [ 0x02 ] = KEY_2,
+       [ 0x03 ] = KEY_3,
+       [ 0x04 ] = KEY_4,
+       [ 0x05 ] = KEY_5,
+       [ 0x06 ] = KEY_6,
+       [ 0x07 ] = KEY_7,
+       [ 0x08 ] = KEY_8,
+       [ 0x09 ] = KEY_9,
+
+       [ 0x5c ] = KEY_POWER,     /* power       */
+       [ 0x20 ] = KEY_F,         /* full screen */
+       [ 0x0f ] = KEY_BACKSPACE, /* recall      */
+       [ 0x1b ] = KEY_ENTER,     /* mute        */
+       [ 0x41 ] = KEY_RECORD,    /* record      */
+       [ 0x43 ] = KEY_STOP,      /* stop        */
+       [ 0x16 ] = KEY_S,
+       [ 0x1a ] = KEY_Q,         /* off         */
+       [ 0x2e ] = KEY_RED,
+       [ 0x1f ] = KEY_DOWN,      /* channel -   */
+       [ 0x1c ] = KEY_UP,        /* channel +   */
+       [ 0x10 ] = KEY_LEFT,      /* volume -    */
+       [ 0x1e ] = KEY_RIGHT,     /* volume +    */
+       [ 0x14 ] = KEY_F1,
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_proteus_2309);
 /* Matt Jesson <dvb@jesson.eclipse.co.uk */
 IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = {
        [ 0x28 ] = KEY_0,         //'0' / 'enter'
@@ -1473,3 +1504,51 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = {
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_npgtech);
+
+/* Norwood Micro (non-Pro) TV Tuner
+   By Peter Naulls <peter@chocky.org>
+   Key comments are the functions given in the manual */
+IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = {
+       /* Keys 0 to 9 */
+       [ 0x20 ] = KEY_0,
+       [ 0x21 ] = KEY_1,
+       [ 0x22 ] = KEY_2,
+       [ 0x23 ] = KEY_3,
+       [ 0x24 ] = KEY_4,
+       [ 0x25 ] = KEY_5,
+       [ 0x26 ] = KEY_6,
+       [ 0x27 ] = KEY_7,
+       [ 0x28 ] = KEY_8,
+       [ 0x29 ] = KEY_9,
+
+       [ 0x78 ] = KEY_TUNER,             /* Video Source        */
+       [ 0x2c ] = KEY_EXIT,              /* Open/Close software */
+       [ 0x2a ] = KEY_SELECT,            /* 2 Digit Select      */
+       [ 0x69 ] = KEY_AGAIN,             /* Recall              */
+
+       [ 0x32 ] = KEY_BRIGHTNESSUP,      /* Brightness increase */
+       [ 0x33 ] = KEY_BRIGHTNESSDOWN,    /* Brightness decrease */
+       [ 0x6b ] = KEY_KPPLUS,            /* (not named >>>>>)   */
+       [ 0x6c ] = KEY_KPMINUS,           /* (not named <<<<<)   */
+
+       [ 0x2d ] = KEY_MUTE,              /* Mute                */
+       [ 0x30 ] = KEY_VOLUMEUP,          /* Volume up           */
+       [ 0x31 ] = KEY_VOLUMEDOWN,        /* Volume down         */
+       [ 0x60 ] = KEY_CHANNELUP,         /* Channel up          */
+       [ 0x61 ] = KEY_CHANNELDOWN,       /* Channel down        */
+
+       [ 0x3f ] = KEY_RECORD,            /* Record              */
+       [ 0x37 ] = KEY_PLAY,              /* Play                */
+       [ 0x36 ] = KEY_PAUSE,             /* Pause               */
+       [ 0x2b ] = KEY_STOP,              /* Stop                */
+       [ 0x67 ] = KEY_FASTFORWARD,       /* Foward              */
+       [ 0x66 ] = KEY_REWIND,            /* Rewind              */
+       [ 0x3e ] = KEY_SEARCH,            /* Auto Scan           */
+       [ 0x2e ] = KEY_CAMERA,            /* Capture Video       */
+       [ 0x6d ] = KEY_MENU,              /* Show/Hide Control   */
+       [ 0x2f ] = KEY_ZOOM,              /* Full Screen         */
+       [ 0x34 ] = KEY_RADIO,             /* FM                  */
+       [ 0x65 ] = KEY_POWER,             /* Computer power      */
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_norwood);
index 0027acc5b8e988b2a271ae79d1a90a96acbbd5d8..d867a6a9e43065335894bf93da8f00bc74a46c67 100644 (file)
@@ -455,7 +455,6 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
 
 static struct video_device device_template =
 {
-       .hardware       = VID_HARDWARE_SAA7146,
        .fops           = &video_fops,
        .minor          = -1,
 };
index 49a06fc54c51add4cb30df21303b0419db633171..a0dcd59da76e5833502814abf62d66eda780ae79 100644 (file)
@@ -2,13 +2,13 @@ config DVB_B2C2_FLEXCOP
        tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters"
        depends on DVB_CORE && I2C
        select DVB_PLL
-       select DVB_STV0299
-       select DVB_MT352
-       select DVB_MT312
-       select DVB_NXT200X
-       select DVB_STV0297
-       select DVB_BCM3510
-       select DVB_LGDT330X
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_MT312 if !DVB_FE_CUSTOMISE
+       select DVB_NXT200X if !DVB_FE_CUSTOMISE
+       select DVB_STV0297 if !DVB_FE_CUSTOMISE
+       select DVB_BCM3510 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        help
          Support for the digital TV receiver chip made by B2C2 Inc. included in
          Technisats PCI cards and USB boxes.
index 3be87c72e37b7f6bf13053f3db75a0fd9a4229af..b8ba8786345783e107aa6e7a31babc4ff0cd6bd4 100644 (file)
@@ -505,7 +505,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
        struct dvb_frontend_ops *ops;
 
        /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
-       if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
                ops = &fc->fe->ops;
 
                ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
@@ -519,36 +519,36 @@ int flexcop_frontend_init(struct flexcop_device *fc)
                info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
        } else
        /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
-       if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
+       if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
                fc->dev_type          = FC_AIR_DVB;
                fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
                info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
        } else
        /* try the air atsc 2nd generation (nxt2002) */
-       if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type          = FC_AIR_ATSC2;
-               dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
+               dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, &dvb_pll_samsung_tbmv);
                info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
        } else
        /* try the air atsc 3nd generation (lgdt3303) */
-       if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type          = FC_AIR_ATSC3;
                fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
                info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
        } else
        /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
-       if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type          = FC_AIR_ATSC1;
                info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
        } else
        /* try the cable dvb (stv0297) */
-       if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
                fc->dev_type                        = FC_CABLE;
                fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
                info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
        } else
        /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
-       if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
+       if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
                ops = &fc->fe->ops;
 
                ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
@@ -571,9 +571,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
        } else {
                if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
                        err("frontend registration failed!");
-                       ops = &fc->fe->ops;
-                       if (ops->release != NULL)
-                               ops->release(fc->fe);
+                       dvb_frontend_detach(fc->fe);
                        fc->fe = NULL;
                        return -EINVAL;
                }
@@ -584,8 +582,10 @@ int flexcop_frontend_init(struct flexcop_device *fc)
 
 void flexcop_frontend_exit(struct flexcop_device *fc)
 {
-       if (fc->init_state & FC_STATE_FE_INIT)
+       if (fc->init_state & FC_STATE_FE_INIT) {
                dvb_unregister_frontend(fc->fe);
+               dvb_frontend_detach(fc->fe);
+       }
 
        fc->init_state &= ~FC_STATE_FE_INIT;
 }
index 7d0ee1ab2903c4bb06b5c16c7146f21f14f2ce9a..ae2ff5dc238d958d03f92fe9bf2a2c4d3926e93d 100644 (file)
@@ -2,13 +2,13 @@ config DVB_BT8XX
        tristate "BT8xx based PCI cards"
        depends on DVB_CORE && PCI && I2C && VIDEO_BT848
        select DVB_PLL
-       select DVB_MT352
-       select DVB_SP887X
-       select DVB_NXT6000
-       select DVB_CX24110
-       select DVB_OR51211
-       select DVB_LGDT330X
-       select DVB_ZL10353
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_SP887X if !DVB_FE_CUSTOMISE
+       select DVB_NXT6000 if !DVB_FE_CUSTOMISE
+       select DVB_CX24110 if !DVB_FE_CUSTOMISE
+       select DVB_OR51211 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          Support for PCI cards based on the Bt8xx PCI bridge. Examples are
index 06ac899a9a26931f3bc23b87cf9a1ae7a351a1a4..9f72b7000c080281e6149318a730b814348a9baf 100644 (file)
@@ -1715,6 +1715,15 @@ static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
 static void dst_release(struct dvb_frontend *fe)
 {
        struct dst_state *state = fe->demodulator_priv;
+       if (state->dst_ca) {
+               dvb_unregister_device(state->dst_ca);
+#ifdef CONFIG_DVB_CORE_ATTACH
+               symbol_put(dst_ca_attach);
+#endif
+       }
+#ifdef CONFIG_DVB_CORE_ATTACH
+       symbol_put(dst_attach);
+#endif
        kfree(state);
 }
 
index fa923b9b346ea99440dceeac23e695c4c4b3a193..240ad084fa787ae4f5dc07b0acf47f25d2554b5c 100644 (file)
@@ -699,12 +699,17 @@ static struct dvb_device dvbdev_ca = {
        .fops = &dst_ca_fops
 };
 
-int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
+struct dvb_device *dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
 {
        struct dvb_device *dvbdev;
+
        dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
-       dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA);
-       return 0;
+       if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA) == 0) {
+               dst->dst_ca = dvbdev;
+               return dst->dst_ca;
+       }
+
+       return NULL;
 }
 
 EXPORT_SYMBOL(dst_ca_attach);
index 0677b047b3a78be3381046c3ef0eb88e576cf5c3..3bf084f2e5226b883aeca002b39e75b54de04801 100644 (file)
@@ -140,6 +140,7 @@ struct dst_state {
        char *tuner_name;
        struct mutex dst_mutex;
        u8 fw_name[8];
+       struct dvb_device *dst_ca;
 };
 
 struct tuner_types {
@@ -178,7 +179,7 @@ int write_dst(struct dst_state *state, u8 * data, u8 len);
 int read_dst(struct dst_state *state, u8 * ret, u8 len);
 u8 dst_check_sum(u8 * buf, u32 len);
 struct dst_state* dst_attach(struct dst_state* state, struct dvb_adapter *dvb_adapter);
-int dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
+struct dvb_device *dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
 int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay);
 
 int dst_command(struct dst_state* state, u8 * data, u8 len);
index b715b972d2fcfbfdbd495d5a1cc2ed558c60e632..fb6c4cc8477db818d04fb061f0893584b428690e 100644 (file)
@@ -67,7 +67,7 @@ static void dvb_bt8xx_task(unsigned long data)
 
 static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-       struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+       struct dvb_demux*dvbdmx = dvbdmxfeed->demux;
        struct dvb_bt8xx_card *card = dvbdmx->priv;
        int rc;
 
@@ -595,15 +595,14 @@ static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
 
 static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 {
-       int ret;
        struct dst_state* state = NULL;
 
        switch(type) {
        case BTTV_BOARD_DVICO_DVBT_LITE:
-               card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
+               card->fe = dvb_attach(mt352_attach, &thomson_dtt7579_config, card->i2c_adapter);
 
                if (card->fe == NULL)
-                       card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config,
+                       card->fe = dvb_attach(zl10353_attach, &thomson_dtt7579_zl10353_config,
                                                  card->i2c_adapter);
 
                if (card->fe != NULL) {
@@ -615,7 +614,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 
        case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
                lgdt330x_reset(card);
-               card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
+               card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
                if (card->fe != NULL) {
                        card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
                        dprintk ("dvb_bt8xx: lgdt330x detected\n");
@@ -630,7 +629,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 
                /* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */
                digitv_alps_tded4_reset(card);
-               card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
+               card->fe = dvb_attach(nxt6000_attach, &vp3021_alps_tded4_config, card->i2c_adapter);
                if (card->fe != NULL) {
                        card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
                        dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
@@ -639,7 +638,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 
                /* New Nebula (marked (c)2005 on low profile pci card) has mt352 demod */
                digitv_alps_tded4_reset(card);
-               card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
+               card->fe = dvb_attach(mt352_attach, &digitv_alps_tded4_config, card->i2c_adapter);
 
                if (card->fe != NULL) {
                        card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
@@ -648,14 +647,14 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                break;
 
        case BTTV_BOARD_AVDVBT_761:
-               card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
+               card->fe = dvb_attach(sp887x_attach, &microtune_mt7202dtf_config, card->i2c_adapter);
                if (card->fe) {
                        card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
                }
                break;
 
        case BTTV_BOARD_AVDVBT_771:
-               card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
+               card->fe = dvb_attach(mt352_attach, &advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
                if (card->fe != NULL) {
                        card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
                        card->fe->ops.info.frequency_min = 174000000;
@@ -670,22 +669,21 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                state->config = &dst_config;
                state->i2c = card->i2c_adapter;
                state->bt = card->bt;
-
+               state->dst_ca = NULL;
                /*      DST is not a frontend, attaching the ASIC       */
-               if ((dst_attach(state, &card->dvb_adapter)) == NULL) {
+               if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
                        printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__);
                        break;
                }
-               card->fe = &state->frontend;
-
                /*      Attach other DST peripherals if any             */
                /*      Conditional Access device                       */
+               card->fe = &state->frontend;
                if (state->dst_hw_cap & DST_TYPE_HAS_CA)
-                       ret = dst_ca_attach(state, &card->dvb_adapter);
+                       dvb_attach(dst_ca_attach, state, &card->dvb_adapter);
                break;
 
        case BTTV_BOARD_PINNACLESAT:
-               card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
+               card->fe = dvb_attach(cx24110_attach, &pctvsat_config, card->i2c_adapter);
                if (card->fe) {
                        card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
                        card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
@@ -694,7 +692,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
                break;
 
        case BTTV_BOARD_PC_HDTV:
-               card->fe = or51211_attach(&or51211_config, card->i2c_adapter);
+               card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
                break;
        }
 
@@ -707,8 +705,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
        else
                if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
                        printk("dvb-bt8xx: Frontend registration failed!\n");
-                       if (card->fe->ops.release)
-                               card->fe->ops.release(card->fe);
+                       dvb_frontend_detach(card->fe);
                        card->fe = NULL;
                }
 }
@@ -925,8 +922,10 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub)
        card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
        dvb_dmxdev_release(&card->dmxdev);
        dvb_dmx_release(&card->demux);
-       if (card->fe)
+       if (card->fe) {
                dvb_unregister_frontend(card->fe);
+               dvb_frontend_detach(card->fe);
+       }
        dvb_unregister_adapter(&card->dvb_adapter);
 
        kfree(card);
index 12ee912a5705176af05f73be9e61ffa2e140687d..e46eae3b9be2624690746413bbb2c74601e2af54 100644 (file)
@@ -9,3 +9,16 @@ config DVB_CORE
          in-kernel drivers will select this automatically if needed.
          If unsure say N.
 
+config DVB_CORE_ATTACH
+       bool "Load and attach frontend modules as needed"
+       depends on DVB_CORE
+       depends on MODULES
+       help
+         Remove the static dependency of DVB card drivers on all
+         frontend modules for all possible card variants. Instead,
+         allow the card drivers to only load the frontend modules
+         they require. This saves several KBytes of memory.
+
+         Note: You will need moudule-init-tools v3.2 or later for this feature.
+
+         If unsure say Y.
index 57b34cda99f5a6f598b9786d42af22d58a19f70d..3dd5dbafb330634c400e57d58b198eb21ef5c9a0 100644 (file)
@@ -1105,18 +1105,42 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
        mutex_lock(&frontend_mutex);
        dvb_unregister_device (fepriv->dvbdev);
        dvb_frontend_stop (fe);
-       if (fe->ops.tuner_ops.release) {
-               fe->ops.tuner_ops.release(fe);
-               if (fe->ops.i2c_gate_ctrl)
-                       fe->ops.i2c_gate_ctrl(fe, 0);
-       }
-       if (fe->ops.release)
-               fe->ops.release(fe);
-       else
-               printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name);
+
        /* fe is invalid now */
        kfree(fepriv);
        mutex_unlock(&frontend_mutex);
        return 0;
 }
 EXPORT_SYMBOL(dvb_unregister_frontend);
+
+#ifdef CONFIG_DVB_CORE_ATTACH
+void dvb_frontend_detach(struct dvb_frontend* fe)
+{
+       void *ptr;
+
+       if (fe->ops.release_sec) {
+               fe->ops.release_sec(fe);
+               symbol_put_addr(fe->ops.release_sec);
+       }
+       if (fe->ops.tuner_ops.release) {
+               fe->ops.tuner_ops.release(fe);
+               symbol_put_addr(fe->ops.tuner_ops.release);
+       }
+       ptr = (void*)fe->ops.release;
+       if (ptr) {
+               fe->ops.release(fe);
+               symbol_put_addr(ptr);
+       }
+}
+#else
+void dvb_frontend_detach(struct dvb_frontend* fe)
+{
+       if (fe->ops.release_sec)
+               fe->ops.release_sec(fe);
+       if (fe->ops.tuner_ops.release)
+               fe->ops.tuner_ops.release(fe);
+       if (fe->ops.release)
+               fe->ops.release(fe);
+}
+#endif
+EXPORT_SYMBOL(dvb_frontend_detach);
index 2887e2b862a4436d1002a5dcee6ffafb1b5aba1f..e5d5028b3694fc68663da122664e6172095c596f 100644 (file)
@@ -92,10 +92,13 @@ struct dvb_frontend_ops {
        struct dvb_frontend_info info;
 
        void (*release)(struct dvb_frontend* fe);
+       void (*release_sec)(struct dvb_frontend* fe);
 
        int (*init)(struct dvb_frontend* fe);
        int (*sleep)(struct dvb_frontend* fe);
 
+       int (*write)(struct dvb_frontend* fe, u8* buf, int len);
+
        /* if this is set, it overrides the default swzigzag */
        int (*tune)(struct dvb_frontend* fe,
                    struct dvb_frontend_parameters* params,
@@ -147,7 +150,7 @@ struct dvb_frontend {
        void* demodulator_priv;
        void* tuner_priv;
        void* frontend_priv;
-       void* misc_priv;
+       void* sec_priv;
 };
 
 extern int dvb_register_frontend(struct dvb_adapter* dvb,
@@ -155,6 +158,8 @@ extern int dvb_register_frontend(struct dvb_adapter* dvb,
 
 extern int dvb_unregister_frontend(struct dvb_frontend* fe);
 
+extern void dvb_frontend_detach(struct dvb_frontend* fe);
+
 extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
 
 extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
index 7a7f75fd168c30f19bf622a349322994914ca336..620e7887b3d3b11c155d65cbbddc12dfdd284555 100644 (file)
@@ -102,4 +102,26 @@ extern int dvb_usercopy(struct inode *inode, struct file *file,
                            int (*func)(struct inode *inode, struct file *file,
                            unsigned int cmd, void *arg));
 
+/** generic DVB attach function. */
+#ifdef CONFIG_DVB_CORE_ATTACH
+#define dvb_attach(FUNCTION, ARGS...) ({ \
+       void *__r = NULL; \
+       typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
+       if (__a) { \
+               __r = (void *) __a(ARGS); \
+               if (__r == NULL) \
+                       symbol_put(FUNCTION); \
+       } else { \
+               printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \
+       } \
+       __r; \
+})
+
+#else
+#define dvb_attach(FUNCTION, ARGS...) ({ \
+       FUNCTION(ARGS); \
+})
+
+#endif
+
 #endif /* #ifndef _DVBDEV_H_ */
index 75824b77198ab2a2524f5d123c719455a1fdadfb..0a3c35399bea7480ef9bdcc84bc510e43704ade2 100644 (file)
@@ -26,6 +26,7 @@ config DVB_USB_A800
        tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
        depends on DVB_USB
        select DVB_DIB3000MC
+       select DVB_TUNER_MT2060
        help
          Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
 
@@ -33,6 +34,7 @@ config DVB_USB_DIBUSB_MB
        tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
        depends on DVB_USB
        select DVB_DIB3000MB
+       select DVB_TUNER_MT2060
        help
          Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
          DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
@@ -65,6 +67,7 @@ config DVB_USB_DIBUSB_MC
        tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
        depends on DVB_USB
        select DVB_DIB3000MC
+       select DVB_TUNER_MT2060
        help
          Support for 2.0 DVB-T receivers based on reference designs made by
          DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
@@ -80,16 +83,17 @@ config DVB_USB_UMT_010
        tristate "HanfTek UMT-010 DVB-T USB2.0 support"
        depends on DVB_USB
        select DVB_DIB3000MC
+       select DVB_TUNER_MT2060
        help
          Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
 
 config DVB_USB_CXUSB
        tristate "Conexant USB2.0 hybrid reference design support"
        depends on DVB_USB
-       select DVB_CX22702
-       select DVB_LGDT330X
-       select DVB_MT352
-       select DVB_ZL10353
+       select DVB_CX22702 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Conexant USB2.0 hybrid reference design.
          Currently, only DVB and ATSC modes are supported, analog mode
@@ -101,8 +105,8 @@ config DVB_USB_CXUSB
 config DVB_USB_DIGITV
        tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
        depends on DVB_USB
-       select DVB_NXT6000
-       select DVB_MT352
+       select DVB_NXT6000 if !DVB_FE_CUSTOMISE
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
 
@@ -145,6 +149,7 @@ config DVB_USB_NOVA_T_USB2
        tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
        depends on DVB_USB
        select DVB_DIB3000MC
+       select DVB_TUNER_MT2060
        help
          Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
 
index ce44aa6bbb838da936e9c41466819a9d226d64cf..df0c384bd4ca8a0d677afcd2507e04685d068648 100644 (file)
@@ -26,6 +26,13 @@ static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
        return 0;
 }
 
+/* assure to put cold to 0 for iManufacturer == 1 */
+static int a800_identify_state(struct usb_device *udev, struct dvb_usb_properties *props,struct dvb_usb_device_description **desc, int *cold)
+{
+       *cold = udev->descriptor.iManufacturer != 1;
+       return 0;
+}
+
 static struct dvb_usb_rc_key a800_rc_keys[] = {
        { 0x02, 0x01, KEY_PROG1 },       /* SOURCE */
        { 0x02, 0x00, KEY_POWER },       /* POWER */
@@ -113,6 +120,7 @@ static struct dvb_usb_properties a800_properties = {
        .power_ctrl       = a800_power_ctrl,
        .frontend_attach  = dibusb_dib3000mc_frontend_attach,
        .tuner_attach     = dibusb_dib3000mc_tuner_attach,
+       .identify_state   = a800_identify_state,
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = a800_rc_keys,
index ae23bdde42a82505271051024dd2d0509ec994cb..c710c0176e0737e9174d3529b88e3e5db69d3dc8 100644 (file)
@@ -349,6 +349,7 @@ static struct mt352_config cxusb_dee1601_config = {
 
 static struct zl10353_config cxusb_zl10353_dee1601_config = {
        .demod_address = 0x0f,
+       .parallel_ts = 1,
 };
 
 static struct mt352_config cxusb_mt352_config = {
@@ -409,7 +410,7 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d)
 
        cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, &b, 1);
 
-       if ((d->fe = cx22702_attach(&cxusb_cx22702_config, &d->i2c_adap)) != NULL)
+       if ((d->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &d->i2c_adap)) != NULL)
                return 0;
 
        return -EIO;
@@ -422,7 +423,7 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_device *d)
 
        cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
 
-       if ((d->fe = lgdt330x_attach(&cxusb_lgdt3303_config, &d->i2c_adap)) != NULL)
+       if ((d->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &d->i2c_adap)) != NULL)
                return 0;
 
        return -EIO;
@@ -435,7 +436,7 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_device *d)
 
        cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
 
-       if ((d->fe = mt352_attach(&cxusb_mt352_config, &d->i2c_adap)) != NULL)
+       if ((d->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &d->i2c_adap)) != NULL)
                return 0;
 
        return -EIO;
@@ -448,8 +449,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
 
        cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
 
-       if (((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
-           ((d->fe = zl10353_attach(&cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
+       if (((d->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
+               ((d->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
                return 0;
 
        return -EIO;
index abd75b4a350dab46c2d054d176edb991668f44bf..124e25ac53b3ce625660ed6819a2d92833fe1ab8 100644 (file)
@@ -131,9 +131,6 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
                return -EAGAIN;
 
-       if (num > 2)
-               warn("more than 2 i2c messages at a time is not handled yet. TODO.");
-
        for (i = 0; i < num; i++) {
                /* write/read request */
                if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
@@ -168,31 +165,137 @@ int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
 }
 EXPORT_SYMBOL(dibusb_read_eeprom_byte);
 
+/* 3000MC/P stuff */
+// Config Adjacent channels  Perf -cal22
+static struct dibx000_agc_config dib3000p_mt2060_agc_config = {
+       .band_caps = BAND_VHF | BAND_UHF,
+       .setup     = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0),
+
+       .agc1_max = 48497,
+       .agc1_min = 23593,
+       .agc2_max = 46531,
+       .agc2_min = 24904,
+
+       .agc1_pt1 = 0x65,
+       .agc1_pt2 = 0x69,
+
+       .agc1_slope1 = 0x51,
+       .agc1_slope2 = 0x27,
+
+       .agc2_pt1 = 0,
+       .agc2_pt2 = 0x33,
+
+       .agc2_slope1 = 0x35,
+       .agc2_slope2 = 0x37,
+};
+
+static struct dib3000mc_config stk3000p_dib3000p_config = {
+       &dib3000p_mt2060_agc_config,
+
+       .max_time     = 0x196,
+       .ln_adc_level = 0x1cc7,
+
+       .output_mpeg2_in_188_bytes = 1,
+};
+
+static struct dibx000_agc_config dib3000p_panasonic_agc_config = {
+       .setup    = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0),
+
+       .agc1_max = 56361,
+       .agc1_min = 22282,
+       .agc2_max = 47841,
+       .agc2_min = 36045,
+
+       .agc1_pt1 = 0x3b,
+       .agc1_pt2 = 0x6b,
+
+       .agc1_slope1 = 0x55,
+       .agc1_slope2 = 0x1d,
+
+       .agc2_pt1 = 0,
+       .agc2_pt2 = 0x0a,
+
+       .agc2_slope1 = 0x95,
+       .agc2_slope2 = 0x1e,
+};
+
+static struct dib3000mc_config mod3000p_dib3000p_config = {
+       &dib3000p_panasonic_agc_config,
+
+       .max_time     = 0x51,
+       .ln_adc_level = 0x1cc7,
+
+       .output_mpeg2_in_188_bytes = 1,
+};
+
 int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
 {
-       struct dib3000_config demod_cfg;
-       struct dibusb_state *st = d->priv;
-
-       for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
-               if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
-                       d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
-                       d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
-                       d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
-                       return 0;
+       if (dib3000mc_attach(&d->i2c_adap, 1, DEFAULT_DIB3000P_I2C_ADDRESS, 0, &mod3000p_dib3000p_config, &d->fe) == 0 ||
+               dib3000mc_attach(&d->i2c_adap, 1, DEFAULT_DIB3000MC_I2C_ADDRESS, 0, &mod3000p_dib3000p_config, &d->fe) == 0) {
+               if (d->priv != NULL) {
+                       struct dibusb_state *st = d->priv;
+                       st->ops.pid_parse = dib3000mc_pid_parse;
+                       st->ops.pid_ctrl  = dib3000mc_pid_control;
                }
-
+               return 0;
+       }
        return -ENODEV;
 }
 EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
 
+static struct mt2060_config stk3000p_mt2060_config = {
+       0x60
+};
+
 int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
 {
-       d->pll_addr = 0x60;
-       d->pll_desc = &dvb_pll_env57h1xd5;
-
-       d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
-       d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+       struct dibusb_state *st = d->priv;
+       int ret;
+       u8 a,b;
+       u16 if1 = 1220;
+       struct i2c_adapter *tun_i2c;
+
+       // First IF calibration for Liteon Sticks
+       if (d->udev->descriptor.idVendor == USB_VID_LITEON &&
+               d->udev->descriptor.idProduct == USB_PID_LITEON_DVB_T_WARM) {
+
+               dibusb_read_eeprom_byte(d,0x7E,&a);
+               dibusb_read_eeprom_byte(d,0x7F,&b);
+
+               if (a == 0x00)
+                       if1 += b;
+               else if (a == 0x80)
+                       if1 -= b;
+               else
+                       warn("LITE-ON DVB-T: Strange IF1 calibration :%2X %2X\n", a, b);
+
+       } else if (d->udev->descriptor.idVendor  == USB_VID_DIBCOM &&
+                  d->udev->descriptor.idProduct == USB_PID_DIBCOM_MOD3001_WARM) {
+               u8 desc;
+               dibusb_read_eeprom_byte(d, 7, &desc);
+               if (desc == 2) {
+                       a = 127;
+                       do {
+                               dibusb_read_eeprom_byte(d, a, &desc);
+                               a--;
+                       } while (a > 7 && (desc == 0xff || desc == 0x00));
+                       if (desc & 0x80)
+                               if1 -= (0xff - desc);
+                       else
+                               if1 += desc;
+               }
+       }
 
+       tun_i2c = dib3000mc_get_tuner_i2c_master(d->fe, 1);
+       if ((ret = mt2060_attach(d->fe, tun_i2c, &stk3000p_mt2060_config, if1)) != 0) {
+               /* not found - use panasonic pll parameters */
+               if (dvb_pll_attach(d->fe, 0x60, tun_i2c, &dvb_pll_env57h1xd5) == NULL)
+                       return -ENOMEM;
+       } else {
+               st->mt2060_present = 1;
+               /* set the correct parameters for the dib3000p */
+               dib3000mc_set_config(d->fe, &stk3000p_dib3000p_config);
+       }
        return 0;
 }
 EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
@@ -267,6 +370,67 @@ struct dvb_usb_rc_key dibusb_rc_keys[] = {
        { 0x86, 0x1e, KEY_DOWN },
        { 0x86, 0x1f, KEY_LEFT },
        { 0x86, 0x1b, KEY_RIGHT },
+
+       /* Key codes for the DiBcom MOD3000 remote. */
+       { 0x80, 0x00, KEY_MUTE },
+       { 0x80, 0x01, KEY_TEXT },
+       { 0x80, 0x02, KEY_HOME },
+       { 0x80, 0x03, KEY_POWER },
+
+       { 0x80, 0x04, KEY_RED },
+       { 0x80, 0x05, KEY_GREEN },
+       { 0x80, 0x06, KEY_YELLOW },
+       { 0x80, 0x07, KEY_BLUE },
+
+       { 0x80, 0x08, KEY_DVD },
+       { 0x80, 0x09, KEY_AUDIO },
+       { 0x80, 0x0a, KEY_MEDIA },      /* Pictures */
+       { 0x80, 0x0b, KEY_VIDEO },
+
+       { 0x80, 0x0c, KEY_BACK },
+       { 0x80, 0x0d, KEY_UP },
+       { 0x80, 0x0e, KEY_RADIO },
+       { 0x80, 0x0f, KEY_EPG },
+
+       { 0x80, 0x10, KEY_LEFT },
+       { 0x80, 0x11, KEY_OK },
+       { 0x80, 0x12, KEY_RIGHT },
+       { 0x80, 0x13, KEY_UNKNOWN },    /* SAP */
+
+       { 0x80, 0x14, KEY_TV },
+       { 0x80, 0x15, KEY_DOWN },
+       { 0x80, 0x16, KEY_MENU },       /* DVD Menu */
+       { 0x80, 0x17, KEY_LAST },
+
+       { 0x80, 0x18, KEY_RECORD },
+       { 0x80, 0x19, KEY_STOP },
+       { 0x80, 0x1a, KEY_PAUSE },
+       { 0x80, 0x1b, KEY_PLAY },
+
+       { 0x80, 0x1c, KEY_PREVIOUS },
+       { 0x80, 0x1d, KEY_REWIND },
+       { 0x80, 0x1e, KEY_FASTFORWARD },
+       { 0x80, 0x1f, KEY_NEXT},
+
+       { 0x80, 0x40, KEY_1 },
+       { 0x80, 0x41, KEY_2 },
+       { 0x80, 0x42, KEY_3 },
+       { 0x80, 0x43, KEY_CHANNELUP },
+
+       { 0x80, 0x44, KEY_4 },
+       { 0x80, 0x45, KEY_5 },
+       { 0x80, 0x46, KEY_6 },
+       { 0x80, 0x47, KEY_CHANNELDOWN },
+
+       { 0x80, 0x48, KEY_7 },
+       { 0x80, 0x49, KEY_8 },
+       { 0x80, 0x4a, KEY_9 },
+       { 0x80, 0x4b, KEY_VOLUMEUP },
+
+       { 0x80, 0x4c, KEY_CLEAR },
+       { 0x80, 0x4d, KEY_0 },
+       { 0x80, 0x4e, KEY_ENTER },
+       { 0x80, 0x4f, KEY_VOLUMEDOWN },
 };
 EXPORT_SYMBOL(dibusb_rc_keys);
 
index f4c45f386ebc693992cb7a165bb76896c1c60086..effd34cc4b02d23601086904734a3b0ce78db57c 100644 (file)
@@ -21,11 +21,11 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
 
        demod_cfg.demod_address = 0x8;
 
-       if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
-               d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
-               d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+       if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
                return -ENODEV;
-       }
+
+       d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+       d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
 
        d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
 
@@ -169,7 +169,7 @@ static struct dvb_usb_properties dibusb1_1_properties = {
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
-       .rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+       .rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
        .rc_query         = dibusb_rc_query,
 
        .i2c_algo         = &dibusb_i2c_algo,
@@ -247,7 +247,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
-       .rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+       .rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
        .rc_query         = dibusb_rc_query,
 
        .i2c_algo         = &dibusb_i2c_algo,
@@ -272,8 +272,8 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
 #endif
        .devices = {
                {       "Artec T1 USB1.1 TVBOX with AN2235",
-                       { &dibusb_dib3000mb_table[20], NULL },
                        { &dibusb_dib3000mb_table[21], NULL },
+                       { &dibusb_dib3000mb_table[22], NULL },
                },
 #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
                {       "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
@@ -304,7 +304,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
-       .rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+       .rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
        .rc_query         = dibusb_rc_query,
 
        .i2c_algo         = &dibusb_i2c_algo,
@@ -355,7 +355,7 @@ static struct dvb_usb_properties artec_t1_usb2_properties = {
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
-       .rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+       .rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
        .rc_query         = dibusb_rc_query,
 
        .i2c_algo         = &dibusb_i2c_algo,
index 55802fba3c29ee71bc320cf056b6fa1a0c665eb7..eca4082a61ae4920b0e49b045b4d55ab21f6e837 100644 (file)
@@ -28,6 +28,17 @@ static struct usb_device_id dibusb_dib3000mc_table [] = {
 /* 00 */       { USB_DEVICE(USB_VID_DIBCOM,            USB_PID_DIBCOM_MOD3001_COLD) },
 /* 01 */       { USB_DEVICE(USB_VID_DIBCOM,            USB_PID_DIBCOM_MOD3001_WARM) },
 /* 02 */       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
+/* 03 */       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, // ( ? )
+/* 04 */       { USB_DEVICE(USB_VID_LITEON,            USB_PID_LITEON_DVB_T_COLD) },
+/* 05 */       { USB_DEVICE(USB_VID_LITEON,            USB_PID_LITEON_DVB_T_WARM) },
+/* 06 */       { USB_DEVICE(USB_VID_EMPIA,             USB_PID_DIGIVOX_MINI_SL_COLD) },
+/* 07 */       { USB_DEVICE(USB_VID_EMPIA,             USB_PID_DIGIVOX_MINI_SL_WARM) },
+/* 08 */       { USB_DEVICE(USB_VID_GRANDTEC,          USB_PID_GRANDTEC_DVBT_USB2_COLD) },
+/* 09 */       { USB_DEVICE(USB_VID_GRANDTEC,          USB_PID_GRANDTEC_DVBT_USB2_WARM) },
+/* 10 */       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_COLD) },
+/* 11 */       { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_WARM) },
+/* 12 */       { USB_DEVICE(USB_VID_LEADTEK,           USB_PID_WINFAST_DTV_DONGLE_COLD) },
+/* 13 */       { USB_DEVICE(USB_VID_LEADTEK,           USB_PID_WINFAST_DTV_DONGLE_WARM) },
                        { }             /* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
@@ -50,7 +61,7 @@ static struct dvb_usb_properties dibusb_mc_properties = {
 
        .rc_interval      = DEFAULT_RC_INTERVAL,
        .rc_key_map       = dibusb_rc_keys,
-       .rc_key_map_size  = 63, /* FIXME */
+       .rc_key_map_size  = 111, /* FIXME */
        .rc_query         = dibusb_rc_query,
 
        .i2c_algo         = &dibusb_i2c_algo,
@@ -68,16 +79,38 @@ static struct dvb_usb_properties dibusb_mc_properties = {
                }
        },
 
-       .num_device_descs = 2,
+       .num_device_descs = 7,
        .devices = {
                {   "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
                        { &dibusb_dib3000mc_table[0], NULL },
                        { &dibusb_dib3000mc_table[1], NULL },
                },
-               {   "Artec T1 USB2.0 TVBOX (please report the warm ID)",
+               {   "Artec T1 USB2.0 TVBOX (please check the warm ID)",
                        { &dibusb_dib3000mc_table[2], NULL },
-                       { NULL },
+                       { &dibusb_dib3000mc_table[3], NULL },
                },
+               {   "LITE-ON USB2.0 DVB-T Tuner",
+                   /* Also rebranded as Intuix S800, Toshiba */
+                       { &dibusb_dib3000mc_table[4], NULL },
+                       { &dibusb_dib3000mc_table[5], NULL },
+               },
+               {   "MSI Digivox Mini SL",
+                       { &dibusb_dib3000mc_table[6], NULL },
+                       { &dibusb_dib3000mc_table[7], NULL },
+               },
+               {   "GRAND - USB2.0 DVB-T adapter",
+                       { &dibusb_dib3000mc_table[8], NULL },
+                       { &dibusb_dib3000mc_table[9], NULL },
+               },
+               {   "Artec T14 - USB2.0 DVB-T",
+                       { &dibusb_dib3000mc_table[10], NULL },
+                       { &dibusb_dib3000mc_table[11], NULL },
+               },
+               {   "Leadtek - USB2.0 Winfast DTV dongle",
+                       { &dibusb_dib3000mc_table[12], NULL },
+                       { &dibusb_dib3000mc_table[13], NULL },
+               },
+               { NULL },
        }
 };
 
index 2d99d05c7eab3c9f7dde14fa17db918d5e56233e..a43f87480cf608810a20c9c320a5f764770780e4 100644 (file)
@@ -17,6 +17,8 @@
 #include "dvb-usb.h"
 
 #include "dib3000.h"
+#include "dib3000mc.h"
+#include "mt2060.h"
 
 /*
  * protocol of all dibusb related devices
@@ -96,6 +98,7 @@
 
 struct dibusb_state {
        struct dib_fe_xfer_ops ops;
+       int mt2060_present;
 
        /* for RC5 remote control */
        int old_toggle;
index c14d9efb48fdb7162a809ba16b3cd5b207acebc0..015854487308b7b7f9c452dd429eb002d1350a3f 100644 (file)
@@ -128,11 +128,11 @@ static struct nxt6000_config digitv_nxt6000_config = {
 
 static int digitv_frontend_attach(struct dvb_usb_device *d)
 {
-       if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL) {
+       if ((d->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &d->i2c_adap)) != NULL) {
                d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
                return 0;
        }
-       if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
+       if ((d->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
                d->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
                return 0;
        }
@@ -147,21 +147,91 @@ static int digitv_tuner_attach(struct dvb_usb_device *d)
 }
 
 static struct dvb_usb_rc_key digitv_rc_keys[] = {
-       { 0x00, 0x16, KEY_POWER }, /* dummy key */
+       { 0x5f, 0x55, KEY_0 },
+       { 0x6f, 0x55, KEY_1 },
+       { 0x9f, 0x55, KEY_2 },
+       { 0xaf, 0x55, KEY_3 },
+       { 0x5f, 0x56, KEY_4 },
+       { 0x6f, 0x56, KEY_5 },
+       { 0x9f, 0x56, KEY_6 },
+       { 0xaf, 0x56, KEY_7 },
+       { 0x5f, 0x59, KEY_8 },
+       { 0x6f, 0x59, KEY_9 },
+       { 0x9f, 0x59, KEY_TV },
+       { 0xaf, 0x59, KEY_AUX },
+       { 0x5f, 0x5a, KEY_DVD },
+       { 0x6f, 0x5a, KEY_POWER },
+       { 0x9f, 0x5a, KEY_MHP },     /* labelled 'Picture' */
+       { 0xaf, 0x5a, KEY_AUDIO },
+       { 0x5f, 0x65, KEY_INFO },
+       { 0x6f, 0x65, KEY_F13 },     /* 16:9 */
+       { 0x9f, 0x65, KEY_F14 },     /* 14:9 */
+       { 0xaf, 0x65, KEY_EPG },
+       { 0x5f, 0x66, KEY_EXIT },
+       { 0x6f, 0x66, KEY_MENU },
+       { 0x9f, 0x66, KEY_UP },
+       { 0xaf, 0x66, KEY_DOWN },
+       { 0x5f, 0x69, KEY_LEFT },
+       { 0x6f, 0x69, KEY_RIGHT },
+       { 0x9f, 0x69, KEY_ENTER },
+       { 0xaf, 0x69, KEY_CHANNELUP },
+       { 0x5f, 0x6a, KEY_CHANNELDOWN },
+       { 0x6f, 0x6a, KEY_VOLUMEUP },
+       { 0x9f, 0x6a, KEY_VOLUMEDOWN },
+       { 0xaf, 0x6a, KEY_RED },
+       { 0x5f, 0x95, KEY_GREEN },
+       { 0x6f, 0x95, KEY_YELLOW },
+       { 0x9f, 0x95, KEY_BLUE },
+       { 0xaf, 0x95, KEY_SUBTITLE },
+       { 0x5f, 0x96, KEY_F15 },     /* AD */
+       { 0x6f, 0x96, KEY_TEXT },
+       { 0x9f, 0x96, KEY_MUTE },
+       { 0xaf, 0x96, KEY_REWIND },
+       { 0x5f, 0x99, KEY_STOP },
+       { 0x6f, 0x99, KEY_PLAY },
+       { 0x9f, 0x99, KEY_FASTFORWARD },
+       { 0xaf, 0x99, KEY_F16 },     /* chapter */
+       { 0x5f, 0x9a, KEY_PAUSE },
+       { 0x6f, 0x9a, KEY_PLAY },
+       { 0x9f, 0x9a, KEY_RECORD },
+       { 0xaf, 0x9a, KEY_F17 },     /* picture in picture */
+       { 0x5f, 0xa5, KEY_KPPLUS },  /* zoom in */
+       { 0x6f, 0xa5, KEY_KPMINUS }, /* zoom out */
+       { 0x9f, 0xa5, KEY_F18 },     /* capture */
+       { 0xaf, 0xa5, KEY_F19 },     /* web */
+       { 0x5f, 0xa6, KEY_EMAIL },
+       { 0x6f, 0xa6, KEY_PHONE },
+       { 0x9f, 0xa6, KEY_PC },
 };
 
-/* TODO is it really the NEC protocol ? */
 static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
+       int i;
        u8 key[5];
+       u8 b[4] = { 0 };
+
+       *event = 0;
+       *state = REMOTE_NO_KEY_PRESSED;
 
        digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
-       /* TODO state, maybe it is VV ? */
+
+       /* Tell the device we've read the remote. Not sure how necessary
+          this is, but the Nebula SDK does it. */
+       digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+
+       /* if something is inside the buffer, simulate key press */
        if (key[1] != 0)
-               key[0] = 0x01; /* if something is inside the buffer, simulate key press */
+       {
+                 for (i = 0; i < d->props.rc_key_map_size; i++) {
+                       if (d->props.rc_key_map[i].custom == key[1] &&
+                           d->props.rc_key_map[i].data == key[2]) {
+                               *event = d->props.rc_key_map[i].event;
+                               *state = REMOTE_KEY_PRESSED;
+                               return 0;
+                       }
+               }
+       }
 
-       /* call the universal NEC remote processor, to find out the key's state and event */
-       dvb_usb_nec_rc_key_to_event(d,key,event,state);
        if (key[0] != 0)
                deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
        return 0;
index 70afcfd141ca02437eda63f7976eb8aaf85e9a05..27af4e43647936fe72a6db60704fcb5eaa804068 100644 (file)
@@ -93,6 +93,7 @@ static int dtt200u_frontend_attach(struct dvb_usb_device *d)
 }
 
 static struct dvb_usb_properties dtt200u_properties;
+static struct dvb_usb_properties wt220u_fc_properties;
 static struct dvb_usb_properties wt220u_properties;
 static struct dvb_usb_properties wt220u_zl0353_properties;
 
@@ -101,6 +102,7 @@ static int dtt200u_usb_probe(struct usb_interface *intf,
 {
        if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
                dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
+               dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
                dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0)
                return 0;
 
@@ -114,6 +116,9 @@ static struct usb_device_id dtt200u_usb_table [] = {
        { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM)  },
        { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD)  },
        { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM)  },
+       { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD)  },
+       { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM)  },
+       { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD)  },
        { 0 },
 };
 MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
@@ -193,13 +198,54 @@ static struct dvb_usb_properties wt220u_properties = {
        .num_device_descs = 1,
        .devices = {
                { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
-                 .cold_ids = { &dtt200u_usb_table[2], NULL },
+                 .cold_ids = { &dtt200u_usb_table[2], &dtt200u_usb_table[8], NULL },
                  .warm_ids = { &dtt200u_usb_table[3], NULL },
                },
                { NULL },
        }
 };
 
+static struct dvb_usb_properties wt220u_fc_properties = {
+       .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+       .pid_filter_count = 15,
+
+       .usb_ctrl = CYPRESS_FX2,
+       .firmware = "dvb-usb-wt220u-fc03.fw",
+
+       .power_ctrl      = dtt200u_power_ctrl,
+       .streaming_ctrl  = dtt200u_streaming_ctrl,
+       .pid_filter      = dtt200u_pid_filter,
+       .frontend_attach = dtt200u_frontend_attach,
+
+       .rc_interval     = 300,
+       .rc_key_map      = dtt200u_rc_keys,
+       .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+       .rc_query        = dtt200u_rc_query,
+
+       .generic_bulk_ctrl_endpoint = 0x01,
+
+       /* parameter for the MPEG2-data transfer */
+       .urb = {
+               .type = DVB_USB_BULK,
+               .count = 7,
+               .endpoint = 0x86,
+               .u = {
+                       .bulk = {
+                               .buffersize = 4096,
+                       }
+               }
+       },
+
+       .num_device_descs = 1,
+       .devices = {
+               { .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
+                 .cold_ids = { &dtt200u_usb_table[6], NULL },
+                 .warm_ids = { &dtt200u_usb_table[7], NULL },
+               },
+               { NULL },
+       }
+};
+
 static struct dvb_usb_properties wt220u_zl0353_properties = {
        .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
        .pid_filter_count = 15,
@@ -271,6 +317,6 @@ module_init(dtt200u_usb_module_init);
 module_exit(dtt200u_usb_module_exit);
 
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon DVB-T USB2.0 devices");
+MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D DVB-T USB2.0 devices");
 MODULE_VERSION("1.0");
 MODULE_LICENSE("GPL");
index ec631708c39480cf7d390267b452c109d2da2088..fe6208ada9037c916ffdb62c594bbe1a9f3b7dd6 100644 (file)
@@ -175,36 +175,36 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
 int dvb_usb_fe_init(struct dvb_usb_device* d)
 {
        if (d->props.frontend_attach == NULL) {
-               err("strange '%s' doesn't want to attach a frontend.",d->desc->name);
+               err("strange: '%s' doesn't want to attach a frontend.",d->desc->name);
                return 0;
        }
 
-       d->props.frontend_attach(d);
-
        /* re-assign sleep and wakeup functions */
-       if (d->fe != NULL) {
+       if (d->props.frontend_attach(d) == 0 && d->fe != NULL) {
                d->fe_init = d->fe->ops.init;   d->fe->ops.init  = dvb_usb_fe_wakeup;
                d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep;
 
                if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
                        err("Frontend registration failed.");
-                       if (d->fe->ops.release)
-                               d->fe->ops.release(d->fe);
+                       dvb_frontend_detach(d->fe);
                        d->fe = NULL;
                        return -ENODEV;
                }
+
+               /* only attach the tuner if the demod is there */
+               if (d->props.tuner_attach != NULL)
+                       d->props.tuner_attach(d);
        } else
                err("no frontend was attached by '%s'",d->desc->name);
 
-       if (d->props.tuner_attach != NULL)
-               d->props.tuner_attach(d);
-
        return 0;
 }
 
 int dvb_usb_fe_exit(struct dvb_usb_device *d)
 {
-       if (d->fe != NULL)
+       if (d->fe != NULL) {
                dvb_unregister_frontend(d->fe);
+               dvb_frontend_detach(d->fe);
+       }
        return 0;
 }
index 95698918bc116878da6ae4ac96f2b77661cf127d..57a10de1d3dd113c986fd858d7b07d7707e72713 100644 (file)
 #define _DVB_USB_IDS_H_
 
 /* Vendor IDs */
-#define USB_VID_ADSTECH                                                0x06e1
-#define USB_VID_ANCHOR                                         0x0547
-#define USB_VID_WIDEVIEW                                       0x14aa
-#define USB_VID_AVERMEDIA                                      0x07ca
-#define USB_VID_COMPRO                                         0x185b
-#define USB_VID_COMPRO_UNK                                     0x145f
-#define USB_VID_CYPRESS                                                0x04b4
-#define USB_VID_DIBCOM                                         0x10b8
-#define USB_VID_DVICO                                          0x0fe9
-#define USB_VID_EMPIA                                          0xeb1a
-#define USB_VID_GRANDTEC                                       0x5032
-#define USB_VID_HANFTEK                                                0x15f4
-#define USB_VID_HAUPPAUGE                                      0x2040
-#define USB_VID_HYPER_PALTEK                           0x1025
-#define USB_VID_KWORLD                                         0xeb2a
-#define USB_VID_KYE                                                    0x0458
-#define USB_VID_MEDION                                         0x1660
-#define USB_VID_PINNACLE                                       0x2304
-#define USB_VID_VISIONPLUS                                     0x13d3
-#define USB_VID_TWINHAN                                                0x1822
-#define USB_VID_ULTIMA_ELECTRONIC                      0x05d8
-#define USB_VID_GENPIX                                 0x09c0
+#define USB_VID_ADSTECH                                0x06e1
+#define USB_VID_ANCHOR                         0x0547
+#define USB_VID_AVERMEDIA                      0x07ca
+#define USB_VID_COMPRO                         0x185b
+#define USB_VID_COMPRO_UNK                     0x145f
+#define USB_VID_CYPRESS                                0x04b4
+#define USB_VID_DIBCOM                         0x10b8
+#define USB_VID_DVICO                          0x0fe9
+#define USB_VID_EMPIA                          0xeb1a
+#define USB_VID_GENPIX                         0x09c0
+#define USB_VID_GRANDTEC                       0x5032
+#define USB_VID_HANFTEK                                0x15f4
+#define USB_VID_HAUPPAUGE                      0x2040
+#define USB_VID_HYPER_PALTEK                   0x1025
+#define USB_VID_KWORLD                         0xeb2a
+#define USB_VID_KYE                            0x0458
+#define USB_VID_LEADTEK                                0x0413
+#define USB_VID_LITEON                         0x04ca
+#define USB_VID_MEDION                         0x1660
+#define USB_VID_PINNACLE                       0x2304
+#define USB_VID_VISIONPLUS                     0x13d3
+#define USB_VID_TWINHAN                                0x1822
+#define USB_VID_ULTIMA_ELECTRONIC              0x05d8
+#define USB_VID_WIDEVIEW                       0x14aa
 
 /* Product IDs */
 #define USB_PID_ADSTECH_USB2_COLD                      0xa333
 #define USB_PID_ADSTECH_USB2_WARM                      0xa334
-#define USB_PID_AVERMEDIA_DVBT_USB_COLD                0x0001
-#define USB_PID_AVERMEDIA_DVBT_USB_WARM                0x0002
-#define USB_PID_AVERMEDIA_DVBT_USB2_COLD       0xa800
-#define USB_PID_AVERMEDIA_DVBT_USB2_WARM       0xa801
-#define USB_PID_COMPRO_DVBU2000_COLD           0xd000
-#define USB_PID_COMPRO_DVBU2000_WARM           0xd001
-#define USB_PID_COMPRO_DVBU2000_UNK_COLD       0x010c
-#define USB_PID_COMPRO_DVBU2000_UNK_WARM       0x010d
+#define USB_PID_AVERMEDIA_DVBT_USB_COLD                        0x0001
+#define USB_PID_AVERMEDIA_DVBT_USB_WARM                        0x0002
+#define USB_PID_AVERMEDIA_DVBT_USB2_COLD               0xa800
+#define USB_PID_AVERMEDIA_DVBT_USB2_WARM               0xa801
+#define USB_PID_COMPRO_DVBU2000_COLD                   0xd000
+#define USB_PID_COMPRO_DVBU2000_WARM                   0xd001
+#define USB_PID_COMPRO_DVBU2000_UNK_COLD               0x010c
+#define USB_PID_COMPRO_DVBU2000_UNK_WARM               0x010d
 #define USB_PID_DIBCOM_HOOK_DEFAULT                    0x0064
-#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM     0x0065
+#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM             0x0065
 #define USB_PID_DIBCOM_MOD3000_COLD                    0x0bb8
 #define USB_PID_DIBCOM_MOD3000_WARM                    0x0bb9
 #define USB_PID_DIBCOM_MOD3001_COLD                    0x0bc6
 #define USB_PID_DIBCOM_MOD3001_WARM                    0x0bc7
 #define USB_PID_DIBCOM_STK7700                         0x1e14
-#define USB_PID_DIBCOM_STK7700_REENUM          0x1e15
-#define USB_PID_DIBCOM_ANCHOR_2135_COLD                0x2131
-#define USB_PID_GRANDTEC_DVBT_USB_COLD         0x0fa0
-#define USB_PID_GRANDTEC_DVBT_USB_WARM         0x0fa1
+#define USB_PID_DIBCOM_STK7700_REENUM                  0x1e15
+#define USB_PID_DIBCOM_ANCHOR_2135_COLD                        0x2131
+#define USB_PID_GRANDTEC_DVBT_USB_COLD                 0x0fa0
+#define USB_PID_GRANDTEC_DVBT_USB_WARM                 0x0fa1
 #define USB_PID_KWORLD_VSTREAM_COLD                    0x17de
 #define USB_PID_KWORLD_VSTREAM_WARM                    0x17df
 #define USB_PID_TWINHAN_VP7041_COLD                    0x3201
 #define USB_PID_DNTV_TINYUSB2_WARM                     0x3224
 #define USB_PID_ULTIMA_TVBOX_COLD                      0x8105
 #define USB_PID_ULTIMA_TVBOX_WARM                      0x8106
-#define USB_PID_ULTIMA_TVBOX_AN2235_COLD       0x8107
-#define USB_PID_ULTIMA_TVBOX_AN2235_WARM       0x8108
-#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD       0x2235
-#define USB_PID_ULTIMA_TVBOX_USB2_COLD         0x8109
-#define USB_PID_ULTIMA_TVBOX_USB2_WARM         0x810a
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD      0x8613
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM      0x1002
-#define USB_PID_UNK_HYPER_PALTEK_COLD          0x005e
-#define USB_PID_UNK_HYPER_PALTEK_WARM          0x005f
-#define USB_PID_HANFTEK_UMT_010_COLD           0x0001
-#define USB_PID_HANFTEK_UMT_010_WARM           0x0015
+#define USB_PID_ULTIMA_TVBOX_AN2235_COLD               0x8107
+#define USB_PID_ULTIMA_TVBOX_AN2235_WARM               0x8108
+#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD               0x2235
+#define USB_PID_ULTIMA_TVBOX_USB2_COLD                 0x8109
+#define USB_PID_ULTIMA_TVBOX_USB2_WARM                 0x810a
+#define USB_PID_ARTEC_T14_COLD                         0x810b
+#define USB_PID_ARTEC_T14_WARM                         0x810c
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD              0x8613
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM              0x1002
+#define USB_PID_UNK_HYPER_PALTEK_COLD                  0x005e
+#define USB_PID_UNK_HYPER_PALTEK_WARM                  0x005f
+#define USB_PID_HANFTEK_UMT_010_COLD                   0x0001
+#define USB_PID_HANFTEK_UMT_010_WARM                   0x0015
 #define USB_PID_DTT200U_COLD                           0x0201
 #define USB_PID_DTT200U_WARM                           0x0301
-#define USB_PID_WT220U_COLD                                    0x0222
-#define USB_PID_WT220U_WARM                                    0x0221
+#define USB_PID_WT220U_ZAP250_COLD                     0x0220
+#define USB_PID_WT220U_COLD                            0x0222
+#define USB_PID_WT220U_WARM                            0x0221
+#define USB_PID_WT220U_FC_COLD                         0x0225
+#define USB_PID_WT220U_FC_WARM                         0x0226
 #define USB_PID_WT220U_ZL0353_COLD                     0x022a
 #define USB_PID_WT220U_ZL0353_WARM                     0x022b
-#define USB_PID_WINTV_NOVA_T_USB2_COLD         0x9300
-#define USB_PID_WINTV_NOVA_T_USB2_WARM         0x9301
+#define USB_PID_WINTV_NOVA_T_USB2_COLD                 0x9300
+#define USB_PID_WINTV_NOVA_T_USB2_WARM                 0x9301
 #define USB_PID_NEBULA_DIGITV                          0x0201
 #define USB_PID_DVICO_BLUEBIRD_LGDT                    0xd820
 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD             0xd500
 #define USB_PID_MEDION_MD95700                         0x0932
 #define USB_PID_KYE_DVB_T_COLD                         0x701e
 #define USB_PID_KYE_DVB_T_WARM                         0x701f
-#define USB_PID_PCTV_200E                                      0x020e
-#define USB_PID_PCTV_400E                                      0x020f
-#define USB_PID_GENPIX_8PSK_COLD                               0x0200
-#define USB_PID_GENPIX_8PSK_WARM                               0x0201
+#define USB_PID_PCTV_200E                              0x020e
+#define USB_PID_PCTV_400E                              0x020f
+#define USB_PID_LITEON_DVB_T_COLD                      0xf000
+#define USB_PID_LITEON_DVB_T_WARM                      0xf001
+#define USB_PID_DIGIVOX_MINI_SL_COLD                   0xe360
+#define USB_PID_DIGIVOX_MINI_SL_WARM                   0xe361
+#define USB_PID_GRANDTEC_DVBT_USB2_COLD                        0x0bc6
+#define USB_PID_GRANDTEC_DVBT_USB2_WARM                        0x0bc7
+#define USB_PID_WINFAST_DTV_DONGLE_COLD                        0x6025
+#define USB_PID_WINFAST_DTV_DONGLE_WARM                        0x6026
+#define USB_PID_GENPIX_8PSK_COLD                       0x0200
+#define USB_PID_GENPIX_8PSK_WARM                       0x0201
+
 #endif
index e5c6d9835e06d24cac72b3ae3f342cab98b055da..380b2a45ee4c2accc59d0b8af0da13e6dc980dc5 100644 (file)
@@ -6,6 +6,7 @@
  * This file contains functions for initializing the the input-device and for handling remote-control-queries.
  */
 #include "dvb-usb-common.h"
+#include <linux/usb/input.h>
 
 /* Remote-control poll function - called every dib->rc_query_interval ms to see
  * whether the remote control has received anything.
@@ -96,7 +97,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
                return 0;
 
        usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
-       strlcpy(d->rc_phys, "/ir0", sizeof(d->rc_phys));
+       strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
 
        d->rc_input_dev = input_allocate_device();
        if (!d->rc_input_dev)
@@ -107,6 +108,8 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
        d->rc_input_dev->keycodemax = KEY_MAX;
        d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver";
        d->rc_input_dev->phys = d->rc_phys;
+       usb_to_input_id(d->udev, &d->rc_input_dev->id);
+       d->rc_input_dev->cdev.dev = &d->udev->dev;
 
        /* set the bits for the keys */
        deb_rc("key map size: %d\n", d->props.rc_key_map_size);
index 412039d8dbae728a730fac25742701a7fe288ad2..79f0a02ce98719742b3ad83791145c0041e2228d 100644 (file)
@@ -156,7 +156,7 @@ static struct dvb_usb_properties nova_t_properties = {
        .pid_filter_count = 32,
 
        .usb_ctrl = CYPRESS_FX2,
-       .firmware = "dvb-usb-nova-t-usb2-01.fw",
+       .firmware = "dvb-usb-nova-t-usb2-02.fw",
 
        .size_of_priv     = sizeof(struct dibusb_state),
 
index 97d74da0dad88676457b01081a6d8eaa406d0371..418a0b707151c9071f9833d6e52f49027bd1e20f 100644 (file)
@@ -58,7 +58,7 @@ static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
        umt_config.demod_init = umt_mt352_demod_init;
        umt_config.demod_address = 0xf;
 
-       d->fe = mt352_attach(&umt_config, &d->i2c_adap);
+       d->fe = dvb_attach(mt352_attach, &umt_config, &d->i2c_adap);
 
        return 0;
 }
index db978555b1eb34d2c5819cf2b5380f6e52450c8d..080fa257a0bc25aca04bd84e77c044dfe3f9043f 100644 (file)
@@ -1,48 +1,73 @@
 menu "Customise DVB Frontends"
        depends on DVB_CORE
 
+config DVB_FE_CUSTOMISE
+       bool "Customise the frontend modules to build"
+       default N
+       help
+         This allows the user to deselect frontend drivers unnecessary
+         for their hardware from the build. Use this option with care
+         as deselecting frontends which are in fact necessary will result
+         in DVB devices which cannot be tuned due to lack of driver support.
+
+         If unsure say N.
+
 comment "DVB-S (satellite) frontends"
        depends on DVB_CORE
 
 config DVB_STV0299
        tristate "ST STV0299 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_CX24110
        tristate "Conexant CX24110 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_CX24123
        tristate "Conexant CX24123 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA8083
        tristate "Philips TDA8083 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_MT312
        tristate "Zarlink VP310/MT312 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_VES1X93
        tristate "VLSI VES1893 or VES1993 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_S5H1420
        tristate "Samsung S5H1420 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_TDA10086
+       tristate "Philips TDA10086 based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
@@ -52,6 +77,7 @@ comment "DVB-T (terrestrial) frontends"
 config DVB_SP8870
        tristate "Spase sp8870 based"
        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.
@@ -64,6 +90,7 @@ config DVB_SP8870
 config DVB_SP887X
        tristate "Spase sp887x based"
        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.
@@ -76,24 +103,28 @@ config DVB_SP887X
 config DVB_CX22700
        tristate "Conexant CX22700 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_CX22702
        tristate "Conexant cx22702 demodulator (OFDM)"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_L64781
        tristate "LSI L64781"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA1004X
        tristate "Philips TDA10045H/TDA10046H based"
        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.
@@ -107,24 +138,28 @@ config DVB_TDA1004X
 config DVB_NXT6000
        tristate "NxtWave Communications NXT6000 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_MT352
        tristate "Zarlink MT352 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_ZL10353
        tristate "Zarlink ZL10353 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_DIB3000MB
        tristate "DiBcom 3000M-B"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
@@ -132,6 +167,7 @@ config DVB_DIB3000MB
 config DVB_DIB3000MC
        tristate "DiBcom 3000P/M-C"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
@@ -142,18 +178,21 @@ comment "DVB-C (cable) frontends"
 config DVB_VES1820
        tristate "VLSI VES1820 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA10021
        tristate "Philips TDA10021 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
 config DVB_STV0297
        tristate "ST STV0297 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
@@ -163,6 +202,7 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
 config DVB_NXT200X
        tristate "NxtWave Communications NXT2002/NXT2004 based"
        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
@@ -177,6 +217,7 @@ config DVB_NXT200X
 config DVB_OR51211
        tristate "Oren OR51211 based"
        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.
@@ -189,6 +230,7 @@ config DVB_OR51211
 config DVB_OR51132
        tristate "Oren OR51132 based"
        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
@@ -204,6 +246,7 @@ config DVB_OR51132
 config DVB_BCM3510
        tristate "Broadcom BCM3510"
        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
@@ -212,28 +255,52 @@ config DVB_BCM3510
 config DVB_LGDT330X
        tristate "LG Electronics LGDT3302/LGDT3303 based"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
 
-
-comment "Miscellaneous devices"
+comment "Tuners/PLL support"
        depends on DVB_CORE
 
 config DVB_PLL
        tristate
        depends on DVB_CORE && I2C
 
+config DVB_TDA826X
+       tristate "Philips TDA826X silicon tuner"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-S silicon tuner module. Say Y when you want to support this tuner.
+
+config DVB_TUNER_MT2060
+       tristate "Microtune MT2060 silicon IF tuner"
+       help
+         A driver for the silicon IF tuner MT2060 from Microtune.
+
+comment "Miscellaneous devices"
+       depends on DVB_CORE
+
 config DVB_LNBP21
        tristate "LNBP21 SEC controller"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          An SEC control chip.
 
 config DVB_ISL6421
        tristate "ISL6421 SEC controller"
        depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
        help
          An SEC control chip.
 
+config DVB_TUA6100
+       tristate "TUA6100 PLL"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVBS PLL chip.
+
 endmenu
index 0e4880b6db14699c8204295884b3a9b0e0454cfc..dce9cf0c75c0880acc234ad7a58d5441b3b6286c 100644 (file)
@@ -11,8 +11,8 @@ obj-$(CONFIG_DVB_CX22700) += cx22700.o
 obj-$(CONFIG_DVB_CX24110) += cx24110.o
 obj-$(CONFIG_DVB_TDA8083) += tda8083.o
 obj-$(CONFIG_DVB_L64781) += l64781.o
-obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o dib3000-common.o
-obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dib3000-common.o
+obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
+obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
 obj-$(CONFIG_DVB_MT312) += mt312.o
 obj-$(CONFIG_DVB_VES1820) += ves1820.o
 obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
@@ -33,3 +33,7 @@ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
 obj-$(CONFIG_DVB_ISL6421) += isl6421.o
+obj-$(CONFIG_DVB_TDA10086) += tda10086.o
+obj-$(CONFIG_DVB_TDA826X) += tda826x.o
+obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
+obj-$(CONFIG_DVB_TUA6100) += tua6100.o
index 80f5d0953d02635797ffdf9fc97ec242ebe01b1f..6dfa839a70224612c4fe72344c78fa080fca18e8 100644 (file)
@@ -34,7 +34,16 @@ struct bcm3510_config
        int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
 
+#if defined(CONFIG_DVB_BCM3510) || defined(CONFIG_DVB_BCM3510_MODULE)
 extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+                                                 struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_BCM3510
 
 #endif
index dcd8979c1a15e2668b5a5a8a8c276b59366edbb2..10286cc29fb40e8245ea76aae8086499d6c71858 100644 (file)
@@ -31,7 +31,16 @@ struct cx22700_config
        u8 demod_address;
 };
 
+#if defined(CONFIG_DVB_CX22700) || defined(CONFIG_DVB_CX22700_MODULE)
 extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_CX22700
 
 #endif // CX22700_H
index 4106d46c957fa2e081c637790dace69827c791c1..335219ebce2d5a5568dc6d815ffe8aaf3ac185c6 100644 (file)
@@ -399,7 +399,9 @@ static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
 {
        struct cx22702_state* state = fe->demodulator_priv;
 
-       *signal_strength = cx22702_readreg (state, 0x23);
+       u16 rs_ber = 0;
+       rs_ber = cx22702_readreg (state, 0x23);
+       *signal_strength = (rs_ber << 8) | rs_ber;
 
        return 0;
 }
index 7f2f241e5d4485985cfe0c0c23ddafd489e8add5..bc217ddf02c09f427c70822b6a4dd74106fa75db 100644 (file)
@@ -41,7 +41,16 @@ struct cx22702_config
        u8 output_mode;
 };
 
+#if defined(CONFIG_DVB_CX22702) || defined(CONFIG_DVB_CX22702_MODULE)
 extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
+                                          struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_CX22702
 
 #endif // CX22702_H
index ce3c7398bac9ffa74168145b9b67d4eccf519c02..ae96395217a2e475c2c79a9b2b21ca62b2ac18bf 100644 (file)
@@ -1,4 +1,4 @@
-/*
+       /*
     cx24110 - Single Chip Satellite Channel Receiver driver module
 
     Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
@@ -311,16 +311,17 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
 
 }
 
-int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
+static int _cx24110_pll_write (struct dvb_frontend* fe, u8 *buf, int len)
 {
        struct cx24110_state *state = fe->demodulator_priv;
 
+       if (len != 3)
+               return -EINVAL;
+
 /* tuner data is 21 bits long, must be left-aligned in data */
 /* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */
 /* FIXME (low): add error handling, avoid infinite loops if HW fails... */
 
-       dprintk("cx24110 debug: cx24108_write(%8.8x)\n",data);
-
        cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */
        cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */
 
@@ -329,19 +330,19 @@ int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
                cx24110_writereg(state,0x72,0);
 
        /* write the topmost 8 bits */
-       cx24110_writereg(state,0x72,(data>>24)&0xff);
+       cx24110_writereg(state,0x72,buf[0]);
 
        /* wait for the send to be completed */
        while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
                ;
 
        /* send another 8 bytes */
-       cx24110_writereg(state,0x72,(data>>16)&0xff);
+       cx24110_writereg(state,0x72,buf[1]);
        while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
                ;
 
        /* and the topmost 5 bits of this byte */
-       cx24110_writereg(state,0x72,(data>>8)&0xff);
+       cx24110_writereg(state,0x72,buf[2]);
        while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
                ;
 
@@ -642,6 +643,7 @@ static struct dvb_frontend_ops cx24110_ops = {
        .release = cx24110_release,
 
        .init = cx24110_initfe,
+       .write = _cx24110_pll_write,
        .set_frontend = cx24110_set_frontend,
        .get_frontend = cx24110_get_frontend,
        .read_status = cx24110_read_status,
@@ -664,4 +666,3 @@ MODULE_AUTHOR("Peter Hettkamp");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(cx24110_attach);
-EXPORT_SYMBOL(cx24110_pll_write);
index b354a64e0e74970f728d4b5f905a24b5abb3ff75..c9d5ae250ebb46296e43ea20fc728dd5b24af86a 100644 (file)
@@ -33,9 +33,24 @@ struct cx24110_config
        u8 demod_address;
 };
 
+static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) {
+       int r = 0;
+       u8 buf[] = {(u8) (val>>24), (u8) (val>>16), (u8) (val>>8)};
+       if (fe->ops.write)
+               r = fe->ops.write(fe, buf, 3);
+       return r;
+}
+
+#if defined(CONFIG_DVB_CX24110) || defined(CONFIG_DVB_CX24110_MODULE)
 extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
                                           struct i2c_adapter* i2c);
-
-extern int cx24110_pll_write(struct dvb_frontend* fe, u32 data);
+#else
+static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
+                                                 struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_CX24110
 
 #endif // CX24110_H
index 274a87b7a5d5fe8e54acf887aaeaa155bd82def1..62d69a6ea699269e2a937c1a764fd28e1cc3976c 100644 (file)
@@ -45,9 +45,6 @@ struct cx24123_state
 
        struct dvb_frontend frontend;
 
-       u32 lastber;
-       u16 snr;
-
        /* Some PLL specifics for tuning */
        u32 VCAarg;
        u32 VGAarg;
@@ -194,7 +191,7 @@ static struct {
        {0x06, 0x31}, /* MPEG (default) */
        {0x0b, 0x00}, /* Freq search start point (default) */
        {0x0c, 0x00}, /* Demodulator sample gain (default) */
-       {0x0d, 0x02}, /* Frequency search range = Fsymbol / 4 (default) */
+       {0x0d, 0x7f}, /* Force driver to shift until the maximum (+-10 MHz) */
        {0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */
        {0x0f, 0xfe}, /* FEC search mask (all supported codes) */
        {0x10, 0x01}, /* Default search inversion, no repeat (default) */
@@ -223,8 +220,9 @@ static struct {
        {0x44, 0x00}, /* Constellation (default) */
        {0x45, 0x00}, /* Symbol count (default) */
        {0x46, 0x0d}, /* Symbol rate estimator on (default) */
-       {0x56, 0x41}, /* Various (default) */
+       {0x56, 0xc1}, /* Error Counter = Viterbi BER */
        {0x57, 0xff}, /* Error Counter Window (default) */
+       {0x5c, 0x20}, /* Acquisition AFC Expiration window (default is 0x10) */
        {0x67, 0x83}, /* Non-DCII symbol clock */
 };
 
@@ -321,6 +319,12 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
        if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
                fec = FEC_AUTO;
 
+       /* Set the soft decision threshold */
+       if(fec == FEC_1_2)
+               cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) | 0x01);
+       else
+               cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) & ~0x01);
+
        switch (fec) {
        case FEC_1_2:
                dprintk("%s:  set FEC to 1/2\n",__FUNCTION__);
@@ -657,6 +661,10 @@ static int cx24123_initfe(struct dvb_frontend* fe)
        for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
                cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
 
+       /* Set the LNB polarity */
+       if(state->config->lnb_polarity)
+               cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02);
+
        return 0;
 }
 
@@ -674,6 +682,9 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
        case SEC_VOLTAGE_18:
                dprintk("%s: setting voltage 18V\n", __FUNCTION__);
                return cx24123_writereg(state, 0x29, val | 0x80);
+       case SEC_VOLTAGE_OFF:
+               /* already handled in cx88-dvb */
+               return 0;
        default:
                return -EINVAL;
        };
@@ -776,13 +787,15 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
        if (lock & 0x01)
                *status |= FE_HAS_SIGNAL;
        if (sync & 0x02)
-               *status |= FE_HAS_CARRIER;
+               *status |= FE_HAS_CARRIER;      /* Phase locked */
        if (sync & 0x04)
                *status |= FE_HAS_VITERBI;
+
+       /* Reed-Solomon Status */
        if (sync & 0x08)
                *status |= FE_HAS_SYNC;
        if (sync & 0x80)
-               *status |= FE_HAS_LOCK;
+               *status |= FE_HAS_LOCK;         /*Full Sync */
 
        return 0;
 }
@@ -795,29 +808,13 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
 {
        struct cx24123_state *state = fe->demodulator_priv;
 
-       state->lastber =
-               ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
+       /* The true bit error rate is this value divided by
+          the window size (set as 256 * 255) */
+       *ber = ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
                (cx24123_readreg(state, 0x1d) << 8 |
-               cx24123_readreg(state, 0x1e));
-
-       /* Do the signal quality processing here, it's derived from the BER. */
-       /* Scale the BER from a 24bit to a SNR 16 bit where higher = better */
-       if (state->lastber < 5000)
-               state->snr = 655*100;
-       else if ( (state->lastber >=   5000) && (state->lastber <  55000) )
-               state->snr = 655*90;
-       else if ( (state->lastber >=  55000) && (state->lastber < 150000) )
-               state->snr = 655*80;
-       else if ( (state->lastber >= 150000) && (state->lastber < 250000) )
-               state->snr = 655*70;
-       else if ( (state->lastber >= 250000) && (state->lastber < 450000) )
-               state->snr = 655*65;
-       else
-               state->snr = 0;
-
-       dprintk("%s:  BER = %d, S/N index = %d\n",__FUNCTION__,state->lastber, state->snr);
+                cx24123_readreg(state, 0x1e));
 
-       *ber = state->lastber;
+       dprintk("%s:  BER = %d\n",__FUNCTION__,*ber);
 
        return 0;
 }
@@ -825,6 +822,7 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
 static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
 {
        struct cx24123_state *state = fe->demodulator_priv;
+
        *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
 
        dprintk("%s:  Signal strength = %d\n",__FUNCTION__,*signal_strength);
@@ -835,19 +833,13 @@ static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
 static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
 {
        struct cx24123_state *state = fe->demodulator_priv;
-       *snr = state->snr;
-
-       dprintk("%s:  read S/N index = %d\n",__FUNCTION__,*snr);
 
-       return 0;
-}
+       /* Inverted raw Es/N0 count, totally bogus but better than the
+          BER threshold. */
+       *snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) |
+                        (u16)cx24123_readreg(state, 0x19));
 
-static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-       struct cx24123_state *state = fe->demodulator_priv;
-       *ucblocks = state->lastber;
-
-       dprintk("%s:  ucblocks (ber) = %d\n",__FUNCTION__,*ucblocks);
+       dprintk("%s:  read S/N index = %d\n",__FUNCTION__,*snr);
 
        return 0;
 }
@@ -922,6 +914,29 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
        return 0;
 }
 
+static int cx24123_tune(struct dvb_frontend* fe,
+                       struct dvb_frontend_parameters* params,
+                       unsigned int mode_flags,
+                       int *delay,
+                       fe_status_t *status)
+{
+       int retval = 0;
+
+       if (params != NULL)
+               retval = cx24123_set_frontend(fe, params);
+
+       if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+               cx24123_read_status(fe, status);
+       *delay = HZ/10;
+
+       return retval;
+}
+
+static int cx24123_get_algo(struct dvb_frontend *fe)
+{
+       return 1; //FE_ALGO_HW
+}
+
 static void cx24123_release(struct dvb_frontend* fe)
 {
        struct cx24123_state* state = fe->demodulator_priv;
@@ -949,8 +964,6 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
        /* setup the state */
        state->config = config;
        state->i2c = i2c;
-       state->lastber = 0;
-       state->snr = 0;
        state->VCAarg = 0;
        state->VGAarg = 0;
        state->bandselectarg = 0;
@@ -1003,11 +1016,12 @@ static struct dvb_frontend_ops cx24123_ops = {
        .read_ber = cx24123_read_ber,
        .read_signal_strength = cx24123_read_signal_strength,
        .read_snr = cx24123_read_snr,
-       .read_ucblocks = cx24123_read_ucblocks,
        .diseqc_send_master_cmd = cx24123_send_diseqc_msg,
        .diseqc_send_burst = cx24123_diseqc_send_burst,
        .set_tone = cx24123_set_tone,
        .set_voltage = cx24123_set_voltage,
+       .tune = cx24123_tune,
+       .get_frontend_algo = cx24123_get_algo,
 };
 
 module_param(debug, int, 0644);
index 9606f825935c8341f53b760e9c91f06e4146e9a8..57a1dae1dc40a5bc1c61434f614401f638f84b69 100644 (file)
@@ -30,9 +30,21 @@ struct cx24123_config
 
        /* Need to set device param for start_dma */
        int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+
+       /* 0 = LNB voltage normal, 1 = LNB voltage inverted */
+       int lnb_polarity;
 };
 
+#if defined(CONFIG_DVB_CX24123) || defined(CONFIG_DVB_CX24123_MODULE)
 extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
                                           struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
+                                                 struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_CX24123
 
 #endif /* CX24123_H */
diff --git a/drivers/media/dvb/frontends/dib3000-common.c b/drivers/media/dvb/frontends/dib3000-common.c
deleted file mode 100644 (file)
index 1a4f1f7..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-#include "dib3000-common.h"
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
-#endif
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_i2c(args...) dprintk(0x02,args)
-#define deb_srch(args...) dprintk(0x04,args)
-
-
-int dib3000_read_reg(struct dib3000_state *state, u16 reg)
-{
-       u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
-       u8 rb[2];
-       struct i2c_msg msg[] = {
-               { .addr = state->config.demod_address, .flags = 0,        .buf = wb, .len = 2 },
-               { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
-       };
-
-       if (i2c_transfer(state->i2c, msg, 2) != 2)
-               deb_i2c("i2c read error\n");
-
-       deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
-                       (rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);
-
-       return (rb[0] << 8) | rb[1];
-}
-
-int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
-{
-       u8 b[] = {
-               (reg >> 8) & 0xff, reg & 0xff,
-               (val >> 8) & 0xff, val & 0xff,
-       };
-       struct i2c_msg msg[] = {
-               { .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }
-       };
-       deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);
-
-       return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
-}
-
-int dib3000_search_status(u16 irq,u16 lock)
-{
-       if (irq & 0x02) {
-               if (lock & 0x01) {
-                       deb_srch("auto search succeeded\n");
-                       return 1; // auto search succeeded
-               } else {
-                       deb_srch("auto search not successful\n");
-                       return 0; // auto search failed
-               }
-       } else if (irq & 0x01)  {
-               deb_srch("auto search failed\n");
-               return 0; // auto search failed
-       }
-       return -1; // try again
-}
-
-/* for auto search */
-u16 dib3000_seq[2][2][2] =     /* fft,gua,   inv   */
-       { /* fft */
-               { /* gua */
-                       { 0, 1 },                   /*  0   0   { 0,1 } */
-                       { 3, 9 },                   /*  0   1   { 0,1 } */
-               },
-               {
-                       { 2, 5 },                   /*  1   0   { 0,1 } */
-                       { 6, 11 },                  /*  1   1   { 0,1 } */
-               }
-       };
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
-MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dib3000_seq);
-
-EXPORT_SYMBOL(dib3000_read_reg);
-EXPORT_SYMBOL(dib3000_write_reg);
-EXPORT_SYMBOL(dib3000_search_status);
diff --git a/drivers/media/dvb/frontends/dib3000-common.h b/drivers/media/dvb/frontends/dib3000-common.h
deleted file mode 100644 (file)
index be1c0d3..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * .h-files for the common use of the frontend drivers made by DiBcom
- * DiBcom 3000M-B/C, 3000P
- *
- * DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * based on GPL code from DibCom, which has
- *
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation, version 2.
- *
- * Acknowledgements
- *
- *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- *  sources, on which this driver (and the dvb-dibusb) are based.
- *
- * see Documentation/dvb/README.dibusb for more information
- *
- */
-
-#ifndef DIB3000_COMMON_H
-#define DIB3000_COMMON_H
-
-#include "dvb_frontend.h"
-#include "dib3000.h"
-
-/* info and err, taken from usb.h, if there is anything available like by default. */
-#define err(format, arg...)  printk(KERN_ERR     "dib3000: " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO    "dib3000: " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
-
-/* frontend state */
-struct dib3000_state {
-       struct i2c_adapter* i2c;
-
-/* configuration settings */
-       struct dib3000_config config;
-
-       struct dvb_frontend frontend;
-       int timing_offset;
-       int timing_offset_comp_done;
-
-       fe_bandwidth_t last_tuned_bw;
-       u32 last_tuned_freq;
-};
-
-/* commonly used methods by the dib3000mb/mc/p frontend */
-extern int dib3000_read_reg(struct dib3000_state *state, u16 reg);
-extern int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val);
-
-extern int dib3000_search_status(u16 irq,u16 lock);
-
-/* handy shortcuts */
-#define rd(reg) dib3000_read_reg(state,reg)
-
-#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
-       { err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
-
-#define wr_foreach(a,v) { int i; \
-       if (sizeof(a) != sizeof(v)) \
-               err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
-       for (i=0; i < sizeof(a)/sizeof(u16); i++) \
-               wr(a[i],v[i]); \
-       }
-
-#define set_or(reg,val) wr(reg,rd(reg) | val)
-
-#define set_and(reg,val) wr(reg,rd(reg) & val)
-
-
-/* debug */
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-#define dprintk(level,args...) \
-    do { if ((debug & level)) { printk(args); } } while (0)
-#else
-#define dprintk(args...) do { } while (0)
-#endif
-
-/* mask for enabling a specific pid for the pid_filter */
-#define DIB3000_ACTIVATE_PID_FILTERING (0x2000)
-
-/* common values for tuning */
-#define DIB3000_ALPHA_0                                        (     0)
-#define DIB3000_ALPHA_1                                        (     1)
-#define DIB3000_ALPHA_2                                        (     2)
-#define DIB3000_ALPHA_4                                        (     4)
-
-#define DIB3000_CONSTELLATION_QPSK             (     0)
-#define DIB3000_CONSTELLATION_16QAM            (     1)
-#define DIB3000_CONSTELLATION_64QAM            (     2)
-
-#define DIB3000_GUARD_TIME_1_32                        (     0)
-#define DIB3000_GUARD_TIME_1_16                        (     1)
-#define DIB3000_GUARD_TIME_1_8                 (     2)
-#define DIB3000_GUARD_TIME_1_4                 (     3)
-
-#define DIB3000_TRANSMISSION_MODE_2K   (     0)
-#define DIB3000_TRANSMISSION_MODE_8K   (     1)
-
-#define DIB3000_SELECT_LP                              (     0)
-#define DIB3000_SELECT_HP                              (     1)
-
-#define DIB3000_FEC_1_2                                        (     1)
-#define DIB3000_FEC_2_3                                        (     2)
-#define DIB3000_FEC_3_4                                        (     3)
-#define DIB3000_FEC_5_6                                        (     5)
-#define DIB3000_FEC_7_8                                        (     7)
-
-#define DIB3000_HRCH_OFF                               (     0)
-#define DIB3000_HRCH_ON                                        (     1)
-
-#define DIB3000_DDS_INVERSION_OFF              (     0)
-#define DIB3000_DDS_INVERSION_ON               (     1)
-
-#define DIB3000_TUNER_WRITE_ENABLE(a)  (0xffff & (a << 8))
-#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7)))
-
-/* for auto search */
-extern u16 dib3000_seq[2][2][2];
-
-#define DIB3000_REG_MANUFACTOR_ID              (  1025)
-#define DIB3000_I2C_ID_DIBCOM                  (0x01b3)
-
-#define DIB3000_REG_DEVICE_ID                  (  1026)
-#define DIB3000MB_DEVICE_ID                            (0x3000)
-#define DIB3000MC_DEVICE_ID                            (0x3001)
-#define DIB3000P_DEVICE_ID                             (0x3002)
-
-#endif // DIB3000_COMMON_H
index ec927628d2734cac2eee5ef633e5eb55de4d680e..0caac3f0f279f3b1ed461f5d7658f3900fa18a12 100644 (file)
@@ -41,9 +41,16 @@ struct dib_fe_xfer_ops
        int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl);
 };
 
+#if defined(CONFIG_DVB_DIB3000MB) || defined(CONFIG_DVB_DIB3000MB_MODULE)
 extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
                                             struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
+#else
+static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
+                                            struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_DIB3000MB
 
-extern struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
-                                            struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
 #endif // DIB3000_H
index 5302e11883a24738153dfd75f1f4c6ed3c53b354..adbabfdb04a95c0fe50f23251af39e2140139d2a 100644 (file)
 #include <linux/string.h>
 #include <linux/slab.h>
 
-#include "dib3000-common.h"
-#include "dib3000mb_priv.h"
+#include "dvb_frontend.h"
+
 #include "dib3000.h"
+#include "dib3000mb_priv.h"
 
 /* Version information */
 #define DRIVER_VERSION "0.1"
@@ -44,10 +45,81 @@ module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");
 #endif
 #define deb_info(args...) dprintk(0x01,args)
+#define deb_i2c(args...)  dprintk(0x02,args)
+#define deb_srch(args...) dprintk(0x04,args)
+#define deb_info(args...) dprintk(0x01,args)
 #define deb_xfer(args...) dprintk(0x02,args)
 #define deb_setf(args...) dprintk(0x04,args)
 #define deb_getf(args...) dprintk(0x08,args)
 
+#ifdef CONFIG_DVB_DIBCOM_DEBUG
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
+#endif
+
+static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
+{
+       u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
+       u8 rb[2];
+       struct i2c_msg msg[] = {
+               { .addr = state->config.demod_address, .flags = 0,        .buf = wb, .len = 2 },
+               { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+       };
+
+       if (i2c_transfer(state->i2c, msg, 2) != 2)
+               deb_i2c("i2c read error\n");
+
+       deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
+                       (rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);
+
+       return (rb[0] << 8) | rb[1];
+}
+
+static int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
+{
+       u8 b[] = {
+               (reg >> 8) & 0xff, reg & 0xff,
+               (val >> 8) & 0xff, val & 0xff,
+       };
+       struct i2c_msg msg[] = {
+               { .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }
+       };
+       deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);
+
+       return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+static int dib3000_search_status(u16 irq,u16 lock)
+{
+       if (irq & 0x02) {
+               if (lock & 0x01) {
+                       deb_srch("auto search succeeded\n");
+                       return 1; // auto search succeeded
+               } else {
+                       deb_srch("auto search not successful\n");
+                       return 0; // auto search failed
+               }
+       } else if (irq & 0x01)  {
+               deb_srch("auto search failed\n");
+               return 0; // auto search failed
+       }
+       return -1; // try again
+}
+
+/* for auto search */
+static u16 dib3000_seq[2][2][2] =     /* fft,gua,   inv   */
+       { /* fft */
+               { /* gua */
+                       { 0, 1 },                   /*  0   0   { 0,1 } */
+                       { 3, 9 },                   /*  0   1   { 0,1 } */
+               },
+               {
+                       { 2, 5 },                   /*  1   0   { 0,1 } */
+                       { 6, 11 },                  /*  1   1   { 0,1 } */
+               }
+       };
+
 static int dib3000mb_get_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep);
 
index 999b19047816dfc4402781557b9aea7a6f611de5..1a12747fdc914108bf6ee5f4d4bc26342b7c3392 100644 (file)
 #ifndef __DIB3000MB_PRIV_H_INCLUDED__
 #define __DIB3000MB_PRIV_H_INCLUDED__
 
+/* info and err, taken from usb.h, if there is anything available like by default. */
+#define err(format, arg...)  printk(KERN_ERR     "dib3000: " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO    "dib3000: " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
+
+/* handy shortcuts */
+#define rd(reg) dib3000_read_reg(state,reg)
+
+#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
+       { err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
+
+#define wr_foreach(a,v) { int i; \
+       if (sizeof(a) != sizeof(v)) \
+               err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
+       for (i=0; i < sizeof(a)/sizeof(u16); i++) \
+               wr(a[i],v[i]); \
+       }
+
+#define set_or(reg,val) wr(reg,rd(reg) | val)
+
+#define set_and(reg,val) wr(reg,rd(reg) & val)
+
+/* debug */
+
+#ifdef CONFIG_DVB_DIBCOM_DEBUG
+#define dprintk(level,args...) \
+    do { if ((debug & level)) { printk(args); } } while (0)
+#else
+#define dprintk(args...) do { } while (0)
+#endif
+
+/* mask for enabling a specific pid for the pid_filter */
+#define DIB3000_ACTIVATE_PID_FILTERING (0x2000)
+
+/* common values for tuning */
+#define DIB3000_ALPHA_0                                        (     0)
+#define DIB3000_ALPHA_1                                        (     1)
+#define DIB3000_ALPHA_2                                        (     2)
+#define DIB3000_ALPHA_4                                        (     4)
+
+#define DIB3000_CONSTELLATION_QPSK             (     0)
+#define DIB3000_CONSTELLATION_16QAM            (     1)
+#define DIB3000_CONSTELLATION_64QAM            (     2)
+
+#define DIB3000_GUARD_TIME_1_32                        (     0)
+#define DIB3000_GUARD_TIME_1_16                        (     1)
+#define DIB3000_GUARD_TIME_1_8                 (     2)
+#define DIB3000_GUARD_TIME_1_4                 (     3)
+
+#define DIB3000_TRANSMISSION_MODE_2K   (     0)
+#define DIB3000_TRANSMISSION_MODE_8K   (     1)
+
+#define DIB3000_SELECT_LP                              (     0)
+#define DIB3000_SELECT_HP                              (     1)
+
+#define DIB3000_FEC_1_2                                        (     1)
+#define DIB3000_FEC_2_3                                        (     2)
+#define DIB3000_FEC_3_4                                        (     3)
+#define DIB3000_FEC_5_6                                        (     5)
+#define DIB3000_FEC_7_8                                        (     7)
+
+#define DIB3000_HRCH_OFF                               (     0)
+#define DIB3000_HRCH_ON                                        (     1)
+
+#define DIB3000_DDS_INVERSION_OFF              (     0)
+#define DIB3000_DDS_INVERSION_ON               (     1)
+
+#define DIB3000_TUNER_WRITE_ENABLE(a)  (0xffff & (a << 8))
+#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7)))
+
+#define DIB3000_REG_MANUFACTOR_ID              (  1025)
+#define DIB3000_I2C_ID_DIBCOM                  (0x01b3)
+
+#define DIB3000_REG_DEVICE_ID                  (  1026)
+#define DIB3000MB_DEVICE_ID                            (0x3000)
+#define DIB3000MC_DEVICE_ID                            (0x3001)
+#define DIB3000P_DEVICE_ID                             (0x3002)
+
+/* frontend state */
+struct dib3000_state {
+       struct i2c_adapter* i2c;
+
+/* configuration settings */
+       struct dib3000_config config;
+
+       struct dvb_frontend frontend;
+       int timing_offset;
+       int timing_offset_comp_done;
+
+       fe_bandwidth_t last_tuned_bw;
+       u32 last_tuned_freq;
+};
+
 /* register addresses and some of their default values */
 
 /* restart subsystems */
index 98673474a14021dd551ea887f9867e7b40ad4c79..cc28417fa33ac7fb6bc1eef2e496cd0ec682ec6e 100644 (file)
 /*
- * Frontend driver for mobile DVB-T demodulator DiBcom 3000P/M-C
- * DiBcom (http://www.dibcom.fr/)
+ * Driver for DiBcom DiB3000MC/P-demodulator.
  *
+ * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
  * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
  *
- * based on GPL code from DiBCom, which has
+ * This code is partially based on the previous dib3000mc.c .
  *
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
- *
- *     This program is free software; you can redistribute it and/or
+ * This program is free software; 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.
- *
- * Acknowledgements
- *
- *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- *  sources, on which this driver (and the dvb-dibusb) are based.
- *
- * see Documentation/dvb/README.dibusb for more information
- *
  */
+
 #include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dib3000-common.h"
-#include "dib3000mc_priv.h"
-#include "dib3000.h"
-
-/* Version information */
-#define DRIVER_VERSION "0.1"
-#define DRIVER_DESC "DiBcom 3000M-C DVB-T demodulator"
-#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
+#include <linux/i2c.h>
+//#include <linux/init.h>
+//#include <linux/delay.h>
+//#include <linux/string.h>
+//#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+
+#include "dib3000mc.h"
+
 static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe,16=stat (|-able)).");
-#endif
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_xfer(args...) dprintk(0x02,args)
-#define deb_setf(args...) dprintk(0x04,args)
-#define deb_getf(args...) dprintk(0x08,args)
-#define deb_stat(args...) dprintk(0x10,args)
-
-static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode,
-       fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth)
-{
-       switch (transmission_mode) {
-               case TRANSMISSION_MODE_2K:
-                       wr_foreach(dib3000mc_reg_fft,dib3000mc_fft_modes[0]);
-                       break;
-               case TRANSMISSION_MODE_8K:
-                       wr_foreach(dib3000mc_reg_fft,dib3000mc_fft_modes[1]);
-                       break;
-               default:
-                       break;
-       }
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
-       switch (bandwidth) {
-/*             case BANDWIDTH_5_MHZ:
-                       wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[0]);
-                       break; */
-               case BANDWIDTH_6_MHZ:
-                       wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[1]);
-                       break;
-               case BANDWIDTH_7_MHZ:
-                       wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[2]);
-                       break;
-               case BANDWIDTH_8_MHZ:
-                       wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[3]);
-                       break;
-               default:
-                       break;
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0)
+
+struct dib3000mc_state {
+       struct dvb_frontend demod;
+       struct dib3000mc_config *cfg;
+
+       u8 i2c_addr;
+       struct i2c_adapter *i2c_adap;
+
+       struct dibx000_i2c_master i2c_master;
+
+       fe_bandwidth_t current_bandwidth;
+
+       u16 dev_id;
+};
+
+static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
+{
+       u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
+       u8 rb[2];
+       struct i2c_msg msg[2] = {
+               { .addr = state->i2c_addr >> 1, .flags = 0,        .buf = wb, .len = 2 },
+               { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+       };
+
+       if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+               dprintk("i2c read error on %d\n",reg);
+
+       return (rb[0] << 8) | rb[1];
+}
+
+static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
+{
+       u8 b[4] = {
+               (reg >> 8) & 0xff, reg & 0xff,
+               (val >> 8) & 0xff, val & 0xff,
+       };
+       struct i2c_msg msg = {
+               .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+       };
+       return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+
+static int dib3000mc_identify(struct dib3000mc_state *state)
+{
+       u16 value;
+       if ((value = dib3000mc_read_word(state, 1025)) != 0x01b3) {
+               dprintk("-E-  DiB3000MC/P: wrong Vendor ID (read=0x%x)\n",value);
+               return -EREMOTEIO;
        }
 
-       switch (mode) {
-               case 0: /* no impulse */ /* fall through */
-                       wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[0]);
-                       break;
-               case 1: /* new algo */
-                       wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[1]);
-                       set_or(DIB3000MC_REG_IMP_NOISE_55,DIB3000MC_IMP_NEW_ALGO(0)); /* gives 1<<10 */
-                       break;
-               default: /* old algo */
-                       wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[3]);
-                       break;
+       value = dib3000mc_read_word(state, 1026);
+       if (value != 0x3001 && value != 0x3002) {
+               dprintk("-E-  DiB3000MC/P: wrong Device ID (%x)\n",value);
+               return -EREMOTEIO;
        }
+       state->dev_id = value;
+
+       dprintk("-I-  found DiB3000MC/P: %x\n",state->dev_id);
+
        return 0;
 }
 
-static int dib3000mc_set_timing(struct dib3000_state *state, int upd_offset,
-               fe_transmit_mode_t fft, fe_bandwidth_t bw)
+static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, u8 update_offset)
 {
-       u16 timf_msb,timf_lsb;
-       s32 tim_offset,tim_sgn;
-       u64 comp1,comp2,comp=0;
-
-       switch (bw) {
-               case BANDWIDTH_8_MHZ: comp = DIB3000MC_CLOCK_REF*8; break;
-               case BANDWIDTH_7_MHZ: comp = DIB3000MC_CLOCK_REF*7; break;
-               case BANDWIDTH_6_MHZ: comp = DIB3000MC_CLOCK_REF*6; break;
-               default: err("unknown bandwidth (%d)",bw); break;
-       }
-       timf_msb = (comp >> 16) & 0xff;
-       timf_lsb = (comp & 0xffff);
+/*
+       u32 timf_msb, timf_lsb, i;
+       int tim_sgn ;
+       LUInt comp1, comp2, comp ;
+//     u32 tim_offset ;
+       comp = 27700 * BW_INDEX_TO_KHZ(bw) / 1000;
+       timf_msb = (comp >> 16) & 0x00FF;
+       timf_lsb =  comp        & 0xFFFF;
 
        // Update the timing offset ;
-       if (upd_offset > 0) {
-               if (!state->timing_offset_comp_done) {
-                       msleep(200);
+       if (update_offset) {
+               if (state->timing_offset_comp_done == 0) {
+                       usleep(200000);
                        state->timing_offset_comp_done = 1;
                }
-               tim_offset = rd(DIB3000MC_REG_TIMING_OFFS_MSB);
+               tim_offset = dib3000mc_read_word(state, 416);
                if ((tim_offset & 0x2000) == 0x2000)
-                       tim_offset |= 0xC000;
-               if (fft == TRANSMISSION_MODE_2K)
-                       tim_offset <<= 2;
+                       tim_offset |= 0xC000; // PB: This only works if tim_offset is s16 - weird
+
+               if (nfft == 0)
+                       tim_offset = tim_offset << 2; // PB: Do not store the offset for different things in one variable
                state->timing_offset += tim_offset;
        }
-
        tim_offset = state->timing_offset;
+
        if (tim_offset < 0) {
                tim_sgn = 1;
                tim_offset = -tim_offset;
        } else
                tim_sgn = 0;
 
-       comp1 =  (u32)tim_offset * (u32)timf_lsb ;
-       comp2 =  (u32)tim_offset * (u32)timf_msb ;
+       comp1 = tim_offset * timf_lsb;
+       comp2 = tim_offset * timf_msb;
        comp  = ((comp1 >> 16) + comp2) >> 7;
 
        if (tim_sgn == 0)
-               comp = (u32)(timf_msb << 16) + (u32) timf_lsb + comp;
+               comp = timf_msb * (1<<16) + timf_lsb + comp;
        else
-               comp = (u32)(timf_msb << 16) + (u32) timf_lsb - comp ;
+               comp = timf_msb * (1<<16) + timf_lsb - comp;
+
+       timf_msb = (comp>>16)&0xFF ;
+       timf_lsb = comp&0xFFFF;
+*/
+       u32 timf = 1384402 * (BW_INDEX_TO_KHZ(bw) / 1000);
 
-       timf_msb = (comp >> 16) & 0xff;
-       timf_lsb = comp & 0xffff;
+       dib3000mc_write_word(state, 23, timf >> 16);
+       dib3000mc_write_word(state, 24, timf & 0xffff);
 
-       wr(DIB3000MC_REG_TIMING_FREQ_MSB,timf_msb);
-       wr(DIB3000MC_REG_TIMING_FREQ_LSB,timf_lsb);
        return 0;
 }
 
-static int dib3000mc_init_auto_scan(struct dib3000_state *state, fe_bandwidth_t bw, int boost)
+static int dib3000mc_setup_pwm3_state(struct dib3000mc_state *state)
 {
-       if (boost) {
-               wr(DIB3000MC_REG_SCAN_BOOST,DIB3000MC_SCAN_BOOST_ON);
+    if (state->cfg->pwm3_inversion) {
+               dib3000mc_write_word(state, 51, (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0));
+               dib3000mc_write_word(state, 52, (0 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (2 << 0));
        } else {
-               wr(DIB3000MC_REG_SCAN_BOOST,DIB3000MC_SCAN_BOOST_OFF);
-       }
-       switch (bw) {
-               case BANDWIDTH_8_MHZ:
-                       wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz);
-                       break;
-               case BANDWIDTH_7_MHZ:
-                       wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_7mhz);
-                       break;
-               case BANDWIDTH_6_MHZ:
-                       wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_6mhz);
-                       break;
-/*             case BANDWIDTH_5_MHZ:
-                       wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_5mhz);
-                       break;*/
-               case BANDWIDTH_AUTO:
-                       return -EOPNOTSUPP;
-               default:
-                       err("unknown bandwidth value (%d).",bw);
-                       return -EINVAL;
-       }
-       if (boost) {
-               u32 timeout = (rd(DIB3000MC_REG_BW_TIMOUT_MSB) << 16) +
-                       rd(DIB3000MC_REG_BW_TIMOUT_LSB);
-               timeout *= 85; timeout >>= 7;
-               wr(DIB3000MC_REG_BW_TIMOUT_MSB,(timeout >> 16) & 0xffff);
-               wr(DIB3000MC_REG_BW_TIMOUT_LSB,timeout & 0xffff);
+               dib3000mc_write_word(state, 51, (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0));
+               dib3000mc_write_word(state, 52, (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0));
        }
+
+    if (state->cfg->use_pwm3)
+               dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
+       else
+               dib3000mc_write_word(state, 245, 0);
+
+    dib3000mc_write_word(state, 1040, 0x3);
        return 0;
 }
 
-static int dib3000mc_set_adp_cfg(struct dib3000_state *state, fe_modulation_t con)
+static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
 {
-       switch (con) {
-               case QAM_64:
-                       wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[2]);
-                       break;
-               case QAM_16:
-                       wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[1]);
-                       break;
-               case QPSK:
-                       wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[0]);
-                       break;
-               case QAM_AUTO:
+       int    ret = 0;
+       u16 fifo_threshold = 1792;
+       u16 outreg = 0;
+       u16 outmode = 0;
+       u16 elecout = 1;
+       u16 smo_reg = dib3000mc_read_word(state, 206) & 0x0010; /* keep the pid_parse bit */
+
+       dprintk("-I-  Setting output mode for demod %p to %d\n",
+                       &state->demod, mode);
+
+       switch (mode) {
+               case OUTMODE_HIGH_Z:  // disable
+                       elecout = 0;
+                       break;
+               case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
+                       outmode = 0;
+                       break;
+               case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
+                       outmode = 1;
+                       break;
+               case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
+                       outmode = 2;
+                       break;
+               case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
+                       elecout = 3;
+                       /*ADDR @ 206 :
+                       P_smo_error_discard  [1;6:6] = 0
+                       P_smo_rs_discard     [1;5:5] = 0
+                       P_smo_pid_parse      [1;4:4] = 0
+                       P_smo_fifo_flush     [1;3:3] = 0
+                       P_smo_mode           [2;2:1] = 11
+                       P_smo_ovf_prot       [1;0:0] = 0
+                       */
+                       smo_reg |= 3 << 1;
+                       fifo_threshold = 512;
+                       outmode = 5;
+                       break;
+               case OUTMODE_DIVERSITY:
+                       outmode = 4;
+                       elecout = 1;
                        break;
                default:
-                       warn("unkown constellation.");
+                       dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
+                       outmode = 0;
                        break;
        }
-       return 0;
+
+       if ((state->cfg->output_mpeg2_in_188_bytes))
+               smo_reg |= (1 << 5); // P_smo_rs_discard     [1;5:5] = 1
+
+       outreg = dib3000mc_read_word(state, 244) & 0x07FF;
+       outreg |= (outmode << 11);
+       ret |= dib3000mc_write_word(state,  244, outreg);
+       ret |= dib3000mc_write_word(state,  206, smo_reg);   /*smo_ mode*/
+       ret |= dib3000mc_write_word(state,  207, fifo_threshold); /* synchronous fread */
+       ret |= dib3000mc_write_word(state, 1040, elecout);         /* P_out_cfg */
+       return ret;
 }
 
-static int dib3000mc_set_general_cfg(struct dib3000_state *state, struct dvb_frontend_parameters *fep, int *auto_val)
+static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw)
 {
-       struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
-       fe_code_rate_t fe_cr = FEC_NONE;
-       u8 fft=0, guard=0, qam=0, alpha=0, sel_hp=0, cr=0, hrch=0;
-       int seq;
+       struct dib3000mc_state *state = demod->demodulator_priv;
+       u16 bw_cfg[6] = { 0 };
+       u16 imp_bw_cfg[3] = { 0 };
+       u16 reg;
 
-       switch (ofdm->transmission_mode) {
-               case TRANSMISSION_MODE_2K: fft = DIB3000_TRANSMISSION_MODE_2K; break;
-               case TRANSMISSION_MODE_8K: fft = DIB3000_TRANSMISSION_MODE_8K; break;
-               case TRANSMISSION_MODE_AUTO: break;
-               default: return -EINVAL;
-       }
-       switch (ofdm->guard_interval) {
-               case GUARD_INTERVAL_1_32: guard = DIB3000_GUARD_TIME_1_32; break;
-               case GUARD_INTERVAL_1_16: guard = DIB3000_GUARD_TIME_1_16; break;
-               case GUARD_INTERVAL_1_8:  guard = DIB3000_GUARD_TIME_1_8; break;
-               case GUARD_INTERVAL_1_4:  guard = DIB3000_GUARD_TIME_1_4; break;
-               case GUARD_INTERVAL_AUTO: break;
-               default: return -EINVAL;
-       }
-       switch (ofdm->constellation) {
-               case QPSK:   qam = DIB3000_CONSTELLATION_QPSK; break;
-               case QAM_16: qam = DIB3000_CONSTELLATION_16QAM; break;
-               case QAM_64: qam = DIB3000_CONSTELLATION_64QAM; break;
-               case QAM_AUTO: break;
-               default: return -EINVAL;
-       }
-       switch (ofdm->hierarchy_information) {
-               case HIERARCHY_NONE: /* fall through */
-               case HIERARCHY_1: alpha = DIB3000_ALPHA_1; break;
-               case HIERARCHY_2: alpha = DIB3000_ALPHA_2; break;
-               case HIERARCHY_4: alpha = DIB3000_ALPHA_4; break;
-               case HIERARCHY_AUTO: break;
-               default: return -EINVAL;
-       }
-       if (ofdm->hierarchy_information == HIERARCHY_NONE) {
-               hrch   = DIB3000_HRCH_OFF;
-               sel_hp = DIB3000_SELECT_HP;
-               fe_cr  = ofdm->code_rate_HP;
-       } else if (ofdm->hierarchy_information != HIERARCHY_AUTO) {
-               hrch   = DIB3000_HRCH_ON;
-               sel_hp = DIB3000_SELECT_LP;
-               fe_cr  = ofdm->code_rate_LP;
-       }
-       switch (fe_cr) {
-               case FEC_1_2: cr = DIB3000_FEC_1_2; break;
-               case FEC_2_3: cr = DIB3000_FEC_2_3; break;
-               case FEC_3_4: cr = DIB3000_FEC_3_4; break;
-               case FEC_5_6: cr = DIB3000_FEC_5_6; break;
-               case FEC_7_8: cr = DIB3000_FEC_7_8; break;
-               case FEC_NONE: break;
-               case FEC_AUTO: break;
-               default: return -EINVAL;
-       }
+/* settings here are for 27.7MHz */
+       switch (bw) {
+               case BANDWIDTH_8_MHZ:
+                       bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
+                       imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
+                       break;
 
-       wr(DIB3000MC_REG_DEMOD_PARM,DIB3000MC_DEMOD_PARM(alpha,qam,guard,fft));
-       wr(DIB3000MC_REG_HRCH_PARM,DIB3000MC_HRCH_PARM(sel_hp,cr,hrch));
+               case BANDWIDTH_7_MHZ:
+                       bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
+                       imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
+                       break;
 
-       switch (fep->inversion) {
-               case INVERSION_OFF:
-                       wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF);
+               case BANDWIDTH_6_MHZ:
+                       bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
+                       imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
                        break;
-               case INVERSION_AUTO: /* fall through */
-               case INVERSION_ON:
-                       wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_ON);
+
+               case 255 /* BANDWIDTH_5_MHZ */:
+                       bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
+                       imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
                        break;
-               default:
-                       return -EINVAL;
+
+               default: return -EINVAL;
        }
 
-       seq = dib3000_seq
-               [ofdm->transmission_mode == TRANSMISSION_MODE_AUTO]
-               [ofdm->guard_interval == GUARD_INTERVAL_AUTO]
-               [fep->inversion == INVERSION_AUTO];
-
-       deb_setf("seq? %d\n", seq);
-       wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS(seq,1));
-       *auto_val = ofdm->constellation == QAM_AUTO ||
-                       ofdm->hierarchy_information == HIERARCHY_AUTO ||
-                       ofdm->guard_interval == GUARD_INTERVAL_AUTO ||
-                       ofdm->transmission_mode == TRANSMISSION_MODE_AUTO ||
-                       fe_cr == FEC_AUTO ||
-                       fep->inversion == INVERSION_AUTO;
-       return 0;
-}
+       for (reg = 6; reg < 12; reg++)
+               dib3000mc_write_word(state, reg, bw_cfg[reg - 6]);
+       dib3000mc_write_word(state, 12, 0x0000);
+       dib3000mc_write_word(state, 13, 0x03e8);
+       dib3000mc_write_word(state, 14, 0x0000);
+       dib3000mc_write_word(state, 15, 0x03f2);
+       dib3000mc_write_word(state, 16, 0x0001);
+       dib3000mc_write_word(state, 17, 0xb0d0);
+       // P_sec_len
+       dib3000mc_write_word(state, 18, 0x0393);
+       dib3000mc_write_word(state, 19, 0x8700);
 
-static int dib3000mc_get_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
-{
-       struct dib3000_state* state = fe->demodulator_priv;
-       struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
-       fe_code_rate_t *cr;
-       u16 tps_val,cr_val;
-       int inv_test1,inv_test2;
-       u32 dds_val, threshold = 0x1000000;
-
-       if (!(rd(DIB3000MC_REG_LOCK_507) & DIB3000MC_LOCK_507))
-               return 0;
-
-       dds_val = (rd(DIB3000MC_REG_DDS_FREQ_MSB) << 16) + rd(DIB3000MC_REG_DDS_FREQ_LSB);
-       deb_getf("DDS_FREQ: %6x\n",dds_val);
-       if (dds_val < threshold)
-               inv_test1 = 0;
-       else if (dds_val == threshold)
-               inv_test1 = 1;
-       else
-               inv_test1 = 2;
-
-       dds_val = (rd(DIB3000MC_REG_SET_DDS_FREQ_MSB) << 16) + rd(DIB3000MC_REG_SET_DDS_FREQ_LSB);
-       deb_getf("DDS_SET_FREQ: %6x\n",dds_val);
-       if (dds_val < threshold)
-               inv_test2 = 0;
-       else if (dds_val == threshold)
-               inv_test2 = 1;
-       else
-               inv_test2 = 2;
+       for (reg = 55; reg < 58; reg++)
+               dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
 
-       fep->inversion =
-               ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||
-               ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?
-               INVERSION_ON : INVERSION_OFF;
+       // Timing configuration
+       dib3000mc_set_timing(state, 0, bw, 0);
 
-       deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion);
+       return 0;
+}
 
-       fep->frequency = state->last_tuned_freq;
-       fep->u.ofdm.bandwidth= state->last_tuned_bw;
+static u16 impulse_noise_val[29] =
 
-       tps_val = rd(DIB3000MC_REG_TUNING_PARM);
+{
+       0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, 0x3ffe, 0x7f3,
+       0x2d94, 0x76, 0x53d, 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, 0x3feb, 0x7d2,
+       0x365e, 0x76, 0x48c, 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0000, 0xd
+};
 
-       switch (DIB3000MC_TP_QAM(tps_val)) {
-               case DIB3000_CONSTELLATION_QPSK:
-                       deb_getf("QPSK ");
-                       ofdm->constellation = QPSK;
-                       break;
-               case DIB3000_CONSTELLATION_16QAM:
-                       deb_getf("QAM16 ");
-                       ofdm->constellation = QAM_16;
-                       break;
-               case DIB3000_CONSTELLATION_64QAM:
-                       deb_getf("QAM64 ");
-                       ofdm->constellation = QAM_64;
-                       break;
-               default:
-                       err("Unexpected constellation returned by TPS (%d)", tps_val);
-                       break;
+static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, s16 nfft)
+{
+       u16 i;
+       for (i = 58; i < 87; i++)
+               dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
+
+       if (nfft == 1) {
+               dib3000mc_write_word(state, 58, 0x3b);
+               dib3000mc_write_word(state, 84, 0x00);
+               dib3000mc_write_word(state, 85, 0x8200);
        }
 
-       if (DIB3000MC_TP_HRCH(tps_val)) {
-               deb_getf("HRCH ON ");
-               cr = &ofdm->code_rate_LP;
-               ofdm->code_rate_HP = FEC_NONE;
-               switch (DIB3000MC_TP_ALPHA(tps_val)) {
-                       case DIB3000_ALPHA_0:
-                               deb_getf("HIERARCHY_NONE ");
-                               ofdm->hierarchy_information = HIERARCHY_NONE;
-                               break;
-                       case DIB3000_ALPHA_1:
-                               deb_getf("HIERARCHY_1 ");
-                               ofdm->hierarchy_information = HIERARCHY_1;
-                               break;
-                       case DIB3000_ALPHA_2:
-                               deb_getf("HIERARCHY_2 ");
-                               ofdm->hierarchy_information = HIERARCHY_2;
-                               break;
-                       case DIB3000_ALPHA_4:
-                               deb_getf("HIERARCHY_4 ");
-                               ofdm->hierarchy_information = HIERARCHY_4;
-                               break;
-                       default:
-                               err("Unexpected ALPHA value returned by TPS (%d)", tps_val);
-                               break;
-               }
-               cr_val = DIB3000MC_TP_FEC_CR_LP(tps_val);
+       dib3000mc_write_word(state, 34, 0x1294);
+       dib3000mc_write_word(state, 35, 0x1ff8);
+       if (mode == 1)
+               dib3000mc_write_word(state, 55, dib3000mc_read_word(state, 55) | (1 << 10));
+}
+
+static int dib3000mc_init(struct dvb_frontend *demod)
+{
+       struct dib3000mc_state *state = demod->demodulator_priv;
+       struct dibx000_agc_config *agc = state->cfg->agc;
+
+       // Restart Configuration
+       dib3000mc_write_word(state, 1027, 0x8000);
+       dib3000mc_write_word(state, 1027, 0x0000);
+
+       // power up the demod + mobility configuration
+       dib3000mc_write_word(state, 140, 0x0000);
+       dib3000mc_write_word(state, 1031, 0);
+
+       if (state->cfg->mobile_mode) {
+               dib3000mc_write_word(state, 139,  0x0000);
+               dib3000mc_write_word(state, 141,  0x0000);
+               dib3000mc_write_word(state, 175,  0x0002);
+               dib3000mc_write_word(state, 1032, 0x0000);
        } else {
-               deb_getf("HRCH OFF ");
-               cr = &ofdm->code_rate_HP;
-               ofdm->code_rate_LP = FEC_NONE;
-               ofdm->hierarchy_information = HIERARCHY_NONE;
-               cr_val = DIB3000MC_TP_FEC_CR_HP(tps_val);
+               dib3000mc_write_word(state, 139,  0x0001);
+               dib3000mc_write_word(state, 141,  0x0000);
+               dib3000mc_write_word(state, 175,  0x0000);
+               dib3000mc_write_word(state, 1032, 0x012C);
        }
+       dib3000mc_write_word(state, 1033, 0);
 
-       switch (cr_val) {
-               case DIB3000_FEC_1_2:
-                       deb_getf("FEC_1_2 ");
-                       *cr = FEC_1_2;
-                       break;
-               case DIB3000_FEC_2_3:
-                       deb_getf("FEC_2_3 ");
-                       *cr = FEC_2_3;
-                       break;
-               case DIB3000_FEC_3_4:
-                       deb_getf("FEC_3_4 ");
-                       *cr = FEC_3_4;
-                       break;
-               case DIB3000_FEC_5_6:
-                       deb_getf("FEC_5_6 ");
-                       *cr = FEC_4_5;
-                       break;
-               case DIB3000_FEC_7_8:
-                       deb_getf("FEC_7_8 ");
-                       *cr = FEC_7_8;
-                       break;
-               default:
-                       err("Unexpected FEC returned by TPS (%d)", tps_val);
-                       break;
-       }
+       // P_clk_cfg
+       dib3000mc_write_word(state, 1037, 12592);
 
-       switch (DIB3000MC_TP_GUARD(tps_val)) {
-               case DIB3000_GUARD_TIME_1_32:
-                       deb_getf("GUARD_INTERVAL_1_32 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_32;
-                       break;
-               case DIB3000_GUARD_TIME_1_16:
-                       deb_getf("GUARD_INTERVAL_1_16 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_16;
-                       break;
-               case DIB3000_GUARD_TIME_1_8:
-                       deb_getf("GUARD_INTERVAL_1_8 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_8;
-                       break;
-               case DIB3000_GUARD_TIME_1_4:
-                       deb_getf("GUARD_INTERVAL_1_4 ");
-                       ofdm->guard_interval = GUARD_INTERVAL_1_4;
-                       break;
-               default:
-                       err("Unexpected Guard Time returned by TPS (%d)", tps_val);
-                       break;
-       }
+       // other configurations
 
-       switch (DIB3000MC_TP_FFT(tps_val)) {
-               case DIB3000_TRANSMISSION_MODE_2K:
-                       deb_getf("TRANSMISSION_MODE_2K ");
-                       ofdm->transmission_mode = TRANSMISSION_MODE_2K;
-                       break;
-               case DIB3000_TRANSMISSION_MODE_8K:
-                       deb_getf("TRANSMISSION_MODE_8K ");
-                       ofdm->transmission_mode = TRANSMISSION_MODE_8K;
-                       break;
-               default:
-                       err("unexpected transmission mode return by TPS (%d)", tps_val);
-                       break;
-       }
-       deb_getf("\n");
+       // P_ctrl_sfreq
+       dib3000mc_write_word(state, 33, (5 << 0));
+       dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0));
+
+       // Phase noise control
+       // P_fft_phacor_inh, P_fft_phacor_cpe, P_fft_powrange
+       dib3000mc_write_word(state, 99, (1 << 9) | (0x20 << 0));
+
+       if (state->cfg->phase_noise_mode == 0)
+               dib3000mc_write_word(state, 111, 0x00);
+       else
+               dib3000mc_write_word(state, 111, 0x02);
+
+       // P_agc_global
+       dib3000mc_write_word(state, 50, 0x8000);
+
+       // agc setup misc
+       dib3000mc_setup_pwm3_state(state);
+
+       // P_agc_counter_lock
+       dib3000mc_write_word(state, 53, 0x87);
+       // P_agc_counter_unlock
+       dib3000mc_write_word(state, 54, 0x87);
+
+       /* agc */
+       dib3000mc_write_word(state, 36, state->cfg->max_time);
+       dib3000mc_write_word(state, 37, agc->setup);
+       dib3000mc_write_word(state, 38, state->cfg->pwm3_value);
+       dib3000mc_write_word(state, 39, state->cfg->ln_adc_level);
+
+       // set_agc_loop_Bw
+       dib3000mc_write_word(state, 40, 0x0179);
+       dib3000mc_write_word(state, 41, 0x03f0);
+
+       dib3000mc_write_word(state, 42, agc->agc1_max);
+       dib3000mc_write_word(state, 43, agc->agc1_min);
+       dib3000mc_write_word(state, 44, agc->agc2_max);
+       dib3000mc_write_word(state, 45, agc->agc2_min);
+       dib3000mc_write_word(state, 46, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
+       dib3000mc_write_word(state, 47, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+       dib3000mc_write_word(state, 48, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+       dib3000mc_write_word(state, 49, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+
+// Begin: TimeOut registers
+       // P_pha3_thres
+       dib3000mc_write_word(state, 110, 3277);
+       // P_timf_alpha = 6, P_corm_alpha = 6, P_corm_thres = 0x80
+       dib3000mc_write_word(state,  26, 0x6680);
+       // lock_mask0
+       dib3000mc_write_word(state, 1, 4);
+       // lock_mask1
+       dib3000mc_write_word(state, 2, 4);
+       // lock_mask2
+       dib3000mc_write_word(state, 3, 0x1000);
+       // P_search_maxtrial=1
+       dib3000mc_write_word(state, 5, 1);
+
+       dib3000mc_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ);
+
+       // div_lock_mask
+       dib3000mc_write_word(state,  4, 0x814);
+
+       dib3000mc_write_word(state, 21, (1 << 9) | 0x164);
+       dib3000mc_write_word(state, 22, 0x463d);
+
+       // Spurious rm cfg
+       // P_cspu_regul, P_cspu_win_cut
+       dib3000mc_write_word(state, 120, 0x200f);
+       // P_adp_selec_monit
+       dib3000mc_write_word(state, 134, 0);
+
+       // Fec cfg
+       dib3000mc_write_word(state, 195, 0x10);
+
+       // diversity register: P_dvsy_sync_wait..
+       dib3000mc_write_word(state, 180, 0x2FF0);
+
+       // Impulse noise configuration
+       dib3000mc_set_impulse_noise(state, 0, 1);
+
+       // output mode set-up
+       dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
+
+       /* close the i2c-gate */
+       dib3000mc_write_word(state, 769, (1 << 7) );
 
        return 0;
 }
 
-static int dib3000mc_set_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep, int tuner)
+static int dib3000mc_sleep(struct dvb_frontend *demod)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-       struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
-       int search_state,auto_val;
-       u16 val;
+       struct dib3000mc_state *state = demod->demodulator_priv;
 
-       if (tuner && fe->ops.tuner_ops.set_params) { /* initial call from dvb */
-               fe->ops.tuner_ops.set_params(fe, fep);
-               if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-
-               state->last_tuned_freq = fep->frequency;
-       //      if (!scanboost) {
-                       dib3000mc_set_timing(state,0,ofdm->transmission_mode,ofdm->bandwidth);
-                       dib3000mc_init_auto_scan(state, ofdm->bandwidth, 0);
-                       state->last_tuned_bw = ofdm->bandwidth;
-
-                       wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth);
-                       wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_AGC);
-                       wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF);
-
-                       /* Default cfg isi offset adp */
-                       wr_foreach(dib3000mc_reg_offset,dib3000mc_offset[0]);
-
-                       wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT | DIB3000MC_ISI_INHIBIT);
-                       dib3000mc_set_adp_cfg(state,ofdm->constellation);
-                       wr(DIB3000MC_REG_UNK_133,DIB3000MC_UNK_133);
-
-                       wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general);
-                       /* power smoothing */
-                       if (ofdm->bandwidth != BANDWIDTH_8_MHZ) {
-                               wr_foreach(dib3000mc_reg_bw,dib3000mc_bw[0]);
-                       } else {
-                               wr_foreach(dib3000mc_reg_bw,dib3000mc_bw[3]);
-                       }
-                       auto_val = 0;
-                       dib3000mc_set_general_cfg(state,fep,&auto_val);
-                       dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth);
-
-                       val = rd(DIB3000MC_REG_DEMOD_PARM);
-                       wr(DIB3000MC_REG_DEMOD_PARM,val|DIB3000MC_DEMOD_RST_DEMOD_ON);
-                       wr(DIB3000MC_REG_DEMOD_PARM,val);
-       //      }
-               msleep(70);
-
-               /* something has to be auto searched */
-               if (auto_val) {
-                       int as_count=0;
-
-                       deb_setf("autosearch enabled.\n");
-
-                       val = rd(DIB3000MC_REG_DEMOD_PARM);
-                       wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON);
-                       wr(DIB3000MC_REG_DEMOD_PARM,val);
-
-                       while ((search_state = dib3000_search_status(
-                                               rd(DIB3000MC_REG_AS_IRQ),1)) < 0 && as_count++ < 100)
-                               msleep(10);
-
-                       deb_info("search_state after autosearch %d after %d checks\n",search_state,as_count);
-
-                       if (search_state == 1) {
-                               struct dvb_frontend_parameters feps;
-                               if (dib3000mc_get_frontend(fe, &feps) == 0) {
-                                       deb_setf("reading tuning data from frontend succeeded.\n");
-                                       return dib3000mc_set_frontend(fe, &feps, 0);
-                               }
-                       }
-               } else {
-                       dib3000mc_set_impulse_noise(state,0,ofdm->transmission_mode,ofdm->bandwidth);
-                       wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE);
-                       dib3000mc_set_adp_cfg(state,ofdm->constellation);
-
-                       /* set_offset_cfg */
-                       wr_foreach(dib3000mc_reg_offset,
-                                       dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
-               }
-       } else { /* second call, after autosearch (fka: set_WithKnownParams) */
-//             dib3000mc_set_timing(state,1,ofdm->transmission_mode,ofdm->bandwidth);
-
-               auto_val = 0;
-               dib3000mc_set_general_cfg(state,fep,&auto_val);
-               if (auto_val)
-                       deb_info("auto_val is true, even though an auto search was already performed.\n");
-
-               dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth);
-
-               val = rd(DIB3000MC_REG_DEMOD_PARM);
-               wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON);
-               wr(DIB3000MC_REG_DEMOD_PARM,val);
+       dib3000mc_write_word(state, 1037, dib3000mc_read_word(state, 1037) | 0x0003);
+       dib3000mc_write_word(state, 1031, 0xFFFF);
+       dib3000mc_write_word(state, 1032, 0xFFFF);
+       dib3000mc_write_word(state, 1033, 0xFFF4);   // ****  Bin2
 
-               msleep(30);
+    return 0;
+}
 
-               wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE);
-                       dib3000mc_set_adp_cfg(state,ofdm->constellation);
-               wr_foreach(dib3000mc_reg_offset,
-                               dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
+static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
+{
+       u16 cfg[4] = { 0 },reg;
+       switch (qam) {
+               case 0:
+                       cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
+                       break;
+               case 1:
+                       cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
+                       break;
+               case 2:
+                       cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
+                       break;
        }
-       return 0;
+       for (reg = 129; reg < 133; reg++)
+               dib3000mc_write_word(state, reg, cfg[reg - 129]);
 }
 
-static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
+static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx000_ofdm_channel *chan, u16 seq)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       deb_info("init start\n");
-
-       state->timing_offset = 0;
-       state->timing_offset_comp_done = 0;
+       u16 tmp;
 
-       wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_CONFIG);
-       wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF);
-       wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_UP);
-       wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_PUP_MOBILE);
-       wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_UP);
-       wr(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_INIT);
+       dib3000mc_set_timing(state, chan->nfft, chan->Bw, 0);
 
-       wr(DIB3000MC_REG_RST_UNC,DIB3000MC_RST_UNC_OFF);
-       wr(DIB3000MC_REG_UNK_19,DIB3000MC_UNK_19);
+//     if (boost)
+//             dib3000mc_write_word(state, 100, (11 << 6) + 6);
+//     else
+               dib3000mc_write_word(state, 100, (16 << 6) + 9);
 
-       wr(33,5);
-       wr(36,81);
-       wr(DIB3000MC_REG_UNK_88,DIB3000MC_UNK_88);
+       dib3000mc_write_word(state, 1027, 0x0800);
+       dib3000mc_write_word(state, 1027, 0x0000);
 
-       wr(DIB3000MC_REG_UNK_99,DIB3000MC_UNK_99);
-       wr(DIB3000MC_REG_UNK_111,DIB3000MC_UNK_111_PH_N_MODE_0); /* phase noise algo off */
+       //Default cfg isi offset adp
+       dib3000mc_write_word(state, 26,  0x6680);
+       dib3000mc_write_word(state, 29,  0x1273);
+       dib3000mc_write_word(state, 33,       5);
+       dib3000mc_set_adp_cfg(state, 1);
+       dib3000mc_write_word(state, 133,  15564);
 
-       /* mobile mode - portable reception */
-       wr_foreach(dib3000mc_reg_mobile_mode,dib3000mc_mobile_mode[1]);
+       dib3000mc_write_word(state, 12 , 0x0);
+       dib3000mc_write_word(state, 13 , 0x3e8);
+       dib3000mc_write_word(state, 14 , 0x0);
+       dib3000mc_write_word(state, 15 , 0x3f2);
 
-/* TUNER_PANASONIC_ENV57H12D5: */
-       wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth);
-       wr_foreach(dib3000mc_reg_agc_bandwidth_general,dib3000mc_agc_bandwidth_general);
-       wr_foreach(dib3000mc_reg_agc,dib3000mc_agc_tuner[1]);
+       dib3000mc_write_word(state, 93,0);
+       dib3000mc_write_word(state, 94,0);
+       dib3000mc_write_word(state, 95,0);
+       dib3000mc_write_word(state, 96,0);
+       dib3000mc_write_word(state, 97,0);
+       dib3000mc_write_word(state, 98,0);
 
-       wr(DIB3000MC_REG_UNK_110,DIB3000MC_UNK_110);
-       wr(26,0x6680);
-       wr(DIB3000MC_REG_UNK_1,DIB3000MC_UNK_1);
-       wr(DIB3000MC_REG_UNK_2,DIB3000MC_UNK_2);
-       wr(DIB3000MC_REG_UNK_3,DIB3000MC_UNK_3);
-       wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS_DEFAULT);
+       dib3000mc_set_impulse_noise(state, 0, chan->nfft);
 
-       wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz);
-       wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general);
+       tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha;
+       dib3000mc_write_word(state, 0, tmp);
 
-       wr(DIB3000MC_REG_UNK_4,DIB3000MC_UNK_4);
+       dib3000mc_write_word(state, 5, seq);
 
-       wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF);
-       wr(DIB3000MC_REG_SET_DDS_FREQ_LSB,DIB3000MC_DDS_FREQ_LSB);
+       tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp);
+       if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp))
+               tmp |= chan->vit_code_rate_hp << 1;
+       else
+               tmp |= chan->vit_code_rate_lp << 1;
+       dib3000mc_write_word(state, 181, tmp);
 
-       dib3000mc_set_timing(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);
-//     wr_foreach(dib3000mc_reg_timing_freq,dib3000mc_timing_freq[3]);
+       // diversity synchro delay
+       tmp = dib3000mc_read_word(state, 180) & 0x000f;
+       tmp |= ((chan->nfft == 0) ? 64 : 256) * ((1 << (chan->guard)) * 3 / 2) << 4; // add 50% SFN margin
+       dib3000mc_write_word(state, 180, tmp);
 
-       wr(DIB3000MC_REG_UNK_120,DIB3000MC_UNK_120);
-       wr(DIB3000MC_REG_UNK_134,DIB3000MC_UNK_134);
-       wr(DIB3000MC_REG_FEC_CFG,DIB3000MC_FEC_CFG);
+       // restart demod
+       tmp = dib3000mc_read_word(state, 0);
+       dib3000mc_write_word(state, 0, tmp | (1 << 9));
+       dib3000mc_write_word(state, 0, tmp);
 
-       wr(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF);
+       msleep(30);
 
-       dib3000mc_set_impulse_noise(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ);
+       dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, chan->nfft);
+}
 
-/* output mode control, just the MPEG2_SLAVE */
-//     set_or(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_SLAVE);
-       wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_SLAVE);
-       wr(DIB3000MC_REG_SMO_MODE,DIB3000MC_SMO_MODE_SLAVE);
-       wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_SLAVE);
-       wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_SLAVE);
+static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *chan)
+{
+       struct dib3000mc_state *state = demod->demodulator_priv;
+       u16 reg;
+//     u32 val;
+       struct dibx000_ofdm_channel fchan;
 
-/* MPEG2_PARALLEL_CONTINUOUS_CLOCK
-       wr(DIB3000MC_REG_OUTMODE,
-               DIB3000MC_SET_OUTMODE(DIB3000MC_OM_PAR_CONT_CLK,
-                       rd(DIB3000MC_REG_OUTMODE)));
+       INIT_OFDM_CHANNEL(&fchan);
+       fchan = *chan;
 
-       wr(DIB3000MC_REG_SMO_MODE,
-                       DIB3000MC_SMO_MODE_DEFAULT |
-                       DIB3000MC_SMO_MODE_188);
 
-       wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_DEFAULT);
-       wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON);
-*/
+       /* a channel for autosearch */
+       reg = 0;
+       if (chan->nfft == -1 && chan->guard == -1) reg = 7;
+       if (chan->nfft == -1 && chan->guard != -1) reg = 2;
+       if (chan->nfft != -1 && chan->guard == -1) reg = 3;
 
-/* diversity */
-       wr(DIB3000MC_REG_DIVERSITY1,DIB3000MC_DIVERSITY1_DEFAULT);
-       wr(DIB3000MC_REG_DIVERSITY2,DIB3000MC_DIVERSITY2_DEFAULT);
+       fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2;
+       fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2;
+       fchan.vit_hrch = 0; fchan.vit_select_hp = 1;
 
-       set_and(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF);
+       dib3000mc_set_channel_cfg(state, &fchan, reg);
 
-       set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
+       reg = dib3000mc_read_word(state, 0);
+       dib3000mc_write_word(state, 0, reg | (1 << 8));
+       dib3000mc_write_word(state, 0, reg);
 
-       deb_info("init end\n");
        return 0;
 }
-static int dib3000mc_read_status(struct dvb_frontend* fe, fe_status_t *stat)
+
+static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-       u16 lock = rd(DIB3000MC_REG_LOCKING);
+       struct dib3000mc_state *state = demod->demodulator_priv;
+       u16 irq_pending = dib3000mc_read_word(state, 511);
 
-       *stat = 0;
-       if (DIB3000MC_AGC_LOCK(lock))
-               *stat |= FE_HAS_SIGNAL;
-       if (DIB3000MC_CARRIER_LOCK(lock))
-               *stat |= FE_HAS_CARRIER;
-       if (DIB3000MC_TPS_LOCK(lock))
-               *stat |= FE_HAS_VITERBI;
-       if (DIB3000MC_MPEG_SYNC_LOCK(lock))
-               *stat |= (FE_HAS_SYNC | FE_HAS_LOCK);
+       if (irq_pending & 0x1) // failed
+               return 1;
 
-       deb_stat("actual status is %2x fifo_level: %x,244: %x, 206: %x, 207: %x, 1040: %x\n",*stat,rd(510),rd(244),rd(206),rd(207),rd(1040));
+       if (irq_pending & 0x2) // succeeded
+               return 2;
 
-       return 0;
+       return 0; // still pending
 }
 
-static int dib3000mc_read_ber(struct dvb_frontend* fe, u32 *ber)
+static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-       *ber = ((rd(DIB3000MC_REG_BER_MSB) << 16) | rd(DIB3000MC_REG_BER_LSB));
+       struct dib3000mc_state *state = demod->demodulator_priv;
+
+       // ** configure demod **
+       dib3000mc_set_channel_cfg(state, ch, 0);
+
+       // activates isi
+       dib3000mc_write_word(state, 29, 0x1073);
+
+       dib3000mc_set_adp_cfg(state, (u8)ch->nqam);
+
+       if (ch->nfft == 1) {
+               dib3000mc_write_word(state, 26, 38528);
+               dib3000mc_write_word(state, 33, 8);
+       } else {
+               dib3000mc_write_word(state, 26, 30336);
+               dib3000mc_write_word(state, 33, 6);
+       }
+
+       // if (lock)
+       //      dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1);
+
        return 0;
 }
 
-static int dib3000mc_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+static int dib3000mc_demod_output_mode(struct dvb_frontend *demod, int mode)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-
-       *unc = rd(DIB3000MC_REG_PACKET_ERRORS);
-       return 0;
+       struct dib3000mc_state *state = demod->demodulator_priv;
+       return dib3000mc_set_output_mode(state, mode);
 }
 
-/* see dib3000mb.c for calculation comments */
-static int dib3000mc_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+static int dib3000mc_i2c_enumeration(struct dvb_frontend *demod[], int no_of_demods, u8 default_addr)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-       u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB);
-       *strength = (((val >> 6) & 0xff) << 8) + (val & 0x3f);
+       struct dib3000mc_state *st;
+       int k,ret=0;
+       u8 new_addr;
+
+       static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
+
+       for (k = no_of_demods-1; k >= 0; k--) {
+               st = demod[k]->demodulator_priv;
+
+               /* designated i2c address */
+               new_addr          = DIB3000MC_I2C_ADDRESS[k];
+
+               st->i2c_addr = new_addr;
+               if (dib3000mc_identify(st) != 0) {
+                       st->i2c_addr = default_addr;
+                       if (dib3000mc_identify(st) != 0) {
+                               dprintk("-E-  DiB3000P/MC #%d: not identified\n", k);
+                               return -EINVAL;
+                       }
+               }
+
+               /* turn on div_out */
+               dib3000mc_demod_output_mode(demod[k], OUTMODE_MPEG2_PAR_CONT_CLK);
+
+               // set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
+               ret |= dib3000mc_write_word(st, 1024, (new_addr << 3) | 0x1);
+               st->i2c_addr = new_addr;
+       }
+
+       for (k = 0; k < no_of_demods; k++) {
+               st = demod[k]->demodulator_priv;
+
+               ret |= dib3000mc_write_word(st, 1024, st->i2c_addr << 3);
 
-       deb_stat("signal: mantisse = %d, exponent = %d\n",(*strength >> 8) & 0xff, *strength & 0xff);
+               /* turn off data output */
+               dib3000mc_demod_output_mode(demod[k],OUTMODE_HIGH_Z);
+               dib3000mc_write_word(st, 769, (1 << 7) );
+
+       }
        return 0;
 }
 
-/* see dib3000mb.c for calculation comments */
-static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
+struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
-       u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB),
-               val2 = rd(DIB3000MC_REG_SIGNAL_NOISE_MSB);
-       u16 sig,noise;
+       struct dib3000mc_state *st = demod->demodulator_priv;
+       return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);
+}
 
-       sig =   (((val >> 6) & 0xff) << 8) + (val & 0x3f);
-       noise = (((val >> 4) & 0xff) << 8) + ((val & 0xf) << 2) + ((val2 >> 14) & 0x3);
-       if (noise == 0)
-               *snr = 0xffff;
-       else
-               *snr = (u16) sig/noise;
+EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
+
+static int dib3000mc_get_frontend(struct dvb_frontend* fe,
+                               struct dvb_frontend_parameters *fep)
+{
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       u16 tps = dib3000mc_read_word(state,458);
+
+       fep->inversion = INVERSION_AUTO;
+
+       fep->u.ofdm.bandwidth = state->current_bandwidth;
+
+       switch ((tps >> 8) & 0x1) {
+               case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
+               case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
+       }
+
+       switch (tps & 0x3) {
+               case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
+               case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
+               case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
+               case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+       }
+
+       switch ((tps >> 13) & 0x3) {
+               case 0: fep->u.ofdm.constellation = QPSK; break;
+               case 1: fep->u.ofdm.constellation = QAM_16; break;
+               case 2:
+               default: fep->u.ofdm.constellation = QAM_64; break;
+       }
+
+       /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
+       /* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
+
+       fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
+       switch ((tps >> 5) & 0x7) {
+               case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
+               case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
+               case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
+               case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
+               case 7:
+               default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+
+       }
+
+       switch ((tps >> 2) & 0x7) {
+               case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
+               case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
+               case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
+               case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
+               case 7:
+               default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+       }
 
-       deb_stat("signal: mantisse = %d, exponent = %d\n",(sig >> 8) & 0xff, sig & 0xff);
-       deb_stat("noise:  mantisse = %d, exponent = %d\n",(noise >> 8) & 0xff, noise & 0xff);
-       deb_stat("snr: %d\n",*snr);
        return 0;
 }
 
-static int dib3000mc_sleep(struct dvb_frontend* fe)
+static int dib3000mc_set_frontend(struct dvb_frontend* fe,
+                               struct dvb_frontend_parameters *fep)
 {
-       struct dib3000_state* state = fe->demodulator_priv;
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       struct dibx000_ofdm_channel ch;
 
-       set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_PWR_DOWN);
-       wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_DOWN);
-       wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_POWER_DOWN);
-       wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_DOWN);
-       return 0;
+       INIT_OFDM_CHANNEL(&ch);
+       FEP2DIB(fep,&ch);
+
+       state->current_bandwidth = fep->u.ofdm.bandwidth;
+       dib3000mc_set_bandwidth(fe, fep->u.ofdm.bandwidth);
+
+       if (fe->ops.tuner_ops.set_params) {
+               fe->ops.tuner_ops.set_params(fe, fep);
+               msleep(100);
+       }
+
+       if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
+               fep->u.ofdm.guard_interval    == GUARD_INTERVAL_AUTO ||
+               fep->u.ofdm.constellation     == QAM_AUTO ||
+               fep->u.ofdm.code_rate_HP      == FEC_AUTO) {
+               int i = 100, found;
+
+               dib3000mc_autosearch_start(fe, &ch);
+               do {
+                       msleep(1);
+                       found = dib3000mc_autosearch_is_irq(fe);
+               } while (found == 0 && i--);
+
+               dprintk("autosearch returns: %d\n",found);
+               if (found == 0 || found == 1)
+                       return 0; // no channel found
+
+               dib3000mc_get_frontend(fe, fep);
+               FEP2DIB(fep,&ch);
+       }
+
+       /* make this a config parameter */
+       dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+
+       return dib3000mc_tune(fe, &ch);
 }
 
-static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
 {
-       tune->min_delay_ms = 1000;
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       u16 lock = dib3000mc_read_word(state, 509);
+
+       *stat = 0;
+
+       if (lock & 0x8000)
+               *stat |= FE_HAS_SIGNAL;
+       if (lock & 0x3000)
+               *stat |= FE_HAS_CARRIER;
+       if (lock & 0x0100)
+               *stat |= FE_HAS_VITERBI;
+       if (lock & 0x0010)
+               *stat |= FE_HAS_SYNC;
+       if (lock & 0x0008)
+               *stat |= FE_HAS_LOCK;
+
        return 0;
 }
 
-static int dib3000mc_fe_init_nonmobile(struct dvb_frontend* fe)
+static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
-       return dib3000mc_fe_init(fe, 0);
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       *ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501);
+       return 0;
 }
 
-static int dib3000mc_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep)
+static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
 {
-       return dib3000mc_set_frontend(fe, fep, 1);
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       *unc = dib3000mc_read_word(state, 508);
+       return 0;
 }
 
-static void dib3000mc_release(struct dvb_frontend* fe)
+static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       kfree(state);
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       u16 val = dib3000mc_read_word(state, 392);
+       *strength = 65535 - val;
+       return 0;
 }
 
-/* pid filter and transfer stuff */
-static int dib3000mc_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)
+static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);
-       wr(index+DIB3000MC_REG_FIRST_PID,pid);
+       *snr = 0x0000;
        return 0;
 }
 
-static int dib3000mc_fifo_control(struct dvb_frontend *fe, int onoff)
+static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       u16 tmp = rd(DIB3000MC_REG_SMO_MODE);
-
-       deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");
-
-       if (onoff) {
-               deb_xfer("%d %x\n",tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH);
-               wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH);
-       } else {
-               deb_xfer("%d %x\n",tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH,tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH);
-               wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH);
-       }
+       tune->min_delay_ms = 1000;
        return 0;
 }
 
-static int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
+static void dib3000mc_release(struct dvb_frontend *fe)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       u16 tmp = rd(DIB3000MC_REG_SMO_MODE);
-
-       deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");
-
-       if (onoff) {
-               wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_PID_PARSE);
-       } else {
-               wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_NO_PID_PARSE);
-       }
-       return 0;
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       dibx000_exit_i2c_master(&state->i2c_master);
+       kfree(state);
 }
 
-static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)
+int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff)
 {
-       struct dib3000_state *state = fe->demodulator_priv;
-       if (onoff) {
-               wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));
-       } else {
-               wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr));
-       }
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       dib3000mc_write_word(state, 212 + index,  onoff ? (1 << 13) | pid : 0);
        return 0;
 }
+EXPORT_SYMBOL(dib3000mc_pid_control);
 
-static int dib3000mc_demod_init(struct dib3000_state *state)
+int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
 {
-       u16 default_addr = 0x0a;
-       /* first init */
-       if (state->config.demod_address != default_addr) {
-               deb_info("initializing the demod the first time. Setting demod addr to 0x%x\n",default_addr);
-               wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON);
-               wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_PAR_CONT_CLK);
-
-               wr(DIB3000MC_REG_RST_I2C_ADDR,
-                       DIB3000MC_DEMOD_ADDR(default_addr) |
-                       DIB3000MC_DEMOD_ADDR_ON);
-
-               state->config.demod_address = default_addr;
-
-               wr(DIB3000MC_REG_RST_I2C_ADDR,
-                       DIB3000MC_DEMOD_ADDR(default_addr));
-       } else
-               deb_info("demod is already initialized. Demod addr: 0x%x\n",state->config.demod_address);
-       return 0;
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       u16 tmp = dib3000mc_read_word(state, 206) & ~(1 << 4);
+       tmp |= (onoff << 4);
+       return dib3000mc_write_word(state, 206, tmp);
 }
+EXPORT_SYMBOL(dib3000mc_pid_parse);
 
+void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
+{
+       struct dib3000mc_state *state = fe->demodulator_priv;
+       state->cfg = cfg;
+}
+EXPORT_SYMBOL(dib3000mc_set_config);
 
 static struct dvb_frontend_ops dib3000mc_ops;
 
-struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
-                                     struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8        default_addr,                           u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[])
 {
-       struct dib3000_state* state = NULL;
-       u16 devid;
+       struct dib3000mc_state *st;
+       int k, num=0;
 
-       /* allocate memory for the internal state */
-       state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);
-       if (state == NULL)
-               goto error;
+       if (no_of_demods < 1)
+               return -EINVAL;
 
-       /* setup the state */
-       state->i2c = i2c;
-       memcpy(&state->config,config,sizeof(struct dib3000_config));
+       for (k = 0; k < no_of_demods; k++) {
+               st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
+               if (st == NULL)
+                       goto error;
 
-       /* check for the correct demod */
-       if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
-               goto error;
+               num++;
 
-       devid = rd(DIB3000_REG_DEVICE_ID);
-       if (devid != DIB3000MC_DEVICE_ID && devid != DIB3000P_DEVICE_ID)
-               goto error;
+               st->cfg = &cfg[k];
+       //      st->gpio_val = cfg[k].gpio_val;
+       //      st->gpio_dir = cfg[k].gpio_dir;
+               st->i2c_adap = i2c_adap;
 
-       switch (devid) {
-               case DIB3000MC_DEVICE_ID:
-                       info("Found a DiBcom 3000M-C, interesting...");
-                       break;
-               case DIB3000P_DEVICE_ID:
-                       info("Found a DiBcom 3000P.");
-                       break;
-       }
+               demod[k]           = &st->demod;
+               demod[k]->demodulator_priv     = st;
+               memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
 
-       /* create dvb_frontend */
-       memcpy(&state->frontend.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
-       state->frontend.demodulator_priv = state;
+//             INIT_COMPONENT_REGISTER_ACCESS(&st->register_access, 12, 16, dib7000p_register_read, dib7000p_register_write, st);
+//             demod[k]->register_access = &st->register_access;
+       }
 
-       /* set the xfer operations */
-       xfer_ops->pid_parse = dib3000mc_pid_parse;
-       xfer_ops->fifo_ctrl = dib3000mc_fifo_control;
-       xfer_ops->pid_ctrl = dib3000mc_pid_control;
-       xfer_ops->tuner_pass_ctrl = dib3000mc_tuner_pass_ctrl;
+       if (do_i2c_enum) {
+               if (dib3000mc_i2c_enumeration(demod,no_of_demods,default_addr) != 0)
+                       goto error;
+       } else {
+               st = demod[0]->demodulator_priv;
+               st->i2c_addr = default_addr;
+               if (dib3000mc_identify(st) != 0)
+                       goto error;
+       }
 
-       dib3000mc_demod_init(state);
+       for (k = 0; k < num; k++) {
+               st = demod[k]->demodulator_priv;
+               dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
+       }
 
-       return &state->frontend;
+       return 0;
 
 error:
-       kfree(state);
-       return NULL;
+       for (k = 0; k < num; k++) {
+               kfree(demod[k]->demodulator_priv);
+               demod[k] = NULL;
+       }
+       return -EINVAL;
 }
+
 EXPORT_SYMBOL(dib3000mc_attach);
 
 static struct dvb_frontend_ops dib3000mc_ops = {
-
        .info = {
-               .name                   = "DiBcom 3000P/M-C DVB-T",
-               .type                   = FE_OFDM,
-               .frequency_min          = 44250000,
-               .frequency_max          = 867250000,
-               .frequency_stepsize     = 62500,
+               .name = "DiBcom 3000MC/P",
+               .type = FE_OFDM,
+               .frequency_min      = 44250000,
+               .frequency_max      = 867250000,
+               .frequency_stepsize = 62500,
                .caps = FE_CAN_INVERSION_AUTO |
-                               FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-                               FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-                               FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-                               FE_CAN_TRANSMISSION_MODE_AUTO |
-                               FE_CAN_GUARD_INTERVAL_AUTO |
-                               FE_CAN_RECOVER |
-                               FE_CAN_HIERARCHY_AUTO,
+                       FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+                       FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+                       FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+                       FE_CAN_TRANSMISSION_MODE_AUTO |
+                       FE_CAN_GUARD_INTERVAL_AUTO |
+                       FE_CAN_RECOVER |
+                       FE_CAN_HIERARCHY_AUTO,
        },
 
-       .release = dib3000mc_release,
+       .release              = dib3000mc_release,
 
-       .init = dib3000mc_fe_init_nonmobile,
-       .sleep = dib3000mc_sleep,
+       .init                 = dib3000mc_init,
+       .sleep                = dib3000mc_sleep,
 
-       .set_frontend = dib3000mc_set_frontend_and_tuner,
-       .get_frontend = dib3000mc_get_frontend,
-       .get_tune_settings = dib3000mc_fe_get_tune_settings,
+       .set_frontend         = dib3000mc_set_frontend,
+       .get_tune_settings    = dib3000mc_fe_get_tune_settings,
+       .get_frontend         = dib3000mc_get_frontend,
 
-       .read_status = dib3000mc_read_status,
-       .read_ber = dib3000mc_read_ber,
+       .read_status          = dib3000mc_read_status,
+       .read_ber             = dib3000mc_read_ber,
        .read_signal_strength = dib3000mc_read_signal_strength,
-       .read_snr = dib3000mc_read_snr,
-       .read_ucblocks = dib3000mc_read_unc_blocks,
+       .read_snr             = dib3000mc_read_snr,
+       .read_ucblocks        = dib3000mc_read_unc_blocks,
 };
 
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h
new file mode 100644 (file)
index 0000000..fd0b2e7
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Driver for DiBcom DiB3000MC/P-demodulator.
+ *
+ * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher\@desy.de)
+ *
+ * This code is partially based on the previous dib3000mc.c .
+ *
+ * This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ */
+#ifndef DIB3000MC_H
+#define DIB3000MC_H
+
+#include "dibx000_common.h"
+
+struct dib3000mc_config {
+       struct dibx000_agc_config *agc;
+
+       u8 phase_noise_mode;
+       u8 impulse_noise_mode;
+
+       u8  pwm3_inversion;
+       u8  use_pwm3;
+       u16 pwm3_value;
+
+       u16 max_time;
+       u16 ln_adc_level;
+
+       u8 mobile_mode;
+
+       u8 output_mpeg2_in_188_bytes;
+};
+
+#define DEFAULT_DIB3000MC_I2C_ADDRESS 16
+#define DEFAULT_DIB3000P_I2C_ADDRESS  24
+
+#if defined(CONFIG_DVB_DIB3000MC) || defined(CONFIG_DVB_DIB3000MC_MODULE)
+extern int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr,
+    u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[]);
+#else
+static inline struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
+                                            struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_DIB3000MC
+
+extern struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating);
+
+extern int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff);
+extern int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff);
+
+extern void dib3000mc_set_config(struct dvb_frontend *, struct dib3000mc_config *);
+
+#endif
diff --git a/drivers/media/dvb/frontends/dib3000mc_priv.h b/drivers/media/dvb/frontends/dib3000mc_priv.h
deleted file mode 100644 (file)
index 2930aac..0000000
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * dib3000mc_priv.h
- *
- * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation, version 2.
- *
- * for more information see dib3000mc.c .
- */
-
-#ifndef __DIB3000MC_PRIV_H__
-#define __DIB3000MC_PRIV_H__
-
-/*
- * Demodulator parameters
- * reg: 0  1 1  1 11 11 111
- *         | |  |  |  |  |
- *         | |  |  |  |  +-- alpha (000=0, 001=1, 010=2, 100=4)
- *         | |  |  |  +----- constellation (00=QPSK, 01=16QAM, 10=64QAM)
- *         | |  |  +-------- guard (00=1/32, 01=1/16, 10=1/8, 11=1/4)
- *         | |  +----------- transmission mode (0=2k, 1=8k)
- *         | |
- *         | +-------------- restart autosearch for parameters
- *         +---------------- restart the demodulator
- * reg: 181      1 111 1
- *               |  |  |
- *               |  |  +- FEC applies for HP or LP (0=LP, 1=HP)
- *               |  +---- FEC rate (001=1/2, 010=2/3, 011=3/4, 101=5/6, 111=7/8)
- *               +------- hierarchy on (0=no, 1=yes)
- */
-
-/* demodulator tuning parameter and restart options */
-#define DIB3000MC_REG_DEMOD_PARM               (     0)
-#define DIB3000MC_DEMOD_PARM(a,c,g,t)  ( \
-                (0x7 & a) | \
-               ((0x3 & c) << 3) | \
-               ((0x3 & g) << 5) | \
-               ((0x1 & t) << 7) )
-#define DIB3000MC_DEMOD_RST_AUTO_SRCH_ON       (1 << 8)
-#define DIB3000MC_DEMOD_RST_AUTO_SRCH_OFF      (0 << 8)
-#define DIB3000MC_DEMOD_RST_DEMOD_ON           (1 << 9)
-#define DIB3000MC_DEMOD_RST_DEMOD_OFF          (0 << 9)
-
-/* register for hierarchy parameters */
-#define DIB3000MC_REG_HRCH_PARM                        (   181)
-#define DIB3000MC_HRCH_PARM(s,f,h)             ( \
-                (0x1 & s) | \
-               ((0x7 & f) << 1) | \
-               ((0x1 & h) << 4) )
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_1                            (     1)
-#define DIB3000MC_UNK_1                                        (  0x04)
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_2                            (     2)
-#define DIB3000MC_UNK_2                                        (  0x04)
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_3                            (     3)
-#define DIB3000MC_UNK_3                                        (0x1000)
-
-#define DIB3000MC_REG_UNK_4                            (     4)
-#define DIB3000MC_UNK_4                                        (0x0814)
-
-/* timeout ??? */
-#define DIB3000MC_REG_SEQ_TPS                  (     5)
-#define DIB3000MC_SEQ_TPS_DEFAULT              (     1)
-#define DIB3000MC_SEQ_TPS(s,t)                 ( \
-               ((s & 0x0f) << 4) | \
-               ((t & 0x01) << 8) )
-#define DIB3000MC_IS_TPS(v)                            ((v << 8) & 0x1)
-#define DIB3000MC_IS_AS(v)                             ((v >> 4) & 0xf)
-
-/* parameters for the bandwidth */
-#define DIB3000MC_REG_BW_TIMOUT_MSB            (     6)
-#define DIB3000MC_REG_BW_TIMOUT_LSB            (     7)
-
-static u16 dib3000mc_reg_bandwidth[] = { 6,7,8,9,10,11,16,17 };
-
-/*static u16 dib3000mc_bandwidth_5mhz[] =
-       { 0x28, 0x9380, 0x87, 0x4100, 0x2a4, 0x4500, 0x1, 0xb0d0 };*/
-
-static u16 dib3000mc_bandwidth_6mhz[] =
-       { 0x21, 0xd040, 0x70, 0xb62b, 0x233, 0x8ed5, 0x1, 0xb0d0 };
-
-static u16 dib3000mc_bandwidth_7mhz[] =
-       { 0x1c, 0xfba5, 0x60, 0x9c25, 0x1e3, 0x0cb7, 0x1, 0xb0d0 };
-
-static u16 dib3000mc_bandwidth_8mhz[] =
-       { 0x19, 0x5c30, 0x54, 0x88a0, 0x1a6, 0xab20, 0x1, 0xb0d0 };
-
-static u16 dib3000mc_reg_bandwidth_general[] = { 12,13,14,15 };
-static u16 dib3000mc_bandwidth_general[] = { 0x0000, 0x03e8, 0x0000, 0x03f2 };
-
-/* lock mask */
-#define DIB3000MC_REG_LOCK_MASK                        (    15)
-#define DIB3000MC_ACTIVATE_LOCK_MASK   (0x0800)
-
-/* reset the uncorrected packet count (??? do it 5 times) */
-#define DIB3000MC_REG_RST_UNC                  (    18)
-#define DIB3000MC_RST_UNC_ON                   (     1)
-#define DIB3000MC_RST_UNC_OFF                  (     0)
-
-#define DIB3000MC_REG_UNK_19                   (    19)
-#define DIB3000MC_UNK_19                               (     0)
-
-/* DDS frequency value (IF position) and inversion bit */
-#define DIB3000MC_REG_INVERSION                        (    21)
-#define DIB3000MC_REG_SET_DDS_FREQ_MSB (    21)
-#define DIB3000MC_DDS_FREQ_MSB_INV_OFF (0x0164)
-#define DIB3000MC_DDS_FREQ_MSB_INV_ON  (0x0364)
-
-#define DIB3000MC_REG_SET_DDS_FREQ_LSB (    22)
-#define DIB3000MC_DDS_FREQ_LSB                 (0x463d)
-
-/* timing frequencies setting */
-#define DIB3000MC_REG_TIMING_FREQ_MSB  (    23)
-#define DIB3000MC_REG_TIMING_FREQ_LSB  (    24)
-#define DIB3000MC_CLOCK_REF                            (0x151fd1)
-
-//static u16 dib3000mc_reg_timing_freq[] = { 23,24 };
-
-//static u16 dib3000mc_timing_freq[][2] = {
-//     { 0x69, 0x9f18 }, /* 5 MHz */
-//     { 0x7e ,0xbee9 }, /* 6 MHz */
-//     { 0x93 ,0xdebb }, /* 7 MHz */
-//     { 0xa8 ,0xfe8c }, /* 8 MHz */
-//};
-
-/* timeout ??? */
-static u16 dib3000mc_reg_offset[] = { 26,33 };
-
-static u16 dib3000mc_offset[][2] = {
-       { 26240, 5 }, /* default */
-       { 30336, 6 }, /* 8K */
-       { 38528, 8 }, /* 2K */
-};
-
-#define DIB3000MC_REG_ISI                              (    29)
-#define DIB3000MC_ISI_DEFAULT                  (0x1073)
-#define DIB3000MC_ISI_ACTIVATE                 (0x0000)
-#define DIB3000MC_ISI_INHIBIT                  (0x0200)
-
-/* impulse noise control */
-static u16 dib3000mc_reg_imp_noise_ctl[] = { 34,35 };
-
-static u16 dib3000mc_imp_noise_ctl[][2] = {
-       { 0x1294, 0x1ff8 }, /* mode 0 */
-       { 0x1294, 0x1ff8 }, /* mode 1 */
-       { 0x1294, 0x1ff8 }, /* mode 2 */
-       { 0x1294, 0x1ff8 }, /* mode 3 */
-       { 0x1294, 0x1ff8 }, /* mode 4 */
-};
-
-/* AGC registers */
-static u16 dib3000mc_reg_agc[] = {
-       36,37,38,39,42,43,44,45,46,47,48,49
-};
-
-static u16 dib3000mc_agc_tuner[][12] = {
-       {       0x0051, 0x301d, 0x0000, 0x1cc7, 0xcf5c, 0x6666,
-               0xbae1, 0xa148, 0x3b5e, 0x3c1c, 0x001a, 0x2019
-       }, /* TUNER_PANASONIC_ENV77H04D5, */
-
-       {       0x0051, 0x301d, 0x0000, 0x1cc7, 0xdc29, 0x570a,
-               0xbae1, 0x8ccd, 0x3b6d, 0x551d, 0x000a, 0x951e
-       }, /* TUNER_PANASONIC_ENV57H13D5, TUNER_PANASONIC_ENV57H12D5 */
-
-       {       0x0051, 0x301d, 0x0000, 0x1cc7, 0xffff, 0xffff,
-               0xffff, 0x0000, 0xfdfd, 0x4040, 0x00fd, 0x4040
-       }, /* TUNER_SAMSUNG_DTOS333IH102, TUNER_RFAGCIN_UNKNOWN */
-
-       {       0x0196, 0x301d, 0x0000, 0x1cc7, 0xbd71, 0x5c29,
-               0xb5c3, 0x6148, 0x6569, 0x5127, 0x0033, 0x3537
-       }, /* TUNER_PROVIDER_X */
-       /* TODO TUNER_PANASONIC_ENV57H10D8, TUNER_PANASONIC_ENV57H11D8 */
-};
-
-/* AGC loop bandwidth */
-static u16 dib3000mc_reg_agc_bandwidth[] = { 40,41 };
-static u16 dib3000mc_agc_bandwidth[]  = { 0x119,0x330 };
-
-static u16 dib3000mc_reg_agc_bandwidth_general[] = { 50,51,52,53,54 };
-static u16 dib3000mc_agc_bandwidth_general[] =
-       { 0x8000, 0x91ca, 0x01ba, 0x0087, 0x0087 };
-
-#define DIB3000MC_REG_IMP_NOISE_55             (    55)
-#define DIB3000MC_IMP_NEW_ALGO(w)              (w | (1<<10))
-
-/* Impulse noise params */
-static u16 dib3000mc_reg_impulse_noise[] = { 55,56,57 };
-static u16 dib3000mc_impluse_noise[][3] = {
-       { 0x489, 0x89, 0x72 }, /* 5 MHz */
-       { 0x4a5, 0xa5, 0x89 }, /* 6 MHz */
-       { 0x4c0, 0xc0, 0xa0 }, /* 7 MHz */
-       { 0x4db, 0xdb, 0xb7 }, /* 8 Mhz */
-};
-
-static u16 dib3000mc_reg_fft[] = {
-       58,59,60,61,62,63,64,65,66,67,68,69,
-       70,71,72,73,74,75,76,77,78,79,80,81,
-       82,83,84,85,86
-};
-
-static u16 dib3000mc_fft_modes[][29] = {
-       {       0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c,
-               0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d,
-               0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3,
-               0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
-               0x3ffe, 0x5b3, 0x3feb, 0x76,   0x0, 0xd
-       }, /* fft mode 0 */
-       {       0x3b, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c,
-               0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d,
-               0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3,
-               0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
-               0x3ffe, 0x5b3, 0x3feb, 0x0,  0x8200, 0xd
-       }, /* fft mode 1 */
-};
-
-#define DIB3000MC_REG_UNK_88                   (    88)
-#define DIB3000MC_UNK_88                               (0x0410)
-
-static u16 dib3000mc_reg_bw[] = { 93,94,95,96,97,98 };
-static u16 dib3000mc_bw[][6] = {
-       { 0,0,0,0,0,0 }, /* 5 MHz */
-       { 0,0,0,0,0,0 }, /* 6 MHz */
-       { 0,0,0,0,0,0 }, /* 7 MHz */
-       { 0x20, 0x21, 0x20, 0x23, 0x20, 0x27 }, /* 8 MHz */
-};
-
-
-/* phase noise control */
-#define DIB3000MC_REG_UNK_99                   (    99)
-#define DIB3000MC_UNK_99                               (0x0220)
-
-#define DIB3000MC_REG_SCAN_BOOST               (   100)
-#define DIB3000MC_SCAN_BOOST_ON                        ((11 << 6) + 6)
-#define DIB3000MC_SCAN_BOOST_OFF               ((16 << 6) + 9)
-
-/* timeout ??? */
-#define DIB3000MC_REG_UNK_110                  (   110)
-#define DIB3000MC_UNK_110                              (  3277)
-
-#define DIB3000MC_REG_UNK_111                  (   111)
-#define DIB3000MC_UNK_111_PH_N_MODE_0  (     0)
-#define DIB3000MC_UNK_111_PH_N_MODE_1  (1 << 1)
-
-/* superious rm config */
-#define DIB3000MC_REG_UNK_120                  (   120)
-#define DIB3000MC_UNK_120                              (  8207)
-
-#define DIB3000MC_REG_UNK_133                  (   133)
-#define DIB3000MC_UNK_133                              ( 15564)
-
-#define DIB3000MC_REG_UNK_134                  (   134)
-#define DIB3000MC_UNK_134                              (     0)
-
-/* adapter config for constellation */
-static u16 dib3000mc_reg_adp_cfg[] = { 129, 130, 131, 132 };
-
-static u16 dib3000mc_adp_cfg[][4] = {
-       { 0x99a, 0x7fae, 0x333, 0x7ff0 }, /* QPSK  */
-       { 0x23d, 0x7fdf, 0x0a4, 0x7ff0 }, /* 16-QAM */
-       { 0x148, 0x7ff0, 0x0a4, 0x7ff8 }, /* 64-QAM */
-};
-
-static u16 dib3000mc_reg_mobile_mode[] = { 139, 140, 141, 175, 1032 };
-
-static u16 dib3000mc_mobile_mode[][5] = {
-       { 0x01, 0x0, 0x0, 0x00, 0x12c }, /* fixed */
-       { 0x01, 0x0, 0x0, 0x00, 0x12c }, /* portable */
-       { 0x00, 0x0, 0x0, 0x02, 0x000 }, /* mobile */
-       { 0x00, 0x0, 0x0, 0x02, 0x000 }, /* auto */
-};
-
-#define DIB3000MC_REG_DIVERSITY1               (   177)
-#define DIB3000MC_DIVERSITY1_DEFAULT   (     1)
-
-#define DIB3000MC_REG_DIVERSITY2               (   178)
-#define DIB3000MC_DIVERSITY2_DEFAULT   (     1)
-
-#define DIB3000MC_REG_DIVERSITY3               (   180)
-#define DIB3000MC_DIVERSITY3_IN_OFF            (0xfff0)
-#define DIB3000MC_DIVERSITY3_IN_ON             (0xfff6)
-
-#define DIB3000MC_REG_FEC_CFG                  (   195)
-#define DIB3000MC_FEC_CFG                              (  0x10)
-
-/*
- * reg 206, output mode
- *              1111 1111
- *              |||| ||||
- *              |||| |||+- unk
- *              |||| ||+-- unk
- *              |||| |+--- unk (on by default)
- *              |||| +---- fifo_ctrl (1 = inhibit (flushed), 0 = active (unflushed))
- *              |||+------ pid_parse (1 = enabled, 0 = disabled)
- *              ||+------- outp_188  (1 = TS packet size 188, 0 = packet size 204)
- *              |+-------- unk
- *              +--------- unk
- */
-
-#define DIB3000MC_REG_SMO_MODE                 (   206)
-#define DIB3000MC_SMO_MODE_DEFAULT             (1 << 2)
-#define DIB3000MC_SMO_MODE_FIFO_FLUSH  (1 << 3)
-#define DIB3000MC_SMO_MODE_FIFO_UNFLUSH        (0xfff7)
-#define DIB3000MC_SMO_MODE_PID_PARSE   (1 << 4)
-#define DIB3000MC_SMO_MODE_NO_PID_PARSE        (0xffef)
-#define DIB3000MC_SMO_MODE_188                 (1 << 5)
-#define DIB3000MC_SMO_MODE_SLAVE               (DIB3000MC_SMO_MODE_DEFAULT | \
-                       DIB3000MC_SMO_MODE_188 | DIB3000MC_SMO_MODE_PID_PARSE | (1<<1))
-
-#define DIB3000MC_REG_FIFO_THRESHOLD   (   207)
-#define DIB3000MC_FIFO_THRESHOLD_DEFAULT       (  1792)
-#define DIB3000MC_FIFO_THRESHOLD_SLAVE (   512)
-/*
- * pidfilter
- * it is not a hardware pidfilter but a filter which drops all pids
- * except the ones set. When connected to USB1.1 bandwidth this is important.
- * DiB3000P/M-C can filter up to 32 PIDs
- */
-#define DIB3000MC_REG_FIRST_PID                        (   212)
-#define DIB3000MC_NUM_PIDS                             (    32)
-
-#define DIB3000MC_REG_OUTMODE                  (   244)
-#define DIB3000MC_OM_PARALLEL_GATED_CLK        (     0)
-#define DIB3000MC_OM_PAR_CONT_CLK              (1 << 11)
-#define DIB3000MC_OM_SERIAL                            (2 << 11)
-#define DIB3000MC_OM_DIVOUT_ON                 (4 << 11)
-#define DIB3000MC_OM_SLAVE                             (DIB3000MC_OM_DIVOUT_ON | DIB3000MC_OM_PAR_CONT_CLK)
-
-#define DIB3000MC_REG_RF_POWER                 (   392)
-
-#define DIB3000MC_REG_FFT_POSITION             (   407)
-
-#define DIB3000MC_REG_DDS_FREQ_MSB             (   414)
-#define DIB3000MC_REG_DDS_FREQ_LSB             (   415)
-
-#define DIB3000MC_REG_TIMING_OFFS_MSB  (   416)
-#define DIB3000MC_REG_TIMING_OFFS_LSB  (   417)
-
-#define DIB3000MC_REG_TUNING_PARM              (   458)
-#define DIB3000MC_TP_QAM(v)                            ((v >> 13) & 0x03)
-#define DIB3000MC_TP_HRCH(v)                   ((v >> 12) & 0x01)
-#define DIB3000MC_TP_ALPHA(v)                  ((v >> 9) & 0x07)
-#define DIB3000MC_TP_FFT(v)                            ((v >> 8) & 0x01)
-#define DIB3000MC_TP_FEC_CR_HP(v)              ((v >> 5) & 0x07)
-#define DIB3000MC_TP_FEC_CR_LP(v)              ((v >> 2) & 0x07)
-#define DIB3000MC_TP_GUARD(v)                  (v & 0x03)
-
-#define DIB3000MC_REG_SIGNAL_NOISE_MSB (   483)
-#define DIB3000MC_REG_SIGNAL_NOISE_LSB (   484)
-
-#define DIB3000MC_REG_MER                              (   485)
-
-#define DIB3000MC_REG_BER_MSB                  (   500)
-#define DIB3000MC_REG_BER_LSB                  (   501)
-
-#define DIB3000MC_REG_PACKET_ERRORS            (   503)
-
-#define DIB3000MC_REG_PACKET_ERROR_COUNT       (   506)
-
-#define DIB3000MC_REG_LOCK_507                 (   507)
-#define DIB3000MC_LOCK_507                             (0x0002) // ? name correct ?
-
-#define DIB3000MC_REG_LOCKING                  (   509)
-#define DIB3000MC_AGC_LOCK(v)                  (v & 0x8000)
-#define DIB3000MC_CARRIER_LOCK(v)              (v & 0x2000)
-#define DIB3000MC_MPEG_SYNC_LOCK(v)            (v & 0x0080)
-#define DIB3000MC_MPEG_DATA_LOCK(v)            (v & 0x0040)
-#define DIB3000MC_TPS_LOCK(v)                  (v & 0x0004)
-
-#define DIB3000MC_REG_AS_IRQ                   (   511)
-#define DIB3000MC_AS_IRQ_SUCCESS               (1 << 1)
-#define DIB3000MC_AS_IRQ_FAIL                  (     1)
-
-#define DIB3000MC_REG_TUNER                            (   769)
-
-#define DIB3000MC_REG_RST_I2C_ADDR             (  1024)
-#define DIB3000MC_DEMOD_ADDR_ON                        (     1)
-#define DIB3000MC_DEMOD_ADDR(a)                        ((a << 4) & 0x03F0)
-
-#define DIB3000MC_REG_RESTART                  (  1027)
-#define DIB3000MC_RESTART_OFF                  (0x0000)
-#define DIB3000MC_RESTART_AGC                  (0x0800)
-#define DIB3000MC_RESTART_CONFIG               (0x8000)
-
-#define DIB3000MC_REG_RESTART_VIT              (  1028)
-#define DIB3000MC_RESTART_VIT_OFF              (     0)
-#define DIB3000MC_RESTART_VIT_ON               (     1)
-
-#define DIB3000MC_REG_CLK_CFG_1                        (  1031)
-#define DIB3000MC_CLK_CFG_1_POWER_UP   (     0)
-#define DIB3000MC_CLK_CFG_1_POWER_DOWN (0xffff)
-
-#define DIB3000MC_REG_CLK_CFG_2                        (  1032)
-#define DIB3000MC_CLK_CFG_2_PUP_FIXED  (0x012c)
-#define DIB3000MC_CLK_CFG_2_PUP_PORT   (0x0104)
-#define DIB3000MC_CLK_CFG_2_PUP_MOBILE  (0x0000)
-#define DIB3000MC_CLK_CFG_2_POWER_DOWN (0xffff)
-
-#define DIB3000MC_REG_CLK_CFG_3                        (  1033)
-#define DIB3000MC_CLK_CFG_3_POWER_UP   (     0)
-#define DIB3000MC_CLK_CFG_3_POWER_DOWN (0xfff5)
-
-#define DIB3000MC_REG_CLK_CFG_7                        (  1037)
-#define DIB3000MC_CLK_CFG_7_INIT               ( 12592)
-#define DIB3000MC_CLK_CFG_7_POWER_UP   (~0x0003)
-#define DIB3000MC_CLK_CFG_7_PWR_DOWN   (0x0003)
-#define DIB3000MC_CLK_CFG_7_DIV_IN_OFF (1 << 8)
-
-/* was commented out ??? */
-#define DIB3000MC_REG_CLK_CFG_8                        (  1038)
-#define DIB3000MC_CLK_CFG_8_POWER_UP   (0x160c)
-
-#define DIB3000MC_REG_CLK_CFG_9                        (  1039)
-#define DIB3000MC_CLK_CFG_9_POWER_UP   (     0)
-
-/* also clock ??? */
-#define DIB3000MC_REG_ELEC_OUT                 (  1040)
-#define DIB3000MC_ELEC_OUT_HIGH_Z              (     0)
-#define DIB3000MC_ELEC_OUT_DIV_OUT_ON  (     1)
-#define DIB3000MC_ELEC_OUT_SLAVE               (     3)
-
-#endif
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c
new file mode 100644 (file)
index 0000000..a18c8f4
--- /dev/null
@@ -0,0 +1,152 @@
+#include <linux/i2c.h>
+
+#include "dibx000_common.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0)
+
+static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
+{
+       u8 b[4] = {
+               (reg >> 8) & 0xff, reg & 0xff,
+               (val >> 8) & 0xff, val & 0xff,
+       };
+       struct i2c_msg msg = {
+               .addr = mst->i2c_addr, .flags = 0, .buf = b, .len = 4
+       };
+       return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+
+static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf)
+{
+       if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
+               dprintk("selecting interface: %d\n",intf);
+               mst->selected_interface = intf;
+               return dibx000_write_word(mst, mst->base_reg + 4, intf);
+       }
+       return 0;
+}
+
+static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], u8 addr, int onoff)
+{
+       u16 val;
+
+
+       if (onoff)
+               val = addr << 8; // bit 7 = use master or not, if 0, the gate is open
+       else
+               val = 1 << 7;
+
+       if (mst->device_rev > DIB7000)
+               val <<= 1;
+
+       tx[0] = (((mst->base_reg + 1) >> 8) & 0xff);
+       tx[1] = ( (mst->base_reg + 1)       & 0xff);
+       tx[2] = val >> 8;
+       tx[3] = val & 0xff;
+
+       return 0;
+}
+
+static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+       struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+       struct i2c_msg m[2 + num];
+       u8 tx_open[4], tx_close[4];
+
+       memset(m,0, sizeof(struct i2c_msg) * (2 + num));
+
+       dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
+
+       dibx000_i2c_gate_ctrl(mst, tx_open,  msg[0].addr, 1);
+       m[0].addr = mst->i2c_addr;
+       m[0].buf  = tx_open;
+       m[0].len  = 4;
+
+       memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
+
+       dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
+       m[num+1].addr = mst->i2c_addr;
+       m[num+1].buf  = tx_close;
+       m[num+1].len  = 4;
+
+       return i2c_transfer(mst->i2c_adap, m, 2+num) == 2 + num ? num : -EIO;
+}
+
+static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
+       .master_xfer   = dibx000_i2c_gated_tuner_xfer,
+       .functionality = dibx000_i2c_func,
+};
+
+struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating)
+{
+       struct i2c_adapter *i2c = NULL;
+
+       switch (intf) {
+               case DIBX000_I2C_INTERFACE_TUNER:
+                       if (gating)
+                               i2c = &mst->gated_tuner_i2c_adap;
+                       break;
+               default:
+                       printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n");
+                       break;
+       }
+
+       return i2c;
+}
+EXPORT_SYMBOL(dibx000_get_i2c_adapter);
+
+static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char name[I2C_NAME_SIZE], struct dibx000_i2c_master *mst)
+{
+       strncpy(i2c_adap->name, name, I2C_NAME_SIZE);
+       i2c_adap->class     = I2C_CLASS_TV_DIGITAL,
+       i2c_adap->algo      = algo;
+       i2c_adap->algo_data = NULL;
+       i2c_set_adapdata(i2c_adap, mst);
+       if (i2c_add_adapter(i2c_adap) < 0)
+               return -ENODEV;
+       return 0;
+}
+
+int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr)
+{
+       u8 tx[4];
+       struct i2c_msg m = { .addr = i2c_addr >> 1, .buf = tx, .len = 4 };
+
+       mst->device_rev = device_rev;
+       mst->i2c_adap   = i2c_adap;
+       mst->i2c_addr   = i2c_addr >> 1;
+
+       if (device_rev == DIB7000P)
+               mst->base_reg = 1024;
+       else
+               mst->base_reg = 768;
+
+    if (i2c_adapter_init(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo, "DiBX000 tuner I2C bus", mst) != 0)
+               printk(KERN_ERR "DiBX000: could not initialize the tuner i2c_adapter\n");
+
+       /* initialize the i2c-master by closing the gate */
+       dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
+
+       return i2c_transfer(i2c_adap, &m, 1) == 1;
+}
+EXPORT_SYMBOL(dibx000_init_i2c_master);
+
+void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
+{
+       i2c_del_adapter(&mst->gated_tuner_i2c_adap);
+}
+EXPORT_SYMBOL(dibx000_exit_i2c_master);
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h
new file mode 100644 (file)
index 0000000..bb0c65f
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef DIBX000_COMMON_H
+#define DIBX000_COMMON_H
+
+enum dibx000_i2c_interface {
+       DIBX000_I2C_INTERFACE_TUNER    = 0,
+       DIBX000_I2C_INTERFACE_GPIO_1_2 = 1,
+       DIBX000_I2C_INTERFACE_GPIO_3_4 = 2
+};
+
+struct dibx000_i2c_master {
+#define DIB3000MC 1
+#define DIB7000   2
+#define DIB7000P  11
+#define DIB7000MC 12
+       u16 device_rev;
+
+       enum dibx000_i2c_interface selected_interface;
+
+//     struct i2c_adapter  tuner_i2c_adap;
+       struct i2c_adapter  gated_tuner_i2c_adap;
+
+       struct i2c_adapter *i2c_adap;
+       u8                  i2c_addr;
+
+       u16 base_reg;
+};
+
+extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr);
+extern struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating);
+extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
+
+#define BAND_LBAND 0x01
+#define BAND_UHF   0x02
+#define BAND_VHF   0x04
+
+struct dibx000_agc_config {
+       /* defines the capabilities of this AGC-setting - using the BAND_-defines*/
+       u8  band_caps;
+
+       u16 setup;
+
+       u16 inv_gain;
+       u16 time_stabiliz;
+
+       u8  alpha_level;
+       u16 thlock;
+
+       u8  wbd_inv;
+       u16 wbd_ref;
+       u8 wbd_sel;
+       u8 wbd_alpha;
+
+       u16 agc1_max;
+       u16 agc1_min;
+       u16 agc2_max;
+       u16 agc2_min;
+
+       u8 agc1_pt1;
+       u8 agc1_pt2;
+       u8 agc1_pt3;
+
+       u8 agc1_slope1;
+       u8 agc1_slope2;
+
+       u8 agc2_pt1;
+       u8 agc2_pt2;
+
+       u8 agc2_slope1;
+       u8 agc2_slope2;
+
+       u8 alpha_mant;
+       u8 alpha_exp;
+
+       u8 beta_mant;
+       u8 beta_exp;
+
+       u8 perform_agc_softsplit;
+
+       struct {
+               u16 min;
+               u16 max;
+               u16 min_thres;
+               u16 max_thres;
+       } split;
+};
+
+struct dibx000_bandwidth_config {
+       u32   internal;
+       u32   sampling;
+
+       u8 pll_prediv;
+       u8 pll_ratio;
+       u8 pll_range;
+       u8 pll_reset;
+       u8 pll_bypass;
+
+       u8 enable_refdiv;
+       u8 bypclk_div;
+       u8 IO_CLK_en_core;
+       u8 ADClkSrc;
+       u8 modulo;
+
+       u16 sad_cfg;
+
+       u32 ifreq;
+       u32 timf;
+};
+
+enum dibx000_adc_states {
+       DIBX000_SLOW_ADC_ON = 0,
+       DIBX000_SLOW_ADC_OFF,
+       DIBX000_ADC_ON,
+       DIBX000_ADC_OFF,
+       DIBX000_VBG_ENABLE,
+       DIBX000_VBG_DISABLE,
+};
+
+#define BW_INDEX_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ  ? 8000 : \
+                            (v) == BANDWIDTH_7_MHZ  ? 7000 : \
+                            (v) == BANDWIDTH_6_MHZ  ? 6000 : 8000 )
+
+/* Chip output mode. */
+#define OUTMODE_HIGH_Z                      0
+#define OUTMODE_MPEG2_PAR_GATED_CLK         1
+#define OUTMODE_MPEG2_PAR_CONT_CLK          2
+#define OUTMODE_MPEG2_SERIAL                7
+#define OUTMODE_DIVERSITY                   4
+#define OUTMODE_MPEG2_FIFO                  5
+
+/* I hope I can get rid of the following kludge in the near future */
+struct dibx000_ofdm_channel {
+       u8  Bw;
+       s16 nfft;
+       s16 guard;
+       s16 nqam;
+       s16 vit_hrch;
+       s16 vit_select_hp;
+       s16 vit_alpha;
+       s16 vit_code_rate_hp;
+       s16 vit_code_rate_lp;
+};
+
+#define FEP2DIB(fep,ch) \
+       (ch)->Bw               = (fep)->u.ofdm.bandwidth; \
+       (ch)->nfft             = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \
+       (ch)->guard            = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \
+       (ch)->nqam             = (fep)->u.ofdm.constellation == QAM_AUTO ? -1 : (fep)->u.ofdm.constellation == QAM_64 ? 2 : (fep)->u.ofdm.constellation; \
+       (ch)->vit_hrch         = 0; /* linux-dvb is not prepared for HIERARCHICAL TRANSMISSION */ \
+       (ch)->vit_select_hp    = 1; \
+       (ch)->vit_alpha        = 1; \
+       (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \
+       (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP;
+
+#define INIT_OFDM_CHANNEL(ch) do {\
+       (ch)->Bw               = 0;  \
+       (ch)->nfft             = -1; \
+       (ch)->guard            = -1; \
+       (ch)->nqam             = -1; \
+       (ch)->vit_hrch         = -1; \
+       (ch)->vit_select_hp    = -1; \
+       (ch)->vit_alpha        = -1; \
+       (ch)->vit_code_rate_hp = -1; \
+       (ch)->vit_code_rate_lp = -1; \
+} while (0)
+
+#endif
index 2be33f27c69fbfb7944140220eb34df815f15034..b7e7108ee5b3cadd0e82c562a1264575a9e9a093 100644 (file)
@@ -493,6 +493,9 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
        int i;
        int result;
 
+       if (priv->i2c == NULL)
+               return -EINVAL;
+
        for (i = 0; i < priv->pll_desc->count; i++) {
                if (priv->pll_desc->entries[i].limit == 0)
                        break;
@@ -611,7 +614,7 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = {
        .get_bandwidth = dvb_pll_get_bandwidth,
 };
 
-int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
+struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
 {
        u8 b1 [] = { 0 };
        struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 };
@@ -624,14 +627,14 @@ int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2
 
                ret = i2c_transfer (i2c, &msg, 1);
                if (ret != 1)
-                       return -1;
+                       return NULL;
                if (fe->ops.i2c_gate_ctrl)
                             fe->ops.i2c_gate_ctrl(fe, 0);
        }
 
        priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
        if (priv == NULL)
-               return -ENOMEM;
+               return NULL;
 
        priv->pll_i2c_address = pll_addr;
        priv->i2c = i2c;
@@ -643,7 +646,7 @@ int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2
        fe->ops.tuner_ops.info.frequency_min = desc->max;
 
        fe->tuner_priv = priv;
-       return 0;
+       return fe;
 }
 EXPORT_SYMBOL(dvb_pll_attach);
 
index 66361cd188078c6361d84d255febce35d0685aa2..ed5ac5a361ae12da3c65a850f33bbe67f48f3f63 100644 (file)
@@ -57,8 +57,8 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
  * @param pll_addr i2c address of the PLL (if used).
  * @param i2c i2c adapter to use (set to NULL if not used).
  * @param desc dvb_pll_desc to use.
- * @return 0 on success, nonzero on failure.
+ * @return Frontend pointer on success, NULL on failure
  */
-extern int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
+extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
 
 #endif
index 58c34db31071e948d42049022150cc14a7e72fac..ef319369ec262e2fd9016e0fa9d4b1674b433424 100644 (file)
@@ -42,12 +42,11 @@ struct isl6421 {
        u8                      override_and;
        struct i2c_adapter      *i2c;
        u8                      i2c_addr;
-       void                    (*release_chain)(struct dvb_frontend* fe);
 };
 
 static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
-       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+       struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
        struct i2c_msg msg = {  .addr = isl6421->i2c_addr, .flags = 0,
                                .buf = &isl6421->config,
                                .len = sizeof(isl6421->config) };
@@ -75,7 +74,7 @@ static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
 
 static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 {
-       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+       struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
        struct i2c_msg msg = {  .addr = isl6421->i2c_addr, .flags = 0,
                                .buf = &isl6421->config,
                                .len = sizeof(isl6421->config) };
@@ -93,31 +92,26 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 
 static void isl6421_release(struct dvb_frontend *fe)
 {
-       struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
-
        /* power off */
        isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
 
-       /* free data & call next release routine */
-       fe->ops.release = isl6421->release_chain;
-       kfree(fe->misc_priv);
-       fe->misc_priv = NULL;
-       if (fe->ops.release)
-               fe->ops.release(fe);
+       /* free */
+       kfree(fe->sec_priv);
+       fe->sec_priv = NULL;
 }
 
-int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
                   u8 override_set, u8 override_clear)
 {
        struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
        if (!isl6421)
-               return -ENOMEM;
+               return NULL;
 
        /* default configuration */
        isl6421->config = ISL6421_ISEL1;
        isl6421->i2c = i2c;
        isl6421->i2c_addr = i2c_addr;
-       fe->misc_priv = isl6421;
+       fe->sec_priv = isl6421;
 
        /* bits which should be forced to '1' */
        isl6421->override_or = override_set;
@@ -128,19 +122,17 @@ int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr
        /* detect if it is present or not */
        if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
                kfree(isl6421);
-               fe->misc_priv = NULL;
-               return -EIO;
+               return NULL;
        }
 
        /* install release callback */
-       isl6421->release_chain = fe->ops.release;
-       fe->ops.release = isl6421_release;
+       fe->ops.release_sec = isl6421_release;
 
        /* override frontend ops */
        fe->ops.set_voltage = isl6421_set_voltage;
        fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
 
-       return 0;
+       return fe;
 }
 EXPORT_SYMBOL(isl6421_attach);
 
index 675f80a19b9917ad694121856d4851daaa6878f6..1916e3eb2df39c30d07b5bc889e80e0c08cc7d70 100644 (file)
 #define ISL6421_ISEL1  0x20
 #define ISL6421_DCL    0x40
 
+#if defined(CONFIG_DVB_ISL6421) || defined(CONFIG_DVB_ISL6421_MODULE)
 /* override_set and override_clear control which system register bits (above) to always set & clear */
-extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
                          u8 override_set, u8 override_clear);
+#else
+static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+                                                 u8 override_set, u8 override_clear)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_ISL6421
 
 #endif
index 83b8bc21027404563875208b3e559d2037ef287a..21ba4a2307601067348e4a0d50d774927357c6cb 100644 (file)
@@ -31,8 +31,16 @@ struct l64781_config
        u8 demod_address;
 };
 
-
+#if defined(CONFIG_DVB_L64781) || defined(CONFIG_DVB_L64781_MODULE)
 extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
                                          struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
+                                         struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_L64781
 
 #endif // L64781_H
index bad903c6f0f8261111a6b1d2b7dfe3bdbabb9325..3f96b485584c663ce68deac95b0e32970aa83689 100644 (file)
@@ -52,8 +52,17 @@ struct lgdt330x_config
        int clock_polarity_flip;
 };
 
+#if defined(CONFIG_DVB_LGDT330X) || defined(CONFIG_DVB_LGDT330X_MODULE)
 extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
                                            struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
+                                           struct i2c_adapter* i2c)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_LGDT330X
 
 #endif /* LGDT330X_H */
 
index e933edc8dd292499b78ef7746bde7202f94da2a0..2d2f58c26226527dd7ddadd5fd4e9ba634d388a4 100644 (file)
@@ -40,12 +40,11 @@ struct lnbp21 {
        u8                      override_or;
        u8                      override_and;
        struct i2c_adapter      *i2c;
-       void                    (*release_chain)(struct dvb_frontend* fe);
 };
 
 static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
-       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
        struct i2c_msg msg = {  .addr = 0x08, .flags = 0,
                                .buf = &lnbp21->config,
                                .len = sizeof(lnbp21->config) };
@@ -73,7 +72,7 @@ static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 
 static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 {
-       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
        struct i2c_msg msg = {  .addr = 0x08, .flags = 0,
                                .buf = &lnbp21->config,
                                .len = sizeof(lnbp21->config) };
@@ -91,29 +90,24 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
 
 static void lnbp21_release(struct dvb_frontend *fe)
 {
-       struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-
        /* LNBP power off */
        lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
 
-       /* free data & call next release routine */
-       fe->ops.release = lnbp21->release_chain;
-       kfree(fe->misc_priv);
-       fe->misc_priv = NULL;
-       if (fe->ops.release)
-               fe->ops.release(fe);
+       /* free data */
+       kfree(fe->sec_priv);
+       fe->sec_priv = NULL;
 }
 
-int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
 {
        struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
        if (!lnbp21)
-               return -ENOMEM;
+               return NULL;
 
        /* default configuration */
        lnbp21->config = LNBP21_ISEL;
        lnbp21->i2c = i2c;
-       fe->misc_priv = lnbp21;
+       fe->sec_priv = lnbp21;
 
        /* bits which should be forced to '1' */
        lnbp21->override_or = override_set;
@@ -124,19 +118,17 @@ int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_
        /* detect if it is present or not */
        if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
                kfree(lnbp21);
-               fe->misc_priv = NULL;
-               return -EIO;
+               return NULL;
        }
 
        /* install release callback */
-       lnbp21->release_chain = fe->ops.release;
-       fe->ops.release = lnbp21_release;
+       fe->ops.release_sec = lnbp21_release;
 
        /* override frontend ops */
        fe->ops.set_voltage = lnbp21_set_voltage;
        fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
 
-       return 0;
+       return fe;
 }
 EXPORT_SYMBOL(lnbp21_attach);
 
index 047a4ab68c01be0a0cc0c6579eff5f0c3ec149ad..1fe1dd1793123985b813fda65b992c332e4162cb 100644 (file)
 
 #include <linux/dvb/frontend.h>
 
+#if defined(CONFIG_DVB_LNBP21) || defined(CONFIG_DVB_LNBP21_MODULE)
 /* override_set and override_clear control which system register bits (above) to always set & clear */
-extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
+extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
+#else
+static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
+       return NULL;
+}
+#endif // CONFIG_DVB_LNBP21
 
-#endif
+#endif // _LNBP21_H
diff --git a/drivers/media/dvb/frontends/mt2060.c b/drivers/media/dvb/frontends/mt2060.c
new file mode 100644 (file)
index 0000000..508ec1b
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ *  Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
+ *
+ *  Copyright (c) 2006 Olivier DANET <odanet@caramail.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.=
+ */
+
+/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "mt2060.h"
+#include "mt2060_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2060: " args); printk("\n"); }} while (0)
+
+// Reads a single register
+static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val)
+{
+       struct i2c_msg msg[2] = {
+               { .addr = priv->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
+               { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val,  .len = 1 },
+       };
+
+       if (i2c_transfer(priv->i2c, msg, 2) != 2) {
+               printk(KERN_WARNING "mt2060 I2C read failed\n");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+// Writes a single register
+static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val)
+{
+       u8 buf[2] = { reg, val };
+       struct i2c_msg msg = {
+               .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
+       };
+
+       if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+               printk(KERN_WARNING "mt2060 I2C write failed\n");
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+// Writes a set of consecutive registers
+static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len)
+{
+       struct i2c_msg msg = {
+               .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
+       };
+       if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
+               printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n",(int)len);
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+// Initialisation sequences
+// LNABAND=3, NUM1=0x3C, DIV1=0x74, NUM2=0x1080, DIV2=0x49
+static u8 mt2060_config1[] = {
+       REG_LO1C1,
+       0x3F,   0x74,   0x00,   0x08,   0x93
+};
+
+// FMCG=2, GP2=0, GP1=0
+static u8 mt2060_config2[] = {
+       REG_MISC_CTRL,
+       0x20,   0x1E,   0x30,   0xff,   0x80,   0xff,   0x00,   0x2c,   0x42
+};
+
+//  VGAG=3, V1CSE=1
+
+#ifdef  MT2060_SPURCHECK
+/* The function below calculates the frequency offset between the output frequency if2
+ and the closer cross modulation subcarrier between lo1 and lo2 up to the tenth harmonic */
+static int mt2060_spurcalc(u32 lo1,u32 lo2,u32 if2)
+{
+       int I,J;
+       int dia,diamin,diff;
+       diamin=1000000;
+       for (I = 1; I < 10; I++) {
+               J = ((2*I*lo1)/lo2+1)/2;
+               diff = I*(int)lo1-J*(int)lo2;
+               if (diff < 0) diff=-diff;
+               dia = (diff-(int)if2);
+               if (dia < 0) dia=-dia;
+               if (diamin > dia) diamin=dia;
+       }
+       return diamin;
+}
+
+#define BANDWIDTH 4000 // kHz
+
+/* Calculates the frequency offset to add to avoid spurs. Returns 0 if no offset is needed */
+static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2)
+{
+       u32 Spur,Sp1,Sp2;
+       int I,J;
+       I=0;
+       J=1000;
+
+       Spur=mt2060_spurcalc(lo1,lo2,if2);
+       if (Spur < BANDWIDTH) {
+               /* Potential spurs detected */
+               dprintk("Spurs before : f_lo1: %d  f_lo2: %d  (kHz)",
+                       (int)lo1,(int)lo2);
+               I=1000;
+               Sp1 = mt2060_spurcalc(lo1+I,lo2+I,if2);
+               Sp2 = mt2060_spurcalc(lo1-I,lo2-I,if2);
+
+               if (Sp1 < Sp2) {
+                       J=-J; I=-I; Spur=Sp2;
+               } else
+                       Spur=Sp1;
+
+               while (Spur < BANDWIDTH) {
+                       I += J;
+                       Spur = mt2060_spurcalc(lo1+I,lo2+I,if2);
+               }
+               dprintk("Spurs after  : f_lo1: %d  f_lo2: %d  (kHz)",
+                       (int)(lo1+I),(int)(lo2+I));
+       }
+       return I;
+}
+#endif
+
+#define IF2  36150       // IF2 frequency = 36.150 MHz
+#define FREF 16000       // Quartz oscillator 16 MHz
+
+static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+       struct mt2060_priv *priv;
+       int ret=0;
+       int i=0;
+       u32 freq;
+       u8  lnaband;
+       u32 f_lo1,f_lo2;
+       u32 div1,num1,div2,num2;
+       u8  b[8];
+       u32 if1;
+
+       priv = fe->tuner_priv;
+
+       if1 = priv->if1_freq;
+       b[0] = REG_LO1B1;
+       b[1] = 0xFF;
+
+       mt2060_writeregs(priv,b,2);
+
+       freq = params->frequency / 1000; // Hz -> kHz
+       priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
+
+       f_lo1 = freq + if1 * 1000;
+       f_lo1 = (f_lo1 / 250) * 250;
+       f_lo2 = f_lo1 - freq - IF2;
+       // From the Comtech datasheet, the step used is 50kHz. The tuner chip could be more precise
+       f_lo2 = ((f_lo2 + 25) / 50) * 50;
+       priv->frequency =  (f_lo1 - f_lo2 - IF2) * 1000,
+
+#ifdef MT2060_SPURCHECK
+       // LO-related spurs detection and correction
+       num1   = mt2060_spurcheck(f_lo1,f_lo2,IF2);
+       f_lo1 += num1;
+       f_lo2 += num1;
+#endif
+       //Frequency LO1 = 16MHz * (DIV1 + NUM1/64 )
+       num1 = f_lo1 / (FREF / 64);
+       div1 = num1 / 64;
+       num1 &= 0x3f;
+
+       // Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 )
+       num2 = f_lo2 * 64 / (FREF / 128);
+       div2 = num2 / 8192;
+       num2 &= 0x1fff;
+
+       if (freq <=  95000) lnaband = 0xB0; else
+       if (freq <= 180000) lnaband = 0xA0; else
+       if (freq <= 260000) lnaband = 0x90; else
+       if (freq <= 335000) lnaband = 0x80; else
+       if (freq <= 425000) lnaband = 0x70; else
+       if (freq <= 480000) lnaband = 0x60; else
+       if (freq <= 570000) lnaband = 0x50; else
+       if (freq <= 645000) lnaband = 0x40; else
+       if (freq <= 730000) lnaband = 0x30; else
+       if (freq <= 810000) lnaband = 0x20; else lnaband = 0x10;
+
+       b[0] = REG_LO1C1;
+       b[1] = lnaband | ((num1 >>2) & 0x0F);
+       b[2] = div1;
+       b[3] = (num2 & 0x0F)  | ((num1 & 3) << 4);
+       b[4] = num2 >> 4;
+       b[5] = ((num2 >>12) & 1) | (div2 << 1);
+
+       dprintk("IF1: %dMHz",(int)if1);
+       dprintk("PLL freq=%dkHz  f_lo1=%dkHz  f_lo2=%dkHz",(int)freq,(int)f_lo1,(int)f_lo2);
+       dprintk("PLL div1=%d  num1=%d  div2=%d  num2=%d",(int)div1,(int)num1,(int)div2,(int)num2);
+       dprintk("PLL [1..5]: %2x %2x %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3],(int)b[4],(int)b[5]);
+
+       mt2060_writeregs(priv,b,6);
+
+       //Waits for pll lock or timeout
+       i = 0;
+       do {
+               mt2060_readreg(priv,REG_LO_STATUS,b);
+               if ((b[0] & 0x88)==0x88)
+                       break;
+               msleep(4);
+               i++;
+       } while (i<10);
+
+       return ret;
+}
+
+static void mt2060_calibrate(struct mt2060_priv *priv)
+{
+       u8 b = 0;
+       int i = 0;
+
+       if (mt2060_writeregs(priv,mt2060_config1,sizeof(mt2060_config1)))
+               return;
+       if (mt2060_writeregs(priv,mt2060_config2,sizeof(mt2060_config2)))
+               return;
+
+       do {
+               b |= (1 << 6); // FM1SS;
+               mt2060_writereg(priv, REG_LO2C1,b);
+               msleep(20);
+
+               if (i == 0) {
+                       b |= (1 << 7); // FM1CA;
+                       mt2060_writereg(priv, REG_LO2C1,b);
+                       b &= ~(1 << 7); // FM1CA;
+                       msleep(20);
+               }
+
+               b &= ~(1 << 6); // FM1SS
+               mt2060_writereg(priv, REG_LO2C1,b);
+
+               msleep(20);<