فهرست منبع

Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb

* master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (244 commits)
  V4L/DVB (4210b): git-dvb: tea575x-tuner build fix
  V4L/DVB (4210a): git-dvb versus matroxfb
  V4L/DVB (4209): Added some BTTV PCI IDs for newer boards
  Fixes some sync issues between V4L/DVB development and GIT
  V4L/DVB (4206): Cx88-blackbird: always set encoder height based on tvnorm->id
  V4L/DVB (4205): Merge tda9887 module into tuner.
  V4L/DVB (4203): Explicitly set the enum values.
  V4L/DVB (4202): allow selecting CX2341x port mode
  V4L/DVB (4200): Disable bitrate_mode when encoding mpeg-1.
  V4L/DVB (4199): Add cx2341x-specific control array to cx2341x.c
  V4L/DVB (4198): Avoid newer usages of obsoleted experimental MPEGCOMP API
  V4L/DVB (4197): Port new MPEG API to saa7134-empress with saa6752hs
  V4L/DVB (4196): Port cx88-blackbird to the new MPEG API.
  V4L/DVB (4193): Update cx2341x fw encoding API doc.
  V4L/DVB (4192): Use control helpers for saa7115, cx25840, msp3400.
  V4L/DVB (4191): Add CX2341X MPEG encoder module.
  V4L/DVB (4190): Add helper functions for control processing to v4l2-common.
  V4L/DVB (4189): Add videodev support for VIDIOC_S/G/TRY_EXT_CTRLS.
  V4L/DVB (4188): Add new MPEG control/ioctl definitions to videodev2.h
  V4L/DVB (4186): Add support for the DNTV Live! mini DVB-T card.
  ...
Linus Torvalds 19 سال پیش
والد
کامیت
25581ad107
100فایلهای تغییر یافته به همراه5141 افزوده شده و 1442 حذف شده
  1. 2 2
      Documentation/video4linux/CARDLIST.bttv
  2. 7 2
      Documentation/video4linux/CARDLIST.cx88
  3. 1 0
      Documentation/video4linux/CARDLIST.saa7134
  4. 2 1
      Documentation/video4linux/CARDLIST.tuner
  5. 3 200
      Documentation/video4linux/CQcam.txt
  6. 23 0
      Documentation/video4linux/Zoran
  7. 4 4
      Documentation/video4linux/bttv/CONTRIBUTORS
  8. 69 0
      Documentation/video4linux/cx2341x/fw-calling.txt
  9. 319 0
      Documentation/video4linux/cx2341x/fw-decoder-api.txt
  10. 94 0
      Documentation/video4linux/cx2341x/fw-dma.txt
  11. 694 0
      Documentation/video4linux/cx2341x/fw-encoder-api.txt
  12. 141 0
      Documentation/video4linux/cx2341x/fw-memory.txt
  13. 342 0
      Documentation/video4linux/cx2341x/fw-osd-api.txt
  14. 49 0
      Documentation/video4linux/cx2341x/fw-upload.txt
  15. 54 0
      Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt
  16. 26 26
      Documentation/video4linux/et61x251.txt
  17. 84 84
      Documentation/video4linux/ibmcam.txt
  18. 16 16
      Documentation/video4linux/ov511.txt
  19. 39 39
      Documentation/video4linux/sn9c102.txt
  20. 192 0
      Documentation/video4linux/v4lgrab.c
  21. 81 81
      Documentation/video4linux/w9968cf.txt
  22. 48 32
      Documentation/video4linux/zc0301.txt
  23. 5 2
      drivers/media/Kconfig
  24. 1 1
      drivers/media/common/Makefile
  25. 0 1
      drivers/media/common/ir-functions.c
  26. 71 11
      drivers/media/common/ir-keymaps.c
  27. 4 0
      drivers/media/common/saa7146_fops.c
  28. 1 0
      drivers/media/common/saa7146_hlp.c
  29. 2 0
      drivers/media/common/saa7146_video.c
  30. 0 12
      drivers/media/common/saa7146_vv_ksyms.c
  31. 73 49
      drivers/media/dvb/b2c2/flexcop-fe-tuner.c
  32. 7 12
      drivers/media/dvb/b2c2/flexcop-pci.c
  33. 4 6
      drivers/media/dvb/b2c2/flexcop-usb.c
  34. 4 8
      drivers/media/dvb/b2c2/flexcop.c
  35. 8 3
      drivers/media/dvb/bt8xx/bt878.c
  36. 477 129
      drivers/media/dvb/bt8xx/dst.c
  37. 101 15
      drivers/media/dvb/bt8xx/dst_ca.c
  38. 29 4
      drivers/media/dvb/bt8xx/dst_common.h
  39. 61 57
      drivers/media/dvb/bt8xx/dvb-bt8xx.c
  40. 2 0
      drivers/media/dvb/bt8xx/dvb-bt8xx.h
  41. 1 1
      drivers/media/dvb/cinergyT2/Kconfig
  42. 6 2
      drivers/media/dvb/cinergyT2/cinergyT2.c
  43. 3 3
      drivers/media/dvb/dvb-core/Makefile
  44. 0 3
      drivers/media/dvb/dvb-core/dmxdev.c
  45. 23 2
      drivers/media/dvb/dvb-core/dvb_ca_en50221.c
  46. 2 2
      drivers/media/dvb/dvb-core/dvb_demux.c
  47. 85 66
      drivers/media/dvb/dvb-core/dvb_frontend.c
  48. 44 1
      drivers/media/dvb/dvb-core/dvb_frontend.h
  49. 145 0
      drivers/media/dvb/dvb-core/dvb_math.c
  50. 58 0
      drivers/media/dvb/dvb-core/dvb_math.h
  51. 154 76
      drivers/media/dvb/dvb-core/dvb_net.c
  52. 3 2
      drivers/media/dvb/dvb-core/dvbdev.c
  53. 3 1
      drivers/media/dvb/dvb-core/dvbdev.h
  54. 10 0
      drivers/media/dvb/dvb-usb/Kconfig
  55. 3 0
      drivers/media/dvb/dvb-usb/Makefile
  56. 29 19
      drivers/media/dvb/dvb-usb/cxusb.c
  57. 6 3
      drivers/media/dvb/dvb-usb/dibusb-common.c
  58. 4 3
      drivers/media/dvb/dvb-usb/dibusb-mb.c
  59. 9 6
      drivers/media/dvb/dvb-usb/digitv.c
  60. 2 6
      drivers/media/dvb/dvb-usb/dtt200u-fe.c
  61. 8 9
      drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
  62. 15 9
      drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
  63. 3 1
      drivers/media/dvb/dvb-usb/dvb-usb-ids.h
  64. 3 3
      drivers/media/dvb/dvb-usb/dvb-usb.h
  65. 272 0
      drivers/media/dvb/dvb-usb/gp8psk-fe.c
  66. 256 0
      drivers/media/dvb/dvb-usb/gp8psk.c
  67. 79 0
      drivers/media/dvb/dvb-usb/gp8psk.h
  68. 1 1
      drivers/media/dvb/dvb-usb/umt-010.c
  69. 3 4
      drivers/media/dvb/dvb-usb/vp702x-fe.c
  70. 2 7
      drivers/media/dvb/dvb-usb/vp7045-fe.c
  71. 17 1
      drivers/media/dvb/frontends/Kconfig
  72. 2 0
      drivers/media/dvb/frontends/Makefile
  73. 1 3
      drivers/media/dvb/frontends/bcm3510.c
  74. 4 2
      drivers/media/dvb/frontends/bsbe1.h
  75. 4 2
      drivers/media/dvb/frontends/bsru6.h
  76. 18 13
      drivers/media/dvb/frontends/cx22700.c
  77. 0 4
      drivers/media/dvb/frontends/cx22700.h
  78. 5 24
      drivers/media/dvb/frontends/cx22702.c
  79. 0 7
      drivers/media/dvb/frontends/cx22702.h
  80. 8 18
      drivers/media/dvb/frontends/cx24110.c
  81. 0 5
      drivers/media/dvb/frontends/cx24110.h
  82. 51 144
      drivers/media/dvb/frontends/cx24123.c
  83. 0 13
      drivers/media/dvb/frontends/cx24123.h
  84. 0 2
      drivers/media/dvb/frontends/dib3000-common.h
  85. 0 4
      drivers/media/dvb/frontends/dib3000.h
  86. 4 7
      drivers/media/dvb/frontends/dib3000mb.c
  87. 5 9
      drivers/media/dvb/frontends/dib3000mc.c
  88. 176 5
      drivers/media/dvb/frontends/dvb-pll.c
  89. 16 2
      drivers/media/dvb/frontends/dvb-pll.h
  90. 8 13
      drivers/media/dvb/frontends/dvb_dummy_fe.c
  91. 149 0
      drivers/media/dvb/frontends/isl6421.c
  92. 46 0
      drivers/media/dvb/frontends/isl6421.h
  93. 5 6
      drivers/media/dvb/frontends/l64781.c
  94. 0 4
      drivers/media/dvb/frontends/l64781.h
  95. 64 0
      drivers/media/dvb/frontends/lg_h06xf.h
  96. 11 8
      drivers/media/dvb/frontends/lgdt330x.c
  97. 0 1
      drivers/media/dvb/frontends/lgdt330x.h
  98. 145 0
      drivers/media/dvb/frontends/lnbp21.c
  99. 4 98
      drivers/media/dvb/frontends/lnbp21.h
  100. 26 20
      drivers/media/dvb/frontends/mt312.c

+ 2 - 2
Documentation/video4linux/CARDLIST.bttv

@@ -87,7 +87,7 @@
  86 -> Osprey 101/151 w/ svid
  86 -> Osprey 101/151 w/ svid
  87 -> Osprey 200/201/250/251
  87 -> Osprey 200/201/250/251
  88 -> Osprey 200/250                                      [0070:ff01]
  88 -> Osprey 200/250                                      [0070:ff01]
- 89 -> Osprey 210/220
+ 89 -> Osprey 210/220/230
  90 -> Osprey 500                                          [0070:ff02]
  90 -> Osprey 500                                          [0070:ff02]
  91 -> Osprey 540                                          [0070:ff04]
  91 -> Osprey 540                                          [0070:ff04]
  92 -> Osprey 2000                                         [0070:ff03]
  92 -> Osprey 2000                                         [0070:ff03]
@@ -111,7 +111,7 @@
 110 -> IVC-100                                             [ff00:a132]
 110 -> IVC-100                                             [ff00:a132]
 111 -> IVC-120G                                            [ff00:a182,ff01:a182,ff02:a182,ff03:a182,ff04:a182,ff05:a182,ff06:a182,ff07:a182,ff08:a182,ff09:a182,ff0a:a182,ff0b:a182,ff0c:a182,ff0d:a182,ff0e:a182,ff0f:a182]
 111 -> IVC-120G                                            [ff00:a182,ff01:a182,ff02:a182,ff03:a182,ff04:a182,ff05:a182,ff06:a182,ff07:a182,ff08:a182,ff09:a182,ff0a:a182,ff0b:a182,ff0c:a182,ff0d:a182,ff0e:a182,ff0f:a182]
 112 -> pcHDTV HD-2000 TV                                   [7063:2000]
 112 -> pcHDTV HD-2000 TV                                   [7063:2000]
-113 -> Twinhan DST + clones                                [11bd:0026,1822:0001,270f:fc00]
+113 -> Twinhan DST + clones                                [11bd:0026,1822:0001,270f:fc00,1822:0026]
 114 -> Winfast VC100                                       [107d:6607]
 114 -> Winfast VC100                                       [107d:6607]
 115 -> Teppro TEV-560/InterVision IV-560
 115 -> Teppro TEV-560/InterVision IV-560
 116 -> SIMUS GVC1100                                       [aa6a:82b2]
 116 -> SIMUS GVC1100                                       [aa6a:82b2]

+ 7 - 2
Documentation/video4linux/CARDLIST.cx88

@@ -15,7 +15,7 @@
  14 -> KWorld/VStream XPert DVB-T                          [17de:08a6]
  14 -> KWorld/VStream XPert DVB-T                          [17de:08a6]
  15 -> DViCO FusionHDTV DVB-T1                             [18ac:db00]
  15 -> DViCO FusionHDTV DVB-T1                             [18ac:db00]
  16 -> KWorld LTV883RF
  16 -> KWorld LTV883RF
- 17 -> DViCO FusionHDTV 3 Gold-Q                           [18ac:d810]
+ 17 -> DViCO FusionHDTV 3 Gold-Q                           [18ac:d810,18ac:d800]
  18 -> Hauppauge Nova-T DVB-T                              [0070:9002,0070:9001]
  18 -> Hauppauge Nova-T DVB-T                              [0070:9002,0070:9001]
  19 -> Conexant DVB-T reference design                     [14f1:0187]
  19 -> Conexant DVB-T reference design                     [14f1:0187]
  20 -> Provideo PV259                                      [1540:2580]
  20 -> Provideo PV259                                      [1540:2580]
@@ -40,8 +40,13 @@
  39 -> KWorld DVB-S 100                                    [17de:08b2]
  39 -> KWorld DVB-S 100                                    [17de:08b2]
  40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid                [0070:9400,0070:9402]
  40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid                [0070:9400,0070:9402]
  41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)  [0070:9800,0070:9802]
  41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)  [0070:9800,0070:9802]
- 42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025]
+ 42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025,1822:0019]
  43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1]
  43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1]
  44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50,18ac:db54]
  44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50,18ac:db54]
  45 -> KWorld HardwareMpegTV XPert                         [17de:0840]
  45 -> KWorld HardwareMpegTV XPert                         [17de:0840]
  46 -> DViCO FusionHDTV DVB-T Hybrid                       [18ac:db40,18ac:db44]
  46 -> DViCO FusionHDTV DVB-T Hybrid                       [18ac:db40,18ac:db44]
+ 47 -> pcHDTV HD5500 HDTV                                  [7063:5500]
+ 48 -> Kworld MCE 200 Deluxe                               [17de:0841]
+ 49 -> PixelView PlayTV P7000                              [1554:4813]
+ 50 -> NPG Tech Real TV FM Top 10                          [14f1:0842]
+ 51 -> WinFast DTV2000 H                                   [107d:665e]

+ 1 - 0
Documentation/video4linux/CARDLIST.saa7134

@@ -93,3 +93,4 @@
  92 -> AVerMedia A169 B1                        [1461:6360]
  92 -> AVerMedia A169 B1                        [1461:6360]
  93 -> Medion 7134 Bridge #2                    [16be:0005]
  93 -> Medion 7134 Bridge #2                    [16be:0005]
  94 -> LifeView FlyDVB-T Hybrid Cardbus         [5168:3306,5168:3502]
  94 -> LifeView FlyDVB-T Hybrid Cardbus         [5168:3306,5168:3502]
+ 95 -> LifeView FlyVIDEO3000 (NTSC)             [5169:0138]

+ 2 - 1
Documentation/video4linux/CARDLIST.tuner

@@ -62,7 +62,7 @@ tuner=60 - Thomson DTT 761X (ATSC/NTSC)
 tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
 tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
 tuner=62 - Philips TEA5767HN FM Radio
 tuner=62 - Philips TEA5767HN FM Radio
 tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
 tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
-tuner=64 - LG TDVS-H062F/TUA6034
+tuner=64 - LG TDVS-H06xF
 tuner=65 - Ymec TVF66T5-B/DFF
 tuner=65 - Ymec TVF66T5-B/DFF
 tuner=66 - LG TALN series
 tuner=66 - LG TALN series
 tuner=67 - Philips TD1316 Hybrid Tuner
 tuner=67 - Philips TD1316 Hybrid Tuner
@@ -71,3 +71,4 @@ tuner=69 - Tena TNF 5335 and similar models
 tuner=70 - Samsung TCPN 2121P30A
 tuner=70 - Samsung TCPN 2121P30A
 tuner=71 - Xceive xc3028
 tuner=71 - Xceive xc3028
 tuner=72 - Thomson FE6600
 tuner=72 - Thomson FE6600
+tuner=73 - Samsung TCPG 6121P30A

+ 3 - 200
Documentation/video4linux/CQcam.txt

@@ -185,207 +185,10 @@ this work is documented at the video4linux2 site listed below.
 
 
 9.0 --- A sample program using v4lgrabber,
 9.0 --- A sample program using v4lgrabber,
 
 
-This program is a simple image grabber that will copy a frame from the
+v4lgrab is a simple image grabber that will copy a frame from the
 first video device, /dev/video0 to standard output in portable pixmap
 first video device, /dev/video0 to standard output in portable pixmap
-format (.ppm)  Using this like: 'v4lgrab | convert - c-qcam.jpg'
-produced this picture of me at
-    http://mug.sys.virginia.edu/~drf5n/extras/c-qcam.jpg
-
--------------------- 8< ---------------- 8< -----------------------------
-
-/* Simple Video4Linux image grabber. */
-/*
- *	Video4Linux Driver Test/Example Framegrabbing Program
- *
- *	Compile with:
- *		gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
- *      Use as:
- *              v4lgrab >image.ppm
- *
- *	Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
- *      Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
- *      with minor modifications (Dave Forrest, drf5n@virginia.edu).
- *
- */
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <stdlib.h>
-
-#include <linux/types.h>
-#include <linux/videodev.h>
-
-#define FILE "/dev/video0"
-
-/* Stole this from tvset.c */
-
-#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b)                   \
-{                                                                       \
-	switch (format)                                                 \
-	{                                                               \
-		case VIDEO_PALETTE_GREY:                                \
-			switch (depth)                                  \
-			{                                               \
-				case 4:                                 \
-				case 6:                                 \
-				case 8:                                 \
-					(r) = (g) = (b) = (*buf++ << 8);\
-					break;                          \
-									\
-				case 16:                                \
-					(r) = (g) = (b) =               \
-						*((unsigned short *) buf);      \
-					buf += 2;                       \
-					break;                          \
-			}                                               \
-			break;                                          \
-									\
-									\
-		case VIDEO_PALETTE_RGB565:                              \
-		{                                                       \
-			unsigned short tmp = *(unsigned short *)buf;    \
-			(r) = tmp&0xF800;                               \
-			(g) = (tmp<<5)&0xFC00;                          \
-			(b) = (tmp<<11)&0xF800;                         \
-			buf += 2;                                       \
-		}                                                       \
-		break;                                                  \
-									\
-		case VIDEO_PALETTE_RGB555:                              \
-			(r) = (buf[0]&0xF8)<<8;                         \
-			(g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8;    \
-			(b) = ((buf[1] << 2 ) & 0xF8)<<8;               \
-			buf += 2;                                       \
-			break;                                          \
-									\
-		case VIDEO_PALETTE_RGB24:                               \
-			(r) = buf[0] << 8; (g) = buf[1] << 8;           \
-			(b) = buf[2] << 8;                              \
-			buf += 3;                                       \
-			break;                                          \
-									\
-		default:                                                \
-			fprintf(stderr,                                 \
-				"Format %d not yet supported\n",        \
-				format);                                \
-	}                                                               \
-}
-
-int get_brightness_adj(unsigned char *image, long size, int *brightness) {
-  long i, tot = 0;
-  for (i=0;i<size*3;i++)
-    tot += image[i];
-  *brightness = (128 - tot/(size*3))/3;
-  return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
-}
-
-int main(int argc, char ** argv)
-{
-  int fd = open(FILE, O_RDONLY), f;
-  struct video_capability cap;
-  struct video_window win;
-  struct video_picture vpic;
-
-  unsigned char *buffer, *src;
-  int bpp = 24, r, g, b;
-  unsigned int i, src_depth;
-
-  if (fd < 0) {
-    perror(FILE);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
-    perror("VIDIOGCAP");
-    fprintf(stderr, "(" FILE " not a video4linux device?)\n");
-    close(fd);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
-    perror("VIDIOCGWIN");
-    close(fd);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
-    perror("VIDIOCGPICT");
-    close(fd);
-    exit(1);
-  }
-
-  if (cap.type & VID_TYPE_MONOCHROME) {
-    vpic.depth=8;
-    vpic.palette=VIDEO_PALETTE_GREY;    /* 8bit grey */
-    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-      vpic.depth=6;
-      if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-	vpic.depth=4;
-	if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-	  fprintf(stderr, "Unable to find a supported capture format.\n");
-	  close(fd);
-	  exit(1);
-	}
-      }
-    }
-  } else {
-    vpic.depth=24;
-    vpic.palette=VIDEO_PALETTE_RGB24;
-
-    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-      vpic.palette=VIDEO_PALETTE_RGB565;
-      vpic.depth=16;
-
-      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-	vpic.palette=VIDEO_PALETTE_RGB555;
-	vpic.depth=15;
-
-	if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-	  fprintf(stderr, "Unable to find a supported capture format.\n");
-	  return -1;
-	}
-      }
-    }
-  }
-
-  buffer = malloc(win.width * win.height * bpp);
-  if (!buffer) {
-    fprintf(stderr, "Out of memory.\n");
-    exit(1);
-  }
-
-  do {
-    int newbright;
-    read(fd, buffer, win.width * win.height * bpp);
-    f = get_brightness_adj(buffer, win.width * win.height, &newbright);
-    if (f) {
-      vpic.brightness += (newbright << 8);
-      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-	perror("VIDIOSPICT");
-	break;
-      }
-    }
-  } while (f);
-
-  fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
-
-  src = buffer;
-
-  for (i = 0; i < win.width * win.height; i++) {
-    READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
-    fputc(r>>8, stdout);
-    fputc(g>>8, stdout);
-    fputc(b>>8, stdout);
-  }
-
-  close(fd);
-  return 0;
-}
--------------------- 8< ---------------- 8< -----------------------------
+format (.ppm)  To produce .jpg output, you can use it like this:
+'v4lgrab | convert - c-qcam.jpg'
 
 
 
 
 10.0 --- Other Information
 10.0 --- Other Information

+ 23 - 0
Documentation/video4linux/Zoran

@@ -33,6 +33,21 @@ Inputs/outputs: Composite and S-video
 Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
 Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
 Card number: 7
 Card number: 7
 
 
+AverMedia 6 Eyes AVS6EYES:
+* Zoran zr36067 PCI controller
+* Zoran zr36060 MJPEG codec
+* Samsung ks0127 TV decoder
+* Conexant bt866  TV encoder
+Drivers to use: videodev, i2c-core, i2c-algo-bit,
+		videocodec, ks0127, bt866, zr36060, zr36067
+Inputs/outputs: Six physical inputs. 1-6 are composite,
+		1-2, 3-4, 5-6 doubles as S-video,
+		1-3 triples as component.
+		One composite output.
+Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
+Card number: 8
+Not autodetected, card=8 is necessary.
+
 Linux Media Labs LML33:
 Linux Media Labs LML33:
 * Zoran zr36067 PCI controller
 * Zoran zr36067 PCI controller
 * Zoran zr36060 MJPEG codec
 * Zoran zr36060 MJPEG codec
@@ -192,6 +207,10 @@ Micronas vpx3220a TV decoder
 was introduced in 1996, is used in the DC30 and DC30+ and
 was introduced in 1996, is used in the DC30 and DC30+ and
 can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC 44, PAL 60, SECAM,NTSC Comb
 can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC 44, PAL 60, SECAM,NTSC Comb
 
 
+Samsung ks0127 TV decoder
+is used in the AVS6EYES card and
+can handle: NTSC-M/N/44, PAL-M/N/B/G/H/I/D/K/L and SECAM
+
 ===========================
 ===========================
 
 
 1.2 What the TV encoder can do an what not
 1.2 What the TV encoder can do an what not
@@ -221,6 +240,10 @@ ITT mse3000 TV encoder
 was introduced in 1991, is used in the DC10 old
 was introduced in 1991, is used in the DC10 old
 can generate: PAL , NTSC , SECAM
 can generate: PAL , NTSC , SECAM
 
 
+Conexant bt866 TV encoder
+is used in AVS6EYES, and
+can generate: NTSC/PAL, PAL­M, PAL­N
+
 The adv717x, should be able to produce PAL N. But you find nothing PAL N
 The adv717x, should be able to produce PAL N. But you find nothing PAL N
 specific in the registers. Seem that you have to reuse a other standard
 specific in the registers. Seem that you have to reuse a other standard
 to generate PAL N, maybe it would work if you use the PAL M settings.
 to generate PAL N, maybe it would work if you use the PAL M settings.

+ 4 - 4
Documentation/video4linux/bttv/CONTRIBUTORS

@@ -1,4 +1,4 @@
-Contributors to bttv: 
+Contributors to bttv:
 
 
 Michael Chu <mmchu@pobox.com>
 Michael Chu <mmchu@pobox.com>
   AverMedia fix and more flexible card recognition
   AverMedia fix and more flexible card recognition
@@ -8,8 +8,8 @@ Alan Cox <alan@redhat.com>
 
 
 Chris Kleitsch
 Chris Kleitsch
   Hardware I2C
   Hardware I2C
-  
-Gerd Knorr <kraxel@cs.tu-berlin.de> 
+
+Gerd Knorr <kraxel@cs.tu-berlin.de>
   Radio card (ITT sound processor)
   Radio card (ITT sound processor)
 
 
 bigfoot <bigfoot@net-way.net>
 bigfoot <bigfoot@net-way.net>
@@ -18,7 +18,7 @@ Ragnar Hojland Espinosa <ragnar@macula.net>
 
 
 
 
 + many more (please mail me if you are missing in this list and would
 + many more (please mail me if you are missing in this list and would
-             like to be mentioned)
+	     like to be mentioned)
 
 
 
 
 
 

+ 69 - 0
Documentation/video4linux/cx2341x/fw-calling.txt

@@ -0,0 +1,69 @@
+This page describes how to make calls to the firmware api.
+
+How to call
+===========
+
+The preferred calling convention is known as the firmware mailbox. The
+mailboxes are basically a fixed length array that serves as the call-stack.
+
+Firmware mailboxes can be located by searching the encoder and decoder memory
+for a 16 byte signature. That signature will be located on a 256-byte boundary.
+
+Signature:
+0x78, 0x56, 0x34, 0x12, 0x12, 0x78, 0x56, 0x34,
+0x34, 0x12, 0x78, 0x56, 0x56, 0x34, 0x12, 0x78
+
+The firmware implements 20 mailboxes of 20 32-bit words. The first 10 are
+reserved for API calls. The second 10 are used by the firmware for event
+notification.
+
+  Index  Name
+  -----  ----
+  0      Flags
+  1      Command
+  2      Return value
+  3      Timeout
+  4-19   Parameter/Result
+
+
+The flags are defined in the following table. The direction is from the
+perspective of the firmware.
+
+  Bit  Direction  Purpose
+  ---  ---------  -------
+  2    O          Firmware has processed the command.
+  1    I          Driver has finished setting the parameters.
+  0    I          Driver is using this mailbox.
+
+
+The command is a 32-bit enumerator. The API specifics may be found in the
+fw-*-api.txt documents.
+
+The return value is a 32-bit enumerator. Only two values are currently defined:
+0=success and -1=command undefined.
+
+There are 16 parameters/results 32-bit fields. The driver populates these fields
+with values for all the parameters required by the call. The driver overwrites
+these fields with result values returned by the call. The API specifics may be
+found in the fw-*-api.txt documents.
+
+The timeout value protects the card from a hung driver thread. If the driver
+doesn't handle the completed call within the timeout specified, the firmware
+will reset that mailbox.
+
+To make an API call, the driver iterates over each mailbox looking for the
+first one available (bit 0 has been cleared). The driver sets that bit, fills
+in the command enumerator, the timeout value and any required parameters. The
+driver then sets the parameter ready bit (bit 1). The firmware scans the
+mailboxes for pending commands, processes them, sets the result code, populates
+the result value array with that call's return values and sets the call
+complete bit (bit 2). Once bit 2 is set, the driver should retrieve the results
+and clear all the flags. If the driver does not perform this task within the
+time set in the timeout register, the firmware will reset that mailbox.
+
+Event notifications are sent from the firmware to the host. The host tells the
+firmware which events it is interested in via an API call. That call tells the
+firmware which notification mailbox to use. The firmware signals the host via
+an interrupt. Only the 16 Results fields are used, the Flags, Command, Return
+value and Timeout words are not used.
+

+ 319 - 0
Documentation/video4linux/cx2341x/fw-decoder-api.txt

@@ -0,0 +1,319 @@
+Decoder firmware API description
+================================
+
+Note: this API is part of the decoder firmware, so it's cx23415 only.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_PING_FW
+Enum 	0/0x00
+Description
+	This API call does nothing. It may be used to check if the firmware
+	is responding.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_START_PLAYBACK
+Enum 	1/0x01
+Description
+	Begin or resume playback.
+Param[0]
+	0 based frame number in GOP to begin playback from.
+Param[1]
+	Specifies the number of muted audio frames to play before normal
+	audio resumes.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_STOP_PLAYBACK
+Enum 	2/0x02
+Description
+	Ends playback and clears all decoder buffers. If PTS is not zero,
+	playback stops at specified PTS.
+Param[0]
+	Display 0=last frame, 1=black
+Param[1]
+	PTS low
+Param[2]
+	PTS high
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_PLAYBACK_SPEED
+Enum 	3/0x03
+Description
+	Playback stream at speed other than normal. There are two modes of
+	operation:
+	    Smooth: host transfers entire stream and firmware drops unused
+		    frames.
+	    Coarse: host drops frames based on indexing as required to achieve
+		    desired speed.
+Param[0]
+	Bitmap:
+	    0:7  0 normal
+		 1 fast only "1.5 times"
+		 n nX fast, 1/nX slow
+	    30   Framedrop:
+		     '0' during 1.5 times play, every other B frame is dropped
+		     '1' during 1.5 times play, stream is unchanged (bitrate
+			 must not exceed 8mbps)
+	    31   Speed:
+		     '0' slow
+		     '1' fast
+Param[1]
+	Direction: 0=forward, 1=reverse
+Param[2]
+	Picture mask:
+	    1=I frames
+	    3=I, P frames
+	    7=I, P, B frames
+Param[3]
+	B frames per GOP (for reverse play only)
+Param[4]
+	Mute audio: 0=disable, 1=enable
+Param[5]
+	Display 0=frame, 1=field
+Param[6]
+	Specifies the number of muted audio frames to play before normal audio
+	resumes.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_STEP_VIDEO
+Enum 	5/0x05
+Description
+	Each call to this API steps the playback to the next unit defined below
+	in the current playback direction.
+Param[0]
+	0=frame, 1=top field, 2=bottom field
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_DMA_BLOCK_SIZE
+Enum 	8/0x08
+Description
+	Set DMA transfer block size. Counterpart to API 0xC9
+Param[0]
+	DMA transfer block size in bytes. A different size may be specified
+	when issuing the DMA transfer command.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_GET_XFER_INFO
+Enum 	9/0x09
+Description
+	This API call may be used to detect an end of stream condtion.
+Result[0]
+	Stream type
+Result[1]
+	Address offset
+Result[2]
+	Maximum bytes to transfer
+Result[3]
+	Buffer fullness
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_GET_DMA_STATUS
+Enum 	10/0x0A
+Description
+	Status of the last DMA transfer
+Result[0]
+	Bit 1 set means transfer complete
+	Bit 2 set means DMA error
+	Bit 3 set means linked list error
+Result[1]
+	DMA type: 0=MPEG, 1=OSD, 2=YUV
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SCHED_DMA_FROM_HOST
+Enum 	11/0x0B
+Description
+	Setup DMA from host operation. Counterpart to API 0xCC
+Param[0]
+	Memory address of link list
+Param[1]
+	Total # of bytes to transfer
+Param[2]
+	DMA type (0=MPEG, 1=OSD, 2=YUV)
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_PAUSE_PLAYBACK
+Enum 	13/0x0D
+Description
+	Freeze playback immediately. In this mode, when internal buffers are
+	full, no more data will be accepted and data request IRQs will be
+	masked.
+Param[0]
+	Display: 0=last frame, 1=black
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_HALT_FW
+Enum 	14/0x0E
+Description
+	The firmware is halted and no further API calls are serviced until
+	the firmware is uploaded again.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_STANDARD
+Enum 	16/0x10
+Description
+	Selects display standard
+Param[0]
+	0=NTSC, 1=PAL
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_GET_VERSION
+Enum 	17/0x11
+Description
+	Returns decoder firmware version information
+Result[0]
+	Version bitmask:
+	    Bits  0:15 build
+	    Bits 16:23 minor
+	    Bits 24:31 major
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_STREAM_INPUT
+Enum 	20/0x14
+Description
+	Select decoder stream input port
+Param[0]
+	0=memory (default), 1=streaming
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_GET_TIMING_INFO
+Enum 	21/0x15
+Description
+	Returns timing information from start of playback
+Result[0]
+	Frame count by decode order
+Result[1]
+	Video PTS bits 0:31 by display order
+Result[2]
+	Video PTS bit 32 by display order
+Result[3]
+	SCR bits 0:31 by display order
+Result[4]
+	SCR bit 32 by display order
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_AUDIO_MODE
+Enum 	22/0x16
+Description
+	Select audio mode
+Param[0]
+	Dual mono mode action
+Param[1]
+	Stereo mode action:
+	    0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_EVENT_NOTIFICATION
+Enum 	23/0x17
+Description
+	Setup firmware to notify the host about a particular event.
+	Counterpart to API 0xD5
+Param[0]
+	Event: 0=Audio mode change between stereo and dual channel
+Param[1]
+	Notification 0=disabled, 1=enabled
+Param[2]
+	Interrupt bit
+Param[3]
+	Mailbox slot, -1 if no mailbox required.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_DISPLAY_BUFFERS
+Enum 	24/0x18
+Description
+	Number of display buffers. To decode all frames in reverse playback you
+	must use nine buffers.
+Param[0]
+	0=six buffers, 1=nine buffers
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_EXTRACT_VBI
+Enum 	25/0x19
+Description
+	Extracts VBI data
+Param[0]
+	0=extract from extension & user data, 1=extract from private packets
+Result[0]
+	VBI table location
+Result[1]
+	VBI table size
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_DECODER_SOURCE
+Enum 	26/0x1A
+Description
+	Selects decoder source. Ensure that the parameters passed to this
+	API match the encoder settings.
+Param[0]
+	Mode: 0=MPEG from host, 1=YUV from encoder, 2=YUV from host
+Param[1]
+	YUV picture width
+Param[2]
+	YUV picture height
+Param[3]
+	Bitmap: see Param[0] of API 0xBD
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_AUDIO_OUTPUT
+Enum 	27/0x1B
+Description
+	Select audio output format
+Param[0]
+	Bitmask:
+	     0:1  Data size:
+		      '00' 16 bit
+		      '01' 20 bit
+		      '10' 24 bit
+	     2:7  Unused
+	     8:9  Mode:
+		      '00' 2 channels
+		      '01' 4 channels
+		      '10' 6 channels
+		      '11' 6 channels with one line data mode
+			   (for left justified MSB first mode, 20 bit only)
+	    10:11 Unused
+	    12:13 Channel format:
+		      '00' right justified MSB first mode
+		      '01' left justified MSB first mode
+		      '10' I2S mode
+	    14:15 Unused
+	    16:21 Right justify bit count
+	    22:31 Unused
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_AV_DELAY
+Enum 	28/0x1C
+Description
+	Set audio/video delay in 90Khz ticks
+Param[0]
+	0=A/V in sync, negative=audio lags, positive=video lags
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_PREBUFFERING
+Enum 	30/0x1E
+Description
+	Decoder prebuffering, when enabled up to 128KB are buffered for
+	streams <8mpbs or 640KB for streams >8mbps
+Param[0]
+	0=off, 1=on

+ 94 - 0
Documentation/video4linux/cx2341x/fw-dma.txt

@@ -0,0 +1,94 @@
+This page describes the structures and procedures used by the cx2341x DMA
+engine.
+
+Introduction
+============
+
+The cx2341x PCI interface is busmaster capable. This means it has a DMA
+engine to efficiently transfer large volumes of data between the card and main
+memory without requiring help from a CPU. Like most hardware, it must operate
+on contiguous physical memory. This is difficult to come by in large quantities
+on virtual memory machines.
+
+Therefore, it also supports a technique called "scatter-gather". The card can
+transfer multiple buffers in one operation. Instead of allocating one large
+contiguous buffer, the driver can allocate several smaller buffers.
+
+In practice, I've seen the average transfer to be roughly 80K, but transfers
+above 128K were not uncommon, particularly at startup. The 128K figure is
+important, because that is the largest block that the kernel can normally
+allocate. Even still, 128K blocks are hard to come by, so the driver writer is
+urged to choose a smaller block size and learn the scatter-gather technique.
+
+Mailbox #10 is reserved for DMA transfer information.
+
+Flow
+====
+
+This section describes, in general, the order of events when handling DMA
+transfers. Detailed information follows this section.
+
+- The card raises the Encoder interrupt.
+- The driver reads the transfer type, offset and size from Mailbox #10.
+- The driver constructs the scatter-gather array from enough free dma buffers
+  to cover the size.
+- The driver schedules the DMA transfer via the ScheduleDMAtoHost API call.
+- The card raises the DMA Complete interrupt.
+- The driver checks the DMA status register for any errors.
+- The driver post-processes the newly transferred buffers.
+
+NOTE! It is possible that the Encoder and DMA Complete interrupts get raised
+simultaneously. (End of the last, start of the next, etc.)
+
+Mailbox #10
+===========
+
+The Flags, Command, Return Value and Timeout fields are ignored.
+
+Name:       Mailbox #10
+Results[0]: Type: 0: MPEG.
+Results[1]: Offset: The position relative to the card's memory space.
+Results[2]: Size: The exact number of bytes to transfer.
+
+My speculation is that since the StartCapture API has a capture type of "RAW"
+available, that the type field will have other values that correspond to YUV
+and PCM data.
+
+Scatter-Gather Array
+====================
+
+The scatter-gather array is a contiguously allocated block of memory that
+tells the card the source and destination of each data-block to transfer.
+Card "addresses" are derived from the offset supplied by Mailbox #10. Host
+addresses are the physical memory location of the target DMA buffer.
+
+Each S-G array element is a struct of three 32-bit words. The first word is
+the source address, the second is the destination address. Both take up the
+entire 32 bits. The lowest 16 bits of the third word is the transfer byte
+count. The high-bit of the third word is the "last" flag. The last-flag tells
+the card to raise the DMA_DONE interrupt. From hard personal experience, if
+you forget to set this bit, the card will still "work" but the stream will
+most likely get corrupted.
+
+The transfer count must be a multiple of 256. Therefore, the driver will need
+to track how much data in the target buffer is valid and deal with it
+accordingly.
+
+Array Element:
+
+- 32-bit Source Address
+- 32-bit Destination Address
+- 16-bit reserved (high bit is the last flag)
+- 16-bit byte count
+
+DMA Transfer Status
+===================
+
+Register 0x0004 holds the DMA Transfer Status:
+
+Bit
+4   Scatter-Gather array error
+3   DMA write error
+2   DMA read error
+1   write completed
+0   read completed

+ 694 - 0
Documentation/video4linux/cx2341x/fw-encoder-api.txt

@@ -0,0 +1,694 @@
+Encoder firmware API description
+================================
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_PING_FW
+Enum 	128/0x80
+Description
+	Does nothing. Can be used to check if the firmware is responding.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_START_CAPTURE
+Enum 	129/0x81
+Description
+	Commences the capture of video, audio and/or VBI data. All encoding
+	parameters must be initialized prior to this API call. Captures frames
+	continuously or until a predefined number of frames have been captured.
+Param[0]
+	Capture stream type:
+	    0=MPEG
+	    1=Raw
+	    2=Raw passthrough
+	    3=VBI
+
+Param[1]
+	Bitmask:
+	    Bit 0 when set, captures YUV
+	    Bit 1 when set, captures PCM audio
+	    Bit 2 when set, captures VBI (same as param[0]=3)
+	    Bit 3 when set, the capture destination is the decoder
+		(same as param[0]=2)
+	    Bit 4 when set, the capture destination is the host
+	Note: this parameter is only meaningful for RAW capture type.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_STOP_CAPTURE
+Enum 	130/0x82
+Description
+	Ends a capture in progress
+Param[0]
+	0=stop at end of GOP (generates IRQ)
+	1=stop immediate (no IRQ)
+Param[1]
+	Stream type to stop, see param[0] of API 0x81
+Param[2]
+	Subtype, see param[1] of API 0x81
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_AUDIO_ID
+Enum 	137/0x89
+Description
+	Assigns the transport stream ID of the encoded audio stream
+Param[0]
+	Audio Stream ID
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_VIDEO_ID
+Enum 	139/0x8B
+Description
+	Set video transport stream ID
+Param[0]
+	Video stream ID
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_PCR_ID
+Enum 	141/0x8D
+Description
+	Assigns the transport stream ID for PCR packets
+Param[0]
+	PCR Stream ID
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_FRAME_RATE
+Enum 	143/0x8F
+Description
+	Set video frames per second. Change occurs at start of new GOP.
+Param[0]
+	0=30fps
+	1=25fps
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_FRAME_SIZE
+Enum 	145/0x91
+Description
+	Select video stream encoding resolution.
+Param[0]
+	Height in lines. Default 480
+Param[1]
+	Width in pixels. Default 720
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_BIT_RATE
+Enum 	149/0x95
+Description
+	Assign average video stream bitrate. Note on the last three params:
+	Param[3] and [4] seem to be always 0, param [5] doesn't seem to be used.
+Param[0]
+	0=variable bitrate, 1=constant bitrate
+Param[1]
+	bitrate in bits per second
+Param[2]
+	peak bitrate in bits per second, divided by 400
+Param[3]
+	Mux bitrate in bits per second, divided by 400. May be 0 (default).
+Param[4]
+	Rate Control VBR Padding
+Param[5]
+	VBV Buffer used by encoder
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_GOP_PROPERTIES
+Enum 	151/0x97
+Description
+	Setup the GOP structure
+Param[0]
+	GOP size (maximum is 34)
+Param[1]
+	Number of B frames between the I and P frame, plus 1.
+	For example: IBBPBBPBBPBB --> GOP size: 12, number of B frames: 2+1 = 3
+	Note that GOP size must be a multiple of (B-frames + 1).
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_ASPECT_RATIO
+Enum 	153/0x99
+Description
+	Sets the encoding aspect ratio. Changes in the aspect ratio take effect
+	at the start of the next GOP.
+Param[0]
+	'0000' forbidden
+	'0001' 1:1 square
+	'0010' 4:3
+	'0011' 16:9
+	'0100' 2.21:1
+	'0101' reserved
+	 ....
+	'1111' reserved
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_DNR_FILTER_MODE
+Enum 	155/0x9B
+Description
+	Assign Dynamic Noise Reduction operating mode
+Param[0]
+	Bit0: Spatial filter, set=auto, clear=manual
+	Bit1: Temporal filter, set=auto, clear=manual
+Param[1]
+	Median filter:
+	    0=Disabled
+	    1=Horizontal
+	    2=Vertical
+	    3=Horiz/Vert
+	    4=Diagonal
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_DNR_FILTER_PROPS
+Enum 	157/0x9D
+Description
+	These Dynamic Noise Reduction filter values are only meaningful when
+	the respective filter is set to "manual" (See API 0x9B)
+Param[0]
+	Spatial filter: default 0, range 0:15
+Param[1]
+	Temporal filter: default 0, range 0:31
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_CORING_LEVELS
+Enum 	159/0x9F
+Description
+	Assign Dynamic Noise Reduction median filter properties.
+Param[0]
+	Threshold above which the luminance median filter is enabled.
+	Default: 0, range 0:255
+Param[1]
+	Threshold below which the luminance median filter is enabled.
+	Default: 255, range 0:255
+Param[2]
+	Threshold above which the chrominance median filter is enabled.
+	Default: 0, range 0:255
+Param[3]
+	Threshold below which the chrominance median filter is enabled.
+	Default: 255, range 0:255
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_SPATIAL_FILTER_TYPE
+Enum 	161/0xA1
+Description
+	Assign spatial prefilter parameters
+Param[0]
+	Luminance filter
+	    0=Off
+	    1=1D Horizontal
+	    2=1D Vertical
+	    3=2D H/V Separable (default)
+	    4=2D Symmetric non-separable
+Param[1]
+	Chrominance filter
+	    0=Off
+	    1=1D Horizontal (default)
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_3_2_PULLDOWN
+Enum 	177/0xB1
+Description
+	3:2 pulldown properties
+Param[0]
+	0=enabled
+	1=disabled
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_VBI_LINE
+Enum 	183/0xB7
+Description
+	Selects VBI line number.
+Param[0]
+	Bits 0:4 	line number
+	Bit  31		0=top_field, 1=bottom_field
+	Bits 0:31 	all set specifies "all lines"
+Param[1]
+	VBI line information features: 0=disabled, 1=enabled
+Param[2]
+	Slicing: 0=None, 1=Closed Caption
+	Almost certainly not implemented. Set to 0.
+Param[3]
+	Luminance samples in this line.
+	Almost certainly not implemented. Set to 0.
+Param[4]
+	Chrominance samples in this line
+	Almost certainly not implemented. Set to 0.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_STREAM_TYPE
+Enum 	185/0xB9
+Description
+	Assign stream type
+	Note: Transport stream is not working in recent firmwares.
+	And in older firmwares the timestamps in the TS seem to be
+	unreliable.
+Param[0]
+	 0=Program stream
+	 1=Transport stream
+	 2=MPEG1 stream
+	 3=PES A/V stream
+	 5=PES Video stream
+	 7=PES Audio stream
+	10=DVD stream
+	11=VCD stream
+	12=SVCD stream
+	13=DVD_S1 stream
+	14=DVD_S2 stream
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_OUTPUT_PORT
+Enum 	187/0xBB
+Description
+	Assign stream output port. Normally 0 when the data is copied through
+	the PCI bus (DMA), and 1 when the data is streamed to another chip
+	(pvrusb and cx88-blackbird).
+Param[0]
+	0=Memory (default)
+	1=Streaming
+	2=Serial
+Param[1]
+	Unknown, but leaving this to 0 seems to work best. Indications are that
+	this might have to do with USB support, although passing anything but 0
+	onl breaks things.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_AUDIO_PROPERTIES
+Enum 	189/0xBD
+Description
+	Set audio stream properties, may be called while encoding is in progress.
+	Note: all bitfields are consistent with ISO11172 documentation except
+	bits 2:3 which ISO docs define as:
+		'11' Layer I
+		'10' Layer II
+		'01' Layer III
+		'00' Undefined
+	This discrepancy may indicate a possible error in the documentation.
+	Testing indicated that only Layer II is actually working, and that
+	the minimum bitrate should be 192 kbps.
+Param[0]
+	Bitmask:
+	   0:1  '00' 44.1Khz
+		'01' 48Khz
+		'10' 32Khz
+		'11' reserved
+
+	   2:3  '01'=Layer I
+		'10'=Layer II
+
+	   4:7  Bitrate:
+		     Index | Layer I     | Layer II
+		     ------+-------------+------------
+		    '0000' | free format | free format
+		    '0001' |  32 kbit/s  |  32 kbit/s
+		    '0010' |  64 kbit/s  |  48 kbit/s
+		    '0011' |  96 kbit/s  |  56 kbit/s
+		    '0100' | 128 kbit/s  |  64 kbit/s
+		    '0101' | 160 kbit/s  |  80 kbit/s
+		    '0110' | 192 kbit/s  |  96 kbit/s
+		    '0111' | 224 kbit/s  | 112 kbit/s
+		    '1000' | 256 kbit/s  | 128 kbit/s
+		    '1001' | 288 kbit/s  | 160 kbit/s
+		    '1010' | 320 kbit/s  | 192 kbit/s
+		    '1011' | 352 kbit/s  | 224 kbit/s
+		    '1100' | 384 kbit/s  | 256 kbit/s
+		    '1101' | 416 kbit/s  | 320 kbit/s
+		    '1110' | 448 kbit/s  | 384 kbit/s
+		Note: For Layer II, not all combinations of total bitrate
+		and mode are allowed. See ISO11172-3 3-Annex B, Table 3-B.2
+
+	   8:9  '00'=Stereo
+		'01'=JointStereo
+		'10'=Dual
+		'11'=Mono
+		Note: testing seems to indicate that Mono and possibly
+		JointStereo are not working (default to stereo).
+		Dual does work, though.
+
+	  10:11 Mode Extension used in joint_stereo mode.
+		In Layer I and II they indicate which subbands are in
+		intensity_stereo. All other subbands are coded in stereo.
+		    '00' subbands 4-31 in intensity_stereo, bound==4
+		    '01' subbands 8-31 in intensity_stereo, bound==8
+		    '10' subbands 12-31 in intensity_stereo, bound==12
+		    '11' subbands 16-31 in intensity_stereo, bound==16
+
+	  12:13 Emphasis:
+		    '00' None
+		    '01' 50/15uS
+		    '10' reserved
+		    '11' CCITT J.17
+
+	  14 	CRC:
+		    '0' off
+		    '1' on
+
+	  15    Copyright:
+		    '0' off
+		    '1' on
+
+	  16    Generation:
+		    '0' copy
+		    '1' original
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_HALT_FW
+Enum 	195/0xC3
+Description
+	The firmware is halted and no further API calls are serviced until the
+	firmware is uploaded again.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_GET_VERSION
+Enum 	196/0xC4
+Description
+	Returns the version of the encoder firmware.
+Result[0]
+	Version bitmask:
+	    Bits  0:15 build
+	    Bits 16:23 minor
+	    Bits 24:31 major
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_GOP_CLOSURE
+Enum 	197/0xC5
+Description
+	Assigns the GOP open/close property.
+Param[0]
+	0=Open
+	1=Closed
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_GET_SEQ_END
+Enum 	198/0xC6
+Description
+	Obtains the sequence end code of the encoder's buffer. When a capture
+	is started a number of interrupts are still generated, the last of
+	which will have Result[0] set to 1 and Result[1] will contain the size
+	of the buffer.
+Result[0]
+	State of the transfer (1 if last buffer)
+Result[1]
+	If Result[0] is 1, this contains the size of the last buffer, undefined
+	otherwise.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_PGM_INDEX_INFO
+Enum 	199/0xC7
+Description
+	Sets the Program Index Information.
+Param[0]
+	Picture Mask:
+	    0=No index capture
+	    1=I frames
+	    3=I,P frames
+	    7=I,P,B frames
+Param[1]
+	Elements requested (up to 400)
+Result[0]
+	Offset in SDF memory of the table.
+Result[1]
+	Number of allocated elements up to a maximum of Param[1]
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_VBI_CONFIG
+Enum 	200/0xC8
+Description
+	Configure VBI settings
+Param[0]
+	Bitmap:
+	    0    Mode '0' Sliced, '1' Raw
+	    1:3  Insertion:
+		     '000' insert in extension & user data
+		     '001' insert in private packets
+		     '010' separate stream and user data
+		     '111' separate stream and private data
+	    8:15 Stream ID (normally 0xBD)
+Param[1]
+	Frames per interrupt (max 8). Only valid in raw mode.
+Param[2]
+	Total raw VBI frames. Only valid in raw mode.
+Param[3]
+	Start codes
+Param[4]
+	Stop codes
+Param[5]
+	Lines per frame
+Param[6]
+	Byte per line
+Result[0]
+	Observed frames per interrupt in raw mode only. Rage 1 to Param[1]
+Result[1]
+	Observed number of frames in raw mode. Range 1 to Param[2]
+Result[2]
+	Memory offset to start or raw VBI data
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_DMA_BLOCK_SIZE
+Enum 	201/0xC9
+Description
+	Set DMA transfer block size
+Param[0]
+	DMA transfer block size in bytes or frames. When unit is bytes,
+	supported block sizes are 2^7, 2^8 and 2^9 bytes.
+Param[1]
+	Unit: 0=bytes, 1=frames
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_GET_PREV_DMA_INFO_MB_10
+Enum 	202/0xCA
+Description
+	Returns information on the previous DMA transfer in conjunction with
+	bit 27 of the interrupt mask. Uses mailbox 10.
+Result[0]
+	Type of stream
+Result[1]
+	Address Offset
+Result[2]
+	Maximum size of transfer
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_GET_PREV_DMA_INFO_MB_9
+Enum 	203/0xCB
+Description
+	Returns information on the previous DMA transfer in conjunction with
+	bit 27 of the interrupt mask. Uses mailbox 9.
+Result[0]
+	Status bits:
+	    Bit 0 set indicates transfer complete
+	    Bit 2 set indicates transfer error
+	    Bit 4 set indicates linked list error
+Result[1]
+	DMA type
+Result[2]
+	Presentation Time Stamp bits 0..31
+Result[3]
+	Presentation Time Stamp bit 32
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SCHED_DMA_TO_HOST
+Enum 	204/0xCC
+Description
+	Setup DMA to host operation
+Param[0]
+	Memory address of link list
+Param[1]
+	Length of link list (wtf: what units ???)
+Param[2]
+	DMA type (0=MPEG)
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_INITIALIZE_INPUT
+Enum 	205/0xCD
+Description
+	Initializes the video input
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_FRAME_DROP_RATE
+Enum 	208/0xD0
+Description
+	For each frame captured, skip specified number of frames.
+Param[0]
+	Number of frames to skip
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_PAUSE_ENCODER
+Enum 	210/0xD2
+Description
+	During a pause condition, all frames are dropped instead of being encoded.
+Param[0]
+	0=Pause encoding
+	1=Continue encoding
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_REFRESH_INPUT
+Enum 	211/0xD3
+Description
+	Refreshes the video input
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_COPYRIGHT
+Enum 	212/0xD4
+Description
+	Sets stream copyright property
+Param[0]
+	0=Stream is not copyrighted
+	1=Stream is copyrighted
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_EVENT_NOTIFICATION
+Enum 	213/0xD5
+Description
+	Setup firmware to notify the host about a particular event. Host must
+	unmask the interrupt bit.
+Param[0]
+	Event (0=refresh encoder input)
+Param[1]
+	Notification 0=disabled 1=enabled
+Param[2]
+	Interrupt bit
+Param[3]
+	Mailbox slot, -1 if no mailbox required.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_NUM_VSYNC_LINES
+Enum 	214/0xD6
+Description
+	Depending on the analog video decoder used, this assigns the number
+	of lines for field 1 and 2.
+Param[0]
+	Field 1 number of lines:
+	    0x00EF for SAA7114
+	    0x00F0 for SAA7115
+	    0x0105 for Micronas
+Param[1]
+	Field 2 number of lines:
+	    0x00EF for SAA7114
+	    0x00F0 for SAA7115
+	    0x0106 for Micronas
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_PLACEHOLDER
+Enum 	215/0xD7
+Description
+	Provides a mechanism of inserting custom user data in the MPEG stream.
+Param[0]
+	0=extension & user data
+	1=private packet with stream ID 0xBD
+Param[1]
+	Rate at which to insert data, in units of frames (for private packet)
+	or GOPs (for ext. & user data)
+Param[2]
+	Number of data DWORDs (below) to insert
+Param[3]
+	Custom data 0
+Param[4]
+	Custom data 1
+Param[5]
+	Custom data 2
+Param[6]
+	Custom data 3
+Param[7]
+	Custom data 4
+Param[8]
+	Custom data 5
+Param[9]
+	Custom data 6
+Param[10]
+	Custom data 7
+Param[11]
+	Custom data 8
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_MUTE_VIDEO
+Enum 	217/0xD9
+Description
+	Video muting
+Param[0]
+	Bit usage:
+	 0    	'0'=video not muted
+		'1'=video muted, creates frames with the YUV color defined below
+	 1:7  	Unused
+	 8:15 	V chrominance information
+	16:23 	U chrominance information
+	24:31 	Y luminance information
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_MUTE_AUDIO
+Enum 	218/0xDA
+Description
+	Audio muting
+Param[0]
+	0=audio not muted
+	1=audio muted (produces silent mpeg audio stream)
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_UNKNOWN
+Enum 	219/0xDB
+Description
+	Unknown API, it's used by Hauppauge though.
+Param[0]
+	0 This is the value Hauppauge uses, Unknown what it means.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_MISC
+Enum 	220/0xDC
+Description
+	Miscellaneous actions. Not known for 100% what it does. It's really a
+	sort of ioctl call. The first parameter is a command number, the second
+	the value.
+Param[0]
+	Command number:
+	 1=set initial SCR value when starting encoding.
+	 2=set quality mode (apparently some test setting).
+	 3=setup advanced VIM protection handling (supposedly only for the cx23416
+	   for raw YUV).
+	   Actually it looks like this should be 0 for saa7114/5 based card and 1
+	   for cx25840 based cards.
+	 4=generate artificial PTS timestamps
+	 5=USB flush mode
+	 6=something to do with the quantization matrix
+	 7=set navigation pack insertion for DVD
+	 8=enable scene change detection (seems to be a failure)
+	 9=set history parameters of the video input module
+	10=set input field order of VIM
+	11=set quantization matrix
+	12=reset audio interface
+	13=set audio volume delay
+	14=set audio delay
+
+Param[1]
+	Command value.

+ 141 - 0
Documentation/video4linux/cx2341x/fw-memory.txt

@@ -0,0 +1,141 @@
+This document describes the cx2341x memory map and documents some of the register
+space.
+
+Warning! This information was figured out from searching through the memory and
+registers, this information may not be correct and is certainly not complete, and
+was not derived from anything more than searching through the memory space with
+commands like:
+
+	ivtvctl -O min=0x02000000,max=0x020000ff
+
+So take this as is, I'm always searching for more stuff, it's a large
+register space :-).
+
+Memory Map
+==========
+
+The cx2341x exposes its entire 64M memory space to the PCI host via the PCI BAR0
+(Base Address Register 0). The addresses here are offsets relative to the
+address held in BAR0.
+
+0x00000000-0x00ffffff Encoder memory space
+0x00000000-0x0003ffff Encode.rom
+      ???-???         MPEG buffer(s)
+      ???-???         Raw video capture buffer(s)
+      ???-???         Raw audio capture buffer(s)
+      ???-???         Display buffers (6 or 9)
+
+0x01000000-0x01ffffff Decoder memory space
+0x01000000-0x0103ffff Decode.rom
+      ???-???         MPEG buffers(s)
+0x0114b000-0x0115afff Audio.rom (deprecated?)
+
+0x02000000-0x0200ffff Register Space
+
+Registers
+=========
+
+The registers occupy the 64k space starting at the 0x02000000 offset from BAR0.
+All of these registers are 32 bits wide.
+
+DMA Registers 0x000-0xff:
+
+ 0x00 - Control:
+	0=reset/cancel, 1=read, 2=write, 4=stop
+ 0x04 - DMA status:
+	1=read busy, 2=write busy, 4=read error, 8=write error, 16=link list error
+ 0x08 - pci DMA pointer for read link list
+ 0x0c - pci DMA pointer for write link list
+ 0x10 - read/write DMA enable:
+	1=read enable, 2=write enable
+ 0x14 - always 0xffffffff, if set any lower instability occurs, 0x00 crashes
+ 0x18 - ??
+ 0x1c - always 0x20 or 32, smaller values slow down DMA transactions
+ 0x20 - always value of 0x780a010a
+ 0x24-0x3c - usually just random values???
+ 0x40 - Interrupt status
+ 0x44 - Write a bit here and shows up in Interrupt status 0x40
+ 0x48 - Interrupt Mask
+ 0x4C - always value of 0xfffdffff,
+	if changed to 0xffffffff DMA write interrupts break.
+ 0x50 - always 0xffffffff
+ 0x54 - always 0xffffffff (0x4c, 0x50, 0x54 seem like interrupt masks, are
+	3 processors on chip, Java ones, VPU, SPU, APU, maybe these are the
+	interrupt masks???).
+ 0x60-0x7C - random values
+ 0x80 - first write linked list reg, for Encoder Memory addr
+ 0x84 - first write linked list reg, for pci memory addr
+ 0x88 - first write linked list reg, for length of buffer in memory addr
+	(|0x80000000 or this for last link)
+ 0x8c-0xcc - rest of write linked list reg, 8 sets of 3 total, DMA goes here
+	from linked list addr in reg 0x0c, firmware must push through or
+	something.
+ 0xe0 - first (and only) read linked list reg, for pci memory addr
+ 0xe4 - first (and only) read linked list reg, for Decoder memory addr
+ 0xe8 - first (and only) read linked list reg, for length of buffer
+ 0xec-0xff - Nothing seems to be in these registers, 0xec-f4 are 0x00000000.
+
+Memory locations for Encoder Buffers 0x700-0x7ff:
+
+These registers show offsets of memory locations pertaining to each
+buffer area used for encoding, have to shift them by <<1 first.
+
+0x07F8: Encoder SDRAM refresh
+0x07FC: Encoder SDRAM pre-charge
+
+Memory locations for Decoder Buffers 0x800-0x8ff:
+
+These registers show offsets of memory locations pertaining to each
+buffer area used for decoding, have to shift them by <<1 first.
+
+0x08F8: Decoder SDRAM refresh
+0x08FC: Decoder SDRAM pre-charge
+
+Other memory locations:
+
+0x2800: Video Display Module control
+0x2D00: AO (audio output?) control
+0x2D24: Bytes Flushed
+0x7000: LSB I2C write clock bit (inverted)
+0x7004: LSB I2C write data bit (inverted)
+0x7008: LSB I2C read clock bit
+0x700c: LSB I2C read data bit
+0x9008: GPIO get input state
+0x900c: GPIO set output state
+0x9020: GPIO direction (Bit7 (GPIO 0..7) - 0:input, 1:output)
+0x9050: SPU control
+0x9054: Reset HW blocks
+0x9058: VPU control
+0xA018: Bit6: interrupt pending?
+0xA064: APU command
+
+
+Interrupt Status Register
+=========================
+
+The definition of the bits in the interrupt status register 0x0040, and the
+interrupt mask 0x0048. If a bit is cleared in the mask, then we want our ISR to
+execute.
+
+Bit
+31 Encoder Start Capture
+30 Encoder EOS
+29 Encoder VBI capture
+28 Encoder Video Input Module reset event
+27 Encoder DMA complete
+26
+25 Decoder copy protect detection event
+24 Decoder audio mode change detection event
+23
+22 Decoder data request
+21 Decoder I-Frame? done
+20 Decoder DMA complete
+19 Decoder VBI re-insertion
+18 Decoder DMA err (linked-list bad)
+
+Missing
+Encoder API call completed
+Decoder API call completed
+Encoder API post(?)
+Decoder API post(?)
+Decoder VTRACE event

+ 342 - 0
Documentation/video4linux/cx2341x/fw-osd-api.txt

@@ -0,0 +1,342 @@
+OSD firmware API description
+============================
+
+Note: this API is part of the decoder firmware, so it's cx23415 only.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_FRAMEBUFFER
+Enum 	65/0x41
+Description
+	Return base and length of contiguous OSD memory.
+Result[0]
+	OSD base address
+Result[1]
+	OSD length
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_PIXEL_FORMAT
+Enum 	66/0x42
+Description
+	Query OSD format
+Result[0]
+	0=8bit index, 4=AlphaRGB 8:8:8:8
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_PIXEL_FORMAT
+Enum 	67/0x43
+Description
+	Assign pixel format
+Param[0]
+	0=8bit index, 4=AlphaRGB 8:8:8:8
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_STATE
+Enum 	68/0x44
+Description
+	Query OSD state
+Result[0]
+	Bit  0   0=off, 1=on
+	Bits 1:2 alpha control
+	Bits 3:5 pixel format
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_STATE
+Enum 	69/0x45
+Description
+	OSD switch
+Param[0]
+	0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_OSD_COORDS
+Enum 	70/0x46
+Description
+	Retrieve coordinates of OSD area blended with video
+Result[0]
+	OSD buffer address
+Result[1]
+	Stride in pixels
+Result[2]
+	Lines in OSD buffer
+Result[3]
+	Horizontal offset in buffer
+Result[4]
+	Vertical offset in buffer
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_OSD_COORDS
+Enum 	71/0x47
+Description
+	Assign the coordinates of the OSD area to blend with video
+Param[0]
+	buffer address
+Param[1]
+	buffer stride in pixels
+Param[2]
+	lines in buffer
+Param[3]
+	horizontal offset
+Param[4]
+	vertical offset
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_SCREEN_COORDS
+Enum 	72/0x48
+Description
+	Retrieve OSD screen area coordinates
+Result[0]
+	top left horizontal offset
+Result[1]
+	top left vertical offset
+Result[2]
+	bottom right hotizontal offset
+Result[3]
+	bottom right vertical offset
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_SCREEN_COORDS
+Enum 	73/0x49
+Description
+	Assign the coordinates of the screen area to blend with video
+Param[0]
+	top left horizontal offset
+Param[1]
+	top left vertical offset
+Param[2]
+	bottom left horizontal offset
+Param[3]
+	bottom left vertical offset
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_GLOBAL_ALPHA
+Enum 	74/0x4A
+Description
+	Retrieve OSD global alpha
+Result[0]
+	global alpha: 0=off, 1=on
+Result[1]
+	bits 0:7 global alpha
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_GLOBAL_ALPHA
+Enum 	75/0x4B
+Description
+	Update global alpha
+Param[0]
+	global alpha: 0=off, 1=on
+Param[1]
+	global alpha (8 bits)
+Param[2]
+	local alpha: 0=on, 1=off
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_BLEND_COORDS
+Enum 	78/0x4C
+Description
+	Move start of blending area within display buffer
+Param[0]
+	horizontal offset in buffer
+Param[1]
+	vertical offset in buffer
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_FLICKER_STATE
+Enum 	79/0x4F
+Description
+	Retrieve flicker reduction module state
+Result[0]
+	flicker state: 0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_FLICKER_STATE
+Enum 	80/0x50
+Description
+	Set flicker reduction module state
+Param[0]
+	State: 0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_BLT_COPY
+Enum 	82/0x52
+Description
+	BLT copy
+Param[0]
+'0000'  zero
+'0001' ~destination AND ~source
+'0010' ~destination AND  source
+'0011' ~destination
+'0100'  destination AND ~source
+'0101'                  ~source
+'0110'  destination XOR  source
+'0111' ~destination OR  ~source
+'1000' ~destination AND ~source
+'1001'  destination XNOR source
+'1010'                   source
+'1011' ~destination OR   source
+'1100'  destination
+'1101'  destination OR  ~source
+'1110'  destination OR   source
+'1111'  one
+
+Param[1]
+	Resulting alpha blending
+	    '01' source_alpha
+	    '10' destination_alpha
+	    '11' source_alpha*destination_alpha+1
+		 (zero if both source and destination alpha are zero)
+Param[2]
+	'00' output_pixel = source_pixel
+
+	'01' if source_alpha=0:
+		 output_pixel = destination_pixel
+	     if 256 > source_alpha > 1:
+		 output_pixel = ((source_alpha + 1)*source_pixel +
+				 (255 - source_alpha)*destination_pixel)/256
+
+	'10' if destination_alpha=0:
+		 output_pixel = source_pixel
+	      if 255 > destination_alpha > 0:
+		 output_pixel = ((255 - destination_alpha)*source_pixel +
+				 (destination_alpha + 1)*destination_pixel)/256
+
+	'11' if source_alpha=0:
+		 source_temp = 0
+	     if source_alpha=255:
+		 source_temp = source_pixel*256
+	     if 255 > source_alpha > 0:
+		 source_temp = source_pixel*(source_alpha + 1)
+	     if destination_alpha=0:
+		 destination_temp = 0
+	     if destination_alpha=255:
+		 destination_temp = destination_pixel*256
+	     if 255 > destination_alpha > 0:
+		 destination_temp = destination_pixel*(destination_alpha + 1)
+	     output_pixel = (source_temp + destination_temp)/256
+Param[3]
+	width
+Param[4]
+	height
+Param[5]
+	destination pixel mask
+Param[6]
+	destination rectangle start address
+Param[7]
+	destination stride in dwords
+Param[8]
+	source stride in dwords
+Param[9]
+	source rectangle start address
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_BLT_FILL
+Enum 	83/0x53
+Description
+	BLT fill color
+Param[0]
+	Same as Param[0] on API 0x52
+Param[1]
+	Same as Param[1] on API 0x52
+Param[2]
+	Same as Param[2] on API 0x52
+Param[3]
+	width
+Param[4]
+	height
+Param[5]
+	destination pixel mask
+Param[6]
+	destination rectangle start address
+Param[7]
+	destination stride in dwords
+Param[8]
+	color fill value
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_BLT_TEXT
+Enum 	84/0x54
+Description
+	BLT for 8 bit alpha text source
+Param[0]
+	Same as Param[0] on API 0x52
+Param[1]
+	Same as Param[1] on API 0x52
+Param[2]
+	Same as Param[2] on API 0x52
+Param[3]
+	width
+Param[4]
+	height
+Param[5]
+	destination pixel mask
+Param[6]
+	destination rectangle start address
+Param[7]
+	destination stride in dwords
+Param[8]
+	source stride in dwords
+Param[9]
+	source rectangle start address
+Param[10]
+	color fill value
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_FRAMEBUFFER_WINDOW
+Enum 	86/0x56
+Description
+	Positions the main output window on the screen. The coordinates must be
+	such that the entire window fits on the screen.
+Param[0]
+	window width
+Param[1]
+	window height
+Param[2]
+	top left window corner horizontal offset
+Param[3]
+	top left window corner vertical offset
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_CHROMA_KEY
+Enum 	96/0x60
+Description
+	Chroma key switch and color
+Param[0]
+	state: 0=off, 1=on
+Param[1]
+	color
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_ALPHA_CONTENT_INDEX
+Enum 	97/0x61
+Description
+	Retrieve alpha content index
+Result[0]
+	alpha content index, Range 0:15
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_ALPHA_CONTENT_INDEX
+Enum 	98/0x62
+Description
+	Assign alpha content index
+Param[0]
+	alpha content index, range 0:15

+ 49 - 0
Documentation/video4linux/cx2341x/fw-upload.txt

@@ -0,0 +1,49 @@
+This document describes how to upload the cx2341x firmware to the card.
+
+How to find
+===========
+
+See the web pages of the various projects that uses this chip for information
+on how to obtain the firmware.
+
+The firmware stored in a Windows driver can be detected as follows:
+
+- Each firmware image is 256k bytes.
+- The 1st 32-bit word of the Encoder image is 0x0000da7
+- The 1st 32-bit word of the Decoder image is 0x00003a7
+- The 2nd 32-bit word of both images is 0xaa55bb66
+
+How to load
+===========
+
+- Issue the FWapi command to stop the encoder if it is running. Wait for the
+  command to complete.
+- Issue the FWapi command to stop the decoder if it is running. Wait for the
+  command to complete.
+- Issue the I2C command to the digitizer to stop emitting VSYNC events.
+- Issue the FWapi command to halt the encoder's firmware.
+- Sleep for 10ms.
+- Issue the FWapi command to halt the decoder's firmware.
+- Sleep for 10ms.
+- Write 0x00000000 to register 0x2800 to stop the Video Display Module.
+- Write 0x00000005 to register 0x2D00 to stop the AO (audio output?).
+- Write 0x00000000 to register 0xA064 to ping? the APU.
+- Write 0xFFFFFFFE to register 0x9058 to stop the VPU.
+- Write 0xFFFFFFFF to register 0x9054 to reset the HW blocks.
+- Write 0x00000001 to register 0x9050 to stop the SPU.
+- Sleep for 10ms.
+- Write 0x0000001A to register 0x07FC to init the Encoder SDRAM's pre-charge.
+- Write 0x80000640 to register 0x07F8 to init the Encoder SDRAM's refresh to 1us.
+- Write 0x0000001A to register 0x08FC to init the Decoder SDRAM's pre-charge.
+- Write 0x80000640 to register 0x08F8 to init the Decoder SDRAM's refresh to 1us.
+- Sleep for 512ms. (600ms is recommended)
+- Transfer the encoder's firmware image to offset 0 in Encoder memory space.
+- Transfer the decoder's firmware image to offset 0 in Decoder memory space.
+- Use a read-modify-write operation to Clear bit 0 of register 0x9050 to
+  re-enable the SPU.
+- Sleep for 1 second.
+- Use a read-modify-write operation to Clear bits 3 and 0 of register 0x9058
+  to re-enable the VPU.
+- Sleep for 1 second.
+- Issue status API commands to both firmware images to verify.
+

+ 54 - 0
Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt

@@ -0,0 +1,54 @@
+The controls for the mux are GPIO [0,1] for source, and GPIO 2 for muting.
+
+GPIO0  GPIO1
+  0        0    TV Audio
+  1        0    FM radio
+  0        1    Line-In
+  1        1    Mono tuner bypass or CD passthru (tuner specific)
+
+GPIO 16(i believe) is tied to the IR port (if present).
+
+------------------------------------------------------------------------------------
+
+>From the data sheet:
+ Register 24'h20004  PCI Interrupt Status
+  bit [18]  IR_SMP_INT Set when 32 input samples have been collected over
+  gpio[16] pin into GP_SAMPLE register.
+
+What's missing from the data sheet:
+
+Setup 4KHz sampling rate (roughly 2x oversampled; good enough for our RC5
+compat remote)
+set register 0x35C050 to  0xa80a80
+
+enable sampling
+set register 0x35C054 to 0x5
+
+Of course, enable the IRQ bit 18 in the interrupt mask register .(and
+provide for a handler)
+
+GP_SAMPLE register is at 0x35C058
+
+Bits are then right shifted into the GP_SAMPLE register at the specified
+rate; you get an interrupt when a full DWORD is recieved.
+You need to recover the actual RC5 bits out of the (oversampled) IR sensor
+bits. (Hint: look for the 0/1and 1/0 crossings of the RC5 bi-phase data)  An
+actual raw RC5 code will span 2-3 DWORDS, depending on the actual alignment.
+
+I'm pretty sure when no IR signal is present the receiver is always in a
+marking state(1); but stray light, etc can cause intermittent noise values
+as well.  Remember, this is a free running sample of the IR receiver state
+over time, so don't assume any sample starts at any particular place.
+
+http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf
+This data sheet (google search) seems to have a lovely description of the
+RC5 basics
+
+http://users.pandora.be/nenya/electronics/rc5/  and more data
+
+http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt
+and even a reference to how to decode a bi-phase data stream.
+
+http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm
+still more info
+

+ 26 - 26
Documentation/video4linux/et61x251.txt

@@ -1,9 +1,9 @@
 
 
-                       ET61X[12]51 PC Camera Controllers
-                                Driver for Linux
-                       =================================
+		       ET61X[12]51 PC Camera Controllers
+				Driver for Linux
+		       =================================
 
 
-                               - Documentation -
+			       - Documentation -
 
 
 
 
 Index
 Index
@@ -156,46 +156,46 @@ Name:           video_nr
 Type:           short array (min = 0, max = 64)
 Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]>
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L2 minor mode number:
 Description:    Specify V4L2 minor mode number:
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 64 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                registered camera and use auto for the first one and for every
-                other camera.
+		-1 = use next available
+		 n = use minor number n
+		You can specify up to 64 cameras this way.
+		For example:
+		video_nr=-1,2,-1 would assign minor number 2 to the second
+		registered camera and use auto for the first one and for every
+		other camera.
 Default:        -1
 Default:        -1
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           force_munmap
 Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Force the application to unmap previously mapped buffer memory
 Description:    Force the application to unmap previously mapped buffer memory
-                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-                all the applications support this feature. This parameter is
-                specific for each detected camera.
-                0 = do not force memory unmapping
-                1 = force memory unmapping (save memory)
+		before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+		all the applications support this feature. This parameter is
+		specific for each detected camera.
+		0 = do not force memory unmapping
+		1 = force memory unmapping (save memory)
 Default:        0
 Default:        0
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
 Type:           uint array (min = 0, max = 64)
 Syntax:         <n[,...]>
 Syntax:         <n[,...]>
 Description:    Timeout for a video frame in seconds. This parameter is
 Description:    Timeout for a video frame in seconds. This parameter is
-                specific for each detected camera. This parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+		specific for each detected camera. This parameter can be
+		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 Default:        2
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           debug
 Name:           debug
 Type:           ushort
 Type:           ushort
 Syntax:         <n>
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 3:
 Description:    Debugging information level, from 0 to 3:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = more verbose messages
-                Level 3 is useful for testing only, when only one device
-                is used at the same time. It also shows some more informations
-                about the hardware being detected. This module parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+		0 = none (use carefully)
+		1 = critical errors
+		2 = significant informations
+		3 = more verbose messages
+		Level 3 is useful for testing only, when only one device
+		is used at the same time. It also shows some more informations
+		about the hardware being detected. This module parameter can be
+		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 Default:        2
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 
 

+ 84 - 84
Documentation/video4linux/ibmcam.txt

@@ -21,7 +21,7 @@ Internal interface: Video For Linux (V4L)
 Supported controls:
 Supported controls:
 - by V4L: Contrast,  Brightness, Color, Hue
 - by V4L: Contrast,  Brightness, Color, Hue
 - by driver options: frame rate, lighting conditions, video format,
 - by driver options: frame rate, lighting conditions, video format,
-                     default picture settings, sharpness.
+		     default picture settings, sharpness.
 
 
 SUPPORTED CAMERAS:
 SUPPORTED CAMERAS:
 
 
@@ -191,66 +191,66 @@ init_model2_sat Integer         0..255 [0x34]   init_model2_sat=65
 init_model2_yb  Integer         0..255 [0xa0]   init_model2_yb=200
 init_model2_yb  Integer         0..255 [0xa0]   init_model2_yb=200
 
 
 debug           You don't need this option unless you are a developer.
 debug           You don't need this option unless you are a developer.
-                If you are a developer then you will see in the code
-                what values do what. 0=off.
+		If you are a developer then you will see in the code
+		what values do what. 0=off.
 
 
 flags           This is a bit mask, and you can combine any number of
 flags           This is a bit mask, and you can combine any number of
-                bits to produce what you want. Usually you don't want
-                any of extra features this option provides:
-
-                FLAGS_RETRY_VIDIOCSYNC  1  This bit allows to retry failed
-                                           VIDIOCSYNC ioctls without failing.
-                                           Will work with xawtv, will not
-                                           with xrealproducer. Default is
-                                           not set.
-                FLAGS_MONOCHROME        2  Activates monochrome (b/w) mode.
-                FLAGS_DISPLAY_HINTS     4  Shows colored pixels which have
-                                           magic meaning to developers.
-                FLAGS_OVERLAY_STATS     8  Shows tiny numbers on screen,
-                                           useful only for debugging.
-                FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers.
-                FLAGS_SEPARATE_FRAMES   32 Shows each frame separately, as
-                                           it was received from the camera.
-                                           Default (not set) is to mix the
-                                           preceding frame in to compensate
-                                           for occasional loss of Isoc data
-                                           on high frame rates.
-                FLAGS_CLEAN_FRAMES      64 Forces "cleanup" of each frame
-                                           prior to use; relevant only if
-                                           FLAGS_SEPARATE_FRAMES is set.
-                                           Default is not to clean frames,
-                                           this is a little faster but may
-                                           produce flicker if frame rate is
-                                           too high and Isoc data gets lost.
-                FLAGS_NO_DECODING      128 This flag turns the video stream
-                                           decoder off, and dumps the raw
-                                           Isoc data from the camera into
-                                           the reading process. Useful to
-                                           developers, but not to users.
+		bits to produce what you want. Usually you don't want
+		any of extra features this option provides:
+
+		FLAGS_RETRY_VIDIOCSYNC  1  This bit allows to retry failed
+					   VIDIOCSYNC ioctls without failing.
+					   Will work with xawtv, will not
+					   with xrealproducer. Default is
+					   not set.
+		FLAGS_MONOCHROME        2  Activates monochrome (b/w) mode.
+		FLAGS_DISPLAY_HINTS     4  Shows colored pixels which have
+					   magic meaning to developers.
+		FLAGS_OVERLAY_STATS     8  Shows tiny numbers on screen,
+					   useful only for debugging.
+		FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers.
+		FLAGS_SEPARATE_FRAMES   32 Shows each frame separately, as
+					   it was received from the camera.
+					   Default (not set) is to mix the
+					   preceding frame in to compensate
+					   for occasional loss of Isoc data
+					   on high frame rates.
+		FLAGS_CLEAN_FRAMES      64 Forces "cleanup" of each frame
+					   prior to use; relevant only if
+					   FLAGS_SEPARATE_FRAMES is set.
+					   Default is not to clean frames,
+					   this is a little faster but may
+					   produce flicker if frame rate is
+					   too high and Isoc data gets lost.
+		FLAGS_NO_DECODING      128 This flag turns the video stream
+					   decoder off, and dumps the raw
+					   Isoc data from the camera into
+					   the reading process. Useful to
+					   developers, but not to users.
 
 
 framerate       This setting controls frame rate of the camera. This is
 framerate       This setting controls frame rate of the camera. This is
-                an approximate setting (in terms of "worst" ... "best")
-                because camera changes frame rate depending on amount
-                of light available. Setting 0 is slowest, 6 is fastest.
-                Beware - fast settings are very demanding and may not
-                work well with all video sizes. Be conservative.
+		an approximate setting (in terms of "worst" ... "best")
+		because camera changes frame rate depending on amount
+		of light available. Setting 0 is slowest, 6 is fastest.
+		Beware - fast settings are very demanding and may not
+		work well with all video sizes. Be conservative.
 
 
 hue_correction  This highly optional setting allows to adjust the
 hue_correction  This highly optional setting allows to adjust the
-                hue of the image in a way slightly different from
-                what usual "hue" control does. Both controls affect
-                YUV colorspace: regular "hue" control adjusts only
-                U component, and this "hue_correction" option similarly
-                adjusts only V component. However usually it is enough
-                to tweak only U or V to compensate for colored light or
-                color temperature; this option simply allows more
-                complicated correction when and if it is necessary.
+		hue of the image in a way slightly different from
+		what usual "hue" control does. Both controls affect
+		YUV colorspace: regular "hue" control adjusts only
+		U component, and this "hue_correction" option similarly
+		adjusts only V component. However usually it is enough
+		to tweak only U or V to compensate for colored light or
+		color temperature; this option simply allows more
+		complicated correction when and if it is necessary.
 
 
 init_brightness These settings specify _initial_ values which will be
 init_brightness These settings specify _initial_ values which will be
 init_contrast   used to set up the camera. If your V4L application has
 init_contrast   used to set up the camera. If your V4L application has
 init_color      its own controls to adjust the picture then these
 init_color      its own controls to adjust the picture then these
 init_hue        controls will be used too. These options allow you to
 init_hue        controls will be used too. These options allow you to
-                preconfigure the camera when it gets connected, before
-                any V4L application connects to it. Good for webcams.
+		preconfigure the camera when it gets connected, before
+		any V4L application connects to it. Good for webcams.
 
 
 init_model2_rg  These initial settings alter color balance of the
 init_model2_rg  These initial settings alter color balance of the
 init_model2_rg2 camera on hardware level. All four settings may be used
 init_model2_rg2 camera on hardware level. All four settings may be used
@@ -258,47 +258,47 @@ init_model2_sat to tune the camera to specific lighting conditions. These
 init_model2_yb  settings only apply to Model 2 cameras.
 init_model2_yb  settings only apply to Model 2 cameras.
 
 
 lighting        This option selects one of three hardware-defined
 lighting        This option selects one of three hardware-defined
-                photosensitivity settings of the camera. 0=bright light,
-                1=Medium (default), 2=Low light. This setting affects
-                frame rate: the dimmer the lighting the lower the frame
-                rate (because longer exposition time is needed). The
-                Model 2 cameras allow values more than 2 for this option,
-                thus enabling extremely high sensitivity at cost of frame
-                rate, color saturation and imaging sensor noise.
+		photosensitivity settings of the camera. 0=bright light,
+		1=Medium (default), 2=Low light. This setting affects
+		frame rate: the dimmer the lighting the lower the frame
+		rate (because longer exposition time is needed). The
+		Model 2 cameras allow values more than 2 for this option,
+		thus enabling extremely high sensitivity at cost of frame
+		rate, color saturation and imaging sensor noise.
 
 
 sharpness       This option controls smoothing (noise reduction)
 sharpness       This option controls smoothing (noise reduction)
-                made by camera. Setting 0 is most smooth, setting 6
-                is most sharp. Be aware that CMOS sensor used in the
-                camera is pretty noisy, so if you choose 6 you will
-                be greeted with "snowy" image. Default is 4. Model 2
-                cameras do not support this feature.
+		made by camera. Setting 0 is most smooth, setting 6
+		is most sharp. Be aware that CMOS sensor used in the
+		camera is pretty noisy, so if you choose 6 you will
+		be greeted with "snowy" image. Default is 4. Model 2
+		cameras do not support this feature.
 
 
 size            This setting chooses one of several image sizes that are
 size            This setting chooses one of several image sizes that are
-                supported by this driver. Cameras may support more, but
-                it's difficult to reverse-engineer all formats.
-                Following video sizes are supported:
-
-                size=0     128x96  (Model 1 only)
-                size=1     160x120
-                size=2     176x144
-                size=3     320x240 (Model 2 only)
-                size=4     352x240 (Model 2 only)
-                size=5     352x288
-                size=6     640x480 (Model 3 only)
-
-                The 352x288 is the native size of the Model 1 sensor
-                array, so it's the best resolution the camera can
-                yield. The best resolution of Model 2 is 176x144, and
-                larger images are produced by stretching the bitmap.
-                Model 3 has sensor with 640x480 grid, and it works too,
-                but the frame rate will be exceptionally low (1-2 FPS);
-                it may be still OK for some applications, like security.
-                Choose the image size you need. The smaller image can
-                support faster frame rate. Default is 352x288.
+		supported by this driver. Cameras may support more, but
+		it's difficult to reverse-engineer all formats.
+		Following video sizes are supported:
+
+		size=0     128x96  (Model 1 only)
+		size=1     160x120
+		size=2     176x144
+		size=3     320x240 (Model 2 only)
+		size=4     352x240 (Model 2 only)
+		size=5     352x288
+		size=6     640x480 (Model 3 only)
+
+		The 352x288 is the native size of the Model 1 sensor
+		array, so it's the best resolution the camera can
+		yield. The best resolution of Model 2 is 176x144, and
+		larger images are produced by stretching the bitmap.
+		Model 3 has sensor with 640x480 grid, and it works too,
+		but the frame rate will be exceptionally low (1-2 FPS);
+		it may be still OK for some applications, like security.
+		Choose the image size you need. The smaller image can
+		support faster frame rate. Default is 352x288.
 
 
 For more information and the Troubleshooting FAQ visit this URL:
 For more information and the Troubleshooting FAQ visit this URL:
 
 
-                http://www.linux-usb.org/ibmcam/
+		http://www.linux-usb.org/ibmcam/
 
 
 WHAT NEEDS TO BE DONE:
 WHAT NEEDS TO BE DONE:
 
 

+ 16 - 16
Documentation/video4linux/ov511.txt

@@ -81,7 +81,7 @@ MODULE PARAMETERS:
   TYPE: integer (Boolean)
   TYPE: integer (Boolean)
   DEFAULT: 1
   DEFAULT: 1
   DESC: Brightness is normally under automatic control and can't be set
   DESC: Brightness is normally under automatic control and can't be set
-        manually by the video app. Set to 0 for manual control.
+	manually by the video app. Set to 0 for manual control.
 
 
   NAME: autogain
   NAME: autogain
   TYPE: integer (Boolean)
   TYPE: integer (Boolean)
@@ -97,13 +97,13 @@ MODULE PARAMETERS:
   TYPE: integer (0-6)
   TYPE: integer (0-6)
   DEFAULT: 3
   DEFAULT: 3
   DESC: Sets the threshold for printing debug messages. The higher the value,
   DESC: Sets the threshold for printing debug messages. The higher the value,
-        the more is printed. The levels are cumulative, and are as follows:
-          0=no debug messages
-          1=init/detection/unload and other significant messages
-          2=some warning messages
-          3=config/control function calls
-          4=most function calls and data parsing messages
-          5=highly repetitive mesgs
+	the more is printed. The levels are cumulative, and are as follows:
+	  0=no debug messages
+	  1=init/detection/unload and other significant messages
+	  2=some warning messages
+	  3=config/control function calls
+	  4=most function calls and data parsing messages
+	  5=highly repetitive mesgs
 
 
   NAME: snapshot
   NAME: snapshot
   TYPE: integer (Boolean)
   TYPE: integer (Boolean)
@@ -116,24 +116,24 @@ MODULE PARAMETERS:
   TYPE: integer (1-4 for OV511, 1-31 for OV511+)
   TYPE: integer (1-4 for OV511, 1-31 for OV511+)
   DEFAULT: 1
   DEFAULT: 1
   DESC: Number of cameras allowed to stream simultaneously on a single bus.
   DESC: Number of cameras allowed to stream simultaneously on a single bus.
-        Values higher than 1 reduce the data rate of each camera, allowing two
-        or more to be used at once. If you have a complicated setup involving
-        both OV511 and OV511+ cameras, trial-and-error may be necessary for
-        finding the optimum setting.
+	Values higher than 1 reduce the data rate of each camera, allowing two
+	or more to be used at once. If you have a complicated setup involving
+	both OV511 and OV511+ cameras, trial-and-error may be necessary for
+	finding the optimum setting.
 
 
   NAME: compress
   NAME: compress
   TYPE: integer (Boolean)
   TYPE: integer (Boolean)
   DEFAULT: 0
   DEFAULT: 0
   DESC: Set this to 1 to turn on the camera's compression engine. This can
   DESC: Set this to 1 to turn on the camera's compression engine. This can
-        potentially increase the frame rate at the expense of quality, if you
-        have a fast CPU. You must load the proper compression module for your
-        camera before starting your application (ov511_decomp or ov518_decomp).
+	potentially increase the frame rate at the expense of quality, if you
+	have a fast CPU. You must load the proper compression module for your
+	camera before starting your application (ov511_decomp or ov518_decomp).
 
 
   NAME: testpat
   NAME: testpat
   TYPE: integer (Boolean)
   TYPE: integer (Boolean)
   DEFAULT: 0
   DEFAULT: 0
   DESC: This configures the camera's sensor to transmit a colored test-pattern
   DESC: This configures the camera's sensor to transmit a colored test-pattern
-        instead of an image. This does not work correctly yet.
+	instead of an image. This does not work correctly yet.
 
 
   NAME: dumppix
   NAME: dumppix
   TYPE: integer (0-2)
   TYPE: integer (0-2)

+ 39 - 39
Documentation/video4linux/sn9c102.txt

@@ -1,9 +1,9 @@
 
 
-                         SN9C10x PC Camera Controllers
-                                Driver for Linux
-                         =============================
+			 SN9C10x PC Camera Controllers
+				Driver for Linux
+			 =============================
 
 
-                               - Documentation -
+			       - Documentation -
 
 
 
 
 Index
 Index
@@ -176,46 +176,46 @@ Name:           video_nr
 Type:           short array (min = 0, max = 64)
 Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]>
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L2 minor mode number:
 Description:    Specify V4L2 minor mode number:
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 64 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                recognized camera and use auto for the first one and for every
-                other camera.
+		-1 = use next available
+		 n = use minor number n
+		You can specify up to 64 cameras this way.
+		For example:
+		video_nr=-1,2,-1 would assign minor number 2 to the second
+		recognized camera and use auto for the first one and for every
+		other camera.
 Default:        -1
 Default:        -1
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           force_munmap
 Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Force the application to unmap previously mapped buffer memory
 Description:    Force the application to unmap previously mapped buffer memory
-                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-                all the applications support this feature. This parameter is
-                specific for each detected camera.
-                0 = do not force memory unmapping
-                1 = force memory unmapping (save memory)
+		before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+		all the applications support this feature. This parameter is
+		specific for each detected camera.
+		0 = do not force memory unmapping
+		1 = force memory unmapping (save memory)
 Default:        0
 Default:        0
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
 Type:           uint array (min = 0, max = 64)
 Syntax:         <n[,...]>
 Syntax:         <n[,...]>
 Description:    Timeout for a video frame in seconds. This parameter is
 Description:    Timeout for a video frame in seconds. This parameter is
-                specific for each detected camera. This parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+		specific for each detected camera. This parameter can be
+		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 Default:        2
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           debug
 Name:           debug
 Type:           ushort
 Type:           ushort
 Syntax:         <n>
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 3:
 Description:    Debugging information level, from 0 to 3:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = more verbose messages
-                Level 3 is useful for testing only, when only one device
-                is used. It also shows some more informations about the
-                hardware being detected. This parameter can be changed at
-                runtime thanks to the /sys filesystem interface.
+		0 = none (use carefully)
+		1 = critical errors
+		2 = significant informations
+		3 = more verbose messages
+		Level 3 is useful for testing only, when only one device
+		is used. It also shows some more informations about the
+		hardware being detected. This parameter can be changed at
+		runtime thanks to the /sys filesystem interface.
 Default:        2
 Default:        2
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 
 
@@ -280,24 +280,24 @@ Byte #  Value         Description
 0x04    0xC4          Frame synchronisation pattern.
 0x04    0xC4          Frame synchronisation pattern.
 0x05    0x96          Frame synchronisation pattern.
 0x05    0x96          Frame synchronisation pattern.
 0x06    0xXX          Unknown meaning. The exact value depends on the chip;
 0x06    0xXX          Unknown meaning. The exact value depends on the chip;
-                      possible values are 0x00, 0x01 and 0x20.
+		      possible values are 0x00, 0x01 and 0x20.
 0x07    0xXX          Variable value, whose bits are ff00uzzc, where ff is a
 0x07    0xXX          Variable value, whose bits are ff00uzzc, where ff is a
-                      frame counter, u is unknown, zz is a size indicator
-                      (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
-                      "compression enabled" (1 = yes, 0 = no).
+		      frame counter, u is unknown, zz is a size indicator
+		      (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
+		      "compression enabled" (1 = yes, 0 = no).
 0x08    0xXX          Brightness sum inside Auto-Exposure area (low-byte).
 0x08    0xXX          Brightness sum inside Auto-Exposure area (low-byte).
 0x09    0xXX          Brightness sum inside Auto-Exposure area (high-byte).
 0x09    0xXX          Brightness sum inside Auto-Exposure area (high-byte).
-                      For a pure white image, this number will be equal to 500
-                      times the area of the specified AE area. For images
-                      that are not pure white, the value scales down according
-                      to relative whiteness.
+		      For a pure white image, this number will be equal to 500
+		      times the area of the specified AE area. For images
+		      that are not pure white, the value scales down according
+		      to relative whiteness.
 0x0A    0xXX          Brightness sum outside Auto-Exposure area (low-byte).
 0x0A    0xXX          Brightness sum outside Auto-Exposure area (low-byte).
 0x0B    0xXX          Brightness sum outside Auto-Exposure area (high-byte).
 0x0B    0xXX          Brightness sum outside Auto-Exposure area (high-byte).
-                      For a pure white image, this number will be equal to 125
-                      times the area outside of the specified AE area. For
-                      images that are not pure white, the value scales down
-                      according to relative whiteness.
-                      according to relative whiteness.
+		      For a pure white image, this number will be equal to 125
+		      times the area outside of the specified AE area. For
+		      images that are not pure white, the value scales down
+		      according to relative whiteness.
+		      according to relative whiteness.
 
 
 The following bytes are used by the SN9C103 bridge only:
 The following bytes are used by the SN9C103 bridge only:
 
 

+ 192 - 0
Documentation/video4linux/v4lgrab.c

@@ -0,0 +1,192 @@
+/* Simple Video4Linux image grabber. */
+/*
+ *	Video4Linux Driver Test/Example Framegrabbing Program
+ *
+ *	Compile with:
+ *		gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
+ *      Use as:
+ *              v4lgrab >image.ppm
+ *
+ *	Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
+ *      Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
+ *      with minor modifications (Dave Forrest, drf5n@virginia.edu).
+ *
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+
+#include <linux/types.h>
+#include <linux/videodev.h>
+
+#define FILE "/dev/video0"
+
+/* Stole this from tvset.c */
+
+#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b)                   \
+{                                                                       \
+	switch (format)                                                 \
+	{                                                               \
+		case VIDEO_PALETTE_GREY:                                \
+			switch (depth)                                  \
+			{                                               \
+				case 4:                                 \
+				case 6:                                 \
+				case 8:                                 \
+					(r) = (g) = (b) = (*buf++ << 8);\
+					break;                          \
+									\
+				case 16:                                \
+					(r) = (g) = (b) =               \
+						*((unsigned short *) buf);      \
+					buf += 2;                       \
+					break;                          \
+			}                                               \
+			break;                                          \
+									\
+									\
+		case VIDEO_PALETTE_RGB565:                              \
+		{                                                       \
+			unsigned short tmp = *(unsigned short *)buf;    \
+			(r) = tmp&0xF800;                               \
+			(g) = (tmp<<5)&0xFC00;                          \
+			(b) = (tmp<<11)&0xF800;                         \
+			buf += 2;                                       \
+		}                                                       \
+		break;                                                  \
+									\
+		case VIDEO_PALETTE_RGB555:                              \
+			(r) = (buf[0]&0xF8)<<8;                         \
+			(g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8;    \
+			(b) = ((buf[1] << 2 ) & 0xF8)<<8;               \
+			buf += 2;                                       \
+			break;                                          \
+									\
+		case VIDEO_PALETTE_RGB24:                               \
+			(r) = buf[0] << 8; (g) = buf[1] << 8;           \
+			(b) = buf[2] << 8;                              \
+			buf += 3;                                       \
+			break;                                          \
+									\
+		default:                                                \
+			fprintf(stderr,                                 \
+				"Format %d not yet supported\n",        \
+				format);                                \
+	}                                                               \
+}
+
+int get_brightness_adj(unsigned char *image, long size, int *brightness) {
+  long i, tot = 0;
+  for (i=0;i<size*3;i++)
+    tot += image[i];
+  *brightness = (128 - tot/(size*3))/3;
+  return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
+}
+
+int main(int argc, char ** argv)
+{
+  int fd = open(FILE, O_RDONLY), f;
+  struct video_capability cap;
+  struct video_window win;
+  struct video_picture vpic;
+
+  unsigned char *buffer, *src;
+  int bpp = 24, r, g, b;
+  unsigned int i, src_depth;
+
+  if (fd < 0) {
+    perror(FILE);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
+    perror("VIDIOGCAP");
+    fprintf(stderr, "(" FILE " not a video4linux device?)\n");
+    close(fd);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
+    perror("VIDIOCGWIN");
+    close(fd);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
+    perror("VIDIOCGPICT");
+    close(fd);
+    exit(1);
+  }
+
+  if (cap.type & VID_TYPE_MONOCHROME) {
+    vpic.depth=8;
+    vpic.palette=VIDEO_PALETTE_GREY;    /* 8bit grey */
+    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+      vpic.depth=6;
+      if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+	vpic.depth=4;
+	if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+	  fprintf(stderr, "Unable to find a supported capture format.\n");
+	  close(fd);
+	  exit(1);
+	}
+      }
+    }
+  } else {
+    vpic.depth=24;
+    vpic.palette=VIDEO_PALETTE_RGB24;
+
+    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+      vpic.palette=VIDEO_PALETTE_RGB565;
+      vpic.depth=16;
+
+      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+	vpic.palette=VIDEO_PALETTE_RGB555;
+	vpic.depth=15;
+
+	if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+	  fprintf(stderr, "Unable to find a supported capture format.\n");
+	  return -1;
+	}
+      }
+    }
+  }
+
+  buffer = malloc(win.width * win.height * bpp);
+  if (!buffer) {
+    fprintf(stderr, "Out of memory.\n");
+    exit(1);
+  }
+
+  do {
+    int newbright;
+    read(fd, buffer, win.width * win.height * bpp);
+    f = get_brightness_adj(buffer, win.width * win.height, &newbright);
+    if (f) {
+      vpic.brightness += (newbright << 8);
+      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+	perror("VIDIOSPICT");
+	break;
+      }
+    }
+  } while (f);
+
+  fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
+
+  src = buffer;
+
+  for (i = 0; i < win.width * win.height; i++) {
+    READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
+    fputc(r>>8, stdout);
+    fputc(g>>8, stdout);
+    fputc(b>>8, stdout);
+  }
+
+  close(fd);
+  return 0;
+}

+ 81 - 81
Documentation/video4linux/w9968cf.txt

@@ -1,9 +1,9 @@
 
 
-                   W996[87]CF JPEG USB Dual Mode Camera Chip
-                     Driver for Linux 2.6 (basic version)
-                   =========================================
+		   W996[87]CF JPEG USB Dual Mode Camera Chip
+		     Driver for Linux 2.6 (basic version)
+		   =========================================
 
 
-                               - Documentation -
+			       - Documentation -
 
 
 
 
 Index
 Index
@@ -188,57 +188,57 @@ Name:            ovmod_load
 Type:            bool
 Type:            bool
 Syntax:          <0|1>
 Syntax:          <0|1>
 Description:     Automatic 'ovcamchip' module loading: 0 disabled, 1 enabled.
 Description:     Automatic 'ovcamchip' module loading: 0 disabled, 1 enabled.
-                 If enabled, 'insmod' searches for the required 'ovcamchip'
-                 module in the system, according to its configuration, and
-                 loads that module automatically. This action is performed as
-                 once soon as the 'w9968cf' module is loaded into memory.
+		 If enabled, 'insmod' searches for the required 'ovcamchip'
+		 module in the system, according to its configuration, and
+		 loads that module automatically. This action is performed as
+		 once soon as the 'w9968cf' module is loaded into memory.
 Default:         1
 Default:         1
 Note:            The kernel must be compiled with the CONFIG_KMOD option
 Note:            The kernel must be compiled with the CONFIG_KMOD option
-                 enabled for the 'ovcamchip' module to be loaded and for
-                 this parameter to be present.
+		 enabled for the 'ovcamchip' module to be loaded and for
+		 this parameter to be present.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           simcams
 Name:           simcams
 Type:           int
 Type:           int
 Syntax:         <n>
 Syntax:         <n>
 Description:    Number of cameras allowed to stream simultaneously.
 Description:    Number of cameras allowed to stream simultaneously.
-                n may vary from 0 to 32.
+		n may vary from 0 to 32.
 Default:        32
 Default:        32
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           video_nr
 Name:           video_nr
 Type:           int array (min = 0, max = 32)
 Type:           int array (min = 0, max = 32)
 Syntax:         <-1|n[,...]>
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L minor mode number.
 Description:    Specify V4L minor mode number.
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 32 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                recognized camera and use auto for the first one and for every
-                other camera.
+		-1 = use next available
+		 n = use minor number n
+		You can specify up to 32 cameras this way.
+		For example:
+		video_nr=-1,2,-1 would assign minor number 2 to the second
+		recognized camera and use auto for the first one and for every
+		other camera.
 Default:        -1
 Default:        -1
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           packet_size
 Name:           packet_size
 Type:           int array (min = 0, max = 32)
 Type:           int array (min = 0, max = 32)
 Syntax:         <n[,...]>
 Syntax:         <n[,...]>
 Description:    Specify the maximum data payload size in bytes for alternate
 Description:    Specify the maximum data payload size in bytes for alternate
-                settings, for each device. n is scaled between 63 and 1023.
+		settings, for each device. n is scaled between 63 and 1023.
 Default:        1023
 Default:        1023
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           max_buffers
 Name:           max_buffers
 Type:           int array (min = 0, max = 32)
 Type:           int array (min = 0, max = 32)
 Syntax:         <n[,...]>
 Syntax:         <n[,...]>
 Description:    For advanced users.
 Description:    For advanced users.
-                Specify the maximum number of video frame buffers to allocate
-                for each device, from 2 to 32.
+		Specify the maximum number of video frame buffers to allocate
+		for each device, from 2 to 32.
 Default:        2
 Default:        2
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           double_buffer
 Name:           double_buffer
 Type:           bool array (min = 0, max = 32)
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Hardware double buffering: 0 disabled, 1 enabled.
 Description:    Hardware double buffering: 0 disabled, 1 enabled.
-                It should be enabled if you want smooth video output: if you
-                obtain out of sync. video, disable it, or try to
-                decrease the 'clockdiv' module parameter value.
+		It should be enabled if you want smooth video output: if you
+		obtain out of sync. video, disable it, or try to
+		decrease the 'clockdiv' module parameter value.
 Default:        1 for every device.
 Default:        1 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           clamping
 Name:           clamping
@@ -251,9 +251,9 @@ Name:           filter_type
 Type:           int array (min = 0, max = 32)
 Type:           int array (min = 0, max = 32)
 Syntax:         <0|1|2[,...]>
 Syntax:         <0|1|2[,...]>
 Description:    Video filter type.
 Description:    Video filter type.
-                0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
-                The filter is used to reduce noise and aliasing artifacts
-                produced by the CCD or CMOS image sensor.
+		0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
+		The filter is used to reduce noise and aliasing artifacts
+		produced by the CCD or CMOS image sensor.
 Default:        0 for every device.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           largeview
 Name:           largeview
@@ -266,9 +266,9 @@ Name:           upscaling
 Type:           bool array (min = 0, max = 32)
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Software scaling (for non-compressed video only):
 Description:    Software scaling (for non-compressed video only):
-                0 disabled, 1 enabled.
-                Disable it if you have a slow CPU or you don't have enough
-                memory.
+		0 disabled, 1 enabled.
+		Disable it if you have a slow CPU or you don't have enough
+		memory.
 Default:        0 for every device.
 Default:        0 for every device.
 Note:           If 'w9968cf-vpp' is not present, this parameter is set to 0.
 Note:           If 'w9968cf-vpp' is not present, this parameter is set to 0.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
@@ -276,36 +276,36 @@ Name:           decompression
 Type:           int array (min = 0, max = 32)
 Type:           int array (min = 0, max = 32)
 Syntax:         <0|1|2[,...]>
 Syntax:         <0|1|2[,...]>
 Description:    Software video decompression:
 Description:    Software video decompression:
-                0 = disables decompression
-                    (doesn't allow formats needing decompression).
-                1 = forces decompression
-                    (allows formats needing decompression only).
-                2 = allows any permitted formats.
-                Formats supporting (de)compressed video are YUV422P and
-                YUV420P/YUV420 in any resolutions where width and height are
-                multiples of 16.
+		0 = disables decompression
+		    (doesn't allow formats needing decompression).
+		1 = forces decompression
+		    (allows formats needing decompression only).
+		2 = allows any permitted formats.
+		Formats supporting (de)compressed video are YUV422P and
+		YUV420P/YUV420 in any resolutions where width and height are
+		multiples of 16.
 Default:        2 for every device.
 Default:        2 for every device.
 Note:           If 'w9968cf-vpp' is not present, forcing decompression is not
 Note:           If 'w9968cf-vpp' is not present, forcing decompression is not
-                allowed; in this case this parameter is set to 2.
+		allowed; in this case this parameter is set to 2.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           force_palette
 Name:           force_palette
 Type:           int array (min = 0, max = 32)
 Type:           int array (min = 0, max = 32)
 Syntax:         <0|9|10|13|15|8|7|1|6|3|4|5[,...]>
 Syntax:         <0|9|10|13|15|8|7|1|6|3|4|5[,...]>
 Description:    Force picture palette.
 Description:    Force picture palette.
-                In order:
-                 0 = Off - allows any of the following formats:
-                 9 = UYVY    16 bpp - Original video, compression disabled
-                10 = YUV420  12 bpp - Original video, compression enabled
-                13 = YUV422P 16 bpp - Original video, compression enabled
-                15 = YUV420P 12 bpp - Original video, compression enabled
-                 8 = YUVY    16 bpp - Software conversion from UYVY
-                 7 = YUV422  16 bpp - Software conversion from UYVY
-                 1 = GREY     8 bpp - Software conversion from UYVY
-                 6 = RGB555  16 bpp - Software conversion from UYVY
-                 3 = RGB565  16 bpp - Software conversion from UYVY
-                 4 = RGB24   24 bpp - Software conversion from UYVY
-                 5 = RGB32   32 bpp - Software conversion from UYVY
-                When not 0, this parameter will override 'decompression'.
+		In order:
+		 0 = Off - allows any of the following formats:
+		 9 = UYVY    16 bpp - Original video, compression disabled
+		10 = YUV420  12 bpp - Original video, compression enabled
+		13 = YUV422P 16 bpp - Original video, compression enabled
+		15 = YUV420P 12 bpp - Original video, compression enabled
+		 8 = YUVY    16 bpp - Software conversion from UYVY
+		 7 = YUV422  16 bpp - Software conversion from UYVY
+		 1 = GREY     8 bpp - Software conversion from UYVY
+		 6 = RGB555  16 bpp - Software conversion from UYVY
+		 3 = RGB565  16 bpp - Software conversion from UYVY
+		 4 = RGB24   24 bpp - Software conversion from UYVY
+		 5 = RGB32   32 bpp - Software conversion from UYVY
+		When not 0, this parameter will override 'decompression'.
 Default:        0 for every device. Initial palette is 9 (UYVY).
 Default:        0 for every device. Initial palette is 9 (UYVY).
 Note:           If 'w9968cf-vpp' is not present, this parameter is set to 9.
 Note:           If 'w9968cf-vpp' is not present, this parameter is set to 9.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
@@ -313,77 +313,77 @@ Name:           force_rgb
 Type:           bool array (min = 0, max = 32)
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Read RGB video data instead of BGR:
 Description:    Read RGB video data instead of BGR:
-                1 = use RGB component ordering.
-                0 = use BGR component ordering.
-                This parameter has effect when using RGBX palettes only.
+		1 = use RGB component ordering.
+		0 = use BGR component ordering.
+		This parameter has effect when using RGBX palettes only.
 Default:        0 for every device.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           autobright
 Name:           autobright
 Type:           bool array (min = 0, max = 32)
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Image sensor automatically changes brightness:
 Description:    Image sensor automatically changes brightness:
-                0 = no, 1 = yes
+		0 = no, 1 = yes
 Default:        0 for every device.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           autoexp
 Name:           autoexp
 Type:           bool array (min = 0, max = 32)
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Image sensor automatically changes exposure:
 Description:    Image sensor automatically changes exposure:
-                0 = no, 1 = yes
+		0 = no, 1 = yes
 Default:        1 for every device.
 Default:        1 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           lightfreq
 Name:           lightfreq
 Type:           int array (min = 0, max = 32)
 Type:           int array (min = 0, max = 32)
 Syntax:         <50|60[,...]>
 Syntax:         <50|60[,...]>
 Description:    Light frequency in Hz:
 Description:    Light frequency in Hz:
-                50 for European and Asian lighting, 60 for American lighting.
+		50 for European and Asian lighting, 60 for American lighting.
 Default:        50 for every device.
 Default:        50 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           bandingfilter
 Name:           bandingfilter
 Type:           bool array (min = 0, max = 32)
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Banding filter to reduce effects of fluorescent
 Description:    Banding filter to reduce effects of fluorescent
-                lighting:
-                0 disabled, 1 enabled.
-                This filter tries to reduce the pattern of horizontal
-                light/dark bands caused by some (usually fluorescent) lighting.
+		lighting:
+		0 disabled, 1 enabled.
+		This filter tries to reduce the pattern of horizontal
+		light/dark bands caused by some (usually fluorescent) lighting.
 Default:        0 for every device.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           clockdiv
 Name:           clockdiv
 Type:           int array (min = 0, max = 32)
 Type:           int array (min = 0, max = 32)
 Syntax:         <-1|n[,...]>
 Syntax:         <-1|n[,...]>
 Description:    Force pixel clock divisor to a specific value (for experts):
 Description:    Force pixel clock divisor to a specific value (for experts):
-                n may vary from 0 to 127.
-                -1 for automatic value.
-                See also the 'double_buffer' module parameter.
+		n may vary from 0 to 127.
+		-1 for automatic value.
+		See also the 'double_buffer' module parameter.
 Default:        -1 for every device.
 Default:        -1 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           backlight
 Name:           backlight
 Type:           bool array (min = 0, max = 32)
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Objects are lit from behind:
 Description:    Objects are lit from behind:
-                0 = no, 1 = yes
+		0 = no, 1 = yes
 Default:        0 for every device.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           mirror
 Name:           mirror
 Type:           bool array (min = 0, max = 32)
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Reverse image horizontally:
 Description:    Reverse image horizontally:
-                0 = no, 1 = yes
+		0 = no, 1 = yes
 Default:        0 for every device.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           monochrome
 Name:           monochrome
 Type:           bool array (min = 0, max = 32)
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    The image sensor is monochrome:
 Description:    The image sensor is monochrome:
-                0 = no, 1 = yes
+		0 = no, 1 = yes
 Default:        0 for every device.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           brightness
 Name:           brightness
 Type:           long array (min = 0, max = 32)
 Type:           long array (min = 0, max = 32)
 Syntax:         <n[,...]>
 Syntax:         <n[,...]>
 Description:    Set picture brightness (0-65535).
 Description:    Set picture brightness (0-65535).
-                This parameter has no effect if 'autobright' is enabled.
+		This parameter has no effect if 'autobright' is enabled.
 Default:        31000 for every device.
 Default:        31000 for every device.
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           hue
 Name:           hue
@@ -414,23 +414,23 @@ Name:           debug
 Type:           int
 Type:           int
 Syntax:         <n>
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 6:
 Description:    Debugging information level, from 0 to 6:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = configuration or general messages
-                4 = warnings
-                5 = called functions
-                6 = function internals
-                Level 5 and 6 are useful for testing only, when only one
-                device is used.
+		0 = none (use carefully)
+		1 = critical errors
+		2 = significant informations
+		3 = configuration or general messages
+		4 = warnings
+		5 = called functions
+		6 = function internals
+		Level 5 and 6 are useful for testing only, when only one
+		device is used.
 Default:        2
 Default:        2
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           specific_debug
 Name:           specific_debug
 Type:           bool
 Type:           bool
 Syntax:         <0|1>
 Syntax:         <0|1>
 Description:    Enable or disable specific debugging messages:
 Description:    Enable or disable specific debugging messages:
-                0 = print messages concerning every level <= 'debug' level.
-                1 = print messages concerning the level indicated by 'debug'.
+		0 = print messages concerning every level <= 'debug' level.
+		1 = print messages concerning the level indicated by 'debug'.
 Default:        0
 Default:        0
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 
 

+ 48 - 32
Documentation/video4linux/zc0301.txt

@@ -1,9 +1,9 @@
 
 
-                    ZC0301 Image Processor and Control Chip
-                                Driver for Linux
-                    =======================================
+	      ZC0301 and ZC0301P Image Processor and Control Chip
+				Driver for Linux
+	      ===================================================
 
 
-                               - Documentation -
+			       - Documentation -
 
 
 
 
 Index
 Index
@@ -51,13 +51,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 
 4. Overview and features
 4. Overview and features
 ========================
 ========================
-This driver supports the video interface of the devices mounting the ZC0301
-Image Processor and Control Chip.
+This driver supports the video interface of the devices mounting the ZC0301 or
+ZC0301P Image Processors and Control Chips.
 
 
 The driver relies on the Video4Linux2 and USB core modules. It has been
 The driver relies on the Video4Linux2 and USB core modules. It has been
 designed to run properly on SMP systems as well.
 designed to run properly on SMP systems as well.
 
 
-The latest version of the ZC0301 driver can be found at the following URL:
+The latest version of the ZC0301[P] driver can be found at the following URL:
 http://www.linux-projects.org/
 http://www.linux-projects.org/
 
 
 Some of the features of the driver are:
 Some of the features of the driver are:
@@ -117,7 +117,7 @@ supported by the USB Audio driver thanks to the ALSA API:
 
 
 And finally:
 And finally:
 
 
-	# USB Multimedia devices
+	# V4L USB devices
 	#
 	#
 	CONFIG_USB_ZC0301=m
 	CONFIG_USB_ZC0301=m
 
 
@@ -146,46 +146,46 @@ Name:           video_nr
 Type:           short array (min = 0, max = 64)
 Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]>
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L2 minor mode number:
 Description:    Specify V4L2 minor mode number:
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 64 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                registered camera and use auto for the first one and for every
-                other camera.
+		-1 = use next available
+		 n = use minor number n
+		You can specify up to 64 cameras this way.
+		For example:
+		video_nr=-1,2,-1 would assign minor number 2 to the second
+		registered camera and use auto for the first one and for every
+		other camera.
 Default:        -1
 Default:        -1
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           force_munmap
 Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]>
 Syntax:         <0|1[,...]>
 Description:    Force the application to unmap previously mapped buffer memory
 Description:    Force the application to unmap previously mapped buffer memory
-                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-                all the applications support this feature. This parameter is
-                specific for each detected camera.
-                0 = do not force memory unmapping
-                1 = force memory unmapping (save memory)
+		before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+		all the applications support this feature. This parameter is
+		specific for each detected camera.
+		0 = do not force memory unmapping
+		1 = force memory unmapping (save memory)
 Default:        0
 Default:        0
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
 Type:           uint array (min = 0, max = 64)
 Syntax:         <n[,...]>
 Syntax:         <n[,...]>
 Description:    Timeout for a video frame in seconds. This parameter is
 Description:    Timeout for a video frame in seconds. This parameter is
-                specific for each detected camera. This parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+		specific for each detected camera. This parameter can be
+		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 Default:        2
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 Name:           debug
 Name:           debug
 Type:           ushort
 Type:           ushort
 Syntax:         <n>
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 3:
 Description:    Debugging information level, from 0 to 3:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = more verbose messages
-                Level 3 is useful for testing only, when only one device
-                is used at the same time. It also shows some more informations
-                about the hardware being detected. This module parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+		0 = none (use carefully)
+		1 = critical errors
+		2 = significant informations
+		3 = more verbose messages
+		Level 3 is useful for testing only, when only one device
+		is used at the same time. It also shows some more informations
+		about the hardware being detected. This module parameter can be
+		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 Default:        2
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 
 
@@ -204,11 +204,25 @@ Vendor ID  Product ID
 0x041e     0x4017
 0x041e     0x4017
 0x041e     0x401c
 0x041e     0x401c
 0x041e     0x401e
 0x041e     0x401e
+0x041e     0x401f
+0x041e     0x4022
 0x041e     0x4034
 0x041e     0x4034
 0x041e     0x4035
 0x041e     0x4035
+0x041e     0x4036
+0x041e     0x403a
+0x0458     0x7007
+0x0458     0x700C
+0x0458     0x700f
+0x046d     0x08ae
+0x055f     0xd003
+0x055f     0xd004
 0x046d     0x08ae
 0x046d     0x08ae
 0x0ac8     0x0301
 0x0ac8     0x0301
+0x0ac8     0x301b
+0x0ac8     0x303b
+0x10fd     0x0128
 0x10fd     0x8050
 0x10fd     0x8050
+0x10fd     0x804e
 
 
 The list above does not imply that all those devices work with this driver: up
 The list above does not imply that all those devices work with this driver: up
 until now only the ones that mount the following image sensors are supported;
 until now only the ones that mount the following image sensors are supported;
@@ -217,6 +231,7 @@ kernel messages will always tell you whether this is the case:
 Model       Manufacturer
 Model       Manufacturer
 -----       ------------
 -----       ------------
 PAS202BCB   PixArt Imaging, Inc.
 PAS202BCB   PixArt Imaging, Inc.
+PB-0330     Photobit Corporation
 
 
 
 
 9. Notes for V4L2 application developers
 9. Notes for V4L2 application developers
@@ -250,5 +265,6 @@ the fingerprint is: '88E8 F32F 7244 68BA 3958  5D40 99DA 5D2A FCE6 35A4'.
   been taken from the documentation of the ZC030x Video4Linux1 driver written
   been taken from the documentation of the ZC030x Video4Linux1 driver written
   by Andrew Birkett <andy@nobugs.org>;
   by Andrew Birkett <andy@nobugs.org>;
 - The initialization values of the ZC0301 controller connected to the PAS202BCB
 - The initialization values of the ZC0301 controller connected to the PAS202BCB
-  image sensor have been taken from the SPCA5XX driver maintained by
-  Michel Xhaard <mxhaard@magic.fr>.
+  and PB-0330 image sensors have been taken from the SPCA5XX driver maintained
+  by Michel Xhaard <mxhaard@magic.fr>;
+- Stanislav Lechev donated one camera.

+ 5 - 2
drivers/media/Kconfig

@@ -25,7 +25,7 @@ config VIDEO_DEV
 	  module will be called videodev.
 	  module will be called videodev.
 
 
 config VIDEO_V4L1
 config VIDEO_V4L1
-	boolean "Enable Video For Linux API 1 (DEPRECATED)"
+	bool "Enable Video For Linux API 1 (DEPRECATED)"
 	depends on VIDEO_DEV
 	depends on VIDEO_DEV
 	select VIDEO_V4L1_COMPAT
 	select VIDEO_V4L1_COMPAT
 	default y
 	default y
@@ -36,7 +36,7 @@ config VIDEO_V4L1
 	  If you are unsure as to whether this is required, answer Y.
 	  If you are unsure as to whether this is required, answer Y.
 
 
 config VIDEO_V4L1_COMPAT
 config VIDEO_V4L1_COMPAT
-	boolean "Enable Video For Linux API 1 compatible Layer"
+	bool "Enable Video For Linux API 1 compatible Layer"
 	depends on VIDEO_DEV
 	depends on VIDEO_DEV
 	default y
 	default y
 	---help---
 	---help---
@@ -82,6 +82,9 @@ config VIDEO_IR
 config VIDEO_TVEEPROM
 config VIDEO_TVEEPROM
 	tristate
 	tristate
 
 
+config VIDEO_CX2341X
+	tristate
+
 config USB_DABUSB
 config USB_DABUSB
 	tristate "DABUSB driver"
 	tristate "DABUSB driver"
 	depends on USB
 	depends on USB

+ 1 - 1
drivers/media/common/Makefile

@@ -1,5 +1,5 @@
 saa7146-objs    := saa7146_i2c.o saa7146_core.o
 saa7146-objs    := saa7146_i2c.o saa7146_core.o
-saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
+saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
 ir-common-objs  := ir-functions.o ir-keymaps.o
 ir-common-objs  := ir-functions.o ir-keymaps.o
 
 
 obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
 obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o

+ 0 - 1
drivers/media/common/ir-functions.c

@@ -269,4 +269,3 @@ EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
  * c-basic-offset: 8
  * c-basic-offset: 8
  * End:
  * End:
  */
  */
-

+ 71 - 11
drivers/media/common/ir-keymaps.c

@@ -618,7 +618,7 @@ IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = {
 
 
 EXPORT_SYMBOL_GPL(ir_codes_em_terratec);
 EXPORT_SYMBOL_GPL(ir_codes_em_terratec);
 
 
-IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
+IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = {
 	[ 0x3a ] = KEY_0,
 	[ 0x3a ] = KEY_0,
 	[ 0x31 ] = KEY_1,
 	[ 0x31 ] = KEY_1,
 	[ 0x32 ] = KEY_2,
 	[ 0x32 ] = KEY_2,
@@ -670,7 +670,7 @@ IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
 	[ 0x27 ] = KEY_RECORD,
 	[ 0x27 ] = KEY_RECORD,
 };
 };
 
 
-EXPORT_SYMBOL_GPL(ir_codes_em_pinnacle_usb);
+EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey);
 
 
 IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
 IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
 	[ 0x0f ] = KEY_0,
 	[ 0x0f ] = KEY_0,
@@ -1263,34 +1263,51 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
 	[ 0x0f ] = KEY_9,
 	[ 0x0f ] = KEY_9,
 
 
 	[ 0x00 ] = KEY_POWER,
 	[ 0x00 ] = KEY_POWER,
-	[ 0x02 ] = KEY_TUNER,		/* TV/FM */
-	[ 0x1e ] = KEY_VIDEO,
+	[ 0x1b ] = KEY_AUDIO,           /* Audio Source */
+	[ 0x02 ] = KEY_TUNER,		/* TV/FM, not on Y0400052 */
+	[ 0x1e ] = KEY_VIDEO,           /* Video Source */
+	[ 0x16 ] = KEY_INFO,            /* Display information */
 	[ 0x04 ] = KEY_VOLUMEUP,
 	[ 0x04 ] = KEY_VOLUMEUP,
 	[ 0x08 ] = KEY_VOLUMEDOWN,
 	[ 0x08 ] = KEY_VOLUMEDOWN,
 	[ 0x0c ] = KEY_CHANNELUP,
 	[ 0x0c ] = KEY_CHANNELUP,
 	[ 0x10 ] = KEY_CHANNELDOWN,
 	[ 0x10 ] = KEY_CHANNELDOWN,
 	[ 0x03 ] = KEY_ZOOM,		/* fullscreen */
 	[ 0x03 ] = KEY_ZOOM,		/* fullscreen */
-	[ 0x1f ] = KEY_SUBTITLE,		/* closed caption/teletext */
+	[ 0x1f ] = KEY_TEXT,		/* closed caption/teletext */
 	[ 0x20 ] = KEY_SLEEP,
 	[ 0x20 ] = KEY_SLEEP,
+	[ 0x29 ] = KEY_CLEAR,           /* boss key */
 	[ 0x14 ] = KEY_MUTE,
 	[ 0x14 ] = KEY_MUTE,
 	[ 0x2b ] = KEY_RED,
 	[ 0x2b ] = KEY_RED,
 	[ 0x2c ] = KEY_GREEN,
 	[ 0x2c ] = KEY_GREEN,
 	[ 0x2d ] = KEY_YELLOW,
 	[ 0x2d ] = KEY_YELLOW,
 	[ 0x2e ] = KEY_BLUE,
 	[ 0x2e ] = KEY_BLUE,
-	[ 0x18 ] = KEY_KPPLUS,		/* fine tune + */
-	[ 0x19 ] = KEY_KPMINUS,		/* fine tune - */
+	[ 0x18 ] = KEY_KPPLUS,		/* fine tune + , not on Y040052 */
+	[ 0x19 ] = KEY_KPMINUS,		/* fine tune - , not on Y040052 */
+	[ 0x2a ] = KEY_MEDIA,           /* PIP (Picture in picture */
 	[ 0x21 ] = KEY_DOT,
 	[ 0x21 ] = KEY_DOT,
 	[ 0x13 ] = KEY_ENTER,
 	[ 0x13 ] = KEY_ENTER,
-	[ 0x22 ] = KEY_BACK,
+	[ 0x11 ] = KEY_LAST,            /* Recall (last channel */
+	[ 0x22 ] = KEY_PREVIOUS,
 	[ 0x23 ] = KEY_PLAYPAUSE,
 	[ 0x23 ] = KEY_PLAYPAUSE,
 	[ 0x24 ] = KEY_NEXT,
 	[ 0x24 ] = KEY_NEXT,
+	[ 0x25 ] = KEY_ARCHIVE,       /* Time Shifting */
 	[ 0x26 ] = KEY_STOP,
 	[ 0x26 ] = KEY_STOP,
-	[ 0x27 ] = KEY_RECORD
+	[ 0x27 ] = KEY_RECORD,
+	[ 0x28 ] = KEY_SAVE,          /* Screenshot */
+	[ 0x2f ] = KEY_MENU,
+	[ 0x30 ] = KEY_CANCEL,
+	[ 0x31 ] = KEY_CHANNEL,       /* Channel Surf */
+	[ 0x32 ] = KEY_SUBTITLE,
+	[ 0x33 ] = KEY_LANGUAGE,
+	[ 0x34 ] = KEY_REWIND,
+	[ 0x35 ] = KEY_FASTFORWARD,
+	[ 0x36 ] = KEY_TV,
+	[ 0x37 ] = KEY_RADIO,         /* FM */
+	[ 0x38 ] = KEY_DVD
 };
 };
 
 
 EXPORT_SYMBOL_GPL(ir_codes_winfast);
 EXPORT_SYMBOL_GPL(ir_codes_winfast);
 
 
-IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
+IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = {
 	[ 0x59 ] = KEY_MUTE,
 	[ 0x59 ] = KEY_MUTE,
 	[ 0x4a ] = KEY_POWER,
 	[ 0x4a ] = KEY_POWER,
 
 
@@ -1348,7 +1365,7 @@ IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
 	[ 0x0a ] = KEY_BACKSPACE,
 	[ 0x0a ] = KEY_BACKSPACE,
 };
 };
 
 
-EXPORT_SYMBOL_GPL(ir_codes_pinnacle);
+EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color);
 
 
 /* Hauppauge: the newer, gray remotes (seems there are multiple
 /* Hauppauge: the newer, gray remotes (seems there are multiple
  * slightly different versions), shipped with cx88+ivtv cards.
  * slightly different versions), shipped with cx88+ivtv cards.
@@ -1413,3 +1430,46 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
 
 
 EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new);
 EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new);
 
 
+IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = {
+	[ 0x1d ] = KEY_SWITCHVIDEOMODE, /* switch inputs */
+	[ 0x2a ] = KEY_FRONT,
+
+	[ 0x3e ] = KEY_1,
+	[ 0x02 ] = KEY_2,
+	[ 0x06 ] = KEY_3,
+	[ 0x0a ] = KEY_4,
+	[ 0x0e ] = KEY_5,
+	[ 0x12 ] = KEY_6,
+	[ 0x16 ] = KEY_7,
+	[ 0x1a ] = KEY_8,
+	[ 0x1e ] = KEY_9,
+	[ 0x3a ] = KEY_0,
+	[ 0x22 ] = KEY_NUMLOCK,         /* -/-- */
+	[ 0x20 ] = KEY_REFRESH,
+
+	[ 0x03 ] = KEY_BRIGHTNESSDOWN,
+	[ 0x28 ] = KEY_AUDIO,
+	[ 0x3c ] = KEY_UP,
+	[ 0x3f ] = KEY_LEFT,
+	[ 0x2e ] = KEY_MUTE,
+	[ 0x3b ] = KEY_RIGHT,
+	[ 0x00 ] = KEY_DOWN,
+	[ 0x07 ] = KEY_BRIGHTNESSUP,
+	[ 0x2c ] = KEY_TEXT,
+
+	[ 0x37 ] = KEY_RECORD,
+	[ 0x17 ] = KEY_PLAY,
+	[ 0x13 ] = KEY_PAUSE,
+	[ 0x26 ] = KEY_STOP,
+	[ 0x18 ] = KEY_FASTFORWARD,
+	[ 0x14 ] = KEY_REWIND,
+	[ 0x33 ] = KEY_ZOOM,
+	[ 0x32 ] = KEY_KEYBOARD,
+	[ 0x30 ] = KEY_GOTO,            /* Pointing arrow */
+	[ 0x36 ] = KEY_MACRO,           /* Maximize/Minimize (yellow) */
+	[ 0x0b ] = KEY_RADIO,
+	[ 0x10 ] = KEY_POWER,
+
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_npgtech);

+ 4 - 0
drivers/media/common/saa7146_fops.c

@@ -501,6 +501,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL_GPL(saa7146_vv_init);
 
 
 int saa7146_vv_release(struct saa7146_dev* dev)
 int saa7146_vv_release(struct saa7146_dev* dev)
 {
 {
@@ -515,6 +516,7 @@ int saa7146_vv_release(struct saa7146_dev* dev)
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL_GPL(saa7146_vv_release);
 
 
 int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
 int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
 			    char *name, int type)
 			    char *name, int type)
@@ -553,6 +555,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
 	*vid = vfd;
 	*vid = vfd;
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL_GPL(saa7146_register_device);
 
 
 int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
 int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
 {
 {
@@ -571,6 +574,7 @@ int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL_GPL(saa7146_unregister_device);
 
 
 static int __init saa7146_vv_init_module(void)
 static int __init saa7146_vv_init_module(void)
 {
 {

+ 1 - 0
drivers/media/common/saa7146_hlp.c

@@ -641,6 +641,7 @@ void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sy
 	vv->current_hps_source = source;
 	vv->current_hps_source = source;
 	vv->current_hps_sync = sync;
 	vv->current_hps_sync = sync;
 }
 }
+EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
 
 
 int saa7146_enable_overlay(struct saa7146_fh *fh)
 int saa7146_enable_overlay(struct saa7146_fh *fh)
 {
 {

+ 2 - 0
drivers/media/common/saa7146_video.c

@@ -318,6 +318,7 @@ int saa7146_start_preview(struct saa7146_fh *fh)
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL_GPL(saa7146_start_preview);
 
 
 int saa7146_stop_preview(struct saa7146_fh *fh)
 int saa7146_stop_preview(struct saa7146_fh *fh)
 {
 {
@@ -352,6 +353,7 @@ int saa7146_stop_preview(struct saa7146_fh *fh)
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL_GPL(saa7146_stop_preview);
 
 
 static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
 static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
 {
 {

+ 0 - 12
drivers/media/common/saa7146_vv_ksyms.c

@@ -1,12 +0,0 @@
-#include <linux/module.h>
-#include <media/saa7146_vv.h>
-
-EXPORT_SYMBOL_GPL(saa7146_start_preview);
-EXPORT_SYMBOL_GPL(saa7146_stop_preview);
-
-EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
-EXPORT_SYMBOL_GPL(saa7146_register_device);
-EXPORT_SYMBOL_GPL(saa7146_unregister_device);
-
-EXPORT_SYMBOL_GPL(saa7146_vv_init);
-EXPORT_SYMBOL_GPL(saa7146_vv_release);

+ 73 - 49
drivers/media/dvb/b2c2/flexcop-fe-tuner.c

@@ -14,6 +14,7 @@
 #include "stv0297.h"
 #include "stv0297.h"
 #include "mt312.h"
 #include "mt312.h"
 #include "lgdt330x.h"
 #include "lgdt330x.h"
+#include "lg_h06xf.h"
 #include "dvb-pll.h"
 #include "dvb-pll.h"
 
 
 /* lnb control */
 /* lnb control */
@@ -166,11 +167,12 @@ static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate,
 	return 0;
 	return 0;
 }
 }
 
 
-static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
+static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 {
 	u8 buf[4];
 	u8 buf[4];
 	u32 div;
 	u32 div;
 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+	struct flexcop_device *fc = fe->dvb->priv;
 
 
 	div = params->frequency / 125;
 	div = params->frequency / 125;
 
 
@@ -181,8 +183,11 @@ static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter
 
 
 	if (params->frequency < 1500000) buf[3] |= 0x10;
 	if (params->frequency < 1500000) buf[3] |= 0x10;
 
 
-	if (i2c_transfer(i2c, &msg, 1) != 1)
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
 		return -EIO;
 		return -EIO;
+	}
 	return 0;
 	return 0;
 }
 }
 
 
@@ -241,7 +246,6 @@ static struct stv0299_config samsung_tbmu24112_config = {
 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
 	.min_delay_ms = 100,
 	.min_delay_ms = 100,
 	.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
 	.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
-	.pll_set = samsung_tbmu24112_pll_set,
 };
 };
 
 
 /* dvb-t mt352 */
 /* dvb-t mt352 */
@@ -264,11 +268,14 @@ static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
 	return 0;
 	return 0;
 }
 }
 
 
-static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
 {
 {
 	u32 div;
 	u32 div;
 	unsigned char bs = 0;
 	unsigned char bs = 0;
 
 
+	if (buf_len < 5)
+		return -EINVAL;
+
 	#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
 	#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
 
@@ -276,19 +283,18 @@ static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_front
 	if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
 	if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
 	if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
 	if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
 
 
-	pllbuf[0] = 0xc2; /* Note: non-linux standard PLL i2c address */
+	pllbuf[0] = 0x61;
 	pllbuf[1] = div >> 8;
 	pllbuf[1] = div >> 8;
 	pllbuf[2] = div & 0xff;
 	pllbuf[2] = div & 0xff;
 	pllbuf[3] = 0xcc;
 	pllbuf[3] = 0xcc;
 	pllbuf[4] = bs;
 	pllbuf[4] = bs;
 
 
-	return 0;
+	return 5;
 }
 }
 
 
 static struct mt352_config samsung_tdtc9251dh0_config = {
 static struct mt352_config samsung_tdtc9251dh0_config = {
 	.demod_address = 0x0f,
 	.demod_address = 0x0f,
 	.demod_init    = samsung_tdtc9251dh0_demod_init,
 	.demod_init    = samsung_tdtc9251dh0_demod_init,
-	.pll_set       = samsung_tdtc9251dh0_pll_set,
 };
 };
 
 
 static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
 static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
@@ -297,56 +303,21 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
 	return request_firmware(fw, name, fc->dev);
 	return request_firmware(fw, name, fc->dev);
 }
 }
 
 
-static int lgdt3303_pll_set(struct dvb_frontend* fe,
-			    struct dvb_frontend_parameters* params)
+static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 {
 	struct flexcop_device *fc = fe->dvb->priv;
 	struct flexcop_device *fc = fe->dvb->priv;
-	u8 buf[4];
-	struct i2c_msg msg =
-		{ .addr = 0x61, .flags = 0, .buf = buf, .len = 4 };
-	int err;
-
-	dvb_pll_configure(&dvb_pll_tdvs_tua6034,buf, params->frequency, 0);
-	dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-			__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
-	if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
-		printk(KERN_WARNING "lgdt3303: %s error "
-			   "(addr %02x <- %02x, err = %i)\n",
-			   __FUNCTION__, buf[0], buf[1], err);
-		if (err < 0)
-			return err;
-		else
-			return -EREMOTEIO;
-	}
-
-	buf[0] = 0x86 | 0x18;
-	buf[1] = 0x50;
-	msg.len = 2;
-	if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
-		printk(KERN_WARNING "lgdt3303: %s error "
-			   "(addr %02x <- %02x, err = %i)\n",
-			   __FUNCTION__, buf[0], buf[1], err);
-		if (err < 0)
-			return err;
-		else
-			return -EREMOTEIO;
-	}
-
-	return 0;
+	return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
 }
 }
 
 
 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
 	.demod_address       = 0x59,
 	.demod_address       = 0x59,
 	.demod_chip          = LGDT3303,
 	.demod_chip          = LGDT3303,
 	.serial_mpeg         = 0x04,
 	.serial_mpeg         = 0x04,
-	.pll_set             = lgdt3303_pll_set,
 	.clock_polarity_flip = 1,
 	.clock_polarity_flip = 1,
 };
 };
 
 
 static struct nxt200x_config samsung_tbmv_config = {
 static struct nxt200x_config samsung_tbmv_config = {
 	.demod_address    = 0x0a,
 	.demod_address    = 0x0a,
-	.pll_address      = 0xc2,
-	.pll_desc         = &dvb_pll_samsung_tbmv,
 };
 };
 
 
 static struct bcm3510_config air2pc_atsc_first_gen_config = {
 static struct bcm3510_config air2pc_atsc_first_gen_config = {
@@ -354,7 +325,7 @@ static struct bcm3510_config air2pc_atsc_first_gen_config = {
 	.request_firmware = flexcop_fe_request_firmware,
 	.request_firmware = flexcop_fe_request_firmware,
 };
 };
 
 
-static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 {
 	u8 buf[4];
 	u8 buf[4];
 	u32 div;
 	u32 div;
@@ -371,6 +342,8 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d
 	if (params->frequency < 1550000)
 	if (params->frequency < 1550000)
 		buf[3] |= 0x02;
 		buf[3] |= 0x02;
 
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
 	if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 		return -EIO;
 	return 0;
 	return 0;
@@ -379,9 +352,52 @@ static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct d
 static struct mt312_config skystar23_samsung_tbdu18132_config = {
 static struct mt312_config skystar23_samsung_tbdu18132_config = {
 
 
 	.demod_address = 0x0e,
 	.demod_address = 0x0e,
-	.pll_set = skystar23_samsung_tbdu18132_pll_set,
 };
 };
 
 
+static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
+					       struct dvb_frontend_parameters *fep)
+{
+	struct flexcop_device *fc = fe->dvb->priv;
+	u8 buf[4];
+	u16 div;
+	int ret;
+
+/*  62.5 kHz * 10 */
+#define REF_FREQ    625
+#define FREQ_OFFSET 36125
+
+	div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10)  / REF_FREQ; // 4 MHz = 4000 KHz
+
+	buf[0] = (u8)( div >> 8) & 0x7f;
+	buf[1] = (u8)        div & 0xff;
+
+/* F(osc) = N * Reference Freq. (62.5 kHz)
+ * byte 2 :  0 N14 N13 N12 N11 N10 N9  N8
+ * byte 3 : N7 N6  N5  N4  N3  N2  N1  N0
+ * byte 4 : 1  *   *   AGD R3  R2  R1  R0
+ * byte 5 : C1 *   RE  RTS BS4 BS3 BS2 BS1
+ * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
+	buf[2] = 0x95;
+
+// Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
+//  47 - 153   0  *  0   0   0   0   0   1   0x01
+// 153 - 430   0  *  0   0   0   0   1   0   0x02
+// 430 - 822   0  *  0   0   1   0   0   0   0x08
+// 822 - 862   1  *  0   0   1   0   0   0   0x88
+
+	     if (fep->frequency <= 153000000) buf[3] = 0x01;
+	else if (fep->frequency <= 430000000) buf[3] = 0x02;
+	else if (fep->frequency <= 822000000) buf[3] = 0x08;
+	else buf[3] = 0x88;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
+	ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3);
+	deb_tuner("tuner write returned: %d\n",ret);
+
+	return 0;
+}
 
 
 static u8 alps_tdee4_stv0297_inittab[] = {
 static u8 alps_tdee4_stv0297_inittab[] = {
 	0x80, 0x01,
 	0x80, 0x01,
@@ -490,7 +506,9 @@ int flexcop_frontend_init(struct flexcop_device *fc)
 
 
 	/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
 	/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
 	if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
 	if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
-		ops = fc->fe->ops;
+		ops = &fc->fe->ops;
+
+		ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
 
 
 		ops->set_voltage = flexcop_set_voltage;
 		ops->set_voltage = flexcop_set_voltage;
 
 
@@ -503,16 +521,19 @@ int flexcop_frontend_init(struct flexcop_device *fc)
 	/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
 	/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
 	if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
 	if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
 		fc->dev_type          = FC_AIR_DVB;
 		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);
 		info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
 	} else
 	} else
 	/* try the air atsc 2nd generation (nxt2002) */
 	/* try the air atsc 2nd generation (nxt2002) */
 	if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
 	if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
 		fc->dev_type          = FC_AIR_ATSC2;
 		fc->dev_type          = FC_AIR_ATSC2;
+		dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
 		info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
 		info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
 	} else
 	} else
 	/* try the air atsc 3nd generation (lgdt3303) */
 	/* try the air atsc 3nd generation (lgdt3303) */
 	if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
 	if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
 		fc->dev_type          = FC_AIR_ATSC3;
 		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);
 		info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
 	} else
 	} else
 	/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
 	/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
@@ -523,11 +544,14 @@ int flexcop_frontend_init(struct flexcop_device *fc)
 	/* try the cable dvb (stv0297) */
 	/* try the cable dvb (stv0297) */
 	if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
 	if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
 		fc->dev_type                        = FC_CABLE;
 		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);
 		info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
 	} else
 	} else
 	/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
 	/* 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 = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
-		ops = fc->fe->ops;
+		ops = &fc->fe->ops;
+
+		ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
 
 
 		ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
 		ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
 		ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
 		ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
@@ -547,7 +571,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
 	} else {
 	} else {
 		if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
 		if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
 			err("frontend registration failed!");
 			err("frontend registration failed!");
-			ops = fc->fe->ops;
+			ops = &fc->fe->ops;
 			if (ops->release != NULL)
 			if (ops->release != NULL)
 				ops->release(fc->fe);
 				ops->release(fc->fe);
 			fc->fe = NULL;
 			fc->fe = NULL;

+ 7 - 12
drivers/media/dvb/b2c2/flexcop-pci.c

@@ -242,19 +242,16 @@ static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci)
 	if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0)
 	if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0)
 		return ret;
 		return ret;
 
 
-	if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0)
-		goto dma1_free;
+	if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) {
+		flexcop_dma_free(&fc_pci->dma[0]);
+		return ret;
+	}
 
 
 	flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
 	flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
 	flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO   | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
 	flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO   | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
 
 
 	fc_pci->init_state |= FC_PCI_DMA_INIT;
 	fc_pci->init_state |= FC_PCI_DMA_INIT;
 
 
-	goto success;
-dma1_free:
-	flexcop_dma_free(&fc_pci->dma[0]);
-
-success:
 	return ret;
 	return ret;
 }
 }
 
 
@@ -303,7 +300,7 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
 	spin_lock_init(&fc_pci->irq_lock);
 	spin_lock_init(&fc_pci->irq_lock);
 
 
 	fc_pci->init_state |= FC_PCI_INIT;
 	fc_pci->init_state |= FC_PCI_INIT;
-	goto success;
+	return ret;
 
 
 err_pci_iounmap:
 err_pci_iounmap:
 	pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
 	pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
@@ -312,8 +309,6 @@ err_pci_release_regions:
 	pci_release_regions(fc_pci->pdev);
 	pci_release_regions(fc_pci->pdev);
 err_pci_disable_device:
 err_pci_disable_device:
 	pci_disable_device(fc_pci->pdev);
 	pci_disable_device(fc_pci->pdev);
-
-success:
 	return ret;
 	return ret;
 }
 }
 
 
@@ -378,14 +373,14 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
 
 	INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci);
 	INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci);
 
 
-	goto success;
+	return ret;
+
 err_fc_exit:
 err_fc_exit:
 	flexcop_device_exit(fc);
 	flexcop_device_exit(fc);
 err_pci_exit:
 err_pci_exit:
 	flexcop_pci_exit(fc_pci);
 	flexcop_pci_exit(fc_pci);
 err_kfree:
 err_kfree:
 	flexcop_device_kfree(fc);
 	flexcop_device_kfree(fc);
-success:
 	return ret;
 	return ret;
 }
 }
 
 

+ 4 - 6
drivers/media/dvb/b2c2/flexcop-usb.c

@@ -433,11 +433,10 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
 	flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS);
 	flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS);
 	flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1);
 	flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1);
 
 
-	ret = 0;
-	goto success;
+	return 0;
+
 urb_error:
 urb_error:
 	flexcop_usb_transfer_exit(fc_usb);
 	flexcop_usb_transfer_exit(fc_usb);
-success:
 	return ret;
 	return ret;
 }
 }
 
 
@@ -515,15 +514,14 @@ static int flexcop_usb_probe(struct usb_interface *intf,
 		goto err_fc_exit;
 		goto err_fc_exit;
 
 
 	info("%s successfully initialized and connected.",DRIVER_NAME);
 	info("%s successfully initialized and connected.",DRIVER_NAME);
-	ret = 0;
-	goto success;
+	return 0;
+
 err_fc_exit:
 err_fc_exit:
 	flexcop_device_exit(fc);
 	flexcop_device_exit(fc);
 err_usb_exit:
 err_usb_exit:
 	flexcop_usb_exit(fc_usb);
 	flexcop_usb_exit(fc_usb);
 err_kfree:
 err_kfree:
 	flexcop_device_kfree(fc);
 	flexcop_device_kfree(fc);
-success:
 	return ret;
 	return ret;
 }
 }
 
 

+ 4 - 8
drivers/media/dvb/b2c2/flexcop.c

@@ -67,7 +67,7 @@ static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 static int flexcop_dvb_init(struct flexcop_device *fc)
 static int flexcop_dvb_init(struct flexcop_device *fc)
 {
 {
 	int ret;
 	int ret;
-	if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner)) < 0) {
+	if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) {
 		err("error registering DVB adapter");
 		err("error registering DVB adapter");
 		return ret;
 		return ret;
 	}
 	}
@@ -116,7 +116,7 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
 	dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
 	dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
 
 
 	fc->init_state |= FC_STATE_DVB_INIT;
 	fc->init_state |= FC_STATE_DVB_INIT;
-	goto success;
+	return 0;
 
 
 err_connect_frontend:
 err_connect_frontend:
 	fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
 	fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
@@ -129,9 +129,6 @@ err_dmx_dev:
 err_dmx:
 err_dmx:
 	dvb_unregister_adapter(&fc->dvb_adapter);
 	dvb_unregister_adapter(&fc->dvb_adapter);
 	return ret;
 	return ret;
-
-success:
-	return 0;
 }
 }
 
 
 static void flexcop_dvb_exit(struct flexcop_device *fc)
 static void flexcop_dvb_exit(struct flexcop_device *fc)
@@ -279,11 +276,10 @@ int flexcop_device_initialize(struct flexcop_device *fc)
 
 
 	flexcop_device_name(fc,"initialization of","complete");
 	flexcop_device_name(fc,"initialization of","complete");
 
 
-	ret = 0;
-	goto success;
+	return 0;
+
 error:
 error:
 	flexcop_device_exit(fc);
 	flexcop_device_exit(fc);
-success:
 	return ret;
 	return ret;
 }
 }
 EXPORT_SYMBOL(flexcop_device_initialize);
 EXPORT_SYMBOL(flexcop_device_initialize);

+ 8 - 3
drivers/media/dvb/bt8xx/bt878.c

@@ -63,8 +63,6 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off).");
 int bt878_num;
 int bt878_num;
 struct bt878 bt878[BT878_MAX];
 struct bt878 bt878[BT878_MAX];
 
 
-EXPORT_SYMBOL(bt878_debug);
-EXPORT_SYMBOL(bt878_verbose);
 EXPORT_SYMBOL(bt878_num);
 EXPORT_SYMBOL(bt878_num);
 EXPORT_SYMBOL(bt878);
 EXPORT_SYMBOL(bt878);
 
 
@@ -393,7 +391,9 @@ static struct cards card_list[] __devinitdata = {
 	{ 0x07711461, BTTV_BOARD_AVDVBT_771,			"AVermedia AverTV DVB-T 771" },
 	{ 0x07711461, BTTV_BOARD_AVDVBT_771,			"AVermedia AverTV DVB-T 771" },
 	{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,		"DViCO FusionHDTV DVB-T Lite" },
 	{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,		"DViCO FusionHDTV DVB-T Lite" },
 	{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,	"DViCO FusionHDTV 5 Lite" },
 	{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,	"DViCO FusionHDTV 5 Lite" },
-	{ 0x20007063, BTTV_BOARD_PC_HDTV,			"pcHDTV HD-2000 TV"},
+	{ 0x20007063, BTTV_BOARD_PC_HDTV,			"pcHDTV HD-2000 TV" },
+	{ 0x00261822, BTTV_BOARD_TWINHAN_DST,			"DNTV Live! Mini" },
+
 	{ 0, -1, NULL }
 	{ 0, -1, NULL }
 };
 };
 
 
@@ -417,6 +417,11 @@ static int __devinit bt878_probe(struct pci_dev *dev,
 
 
 	printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
 	printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
 	       bt878_num);
 	       bt878_num);
+	if (bt878_num >= BT878_MAX) {
+		printk(KERN_ERR "bt878: Too many devices inserted\n");
+		result = -ENOMEM;
+		goto fail0;
+	}
 	if (pci_enable_device(dev))
 	if (pci_enable_device(dev))
 		return -EIO;
 		return -EIO;
 
 

+ 477 - 129
drivers/media/dvb/bt8xx/dst.c

@@ -38,6 +38,10 @@ static unsigned int dst_addons;
 module_param(dst_addons, int, 0644);
 module_param(dst_addons, int, 0644);
 MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
 MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
 
 
+static unsigned int dst_algo;
+module_param(dst_algo, int, 0644);
+MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
+
 #define HAS_LOCK		1
 #define HAS_LOCK		1
 #define ATTEMPT_TUNE		2
 #define ATTEMPT_TUNE		2
 #define HAS_POWER		4
 #define HAS_POWER		4
@@ -47,20 +51,24 @@ MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
 #define DST_INFO		2
 #define DST_INFO		2
 #define DST_DEBUG		3
 #define DST_DEBUG		3
 
 
-#define dprintk(x, y, z, format, arg...) do {						\
-	if (z) {									\
-		if	((x > DST_ERROR) && (x > y))					\
-			printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg);	\
-		else if	((x > DST_NOTICE) && (x > y))					\
-			printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg);	\
-		else if ((x > DST_INFO) && (x > y))					\
-			printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg);	\
-		else if ((x > DST_DEBUG) && (x > y))					\
-			printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg);	\
-	} else {									\
-		if (x > y)								\
-			printk(format, ##arg);						\
-	}										\
+#define dprintk(x, y, z, format, arg...) do {				\
+	if (z) {							\
+		if	((x > DST_ERROR) && (x > y))			\
+			printk(KERN_ERR "dst(%d) %s: " format "\n",	\
+				state->bt->nr, __func__ , ##arg);	\
+		else if	((x > DST_NOTICE) && (x > y))			\
+			printk(KERN_NOTICE "dst(%d) %s: " format "\n",  \
+				state->bt->nr, __func__ , ##arg);	\
+		else if ((x > DST_INFO) && (x > y))			\
+			printk(KERN_INFO "dst(%d) %s: " format "\n",	\
+				state->bt->nr, __func__ , ##arg);	\
+		else if ((x > DST_DEBUG) && (x > y))			\
+			printk(KERN_DEBUG "dst(%d) %s: " format "\n",	\
+				state->bt->nr,  __func__ , ##arg);	\
+	} else {							\
+		if (x > y)						\
+			printk(format, ##arg);				\
+	}								\
 } while(0)
 } while(0)
 
 
 
 
@@ -110,7 +118,7 @@ int dst_gpio_inb(struct dst_state *state, u8 *result)
 
 
 	*result = 0;
 	*result = 0;
 	if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
 	if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err);
+		dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err);
 		return -EREMOTEIO;
 		return -EREMOTEIO;
 	}
 	}
 	*result = (u8) rd_packet.rd.value;
 	*result = (u8) rd_packet.rd.value;
@@ -363,6 +371,17 @@ static int dst_set_freq(struct dst_state *state, u32 freq)
 		state->tx_tuna[2] = (freq >> 16) & 0xff;
 		state->tx_tuna[2] = (freq >> 16) & 0xff;
 		state->tx_tuna[3] = (freq >> 8) & 0xff;
 		state->tx_tuna[3] = (freq >> 8) & 0xff;
 		state->tx_tuna[4] = (u8) freq;
 		state->tx_tuna[4] = (u8) freq;
+	} else if (state->dst_type == DST_TYPE_IS_ATSC) {
+		freq = freq / 1000;
+		if (freq < 51000 || freq > 858000)
+			return -EINVAL;
+		state->tx_tuna[2] = (freq >> 16) & 0xff;
+		state->tx_tuna[3] = (freq >>  8) & 0xff;
+		state->tx_tuna[4] = (u8) freq;
+		state->tx_tuna[5] = 0x00;		/*	ATSC	*/
+		state->tx_tuna[6] = 0x00;
+		if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG)
+			state->tx_tuna[7] = 0x00;	/*	Digital	*/
 	} else
 	} else
 		return -EINVAL;
 		return -EINVAL;
 
 
@@ -447,29 +466,41 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate)
 	}
 	}
 	dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
 	dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
 	srate /= 1000;
 	srate /= 1000;
-	if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
-		sval = srate;
-		sval <<= 20;
-		do_div(sval, 88000);
-		symcalc = (u32) sval;
-		dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
-		state->tx_tuna[5] = (u8) (symcalc >> 12);
-		state->tx_tuna[6] = (u8) (symcalc >> 4);
-		state->tx_tuna[7] = (u8) (symcalc << 4);
-	} else {
-		state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
-		state->tx_tuna[6] = (u8) (srate >> 8);
-		state->tx_tuna[7] = (u8) srate;
-	}
-	state->tx_tuna[8] &= ~0x20;
-	if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
-		if (srate > 8000)
-			state->tx_tuna[8] |= 0x20;
+	if (state->dst_type == DST_TYPE_IS_SAT) {
+		if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
+			sval = srate;
+			sval <<= 20;
+			do_div(sval, 88000);
+			symcalc = (u32) sval;
+			dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
+			state->tx_tuna[5] = (u8) (symcalc >> 12);
+			state->tx_tuna[6] = (u8) (symcalc >> 4);
+			state->tx_tuna[7] = (u8) (symcalc << 4);
+		} else {
+			state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
+			state->tx_tuna[6] = (u8) (srate >> 8);
+			state->tx_tuna[7] = (u8) srate;
+		}
+		state->tx_tuna[8] &= ~0x20;
+		if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
+			if (srate > 8000)
+				state->tx_tuna[8] |= 0x20;
+		}
+	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
+		dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name);
+		if (!strncmp(state->fw_name, "DCTNEW", 6)) {
+			state->tx_tuna[5] = (u8) (srate >> 8);
+			state->tx_tuna[6] = (u8) srate;
+			state->tx_tuna[7] = 0x00;
+		} else if (!strncmp(state->fw_name, "DCT-CI", 6)) {
+			state->tx_tuna[5] = 0x00;
+			state->tx_tuna[6] = (u8) (srate >> 8);
+			state->tx_tuna[7] = (u8) srate;
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }
 
 
-
 static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
 static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
 {
 {
 	if (state->dst_type != DST_TYPE_IS_CABLE)
 	if (state->dst_type != DST_TYPE_IS_CABLE)
@@ -490,7 +521,10 @@ static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulatio
 		state->tx_tuna[8] = 0x80;
 		state->tx_tuna[8] = 0x80;
 		break;
 		break;
 	case QAM_256:
 	case QAM_256:
-		state->tx_tuna[8] = 0x00;
+		if (!strncmp(state->fw_name, "DCTNEW", 6))
+			state->tx_tuna[8] = 0xff;
+		else if (!strncmp(state->fw_name, "DCT-CI", 6))
+			state->tx_tuna[8] = 0x00;
 		break;
 		break;
 	case QPSK:
 	case QPSK:
 	case QAM_AUTO:
 	case QAM_AUTO:
@@ -523,13 +557,19 @@ u8 dst_check_sum(u8 *buf, u32 len)
 }
 }
 EXPORT_SYMBOL(dst_check_sum);
 EXPORT_SYMBOL(dst_check_sum);
 
 
-static void dst_type_flags_print(u32 type_flags)
+static void dst_type_flags_print(struct dst_state *state)
 {
 {
+	u32 type_flags = state->type_flags;
+
 	dprintk(verbose, DST_ERROR, 0, "DST type flags :");
 	dprintk(verbose, DST_ERROR, 0, "DST type flags :");
-	if (type_flags & DST_TYPE_HAS_NEWTUNE)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
+	if (type_flags & DST_TYPE_HAS_TS188)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188);
+	if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2);
 	if (type_flags & DST_TYPE_HAS_TS204)
 	if (type_flags & DST_TYPE_HAS_TS204)
 		dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
 		dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
+	if (type_flags & DST_TYPE_HAS_VLF)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF);
 	if (type_flags & DST_TYPE_HAS_SYMDIV)
 	if (type_flags & DST_TYPE_HAS_SYMDIV)
 		dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
 		dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
 	if (type_flags & DST_TYPE_HAS_FW_1)
 	if (type_flags & DST_TYPE_HAS_FW_1)
@@ -542,7 +582,7 @@ static void dst_type_flags_print(u32 type_flags)
 }
 }
 
 
 
 
-static int dst_type_print(u8 type)
+static int dst_type_print(struct dst_state *state, u8 type)
 {
 {
 	char *otype;
 	char *otype;
 	switch (type) {
 	switch (type) {
@@ -558,6 +598,10 @@ static int dst_type_print(u8 type)
 		otype = "cable";
 		otype = "cable";
 		break;
 		break;
 
 
+	case DST_TYPE_IS_ATSC:
+		otype = "atsc";
+		break;
+
 	default:
 	default:
 		dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
 		dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
 		return -EINVAL;
 		return -EINVAL;
@@ -567,6 +611,127 @@ static int dst_type_print(u8 type)
 	return 0;
 	return 0;
 }
 }
 
 
+struct tuner_types tuner_list[] = {
+	{
+		.tuner_type = TUNER_TYPE_L64724,
+		.tuner_name = "L 64724",
+		.board_name = "UNKNOWN",
+		.fw_name    = "UNKNOWN"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1020",
+		.fw_name    = "DST-MOT"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1020",
+		.fw_name    = "DST-03T"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_MB86A15,
+		.tuner_name = "MB 86A15",
+		.board_name = "VP1022",
+		.fw_name    = "DST-03T"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_MB86A15,
+		.tuner_name = "MB 86A15",
+		.board_name = "VP1025",
+		.fw_name    = "DST-03T"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1030",
+		.fw_name    = "DST-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1030",
+		.fw_name    = "DSTMCI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2021",
+		.fw_name    = "DCTNEW"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2030",
+		.fw_name    = "DCT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2031",
+		.fw_name    = "DCT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2040",
+		.fw_name    = "DCT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP3020",
+		.fw_name    = "DTTFTA"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP3021",
+		.fw_name    = "DTTFTA"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_TDA10046,
+		.tuner_name = "TDA10046",
+		.board_name = "VP3040",
+		.fw_name    = "DTT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP3051",
+		.fw_name    = "DTTNXT"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_NXT200x,
+		.tuner_name = "NXT200x",
+		.board_name = "VP3220",
+		.fw_name    = "ATSCDI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_NXT200x,
+		.tuner_name = "NXT200x",
+		.board_name = "VP3250",
+		.fw_name    = "ATSCAD"
+	},
+};
+
 /*
 /*
 	Known cards list
 	Known cards list
 	Satellite
 	Satellite
@@ -608,7 +773,8 @@ static struct dst_types dst_tlist[] = {
 		.offset = 0,
 		.offset = 0,
 		.dst_type =  DST_TYPE_IS_SAT,
 		.dst_type =  DST_TYPE_IS_SAT,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
-		.dst_feature = 0
+		.dst_feature = 0,
+		.tuner_type = 0
 	},	/*	obsolete	*/
 	},	/*	obsolete	*/
 
 
 	{
 	{
@@ -616,15 +782,17 @@ static struct dst_types dst_tlist[] = {
 		.offset = 0,
 		.offset = 0,
 		.dst_type =  DST_TYPE_IS_SAT,
 		.dst_type =  DST_TYPE_IS_SAT,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0
+		.dst_feature = 0,
+		.tuner_type = 0
 	},	/*	obsolete	*/
 	},	/*	obsolete	*/
 
 
 	{
 	{
 		.device_id = "DST-030",
 		.device_id = "DST-030",
 		.offset =  0,
 		.offset =  0,
 		.dst_type = DST_TYPE_IS_SAT,
 		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0
+		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
+		.dst_feature = 0,
+		.tuner_type = 0
 	},	/*	obsolete	*/
 	},	/*	obsolete	*/
 
 
 	{
 	{
@@ -633,7 +801,8 @@ static struct dst_types dst_tlist[] = {
 		.dst_type = DST_TYPE_IS_SAT,
 		.dst_type = DST_TYPE_IS_SAT,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
 		.dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
 		.dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
-							 | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO
+							 | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO,
+		.tuner_type = TUNER_TYPE_MULTI
 	 },
 	 },
 
 
 	{
 	{
@@ -641,57 +810,63 @@ static struct dst_types dst_tlist[] = {
 		.offset =  0,
 		.offset =  0,
 		.dst_type = DST_TYPE_IS_SAT,
 		.dst_type = DST_TYPE_IS_SAT,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0
+		.dst_feature = 0,
+		.tuner_type = 0
 	},	/*	obsolete	*/
 	},	/*	obsolete	*/
 
 
 	{
 	{
 		.device_id = "DST-CI",
 		.device_id = "DST-CI",
 		.offset = 1,
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_SAT,
 		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
-		.dst_feature = DST_TYPE_HAS_CA
+		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1,
+		.dst_feature = DST_TYPE_HAS_CA,
+		.tuner_type = 0
 	},	/*	An OEM board	*/
 	},	/*	An OEM board	*/
 
 
 	{
 	{
 		.device_id = "DSTMCI",
 		.device_id = "DSTMCI",
 		.offset = 1,
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_SAT,
 		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT,
+		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF,
 		.dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
 		.dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
-							| DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC
+							| DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC,
+		.tuner_type = TUNER_TYPE_MULTI
 	},
 	},
 
 
 	{
 	{
 		.device_id = "DSTFCI",
 		.device_id = "DSTFCI",
 		.offset = 1,
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_SAT,
 		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0
+		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
+		.dst_feature = 0,
+		.tuner_type = 0
 	},	/* unknown to vendor	*/
 	},	/* unknown to vendor	*/
 
 
 	{
 	{
 		.device_id = "DCT-CI",
 		.device_id = "DCT-CI",
 		.offset = 1,
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_CABLE,
 		.dst_type = DST_TYPE_IS_CABLE,
-		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
-							| DST_TYPE_HAS_FW_2,
-		.dst_feature = DST_TYPE_HAS_CA
+		.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1	| DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF,
+		.dst_feature = DST_TYPE_HAS_CA,
+		.tuner_type = 0
 	},
 	},
 
 
 	{
 	{
 		.device_id = "DCTNEW",
 		.device_id = "DCTNEW",
 		.offset = 1,
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_CABLE,
 		.dst_type = DST_TYPE_IS_CABLE,
-		.type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD,
-		.dst_feature = 0
+		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE,
+		.dst_feature = 0,
+		.tuner_type = 0
 	},
 	},
 
 
 	{
 	{
 		.device_id = "DTT-CI",
 		.device_id = "DTT-CI",
 		.offset = 1,
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_TERR,
 		.dst_type = DST_TYPE_IS_TERR,
-		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE,
-		.dst_feature = DST_TYPE_HAS_CA
+		.type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF,
+		.dst_feature = DST_TYPE_HAS_CA,
+		.tuner_type = 0
 	},
 	},
 
 
 	{
 	{
@@ -699,7 +874,8 @@ static struct dst_types dst_tlist[] = {
 		.offset = 1,
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_TERR,
 		.dst_type = DST_TYPE_IS_TERR,
 		.type_flags = DST_TYPE_HAS_FW_2,
 		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = 0
+		.dst_feature = 0,
+		.tuner_type = 0
 	},
 	},
 
 
 	{
 	{
@@ -707,7 +883,8 @@ static struct dst_types dst_tlist[] = {
 		.offset = 1,
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_TERR,
 		.dst_type = DST_TYPE_IS_TERR,
 		.type_flags = DST_TYPE_HAS_FW_2,
 		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = DST_TYPE_HAS_ANALOG
+		.dst_feature = DST_TYPE_HAS_ANALOG,
+		.tuner_type = 0
 	},
 	},
 
 
 	{
 	{
@@ -715,15 +892,17 @@ static struct dst_types dst_tlist[] = {
 		.offset = 1,
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_ATSC,
 		.dst_type = DST_TYPE_IS_ATSC,
 		.type_flags = DST_TYPE_HAS_FW_2,
 		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = 0
+		.dst_feature = 0,
+		.tuner_type = 0
 	},
 	},
 
 
 	{
 	{
 		.device_id = "ATSCAD",
 		.device_id = "ATSCAD",
 		.offset = 1,
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_ATSC,
 		.dst_type = DST_TYPE_IS_ATSC,
-		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = 0
+		.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+		.dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG,
+		.tuner_type = 0
 	},
 	},
 
 
 	{ }
 	{ }
@@ -768,6 +947,9 @@ static int dst_fw_ver(struct dst_state *state)
 
 
 static int dst_card_type(struct dst_state *state)
 static int dst_card_type(struct dst_state *state)
 {
 {
+	int j;
+	struct tuner_types *p_tuner_list = NULL;
+
 	u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	get_type[7] = dst_check_sum(get_type, 7);
 	get_type[7] = dst_check_sum(get_type, 7);
 	if (dst_command(state, get_type, 8) < 0) {
 	if (dst_command(state, get_type, 8) < 0) {
@@ -775,9 +957,17 @@ static int dst_card_type(struct dst_state *state)
 		return -1;
 		return -1;
 	}
 	}
 	memset(&state->card_info, '\0', 8);
 	memset(&state->card_info, '\0', 8);
-	memcpy(&state->card_info, &state->rxbuffer, 8);
+	memcpy(&state->card_info, &state->rxbuffer, 7);
 	dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
 	dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
 
 
+	for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
+		if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
+			state->tuner_type = p_tuner_list->tuner_type;
+			dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
+				p_tuner_list->tuner_name, p_tuner_list->tuner_type);
+		}
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -790,12 +980,64 @@ static int dst_get_vendor(struct dst_state *state)
 		return -1;
 		return -1;
 	}
 	}
 	memset(&state->vendor, '\0', 8);
 	memset(&state->vendor, '\0', 8);
-	memcpy(&state->vendor, &state->rxbuffer, 8);
+	memcpy(&state->vendor, &state->rxbuffer, 7);
 	dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
 	dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
 
 
 	return 0;
 	return 0;
 }
 }
 
 
+static void debug_dst_buffer(struct dst_state *state)
+{
+	int i;
+
+	if (verbose > 2) {
+		printk("%s: [", __func__);
+		for (i = 0; i < 8; i++)
+			printk(" %02x", state->rxbuffer[i]);
+		printk("]\n");
+	}
+}
+
+static int dst_check_stv0299(struct dst_state *state)
+{
+	u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+	check_stv0299[7] = dst_check_sum(check_stv0299, 7);
+	if (dst_command(state, check_stv0299, 8) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
+		return -1;
+	}
+	debug_dst_buffer(state);
+
+	if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
+		dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
+		state->tuner_type = TUNER_TYPE_STV0299;
+		return 0;
+	}
+
+	return -1;
+}
+
+static int dst_check_mb86a15(struct dst_state *state)
+{
+	u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+	check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
+	if (dst_command(state, check_mb86a15, 8) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
+		return -1;
+	}
+	debug_dst_buffer(state);
+
+	if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
+		state->tuner_type = TUNER_TYPE_MB86A15;
+		return 0;
+	}
+
+	return -1;
+}
+
 static int dst_get_tuner_info(struct dst_state *state)
 static int dst_get_tuner_info(struct dst_state *state)
 {
 {
 	u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -803,60 +1045,59 @@ static int dst_get_tuner_info(struct dst_state *state)
 
 
 	get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
 	get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
 	get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
 	get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
+	dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
 	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
 	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
-		if (dst_command(state, get_tuner_2, 8) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Unsupported Command");
-			return -1;
+		if (dst_command(state, get_tuner_1, 8) < 0) {
+			dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
+			goto force;
 		}
 		}
 	} else {
 	} else {
-		if (dst_command(state, get_tuner_1, 8) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Unsupported Command");
-			return -1;
+		if (dst_command(state, get_tuner_2, 8) < 0) {
+			dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
+			goto force;
 		}
 		}
 	}
 	}
 	memset(&state->board_info, '\0', 8);
 	memset(&state->board_info, '\0', 8);
 	memcpy(&state->board_info, &state->rxbuffer, 8);
 	memcpy(&state->board_info, &state->rxbuffer, 8);
 	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
 	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
-		if (state->board_info[1] == 0x0b) {
-			if (state->type_flags & DST_TYPE_HAS_TS204)
-				state->type_flags &= ~DST_TYPE_HAS_TS204;
-			state->type_flags |= DST_TYPE_HAS_NEWTUNE;
-			dprintk(verbose, DST_INFO, 1, "DST type has TS=188");
-		} else {
-			if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
-				state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
-			state->type_flags |= DST_TYPE_HAS_TS204;
-			dprintk(verbose, DST_INFO, 1, "DST type has TS=204");
-		}
-	} else {
-		if (state->board_info[0] == 0xbc) {
-			if (state->type_flags & DST_TYPE_HAS_TS204)
-				state->type_flags &= ~DST_TYPE_HAS_TS204;
-			state->type_flags |= DST_TYPE_HAS_NEWTUNE;
-			dprintk(verbose, DST_INFO, 1, "DST type has TS=188, Daughterboard=[%d]", state->board_info[1]);
-
-		} else if (state->board_info[0] == 0xcc) {
-			if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
-				state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
-			state->type_flags |= DST_TYPE_HAS_TS204;
-			dprintk(verbose, DST_INFO, 1, "DST type has TS=204 Daughterboard=[%d]", state->board_info[1]);
+		dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
+	}
+	if (state->board_info[0] == 0xbc) {
+		if (state->type_flags != DST_TYPE_IS_ATSC)
+			state->type_flags |= DST_TYPE_HAS_TS188;
+		else
+			state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;
+
+		if (state->board_info[1] == 0x01) {
+			state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
+			dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard");
 		}
 		}
 	}
 	}
 
 
 	return 0;
 	return 0;
+force:
+	if (!strncmp(state->fw_name, "DCT-CI", 6)) {
+		state->type_flags |= DST_TYPE_HAS_TS204;
+		dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name);
+	}
+
+	return -1;
 }
 }
 
 
 static int dst_get_device_id(struct dst_state *state)
 static int dst_get_device_id(struct dst_state *state)
 {
 {
 	u8 reply;
 	u8 reply;
 
 
-	int i;
-	struct dst_types *p_dst_type;
+	int i, j;
+	struct dst_types *p_dst_type = NULL;
+	struct tuner_types *p_tuner_list = NULL;
+
 	u8 use_dst_type = 0;
 	u8 use_dst_type = 0;
 	u32 use_type_flags = 0;
 	u32 use_type_flags = 0;
 
 
 	static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
 	static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
 
 
+	state->tuner_type = 0;
 	device_type[7] = dst_check_sum(device_type, 7);
 	device_type[7] = dst_check_sum(device_type, 7);
 
 
 	if (write_dst(state, device_type, FIXED_COMM))
 	if (write_dst(state, device_type, FIXED_COMM))
@@ -888,8 +1129,34 @@ static int dst_get_device_id(struct dst_state *state)
 
 
 			/*	Card capabilities	*/
 			/*	Card capabilities	*/
 			state->dst_hw_cap = p_dst_type->dst_feature;
 			state->dst_hw_cap = p_dst_type->dst_feature;
-			dprintk(verbose, DST_ERROR, 1, "Recognise [%s]\n", p_dst_type->device_id);
-
+			dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id);
+			strncpy(&state->fw_name[0], p_dst_type->device_id, 6);
+			/*	Multiple tuners		*/
+			if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
+				switch (use_dst_type) {
+				case DST_TYPE_IS_SAT:
+					/*	STV0299 check	*/
+					if (dst_check_stv0299(state) < 0) {
+						dprintk(verbose, DST_ERROR, 1, "Unsupported");
+						state->tuner_type = TUNER_TYPE_MB86A15;
+					}
+					break;
+				default:
+					break;
+				}
+				if (dst_check_mb86a15(state) < 0)
+					dprintk(verbose, DST_ERROR, 1, "Unsupported");
+			/*	Single tuner		*/
+			} else {
+				state->tuner_type = p_dst_type->tuner_type;
+			}
+			for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
+				if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
+					p_tuner_list->tuner_type == state->tuner_type) {
+					dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]",
+						p_dst_type->device_id, p_tuner_list->tuner_name);
+				}
+			}
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -900,10 +1167,10 @@ static int dst_get_device_id(struct dst_state *state)
 		use_dst_type = DST_TYPE_IS_SAT;
 		use_dst_type = DST_TYPE_IS_SAT;
 		use_type_flags = DST_TYPE_HAS_SYMDIV;
 		use_type_flags = DST_TYPE_HAS_SYMDIV;
 	}
 	}
-	dst_type_print(use_dst_type);
+	dst_type_print(state, use_dst_type);
 	state->type_flags = use_type_flags;
 	state->type_flags = use_type_flags;
 	state->dst_type = use_dst_type;
 	state->dst_type = use_dst_type;
-	dst_type_flags_print(state->type_flags);
+	dst_type_flags_print(state);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -911,15 +1178,15 @@ static int dst_get_device_id(struct dst_state *state)
 static int dst_probe(struct dst_state *state)
 static int dst_probe(struct dst_state *state)
 {
 {
 	mutex_init(&state->dst_mutex);
 	mutex_init(&state->dst_mutex);
-	if ((rdc_8820_reset(state)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
-		return -1;
-	}
-	if (dst_addons & DST_TYPE_HAS_CA)
+	if (dst_addons & DST_TYPE_HAS_CA) {
+		if ((rdc_8820_reset(state)) < 0) {
+			dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
+			return -1;
+		}
 		msleep(4000);
 		msleep(4000);
-	else
+	} else {
 		msleep(100);
 		msleep(100);
-
+	}
 	if ((dst_comm_init(state)) < 0) {
 	if ((dst_comm_init(state)) < 0) {
 		dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
 		dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
 		return -1;
 		return -1;
@@ -931,7 +1198,6 @@ static int dst_probe(struct dst_state *state)
 	}
 	}
 	if (dst_get_mac(state) < 0) {
 	if (dst_get_mac(state) < 0) {
 		dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
 		dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
-		return 0;
 	}
 	}
 	if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
 	if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
 		if (dst_get_tuner_info(state) < 0)
 		if (dst_get_tuner_info(state) < 0)
@@ -1048,6 +1314,10 @@ static int dst_get_signal(struct dst_state *state)
 			state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
 			state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
 			state->decode_strength = state->rxbuffer[4] << 8;
 			state->decode_strength = state->rxbuffer[4] << 8;
 			state->decode_snr = state->rxbuffer[3] << 8;
 			state->decode_snr = state->rxbuffer[3] << 8;
+		} else if (state->dst_type == DST_TYPE_IS_ATSC) {
+			state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0;
+			state->decode_strength = state->rxbuffer[4] << 8;
+			state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
 		}
 		}
 		state->cur_jiff = jiffies;
 		state->cur_jiff = jiffies;
 	}
 	}
@@ -1078,8 +1348,9 @@ static int dst_get_tuna(struct dst_state *state)
 	state->diseq_flags &= ~(HAS_LOCK);
 	state->diseq_flags &= ~(HAS_LOCK);
 	if (!dst_wait_dst_ready(state, NO_DELAY))
 	if (!dst_wait_dst_ready(state, NO_DELAY))
 		return -EIO;
 		return -EIO;
-	if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
-		/* how to get variable length reply ???? */
+	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+		!(state->dst_type == DST_TYPE_IS_ATSC))
+
 		retval = read_dst(state, state->rx_tuna, 10);
 		retval = read_dst(state, state->rx_tuna, 10);
 	else
 	else
 		retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
 		retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
@@ -1087,7 +1358,10 @@ static int dst_get_tuna(struct dst_state *state)
 		dprintk(verbose, DST_DEBUG, 1, "read not successful");
 		dprintk(verbose, DST_DEBUG, 1, "read not successful");
 		return retval;
 		return retval;
 	}
 	}
-	if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+		!(state->dst_type == DST_TYPE_IS_CABLE) &&
+		!(state->dst_type == DST_TYPE_IS_ATSC)) {
+
 		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
 		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
 			dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
 			dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
 			return -EIO;
 			return -EIO;
@@ -1133,7 +1407,10 @@ static int dst_write_tuna(struct dvb_frontend *fe)
 		dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
 		dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
 		goto error;
 		goto error;
 	}
 	}
-	if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+//	if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+		(!(state->dst_type == DST_TYPE_IS_ATSC))) {
+
 		state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
 		state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
 		retval = write_dst(state, &state->tx_tuna[0], 10);
 		retval = write_dst(state, &state->tx_tuna[0], 10);
 	} else {
 	} else {
@@ -1189,9 +1466,12 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd
 
 
 	if (state->dst_type != DST_TYPE_IS_SAT)
 	if (state->dst_type != DST_TYPE_IS_SAT)
 		return 0;
 		return 0;
-	if (cmd->msg_len == 0 || cmd->msg_len > 4)
+	if (cmd->msg_len > 0 && cmd->msg_len < 5)
+		memcpy(&paket[3], cmd->msg, cmd->msg_len);
+	else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
+		memcpy(&paket[2], cmd->msg, cmd->msg_len);
+	else
 		return -EINVAL;
 		return -EINVAL;
-	memcpy(&paket[3], cmd->msg, cmd->msg_len);
 	paket[7] = dst_check_sum(&paket[0], 7);
 	paket[7] = dst_check_sum(&paket[0], 7);
 	dst_command(state, paket, 8);
 	dst_command(state, paket, 8);
 	return 0;
 	return 0;
@@ -1287,8 +1567,9 @@ static int dst_init(struct dvb_frontend *fe)
 	static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
 	static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
 	static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
 	static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
 	static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
 	static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
-	static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
 	static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
 	static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+	static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+	static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
 
 
 	state->inversion = INVERSION_OFF;
 	state->inversion = INVERSION_OFF;
 	state->voltage = SEC_VOLTAGE_13;
 	state->voltage = SEC_VOLTAGE_13;
@@ -1298,11 +1579,13 @@ static int dst_init(struct dvb_frontend *fe)
 	state->bandwidth = BANDWIDTH_7_MHZ;
 	state->bandwidth = BANDWIDTH_7_MHZ;
 	state->cur_jiff = jiffies;
 	state->cur_jiff = jiffies;
 	if (state->dst_type == DST_TYPE_IS_SAT)
 	if (state->dst_type == DST_TYPE_IS_SAT)
-		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
+		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
 	else if (state->dst_type == DST_TYPE_IS_TERR)
 	else if (state->dst_type == DST_TYPE_IS_TERR)
-		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
+		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
 	else if (state->dst_type == DST_TYPE_IS_CABLE)
 	else if (state->dst_type == DST_TYPE_IS_CABLE)
-		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
+		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
+	else if (state->dst_type == DST_TYPE_IS_ATSC)
+		memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner));
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1341,7 +1624,36 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
 	return 0;
 	return 0;
 }
 }
 
 
-static int dst_set_frontend(struct dvb_frontend* fe,
+static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	struct dst_state *state = fe->demodulator_priv;
+
+	if (p != NULL) {
+		dst_set_freq(state, p->frequency);
+		dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+
+		if (state->dst_type == DST_TYPE_IS_SAT) {
+			if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+				dst_set_inversion(state, p->inversion);
+			dst_set_fec(state, p->u.qpsk.fec_inner);
+			dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+			dst_set_polarization(state);
+			dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+
+		} else if (state->dst_type == DST_TYPE_IS_TERR)
+			dst_set_bandwidth(state, p->u.ofdm.bandwidth);
+		else if (state->dst_type == DST_TYPE_IS_CABLE) {
+			dst_set_fec(state, p->u.qam.fec_inner);
+			dst_set_symbolrate(state, p->u.qam.symbol_rate);
+			dst_set_modulation(state, p->u.qam.modulation);
+		}
+		dst_write_tuna(fe);
+	}
+
+	return 0;
+}
+
+static int dst_tune_frontend(struct dvb_frontend* fe,
 			    struct dvb_frontend_parameters* p,
 			    struct dvb_frontend_parameters* p,
 			    unsigned int mode_flags,
 			    unsigned int mode_flags,
 			    int *delay,
 			    int *delay,
@@ -1378,6 +1690,11 @@ static int dst_set_frontend(struct dvb_frontend* fe,
 	return 0;
 	return 0;
 }
 }
 
 
+static int dst_get_tuning_algo(struct dvb_frontend *fe)
+{
+	return dst_algo;
+}
+
 static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
 static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
 {
 {
 	struct dst_state *state = fe->demodulator_priv;
 	struct dst_state *state = fe->demodulator_priv;
@@ -1408,6 +1725,7 @@ static void dst_release(struct dvb_frontend *fe)
 static struct dvb_frontend_ops dst_dvbt_ops;
 static struct dvb_frontend_ops dst_dvbt_ops;
 static struct dvb_frontend_ops dst_dvbs_ops;
 static struct dvb_frontend_ops dst_dvbs_ops;
 static struct dvb_frontend_ops dst_dvbc_ops;
 static struct dvb_frontend_ops dst_dvbc_ops;
+static struct dvb_frontend_ops dst_atsc_ops;
 
 
 struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
 struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
 {
 {
@@ -1417,24 +1735,25 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
 		return NULL;
 		return NULL;
 	}
 	}
 	/* determine settings based on type */
 	/* determine settings based on type */
+	/* create dvb_frontend */
 	switch (state->dst_type) {
 	switch (state->dst_type) {
 	case DST_TYPE_IS_TERR:
 	case DST_TYPE_IS_TERR:
-		memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
+		memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
 		break;
 		break;
 	case DST_TYPE_IS_CABLE:
 	case DST_TYPE_IS_CABLE:
-		memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
+		memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
 		break;
 		break;
 	case DST_TYPE_IS_SAT:
 	case DST_TYPE_IS_SAT:
-		memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
+		memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
+		break;
+	case DST_TYPE_IS_ATSC:
+		memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
 		break;
 		break;
 	default:
 	default:
 		dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
 		dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
 		kfree(state);
 		kfree(state);
 		return NULL;
 		return NULL;
 	}
 	}
-
-	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 
 
 	return state;				/*	Manu (DST is a card not a frontend)	*/
 	return state;				/*	Manu (DST is a card not a frontend)	*/
@@ -1455,8 +1774,10 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
 
 
 	.release = dst_release,
 	.release = dst_release,
 	.init = dst_init,
 	.init = dst_init,
-	.tune = dst_set_frontend,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
 	.get_frontend = dst_get_frontend,
 	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
 	.read_status = dst_read_status,
 	.read_status = dst_read_status,
 	.read_signal_strength = dst_read_signal_strength,
 	.read_signal_strength = dst_read_signal_strength,
 	.read_snr = dst_read_snr,
 	.read_snr = dst_read_snr,
@@ -1479,8 +1800,10 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
 
 
 	.release = dst_release,
 	.release = dst_release,
 	.init = dst_init,
 	.init = dst_init,
-	.tune = dst_set_frontend,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
 	.get_frontend = dst_get_frontend,
 	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
 	.read_status = dst_read_status,
 	.read_status = dst_read_status,
 	.read_signal_strength = dst_read_signal_strength,
 	.read_signal_strength = dst_read_signal_strength,
 	.read_snr = dst_read_snr,
 	.read_snr = dst_read_snr,
@@ -1506,13 +1829,38 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
 
 
 	.release = dst_release,
 	.release = dst_release,
 	.init = dst_init,
 	.init = dst_init,
-	.tune = dst_set_frontend,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
+	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
+	.read_status = dst_read_status,
+	.read_signal_strength = dst_read_signal_strength,
+	.read_snr = dst_read_snr,
+};
+
+static struct dvb_frontend_ops dst_atsc_ops = {
+	.info = {
+		.name = "DST ATSC",
+		.type = FE_ATSC,
+		.frequency_stepsize = 62500,
+		.frequency_min = 510000000,
+		.frequency_max = 858000000,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+
+	.release = dst_release,
+	.init = dst_init,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
 	.get_frontend = dst_get_frontend,
 	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
 	.read_status = dst_read_status,
 	.read_status = dst_read_status,
 	.read_signal_strength = dst_read_signal_strength,
 	.read_signal_strength = dst_read_signal_strength,
 	.read_snr = dst_read_snr,
 	.read_snr = dst_read_snr,
 };
 };
 
 
-MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
+MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
 MODULE_AUTHOR("Jamie Honan, Manu Abraham");
 MODULE_AUTHOR("Jamie Honan, Manu Abraham");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 101 - 15
drivers/media/dvb/bt8xx/dst_ca.c

@@ -68,6 +68,13 @@ static int ca_set_pid(void)
 	return -EOPNOTSUPP;
 	return -EOPNOTSUPP;
 }
 }
 
 
+static void put_command_and_length(u8 *data, int command, int length)
+{
+	data[0] = (command >> 16) & 0xff;
+	data[1] = (command >> 8) & 0xff;
+	data[2] = command & 0xff;
+	data[3] = length;
+}
 
 
 static void put_checksum(u8 *check_string, int length)
 static void put_checksum(u8 *check_string, int length)
 {
 {
@@ -124,15 +131,18 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
 	u8 dst_ca_comm_err = 0;
 	u8 dst_ca_comm_err = 0;
 
 
 	while (dst_ca_comm_err < RETRIES) {
 	while (dst_ca_comm_err < RETRIES) {
-		dst_comm_init(state);
 		dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
 		dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
 		if (dst_ci_command(state, data, ca_string, len, read)) {	// If error
 		if (dst_ci_command(state, data, ca_string, len, read)) {	// If error
 			dst_error_recovery(state);
 			dst_error_recovery(state);
 			dst_ca_comm_err++; // work required here.
 			dst_ca_comm_err++; // work required here.
+		} else {
+			break;
 		}
 		}
-		break;
 	}
 	}
 
 
+	if(dst_ca_comm_err == RETRIES)
+		return -1;
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -140,6 +150,7 @@ static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string,
 
 
 static int ca_get_app_info(struct dst_state *state)
 static int ca_get_app_info(struct dst_state *state)
 {
 {
+	int length, str_length;
 	static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
 	static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
 
 
 	put_checksum(&command[0], command[0]);
 	put_checksum(&command[0], command[0]);
@@ -154,6 +165,68 @@ static int ca_get_app_info(struct dst_state *state)
 		(state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
 		(state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
 	dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
 	dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
 
 
+	// Transform dst message to correct application_info message
+	length = state->messages[5];
+	str_length = length - 6;
+	if (str_length < 0) {
+		str_length = 0;
+		dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering.");
+	}
+
+	// First, the command and length fields
+	put_command_and_length(&state->messages[0], CA_APP_INFO, length);
+
+	// Copy application_type, application_manufacturer and manufacturer_code
+	memcpy(&state->messages[4], &state->messages[7], 5);
+
+	// Set string length and copy string
+	state->messages[9] = str_length;
+	memcpy(&state->messages[10], &state->messages[12], str_length);
+
+	return 0;
+}
+
+static int ca_get_ca_info(struct dst_state *state)
+{
+	int srcPtr, dstPtr, i, num_ids;
+	static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff};
+	const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7;
+
+	put_checksum(&slot_command[0], slot_command[0]);
+	if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) {
+		dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
+		return -1;
+	}
+	dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+
+	// Print raw data
+	dprintk(verbose, DST_CA_INFO, 0, " DST data = [");
+	for (i = 0; i < state->messages[0] + 1; i++) {
+		dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]);
+	}
+	dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
+	// Set the command and length of the output
+	num_ids = state->messages[in_num_ids_pos];
+	if (num_ids >= 100) {
+		num_ids = 100;
+		dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering.");
+	}
+	put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2);
+
+	dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = [");
+	srcPtr = in_system_id_pos;
+	dstPtr = out_system_id_pos;
+	for(i = 0; i < num_ids; i++) {
+		dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]);
+		// Append to output
+		state->messages[dstPtr + 0] = state->messages[srcPtr + 0];
+		state->messages[dstPtr + 1] = state->messages[srcPtr + 1];
+		srcPtr += 2;
+		dstPtr += 2;
+	}
+	dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -174,7 +247,7 @@ static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps,
 
 
 	dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
 	dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
 	dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
 	dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
-	for (i = 0; i < 8; i++)
+	for (i = 0; i < slot_cap[0] + 1; i++)
 		dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
 		dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
 	dprintk(verbose, DST_CA_INFO, 0, "\n");
 	dprintk(verbose, DST_CA_INFO, 0, "\n");
 
 
@@ -260,6 +333,11 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
 			if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
 			if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
 				return -EFAULT;
 				return -EFAULT;
 			break;
 			break;
+		case CA_INFO:
+			memcpy(p_ca_message->msg, state->messages, 128);
+			if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
+				return -EFAULT;
+			break;
 		}
 		}
 	}
 	}
 
 
@@ -302,7 +380,7 @@ static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 l
 		rdc_reset_state(state);
 		rdc_reset_state(state);
 		return -1;
 		return -1;
 	}
 	}
-	dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes.");
+	dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success.");
 
 
 	return 0;
 	return 0;
 }
 }
@@ -340,6 +418,7 @@ static int debug_string(u8 *msg, u32 length, u32 offset)
 	return 0;
 	return 0;
 }
 }
 
 
+
 static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
 static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
 {
 {
 	u32 length = 0;
 	u32 length = 0;
@@ -455,6 +534,16 @@ static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message,
 			}
 			}
 			dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
 			dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
 			break;
 			break;
+		case CA_INFO_ENQUIRY:
+			dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information");
+
+			if ((ca_get_ca_info(state)) < 0) {
+				dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !");
+				result = -1;
+				goto free_mem_and_exit;
+			}
+			dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !");
+			break;
 		}
 		}
 	}
 	}
 free_mem_and_exit:
 free_mem_and_exit:
@@ -473,18 +562,15 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 	void __user *arg = (void __user *)ioctl_arg;
 	void __user *arg = (void __user *)ioctl_arg;
 	int result = 0;
 	int result = 0;
 
 
-	if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
-		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-		return -ENOMEM;
-	}
-	if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
+	p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
+	p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
+	p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL);
+	if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) {
 		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
 		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-		return -ENOMEM;
-	}
-	if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
-		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-		return -ENOMEM;
+		result = -ENOMEM;
+		goto free_mem_and_exit;
 	}
 	}
+
 	/*	We have now only the standard ioctl's, the driver is upposed to handle internals.	*/
 	/*	We have now only the standard ioctl's, the driver is upposed to handle internals.	*/
 	switch (cmd) {
 	switch (cmd) {
 	case CA_SEND_MSG:
 	case CA_SEND_MSG:
@@ -582,7 +668,7 @@ static int dst_ca_release(struct inode *inode, struct file *file)
 
 
 static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
 static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
 {
 {
-	int bytes_read = 0;
+	ssize_t bytes_read = 0;
 
 
 	dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
 	dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
 
 

+ 29 - 4
drivers/media/dvb/bt8xx/dst_common.h

@@ -42,7 +42,7 @@
 #define DST_TYPE_IS_CABLE	2
 #define DST_TYPE_IS_CABLE	2
 #define DST_TYPE_IS_ATSC	3
 #define DST_TYPE_IS_ATSC	3
 
 
-#define DST_TYPE_HAS_NEWTUNE	1
+#define DST_TYPE_HAS_TS188	1
 #define DST_TYPE_HAS_TS204	2
 #define DST_TYPE_HAS_TS204	2
 #define DST_TYPE_HAS_SYMDIV	4
 #define DST_TYPE_HAS_SYMDIV	4
 #define DST_TYPE_HAS_FW_1	8
 #define DST_TYPE_HAS_FW_1	8
@@ -52,6 +52,9 @@
 #define DST_TYPE_HAS_OBS_REGS	128
 #define DST_TYPE_HAS_OBS_REGS	128
 #define DST_TYPE_HAS_INC_COUNT	256
 #define DST_TYPE_HAS_INC_COUNT	256
 #define DST_TYPE_HAS_MULTI_FE	512
 #define DST_TYPE_HAS_MULTI_FE	512
+#define DST_TYPE_HAS_NEWTUNE_2	1024
+#define DST_TYPE_HAS_DBOARD	2048
+#define DST_TYPE_HAS_VLF	4096
 
 
 /*	Card capability list	*/
 /*	Card capability list	*/
 
 
@@ -64,6 +67,20 @@
 #define	DST_TYPE_HAS_ANALOG	64	/*	Analog inputs	*/
 #define	DST_TYPE_HAS_ANALOG	64	/*	Analog inputs	*/
 #define DST_TYPE_HAS_SESSION	128
 #define DST_TYPE_HAS_SESSION	128
 
 
+#define TUNER_TYPE_MULTI	1
+#define TUNER_TYPE_UNKNOWN	2
+/*	DVB-S		*/
+#define TUNER_TYPE_L64724	4
+#define TUNER_TYPE_STV0299	8
+#define TUNER_TYPE_MB86A15	16
+
+/*	DVB-T		*/
+#define TUNER_TYPE_TDA10046	32
+
+/*	ATSC		*/
+#define TUNER_TYPE_NXT200x	64
+
+
 #define RDC_8820_PIO_0_DISABLE	0
 #define RDC_8820_PIO_0_DISABLE	0
 #define RDC_8820_PIO_0_ENABLE	1
 #define RDC_8820_PIO_0_ENABLE	1
 #define RDC_8820_INT		2
 #define RDC_8820_INT		2
@@ -84,8 +101,6 @@ struct dst_state {
 
 
 	struct bt878* bt;
 	struct bt878* bt;
 
 
-	struct dvb_frontend_ops ops;
-
 	/* configuration settings */
 	/* configuration settings */
 	const struct dst_config* config;
 	const struct dst_config* config;
 
 
@@ -121,8 +136,17 @@ struct dst_state {
 	u8 card_info[8];
 	u8 card_info[8];
 	u8 vendor[8];
 	u8 vendor[8];
 	u8 board_info[8];
 	u8 board_info[8];
-
+	u32 tuner_type;
+	char *tuner_name;
 	struct mutex dst_mutex;
 	struct mutex dst_mutex;
+	u8 fw_name[8];
+};
+
+struct tuner_types {
+	u32 tuner_type;
+	char *tuner_name;
+	char *board_name;
+	char *fw_name;
 };
 };
 
 
 struct dst_types {
 struct dst_types {
@@ -131,6 +155,7 @@ struct dst_types {
 	u8 dst_type;
 	u8 dst_type;
 	u32 type_flags;
 	u32 type_flags;
 	u32 dst_feature;
 	u32 dst_feature;
+	u32 tuner_type;
 };
 };
 
 
 struct dst_config
 struct dst_config

+ 61 - 57
drivers/media/dvb/bt8xx/dvb-bt8xx.c

@@ -147,12 +147,15 @@ static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
 	return 0;
 	return 0;
 }
 }
 
 
-static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
 {
 	u32 div;
 	u32 div;
 	unsigned char bs = 0;
 	unsigned char bs = 0;
 	unsigned char cp = 0;
 	unsigned char cp = 0;
 
 
+	if (buf_len < 5)
+		return -EINVAL;
+
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
 
 	if (params->frequency < 542000000)
 	if (params->frequency < 542000000)
@@ -169,22 +172,25 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
 	else
 	else
 		bs = 0x08;
 		bs = 0x08;
 
 
-	pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
+	pllbuf[0] = 0x60;
 	pllbuf[1] = div >> 8;
 	pllbuf[1] = div >> 8;
 	pllbuf[2] = div & 0xff;
 	pllbuf[2] = div & 0xff;
 	pllbuf[3] = cp;
 	pllbuf[3] = cp;
 	pllbuf[4] = bs;
 	pllbuf[4] = bs;
 
 
-	return 0;
+	return 5;
 }
 }
 
 
 static struct mt352_config thomson_dtt7579_config = {
 static struct mt352_config thomson_dtt7579_config = {
 	.demod_address = 0x0f,
 	.demod_address = 0x0f,
 	.demod_init = thomson_dtt7579_demod_init,
 	.demod_init = thomson_dtt7579_demod_init,
-	.pll_set = thomson_dtt7579_pll_set,
 };
 };
 
 
-static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static struct zl10353_config thomson_dtt7579_zl10353_config = {
+	.demod_address = 0x0f,
+};
+
+static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 {
 	u32 freq = params->frequency;
 	u32 freq = params->frequency;
 
 
@@ -237,7 +243,7 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
 	return 0;
 	return 0;
 }
 }
 
 
-static int pinnsat_pll_init(struct dvb_frontend* fe)
+static int pinnsat_tuner_init(struct dvb_frontend* fe)
 {
 {
 	struct dvb_bt8xx_card *card = fe->dvb->priv;
 	struct dvb_bt8xx_card *card = fe->dvb->priv;
 
 
@@ -247,7 +253,7 @@ static int pinnsat_pll_init(struct dvb_frontend* fe)
 	return 0;
 	return 0;
 }
 }
 
 
-static int pinnsat_pll_sleep(struct dvb_frontend* fe)
+static int pinnsat_tuner_sleep(struct dvb_frontend* fe)
 {
 {
 	struct dvb_bt8xx_card *card = fe->dvb->priv;
 	struct dvb_bt8xx_card *card = fe->dvb->priv;
 
 
@@ -258,12 +264,9 @@ static int pinnsat_pll_sleep(struct dvb_frontend* fe)
 
 
 static struct cx24110_config pctvsat_config = {
 static struct cx24110_config pctvsat_config = {
 	.demod_address = 0x55,
 	.demod_address = 0x55,
-	.pll_init = pinnsat_pll_init,
-	.pll_set = cx24108_pll_set,
-	.pll_sleep = pinnsat_pll_sleep,
 };
 };
 
 
-static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 {
 	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
 	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
 	u8 cfg, cpump, band_select;
 	u8 cfg, cpump, band_select;
@@ -297,6 +300,8 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front
 	data[2] = ((div >> 10) & 0x60) | cfg;
 	data[2] = ((div >> 10) & 0x60) | cfg;
 	data[3] = (cpump << 6) | band_select;
 	data[3] = (cpump << 6) | band_select;
 
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(card->i2c_adapter, &msg, 1);
 	i2c_transfer(card->i2c_adapter, &msg, 1);
 	return (div * 166666 - 36000000);
 	return (div * 166666 - 36000000);
 }
 }
@@ -310,7 +315,6 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s
 
 
 static struct sp887x_config microtune_mt7202dtf_config = {
 static struct sp887x_config microtune_mt7202dtf_config = {
 	.demod_address = 0x70,
 	.demod_address = 0x70,
-	.pll_set = microtune_mt7202dtf_pll_set,
 	.request_firmware = microtune_mt7202dtf_request_firmware,
 	.request_firmware = microtune_mt7202dtf_request_firmware,
 };
 };
 
 
@@ -337,12 +341,14 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
 	return 0;
 	return 0;
 }
 }
 
 
-static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
 {
 	u32 div;
 	u32 div;
 	unsigned char bs = 0;
 	unsigned char bs = 0;
 	unsigned char cp = 0;
 	unsigned char cp = 0;
 
 
+	if (buf_len < 5) return -EINVAL;
+
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
 
 	if (params->frequency < 150000000)
 	if (params->frequency < 150000000)
@@ -383,19 +389,18 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
 	else
 	else
 		bs = 0x08;
 		bs = 0x08;
 
 
-	pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
+	pllbuf[0] = 0x61;
 	pllbuf[1] = div >> 8;
 	pllbuf[1] = div >> 8;
 	pllbuf[2] = div & 0xff;
 	pllbuf[2] = div & 0xff;
 	pllbuf[3] = cp;
 	pllbuf[3] = cp;
 	pllbuf[4] = bs;
 	pllbuf[4] = bs;
 
 
-	return 0;
+	return 5;
 }
 }
 
 
 static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
 static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
 	.demod_address = 0x0f,
 	.demod_address = 0x0f,
 	.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
 	.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
-	.pll_set = advbt771_samsung_tdtc9251dh0_pll_set,
 };
 };
 
 
 static struct dst_config dst_config = {
 static struct dst_config dst_config = {
@@ -455,7 +460,7 @@ static struct or51211_config or51211_config = {
 	.sleep = or51211_sleep,
 	.sleep = or51211_sleep,
 };
 };
 
 
-static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 {
 	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
 	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
 	u8 buf[4];
 	u8 buf[4];
@@ -478,6 +483,8 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
 	else
 	else
 		return -EINVAL;
 		return -EINVAL;
 
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(card->i2c_adapter, &msg, 1);
 	i2c_transfer(card->i2c_adapter, &msg, 1);
 	return 0;
 	return 0;
 }
 }
@@ -485,7 +492,6 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
 static struct nxt6000_config vp3021_alps_tded4_config = {
 static struct nxt6000_config vp3021_alps_tded4_config = {
 	.demod_address = 0x0a,
 	.demod_address = 0x0a,
 	.clock_inversion = 1,
 	.clock_inversion = 1,
-	.pll_set = vp3021_alps_tded4_pll_set,
 };
 };
 
 
 static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
 static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
@@ -506,14 +512,17 @@ static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
 	return 0;
 	return 0;
 }
 }
 
 
-static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
 {
 	u32 div;
 	u32 div;
 	struct dvb_ofdm_parameters *op = &params->u.ofdm;
 	struct dvb_ofdm_parameters *op = &params->u.ofdm;
 
 
+	if (buf_len < 5)
+		return -EINVAL;
+
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
 
-	pllbuf[0] = 0xc2;
+	pllbuf[0] = 0x61;
 	pllbuf[1] = (div >> 8) & 0x7F;
 	pllbuf[1] = (div >> 8) & 0x7F;
 	pllbuf[2] = div & 0xFF;
 	pllbuf[2] = div & 0xFF;
 	pllbuf[3] = 0x85;
 	pllbuf[3] = 0x85;
@@ -530,7 +539,7 @@ static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
 	if (op->bandwidth == 8)
 	if (op->bandwidth == 8)
 		pllbuf[4] |= 0x04;
 		pllbuf[4] |= 0x04;
 
 
-	return 0;
+	return 5;
 }
 }
 
 
 static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
 static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
@@ -557,43 +566,18 @@ static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
 static struct mt352_config digitv_alps_tded4_config = {
 static struct mt352_config digitv_alps_tded4_config = {
 	.demod_address = 0x0a,
 	.demod_address = 0x0a,
 	.demod_init = digitv_alps_tded4_demod_init,
 	.demod_init = digitv_alps_tded4_demod_init,
-	.pll_set = digitv_alps_tded4_pll_set,
 };
 };
 
 
-static int tdvs_tua6034_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 {
 	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
 	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
-	u8 buf[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-	int err;
-
-	dvb_pll_configure(&dvb_pll_tdvs_tua6034, buf, params->frequency, 0);
-	dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
-	if ((err = i2c_transfer(card->i2c_adapter, &msg, 1)) != 1) {
-		printk(KERN_WARNING "dvb-bt8xx: %s error "
-			"(addr %02x <- %02x, err = %i)\n",
-			__FUNCTION__, buf[0], buf[1], err);
-		if (err < 0)
-			return err;
-		else
-			return -EREMOTEIO;
-	}
-
-	/* Set the Auxiliary Byte. */
-	buf[2] &= ~0x20;
-	buf[2] |= 0x18;
-	buf[3] = 0x50;
-	i2c_transfer(card->i2c_adapter, &msg, 1);
-
-	return 0;
+	return lg_h06xf_pll_set(fe, card->i2c_adapter, params);
 }
 }
 
 
 static struct lgdt330x_config tdvs_tua6034_config = {
 static struct lgdt330x_config tdvs_tua6034_config = {
 	.demod_address    = 0x0e,
 	.demod_address    = 0x0e,
 	.demod_chip       = LGDT3303,
 	.demod_chip       = LGDT3303,
 	.serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
 	.serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-	.pll_set          = tdvs_tua6034_pll_set,
 };
 };
 
 
 static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
 static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
@@ -617,17 +601,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 	switch(type) {
 	switch(type) {
 	case BTTV_BOARD_DVICO_DVBT_LITE:
 	case BTTV_BOARD_DVICO_DVBT_LITE:
 		card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
 		card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
+
+		if (card->fe == NULL)
+			card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config,
+						  card->i2c_adapter);
+
 		if (card->fe != NULL) {
 		if (card->fe != NULL) {
-			card->fe->ops->info.frequency_min = 174000000;
-			card->fe->ops->info.frequency_max = 862000000;
+			card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs;
+			card->fe->ops.info.frequency_min = 174000000;
+			card->fe->ops.info.frequency_max = 862000000;
 		}
 		}
 		break;
 		break;
 
 
 	case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
 	case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
 		lgdt330x_reset(card);
 		lgdt330x_reset(card);
 		card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
 		card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
-		if (card->fe != NULL)
+		if (card->fe != NULL) {
+			card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
 			dprintk ("dvb_bt8xx: lgdt330x detected\n");
 			dprintk ("dvb_bt8xx: lgdt330x detected\n");
+		}
 		break;
 		break;
 
 
 	case BTTV_BOARD_NEBULA_DIGITV:
 	case BTTV_BOARD_NEBULA_DIGITV:
@@ -640,6 +632,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 		digitv_alps_tded4_reset(card);
 		digitv_alps_tded4_reset(card);
 		card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
 		card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
 		if (card->fe != NULL) {
 		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");
 			dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
 			break;
 			break;
 		}
 		}
@@ -648,19 +641,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 		digitv_alps_tded4_reset(card);
 		digitv_alps_tded4_reset(card);
 		card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
 		card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
 
 
-		if (card->fe != NULL)
+		if (card->fe != NULL) {
+			card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
 			dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
 			dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
+		}
 		break;
 		break;
 
 
 	case BTTV_BOARD_AVDVBT_761:
 	case BTTV_BOARD_AVDVBT_761:
 		card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
 		card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
+		if (card->fe) {
+			card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
+		}
 		break;
 		break;
 
 
 	case BTTV_BOARD_AVDVBT_771:
 	case BTTV_BOARD_AVDVBT_771:
 		card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
 		card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
 		if (card->fe != NULL) {
 		if (card->fe != NULL) {
-			card->fe->ops->info.frequency_min = 174000000;
-			card->fe->ops->info.frequency_max = 862000000;
+			card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
+			card->fe->ops.info.frequency_min = 174000000;
+			card->fe->ops.info.frequency_max = 862000000;
 		}
 		}
 		break;
 		break;
 
 
@@ -687,6 +686,11 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 
 
 	case BTTV_BOARD_PINNACLESAT:
 	case BTTV_BOARD_PINNACLESAT:
 		card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
 		card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
+		if (card->fe) {
+			card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
+			card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
+			card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params;
+		}
 		break;
 		break;
 
 
 	case BTTV_BOARD_PC_HDTV:
 	case BTTV_BOARD_PC_HDTV:
@@ -703,8 +707,8 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 	else
 	else
 		if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
 		if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
 			printk("dvb-bt8xx: Frontend registration failed!\n");
 			printk("dvb-bt8xx: Frontend registration failed!\n");
-			if (card->fe->ops->release)
-				card->fe->ops->release(card->fe);
+			if (card->fe->ops.release)
+				card->fe->ops.release(card->fe);
 			card->fe = NULL;
 			card->fe = NULL;
 		}
 		}
 }
 }
@@ -713,7 +717,7 @@ static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
 {
 {
 	int result;
 	int result;
 
 
-	if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) {
+	if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) {
 		printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
 		printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
 		return result;
 		return result;
 	}
 	}

+ 2 - 0
drivers/media/dvb/bt8xx/dvb-bt8xx.h

@@ -37,6 +37,8 @@
 #include "cx24110.h"
 #include "cx24110.h"
 #include "or51211.h"
 #include "or51211.h"
 #include "lgdt330x.h"
 #include "lgdt330x.h"
+#include "lg_h06xf.h"
+#include "zl10353.h"
 
 
 struct dvb_bt8xx_card {
 struct dvb_bt8xx_card {
 	struct mutex lock;
 	struct mutex lock;

+ 1 - 1
drivers/media/dvb/cinergyT2/Kconfig

@@ -64,7 +64,7 @@ config DVB_CINERGYT2_QUERY_INTERVAL
 config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
 config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
 	bool "Register the onboard IR Remote Control Receiver as Input Device"
 	bool "Register the onboard IR Remote Control Receiver as Input Device"
 	depends on DVB_CINERGYT2_TUNING
 	depends on DVB_CINERGYT2_TUNING
-	default "yes"
+	default y
 	help
 	help
 	  Enable this option if you want to use the onboard Infrared Remote
 	  Enable this option if you want to use the onboard Infrared Remote
 	  Control Receiver as Linux-Input device.
 	  Control Receiver as Linux-Input device.

+ 6 - 2
drivers/media/dvb/cinergyT2/cinergyT2.c

@@ -544,15 +544,19 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
 {
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_device *dvbdev = file->private_data;
 	struct cinergyt2 *cinergyt2 = dvbdev->priv;
 	struct cinergyt2 *cinergyt2 = dvbdev->priv;
+       unsigned int mask = 0;
 
 
 	if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
 	if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
 		return -ERESTARTSYS;
 		return -ERESTARTSYS;
 
 
 	poll_wait(file, &cinergyt2->poll_wq, wait);
 	poll_wait(file, &cinergyt2->poll_wq, wait);
 
 
+       if (cinergyt2->pending_fe_events != 0)
+		mask |= (POLLIN | POLLRDNORM | POLLPRI);
+
 	mutex_unlock(&cinergyt2->sem);
 	mutex_unlock(&cinergyt2->sem);
 
 
-	return (POLLIN | POLLRDNORM | POLLPRI);
+       return mask;
 }
 }
 
 
 
 
@@ -902,7 +906,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE)) < 0) {
+	if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) {
 		kfree(cinergyt2);
 		kfree(cinergyt2);
 		return err;
 		return err;
 	}
 	}

+ 3 - 3
drivers/media/dvb/dvb-core/Makefile

@@ -2,8 +2,8 @@
 # Makefile for the kernel DVB device drivers.
 # Makefile for the kernel DVB device drivers.
 #
 #
 
 
-dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
-		dvb_ca_en50221.o dvb_frontend.o \
-		dvb_net.o dvb_ringbuffer.o
+dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\
+		dvb_ca_en50221.o dvb_frontend.o 		\
+		dvb_net.o dvb_ringbuffer.o dvb_math.o
 
 
 obj-$(CONFIG_DVB_CORE) += dvb-core.o
 obj-$(CONFIG_DVB_CORE) += dvb-core.o

+ 0 - 3
drivers/media/dvb/dvb-core/dmxdev.c

@@ -872,9 +872,6 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file,
 		mutex_unlock(&dmxdevfilter->mutex);
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 		break;
 
 
-	case DMX_GET_EVENT:
-		break;
-
 	case DMX_GET_PES_PIDS:
 	case DMX_GET_PES_PIDS:
 		if (!dmxdev->demux->get_pes_pids) {
 		if (!dmxdev->demux->get_pes_pids) {
 			ret = -EINVAL;
 			ret = -EINVAL;

+ 23 - 2
drivers/media/dvb/dvb-core/dvb_ca_en50221.c

@@ -1060,8 +1060,18 @@ static int dvb_ca_en50221_thread(void *data)
 				break;
 				break;
 
 
 			case DVB_CA_SLOTSTATE_VALIDATE:
 			case DVB_CA_SLOTSTATE_VALIDATE:
-				if (dvb_ca_en50221_parse_attributes(ca, slot)
-				    != 0) {
+				if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
+					/* we need this extra check for annoying interfaces like the budget-av */
+					if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
+					    (ca->pub->poll_slot_status)) {
+						int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+						if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
+							ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+							dvb_ca_en50221_thread_update_delay(ca);
+							break;
+						}
+					}
+
 					printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
 					printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
 					       ca->dvbdev->adapter->num);
 					       ca->dvbdev->adapter->num);
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
@@ -1108,6 +1118,17 @@ static int dvb_ca_en50221_thread(void *data)
 
 
 			case DVB_CA_SLOTSTATE_LINKINIT:
 			case DVB_CA_SLOTSTATE_LINKINIT:
 				if (dvb_ca_en50221_link_init(ca, slot) != 0) {
 				if (dvb_ca_en50221_link_init(ca, slot) != 0) {
+					/* we need this extra check for annoying interfaces like the budget-av */
+					if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
+					    (ca->pub->poll_slot_status)) {
+						int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+						if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
+							ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+							dvb_ca_en50221_thread_update_delay(ca);
+							break;
+						}
+					}
+
 					printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
 					printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 					dvb_ca_en50221_thread_update_delay(ca);
 					dvb_ca_en50221_thread_update_delay(ca);

+ 2 - 2
drivers/media/dvb/dvb-core/dvb_demux.c

@@ -473,7 +473,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
 			goto bailout;
 			goto bailout;
 		}
 		}
 		memcpy(&demux->tsbuf[i], buf, j);
 		memcpy(&demux->tsbuf[i], buf, j);
-		if ((demux->tsbuf[0] == 0x47) | (demux->tsbuf[0] == 0xB8)) {
+		if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) {
 			memcpy(tmppack, demux->tsbuf, 188);
 			memcpy(tmppack, demux->tsbuf, 188);
 			if (tmppack[0] == 0xB8)
 			if (tmppack[0] == 0xB8)
 				tmppack[0] = 0x47;
 				tmppack[0] = 0x47;
@@ -484,7 +484,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
 	}
 	}
 
 
 	while (p < count) {
 	while (p < count) {
-		if ((buf[p] == 0x47) | (buf[p] == 0xB8)) {
+		if ((buf[p] == 0x47) || (buf[p] == 0xB8)) {
 			if (count - p >= 204) {
 			if (count - p >= 204) {
 				memcpy(tmppack, &buf[p], 188);
 				memcpy(tmppack, &buf[p], 188);
 				if (tmppack[0] == 0xB8)
 				if (tmppack[0] == 0xB8)

+ 85 - 66
drivers/media/dvb/dvb-core/dvb_frontend.c

@@ -56,7 +56,7 @@ MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AU
 module_param(dvb_override_tune_delay, int, 0644);
 module_param(dvb_override_tune_delay, int, 0644);
 MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
 MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
 module_param(dvb_powerdown_on_sleep, int, 0644);
 module_param(dvb_powerdown_on_sleep, int, 0644);
-MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)");
+MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
 
 
 #define dprintk if (dvb_frontend_debug) printk
 #define dprintk if (dvb_frontend_debug) printk
 
 
@@ -72,6 +72,8 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB vola
 #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
 #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
 #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
 #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
 #define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
 #define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
+
+#define FE_ALGO_HW		1
 /*
 /*
  * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
  * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
  * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
  * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
@@ -151,8 +153,8 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
 		sizeof (struct dvb_frontend_parameters));
 		sizeof (struct dvb_frontend_parameters));
 
 
 	if (status & FE_HAS_LOCK)
 	if (status & FE_HAS_LOCK)
-		if (fe->ops->get_frontend)
-			fe->ops->get_frontend(fe, &e->parameters);
+		if (fe->ops.get_frontend)
+			fe->ops.get_frontend(fe, &e->parameters);
 
 
 	events->eventw = wp;
 	events->eventw = wp;
 
 
@@ -211,10 +213,15 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
 {
 {
 	dprintk ("DVB: initialising frontend %i (%s)...\n",
 	dprintk ("DVB: initialising frontend %i (%s)...\n",
 		 fe->dvb->num,
 		 fe->dvb->num,
-		 fe->ops->info.name);
-
-	if (fe->ops->init)
-		fe->ops->init(fe);
+		 fe->ops.info.name);
+
+	if (fe->ops.init)
+		fe->ops.init(fe);
+	if (fe->ops.tuner_ops.init) {
+		fe->ops.tuner_ops.init(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 }
 }
 
 
 void dvb_frontend_reinitialise(struct dvb_frontend *fe)
 void dvb_frontend_reinitialise(struct dvb_frontend *fe)
@@ -259,7 +266,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
 	u32 original_frequency = fepriv->parameters.frequency;
 	u32 original_frequency = fepriv->parameters.frequency;
 
 
 	/* are we using autoinversion? */
 	/* are we using autoinversion? */
-	autoinversion = ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+	autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
 			 (fepriv->parameters.inversion == INVERSION_AUTO));
 			 (fepriv->parameters.inversion == INVERSION_AUTO));
 
 
 	/* setup parameters correctly */
 	/* setup parameters correctly */
@@ -329,8 +336,8 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
 	fepriv->parameters.frequency += fepriv->lnb_drift;
 	fepriv->parameters.frequency += fepriv->lnb_drift;
 	if (autoinversion)
 	if (autoinversion)
 		fepriv->parameters.inversion = fepriv->inversion;
 		fepriv->parameters.inversion = fepriv->inversion;
-	if (fe->ops->set_frontend)
-		fe->ops->set_frontend(fe, &fepriv->parameters);
+	if (fe->ops.set_frontend)
+		fe->ops.set_frontend(fe, &fepriv->parameters);
 
 
 	fepriv->parameters.frequency = original_frequency;
 	fepriv->parameters.frequency = original_frequency;
 	fepriv->parameters.inversion = original_inversion;
 	fepriv->parameters.inversion = original_inversion;
@@ -354,8 +361,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
 	/* in SCAN mode, we just set the frontend when asked and leave it alone */
 	/* in SCAN mode, we just set the frontend when asked and leave it alone */
 	if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
 	if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
 		if (fepriv->state & FESTATE_RETUNE) {
 		if (fepriv->state & FESTATE_RETUNE) {
-			if (fe->ops->set_frontend)
-				fe->ops->set_frontend(fe, &fepriv->parameters);
+			if (fe->ops.set_frontend)
+				fe->ops.set_frontend(fe, &fepriv->parameters);
 			fepriv->state = FESTATE_TUNED;
 			fepriv->state = FESTATE_TUNED;
 		}
 		}
 		fepriv->delay = 3*HZ;
 		fepriv->delay = 3*HZ;
@@ -367,8 +374,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
 	if (fepriv->state & FESTATE_RETUNE) {
 	if (fepriv->state & FESTATE_RETUNE) {
 		s = 0;
 		s = 0;
 	} else {
 	} else {
-		if (fe->ops->read_status)
-			fe->ops->read_status(fe, &s);
+		if (fe->ops.read_status)
+			fe->ops.read_status(fe, &s);
 		if (s != fepriv->status) {
 		if (s != fepriv->status) {
 			dvb_frontend_add_event(fe, s);
 			dvb_frontend_add_event(fe, s);
 			fepriv->status = s;
 			fepriv->status = s;
@@ -381,7 +388,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
 		fepriv->state = FESTATE_TUNED;
 		fepriv->state = FESTATE_TUNED;
 
 
 		/* if we're tuned, then we have determined the correct inversion */
 		/* if we're tuned, then we have determined the correct inversion */
-		if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+		if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
 		    (fepriv->parameters.inversion == INVERSION_AUTO)) {
 		    (fepriv->parameters.inversion == INVERSION_AUTO)) {
 			fepriv->parameters.inversion = fepriv->inversion;
 			fepriv->parameters.inversion = fepriv->inversion;
 		}
 		}
@@ -405,7 +412,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
 	/* don't actually do anything if we're in the LOSTLOCK state,
 	/* don't actually do anything if we're in the LOSTLOCK state,
 	 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
 	 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
 	if ((fepriv->state & FESTATE_LOSTLOCK) &&
 	if ((fepriv->state & FESTATE_LOSTLOCK) &&
-	    (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
+	    (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
 		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
 		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
 		return;
 		return;
 	}
 	}
@@ -540,16 +547,16 @@ static int dvb_frontend_thread(void *data)
 		if (fepriv->reinitialise) {
 		if (fepriv->reinitialise) {
 			dvb_frontend_init(fe);
 			dvb_frontend_init(fe);
 			if (fepriv->tone != -1) {
 			if (fepriv->tone != -1) {
-				fe->ops->set_tone(fe, fepriv->tone);
+				fe->ops.set_tone(fe, fepriv->tone);
 			}
 			}
 			if (fepriv->voltage != -1) {
 			if (fepriv->voltage != -1) {
-				fe->ops->set_voltage(fe, fepriv->voltage);
+				fe->ops.set_voltage(fe, fepriv->voltage);
 			}
 			}
 			fepriv->reinitialise = 0;
 			fepriv->reinitialise = 0;
 		}
 		}
 
 
 		/* do an iteration of the tuning loop */
 		/* do an iteration of the tuning loop */
-		if (fe->ops->tune) {
+		if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
 			/* have we been asked to retune? */
 			/* have we been asked to retune? */
 			params = NULL;
 			params = NULL;
 			if (fepriv->state & FESTATE_RETUNE) {
 			if (fepriv->state & FESTATE_RETUNE) {
@@ -557,7 +564,7 @@ static int dvb_frontend_thread(void *data)
 				fepriv->state = FESTATE_TUNED;
 				fepriv->state = FESTATE_TUNED;
 			}
 			}
 
 
-			fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+			fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
 			if (s != fepriv->status) {
 			if (s != fepriv->status) {
 				dvb_frontend_add_event(fe, s);
 				dvb_frontend_add_event(fe, s);
 				fepriv->status = s;
 				fepriv->status = s;
@@ -569,10 +576,15 @@ static int dvb_frontend_thread(void *data)
 
 
 	if (dvb_shutdown_timeout) {
 	if (dvb_shutdown_timeout) {
 		if (dvb_powerdown_on_sleep)
 		if (dvb_powerdown_on_sleep)
-			if (fe->ops->set_voltage)
-				fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF);
-		if (fe->ops->sleep)
-			fe->ops->sleep(fe);
+			if (fe->ops.set_voltage)
+				fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
+		if (fe->ops.tuner_ops.sleep) {
+			fe->ops.tuner_ops.sleep(fe);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		if (fe->ops.sleep)
+			fe->ops.sleep(fe);
 	}
 	}
 
 
 	fepriv->thread_pid = 0;
 	fepriv->thread_pid = 0;
@@ -724,7 +736,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 	switch (cmd) {
 	switch (cmd) {
 	case FE_GET_INFO: {
 	case FE_GET_INFO: {
 		struct dvb_frontend_info* info = parg;
 		struct dvb_frontend_info* info = parg;
-		memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info));
+		memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
 
 
 		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
 		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
 		 * do it, it is done for it. */
 		 * do it, it is done for it. */
@@ -744,58 +756,58 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 			break;
 			break;
 		}
 		}
 
 
-		if (fe->ops->read_status)
-			err = fe->ops->read_status(fe, status);
+		if (fe->ops.read_status)
+			err = fe->ops.read_status(fe, status);
 		break;
 		break;
 	}
 	}
 	case FE_READ_BER:
 	case FE_READ_BER:
-		if (fe->ops->read_ber)
-			err = fe->ops->read_ber(fe, (__u32*) parg);
+		if (fe->ops.read_ber)
+			err = fe->ops.read_ber(fe, (__u32*) parg);
 		break;
 		break;
 
 
 	case FE_READ_SIGNAL_STRENGTH:
 	case FE_READ_SIGNAL_STRENGTH:
-		if (fe->ops->read_signal_strength)
-			err = fe->ops->read_signal_strength(fe, (__u16*) parg);
+		if (fe->ops.read_signal_strength)
+			err = fe->ops.read_signal_strength(fe, (__u16*) parg);
 		break;
 		break;
 
 
 	case FE_READ_SNR:
 	case FE_READ_SNR:
-		if (fe->ops->read_snr)
-			err = fe->ops->read_snr(fe, (__u16*) parg);
+		if (fe->ops.read_snr)
+			err = fe->ops.read_snr(fe, (__u16*) parg);
 		break;
 		break;
 
 
 	case FE_READ_UNCORRECTED_BLOCKS:
 	case FE_READ_UNCORRECTED_BLOCKS:
-		if (fe->ops->read_ucblocks)
-			err = fe->ops->read_ucblocks(fe, (__u32*) parg);
+		if (fe->ops.read_ucblocks)
+			err = fe->ops.read_ucblocks(fe, (__u32*) parg);
 		break;
 		break;
 
 
 
 
 	case FE_DISEQC_RESET_OVERLOAD:
 	case FE_DISEQC_RESET_OVERLOAD:
-		if (fe->ops->diseqc_reset_overload) {
-			err = fe->ops->diseqc_reset_overload(fe);
+		if (fe->ops.diseqc_reset_overload) {
+			err = fe->ops.diseqc_reset_overload(fe);
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
 			fepriv->status = 0;
 		}
 		}
 		break;
 		break;
 
 
 	case FE_DISEQC_SEND_MASTER_CMD:
 	case FE_DISEQC_SEND_MASTER_CMD:
-		if (fe->ops->diseqc_send_master_cmd) {
-			err = fe->ops->diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
+		if (fe->ops.diseqc_send_master_cmd) {
+			err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
 			fepriv->status = 0;
 		}
 		}
 		break;
 		break;
 
 
 	case FE_DISEQC_SEND_BURST:
 	case FE_DISEQC_SEND_BURST:
-		if (fe->ops->diseqc_send_burst) {
-			err = fe->ops->diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
+		if (fe->ops.diseqc_send_burst) {
+			err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
 			fepriv->status = 0;
 		}
 		}
 		break;
 		break;
 
 
 	case FE_SET_TONE:
 	case FE_SET_TONE:
-		if (fe->ops->set_tone) {
-			err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
+		if (fe->ops.set_tone) {
+			err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg);
 			fepriv->tone = (fe_sec_tone_mode_t) parg;
 			fepriv->tone = (fe_sec_tone_mode_t) parg;
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
 			fepriv->status = 0;
@@ -803,8 +815,8 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 		break;
 		break;
 
 
 	case FE_SET_VOLTAGE:
 	case FE_SET_VOLTAGE:
-		if (fe->ops->set_voltage) {
-			err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg);
+		if (fe->ops.set_voltage) {
+			err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg);
 			fepriv->voltage = (fe_sec_voltage_t) parg;
 			fepriv->voltage = (fe_sec_voltage_t) parg;
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
 			fepriv->status = 0;
@@ -812,11 +824,11 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 		break;
 		break;
 
 
 	case FE_DISHNETWORK_SEND_LEGACY_CMD:
 	case FE_DISHNETWORK_SEND_LEGACY_CMD:
-		if (fe->ops->dishnetwork_send_legacy_command) {
-			err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg);
+		if (fe->ops.dishnetwork_send_legacy_command) {
+			err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg);
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
 			fepriv->status = 0;
-		} else if (fe->ops->set_voltage) {
+		} else if (fe->ops.set_voltage) {
 			/*
 			/*
 			 * NOTE: This is a fallback condition.  Some frontends
 			 * NOTE: This is a fallback condition.  Some frontends
 			 * (stv0299 for instance) take longer than 8msec to
 			 * (stv0299 for instance) take longer than 8msec to
@@ -846,7 +858,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 			/* before sending a command, initialize by sending
 			/* before sending a command, initialize by sending
 			 * a 32ms 18V to the switch
 			 * a 32ms 18V to the switch
 			 */
 			 */
-			fe->ops->set_voltage(fe, SEC_VOLTAGE_18);
+			fe->ops.set_voltage(fe, SEC_VOLTAGE_18);
 			dvb_frontend_sleep_until(&nexttime, 32000);
 			dvb_frontend_sleep_until(&nexttime, 32000);
 
 
 			for (i = 0; i < 9; i++) {
 			for (i = 0; i < 9; i++) {
@@ -854,7 +866,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 					do_gettimeofday(&tv[i + 1]);
 					do_gettimeofday(&tv[i + 1]);
 				if ((cmd & 0x01) != last) {
 				if ((cmd & 0x01) != last) {
 					/* set voltage to (last ? 13V : 18V) */
 					/* set voltage to (last ? 13V : 18V) */
-					fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
+					fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
 					last = (last) ? 0 : 1;
 					last = (last) ? 0 : 1;
 				}
 				}
 				cmd = cmd >> 1;
 				cmd = cmd >> 1;
@@ -874,13 +886,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 		break;
 		break;
 
 
 	case FE_DISEQC_RECV_SLAVE_REPLY:
 	case FE_DISEQC_RECV_SLAVE_REPLY:
-		if (fe->ops->diseqc_recv_slave_reply)
-			err = fe->ops->diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
+		if (fe->ops.diseqc_recv_slave_reply)
+			err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
 		break;
 		break;
 
 
 	case FE_ENABLE_HIGH_LNB_VOLTAGE:
 	case FE_ENABLE_HIGH_LNB_VOLTAGE:
-		if (fe->ops->enable_high_lnb_voltage)
-			err = fe->ops->enable_high_lnb_voltage(fe, (long) parg);
+		if (fe->ops.enable_high_lnb_voltage)
+			err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
 		break;
 		break;
 
 
 	case FE_SET_FRONTEND: {
 	case FE_SET_FRONTEND: {
@@ -898,7 +910,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 			fepriv->parameters.inversion = INVERSION_AUTO;
 			fepriv->parameters.inversion = INVERSION_AUTO;
 			fetunesettings.parameters.inversion = INVERSION_AUTO;
 			fetunesettings.parameters.inversion = INVERSION_AUTO;
 		}
 		}
-		if (fe->ops->info.type == FE_OFDM) {
+		if (fe->ops.info.type == FE_OFDM) {
 			/* without hierachical coding code_rate_LP is irrelevant,
 			/* without hierachical coding code_rate_LP is irrelevant,
 			 * so we tolerate the otherwise invalid FEC_NONE setting */
 			 * so we tolerate the otherwise invalid FEC_NONE setting */
 			if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
 			if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
@@ -907,13 +919,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 		}
 		}
 
 
 		/* get frontend-specific tuning settings */
 		/* get frontend-specific tuning settings */
-		if (fe->ops->get_tune_settings && (fe->ops->get_tune_settings(fe, &fetunesettings) == 0)) {
+		if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
 			fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
 			fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
 			fepriv->max_drift = fetunesettings.max_drift;
 			fepriv->max_drift = fetunesettings.max_drift;
 			fepriv->step_size = fetunesettings.step_size;
 			fepriv->step_size = fetunesettings.step_size;
 		} else {
 		} else {
 			/* default values */
 			/* default values */
-			switch(fe->ops->info.type) {
+			switch(fe->ops.info.type) {
 			case FE_QPSK:
 			case FE_QPSK:
 				fepriv->min_delay = HZ/20;
 				fepriv->min_delay = HZ/20;
 				fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
 				fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
@@ -928,11 +940,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 
 
 			case FE_OFDM:
 			case FE_OFDM:
 				fepriv->min_delay = HZ/20;
 				fepriv->min_delay = HZ/20;
-				fepriv->step_size = fe->ops->info.frequency_stepsize * 2;
-				fepriv->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1;
+				fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
+				fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
 				break;
 				break;
 			case FE_ATSC:
 			case FE_ATSC:
-				printk("dvb-core: FE_ATSC not handled yet.\n");
+				fepriv->min_delay = HZ/20;
+				fepriv->step_size = 0;
+				fepriv->max_drift = 0;
 				break;
 				break;
 			}
 			}
 		}
 		}
@@ -952,9 +966,9 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
 		break;
 		break;
 
 
 	case FE_GET_FRONTEND:
 	case FE_GET_FRONTEND:
-		if (fe->ops->get_frontend) {
+		if (fe->ops.get_frontend) {
 			memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
 			memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
-			err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
+			err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
 		}
 		}
 		break;
 		break;
 
 
@@ -1067,7 +1081,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
 
 
 	printk ("DVB: registering frontend %i (%s)...\n",
 	printk ("DVB: registering frontend %i (%s)...\n",
 		fe->dvb->num,
 		fe->dvb->num,
-		fe->ops->info.name);
+		fe->ops.info.name);
 
 
 	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
 	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
 			     fe, DVB_DEVICE_FRONTEND);
 			     fe, DVB_DEVICE_FRONTEND);
@@ -1085,10 +1099,15 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
 	mutex_lock(&frontend_mutex);
 	mutex_lock(&frontend_mutex);
 	dvb_unregister_device (fepriv->dvbdev);
 	dvb_unregister_device (fepriv->dvbdev);
 	dvb_frontend_stop (fe);
 	dvb_frontend_stop (fe);
-	if (fe->ops->release)
-		fe->ops->release(fe);
+	if (fe->ops.tuner_ops.release) {
+		fe->ops.tuner_ops.release(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+	if (fe->ops.release)
+		fe->ops.release(fe);
 	else
 	else
-		printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name);
+		printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name);
 	/* fe is invalid now */
 	/* fe is invalid now */
 	kfree(fepriv);
 	kfree(fepriv);
 	mutex_unlock(&frontend_mutex);
 	mutex_unlock(&frontend_mutex);

+ 44 - 1
drivers/media/dvb/dvb-core/dvb_frontend.h

@@ -49,6 +49,44 @@ struct dvb_frontend_tune_settings {
 
 
 struct dvb_frontend;
 struct dvb_frontend;
 
 
+struct dvb_tuner_info {
+	char name[128];
+
+	u32 frequency_min;
+	u32 frequency_max;
+	u32 frequency_step;
+
+	u32 bandwidth_min;
+	u32 bandwidth_max;
+	u32 bandwidth_step;
+};
+
+struct dvb_tuner_ops {
+
+	struct dvb_tuner_info info;
+
+	int (*release)(struct dvb_frontend *fe);
+	int (*init)(struct dvb_frontend *fe);
+	int (*sleep)(struct dvb_frontend *fe);
+
+	/** This is for simple PLLs - set all parameters in one go. */
+	int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+
+	/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
+	int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
+
+	int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
+	int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+
+#define TUNER_STATUS_LOCKED 1
+	int (*get_status)(struct dvb_frontend *fe, u32 *status);
+
+	/** These are provided seperately from set_params in order to facilitate silicon
+	 * tuners which require sophisticated tuning loops, controlling each parameter seperately. */
+	int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
+	int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+};
+
 struct dvb_frontend_ops {
 struct dvb_frontend_ops {
 
 
 	struct dvb_frontend_info info;
 	struct dvb_frontend_info info;
@@ -64,6 +102,8 @@ struct dvb_frontend_ops {
 		    unsigned int mode_flags,
 		    unsigned int mode_flags,
 		    int *delay,
 		    int *delay,
 		    fe_status_t *status);
 		    fe_status_t *status);
+	/* get frontend tuning algorithm from the module */
+	int (*get_frontend_algo)(struct dvb_frontend *fe);
 
 
 	/* these two are only used for the swzigzag code */
 	/* these two are only used for the swzigzag code */
 	int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 	int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
@@ -86,6 +126,8 @@ struct dvb_frontend_ops {
 	int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
 	int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
 	int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
 	int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
 	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
 	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
+
+	struct dvb_tuner_ops tuner_ops;
 };
 };
 
 
 #define MAX_EVENT 8
 #define MAX_EVENT 8
@@ -100,9 +142,10 @@ struct dvb_fe_events {
 };
 };
 
 
 struct dvb_frontend {
 struct dvb_frontend {
-	struct dvb_frontend_ops* ops;
+	struct dvb_frontend_ops ops;
 	struct dvb_adapter *dvb;
 	struct dvb_adapter *dvb;
 	void* demodulator_priv;
 	void* demodulator_priv;
+	void* tuner_priv;
 	void* frontend_priv;
 	void* frontend_priv;
 	void* misc_priv;
 	void* misc_priv;
 };
 };

+ 145 - 0
drivers/media/dvb/dvb-core/dvb_math.c

@@ -0,0 +1,145 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/bug.h>
+#include "dvb_math.h"
+
+static const unsigned short logtable[256] = {
+	0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
+	0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508,
+	0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6,
+	0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37,
+	0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f,
+	0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41,
+	0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1,
+	0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142,
+	0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68,
+	0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355,
+	0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c,
+	0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490,
+	0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3,
+	0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507,
+	0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe,
+	0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca,
+	0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c,
+	0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7,
+	0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c,
+	0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c,
+	0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a,
+	0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065,
+	0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730,
+	0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc,
+	0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469,
+	0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9,
+	0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c,
+	0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765,
+	0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
+	0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
+	0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
+	0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
+};
+
+unsigned int intlog2(u32 value)
+{
+	/**
+	 *	returns: log2(value) * 2^24
+	 *	wrong result if value = 0 (log2(0) is undefined)
+	 */
+	unsigned int msb;
+	unsigned int logentry;
+	unsigned int significand;
+	unsigned int interpolation;
+
+	if (unlikely(value == 0)) {
+		WARN_ON(1);
+		return 0;
+	}
+
+	/* first detect the msb (count begins at 0) */
+	msb = fls(value) - 1;
+
+	/**
+	 *	now we use a logtable after the following method:
+	 *
+	 *	log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24
+	 *	where x = msb and therefore 1 <= y < 2
+	 *	first y is determined by shifting the value left
+	 *	so that msb is bit 31
+	 *		0x00231f56 -> 0x8C7D5800
+	 *	the result is y * 2^31 -> "significand"
+	 *	then the highest 9 bits are used for a table lookup
+	 *	the highest bit is discarded because it's always set
+	 *	the highest nine bits in our example are 100011000
+	 *	so we would use the entry 0x18
+	 */
+	significand = value << (31 - msb);
+	logentry = (significand >> 23) & 0xff;
+
+	/**
+	 *	last step we do is interpolation because of the
+	 *	limitations of the log table the error is that part of
+	 *	the significand which isn't used for lookup then we
+	 *	compute the ratio between the error and the next table entry
+	 *	and interpolate it between the log table entry used and the
+	 *	next one the biggest error possible is 0x7fffff
+	 *	(in our example it's 0x7D5800)
+	 *	needed value for next table entry is 0x800000
+	 *	so the interpolation is
+	 *	(error / 0x800000) * (logtable_next - logtable_current)
+	 *	in the implementation the division is moved to the end for
+	 *	better accuracy there is also an overflow correction if
+	 *	logtable_next is 256
+	 */
+	interpolation = ((significand & 0x7fffff) *
+			((logtable[(logentry + 1) & 0xff] -
+			  logtable[logentry]) & 0xffff)) >> 15;
+
+	/* now we return the result */
+	return ((msb << 24) + (logtable[logentry] << 8) + interpolation);
+}
+EXPORT_SYMBOL(intlog2);
+
+unsigned int intlog10(u32 value)
+{
+	/**
+	 *	returns: log10(value) * 2^24
+	 *	wrong result if value = 0 (log10(0) is undefined)
+	 */
+	u64 log;
+
+	if (unlikely(value == 0)) {
+		WARN_ON(1);
+		return 0;
+	}
+
+	log = intlog2(value);
+
+	/**
+	 *	we use the following method:
+	 *	log10(x) = log2(x) * log10(2)
+	 */
+
+	return (log * 646456993) >> 31;
+}
+EXPORT_SYMBOL(intlog10);

+ 58 - 0
drivers/media/dvb/dvb-core/dvb_math.h

@@ -0,0 +1,58 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __DVB_MATH_H
+#define __DVB_MATH_H
+
+#include <linux/types.h>
+
+/**
+ * computes log2 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ *   intlog2(value) = intlog2(value * 2^x) - x * 2^24
+ *
+ * example: intlog2(8) will give 3 << 24 = 3 * 2^24
+ * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
+ * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
+ *
+ * @param value The value (must be != 0)
+ * @return log2(value) * 2^24
+ */
+extern unsigned int intlog2(u32 value);
+
+/**
+ * computes log10 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ *   intlog10(value) = intlog10(value * 10^x) - x * 2^24
+ *
+ * example: intlog10(1000) will give 3 << 24 = 3 * 2^24
+ *   due to the implementation intlog10(1000) might be not exactly 3 * 2^24
+ *
+ * look at intlog2 for similar examples
+ *
+ * @param value The value (must be != 0)
+ * @return log10(value) * 2^24
+ */
+extern unsigned int intlog10(u32 value);
+
+#endif

+ 154 - 76
drivers/media/dvb/dvb-core/dvb_net.c

@@ -12,7 +12,7 @@
  *                          Hilmar Linder <hlinder@cosy.sbg.ac.at>
  *                          Hilmar Linder <hlinder@cosy.sbg.ac.at>
  *                      and Wolfram Stering <wstering@cosy.sbg.ac.at>
  *                      and Wolfram Stering <wstering@cosy.sbg.ac.at>
  *
  *
- * ULE Decaps according to draft-ietf-ipdvb-ule-03.txt.
+ * ULE Decaps according to RFC 4326.
  *
  *
  * This program is free software; you can redistribute it and/or
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * modify it under the terms of the GNU General Public License
@@ -42,6 +42,9 @@
  *                     Bugfixes and robustness improvements.
  *                     Bugfixes and robustness improvements.
  *                     Filtering on dest MAC addresses, if present (D-Bit = 0)
  *                     Filtering on dest MAC addresses, if present (D-Bit = 0)
  *                     ULE_DEBUG compile-time option.
  *                     ULE_DEBUG compile-time option.
+ * Apr 2006: cp v3:    Bugfixes and compliency with RFC 4326 (ULE) by
+ *                       Christian Praehauser <cpraehaus@cosy.sbg.ac.at>,
+ *                       Paris Lodron University of Salzburg.
  */
  */
 
 
 /*
 /*
@@ -49,9 +52,6 @@
  *
  *
  * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero.
  * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero.
  *
  *
- * TS_FEED callback is called once for every single TS cell although it is
- * registered (in dvb_net_feed_start()) for 100 TS cells (used for dvb_net_ule()).
- *
  */
  */
 
 
 #include <linux/module.h>
 #include <linux/module.h>
@@ -89,6 +89,9 @@ static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
 
 
 #ifdef ULE_DEBUG
 #ifdef ULE_DEBUG
 
 
+#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
+#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5]
+
 #define isprint(c)	((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
 #define isprint(c)	((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
 
 
 static void hexdump( const unsigned char *buf, unsigned short len )
 static void hexdump( const unsigned char *buf, unsigned short len )
@@ -214,6 +217,8 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
 #define ULE_TEST	0
 #define ULE_TEST	0
 #define ULE_BRIDGED	1
 #define ULE_BRIDGED	1
 
 
+#define ULE_OPTEXTHDR_PADDING 0
+
 static int ule_test_sndu( struct dvb_net_priv *p )
 static int ule_test_sndu( struct dvb_net_priv *p )
 {
 {
 	return -1;
 	return -1;
@@ -221,14 +226,28 @@ static int ule_test_sndu( struct dvb_net_priv *p )
 
 
 static int ule_bridged_sndu( struct dvb_net_priv *p )
 static int ule_bridged_sndu( struct dvb_net_priv *p )
 {
 {
-	/* BRIDGE SNDU handling sucks in draft-ietf-ipdvb-ule-03.txt.
-	 * This has to be the last extension header, otherwise it won't work.
-	 * Blame the authors!
+	struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr;
+	if(ntohs(hdr->h_proto) < 1536) {
+		int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data);
+		/* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */
+		if(framelen != ntohs(hdr->h_proto)) {
+			return -1;
+		}
+	}
+	/* Note:
+	 * From RFC4326:
+	 *  "A bridged SNDU is a Mandatory Extension Header of Type 1.
+	 *   It must be the final (or only) extension header specified in the header chain of a SNDU."
+	 * The 'ule_bridged' flag will cause the extension header processing loop to terminate.
 	 */
 	 */
 	p->ule_bridged = 1;
 	p->ule_bridged = 1;
 	return 0;
 	return 0;
 }
 }
 
 
+static int ule_exthdr_padding(struct dvb_net_priv *p)
+{
+	return 0;
+}
 
 
 /** Handle ULE extension headers.
 /** Handle ULE extension headers.
  *  Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
  *  Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
@@ -242,7 +261,8 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
 		{ [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL,  };
 		{ [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL,  };
 
 
 	/* Table of optional extension header handlers.  The header type is the index. */
 	/* Table of optional extension header handlers.  The header type is the index. */
-	static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = { NULL, };
+	static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) =
+		{ [0] = ule_exthdr_padding, [1] = NULL, };
 
 
 	int ext_len = 0;
 	int ext_len = 0;
 	unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8;
 	unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8;
@@ -253,25 +273,31 @@ static int handle_one_ule_extension( struct dvb_net_priv *p )
 		/* Mandatory extension header */
 		/* Mandatory extension header */
 		if (ule_mandatory_ext_handlers[htype]) {
 		if (ule_mandatory_ext_handlers[htype]) {
 			ext_len = ule_mandatory_ext_handlers[htype]( p );
 			ext_len = ule_mandatory_ext_handlers[htype]( p );
-			p->ule_next_hdr += ext_len;
-			if (! p->ule_bridged) {
-				p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr );
-				p->ule_next_hdr += 2;
-			} else {
-				p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)) );
-				/* This assures the extension handling loop will terminate. */
+			if(ext_len >= 0) {
+				p->ule_next_hdr += ext_len;
+				if (!p->ule_bridged) {
+					p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr);
+					p->ule_next_hdr += 2;
+				} else {
+					p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
+					/* This assures the extension handling loop will terminate. */
+				}
 			}
 			}
+			// else: extension handler failed or SNDU should be discarded
 		} else
 		} else
 			ext_len = -1;	/* SNDU has to be discarded. */
 			ext_len = -1;	/* SNDU has to be discarded. */
 	} else {
 	} else {
 		/* Optional extension header.  Calculate the length. */
 		/* Optional extension header.  Calculate the length. */
-		ext_len = hlen << 2;
+		ext_len = hlen << 1;
 		/* Process the optional extension header according to its type. */
 		/* Process the optional extension header according to its type. */
 		if (ule_optional_ext_handlers[htype])
 		if (ule_optional_ext_handlers[htype])
 			(void)ule_optional_ext_handlers[htype]( p );
 			(void)ule_optional_ext_handlers[htype]( p );
 		p->ule_next_hdr += ext_len;
 		p->ule_next_hdr += ext_len;
-		p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr );
-		p->ule_next_hdr += 2;
+		p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) );
+		/*
+		 * note: the length of the next header type is included in the
+		 * length of THIS optional extension header
+		 */
 	}
 	}
 
 
 	return ext_len;
 	return ext_len;
@@ -284,8 +310,14 @@ static int handle_ule_extensions( struct dvb_net_priv *p )
 	p->ule_next_hdr = p->ule_skb->data;
 	p->ule_next_hdr = p->ule_skb->data;
 	do {
 	do {
 		l = handle_one_ule_extension( p );
 		l = handle_one_ule_extension( p );
-		if (l == -1) return -1;	/* Stop extension header processing and discard SNDU. */
+		if (l < 0)
+			return l;	/* Stop extension header processing and discard SNDU. */
 		total_ext_len += l;
 		total_ext_len += l;
+#ifdef ULE_DEBUG
+		dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, "
+			"l=%i, total_ext_len=%i\n", p->ule_next_hdr,
+			(int) p->ule_sndu_type, l, total_ext_len);
+#endif
 
 
 	} while (p->ule_sndu_type < 1536);
 	} while (p->ule_sndu_type < 1536);
 
 
@@ -355,8 +387,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 				if (priv->ule_skb) {
 				if (priv->ule_skb) {
 					dev_kfree_skb( priv->ule_skb );
 					dev_kfree_skb( priv->ule_skb );
 					/* Prepare for next SNDU. */
 					/* Prepare for next SNDU. */
-					((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-					((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
+					priv->stats.rx_errors++;
+					priv->stats.rx_frame_errors++;
 				}
 				}
 				reset_ule(priv);
 				reset_ule(priv);
 				priv->need_pusi = 1;
 				priv->need_pusi = 1;
@@ -396,27 +428,25 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 			}
 			}
 		}
 		}
 
 
-		/* Check continuity counter. */
 		if (new_ts) {
 		if (new_ts) {
+			/* Check continuity counter. */
 			if ((ts[3] & 0x0F) == priv->tscc)
 			if ((ts[3] & 0x0F) == priv->tscc)
 				priv->tscc = (priv->tscc + 1) & 0x0F;
 				priv->tscc = (priv->tscc + 1) & 0x0F;
 			else {
 			else {
 				/* TS discontinuity handling: */
 				/* TS discontinuity handling: */
 				printk(KERN_WARNING "%lu: TS discontinuity: got %#x, "
 				printk(KERN_WARNING "%lu: TS discontinuity: got %#x, "
-				       "exptected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
+				       "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
 				/* Drop partly decoded SNDU, reset state, resync on PUSI. */
 				/* Drop partly decoded SNDU, reset state, resync on PUSI. */
 				if (priv->ule_skb) {
 				if (priv->ule_skb) {
 					dev_kfree_skb( priv->ule_skb );
 					dev_kfree_skb( priv->ule_skb );
 					/* Prepare for next SNDU. */
 					/* Prepare for next SNDU. */
 					// reset_ule(priv);  moved to below.
 					// reset_ule(priv);  moved to below.
-					((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-					((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
+					priv->stats.rx_errors++;
+					priv->stats.rx_frame_errors++;
 				}
 				}
 				reset_ule(priv);
 				reset_ule(priv);
 				/* skip to next PUSI. */
 				/* skip to next PUSI. */
 				priv->need_pusi = 1;
 				priv->need_pusi = 1;
-				ts += TS_SZ;
-				priv->ts_count++;
 				continue;
 				continue;
 			}
 			}
 			/* If we still have an incomplete payload, but PUSI is
 			/* If we still have an incomplete payload, but PUSI is
@@ -425,7 +455,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 			 * cells (continuity counter wrap). */
 			 * cells (continuity counter wrap). */
 			if (ts[1] & TS_PUSI) {
 			if (ts[1] & TS_PUSI) {
 				if (! priv->need_pusi) {
 				if (! priv->need_pusi) {
-					if (*from_where > 181) {
+					if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) {
 						/* Pointer field is invalid.  Drop this TS cell and any started ULE SNDU. */
 						/* Pointer field is invalid.  Drop this TS cell and any started ULE SNDU. */
 						printk(KERN_WARNING "%lu: Invalid pointer "
 						printk(KERN_WARNING "%lu: Invalid pointer "
 						       "field: %u.\n", priv->ts_count, *from_where);
 						       "field: %u.\n", priv->ts_count, *from_where);
@@ -438,8 +468,6 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 						}
 						}
 						reset_ule(priv);
 						reset_ule(priv);
 						priv->need_pusi = 1;
 						priv->need_pusi = 1;
-						ts += TS_SZ;
-						priv->ts_count++;
 						continue;
 						continue;
 					}
 					}
 					/* Skip pointer field (we're processing a
 					/* Skip pointer field (we're processing a
@@ -452,8 +480,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 				if (priv->ule_sndu_remain > 183) {
 				if (priv->ule_sndu_remain > 183) {
 					/* Current SNDU lacks more data than there could be available in the
 					/* Current SNDU lacks more data than there could be available in the
 					 * current TS cell. */
 					 * current TS cell. */
-					((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-					((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++;
+					priv->stats.rx_errors++;
+					priv->stats.rx_length_errors++;
 					printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
 					printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
 					       "got PUSI (pf %d, ts_remain %d).  Flushing incomplete payload.\n",
 					       "got PUSI (pf %d, ts_remain %d).  Flushing incomplete payload.\n",
 					       priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
 					       priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
@@ -492,9 +520,11 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 				} else
 				} else
 					priv->ule_dbit = 0;
 					priv->ule_dbit = 0;
 
 
-				if (priv->ule_sndu_len > 32763) {
+				if (priv->ule_sndu_len < 5) {
 					printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
 					printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
 					       "Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
 					       "Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
+					priv->stats.rx_errors++;
+					priv->stats.rx_length_errors++;
 					priv->ule_sndu_len = 0;
 					priv->ule_sndu_len = 0;
 					priv->need_pusi = 1;
 					priv->need_pusi = 1;
 					new_ts = 1;
 					new_ts = 1;
@@ -608,58 +638,103 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 				ule_dump = 1;
 				ule_dump = 1;
 #endif
 #endif
 
 
-				((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-				((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++;
+				priv->stats.rx_errors++;
+				priv->stats.rx_crc_errors++;
 				dev_kfree_skb(priv->ule_skb);
 				dev_kfree_skb(priv->ule_skb);
 			} else {
 			} else {
 				/* CRC32 verified OK. */
 				/* CRC32 verified OK. */
+				u8 dest_addr[ETH_ALEN];
+				static const u8 bc_addr[ETH_ALEN] =
+					{ [ 0 ... ETH_ALEN-1] = 0xff };
+
+				/* CRC32 was OK. Remove it from skb. */
+				priv->ule_skb->tail -= 4;
+				priv->ule_skb->len -= 4;
+
+				if (!priv->ule_dbit) {
+					/*
+					 * The destination MAC address is the
+					 * next data in the skb.  It comes
+					 * before any extension headers.
+					 *
+					 * Check if the payload of this SNDU
+					 * should be passed up the stack.
+					 */
+					register int drop = 0;
+					if (priv->rx_mode != RX_MODE_PROMISC) {
+						if (priv->ule_skb->data[0] & 0x01) {
+							/* multicast or broadcast */
+							if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) {
+								/* multicast */
+								if (priv->rx_mode == RX_MODE_MULTI) {
+									int i;
+									for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++)
+										;
+									if (i == priv->multi_num)
+										drop = 1;
+								} else if (priv->rx_mode != RX_MODE_ALL_MULTI)
+									drop = 1; /* no broadcast; */
+								/* else: all multicast mode: accept all multicast packets */
+							}
+							/* else: broadcast */
+						}
+						else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN))
+							drop = 1;
+						/* else: destination address matches the MAC address of our receiver device */
+					}
+					/* else: promiscious mode; pass everything up the stack */
+
+					if (drop) {
+#ifdef ULE_DEBUG
+						dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n",
+							MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr));
+#endif
+						dev_kfree_skb(priv->ule_skb);
+						goto sndu_done;
+					}
+					else
+					{
+						memcpy(dest_addr,  priv->ule_skb->data, ETH_ALEN);
+						skb_pull(priv->ule_skb, ETH_ALEN);
+					}
+				}
+
 				/* Handle ULE Extension Headers. */
 				/* Handle ULE Extension Headers. */
 				if (priv->ule_sndu_type < 1536) {
 				if (priv->ule_sndu_type < 1536) {
 					/* There is an extension header.  Handle it accordingly. */
 					/* There is an extension header.  Handle it accordingly. */
-					int l = handle_ule_extensions( priv );
+					int l = handle_ule_extensions(priv);
 					if (l < 0) {
 					if (l < 0) {
 						/* Mandatory extension header unknown or TEST SNDU.  Drop it. */
 						/* Mandatory extension header unknown or TEST SNDU.  Drop it. */
 						// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
 						// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
-						dev_kfree_skb( priv->ule_skb );
+						dev_kfree_skb(priv->ule_skb);
 						goto sndu_done;
 						goto sndu_done;
 					}
 					}
-					skb_pull( priv->ule_skb, l );
+					skb_pull(priv->ule_skb, l);
 				}
 				}
 
 
-				/* CRC32 was OK. Remove it from skb. */
-				priv->ule_skb->tail -= 4;
-				priv->ule_skb->len -= 4;
-
-				/* Filter on receiver's destination MAC address, if present. */
-				if (!priv->ule_dbit) {
-					/* The destination MAC address is the next data in the skb. */
-					if (memcmp( priv->ule_skb->data, dev->dev_addr, ETH_ALEN )) {
-						/* MAC addresses don't match.  Drop SNDU. */
-						// printk( KERN_WARNING "Dropping SNDU, MAC address.\n" );
-						dev_kfree_skb( priv->ule_skb );
-						goto sndu_done;
-					}
-					if (! priv->ule_bridged) {
-						skb_push( priv->ule_skb, ETH_ALEN + 2 );
-						ethh = (struct ethhdr *)priv->ule_skb->data;
-						memcpy( ethh->h_dest, ethh->h_source, ETH_ALEN );
-						memset( ethh->h_source, 0, ETH_ALEN );
-						ethh->h_proto = htons( priv->ule_sndu_type );
-					} else {
-						/* Skip the Receiver destination MAC address. */
-						skb_pull( priv->ule_skb, ETH_ALEN );
-					}
-				} else {
-					if (! priv->ule_bridged) {
-						skb_push( priv->ule_skb, ETH_HLEN );
-						ethh = (struct ethhdr *)priv->ule_skb->data;
-						memcpy( ethh->h_dest, dev->dev_addr, ETH_ALEN );
-						memset( ethh->h_source, 0, ETH_ALEN );
-						ethh->h_proto = htons( priv->ule_sndu_type );
-					} else {
-						/* skb is in correct state; nothing to do. */
+				/*
+				 * Construct/assure correct ethernet header.
+				 * Note: in bridged mode (priv->ule_bridged !=
+				 * 0) we already have the (original) ethernet
+				 * header at the start of the payload (after
+				 * optional dest. address and any extension
+				 * headers).
+				 */
+
+				if (!priv->ule_bridged) {
+					skb_push(priv->ule_skb, ETH_HLEN);
+					ethh = (struct ethhdr *)priv->ule_skb->data;
+					if (!priv->ule_dbit) {
+						 /* dest_addr buffer is only valid if priv->ule_dbit == 0 */
+						memcpy(ethh->h_dest, dest_addr, ETH_ALEN);
+						memset(ethh->h_source, 0, ETH_ALEN);
 					}
 					}
+					else /* zeroize source and dest */
+						memset( ethh, 0, ETH_ALEN*2 );
+
+					ethh->h_proto = htons(priv->ule_sndu_type);
 				}
 				}
+				/* else:  skb is in correct state; nothing to do. */
 				priv->ule_bridged = 0;
 				priv->ule_bridged = 0;
 
 
 				/* Stuff into kernel's protocol stack. */
 				/* Stuff into kernel's protocol stack. */
@@ -668,8 +743,8 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
 				 * receive the packet anyhow. */
 				 * receive the packet anyhow. */
 				/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
 				/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
 					priv->ule_skb->pkt_type = PACKET_HOST; */
 					priv->ule_skb->pkt_type = PACKET_HOST; */
-				((struct dvb_net_priv *) dev->priv)->stats.rx_packets++;
-				((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len;
+				priv->stats.rx_packets++;
+				priv->stats.rx_bytes += priv->ule_skb->len;
 				netif_rx(priv->ule_skb);
 				netif_rx(priv->ule_skb);
 			}
 			}
 			sndu_done:
 			sndu_done:
@@ -944,7 +1019,7 @@ static int dvb_net_feed_start(struct net_device *dev)
 		dprintk("%s: start filtering\n", __FUNCTION__);
 		dprintk("%s: start filtering\n", __FUNCTION__);
 		priv->secfeed->start_filtering(priv->secfeed);
 		priv->secfeed->start_filtering(priv->secfeed);
 	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
 	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
-		struct timespec timeout = { 0, 30000000 }; // 30 msec
+		struct timespec timeout = { 0, 10000000 }; // 10 msec
 
 
 		/* we have payloads encapsulated in TS */
 		/* we have payloads encapsulated in TS */
 		dprintk("%s: alloc tsfeed\n", __FUNCTION__);
 		dprintk("%s: alloc tsfeed\n", __FUNCTION__);
@@ -956,10 +1031,13 @@ static int dvb_net_feed_start(struct net_device *dev)
 
 
 		/* Set netdevice pointer for ts decaps callback. */
 		/* Set netdevice pointer for ts decaps callback. */
 		priv->tsfeed->priv = (void *)dev;
 		priv->tsfeed->priv = (void *)dev;
-		ret = priv->tsfeed->set(priv->tsfeed, priv->pid,
-					TS_PACKET, DMX_TS_PES_OTHER,
+		ret = priv->tsfeed->set(priv->tsfeed,
+					priv->pid, /* pid */
+					TS_PACKET, /* type */
+					DMX_TS_PES_OTHER, /* pes type */
 					32768,     /* circular buffer size */
 					32768,     /* circular buffer size */
-					timeout);
+					timeout    /* timeout */
+					);
 
 
 		if (ret < 0) {
 		if (ret < 0) {
 			printk("%s: could not set ts feed\n", dev->name);
 			printk("%s: could not set ts feed\n", dev->name);

+ 3 - 2
drivers/media/dvb/dvb-core/dvbdev.c

@@ -236,7 +236,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 			"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
 			"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
 
 
 	class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
 	class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
-			    NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
+			    adap->device, "dvb%d.%s%d", adap->num, dnames[type], id);
 
 
 	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
 	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
 		adap->num, dnames[type], id, nums2minor(adap->num, type, id),
 		adap->num, dnames[type], id, nums2minor(adap->num, type, id),
@@ -285,7 +285,7 @@ skip:
 }
 }
 
 
 
 
-int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module)
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
 {
 {
 	int num;
 	int num;
 
 
@@ -306,6 +306,7 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu
 	adap->num = num;
 	adap->num = num;
 	adap->name = name;
 	adap->name = name;
 	adap->module = module;
 	adap->module = module;
+	adap->device = device;
 
 
 	list_add_tail (&adap->list_head, &dvb_adapter_list);
 	list_add_tail (&adap->list_head, &dvb_adapter_list);
 
 

+ 3 - 1
drivers/media/dvb/dvb-core/dvbdev.h

@@ -51,6 +51,8 @@ struct dvb_adapter {
 	u8 proposed_mac [6];
 	u8 proposed_mac [6];
 	void* priv;
 	void* priv;
 
 
+	struct device *device;
+
 	struct module *module;
 	struct module *module;
 };
 };
 
 
@@ -76,7 +78,7 @@ struct dvb_device {
 };
 };
 
 
 
 
-extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module);
+extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device);
 extern int dvb_unregister_adapter (struct dvb_adapter *adap);
 extern int dvb_unregister_adapter (struct dvb_adapter *adap);
 
 
 extern int dvb_register_device (struct dvb_adapter *adap,
 extern int dvb_register_device (struct dvb_adapter *adap,

+ 10 - 0
drivers/media/dvb/dvb-usb/Kconfig

@@ -88,6 +88,7 @@ config DVB_USB_CXUSB
 	select DVB_CX22702
 	select DVB_CX22702
 	select DVB_LGDT330X
 	select DVB_LGDT330X
 	select DVB_MT352
 	select DVB_MT352
+	select DVB_ZL10353
 	help
 	help
 	  Say Y here to support the Conexant USB2.0 hybrid reference design.
 	  Say Y here to support the Conexant USB2.0 hybrid reference design.
 	  Currently, only DVB and ATSC modes are supported, analog mode
 	  Currently, only DVB and ATSC modes are supported, analog mode
@@ -130,6 +131,15 @@ config DVB_USB_VP702X
 
 
 	  DVB-S USB2.0 receivers.
 	  DVB-S USB2.0 receivers.
 
 
+config DVB_USB_GP8PSK
+	tristate "GENPIX 8PSK->USB module support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the
+	    GENPIX 8psk module
+
+	  DVB-S USB2.0 receivers.
+
 config DVB_USB_NOVA_T_USB2
 config DVB_USB_NOVA_T_USB2
 	tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
 	tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
 	depends on DVB_USB
 	depends on DVB_USB

+ 3 - 0
drivers/media/dvb/dvb-usb/Makefile

@@ -7,6 +7,9 @@ obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
 dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
 dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
 obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
 obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
 
 
+dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o
+obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o
+
 dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
 dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
 obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
 obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
 
 

+ 29 - 19
drivers/media/dvb/dvb-usb/cxusb.c

@@ -27,8 +27,10 @@
 
 
 #include "cx22702.h"
 #include "cx22702.h"
 #include "lgdt330x.h"
 #include "lgdt330x.h"
+#include "lg_h06xf.h"
 #include "mt352.h"
 #include "mt352.h"
 #include "mt352_priv.h"
 #include "mt352_priv.h"
+#include "zl10353.h"
 
 
 /* debug */
 /* debug */
 int dvb_usb_cxusb_debug;
 int dvb_usb_cxusb_debug;
@@ -322,32 +324,37 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
 	return 0;
 	return 0;
 }
 }
 
 
+static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe,
+					  struct dvb_frontend_parameters *fep)
+{
+	struct dvb_usb_device *d = fe->dvb->priv;
+	return lg_h06xf_pll_set(fe, &d->i2c_adap, fep);
+}
+
 static struct cx22702_config cxusb_cx22702_config = {
 static struct cx22702_config cxusb_cx22702_config = {
 	.demod_address = 0x63,
 	.demod_address = 0x63,
 
 
 	.output_mode = CX22702_PARALLEL_OUTPUT,
 	.output_mode = CX22702_PARALLEL_OUTPUT,
-
-	.pll_init = dvb_usb_pll_init_i2c,
-	.pll_set  = dvb_usb_pll_set_i2c,
 };
 };
 
 
 static struct lgdt330x_config cxusb_lgdt3303_config = {
 static struct lgdt330x_config cxusb_lgdt3303_config = {
 	.demod_address = 0x0e,
 	.demod_address = 0x0e,
 	.demod_chip    = LGDT3303,
 	.demod_chip    = LGDT3303,
-	.pll_set       = dvb_usb_pll_set_i2c,
 };
 };
 
 
 static struct mt352_config cxusb_dee1601_config = {
 static struct mt352_config cxusb_dee1601_config = {
 	.demod_address = 0x0f,
 	.demod_address = 0x0f,
 	.demod_init    = cxusb_dee1601_demod_init,
 	.demod_init    = cxusb_dee1601_demod_init,
-	.pll_set       = dvb_usb_pll_set,
 };
 };
 
 
-struct mt352_config cxusb_mt352_config = {
+static struct zl10353_config cxusb_zl10353_dee1601_config = {
+	.demod_address = 0x0f,
+};
+
+static struct mt352_config cxusb_mt352_config = {
 	/* used in both lgz201 and th7579 */
 	/* used in both lgz201 and th7579 */
 	.demod_address = 0x0f,
 	.demod_address = 0x0f,
 	.demod_init    = cxusb_mt352_demod_init,
 	.demod_init    = cxusb_mt352_demod_init,
-	.pll_set       = dvb_usb_pll_set,
 };
 };
 
 
 /* Callbacks for DVB USB */
 /* Callbacks for DVB USB */
@@ -357,17 +364,10 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d)
 	d->pll_addr = 0x61;
 	d->pll_addr = 0x61;
 	memcpy(d->pll_init, bpll, 4);
 	memcpy(d->pll_init, bpll, 4);
 	d->pll_desc = &dvb_pll_fmd1216me;
 	d->pll_desc = &dvb_pll_fmd1216me;
-	return 0;
-}
 
 
-static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d)
-{
-	u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 };
-	/* bpll[2] : unset bit 3, set bits 4&5
-	   bpll[3] : 0x50 - digital, 0x20 - analog */
-	d->pll_addr = 0x61;
-	memcpy(d->pll_init, bpll, 4);
-	d->pll_desc = &dvb_pll_tdvs_tua6034;
+	d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+	d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -375,6 +375,7 @@ static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d)
 {
 {
 	d->pll_addr = 0x61;
 	d->pll_addr = 0x61;
 	d->pll_desc = &dvb_pll_thomson_dtt7579;
 	d->pll_desc = &dvb_pll_thomson_dtt7579;
+	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -382,6 +383,7 @@ static int cxusb_lgz201_tuner_attach(struct dvb_usb_device *d)
 {
 {
 	d->pll_addr = 0x61;
 	d->pll_addr = 0x61;
 	d->pll_desc = &dvb_pll_lg_z201;
 	d->pll_desc = &dvb_pll_lg_z201;
+	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -389,6 +391,13 @@ static int cxusb_dtt7579_tuner_attach(struct dvb_usb_device *d)
 {
 {
 	d->pll_addr = 0x60;
 	d->pll_addr = 0x60;
 	d->pll_desc = &dvb_pll_thomson_dtt7579;
 	d->pll_desc = &dvb_pll_thomson_dtt7579;
+	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+	return 0;
+}
+
+static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_device *d)
+{
+	d->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -439,7 +448,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
 
 
 	cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
 	cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
 
 
-	if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL)
+	if (((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
+	    ((d->fe = zl10353_attach(&cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
 		return 0;
 		return 0;
 
 
 	return -EIO;
 	return -EIO;
@@ -555,7 +565,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
 	.streaming_ctrl   = cxusb_streaming_ctrl,
 	.streaming_ctrl   = cxusb_streaming_ctrl,
 	.power_ctrl       = cxusb_bluebird_power_ctrl,
 	.power_ctrl       = cxusb_bluebird_power_ctrl,
 	.frontend_attach  = cxusb_lgdt3303_frontend_attach,
 	.frontend_attach  = cxusb_lgdt3303_frontend_attach,
-	.tuner_attach     = cxusb_lgh064f_tuner_attach,
+	.tuner_attach     = cxusb_lgdt3303_tuner_attach,
 
 
 	.i2c_algo         = &cxusb_i2c_algo,
 	.i2c_algo         = &cxusb_i2c_algo,
 
 

+ 6 - 3
drivers/media/dvb/dvb-usb/dibusb-common.c

@@ -173,11 +173,10 @@ int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
 	struct dib3000_config demod_cfg;
 	struct dib3000_config demod_cfg;
 	struct dibusb_state *st = d->priv;
 	struct dibusb_state *st = d->priv;
 
 
-	demod_cfg.pll_set = dvb_usb_pll_set_i2c;
-	demod_cfg.pll_init = dvb_usb_pll_init_i2c;
-
 	for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
 	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) {
 		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;
 			d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
 			return 0;
 			return 0;
 		}
 		}
@@ -190,6 +189,10 @@ int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
 {
 {
 	d->pll_addr = 0x60;
 	d->pll_addr = 0x60;
 	d->pll_desc = &dvb_pll_env57h1xd5;
 	d->pll_desc = &dvb_pll_env57h1xd5;
+
+	d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+	d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
 EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);

+ 4 - 3
drivers/media/dvb/dvb-usb/dibusb-mb.c

@@ -20,11 +20,12 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
 	struct dibusb_state *st = d->priv;
 	struct dibusb_state *st = d->priv;
 
 
 	demod_cfg.demod_address = 0x8;
 	demod_cfg.demod_address = 0x8;
-	demod_cfg.pll_set = dvb_usb_pll_set_i2c;
-	demod_cfg.pll_init = dvb_usb_pll_init_i2c;
 
 
-	if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
+	if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
+		d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+		d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
 		return -ENODEV;
 		return -ENODEV;
+	}
 
 
 	d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
 	d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
 
 

+ 9 - 6
drivers/media/dvb/dvb-usb/digitv.c

@@ -112,27 +112,30 @@ static int digitv_mt352_demod_init(struct dvb_frontend *fe)
 
 
 static struct mt352_config digitv_mt352_config = {
 static struct mt352_config digitv_mt352_config = {
 	.demod_init = digitv_mt352_demod_init,
 	.demod_init = digitv_mt352_demod_init,
-	.pll_set = dvb_usb_pll_set,
 };
 };
 
 
-static int digitv_nxt6000_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
 {
 	struct dvb_usb_device *d = fe->dvb->priv;
 	struct dvb_usb_device *d = fe->dvb->priv;
 	u8 b[5];
 	u8 b[5];
-	dvb_usb_pll_set(fe,fep,b);
+	dvb_usb_tuner_calc_regs(fe,fep,b, 5);
 	return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0);
 	return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0);
 }
 }
 
 
 static struct nxt6000_config digitv_nxt6000_config = {
 static struct nxt6000_config digitv_nxt6000_config = {
 	.clock_inversion = 1,
 	.clock_inversion = 1,
-	.pll_set = digitv_nxt6000_pll_set,
 };
 };
 
 
 static int digitv_frontend_attach(struct dvb_usb_device *d)
 static int digitv_frontend_attach(struct dvb_usb_device *d)
 {
 {
-	if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL ||
-		(d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL)
+	if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL) {
+		d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 		return 0;
 		return 0;
+	}
+	if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
+		d->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
+		return 0;
+	}
 	return -EIO;
 	return -EIO;
 }
 }
 
 

+ 2 - 6
drivers/media/dvb/dvb-usb/dtt200u-fe.c

@@ -18,7 +18,6 @@ struct dtt200u_fe_state {
 
 
 	struct dvb_frontend_parameters fep;
 	struct dvb_frontend_parameters fep;
 	struct dvb_frontend frontend;
 	struct dvb_frontend frontend;
-	struct dvb_frontend_ops ops;
 };
 };
 
 
 static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
 static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
@@ -163,16 +162,13 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
 	deb_info("attaching frontend dtt200u\n");
 	deb_info("attaching frontend dtt200u\n");
 
 
 	state->d = d;
 	state->d = d;
-	memcpy(&state->ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
 
 
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 
 
-	goto success;
+	return &state->frontend;
 error:
 error:
 	return NULL;
 	return NULL;
-success:
-	return &state->frontend;
 }
 }
 
 
 static struct dvb_frontend_ops dtt200u_fe_ops = {
 static struct dvb_frontend_ops dtt200u_fe_ops = {

+ 8 - 9
drivers/media/dvb/dvb-usb/dvb-usb-dvb.c

@@ -82,7 +82,7 @@ int dvb_usb_dvb_init(struct dvb_usb_device *d)
 	int ret;
 	int ret;
 
 
 	if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
 	if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
-			d->owner)) < 0) {
+			d->owner, &d->udev->dev)) < 0) {
 		deb_info("dvb_register_adapter failed: error %d", ret);
 		deb_info("dvb_register_adapter failed: error %d", ret);
 		goto err;
 		goto err;
 	}
 	}
@@ -121,16 +121,15 @@ int dvb_usb_dvb_init(struct dvb_usb_device *d)
 
 
 	dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
 	dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
 
 
-	goto success;
+	d->state |= DVB_USB_STATE_DVB;
+	return 0;
+
 err_dmx_dev:
 err_dmx_dev:
 	dvb_dmx_release(&d->demux);
 	dvb_dmx_release(&d->demux);
 err_dmx:
 err_dmx:
 	dvb_unregister_adapter(&d->dvb_adap);
 	dvb_unregister_adapter(&d->dvb_adap);
 err:
 err:
 	return ret;
 	return ret;
-success:
-	d->state |= DVB_USB_STATE_DVB;
-	return 0;
 }
 }
 
 
 int dvb_usb_dvb_exit(struct dvb_usb_device *d)
 int dvb_usb_dvb_exit(struct dvb_usb_device *d)
@@ -184,13 +183,13 @@ int dvb_usb_fe_init(struct dvb_usb_device* d)
 
 
 	/* re-assign sleep and wakeup functions */
 	/* re-assign sleep and wakeup functions */
 	if (d->fe != NULL) {
 	if (d->fe != NULL) {
-		d->fe_init = d->fe->ops->init;   d->fe->ops->init  = dvb_usb_fe_wakeup;
-		d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep;
+		d->fe_init = d->fe->ops.init;   d->fe->ops.init  = dvb_usb_fe_wakeup;
+		d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep;
 
 
 		if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
 		if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
 			err("Frontend registration failed.");
 			err("Frontend registration failed.");
-			if (d->fe->ops->release)
-				d->fe->ops->release(d->fe);
+			if (d->fe->ops.release)
+				d->fe->ops.release(d->fe);
 			d->fe = NULL;
 			d->fe = NULL;
 			return -ENODEV;
 			return -ENODEV;
 		}
 		}

+ 15 - 9
drivers/media/dvb/dvb-usb/dvb-usb-i2c.c

@@ -46,7 +46,7 @@ int dvb_usb_i2c_exit(struct dvb_usb_device *d)
 	return 0;
 	return 0;
 }
 }
 
 
-int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
+int dvb_usb_tuner_init_i2c(struct dvb_frontend *fe)
 {
 {
 	struct dvb_usb_device *d = fe->dvb->priv;
 	struct dvb_usb_device *d = fe->dvb->priv;
 	struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
 	struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
@@ -63,6 +63,8 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
 	deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1],
 	deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1],
 			d->pll_init[2],d->pll_init[3]);
 			d->pll_init[2],d->pll_init[3]);
 
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
 	if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
 		err("tuner i2c write failed for pll_init.");
 		err("tuner i2c write failed for pll_init.");
 		ret = -EREMOTEIO;
 		ret = -EREMOTEIO;
@@ -73,38 +75,42 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
 		d->tuner_pass_ctrl(fe,0,d->pll_addr);
 		d->tuner_pass_ctrl(fe,0,d->pll_addr);
 	return ret;
 	return ret;
 }
 }
-EXPORT_SYMBOL(dvb_usb_pll_init_i2c);
+EXPORT_SYMBOL(dvb_usb_tuner_init_i2c);
 
 
-int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5])
+int dvb_usb_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 *b, int buf_len)
 {
 {
 	struct dvb_usb_device *d = fe->dvb->priv;
 	struct dvb_usb_device *d = fe->dvb->priv;
 
 
+	if (buf_len != 5)
+		return -EINVAL;
 	if (d->pll_desc == NULL)
 	if (d->pll_desc == NULL)
 		return 0;
 		return 0;
 
 
 	deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
 	deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
 
 
-	b[0] = d->pll_addr << 1;
+	b[0] = d->pll_addr;
 	dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth);
 	dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth);
 
 
 	deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
 	deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
 
 
-	return 0;
+	return 5;
 }
 }
-EXPORT_SYMBOL(dvb_usb_pll_set);
+EXPORT_SYMBOL(dvb_usb_tuner_calc_regs);
 
 
-int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
 {
 	struct dvb_usb_device *d = fe->dvb->priv;
 	struct dvb_usb_device *d = fe->dvb->priv;
 	int ret = 0;
 	int ret = 0;
 	u8 b[5];
 	u8 b[5];
 	struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
 	struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
 
 
-	dvb_usb_pll_set(fe,fep,b);
+	dvb_usb_tuner_calc_regs(fe,fep,b,5);
 
 
 	if (d->tuner_pass_ctrl)
 	if (d->tuner_pass_ctrl)
 		d->tuner_pass_ctrl(fe,1,d->pll_addr);
 		d->tuner_pass_ctrl(fe,1,d->pll_addr);
 
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
 	if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
 		err("tuner i2c write failed for pll_set.");
 		err("tuner i2c write failed for pll_set.");
 		ret = -EREMOTEIO;
 		ret = -EREMOTEIO;
@@ -116,4 +122,4 @@ int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters
 
 
 	return ret;
 	return ret;
 }
 }
-EXPORT_SYMBOL(dvb_usb_pll_set_i2c);
+EXPORT_SYMBOL(dvb_usb_tuner_set_params_i2c);

+ 3 - 1
drivers/media/dvb/dvb-usb/dvb-usb-ids.h

@@ -31,6 +31,7 @@
 #define USB_VID_VISIONPLUS					0x13d3
 #define USB_VID_VISIONPLUS					0x13d3
 #define USB_VID_TWINHAN						0x1822
 #define USB_VID_TWINHAN						0x1822
 #define USB_VID_ULTIMA_ELECTRONIC			0x05d8
 #define USB_VID_ULTIMA_ELECTRONIC			0x05d8
+#define USB_VID_GENPIX					0x09c0
 
 
 /* Product IDs */
 /* Product IDs */
 #define USB_PID_ADSTECH_USB2_COLD			0xa333
 #define USB_PID_ADSTECH_USB2_COLD			0xa333
@@ -104,5 +105,6 @@
 #define USB_PID_KYE_DVB_T_WARM				0x701f
 #define USB_PID_KYE_DVB_T_WARM				0x701f
 #define USB_PID_PCTV_200E					0x020e
 #define USB_PID_PCTV_200E					0x020e
 #define USB_PID_PCTV_400E					0x020f
 #define USB_PID_PCTV_400E					0x020f
-
+#define USB_PID_GENPIX_8PSK_COLD				0x0200
+#define USB_PID_GENPIX_8PSK_WARM				0x0201
 #endif
 #endif

+ 3 - 3
drivers/media/dvb/dvb-usb/dvb-usb.h

@@ -330,9 +330,9 @@ extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
 extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
 extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
 
 
 /* commonly used pll init and set functions */
 /* commonly used pll init and set functions */
-extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
-extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
-extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
+extern int dvb_usb_tuner_init_i2c(struct dvb_frontend *);
+extern int dvb_usb_tuner_calc_regs(struct dvb_frontend *, struct dvb_frontend_parameters *, u8 *buf, int buf_len);
+extern int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
 
 
 /* commonly used firmware download types and function */
 /* commonly used firmware download types and function */
 struct hexline {
 struct hexline {

+ 272 - 0
drivers/media/dvb/dvb-usb/gp8psk-fe.c

@@ -0,0 +1,272 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *	This program is free software; you can redistribute it and/or modify it
+ *	under the terms of the GNU General Public License as published by the Free
+ *	Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "gp8psk.h"
+
+struct gp8psk_fe_state {
+	struct dvb_frontend fe;
+
+	struct dvb_usb_device *d;
+
+	u16 snr;
+
+	unsigned long next_snr_check;
+};
+
+static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+{
+	struct gp8psk_fe_state *st = fe->demodulator_priv;
+	u8 lock;
+
+	if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1))
+		return -EINVAL;
+
+	if (lock)
+		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
+	else
+		*status = 0;
+
+	return 0;
+}
+
+/* not supported by this Frontend */
+static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+	(void) fe;
+	*ber = 0;
+	return 0;
+}
+
+/* not supported by this Frontend */
+static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+	(void) fe;
+	*unc = 0;
+	return 0;
+}
+
+static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+	struct gp8psk_fe_state *st = fe->demodulator_priv;
+	u8 buf[2];
+
+	if (time_after(jiffies,st->next_snr_check)) {
+		gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2);
+		*snr = (int)(buf[1]) << 8 | buf[0];
+		/* snr is reported in dBu*256 */
+		/* snr / 38.4 ~= 100% strength */
+		/* snr * 17 returns 100% strength as 65535 */
+		if (*snr <= 3855)
+			*snr = (*snr<<4) + *snr; // snr * 17
+		else
+			*snr = 65535;
+		st->next_snr_check = jiffies + (10*HZ)/1000;
+	} else {
+		*snr = st->snr;
+	}
+	return 0;
+}
+
+static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+	return gp8psk_fe_read_snr(fe, strength);
+}
+
+static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 800;
+	return 0;
+}
+
+static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
+				  struct dvb_frontend_parameters *fep)
+{
+	struct gp8psk_fe_state *state = fe->demodulator_priv;
+	u8 cmd[10];
+	u32 freq = fep->frequency * 1000;
+
+	cmd[4] = freq         & 0xff;
+	cmd[5] = (freq >> 8)  & 0xff;
+	cmd[6] = (freq >> 16) & 0xff;
+	cmd[7] = (freq >> 24) & 0xff;
+
+	switch(fe->ops.info.type) {
+	case FE_QPSK:
+		cmd[0] =  fep->u.qpsk.symbol_rate        & 0xff;
+		cmd[1] = (fep->u.qpsk.symbol_rate >>  8) & 0xff;
+		cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff;
+		cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff;
+		cmd[8] = ADV_MOD_DVB_QPSK;
+		cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/
+		break;
+	default:
+		// other modes are unsuported right now
+		cmd[0] = 0;
+		cmd[1] = 0;
+		cmd[2] = 0;
+		cmd[3] = 0;
+		cmd[8] = 0;
+		cmd[9] = 0;
+		break;
+	}
+
+	gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
+
+	state->next_snr_check = jiffies;
+
+	return 0;
+}
+
+static int gp8psk_fe_get_frontend(struct dvb_frontend* fe,
+				  struct dvb_frontend_parameters *fep)
+{
+	return 0;
+}
+
+
+static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
+				    struct dvb_diseqc_master_cmd *m)
+{
+	struct gp8psk_fe_state *st = fe->demodulator_priv;
+
+	deb_fe("%s\n",__FUNCTION__);
+
+	if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
+			m->msg, m->msg_len)) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
+				    fe_sec_mini_cmd_t burst)
+{
+	struct gp8psk_fe_state *st = fe->demodulator_priv;
+	u8 cmd;
+
+	deb_fe("%s\n",__FUNCTION__);
+
+	/* These commands are certainly wrong */
+	cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
+
+	if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0,
+			&cmd, 0)) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+	struct gp8psk_fe_state* state = fe->demodulator_priv;
+
+	if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE,
+		 (tone == SEC_TONE_ON), 0, NULL, 0)) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+	struct gp8psk_fe_state* state = fe->demodulator_priv;
+
+	if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE,
+			 voltage == SEC_VOLTAGE_18, 0, NULL, 0)) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
+{
+	struct gp8psk_fe_state* state = fe->demodulator_priv;
+	u8 cmd = sw_cmd & 0x7f;
+
+	if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0,
+			NULL, 0)) {
+		return -EINVAL;
+	}
+	if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
+			0, NULL, 0)) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void gp8psk_fe_release(struct dvb_frontend* fe)
+{
+	struct gp8psk_fe_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops gp8psk_fe_ops;
+
+struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d)
+{
+	struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
+	if (s == NULL)
+		goto error;
+
+	s->d = d;
+	memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
+	s->fe.demodulator_priv = s;
+
+	goto success;
+error:
+	return NULL;
+success:
+	return &s->fe;
+}
+
+
+static struct dvb_frontend_ops gp8psk_fe_ops = {
+	.info = {
+		.name			= "Genpix 8psk-USB DVB-S",
+		.type			= FE_QPSK,
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 100,
+		.symbol_rate_min        = 1000000,
+		.symbol_rate_max        = 45000000,
+		.symbol_rate_tolerance  = 500,  /* ppm */
+		.caps = FE_CAN_INVERSION_AUTO |
+				FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+				FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+				FE_CAN_QPSK
+	},
+
+	.release = gp8psk_fe_release,
+
+	.init = NULL,
+	.sleep = NULL,
+
+	.set_frontend = gp8psk_fe_set_frontend,
+	.get_frontend = gp8psk_fe_get_frontend,
+	.get_tune_settings = gp8psk_fe_get_tune_settings,
+
+	.read_status = gp8psk_fe_read_status,
+	.read_ber = gp8psk_fe_read_ber,
+	.read_signal_strength = gp8psk_fe_read_signal_strength,
+	.read_snr = gp8psk_fe_read_snr,
+	.read_ucblocks = gp8psk_fe_read_unc_blocks,
+
+	.diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg,
+	.diseqc_send_burst = gp8psk_fe_send_diseqc_burst,
+	.set_tone = gp8psk_fe_set_tone,
+	.set_voltage = gp8psk_fe_set_voltage,
+	.dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
+};

+ 256 - 0
drivers/media/dvb/dvb-usb/gp8psk.c

@@ -0,0 +1,256 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *	This program is free software; you can redistribute it and/or modify it
+ *	under the terms of the GNU General Public License as published by the Free
+ *	Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "gp8psk.h"
+
+/* debug */
+static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
+int dvb_usb_gp8psk_debug;
+module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+	int ret = 0,try = 0;
+
+	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+		return ret;
+
+	while (ret >= 0 && ret != blen && try < 3) {
+		ret = usb_control_msg(d->udev,
+			usb_rcvctrlpipe(d->udev,0),
+			req,
+			USB_TYPE_VENDOR | USB_DIR_IN,
+			value,index,b,blen,
+			2000);
+		deb_info("reading number %d (ret: %d)\n",try,ret);
+		try++;
+	}
+
+	if (ret < 0 || ret != blen) {
+		warn("usb in operation failed.");
+		ret = -EIO;
+	} else
+		ret = 0;
+
+	deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+	debug_dump(b,blen,deb_xfer);
+
+	mutex_unlock(&d->usb_mutex);
+
+	return ret;
+}
+
+int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+			     u16 index, u8 *b, int blen)
+{
+	int ret;
+
+	deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+	debug_dump(b,blen,deb_xfer);
+
+	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+		return ret;
+
+	if (usb_control_msg(d->udev,
+			usb_sndctrlpipe(d->udev,0),
+			req,
+			USB_TYPE_VENDOR | USB_DIR_OUT,
+			value,index,b,blen,
+			2000) != blen) {
+		warn("usb out operation failed.");
+		ret = -EIO;
+	} else
+		ret = 0;
+	mutex_unlock(&d->usb_mutex);
+
+	return ret;
+}
+
+static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
+{
+	int ret;
+	const struct firmware *fw = NULL;
+	u8 *ptr, *buf;
+	if ((ret = request_firmware(&fw, bcm4500_firmware,
+					&d->udev->dev)) != 0) {
+		err("did not find the bcm4500 firmware file. (%s) "
+			"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+			bcm4500_firmware,ret);
+		return ret;
+	}
+
+	ret = -EINVAL;
+
+	if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
+		goto out_rel_fw;
+
+	info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware);
+
+	ptr = fw->data;
+	buf = kmalloc(512, GFP_KERNEL | GFP_DMA);
+
+	while (ptr[0] != 0xff) {
+		u16 buflen = ptr[0] + 4;
+		if (ptr + buflen >= fw->data + fw->size) {
+			err("failed to load bcm4500 firmware.");
+			goto out_free;
+		}
+		memcpy(buf, ptr, buflen);
+		if (dvb_usb_generic_write(d, buf, buflen)) {
+			err("failed to load bcm4500 firmware.");
+			goto out_free;
+		}
+		ptr += buflen;
+	}
+
+	ret = 0;
+
+out_free:
+	kfree(buf);
+out_rel_fw:
+	release_firmware(fw);
+
+	return ret;
+}
+
+static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	u8 status, buf;
+	if (onoff) {
+		gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+		if (! (status & 0x01))  /* started */
+			if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
+				return -EINVAL;
+
+		if (! (status & 0x02)) /* BCM4500 firmware loaded */
+			if(gp8psk_load_bcm4500fw(d))
+				return EINVAL;
+
+		if (! (status & 0x04)) /* LNB Power */
+			if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
+					&buf, 1))
+				return EINVAL;
+
+		/* Set DVB mode */
+		if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
+			return -EINVAL;
+		gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+	} else {
+		/* Turn off LNB power */
+		if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
+			return EINVAL;
+		/* Turn off 8psk power */
+		if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
+			return -EINVAL;
+
+	}
+	return 0;
+}
+
+
+static int gp8psk_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	return gp8psk_usb_out_op(d, ARM_TRANSFER, onoff, 0 , NULL, 0);
+}
+
+static int gp8psk_frontend_attach(struct dvb_usb_device *d)
+{
+	d->fe = gp8psk_fe_attach(d);
+
+	return 0;
+}
+
+static struct dvb_usb_properties gp8psk_properties;
+
+static int gp8psk_usb_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
+}
+
+static struct usb_device_id gp8psk_usb_table [] = {
+	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) },
+	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) },
+	    { 0 },
+};
+MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
+
+static struct dvb_usb_properties gp8psk_properties = {
+	.caps = 0,
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-gp8psk-01.fw",
+
+	.streaming_ctrl   = gp8psk_streaming_ctrl,
+	.power_ctrl       = gp8psk_power_ctrl,
+	.frontend_attach  = gp8psk_frontend_attach,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x82,
+		.u = {
+			.bulk = {
+				.buffersize = 8192,
+			}
+		}
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{ .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver",
+		  .cold_ids = { &gp8psk_usb_table[0], NULL },
+		  .warm_ids = { &gp8psk_usb_table[1], NULL },
+		},
+		{ 0 },
+	}
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver gp8psk_usb_driver = {
+	.name		= "dvb_usb_gp8psk",
+	.probe		= gp8psk_usb_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= gp8psk_usb_table,
+};
+
+/* module stuff */
+static int __init gp8psk_usb_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&gp8psk_usb_driver))) {
+		err("usb_register failed. (%d)",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit gp8psk_usb_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&gp8psk_usb_driver);
+}
+
+module_init(gp8psk_usb_module_init);
+module_exit(gp8psk_usb_module_exit);
+
+MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
+MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");

+ 79 - 0
drivers/media/dvb/dvb-usb/gp8psk.h

@@ -0,0 +1,79 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *	This program is free software; you can redistribute it and/or modify it
+ *	under the terms of the GNU General Public License as published by the Free
+ *	Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_GP8PSK_H_
+#define _DVB_USB_GP8PSK_H_
+
+#define DVB_USB_LOG_PREFIX "gp8psk"
+#include "dvb-usb.h"
+
+extern int dvb_usb_gp8psk_debug;
+#define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args)
+#define deb_rc(args...)   dprintk(dvb_usb_gp8psk_debug,0x04,args)
+#define deb_fe(args...)   dprintk(dvb_usb_gp8psk_debug,0x08,args)
+/* gp8psk commands */
+
+/* Twinhan Vendor requests */
+#define TH_COMMAND_IN                     0xC0
+#define TH_COMMAND_OUT                    0xC1
+
+/* command bytes */
+#define GET_8PSK_CONFIG                 0x80
+#define SET_8PSK_CONFIG                 0x81
+#define ARM_TRANSFER                    0x85
+#define TUNE_8PSK                       0x86
+#define GET_SIGNAL_STRENGTH             0x87
+#define LOAD_BCM4500                    0x88
+#define BOOT_8PSK                       0x89
+#define START_INTERSIL                  0x8A
+#define SET_LNB_VOLTAGE                 0x8B
+#define SET_22KHZ_TONE                  0x8C
+#define SEND_DISEQC_COMMAND             0x8D
+#define SET_DVB_MODE                    0x8E
+#define SET_DN_SWITCH                   0x8F
+#define GET_SIGNAL_LOCK                 0x90
+
+/* Satellite modulation modes */
+#define ADV_MOD_DVB_QPSK 0     /* DVB-S QPSK */
+#define ADV_MOD_TURBO_QPSK 1   /* Turbo QPSK */
+#define ADV_MOD_TURBO_8PSK 2   /* Turbo 8PSK (also used for Trellis 8PSK) */
+#define ADV_MOD_TURBO_16QAM 3  /* Turbo 16QAM (also used for Trellis 8PSK) */
+
+#define ADV_MOD_DCII_C_QPSK 4  /* Digicipher II Combo */
+#define ADV_MOD_DCII_I_QPSK 5  /* Digicipher II I-stream */
+#define ADV_MOD_DCII_Q_QPSK 6  /* Digicipher II Q-stream */
+#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */
+#define ADV_MOD_DSS_QPSK 8     /* DSS (DIRECTV) QPSK */
+#define ADV_MOD_DVB_BPSK 9     /* DVB-S BPSK */
+
+#define GET_USB_SPEED                     0x07
+ #define USB_SPEED_LOW                    0
+ #define USB_SPEED_FULL                   1
+ #define USB_SPEED_HIGH                   2
+
+#define RESET_FX2                         0x13
+
+#define FW_VERSION_READ                   0x0B
+#define VENDOR_STRING_READ                0x0C
+#define PRODUCT_STRING_READ               0x0D
+#define FW_BCD_VERSION_READ               0x14
+
+extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
+extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+			     u16 index, u8 *b, int blen);
+
+#endif

+ 1 - 1
drivers/media/dvb/dvb-usb/umt-010.c

@@ -57,7 +57,6 @@ static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
 	memset(&umt_config,0,sizeof(struct mt352_config));
 	memset(&umt_config,0,sizeof(struct mt352_config));
 	umt_config.demod_init = umt_mt352_demod_init;
 	umt_config.demod_init = umt_mt352_demod_init;
 	umt_config.demod_address = 0xf;
 	umt_config.demod_address = 0xf;
-	umt_config.pll_set = dvb_usb_pll_set;
 
 
 	d->fe = mt352_attach(&umt_config, &d->i2c_adap);
 	d->fe = mt352_attach(&umt_config, &d->i2c_adap);
 
 
@@ -68,6 +67,7 @@ static int umt_tuner_attach (struct dvb_usb_device *d)
 {
 {
 	d->pll_addr = 0x61;
 	d->pll_addr = 0x61;
 	d->pll_desc = &dvb_pll_tua6034;
 	d->pll_desc = &dvb_pll_tua6034;
+	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 	return 0;
 	return 0;
 }
 }
 
 

+ 3 - 4
drivers/media/dvb/dvb-usb/vp702x-fe.c

@@ -287,17 +287,16 @@ struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
 		goto error;
 		goto error;
 
 
 	s->d = d;
 	s->d = d;
-	s->fe.ops = &vp702x_fe_ops;
+
+	memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops));
 	s->fe.demodulator_priv = s;
 	s->fe.demodulator_priv = s;
 
 
 	s->lnb_buf[1] = SET_LNB_POWER;
 	s->lnb_buf[1] = SET_LNB_POWER;
 	s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
 	s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
 
 
-	goto success;
+	return &s->fe;
 error:
 error:
 	return NULL;
 	return NULL;
-success:
-	return &s->fe;
 }
 }
 
 
 
 

+ 2 - 7
drivers/media/dvb/dvb-usb/vp7045-fe.c

@@ -23,8 +23,6 @@
 
 
 struct vp7045_fe_state {
 struct vp7045_fe_state {
 	struct dvb_frontend fe;
 	struct dvb_frontend fe;
-	struct dvb_frontend_ops ops;
-
 	struct dvb_usb_device *d;
 	struct dvb_usb_device *d;
 };
 };
 
 
@@ -151,15 +149,12 @@ struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
 		goto error;
 		goto error;
 
 
 	s->d = d;
 	s->d = d;
-	memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
-	s->fe.ops = &s->ops;
+	memcpy(&s->fe.ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
 	s->fe.demodulator_priv = s;
 	s->fe.demodulator_priv = s;
 
 
-	goto success;
+	return &s->fe;
 error:
 error:
 	return NULL;
 	return NULL;
-success:
-	return &s->fe;
 }
 }
 
 
 
 

+ 17 - 1
drivers/media/dvb/frontends/Kconfig

@@ -157,7 +157,7 @@ config DVB_STV0297
 	help
 	help
 	  A DVB-C tuner module. Say Y when you want to support this frontend.
 	  A DVB-C tuner module. Say Y when you want to support this frontend.
 
 
-comment "ATSC (North American/Korean Terresterial DTV) frontends"
+comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
 	depends on DVB_CORE
 	depends on DVB_CORE
 
 
 config DVB_NXT200X
 config DVB_NXT200X
@@ -216,4 +216,20 @@ config DVB_LGDT330X
 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
 	  to support this frontend.
 	  to support this frontend.
 
 
+
+comment "Miscellaneous devices"
+	depends on DVB_CORE
+
+config DVB_LNBP21
+	tristate "LNBP21 SEC controller"
+	depends on DVB_CORE
+	help
+	  An SEC control chip.
+
+config DVB_ISL6421
+	tristate "ISL6421 SEC controller"
+	depends on DVB_CORE
+	help
+	  An SEC control chip.
+
 endmenu
 endmenu

+ 2 - 0
drivers/media/dvb/frontends/Makefile

@@ -31,3 +31,5 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
 obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
 obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
 obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
+obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_ISL6421) += isl6421.o

+ 1 - 3
drivers/media/dvb/frontends/bcm3510.c

@@ -48,7 +48,6 @@
 struct bcm3510_state {
 struct bcm3510_state {
 
 
 	struct i2c_adapter* i2c;
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct bcm3510_config* config;
 	const struct bcm3510_config* config;
 	struct dvb_frontend frontend;
 	struct dvb_frontend frontend;
 
 
@@ -791,10 +790,9 @@ struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
 
 
 	state->config = config;
 	state->config = config;
 	state->i2c = i2c;
 	state->i2c = i2c;
-	memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
 
 
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 
 
 	mutex_init(&state->hab_mutex);
 	mutex_init(&state->hab_mutex);

+ 4 - 2
drivers/media/dvb/frontends/bsbe1.h

@@ -89,12 +89,13 @@ static int alps_bsbe1_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ra
 	return 0;
 	return 0;
 }
 }
 
 
-static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
+static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 {
 	int ret;
 	int ret;
 	u8 data[4];
 	u8 data[4];
 	u32 div;
 	u32 div;
 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+	struct i2c_adapter *i2c = fe->tuner_priv;
 
 
 	if ((params->frequency < 950000) || (params->frequency > 2150000))
 	if ((params->frequency < 950000) || (params->frequency > 2150000))
 		return -EINVAL;
 		return -EINVAL;
@@ -105,6 +106,8 @@ static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c,
 	data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
 	data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
 	data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
 	data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
 
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	ret = i2c_transfer(i2c, &msg, 1);
 	ret = i2c_transfer(i2c, &msg, 1);
 	return (ret != 1) ? -EIO : 0;
 	return (ret != 1) ? -EIO : 0;
 }
 }
@@ -117,7 +120,6 @@ static struct stv0299_config alps_bsbe1_config = {
 	.skip_reinit = 0,
 	.skip_reinit = 0,
 	.min_delay_ms = 100,
 	.min_delay_ms = 100,
 	.set_symbol_rate = alps_bsbe1_set_symbol_rate,
 	.set_symbol_rate = alps_bsbe1_set_symbol_rate,
-	.pll_set = alps_bsbe1_pll_set,
 };
 };
 
 
 #endif
 #endif

+ 4 - 2
drivers/media/dvb/frontends/bsru6.h

@@ -101,11 +101,12 @@ static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ra
 	return 0;
 	return 0;
 }
 }
 
 
-static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
+static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 {
 	u8 buf[4];
 	u8 buf[4];
 	u32 div;
 	u32 div;
 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+	struct i2c_adapter *i2c = fe->tuner_priv;
 
 
 	if ((params->frequency < 950000) || (params->frequency > 2150000))
 	if ((params->frequency < 950000) || (params->frequency > 2150000))
 		return -EINVAL;
 		return -EINVAL;
@@ -119,6 +120,8 @@ static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c,
 	if (params->frequency > 1530000)
 	if (params->frequency > 1530000)
 		buf[3] = 0xc0;
 		buf[3] = 0xc0;
 
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(i2c, &msg, 1) != 1)
 	if (i2c_transfer(i2c, &msg, 1) != 1)
 		return -EIO;
 		return -EIO;
 	return 0;
 	return 0;
@@ -134,7 +137,6 @@ static struct stv0299_config alps_bsru6_config = {
 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
 	.min_delay_ms = 100,
 	.min_delay_ms = 100,
 	.set_symbol_rate = alps_bsru6_set_symbol_rate,
 	.set_symbol_rate = alps_bsru6_set_symbol_rate,
-	.pll_set = alps_bsru6_pll_set,
 };
 };
 
 
 #endif
 #endif

+ 18 - 13
drivers/media/dvb/frontends/cx22700.c

@@ -34,8 +34,6 @@ struct cx22700_state {
 
 
 	struct i2c_adapter* i2c;
 	struct i2c_adapter* i2c;
 
 
-	struct dvb_frontend_ops ops;
-
 	const struct cx22700_config* config;
 	const struct cx22700_config* config;
 
 
 	struct dvb_frontend frontend;
 	struct dvb_frontend frontend;
@@ -247,12 +245,6 @@ static int cx22700_init (struct dvb_frontend* fe)
 
 
 	cx22700_writereg (state, 0x00, 0x01);
 	cx22700_writereg (state, 0x00, 0x01);
 
 
-	if (state->config->pll_init) {
-		cx22700_writereg (state, 0x0a, 0x00);  /* open i2c bus switch */
-		state->config->pll_init(fe);
-		cx22700_writereg (state, 0x0a, 0x01);  /* close i2c bus switch */
-	}
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -333,9 +325,11 @@ static int cx22700_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
 	cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
 	cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
 	cx22700_writereg (state, 0x00, 0x00);
 	cx22700_writereg (state, 0x00, 0x00);
 
 
-	cx22700_writereg (state, 0x0a, 0x00);  /* open i2c bus switch */
-	state->config->pll_set(fe, p);
-	cx22700_writereg (state, 0x0a, 0x01);  /* close i2c bus switch */
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
 	cx22700_set_inversion (state, p->inversion);
 	cx22700_set_inversion (state, p->inversion);
 	cx22700_set_tps (state, &p->u.ofdm);
 	cx22700_set_tps (state, &p->u.ofdm);
 	cx22700_writereg (state, 0x37, 0x01);  /* PAL loop filter off */
 	cx22700_writereg (state, 0x37, 0x01);  /* PAL loop filter off */
@@ -353,6 +347,17 @@ static int cx22700_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
 	return cx22700_get_tps (state, &p->u.ofdm);
 	return cx22700_get_tps (state, &p->u.ofdm);
 }
 }
 
 
+static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct cx22700_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return cx22700_writereg(state, 0x0a, 0x00);
+	} else {
+		return cx22700_writereg(state, 0x0a, 0x01);
+	}
+}
+
 static int cx22700_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 static int cx22700_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
 {
 	fesettings->min_delay_ms = 150;
 	fesettings->min_delay_ms = 150;
@@ -381,13 +386,12 @@ struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
 	/* setup the state */
 	/* setup the state */
 	state->config = config;
 	state->config = config;
 	state->i2c = i2c;
 	state->i2c = i2c;
-	memcpy(&state->ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
 
 
 	/* check if the demod is there */
 	/* check if the demod is there */
 	if (cx22700_readreg(state, 0x07) < 0) goto error;
 	if (cx22700_readreg(state, 0x07) < 0) goto error;
 
 
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
 
 
@@ -413,6 +417,7 @@ static struct dvb_frontend_ops cx22700_ops = {
 	.release = cx22700_release,
 	.release = cx22700_release,
 
 
 	.init = cx22700_init,
 	.init = cx22700_init,
+	.i2c_gate_ctrl = cx22700_i2c_gate_ctrl,
 
 
 	.set_frontend = cx22700_set_frontend,
 	.set_frontend = cx22700_set_frontend,
 	.get_frontend = cx22700_get_frontend,
 	.get_frontend = cx22700_get_frontend,

+ 0 - 4
drivers/media/dvb/frontends/cx22700.h

@@ -29,10 +29,6 @@ struct cx22700_config
 {
 {
 	/* the demodulator's i2c address */
 	/* the demodulator's i2c address */
 	u8 demod_address;
 	u8 demod_address;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 };
 
 
 extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
 extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,

+ 5 - 24
drivers/media/dvb/frontends/cx22702.c

@@ -40,8 +40,6 @@ struct cx22702_state {
 
 
 	struct i2c_adapter* i2c;
 	struct i2c_adapter* i2c;
 
 
-	struct dvb_frontend_ops ops;
-
 	/* configuration settings */
 	/* configuration settings */
 	const struct cx22702_config* config;
 	const struct cx22702_config* config;
 
 
@@ -211,22 +209,10 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
 	u8 val;
 	u8 val;
 	struct cx22702_state* state = fe->demodulator_priv;
 	struct cx22702_state* state = fe->demodulator_priv;
 
 
-	/* set PLL */
-	cx22702_i2c_gate_ctrl(fe, 1);
-	if (state->config->pll_set) {
-		state->config->pll_set(fe, p);
-	} else if (state->config->pll_desc) {
-		u8 pllbuf[4];
-		struct i2c_msg msg = { .addr = state->config->pll_address,
-				       .buf = pllbuf, .len = 4 };
-		dvb_pll_configure(state->config->pll_desc, pllbuf,
-				  p->frequency,
-				  p->u.ofdm.bandwidth);
-		i2c_transfer(state->i2c, &msg, 1);
-	} else {
-		BUG();
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 	}
 	}
-	cx22702_i2c_gate_ctrl(fe, 0);
 
 
 	/* set inversion */
 	/* set inversion */
 	cx22702_set_inversion (state, p->inversion);
 	cx22702_set_inversion (state, p->inversion);
@@ -358,10 +344,6 @@ static int cx22702_init (struct dvb_frontend* fe)
 
 
 	cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
 	cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
 
 
-	/* init PLL */
-	if (state->config->pll_init)
-		state->config->pll_init(fe);
-
 	cx22702_i2c_gate_ctrl(fe, 0);
 	cx22702_i2c_gate_ctrl(fe, 0);
 
 
 	return 0;
 	return 0;
@@ -495,7 +477,6 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
 	/* setup the state */
 	/* setup the state */
 	state->config = config;
 	state->config = config;
 	state->i2c = i2c;
 	state->i2c = i2c;
-	memcpy(&state->ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
 	state->prevUCBlocks = 0;
 	state->prevUCBlocks = 0;
 
 
 	/* check if the demod is there */
 	/* check if the demod is there */
@@ -503,7 +484,7 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
 		goto error;
 		goto error;
 
 
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
 
 
@@ -530,6 +511,7 @@ static struct dvb_frontend_ops cx22702_ops = {
 	.release = cx22702_release,
 	.release = cx22702_release,
 
 
 	.init = cx22702_init,
 	.init = cx22702_init,
+	.i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
 
 
 	.set_frontend = cx22702_set_tps,
 	.set_frontend = cx22702_set_tps,
 	.get_frontend = cx22702_get_frontend,
 	.get_frontend = cx22702_get_frontend,
@@ -540,7 +522,6 @@ static struct dvb_frontend_ops cx22702_ops = {
 	.read_signal_strength = cx22702_read_signal_strength,
 	.read_signal_strength = cx22702_read_signal_strength,
 	.read_snr = cx22702_read_snr,
 	.read_snr = cx22702_read_snr,
 	.read_ucblocks = cx22702_read_ucblocks,
 	.read_ucblocks = cx22702_read_ucblocks,
-	.i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
 };
 };
 
 
 module_param(debug, int, 0644);
 module_param(debug, int, 0644);

+ 0 - 7
drivers/media/dvb/frontends/cx22702.h

@@ -39,13 +39,6 @@ struct cx22702_config
 #define CX22702_PARALLEL_OUTPUT 0
 #define CX22702_PARALLEL_OUTPUT 0
 #define CX22702_SERIAL_OUTPUT   1
 #define CX22702_SERIAL_OUTPUT   1
 	u8 output_mode;
 	u8 output_mode;
-
-	/* PLL maintenance */
-	u8 pll_address;
-	struct dvb_pll_desc *pll_desc;
-
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 };
 
 
 extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
 extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,

+ 8 - 18
drivers/media/dvb/frontends/cx24110.c

@@ -36,8 +36,6 @@ struct cx24110_state {
 
 
 	struct i2c_adapter* i2c;
 	struct i2c_adapter* i2c;
 
 
-	struct dvb_frontend_ops ops;
-
 	const struct cx24110_config* config;
 	const struct cx24110_config* config;
 
 
 	struct dvb_frontend frontend;
 	struct dvb_frontend frontend;
@@ -250,7 +248,7 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
 	static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
 	static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
 	int i;
 	int i;
 
 
-dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
+	dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
 	if (srate>90999000UL/2)
 	if (srate>90999000UL/2)
 		srate=90999000UL/2;
 		srate=90999000UL/2;
 	if (srate<500000)
 	if (srate<500000)
@@ -366,17 +364,6 @@ static int cx24110_initfe(struct dvb_frontend* fe)
 		cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
 		cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
 	};
 	};
 
 
-	if (state->config->pll_init) state->config->pll_init(fe);
-
-	return 0;
-}
-
-static int cx24110_sleep(struct dvb_frontend *fe)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-
-	if (state->config->pll_sleep)
-		  return state->config->pll_sleep(fe);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -548,7 +535,12 @@ static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
 {
 {
 	struct cx24110_state *state = fe->demodulator_priv;
 	struct cx24110_state *state = fe->demodulator_priv;
 
 
-	state->config->pll_set(fe, p);
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
 	cx24110_set_inversion (state, p->inversion);
 	cx24110_set_inversion (state, p->inversion);
 	cx24110_set_fec (state, p->u.qpsk.fec_inner);
 	cx24110_set_fec (state, p->u.qpsk.fec_inner);
 	cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate);
 	cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate);
@@ -612,7 +604,6 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
 	/* setup the state */
 	/* setup the state */
 	state->config = config;
 	state->config = config;
 	state->i2c = i2c;
 	state->i2c = i2c;
-	memcpy(&state->ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
 	state->lastber = 0;
 	state->lastber = 0;
 	state->lastbler = 0;
 	state->lastbler = 0;
 	state->lastesn0 = 0;
 	state->lastesn0 = 0;
@@ -622,7 +613,7 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
 	if ((ret != 0x5a) && (ret != 0x69)) goto error;
 	if ((ret != 0x5a) && (ret != 0x69)) goto error;
 
 
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
 
 
@@ -651,7 +642,6 @@ static struct dvb_frontend_ops cx24110_ops = {
 	.release = cx24110_release,
 	.release = cx24110_release,
 
 
 	.init = cx24110_initfe,
 	.init = cx24110_initfe,
-	.sleep = cx24110_sleep,
 	.set_frontend = cx24110_set_frontend,
 	.set_frontend = cx24110_set_frontend,
 	.get_frontend = cx24110_get_frontend,
 	.get_frontend = cx24110_get_frontend,
 	.read_status = cx24110_read_status,
 	.read_status = cx24110_read_status,

+ 0 - 5
drivers/media/dvb/frontends/cx24110.h

@@ -31,11 +31,6 @@ struct cx24110_config
 {
 {
 	/* the demodulator's i2c address */
 	/* the demodulator's i2c address */
 	u8 demod_address;
 	u8 demod_address;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-	int (*pll_sleep)(struct dvb_frontend* fe);
 };
 };
 
 
 extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
 extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,

+ 51 - 144
drivers/media/dvb/frontends/cx24123.c

@@ -41,14 +41,12 @@ static int debug;
 struct cx24123_state
 struct cx24123_state
 {
 {
 	struct i2c_adapter* i2c;
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct cx24123_config* config;
 	const struct cx24123_config* config;
 
 
 	struct dvb_frontend frontend;
 	struct dvb_frontend frontend;
 
 
 	u32 lastber;
 	u32 lastber;
 	u16 snr;
 	u16 snr;
-	u8  lnbreg;
 
 
 	/* Some PLL specifics for tuning */
 	/* Some PLL specifics for tuning */
 	u32 VCAarg;
 	u32 VCAarg;
@@ -249,29 +247,6 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
 	return 0;
 	return 0;
 }
 }
 
 
-static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
-{
-	u8 buf[] = { reg, data };
-	/* fixme: put the intersil addr int the config */
-	struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
-	int err;
-
-	if (debug>1)
-		printk("cx24123: %s:  writeln addr=0x08, reg 0x%02x, value 0x%02x\n",
-						__FUNCTION__,reg, data);
-
-	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-		printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
-		return -EREMOTEIO;
-	}
-
-	/* cache the write, no way to read back */
-	state->lnbreg = data;
-
-	return 0;
-}
-
 static int cx24123_readreg(struct cx24123_state* state, u8 reg)
 static int cx24123_readreg(struct cx24123_state* state, u8 reg)
 {
 {
 	int ret;
 	int ret;
@@ -295,11 +270,6 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg)
 	return b1[0];
 	return b1[0];
 }
 }
 
 
-static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
-{
-	return state->lnbreg;
-}
-
 static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
 static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
 {
 {
 	u8 nom_reg = cx24123_readreg(state, 0x0e);
 	u8 nom_reg = cx24123_readreg(state, 0x0e);
@@ -458,8 +428,8 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
 	u8 pll_mult;
 	u8 pll_mult;
 
 
 	/*  check if symbol rate is within limits */
 	/*  check if symbol rate is within limits */
-	if ((srate > state->ops.info.symbol_rate_max) ||
-	    (srate < state->ops.info.symbol_rate_min))
+	if ((srate > state->frontend.ops.info.symbol_rate_max) ||
+	    (srate < state->frontend.ops.info.symbol_rate_min))
 		return -EOPNOTSUPP;;
 		return -EOPNOTSUPP;;
 
 
 	/* choose the sampling rate high enough for the required operation,
 	/* choose the sampling rate high enough for the required operation,
@@ -687,13 +657,6 @@ static int cx24123_initfe(struct dvb_frontend* fe)
 	for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
 	for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
 		cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
 		cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
 
 
-	if (state->config->pll_init)
-		state->config->pll_init(fe);
-
-	/* Configure the LNB for 14V */
-	if (state->config->use_isl6421)
-		cx24123_writelnbreg(state, 0x0, 0x2a);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -702,50 +665,18 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
 	struct cx24123_state *state = fe->demodulator_priv;
 	struct cx24123_state *state = fe->demodulator_priv;
 	u8 val;
 	u8 val;
 
 
-	switch (state->config->use_isl6421) {
-
-	case 1:
+	val = cx24123_readreg(state, 0x29) & ~0x40;
 
 
-		val = cx24123_readlnbreg(state, 0x0);
-
-		switch (voltage) {
-		case SEC_VOLTAGE_13:
-			dprintk("%s:  isl6421 voltage = 13V\n",__FUNCTION__);
-			return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
-		case SEC_VOLTAGE_18:
-			dprintk("%s:  isl6421 voltage = 18V\n",__FUNCTION__);
-			return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
-		case SEC_VOLTAGE_OFF:
-			dprintk("%s:  isl5421 voltage off\n",__FUNCTION__);
-			return cx24123_writelnbreg(state, 0x0, val & 0x30);
-		default:
-			return -EINVAL;
-		};
-
-	case 0:
-
-		val = cx24123_readreg(state, 0x29);
-
-		switch (voltage) {
-		case SEC_VOLTAGE_13:
-			dprintk("%s: setting voltage 13V\n", __FUNCTION__);
-			if (state->config->enable_lnb_voltage)
-				state->config->enable_lnb_voltage(fe, 1);
-			return cx24123_writereg(state, 0x29, val | 0x80);
-		case SEC_VOLTAGE_18:
-			dprintk("%s: setting voltage 18V\n", __FUNCTION__);
-			if (state->config->enable_lnb_voltage)
-				state->config->enable_lnb_voltage(fe, 1);
-			return cx24123_writereg(state, 0x29, val & 0x7f);
-		case SEC_VOLTAGE_OFF:
-			dprintk("%s: setting voltage off\n", __FUNCTION__);
-			if (state->config->enable_lnb_voltage)
-				state->config->enable_lnb_voltage(fe, 0);
-			return 0;
-		default:
-			return -EINVAL;
-		};
-	}
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+		return cx24123_writereg(state, 0x29, val | 0x80);
+	case SEC_VOLTAGE_18:
+		dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+		return cx24123_writereg(state, 0x29, val & 0x7f);
+	default:
+		return -EINVAL;
+	};
 
 
 	return 0;
 	return 0;
 }
 }
@@ -766,27 +697,20 @@ static void cx24123_wait_for_diseqc(struct cx24123_state *state)
 static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
 static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
 {
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	struct cx24123_state *state = fe->demodulator_priv;
-	int i, val;
+	int i, val, tone;
 
 
 	dprintk("%s:\n",__FUNCTION__);
 	dprintk("%s:\n",__FUNCTION__);
 
 
-	/* check if continuous tone has been stopped */
-	if (state->config->use_isl6421)
-		val = cx24123_readlnbreg(state, 0x00) & 0x10;
-	else
-		val = cx24123_readreg(state, 0x29) & 0x10;
-
-
-	if (val) {
-		printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
-		return -ENOTSUPP;
-	}
+	/* stop continuous tone if enabled */
+	tone = cx24123_readreg(state, 0x29);
+	if (tone & 0x10)
+		cx24123_writereg(state, 0x29, tone & ~0x50);
 
 
 	/* wait for diseqc queue ready */
 	/* wait for diseqc queue ready */
 	cx24123_wait_for_diseqc(state);
 	cx24123_wait_for_diseqc(state);
 
 
 	/* select tone mode */
 	/* select tone mode */
-	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8);
+	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
 
 
 	for (i = 0; i < cmd->msg_len; i++)
 	for (i = 0; i < cmd->msg_len; i++)
 		cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
 		cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
@@ -797,36 +721,33 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
 	/* wait for diseqc message to finish sending */
 	/* wait for diseqc message to finish sending */
 	cx24123_wait_for_diseqc(state);
 	cx24123_wait_for_diseqc(state);
 
 
+	/* restart continuous tone if enabled */
+	if (tone & 0x10) {
+		cx24123_writereg(state, 0x29, tone & ~0x40);
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 
 static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
 static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
 {
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 	struct cx24123_state *state = fe->demodulator_priv;
-	int val;
+	int val, tone;
 
 
 	dprintk("%s:\n", __FUNCTION__);
 	dprintk("%s:\n", __FUNCTION__);
 
 
-	/* check if continuous tone has been stoped */
-	if (state->config->use_isl6421)
-		val = cx24123_readlnbreg(state, 0x00) & 0x10;
-	else
-		val = cx24123_readreg(state, 0x29) & 0x10;
-
-
-	if (val) {
-		printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
-		return -ENOTSUPP;
-	}
+	/* stop continuous tone if enabled */
+	tone = cx24123_readreg(state, 0x29);
+	if (tone & 0x10)
+		cx24123_writereg(state, 0x29, tone & ~0x50);
 
 
+	/* wait for diseqc queue ready */
 	cx24123_wait_for_diseqc(state);
 	cx24123_wait_for_diseqc(state);
 
 
 	/* select tone mode */
 	/* select tone mode */
-	val = cx24123_readreg(state, 0x2a) & 0xf8;
-	cx24123_writereg(state, 0x2a, val | 0x04);
-
+	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4);
+	msleep(30);
 	val = cx24123_readreg(state, 0x29);
 	val = cx24123_readreg(state, 0x29);
-
 	if (burst == SEC_MINI_A)
 	if (burst == SEC_MINI_A)
 		cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
 		cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
 	else if (burst == SEC_MINI_B)
 	else if (burst == SEC_MINI_B)
@@ -835,7 +756,12 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
 		return -EINVAL;
 		return -EINVAL;
 
 
 	cx24123_wait_for_diseqc(state);
 	cx24123_wait_for_diseqc(state);
+	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
 
 
+	/* restart continuous tone if enabled */
+	if (tone & 0x10) {
+		cx24123_writereg(state, 0x29, tone & ~0x40);
+	}
 	return 0;
 	return 0;
 }
 }
 
 
@@ -976,38 +902,21 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
 	struct cx24123_state *state = fe->demodulator_priv;
 	struct cx24123_state *state = fe->demodulator_priv;
 	u8 val;
 	u8 val;
 
 
-	switch (state->config->use_isl6421) {
-	case 1:
-
-		val = cx24123_readlnbreg(state, 0x0);
-
-		switch (tone) {
-		case SEC_TONE_ON:
-			dprintk("%s:  isl6421 sec tone on\n",__FUNCTION__);
-			return cx24123_writelnbreg(state, 0x0, val | 0x10);
-		case SEC_TONE_OFF:
-			dprintk("%s:  isl6421 sec tone off\n",__FUNCTION__);
-			return cx24123_writelnbreg(state, 0x0, val & 0x2f);
-		default:
-			printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
-			return -EINVAL;
-		}
-
-	case 0:
+	/* wait for diseqc queue ready */
+	cx24123_wait_for_diseqc(state);
 
 
-		val = cx24123_readreg(state, 0x29);
+	val = cx24123_readreg(state, 0x29) & ~0x40;
 
 
-		switch (tone) {
-		case SEC_TONE_ON:
-			dprintk("%s: setting tone on\n", __FUNCTION__);
-			return cx24123_writereg(state, 0x29, val | 0x10);
-		case SEC_TONE_OFF:
-			dprintk("%s: setting tone off\n",__FUNCTION__);
-			return cx24123_writereg(state, 0x29, val & 0xef);
-		default:
-			printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
-			return -EINVAL;
-		}
+	switch (tone) {
+	case SEC_TONE_ON:
+		dprintk("%s: setting tone on\n", __FUNCTION__);
+		return cx24123_writereg(state, 0x29, val | 0x10);
+	case SEC_TONE_OFF:
+		dprintk("%s: setting tone off\n",__FUNCTION__);
+		return cx24123_writereg(state, 0x29, val & 0xef);
+	default:
+		printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+		return -EINVAL;
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -1040,10 +949,8 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
 	/* setup the state */
 	/* setup the state */
 	state->config = config;
 	state->config = config;
 	state->i2c = i2c;
 	state->i2c = i2c;
-	memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
 	state->lastber = 0;
 	state->lastber = 0;
 	state->snr = 0;
 	state->snr = 0;
-	state->lnbreg = 0;
 	state->VCAarg = 0;
 	state->VCAarg = 0;
 	state->VGAarg = 0;
 	state->VGAarg = 0;
 	state->bandselectarg = 0;
 	state->bandselectarg = 0;
@@ -1059,7 +966,7 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
 	}
 	}
 
 
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
 
 

+ 0 - 13
drivers/media/dvb/frontends/cx24123.h

@@ -28,21 +28,8 @@ struct cx24123_config
 	/* the demodulator's i2c address */
 	/* the demodulator's i2c address */
 	u8 demod_address;
 	u8 demod_address;
 
 
-	/*
-	   cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
-	   for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
-	   from register 0x29 of the CX24123 demodulator
-	*/
-	int use_isl6421;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
 	/* Need to set device param for start_dma */
 	/* Need to set device param for start_dma */
 	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
 	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
-
-	void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
 };
 };
 
 
 extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
 extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,

+ 0 - 2
drivers/media/dvb/frontends/dib3000-common.h

@@ -38,8 +38,6 @@
 struct dib3000_state {
 struct dib3000_state {
 	struct i2c_adapter* i2c;
 	struct i2c_adapter* i2c;
 
 
-	struct dvb_frontend_ops ops;
-
 /* configuration settings */
 /* configuration settings */
 	struct dib3000_config config;
 	struct dib3000_config config;
 
 

+ 0 - 4
drivers/media/dvb/frontends/dib3000.h

@@ -30,10 +30,6 @@ struct dib3000_config
 {
 {
 	/* the demodulator's i2c address */
 	/* the demodulator's i2c address */
 	u8 demod_address;
 	u8 demod_address;
-
-	/* PLL maintenance and the i2c address of the PLL */
-	int (*pll_init)(struct dvb_frontend *fe);
-	int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params);
 };
 };
 
 
 struct dib_fe_xfer_ops
 struct dib_fe_xfer_ops

+ 4 - 7
drivers/media/dvb/frontends/dib3000mb.c

@@ -60,8 +60,9 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
 	fe_code_rate_t fe_cr = FEC_NONE;
 	fe_code_rate_t fe_cr = FEC_NONE;
 	int search_state, seq;
 	int search_state, seq;
 
 
-	if (tuner && state->config.pll_set) {
-		state->config.pll_set(fe, fep);
+	if (tuner && fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, fep);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 
 
 		deb_setf("bandwidth: ");
 		deb_setf("bandwidth: ");
 		switch (ofdm->bandwidth) {
 		switch (ofdm->bandwidth) {
@@ -386,9 +387,6 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
 
 
 	wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
 	wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
 
 
-	if (state->config.pll_init)
-		state->config.pll_init(fe);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -707,7 +705,6 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
 	/* setup the state */
 	/* setup the state */
 	state->i2c = i2c;
 	state->i2c = i2c;
 	memcpy(&state->config,config,sizeof(struct dib3000_config));
 	memcpy(&state->config,config,sizeof(struct dib3000_config));
-	memcpy(&state->ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
 
 
 	/* check for the correct demod */
 	/* check for the correct demod */
 	if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
 	if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
@@ -717,7 +714,7 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
 		goto error;
 		goto error;
 
 
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 
 
 	/* set the xfer operations */
 	/* set the xfer operations */

+ 5 - 9
drivers/media/dvb/frontends/dib3000mc.c

@@ -462,8 +462,9 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
 	int search_state,auto_val;
 	int search_state,auto_val;
 	u16 val;
 	u16 val;
 
 
-	if (tuner && state->config.pll_set) { /* initial call from dvb */
-		state->config.pll_set(fe,fep);
+	if (tuner && fe->ops.tuner_ops.set_params) { /* initial call from dvb */
+		fe->ops.tuner_ops.set_params(fe, fep);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 
 
 		state->last_tuned_freq = fep->frequency;
 		state->last_tuned_freq = fep->frequency;
 	//	if (!scanboost) {
 	//	if (!scanboost) {
@@ -642,9 +643,6 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
 
 
 	set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
 	set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
 
 
-	if (state->config.pll_init)
-		state->config.pll_init(fe);
-
 	deb_info("init end\n");
 	deb_info("init end\n");
 	return 0;
 	return 0;
 }
 }
@@ -839,7 +837,6 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
 	/* setup the state */
 	/* setup the state */
 	state->i2c = i2c;
 	state->i2c = i2c;
 	memcpy(&state->config,config,sizeof(struct dib3000_config));
 	memcpy(&state->config,config,sizeof(struct dib3000_config));
-	memcpy(&state->ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
 
 
 	/* check for the correct demod */
 	/* check for the correct demod */
 	if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
 	if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
@@ -859,7 +856,7 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
 	}
 	}
 
 
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 
 
 	/* set the xfer operations */
 	/* set the xfer operations */
@@ -876,6 +873,7 @@ error:
 	kfree(state);
 	kfree(state);
 	return NULL;
 	return NULL;
 }
 }
+EXPORT_SYMBOL(dib3000mc_attach);
 
 
 static struct dvb_frontend_ops dib3000mc_ops = {
 static struct dvb_frontend_ops dib3000mc_ops = {
 
 
@@ -914,5 +912,3 @@ static struct dvb_frontend_ops dib3000mc_ops = {
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dib3000mc_attach);

+ 176 - 5
drivers/media/dvb/frontends/dvb-pll.c

@@ -227,10 +227,10 @@ struct dvb_pll_desc dvb_pll_tua6034 = {
 EXPORT_SYMBOL(dvb_pll_tua6034);
 EXPORT_SYMBOL(dvb_pll_tua6034);
 
 
 /* Infineon TUA6034
 /* Infineon TUA6034
- * used in LG TDVS H061F and LG TDVS H062F
+ * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F
  */
  */
-struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
-	.name  = "LG/Infineon TUA6034",
+struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
+	.name  = "LG TDVS-H06xF",
 	.min   =  54000000,
 	.min   =  54000000,
 	.max   = 863000000,
 	.max   = 863000000,
 	.count = 3,
 	.count = 3,
@@ -240,7 +240,7 @@ struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
 		{  999999999, 44000000, 62500, 0xce, 0x04 },
 		{  999999999, 44000000, 62500, 0xce, 0x04 },
 	},
 	},
 };
 };
-EXPORT_SYMBOL(dvb_pll_tdvs_tua6034);
+EXPORT_SYMBOL(dvb_pll_lg_tdvs_h06xf);
 
 
 /* Philips FMD1216ME
 /* Philips FMD1216ME
  * used in Medion Hybrid PCMCIA card and USB Box
  * used in Medion Hybrid PCMCIA card and USB Box
@@ -419,6 +419,19 @@ struct dvb_pll_desc dvb_pll_thomson_fe6600 = {
 };
 };
 EXPORT_SYMBOL(dvb_pll_thomson_fe6600);
 EXPORT_SYMBOL(dvb_pll_thomson_fe6600);
 
 
+struct dvb_pll_priv {
+	/* i2c details */
+	int pll_i2c_address;
+	struct i2c_adapter *i2c;
+
+	/* the PLL descriptor */
+	struct dvb_pll_desc *pll_desc;
+
+	/* cached frequency/bandwidth */
+	u32 frequency;
+	u32 bandwidth;
+};
+
 /* ----------------------------------------------------------- */
 /* ----------------------------------------------------------- */
 /* code                                                        */
 /* code                                                        */
 
 
@@ -443,7 +456,8 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
 	if (debug)
 	if (debug)
 		printk("pll: %s: freq=%d bw=%d | i=%d/%d\n",
 		printk("pll: %s: freq=%d bw=%d | i=%d/%d\n",
 		       desc->name, freq, bandwidth, i, desc->count);
 		       desc->name, freq, bandwidth, i, desc->count);
-	BUG_ON(i == desc->count);
+	if (i == desc->count)
+		return -EINVAL;
 
 
 	div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize;
 	div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize;
 	buf[0] = div >> 8;
 	buf[0] = div >> 8;
@@ -462,6 +476,163 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
 }
 }
 EXPORT_SYMBOL(dvb_pll_configure);
 EXPORT_SYMBOL(dvb_pll_configure);
 
 
+static int dvb_pll_release(struct dvb_frontend *fe)
+{
+	if (fe->tuner_priv)
+		kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static int dvb_pll_sleep(struct dvb_frontend *fe)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	u8 buf[4];
+	struct i2c_msg msg =
+		{ .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+	int i;
+	int result;
+
+	for (i = 0; i < priv->pll_desc->count; i++) {
+		if (priv->pll_desc->entries[i].limit == 0)
+			break;
+	}
+	if (i == priv->pll_desc->count)
+		return 0;
+
+	buf[0] = 0;
+	buf[1] = 0;
+	buf[2] = priv->pll_desc->entries[i].config;
+	buf[3] = priv->pll_desc->entries[i].cb;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+		return result;
+	}
+
+	return 0;
+}
+
+static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	u8 buf[4];
+	struct i2c_msg msg =
+		{ .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+	int result;
+	u32 div;
+	int i;
+	u32 bandwidth = 0;
+
+	if (priv->i2c == NULL)
+		return -EINVAL;
+
+	// DVBT bandwidth only just now
+	if (fe->ops.info.type == FE_OFDM) {
+		bandwidth = params->u.ofdm.bandwidth;
+	}
+
+	if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0)
+		return result;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+		return result;
+	}
+
+	// calculate the frequency we set it to
+	for (i = 0; i < priv->pll_desc->count; i++) {
+		if (params->frequency > priv->pll_desc->entries[i].limit)
+			continue;
+		break;
+	}
+	div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
+	priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+	priv->bandwidth = bandwidth;
+
+	return 0;
+}
+
+static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	int result;
+	u32 div;
+	int i;
+	u32 bandwidth = 0;
+
+	if (buf_len < 5)
+		return -EINVAL;
+
+	// DVBT bandwidth only just now
+	if (fe->ops.info.type == FE_OFDM) {
+		bandwidth = params->u.ofdm.bandwidth;
+	}
+
+	if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0)
+		return result;
+	buf[0] = priv->pll_i2c_address;
+
+	// calculate the frequency we set it to
+	for (i = 0; i < priv->pll_desc->count; i++) {
+		if (params->frequency > priv->pll_desc->entries[i].limit)
+			continue;
+		break;
+	}
+	div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
+	priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+	priv->bandwidth = bandwidth;
+
+	return 5;
+}
+
+static int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	*frequency = priv->frequency;
+	return 0;
+}
+
+static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	*bandwidth = priv->bandwidth;
+	return 0;
+}
+
+static struct dvb_tuner_ops dvb_pll_tuner_ops = {
+	.release = dvb_pll_release,
+	.sleep = dvb_pll_sleep,
+	.set_params = dvb_pll_set_params,
+	.calc_regs = dvb_pll_calc_regs,
+	.get_frequency = dvb_pll_get_frequency,
+	.get_bandwidth = dvb_pll_get_bandwidth,
+};
+
+int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
+{
+	struct dvb_pll_priv *priv = NULL;
+
+	priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return -ENOMEM;
+
+	priv->pll_i2c_address = pll_addr;
+	priv->i2c = i2c;
+	priv->pll_desc = desc;
+
+	memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops));
+	strncpy(fe->ops.tuner_ops.info.name, desc->name, 128);
+	fe->ops.tuner_ops.info.frequency_min = desc->min;
+	fe->ops.tuner_ops.info.frequency_min = desc->max;
+
+	fe->tuner_priv = priv;
+	return 0;
+}
+EXPORT_SYMBOL(dvb_pll_attach);
+
 MODULE_DESCRIPTION("dvb pll library");
 MODULE_DESCRIPTION("dvb pll library");
 MODULE_AUTHOR("Gerd Knorr");
 MODULE_AUTHOR("Gerd Knorr");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 16 - 2
drivers/media/dvb/frontends/dvb-pll.h

@@ -5,6 +5,9 @@
 #ifndef __DVB_PLL_H__
 #ifndef __DVB_PLL_H__
 #define __DVB_PLL_H__
 #define __DVB_PLL_H__
 
 
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
 struct dvb_pll_desc {
 struct dvb_pll_desc {
 	char *name;
 	char *name;
 	u32  min;
 	u32  min;
@@ -31,7 +34,7 @@ extern struct dvb_pll_desc dvb_pll_unknown_1;
 extern struct dvb_pll_desc dvb_pll_tua6010xs;
 extern struct dvb_pll_desc dvb_pll_tua6010xs;
 extern struct dvb_pll_desc dvb_pll_env57h1xd5;
 extern struct dvb_pll_desc dvb_pll_env57h1xd5;
 extern struct dvb_pll_desc dvb_pll_tua6034;
 extern struct dvb_pll_desc dvb_pll_tua6034;
-extern struct dvb_pll_desc dvb_pll_tdvs_tua6034;
+extern struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf;
 extern struct dvb_pll_desc dvb_pll_tda665x;
 extern struct dvb_pll_desc dvb_pll_tda665x;
 extern struct dvb_pll_desc dvb_pll_fmd1216me;
 extern struct dvb_pll_desc dvb_pll_fmd1216me;
 extern struct dvb_pll_desc dvb_pll_tded4;
 extern struct dvb_pll_desc dvb_pll_tded4;
@@ -44,7 +47,18 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316;
 
 
 extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
 extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
 
 
-int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
+extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
 		      u32 freq, int bandwidth);
 		      u32 freq, int bandwidth);
 
 
+/**
+ * Attach a dvb-pll to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param pll_addr i2c address of the PLL (if used).
+ * @param i2c i2c adapter to use (set to NULL if not used).
+ * @param desc dvb_pll_desc to use.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
+
 #endif
 #endif

+ 8 - 13
drivers/media/dvb/frontends/dvb_dummy_fe.c

@@ -30,7 +30,6 @@
 
 
 
 
 struct dvb_dummy_fe_state {
 struct dvb_dummy_fe_state {
-	struct dvb_frontend_ops ops;
 	struct dvb_frontend frontend;
 	struct dvb_frontend frontend;
 };
 };
 
 
@@ -77,6 +76,11 @@ static int dvb_dummy_fe_get_frontend(struct dvb_frontend* fe, struct dvb_fronten
 
 
 static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
 static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
 {
 {
+	if (fe->ops->tuner_ops->set_params) {
+		fe->ops->tuner_ops->set_params(fe, p);
+		if (fe->ops->i2c_gate_ctrl) fe->ops->i2c_gate_ctrl(fe, 0);
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -116,11 +120,8 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
 	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 	if (state == NULL) goto error;
 
 
-	/* setup the state */
-	memcpy(&state->ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
-
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
 
 
@@ -139,11 +140,8 @@ struct dvb_frontend* dvb_dummy_fe_qpsk_attach()
 	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 	if (state == NULL) goto error;
 
 
-	/* setup the state */
-	memcpy(&state->ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
-
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
 
 
@@ -162,11 +160,8 @@ struct dvb_frontend* dvb_dummy_fe_qam_attach()
 	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 	if (state == NULL) goto error;
 
 
-	/* setup the state */
-	memcpy(&state->ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
-
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
 
 

+ 149 - 0
drivers/media/dvb/frontends/isl6421.c

@@ -0,0 +1,149 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6421.h"
+
+struct isl6421 {
+	u8			config;
+	u8			override_or;
+	u8			override_and;
+	struct i2c_adapter	*i2c;
+	u8			i2c_addr;
+	void			(*release_chain)(struct dvb_frontend* fe);
+};
+
+static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+	struct i2c_msg msg = {	.addr = isl6421->i2c_addr, .flags = 0,
+				.buf = &isl6421->config,
+				.len = sizeof(isl6421->config) };
+
+	isl6421->config &= ~(ISL6421_VSEL1 | ISL6421_EN1);
+
+	switch(voltage) {
+	case SEC_VOLTAGE_OFF:
+		break;
+	case SEC_VOLTAGE_13:
+		isl6421->config |= ISL6421_EN1;
+		break;
+	case SEC_VOLTAGE_18:
+		isl6421->config |= (ISL6421_EN1 | ISL6421_VSEL1);
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	isl6421->config |= isl6421->override_or;
+	isl6421->config &= isl6421->override_and;
+
+	return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+	struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+	struct i2c_msg msg = {	.addr = isl6421->i2c_addr, .flags = 0,
+				.buf = &isl6421->config,
+				.len = sizeof(isl6421->config) };
+
+	if (arg)
+		isl6421->config |= ISL6421_LLC1;
+	else
+		isl6421->config &= ~ISL6421_LLC1;
+
+	isl6421->config |= isl6421->override_or;
+	isl6421->config &= isl6421->override_and;
+
+	return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void isl6421_release(struct dvb_frontend *fe)
+{
+	struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+
+	/* power off */
+	isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	/* free data & call next release routine */
+	fe->ops.release = isl6421->release_chain;
+	kfree(fe->misc_priv);
+	fe->misc_priv = NULL;
+	if (fe->ops.release)
+		fe->ops.release(fe);
+}
+
+int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+		   u8 override_set, u8 override_clear)
+{
+	struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
+	if (!isl6421)
+		return -ENOMEM;
+
+	/* default configuration */
+	isl6421->config = ISL6421_ISEL1;
+	isl6421->i2c = i2c;
+	isl6421->i2c_addr = i2c_addr;
+	fe->misc_priv = isl6421;
+
+	/* bits which should be forced to '1' */
+	isl6421->override_or = override_set;
+
+	/* bits which should be forced to '0' */
+	isl6421->override_and = ~override_clear;
+
+	/* detect if it is present or not */
+	if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+		kfree(isl6421);
+		fe->misc_priv = NULL;
+		return -EIO;
+	}
+
+	/* install release callback */
+	isl6421->release_chain = fe->ops.release;
+	fe->ops.release = isl6421_release;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = isl6421_set_voltage;
+	fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
+
+	return 0;
+}
+EXPORT_SYMBOL(isl6421_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421");
+MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss");
+MODULE_LICENSE("GPL");

+ 46 - 0
drivers/media/dvb/frontends/isl6421.h

@@ -0,0 +1,46 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _ISL6421_H
+#define _ISL6421_H
+
+#include <linux/dvb/frontend.h>
+
+/* system register bits */
+#define ISL6421_OLF1	0x01
+#define ISL6421_EN1	0x02
+#define ISL6421_VSEL1	0x04
+#define ISL6421_LLC1	0x08
+#define ISL6421_ENT1	0x10
+#define ISL6421_ISEL1	0x20
+#define ISL6421_DCL	0x40
+
+/* override_set and override_clear control which system register bits (above) to always set & clear */
+extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+			  u8 override_set, u8 override_clear);
+
+#endif

+ 5 - 6
drivers/media/dvb/frontends/l64781.c

@@ -32,7 +32,6 @@
 
 
 struct l64781_state {
 struct l64781_state {
 	struct i2c_adapter* i2c;
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct l64781_config* config;
 	const struct l64781_config* config;
 	struct dvb_frontend frontend;
 	struct dvb_frontend frontend;
 
 
@@ -141,7 +140,10 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
 	u8 val0x06;
 	u8 val0x06;
 	int bw = p->bandwidth - BANDWIDTH_8_MHZ;
 	int bw = p->bandwidth - BANDWIDTH_8_MHZ;
 
 
-	state->config->pll_set(fe, param);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 
 	if (param->inversion != INVERSION_ON &&
 	if (param->inversion != INVERSION_ON &&
 	    param->inversion != INVERSION_OFF)
 	    param->inversion != INVERSION_OFF)
@@ -463,8 +465,6 @@ static int l64781_init(struct dvb_frontend* fe)
 	/* Everything is two's complement, soft bit and CSI_OUT too */
 	/* Everything is two's complement, soft bit and CSI_OUT too */
 	l64781_writereg (state, 0x1e, 0x09);
 	l64781_writereg (state, 0x1e, 0x09);
 
 
-	if (state->config->pll_init) state->config->pll_init(fe);
-
 	/* delay a bit after first init attempt */
 	/* delay a bit after first init attempt */
 	if (state->first) {
 	if (state->first) {
 		state->first = 0;
 		state->first = 0;
@@ -508,7 +508,6 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
 	/* setup the state */
 	/* setup the state */
 	state->config = config;
 	state->config = config;
 	state->i2c = i2c;
 	state->i2c = i2c;
-	memcpy(&state->ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
 	state->first = 1;
 	state->first = 1;
 
 
 	/**
 	/**
@@ -554,7 +553,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
 	}
 	}
 
 
 	/* create dvb_frontend */
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
 
 

+ 0 - 4
drivers/media/dvb/frontends/l64781.h

@@ -29,10 +29,6 @@ struct l64781_config
 {
 {
 	/* the demodulator's i2c address */
 	/* the demodulator's i2c address */
 	u8 demod_address;
 	u8 demod_address;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 };
 
 
 
 

+ 64 - 0
drivers/media/dvb/frontends/lg_h06xf.h

@@ -0,0 +1,64 @@
+/*
+ *  lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LG_H06XF_H_
+#define _LG_H06XF_H_
+#include "dvb-pll.h"
+
+static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap,
+		     struct dvb_frontend_parameters* params)
+{
+	u8 buf[4];
+	struct i2c_msg msg = { .addr = 0x61, .flags = 0,
+			       .buf = buf, .len = sizeof(buf) };
+	int err;
+
+	dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
+		printk(KERN_WARNING "lg_h06xf: %s error "
+			"(addr %02x <- %02x, err = %i)\n",
+			__FUNCTION__, buf[0], buf[1], err);
+		if (err < 0)
+			return err;
+		else
+			return -EREMOTEIO;
+	}
+
+	/* Set the Auxiliary Byte. */
+	buf[0] = buf[2];
+	buf[0] &= ~0x20;
+	buf[0] |= 0x18;
+	buf[1] = 0x50;
+	msg.len = 2;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
+		printk(KERN_WARNING "lg_h06xf: %s error "
+			"(addr %02x <- %02x, err = %i)\n",
+			__FUNCTION__, buf[0], buf[1], err);
+		if (err < 0)
+			return err;
+		else
+			return -EREMOTEIO;
+	}
+
+	return 0;
+}
+#endif

+ 11 - 8
drivers/media/dvb/frontends/lgdt330x.c

@@ -29,6 +29,7 @@
  *   DViCO FusionHDTV 5 Lite
  *   DViCO FusionHDTV 5 Lite
  *   DViCO FusionHDTV 5 USB Gold
  *   DViCO FusionHDTV 5 USB Gold
  *   Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
  *   Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
+ *   pcHDTV HD5500
  *
  *
  * TODO:
  * TODO:
  * signal strength always returns 0.
  * signal strength always returns 0.
@@ -59,7 +60,6 @@ if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
 struct lgdt330x_state
 struct lgdt330x_state
 {
 {
 	struct i2c_adapter* i2c;
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 
 
 	/* Configuration settings */
 	/* Configuration settings */
 	const struct lgdt330x_config* config;
 	const struct lgdt330x_config* config;
@@ -399,8 +399,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
 	}
 	}
 
 
 	/* Tune to the specified frequency */
 	/* Tune to the specified frequency */
-	if (state->config->pll_set)
-		state->config->pll_set(fe, param);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 
 	/* Keep track of the new frequency */
 	/* Keep track of the new frequency */
 	/* FIXME this is the wrong way to do this...           */
 	/* FIXME this is the wrong way to do this...           */
@@ -672,6 +674,7 @@ static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
 
 
 	if (state->current_modulation == VSB_8) {
 	if (state->current_modulation == VSB_8) {
 
 
+		i2c_read_demod_bytes(state, 0x6e, buf, 5);
 		/* Phase Tracker Mean-Square Error Register for VSB */
 		/* Phase Tracker Mean-Square Error Register for VSB */
 		noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
 		noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
 	} else {
 	} else {
@@ -721,16 +724,19 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
 	/* Setup the state */
 	/* Setup the state */
 	state->config = config;
 	state->config = config;
 	state->i2c = i2c;
 	state->i2c = i2c;
+
+	/* Create dvb_frontend */
 	switch (config->demod_chip) {
 	switch (config->demod_chip) {
 	case LGDT3302:
 	case LGDT3302:
-		memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
+		memcpy(&state->frontend.ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
 		break;
 		break;
 	case LGDT3303:
 	case LGDT3303:
-		memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
+		memcpy(&state->frontend.ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
 		break;
 		break;
 	default:
 	default:
 		goto error;
 		goto error;
 	}
 	}
+	state->frontend.demodulator_priv = state;
 
 
 	/* Verify communication with demod chip */
 	/* Verify communication with demod chip */
 	if (i2c_read_demod_bytes(state, 2, buf, 1))
 	if (i2c_read_demod_bytes(state, 2, buf, 1))
@@ -739,9 +745,6 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
 	state->current_frequency = -1;
 	state->current_frequency = -1;
 	state->current_modulation = -1;
 	state->current_modulation = -1;
 
 
-	/* Create dvb_frontend */
-	state->frontend.ops = &state->ops;
-	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
 
 
 error:
 error:

+ 0 - 1
drivers/media/dvb/frontends/lgdt330x.h

@@ -43,7 +43,6 @@ struct lgdt330x_config
 
 
 	/* PLL interface */
 	/* PLL interface */
 	int (*pll_rf_set) (struct dvb_frontend* fe, int index);
 	int (*pll_rf_set) (struct dvb_frontend* fe, int index);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 
 
 	/* Need to set device param for start_dma */
 	/* Need to set device param for start_dma */
 	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
 	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);

+ 145 - 0
drivers/media/dvb/frontends/lnbp21.c

@@ -0,0 +1,145 @@
+/*
+ * lnbp21.h - driver for lnb supply and control ic lnbp21
+ *
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "lnbp21.h"
+
+struct lnbp21 {
+	u8			config;
+	u8			override_or;
+	u8			override_and;
+	struct i2c_adapter	*i2c;
+	void			(*release_chain)(struct dvb_frontend* fe);
+};
+
+static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+	struct i2c_msg msg = {	.addr = 0x08, .flags = 0,
+				.buf = &lnbp21->config,
+				.len = sizeof(lnbp21->config) };
+
+	lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
+
+	switch(voltage) {
+	case SEC_VOLTAGE_OFF:
+		break;
+	case SEC_VOLTAGE_13:
+		lnbp21->config |= LNBP21_EN;
+		break;
+	case SEC_VOLTAGE_18:
+		lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	lnbp21->config |= lnbp21->override_or;
+	lnbp21->config &= lnbp21->override_and;
+
+	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+	struct i2c_msg msg = {	.addr = 0x08, .flags = 0,
+				.buf = &lnbp21->config,
+				.len = sizeof(lnbp21->config) };
+
+	if (arg)
+		lnbp21->config |= LNBP21_LLC;
+	else
+		lnbp21->config &= ~LNBP21_LLC;
+
+	lnbp21->config |= lnbp21->override_or;
+	lnbp21->config &= lnbp21->override_and;
+
+	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void lnbp21_release(struct dvb_frontend *fe)
+{
+	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+
+	/* LNBP power off */
+	lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	/* free data & call next release routine */
+	fe->ops.release = lnbp21->release_chain;
+	kfree(fe->misc_priv);
+	fe->misc_priv = NULL;
+	if (fe->ops.release)
+		fe->ops.release(fe);
+}
+
+int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+{
+	struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
+	if (!lnbp21)
+		return -ENOMEM;
+
+	/* default configuration */
+	lnbp21->config = LNBP21_ISEL;
+	lnbp21->i2c = i2c;
+	fe->misc_priv = lnbp21;
+
+	/* bits which should be forced to '1' */
+	lnbp21->override_or = override_set;
+
+	/* bits which should be forced to '0' */
+	lnbp21->override_and = ~override_clear;
+
+	/* detect if it is present or not */
+	if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+		kfree(lnbp21);
+		fe->misc_priv = NULL;
+		return -EIO;
+	}
+
+	/* install release callback */
+	lnbp21->release_chain = fe->ops.release;
+	fe->ops.release = lnbp21_release;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = lnbp21_set_voltage;
+	fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+
+	return 0;
+}
+EXPORT_SYMBOL(lnbp21_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21");
+MODULE_AUTHOR("Oliver Endriss");
+MODULE_LICENSE("GPL");

+ 4 - 98
drivers/media/dvb/frontends/lnbp21.h

@@ -27,7 +27,7 @@
 #ifndef _LNBP21_H
 #ifndef _LNBP21_H
 #define _LNBP21_H
 #define _LNBP21_H
 
 
-/* system register */
+/* system register bits */
 #define LNBP21_OLF	0x01
 #define LNBP21_OLF	0x01
 #define LNBP21_OTF	0x02
 #define LNBP21_OTF	0x02
 #define LNBP21_EN	0x04
 #define LNBP21_EN	0x04
@@ -37,103 +37,9 @@
 #define LNBP21_ISEL	0x40
 #define LNBP21_ISEL	0x40
 #define LNBP21_PCL	0x80
 #define LNBP21_PCL	0x80
 
 
-struct lnbp21 {
-	u8			config;
-	u8			override_or;
-	u8			override_and;
-	struct i2c_adapter	*i2c;
-	void			(*release_chain)(struct dvb_frontend* fe);
-};
+#include <linux/dvb/frontend.h>
 
 
-static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-	struct i2c_msg msg = {	.addr = 0x08, .flags = 0,
-				.buf = &lnbp21->config,
-				.len = sizeof(lnbp21->config) };
-
-	lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
-
-	switch(voltage) {
-	case SEC_VOLTAGE_OFF:
-		break;
-	case SEC_VOLTAGE_13:
-		lnbp21->config |= LNBP21_EN;
-		break;
-	case SEC_VOLTAGE_18:
-		lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	lnbp21->config |= lnbp21->override_or;
-	lnbp21->config &= lnbp21->override_and;
-
-	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
-{
-	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-	struct i2c_msg msg = {	.addr = 0x08, .flags = 0,
-				.buf = &lnbp21->config,
-				.len = sizeof(lnbp21->config) };
-
-	if (arg)
-		lnbp21->config |= LNBP21_LLC;
-	else
-		lnbp21->config &= ~LNBP21_LLC;
-
-	lnbp21->config |= lnbp21->override_or;
-	lnbp21->config &= lnbp21->override_and;
-
-	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static void lnbp21_exit(struct dvb_frontend *fe)
-{
-	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-
-	/* LNBP power off */
-	lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
-
-	/* free data & call next release routine */
-	fe->ops->release = lnbp21->release_chain;
-	kfree(fe->misc_priv);
-	fe->misc_priv = NULL;
-	if (fe->ops->release)
-		fe->ops->release(fe);
-}
-
-static int lnbp21_init(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
-{
-	struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
-
-	if (!lnbp21)
-		return -ENOMEM;
-
-	/* default configuration */
-	lnbp21->config = LNBP21_ISEL;
-
-	/* bits which should be forced to '1' */
-	lnbp21->override_or = override_set;
-
-	/* bits which should be forced to '0' */
-	lnbp21->override_and = ~override_clear;
-
-	/* install release callback */
-	lnbp21->release_chain = fe->ops->release;
-	fe->ops->release = lnbp21_exit;
-
-	/* override frontend ops */
-	fe->ops->set_voltage = lnbp21_set_voltage;
-	fe->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
-
-	lnbp21->i2c = i2c;
-	fe->misc_priv = lnbp21;
-
-	return lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
-}
+/* override_set and override_clear control which system register bits (above) to always set & clear */
+extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
 
 
 #endif
 #endif

+ 26 - 20
drivers/media/dvb/frontends/mt312.c

@@ -39,7 +39,6 @@
 
 
 struct mt312_state {
 struct mt312_state {
 	struct i2c_adapter* i2c;
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	/* configuration settings */
 	/* configuration settings */
 	const struct mt312_config* config;
 	const struct mt312_config* config;
 	struct dvb_frontend frontend;
 	struct dvb_frontend frontend;
@@ -277,12 +276,6 @@ static int mt312_initfe(struct dvb_frontend* fe)
 	if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0)
 	if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0)
 		return ret;
 		return ret;
 
 
-	if (state->config->pll_init) {
-		mt312_writereg(state, GPP_CTRL, 0x40);
-		state->config->pll_init(fe);
-		mt312_writereg(state, GPP_CTRL, 0x00);
-	}
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -477,16 +470,16 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
 
 
 	dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
 	dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
 
 
-	if ((p->frequency < fe->ops->info.frequency_min)
-	    || (p->frequency > fe->ops->info.frequency_max))
+	if ((p->frequency < fe->ops.info.frequency_min)
+	    || (p->frequency > fe->ops.info.frequency_max))
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if ((p->inversion < INVERSION_OFF)
 	if ((p->inversion < INVERSION_OFF)
 	    || (p->inversion > INVERSION_ON))
 	    || (p->inversion > INVERSION_ON))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if ((p->u.qpsk.symbol_rate < fe->ops->info.symbol_rate_min)
-	    || (p->u.qpsk.symbol_rate > fe->ops->info.symbol_rate_max))
+	if ((p->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min)
+	    || (p->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max))
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if ((p->u.qpsk.fec_inner < FEC_NONE)
 	if ((p->u.qpsk.fec_inner < FEC_NONE)
@@ -529,9 +522,10 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	mt312_writereg(state, GPP_CTRL, 0x40);
-	state->config->pll_set(fe, p);
-	mt312_writereg(state, GPP_CTRL, 0x00);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 
 	/* sr = (u16)(sr * 256.0 / 1000000.0) */
 	/* sr = (u16)(sr * 256.0 / 1000000.0) */
 	sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625);
 	sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625);
@@ -578,6 +572,17 @@ static int mt312_get_frontend(struct dvb_frontend* fe,
 	return 0;
 	return 0;
 }
 }
 
 
+static int mt312_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct mt312_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return mt312_writereg(state, GPP_CTRL, 0x40);
+	} else {
+		return mt312_writereg(state, GPP_CTRL, 0x00);
+	}
+}
+
 static int mt312_sleep(struct dvb_frontend* fe)
 static int mt312_sleep(struct dvb_frontend* fe)
 {
 {
 	struct mt312_state *state = fe->demodulator_priv;
 	struct mt312_state *state = fe->demodulator_priv;
@@ -633,6 +638,7 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
 
 
 	.init = mt312_initfe,
 	.init = mt312_initfe,
 	.sleep = mt312_sleep,
 	.sleep = mt312_sleep,
+	.i2c_gate_ctrl = mt312_i2c_gate_ctrl,
 
 
 	.set_frontend = mt312_set_frontend,
 	.set_frontend = mt312_set_frontend,
 	.get_frontend = mt312_get_frontend,
 	.get_frontend = mt312_get_frontend,
@@ -663,19 +669,22 @@ struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
 	/* setup the state */
 	/* setup the state */
 	state->config = config;
 	state->config = config;
 	state->i2c = i2c;
 	state->i2c = i2c;
-	memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
 
 
 	/* check if the demod is there */
 	/* check if the demod is there */
 	if (mt312_readreg(state, ID, &state->id) < 0)
 	if (mt312_readreg(state, ID, &state->id) < 0)
 		goto error;
 		goto error;
 
 
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
 	switch (state->id) {
 	switch (state->id) {
 	case ID_VP310:
 	case ID_VP310:
-		strcpy(state->ops.info.name, "Zarlink VP310 DVB-S");
+		strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
 		state->frequency = 90;
 		state->frequency = 90;
 		break;
 		break;
 	case ID_MT312:
 	case ID_MT312:
-		strcpy(state->ops.info.name, "Zarlink MT312 DVB-S");
+		strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
 		state->frequency = 60;
 		state->frequency = 60;
 		break;
 		break;
 	default:
 	default:
@@ -683,9 +692,6 @@ struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
 		goto error;
 		goto error;
 	}
 	}
 
 
-	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
-	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
 
 
 error:
 error:

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است