Переглянути джерело

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (583 commits)
  V4L/DVB (10130): use USB API functions rather than constants
  V4L/DVB (10129): dvb: remove deprecated use of RW_LOCK_UNLOCKED in frontends
  V4L/DVB (10128): modify V4L documentation to be a valid XHTML
  V4L/DVB (10127): stv06xx: Avoid having y unitialized
  V4L/DVB (10125): em28xx: Don't do AC97 vendor detection for i2s audio devices
  V4L/DVB (10124): em28xx: expand output formats available
  V4L/DVB (10123): em28xx: fix reversed definitions of I2S audio modes
  V4L/DVB (10122): em28xx: don't load em28xx-alsa for em2870 based devices
  V4L/DVB (10121): em28xx: remove worthless Pinnacle PCTV HD Mini 80e device profile
  V4L/DVB (10120): em28xx: remove redundant Pinnacle Dazzle DVC 100 profile
  V4L/DVB (10119): em28xx: fix corrupted XCLK value
  V4L/DVB (10118): zoran: fix warning for a variable not used
  V4L/DVB (10116): af9013: Fix gcc false warnings
  V4L/DVB (10111a): usbvideo.h: remove an useless blank line
  V4L/DVB (10111): quickcam_messenger.c: fix a warning
  V4L/DVB (10110): v4l2-ioctl: Fix warnings when using .unlocked_ioctl = __video_ioctl2
  V4L/DVB (10109): anysee: Fix usage of an unitialized function
  V4L/DVB (10104): uvcvideo: Add support for video output devices
  V4L/DVB (10102): uvcvideo: Ignore interrupt endpoint for built-in iSight webcams.
  V4L/DVB (10101): uvcvideo: Fix bulk URB processing when the header is erroneous
  ...
Linus Torvalds 16 роки тому
батько
коміт
f54a6ec0fd
100 змінених файлів з 11738 додано та 943 видалено
  1. 69 0
      Documentation/dvb/technisat.txt
  2. 27 16
      Documentation/video4linux/API.html
  3. 5 2
      Documentation/video4linux/CARDLIST.bttv
  4. 1 0
      Documentation/video4linux/CARDLIST.cx23885
  5. 4 1
      Documentation/video4linux/CARDLIST.cx88
  6. 5 4
      Documentation/video4linux/CARDLIST.em28xx
  7. 2 1
      Documentation/video4linux/CARDLIST.saa7134
  8. 3 5
      Documentation/video4linux/README.cx88
  9. 18 1
      Documentation/video4linux/gspca.txt
  10. 520 0
      Documentation/video4linux/v4l2-framework.txt
  11. 93 0
      drivers/media/common/ir-keymaps.c
  12. 1 1
      drivers/media/common/saa7146_fops.c
  13. 2 8
      drivers/media/common/saa7146_video.c
  14. 3 3
      drivers/media/common/tuners/mxl5005s.c
  15. 8 7
      drivers/media/common/tuners/tda827x.c
  16. 53 10
      drivers/media/common/tuners/tda8290.c
  17. 2 3
      drivers/media/common/tuners/tda9887.c
  18. 35 0
      drivers/media/common/tuners/tuner-xc2028.c
  19. 0 7
      drivers/media/common/tuners/xc5000.c
  20. 13 0
      drivers/media/dvb/Kconfig
  21. 1 0
      drivers/media/dvb/b2c2/Kconfig
  22. 1 2
      drivers/media/dvb/dm1105/dm1105.c
  23. 70 7
      drivers/media/dvb/dvb-core/dvb_frontend.c
  24. 133 1
      drivers/media/dvb/dvb-core/dvb_frontend.h
  25. 50 21
      drivers/media/dvb/dvb-core/dvbdev.c
  26. 1 0
      drivers/media/dvb/dvb-core/dvbdev.h
  27. 30 3
      drivers/media/dvb/dvb-usb/af9015.c
  28. 140 0
      drivers/media/dvb/dvb-usb/af9015.h
  29. 1 1
      drivers/media/dvb/dvb-usb/anysee.c
  30. 1 2
      drivers/media/dvb/dvb-usb/cinergyT2-core.c
  31. 5 5
      drivers/media/dvb/dvb-usb/cinergyT2.h
  32. 1 0
      drivers/media/dvb/dvb-usb/dvb-usb-ids.h
  33. 12 3
      drivers/media/dvb/dvb-usb/dw2102.c
  34. 114 26
      drivers/media/dvb/dvb-usb/gp8psk-fe.c
  35. 16 0
      drivers/media/dvb/dvb-usb/gp8psk.c
  36. 1 0
      drivers/media/dvb/dvb-usb/gp8psk.h
  37. 2 1
      drivers/media/dvb/dvb-usb/usb-urb.c
  38. 53 0
      drivers/media/dvb/frontends/Kconfig
  39. 10 0
      drivers/media/dvb/frontends/Makefile
  40. 7 7
      drivers/media/dvb/frontends/af9013.c
  41. 616 0
      drivers/media/dvb/frontends/cx24113.c
  42. 8 3
      drivers/media/dvb/frontends/cx24113.h
  43. 33 10
      drivers/media/dvb/frontends/cx24116.c
  44. 6 3
      drivers/media/dvb/frontends/dib7000p.h
  45. 6 6
      drivers/media/dvb/frontends/drx397xD.c
  46. 2 2
      drivers/media/dvb/frontends/drx397xD_fw.h
  47. 1 1
      drivers/media/dvb/frontends/dvb-pll.c
  48. 378 0
      drivers/media/dvb/frontends/lgdt3304.c
  49. 45 0
      drivers/media/dvb/frontends/lgdt3304.h
  50. 3 0
      drivers/media/dvb/frontends/s5h1411.c
  51. 216 0
      drivers/media/dvb/frontends/s921_core.c
  52. 114 0
      drivers/media/dvb/frontends/s921_core.h
  53. 190 0
      drivers/media/dvb/frontends/s921_module.c
  54. 49 0
      drivers/media/dvb/frontends/s921_module.h
  55. 0 1
      drivers/media/dvb/frontends/si21xx.c
  56. 1519 0
      drivers/media/dvb/frontends/stb0899_algo.c
  57. 287 0
      drivers/media/dvb/frontends/stb0899_cfg.h
  58. 1684 0
      drivers/media/dvb/frontends/stb0899_drv.c
  59. 162 0
      drivers/media/dvb/frontends/stb0899_drv.h
  60. 267 0
      drivers/media/dvb/frontends/stb0899_priv.h
  61. 2027 0
      drivers/media/dvb/frontends/stb0899_reg.h
  62. 545 0
      drivers/media/dvb/frontends/stb6100.c
  63. 115 0
      drivers/media/dvb/frontends/stb6100.h
  64. 108 0
      drivers/media/dvb/frontends/stb6100_cfg.h
  65. 230 0
      drivers/media/dvb/frontends/tda8261.c
  66. 55 0
      drivers/media/dvb/frontends/tda8261.h
  67. 84 0
      drivers/media/dvb/frontends/tda8261_cfg.h
  68. 3 0
      drivers/media/dvb/frontends/zl10353.c
  69. 110 0
      drivers/media/dvb/siano/sms-cards.c
  70. 13 0
      drivers/media/dvb/siano/sms-cards.h
  71. 78 0
      drivers/media/dvb/siano/smscoreapi.c
  72. 35 1
      drivers/media/dvb/siano/smscoreapi.h
  73. 54 2
      drivers/media/dvb/siano/smsdvb.c
  74. 45 0
      drivers/media/dvb/siano/smsusb.c
  75. 4 0
      drivers/media/dvb/ttpci/Kconfig
  76. 298 0
      drivers/media/dvb/ttpci/budget-av.c
  77. 311 0
      drivers/media/dvb/ttpci/budget-ci.c
  78. 1 0
      drivers/media/dvb/ttpci/budget.h
  79. 290 91
      drivers/media/radio/dsbr100.c
  80. 1 1
      drivers/media/radio/radio-aimslab.c
  81. 1 1
      drivers/media/radio/radio-cadet.c
  82. 1 1
      drivers/media/radio/radio-gemtek.c
  83. 91 32
      drivers/media/radio/radio-mr800.c
  84. 1 1
      drivers/media/radio/radio-rtrack2.c
  85. 1 1
      drivers/media/radio/radio-sf16fmi.c
  86. 42 6
      drivers/media/video/Kconfig
  87. 10 2
      drivers/media/video/Makefile
  88. 2 3
      drivers/media/video/arv.c
  89. 0 274
      drivers/media/video/bt8xx/bt832.c
  90. 0 305
      drivers/media/video/bt8xx/bt832.h
  91. 54 18
      drivers/media/video/bt8xx/bttv-cards.c
  92. 3 4
      drivers/media/video/bt8xx/bttv-gpio.c
  93. 7 3
      drivers/media/video/bt8xx/bttv.h
  94. 1 1
      drivers/media/video/bt8xx/bttvp.h
  95. 2 3
      drivers/media/video/bw-qcam.c
  96. 3 4
      drivers/media/video/c-qcam.c
  97. 4 5
      drivers/media/video/cpia.c
  98. 1 1
      drivers/media/video/cpia2/cpia2_core.c
  99. 1 1
      drivers/media/video/cpia2/cpia2_usb.c
  100. 7 8
      drivers/media/video/cpia2/cpia2_v4l.c

+ 69 - 0
Documentation/dvb/technisat.txt

@@ -0,0 +1,69 @@
+How to set up the Technisat devices
+===================================
+
+1) Find out what device you have
+================================
+
+First start your linux box with a shipped kernel:
+lspci -vvv for a PCI device (lsusb -vvv for an USB device) will show you for example:
+02:0b.0 Network controller: Techsan Electronics Co Ltd B2C2 FlexCopII DVB chip / Technisat SkyStar2 DVB card (rev 02)
+
+dmesg | grep frontend may show you for example:
+DVB: registering frontend 0 (Conexant CX24123/CX24109)...
+
+2) Kernel compilation:
+======================
+
+If the Technisat is the only TV device in your box get rid of unnecessary modules and check this one:
+"Multimedia devices" => "Customise analog and hybrid tuner modules to build"
+In this directory uncheck every driver which is activated there.
+
+Then please activate:
+2a) Main module part:
+
+a.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters"
+b.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Technisat/B2C2 Air/Sky/Cable2PC PCI" in case of a PCI card OR
+c.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Technisat/B2C2 Air/Sky/Cable2PC USB" in case of an USB 1.1 adapter
+d.)"Multimedia devices" => "DVB/ATSC adapters" => "Technisat/B2C2 FlexcopII(b) and FlexCopIII adapters" => "Enable debug for the B2C2 FlexCop drivers"
+Notice: d.) is helpful for troubleshooting
+
+2b) Frontend module part:
+
+1.) Revision 2.3:
+a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
+b.)"Multimedia devices" => "Customise DVB frontends" => "Zarlink VP310/MT312/ZL10313 based"
+
+2.) Revision 2.6:
+a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
+b.)"Multimedia devices" => "Customise DVB frontends" => "ST STV0299 based"
+
+3.) Revision 2.7:
+a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
+b.)"Multimedia devices" => "Customise DVB frontends" => "Samsung S5H1420 based"
+c.)"Multimedia devices" => "Customise DVB frontends" => "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
+d.)"Multimedia devices" => "Customise DVB frontends" => "ISL6421 SEC controller"
+
+4.) Revision 2.8:
+a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
+b.)"Multimedia devices" => "Customise DVB frontends" => "Conexant CX24113/CX24128 tuner for DVB-S/DSS"
+c.)"Multimedia devices" => "Customise DVB frontends" => "Conexant CX24123 based"
+d.)"Multimedia devices" => "Customise DVB frontends" => "ISL6421 SEC controller"
+
+5.) DVB-T card:
+a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
+b.)"Multimedia devices" => "Customise DVB frontends" => "Zarlink MT352 based"
+
+6.) DVB-C card:
+a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
+b.)"Multimedia devices" => "Customise DVB frontends" => "ST STV0297 based"
+
+7.) ATSC card 1st generation:
+a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
+b.)"Multimedia devices" => "Customise DVB frontends" => "Broadcom BCM3510"
+
+8.) ATSC card 2nd generation:
+a.)"Multimedia devices" => "Customise DVB frontends" => "Customise the frontend modules to build"
+b.)"Multimedia devices" => "Customise DVB frontends" => "NxtWave Communications NXT2002/NXT2004 based"
+c.)"Multimedia devices" => "Customise DVB frontends" => "LG Electronics LGDT3302/LGDT3303 based"
+
+Author: Uwe Bugla <uwe.bugla@gmx.de> December 2008

+ 27 - 16
Documentation/video4linux/API.html

@@ -1,16 +1,27 @@
-<TITLE>V4L API</TITLE>
-<H1>Video For Linux APIs</H1>
-<table border=0>
-<tr>
-<td>
-<A HREF=http://www.linuxtv.org/downloads/video4linux/API/V4L1_API.html>
-V4L original API</a>
-</td><td>
-Obsoleted by V4L2 API
-</td></tr><tr><td>
-<A HREF=http://www.linuxtv.org/downloads/video4linux/API/V4L2_API>
-V4L2 API</a>
-</td><td>
-Should be used for new projects
-</td></tr>
-</table>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+ <head>
+  <meta content="text/html;charset=ISO-8859-2" http-equiv="Content-Type" />
+  <title>V4L API</title>
+ </head>
+ <body>
+  <h1>Video For Linux APIs</h1>
+  <table border="0">
+   <tr>
+    <td>
+     <a href="http://www.linuxtv.org/downloads/video4linux/API/V4L1_API.html">V4L original API</a>
+    </td>
+    <td>
+     Obsoleted by V4L2 API
+    </td>
+   </tr>
+   <tr>
+    <td>
+     <a href="http://www.linuxtv.org/downloads/video4linux/API/V4L2_API">V4L2 API</a>
+    </td>
+    <td>Should be used for new projects
+    </td>
+   </tr>
+  </table>
+ </body>
+</html>

+ 5 - 2
Documentation/video4linux/CARDLIST.bttv

@@ -104,8 +104,8 @@
 103 -> Grand X-Guard / Trust 814PCI                        [0304:0102]
 104 -> Nebula Electronics DigiTV                           [0071:0101]
 105 -> ProVideo PV143                                      [aa00:1430,aa00:1431,aa00:1432,aa00:1433,aa03:1433]
-106 -> PHYTEC VD-009-X1 MiniDIN (bt878)
-107 -> PHYTEC VD-009-X1 Combi (bt878)
+106 -> PHYTEC VD-009-X1 VD-011 MiniDIN (bt878)
+107 -> PHYTEC VD-009-X1 VD-011 Combi (bt878)
 108 -> PHYTEC VD-009 MiniDIN (bt878)
 109 -> PHYTEC VD-009 Combi (bt878)
 110 -> IVC-100                                             [ff00:a132]
@@ -151,3 +151,6 @@
 150 -> Geovision GV-600                                    [008a:763c]
 151 -> Kozumi KTV-01C
 152 -> Encore ENL TV-FM-2                                  [1000:1801]
+153 -> PHYTEC VD-012 (bt878)
+154 -> PHYTEC VD-012-X1 (bt878)
+155 -> PHYTEC VD-012-X2 (bt878)

+ 1 - 0
Documentation/video4linux/CARDLIST.cx23885

@@ -11,3 +11,4 @@
  10 -> DViCO FusionHDTV7 Dual Express                      [18ac:d618]
  11 -> DViCO FusionHDTV DVB-T Dual Express                 [18ac:db78]
  12 -> Leadtek Winfast PxDVR3200 H                         [107d:6681]
+ 13 -> Compro VideoMate E650F                              [185b:e800]

+ 4 - 1
Documentation/video4linux/CARDLIST.cx88

@@ -2,7 +2,7 @@
   1 -> Hauppauge WinTV 34xxx models                        [0070:3400,0070:3401]
   2 -> GDI Black Gold                                      [14c7:0106,14c7:0107]
   3 -> PixelView                                           [1554:4811]
-  4 -> ATI TV Wonder Pro                                   [1002:00f8]
+  4 -> ATI TV Wonder Pro                                   [1002:00f8,1002:00f9]
   5 -> Leadtek Winfast 2000XP Expert                       [107d:6611,107d:6613]
   6 -> AverTV Studio 303 (M126)                            [1461:000b]
   7 -> MSI TV-@nywhere Master                              [1462:8606]
@@ -74,3 +74,6 @@
  73 -> TeVii S420 DVB-S                                    [d420:9022]
  74 -> Prolink Pixelview Global Extreme                    [1554:4976]
  75 -> PROF 7300 DVB-S/S2                                  [B033:3033]
+ 76 -> SATTRADE ST4200 DVB-S/S2                            [b200:4200]
+ 77 -> TBS 8910 DVB-S                                      [8910:8888]
+ 78 -> Prof 6200 DVB-S                                     [b022:3022]

+ 5 - 4
Documentation/video4linux/CARDLIST.em28xx

@@ -1,5 +1,5 @@
   0 -> Unknown EM2800 video grabber             (em2800)        [eb1a:2800]
-  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2820,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
+  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
   2 -> Terratec Cinergy 250 USB                 (em2820/em2840) [0ccd:0036]
   3 -> Pinnacle PCTV USB 2                      (em2820/em2840) [2304:0208]
   4 -> Hauppauge WinTV USB 2                    (em2820/em2840) [2040:4200,2040:4201]
@@ -12,9 +12,9 @@
  11 -> Terratec Hybrid XS                       (em2880)        [0ccd:0042]
  12 -> Kworld PVR TV 2800 RF                    (em2820/em2840)
  13 -> Terratec Prodigy XS                      (em2880)        [0ccd:0047]
- 14 -> Pixelview Prolink PlayTV USB 2.0         (em2820/em2840) [eb1a:2821]
+ 14 -> Pixelview Prolink PlayTV USB 2.0         (em2820/em2840)
  15 -> V-Gear PocketTV                          (em2800)
- 16 -> Hauppauge WinTV HVR 950                  (em2883)        [2040:6513,2040:6517,2040:651b,2040:651f]
+ 16 -> Hauppauge WinTV HVR 950                  (em2883)        [2040:6513,2040:6517,2040:651b]
  17 -> Pinnacle PCTV HD Pro Stick               (em2880)        [2304:0227]
  18 -> Hauppauge WinTV HVR 900 (R2)             (em2880)        [2040:6502]
  19 -> PointNix Intra-Oral Camera               (em2860)
@@ -27,7 +27,6 @@
  26 -> Hercules Smart TV USB 2.0                (em2820/em2840)
  27 -> Pinnacle PCTV USB 2 (Philips FM1216ME)   (em2820/em2840)
  28 -> Leadtek Winfast USB II Deluxe            (em2820/em2840)
- 29 -> Pinnacle Dazzle DVC 100                  (em2820/em2840)
  30 -> Videology 20K14XUSB USB2.0               (em2820/em2840)
  31 -> Usbgear VD204v9                          (em2821)
  32 -> Supercomp USB 2.0 TV                     (em2821)
@@ -57,3 +56,5 @@
  56 -> Pinnacle Hybrid Pro (2)                  (em2882)        [2304:0226]
  57 -> Kworld PlusTV HD Hybrid 330              (em2883)        [eb1a:a316]
  58 -> Compro VideoMate ForYou/Stereo           (em2820/em2840) [185b:2041]
+ 60 -> Hauppauge WinTV HVR 850                  (em2883)        [2040:651f]
+ 61 -> Pixelview PlayTV Box 4 USB 2.0           (em2820/em2840)

+ 2 - 1
Documentation/video4linux/CARDLIST.saa7134

@@ -10,7 +10,7 @@
   9 -> Medion 5044
  10 -> Kworld/KuroutoShikou SAA7130-TVPCI
  11 -> Terratec Cinergy 600 TV                  [153b:1143]
- 12 -> Medion 7134                              [16be:0003]
+ 12 -> Medion 7134                              [16be:0003,16be:5000]
  13 -> Typhoon TV+Radio 90031
  14 -> ELSA EX-VISION 300TV                     [1048:226b]
  15 -> ELSA EX-VISION 500TV                     [1048:226a]
@@ -151,3 +151,4 @@
 150 -> Zogis Real Angel 220
 151 -> ADS Tech Instant HDTV                    [1421:0380]
 152 -> Asus Tiger Rev:1.00                      [1043:4857]
+153 -> Kworld Plus TV Analog Lite PCI           [17de:7128]

+ 3 - 5
Documentation/video4linux/README.cx88

@@ -1,4 +1,3 @@
-
 cx8800 release notes
 ====================
 
@@ -10,21 +9,20 @@ current status
 
 video
 	- Basically works.
-	- Some minor image quality glitches.
-	- For now only capture, overlay support isn't completed yet.
+	- For now, only capture and read(). Overlay isn't supported.
 
 audio
 	- The chip specs for the on-chip TV sound decoder are next
 	  to useless :-/
 	- Neverless the builtin TV sound decoder starts working now,
-	  at least for PAL-BG.  Other TV norms need other code ...
+	  at least for some standards.
 	  FOR ANY REPORTS ON THIS PLEASE MENTION THE TV NORM YOU ARE
 	  USING.
 	- Most tuner chips do provide mono sound, which may or may not
 	  be useable depending on the board design.  With the Hauppauge
 	  cards it works, so there is mono sound available as fallback.
 	- audio data dma (i.e. recording without loopback cable to the
-	  sound card) should be possible, but there is no code yet ...
+	  sound card) is supported via cx88-alsa.
 
 vbi
 	- Code present. Works for NTSC closed caption. PAL and other

+ 18 - 1
Documentation/video4linux/gspca.txt

@@ -50,9 +50,14 @@ ov519		045e:028c	Micro$oft xbox cam
 spca508		0461:0815	Micro Innovation IC200
 sunplus		0461:0821	Fujifilm MV-1
 zc3xx		0461:0a00	MicroInnovation WebCam320
+stv06xx		046d:0840	QuickCam Express
+stv06xx		046d:0850	LEGO cam / QuickCam Web
+stv06xx		046d:0870	Dexxa WebCam USB
 spca500		046d:0890	Logitech QuickCam traveler
 vc032x		046d:0892	Logitech Orbicam
 vc032x		046d:0896	Logitech Orbicam
+vc032x		046d:0897	Logitech QuickCam for Dell notebooks
+zc3xx		046d:089d	Logitech QuickCam E2500
 zc3xx		046d:08a0	Logitech QC IM
 zc3xx		046d:08a1	Logitech QC IM 0x08A1 +sound
 zc3xx		046d:08a2	Labtec Webcam Pro
@@ -169,6 +174,9 @@ spca500		06bd:0404	Agfa CL20
 spca500		06be:0800	Optimedia
 sunplus		06d6:0031	Trust 610 LCD PowerC@m Zoom
 spca506		06e1:a190	ADS Instant VCD
+ov534		06f8:3002	Hercules Blog Webcam
+ov534		06f8:3003	Hercules Dualpix HD Weblog
+sonixj		06f8:3004	Hercules Classic Silver
 spca508		0733:0110	ViewQuest VQ110
 spca508		0130:0130	Clone Digital Webcam 11043
 spca501		0733:0401	Intel Create and Share
@@ -199,7 +207,8 @@ sunplus		08ca:2050	Medion MD 41437
 sunplus		08ca:2060	Aiptek PocketDV5300
 tv8532		0923:010f	ICM532 cams
 mars		093a:050f	Mars-Semi Pc-Camera
-pac207		093a:2460	PAC207 Qtec Webcam 100
+pac207		093a:2460	Qtec Webcam 100
+pac207		093a:2461	HP Webcam
 pac207		093a:2463	Philips SPC 220 NC
 pac207		093a:2464	Labtec Webcam 1200
 pac207		093a:2468	PAC207
@@ -213,10 +222,13 @@ pac7311		093a:2603	PAC7312
 pac7311		093a:2608	Trust WB-3300p
 pac7311		093a:260e	Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
 pac7311		093a:260f	SnakeCam
+pac7311		093a:2620	Apollo AC-905
 pac7311		093a:2621	PAC731x
+pac7311		093a:2622	Genius Eye 312
 pac7311		093a:2624	PAC7302
 pac7311		093a:2626	Labtec 2200
 pac7311		093a:262a	Webcam 300k
+pac7311		093a:262c	Philips SPC 230 NC
 zc3xx		0ac8:0302	Z-star Vimicro zc0302
 vc032x		0ac8:0321	Vimicro generic vc0321
 vc032x		0ac8:0323	Vimicro Vc0323
@@ -249,11 +261,13 @@ sonixj		0c45:60c0	Sangha Sn535
 sonixj		0c45:60ec	SN9C105+MO4000
 sonixj		0c45:60fb	Surfer NoName
 sonixj		0c45:60fc	LG-LIC300
+sonixj		0c45:60fe	Microdia Audio
 sonixj		0c45:6128	Microdia/Sonix SNP325
 sonixj		0c45:612a	Avant Camera
 sonixj		0c45:612c	Typhoon Rasy Cam 1.3MPix
 sonixj		0c45:6130	Sonix Pccam
 sonixj		0c45:6138	Sn9c120 Mo4000
+sonixj		0c45:613a	Microdia Sonix PC Camera
 sonixj		0c45:613b	Surfer SN-206
 sonixj		0c45:613c	Sonix Pccam168
 sonixj		0c45:6143	Sonix Pccam168
@@ -263,6 +277,9 @@ etoms		102c:6251	Qcam xxxxxx VGA
 zc3xx		10fd:0128	Typhoon Webshot II USB 300k 0x0128
 spca561		10fd:7e50	FlyCam Usb 100
 zc3xx		10fd:8050	Typhoon Webshot II USB 300k
+ov534		1415:2000	Sony HD Eye for PS3 (SLEH 00201)
+pac207		145f:013a	Trust WB-1300N
+vc032x		15b8:6002	HP 2.0 Megapixel rz406aa
 spca501		1776:501c	Arowana 300K CMOS Camera
 t613		17a1:0128	TASCORP JPEG Webcam, NGS Cyclops
 vc032x		17ef:4802	Lenovo Vc0323+MI1310_SOC

+ 520 - 0
Documentation/video4linux/v4l2-framework.txt

@@ -0,0 +1,520 @@
+Overview of the V4L2 driver framework
+=====================================
+
+This text documents the various structures provided by the V4L2 framework and
+their relationships.
+
+
+Introduction
+------------
+
+The V4L2 drivers tend to be very complex due to the complexity of the
+hardware: most devices have multiple ICs, export multiple device nodes in
+/dev, and create also non-V4L2 devices such as DVB, ALSA, FB, I2C and input
+(IR) devices.
+
+Especially the fact that V4L2 drivers have to setup supporting ICs to
+do audio/video muxing/encoding/decoding makes it more complex than most.
+Usually these ICs are connected to the main bridge driver through one or
+more I2C busses, but other busses can also be used. Such devices are
+called 'sub-devices'.
+
+For a long time the framework was limited to the video_device struct for
+creating V4L device nodes and video_buf for handling the video buffers
+(note that this document does not discuss the video_buf framework).
+
+This meant that all drivers had to do the setup of device instances and
+connecting to sub-devices themselves. Some of this is quite complicated
+to do right and many drivers never did do it correctly.
+
+There is also a lot of common code that could never be refactored due to
+the lack of a framework.
+
+So this framework sets up the basic building blocks that all drivers
+need and this same framework should make it much easier to refactor
+common code into utility functions shared by all drivers.
+
+
+Structure of a driver
+---------------------
+
+All drivers have the following structure:
+
+1) A struct for each device instance containing the device state.
+
+2) A way of initializing and commanding sub-devices (if any).
+
+3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX, /dev/radioX and
+   /dev/vtxX) and keeping track of device-node specific data.
+
+4) Filehandle-specific structs containing per-filehandle data.
+
+This is a rough schematic of how it all relates:
+
+    device instances
+      |
+      +-sub-device instances
+      |
+      \-V4L2 device nodes
+	  |
+	  \-filehandle instances
+
+
+Structure of the framework
+--------------------------
+
+The framework closely resembles the driver structure: it has a v4l2_device
+struct for the device instance data, a v4l2_subdev struct to refer to
+sub-device instances, the video_device struct stores V4L2 device node data
+and in the future a v4l2_fh struct will keep track of filehandle instances
+(this is not yet implemented).
+
+
+struct v4l2_device
+------------------
+
+Each device instance is represented by a struct v4l2_device (v4l2-device.h).
+Very simple devices can just allocate this struct, but most of the time you
+would embed this struct inside a larger struct.
+
+You must register the device instance:
+
+	v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
+
+Registration will initialize the v4l2_device struct and link dev->driver_data
+to v4l2_dev. Registration will also set v4l2_dev->name to a value derived from
+dev (driver name followed by the bus_id, to be precise). You may change the
+name after registration if you want.
+
+The first 'dev' argument is normally the struct device pointer of a pci_dev,
+usb_device or platform_device.
+
+You unregister with:
+
+	v4l2_device_unregister(struct v4l2_device *v4l2_dev);
+
+Unregistering will also automatically unregister all subdevs from the device.
+
+Sometimes you need to iterate over all devices registered by a specific
+driver. This is usually the case if multiple device drivers use the same
+hardware. E.g. the ivtvfb driver is a framebuffer driver that uses the ivtv
+hardware. The same is true for alsa drivers for example.
+
+You can iterate over all registered devices as follows:
+
+static int callback(struct device *dev, void *p)
+{
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+
+	/* test if this device was inited */
+	if (v4l2_dev == NULL)
+		return 0;
+	...
+	return 0;
+}
+
+int iterate(void *p)
+{
+	struct device_driver *drv;
+	int err;
+
+	/* Find driver 'ivtv' on the PCI bus.
+	   pci_bus_type is a global. For USB busses use usb_bus_type. */
+	drv = driver_find("ivtv", &pci_bus_type);
+	/* iterate over all ivtv device instances */
+	err = driver_for_each_device(drv, NULL, p, callback);
+	put_driver(drv);
+	return err;
+}
+
+Sometimes you need to keep a running counter of the device instance. This is
+commonly used to map a device instance to an index of a module option array.
+
+The recommended approach is as follows:
+
+static atomic_t drv_instance = ATOMIC_INIT(0);
+
+static int __devinit drv_probe(struct pci_dev *dev,
+				const struct pci_device_id *pci_id)
+{
+	...
+	state->instance = atomic_inc_return(&drv_instance) - 1;
+}
+
+
+struct v4l2_subdev
+------------------
+
+Many drivers need to communicate with sub-devices. These devices can do all
+sort of tasks, but most commonly they handle audio and/or video muxing,
+encoding or decoding. For webcams common sub-devices are sensors and camera
+controllers.
+
+Usually these are I2C devices, but not necessarily. In order to provide the
+driver with a consistent interface to these sub-devices the v4l2_subdev struct
+(v4l2-subdev.h) was created.
+
+Each sub-device driver must have a v4l2_subdev struct. This struct can be
+stand-alone for simple sub-devices or it might be embedded in a larger struct
+if more state information needs to be stored. Usually there is a low-level
+device struct (e.g. i2c_client) that contains the device data as setup
+by the kernel. It is recommended to store that pointer in the private
+data of v4l2_subdev using v4l2_set_subdevdata(). That makes it easy to go
+from a v4l2_subdev to the actual low-level bus-specific device data.
+
+You also need a way to go from the low-level struct to v4l2_subdev. For the
+common i2c_client struct the i2c_set_clientdata() call is used to store a
+v4l2_subdev pointer, for other busses you may have to use other methods.
+
+From the bridge driver perspective you load the sub-device module and somehow
+obtain the v4l2_subdev pointer. For i2c devices this is easy: you call
+i2c_get_clientdata(). For other busses something similar needs to be done.
+Helper functions exists for sub-devices on an I2C bus that do most of this
+tricky work for you.
+
+Each v4l2_subdev contains function pointers that sub-device drivers can
+implement (or leave NULL if it is not applicable). Since sub-devices can do
+so many different things and you do not want to end up with a huge ops struct
+of which only a handful of ops are commonly implemented, the function pointers
+are sorted according to category and each category has its own ops struct.
+
+The top-level ops struct contains pointers to the category ops structs, which
+may be NULL if the subdev driver does not support anything from that category.
+
+It looks like this:
+
+struct v4l2_subdev_core_ops {
+	int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip);
+	int (*log_status)(struct v4l2_subdev *sd);
+	int (*init)(struct v4l2_subdev *sd, u32 val);
+	...
+};
+
+struct v4l2_subdev_tuner_ops {
+	...
+};
+
+struct v4l2_subdev_audio_ops {
+	...
+};
+
+struct v4l2_subdev_video_ops {
+	...
+};
+
+struct v4l2_subdev_ops {
+	const struct v4l2_subdev_core_ops  *core;
+	const struct v4l2_subdev_tuner_ops *tuner;
+	const struct v4l2_subdev_audio_ops *audio;
+	const struct v4l2_subdev_video_ops *video;
+};
+
+The core ops are common to all subdevs, the other categories are implemented
+depending on the sub-device. E.g. a video device is unlikely to support the
+audio ops and vice versa.
+
+This setup limits the number of function pointers while still making it easy
+to add new ops and categories.
+
+A sub-device driver initializes the v4l2_subdev struct using:
+
+	v4l2_subdev_init(subdev, &ops);
+
+Afterwards you need to initialize subdev->name with a unique name and set the
+module owner. This is done for you if you use the i2c helper functions.
+
+A device (bridge) driver needs to register the v4l2_subdev with the
+v4l2_device:
+
+	int err = v4l2_device_register_subdev(device, subdev);
+
+This can fail if the subdev module disappeared before it could be registered.
+After this function was called successfully the subdev->dev field points to
+the v4l2_device.
+
+You can unregister a sub-device using:
+
+	v4l2_device_unregister_subdev(subdev);
+
+Afterwards the subdev module can be unloaded and subdev->dev == NULL.
+
+You can call an ops function either directly:
+
+	err = subdev->ops->core->g_chip_ident(subdev, &chip);
+
+but it is better and easier to use this macro:
+
+	err = v4l2_subdev_call(subdev, core, g_chip_ident, &chip);
+
+The macro will to the right NULL pointer checks and returns -ENODEV if subdev
+is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_chip_ident is
+NULL, or the actual result of the subdev->ops->core->g_chip_ident ops.
+
+It is also possible to call all or a subset of the sub-devices:
+
+	v4l2_device_call_all(dev, 0, core, g_chip_ident, &chip);
+
+Any subdev that does not support this ops is skipped and error results are
+ignored. If you want to check for errors use this:
+
+	err = v4l2_device_call_until_err(dev, 0, core, g_chip_ident, &chip);
+
+Any error except -ENOIOCTLCMD will exit the loop with that error. If no
+errors (except -ENOIOCTLCMD) occured, then 0 is returned.
+
+The second argument to both calls is a group ID. If 0, then all subdevs are
+called. If non-zero, then only those whose group ID match that value will
+be called. Before a bridge driver registers a subdev it can set subdev->grp_id
+to whatever value it wants (it's 0 by default). This value is owned by the
+bridge driver and the sub-device driver will never modify or use it.
+
+The group ID gives the bridge driver more control how callbacks are called.
+For example, there may be multiple audio chips on a board, each capable of
+changing the volume. But usually only one will actually be used when the
+user want to change the volume. You can set the group ID for that subdev to
+e.g. AUDIO_CONTROLLER and specify that as the group ID value when calling
+v4l2_device_call_all(). That ensures that it will only go to the subdev
+that needs it.
+
+The advantage of using v4l2_subdev is that it is a generic struct and does
+not contain any knowledge about the underlying hardware. So a driver might
+contain several subdevs that use an I2C bus, but also a subdev that is
+controlled through GPIO pins. This distinction is only relevant when setting
+up the device, but once the subdev is registered it is completely transparent.
+
+
+I2C sub-device drivers
+----------------------
+
+Since these drivers are so common, special helper functions are available to
+ease the use of these drivers (v4l2-common.h).
+
+The recommended method of adding v4l2_subdev support to an I2C driver is to
+embed the v4l2_subdev struct into the state struct that is created for each
+I2C device instance. Very simple devices have no state struct and in that case
+you can just create a v4l2_subdev directly.
+
+A typical state struct would look like this (where 'chipname' is replaced by
+the name of the chip):
+
+struct chipname_state {
+	struct v4l2_subdev sd;
+	...  /* additional state fields */
+};
+
+Initialize the v4l2_subdev struct as follows:
+
+	v4l2_i2c_subdev_init(&state->sd, client, subdev_ops);
+
+This function will fill in all the fields of v4l2_subdev and ensure that the
+v4l2_subdev and i2c_client both point to one another.
+
+You should also add a helper inline function to go from a v4l2_subdev pointer
+to a chipname_state struct:
+
+static inline struct chipname_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct chipname_state, sd);
+}
+
+Use this to go from the v4l2_subdev struct to the i2c_client struct:
+
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+And this to go from an i2c_client to a v4l2_subdev struct:
+
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+Finally you need to make a command function to make driver->command()
+call the right subdev_ops functions:
+
+static int subdev_command(struct i2c_client *client, unsigned cmd, void *arg)
+{
+	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
+}
+
+If driver->command is never used then you can leave this out. Eventually the
+driver->command usage should be removed from v4l.
+
+Make sure to call v4l2_device_unregister_subdev(sd) when the remove() callback
+is called. This will unregister the sub-device from the bridge driver. It is
+safe to call this even if the sub-device was never registered.
+
+
+The bridge driver also has some helper functions it can use:
+
+struct v4l2_subdev *sd = v4l2_i2c_new_subdev(adapter, "module_foo", "chipid", 0x36);
+
+This loads the given module (can be NULL if no module needs to be loaded) and
+calls i2c_new_device() with the given i2c_adapter and chip/address arguments.
+If all goes well, then it registers the subdev with the v4l2_device. It gets
+the v4l2_device by calling i2c_get_adapdata(adapter), so you should make sure
+that adapdata is set to v4l2_device when you setup the i2c_adapter in your
+driver.
+
+You can also use v4l2_i2c_new_probed_subdev() which is very similar to
+v4l2_i2c_new_subdev(), except that it has an array of possible I2C addresses
+that it should probe. Internally it calls i2c_new_probed_device().
+
+Both functions return NULL if something went wrong.
+
+
+struct video_device
+-------------------
+
+The actual device nodes in the /dev directory are created using the
+video_device struct (v4l2-dev.h). This struct can either be allocated
+dynamically or embedded in a larger struct.
+
+To allocate it dynamically use:
+
+	struct video_device *vdev = video_device_alloc();
+
+	if (vdev == NULL)
+		return -ENOMEM;
+
+	vdev->release = video_device_release;
+
+If you embed it in a larger struct, then you must set the release()
+callback to your own function:
+
+	struct video_device *vdev = &my_vdev->vdev;
+
+	vdev->release = my_vdev_release;
+
+The release callback must be set and it is called when the last user
+of the video device exits.
+
+The default video_device_release() callback just calls kfree to free the
+allocated memory.
+
+You should also set these fields:
+
+- parent: set to the parent device (same device as was used to register
+  v4l2_device).
+- name: set to something descriptive and unique.
+- fops: set to the file_operations struct.
+- ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
+  (highly recommended to use this and it might become compulsory in the
+  future!), then set this to your v4l2_ioctl_ops struct.
+
+If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to
+__video_ioctl2 or .ioctl to video_ioctl2 in your file_operations struct.
+
+
+video_device registration
+-------------------------
+
+Next you register the video device: this will create the character device
+for you.
+
+	err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (err) {
+		video_device_release(vdev); // or kfree(my_vdev);
+		return err;
+	}
+
+Which device is registered depends on the type argument. The following
+types exist:
+
+VFL_TYPE_GRABBER: videoX for video input/output devices
+VFL_TYPE_VBI: vbiX for vertical blank data (i.e. closed captions, teletext)
+VFL_TYPE_RADIO: radioX for radio tuners
+VFL_TYPE_VTX: vtxX for teletext devices (deprecated, don't use)
+
+The last argument gives you a certain amount of control over the device
+kernel number used (i.e. the X in videoX). Normally you will pass -1 to
+let the v4l2 framework pick the first free number. But if a driver creates
+many devices, then it can be useful to have different video devices in
+separate ranges. For example, video capture devices start at 0, video
+output devices start at 16.
+
+So you can use the last argument to specify a minimum kernel number and
+the v4l2 framework will try to pick the first free number that is equal
+or higher to what you passed. If that fails, then it will just pick the
+first free number.
+
+Whenever a device node is created some attributes are also created for you.
+If you look in /sys/class/video4linux you see the devices. Go into e.g.
+video0 and you will see 'name' and 'index' attributes. The 'name' attribute
+is the 'name' field of the video_device struct. The 'index' attribute is
+a device node index that can be assigned by the driver, or that is calculated
+for you.
+
+If you call video_register_device(), then the index is just increased by
+1 for each device node you register. The first video device node you register
+always starts off with 0.
+
+Alternatively you can call video_register_device_index() which is identical
+to video_register_device(), but with an extra index argument. Here you can
+pass a specific index value (between 0 and 31) that should be used.
+
+Users can setup udev rules that utilize the index attribute to make fancy
+device names (e.g. 'mpegX' for MPEG video capture device nodes).
+
+After the device was successfully registered, then you can use these fields:
+
+- vfl_type: the device type passed to video_register_device.
+- minor: the assigned device minor number.
+- num: the device kernel number (i.e. the X in videoX).
+- index: the device index number (calculated or set explicitly using
+  video_register_device_index).
+
+If the registration failed, then you need to call video_device_release()
+to free the allocated video_device struct, or free your own struct if the
+video_device was embedded in it. The vdev->release() callback will never
+be called if the registration failed, nor should you ever attempt to
+unregister the device if the registration failed.
+
+
+video_device cleanup
+--------------------
+
+When the video device nodes have to be removed, either during the unload
+of the driver or because the USB device was disconnected, then you should
+unregister them:
+
+	video_unregister_device(vdev);
+
+This will remove the device nodes from sysfs (causing udev to remove them
+from /dev).
+
+After video_unregister_device() returns no new opens can be done.
+
+However, in the case of USB devices some application might still have one
+of these device nodes open. You should block all new accesses to read,
+write, poll, etc. except possibly for certain ioctl operations like
+queueing buffers.
+
+When the last user of the video device node exits, then the vdev->release()
+callback is called and you can do the final cleanup there.
+
+
+video_device helper functions
+-----------------------------
+
+There are a few useful helper functions:
+
+You can set/get driver private data in the video_device struct using:
+
+void *video_get_drvdata(struct video_device *dev);
+void video_set_drvdata(struct video_device *dev, void *data);
+
+Note that you can safely call video_set_drvdata() before calling
+video_register_device().
+
+And this function:
+
+struct video_device *video_devdata(struct file *file);
+
+returns the video_device belonging to the file struct.
+
+The final helper function combines video_get_drvdata with
+video_devdata:
+
+void *video_drvdata(struct file *file);
+
+You can go from a video_device struct to the v4l2_device struct using:
+
+struct v4l2_device *v4l2_dev = dev_get_drvdata(vdev->parent);
+

+ 93 - 0
drivers/media/common/ir-keymaps.c

@@ -2391,6 +2391,67 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = {
 };
 EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel);
 
+/* Kworld Plus TV Analog Lite PCI IR
+   Mauro Carvalho Chehab <mchehab@infradead.org>
+ */
+IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = {
+	[0x0c] = KEY_PROG1,		/* Kworld key */
+	[0x16] = KEY_CLOSECD,		/* -> ) */
+	[0x1d] = KEY_POWER2,
+
+	[0x00] = KEY_1,
+	[0x01] = KEY_2,
+	[0x02] = KEY_3,			/* Two keys have the same code: 3 and left */
+	[0x03] = KEY_4,			/* Two keys have the same code: 3 and right */
+	[0x04] = KEY_5,
+	[0x05] = KEY_6,
+	[0x06] = KEY_7,
+	[0x07] = KEY_8,
+	[0x08] = KEY_9,
+	[0x0a] = KEY_0,
+
+	[0x09] = KEY_AGAIN,
+	[0x14] = KEY_MUTE,
+
+	[0x20] = KEY_UP,
+	[0x21] = KEY_DOWN,
+	[0x0b] = KEY_ENTER,
+
+	[0x10] = KEY_CHANNELUP,
+	[0x11] = KEY_CHANNELDOWN,
+
+	/* Couldn't map key left/key right since those
+	   conflict with '3' and '4' scancodes
+	   I dunno what the original driver does
+	 */
+
+	[0x13] = KEY_VOLUMEUP,
+	[0x12] = KEY_VOLUMEDOWN,
+
+	/* The lower part of the IR
+	   There are several duplicated keycodes there.
+	   Most of them conflict with digits.
+	   Add mappings just to the unused scancodes.
+	   Somehow, the original driver has a way to know,
+	   but this doesn't seem to be on some GPIO.
+	   Also, it is not related to the time between keyup
+	   and keydown.
+	 */
+	[0x19] = KEY_PAUSE,		/* Timeshift */
+	[0x1a] = KEY_STOP,
+	[0x1b] = KEY_RECORD,
+
+	[0x22] = KEY_TEXT,
+
+	[0x15] = KEY_AUDIO,		/* ((*)) */
+	[0x0f] = KEY_ZOOM,
+	[0x1c] = KEY_SHUFFLE,		/* snapshot */
+
+	[0x18] = KEY_RED,		/* B */
+	[0x23] = KEY_GREEN,		/* C */
+};
+EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog);
+
 IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = {
 	[0x20] = KEY_LIST,
 	[0x00] = KEY_POWER,
@@ -2511,3 +2572,35 @@ IR_KEYTAB_TYPE ir_codes_real_audio_220_32_keys[IR_KEYTAB_SIZE] = {
 
 };
 EXPORT_SYMBOL_GPL(ir_codes_real_audio_220_32_keys);
+
+/* ATI TV Wonder HD 600 USB
+   Devin Heitmueller <devin.heitmueller@gmail.com>
+ */
+IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE] = {
+	[0x00] = KEY_RECORD,		/* Row 1 */
+	[0x01] = KEY_PLAYPAUSE,
+	[0x02] = KEY_STOP,
+	[0x03] = KEY_POWER,
+	[0x04] = KEY_PREVIOUS,	/* Row 2 */
+	[0x05] = KEY_REWIND,
+	[0x06] = KEY_FORWARD,
+	[0x07] = KEY_NEXT,
+	[0x08] = KEY_EPG,		/* Row 3 */
+	[0x09] = KEY_HOME,
+	[0x0a] = KEY_MENU,
+	[0x0b] = KEY_CHANNELUP,
+	[0x0c] = KEY_BACK,		/* Row 4 */
+	[0x0d] = KEY_UP,
+	[0x0e] = KEY_INFO,
+	[0x0f] = KEY_CHANNELDOWN,
+	[0x10] = KEY_LEFT,		/* Row 5 */
+	[0x11] = KEY_SELECT,
+	[0x12] = KEY_RIGHT,
+	[0x13] = KEY_VOLUMEUP,
+	[0x14] = KEY_LAST,		/* Row 6 */
+	[0x15] = KEY_DOWN,
+	[0x16] = KEY_MUTE,
+	[0x17] = KEY_VOLUMEDOWN,
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600);

+ 1 - 1
drivers/media/common/saa7146_fops.c

@@ -313,7 +313,7 @@ static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 /*
 	DEB_EE(("inode:%p, file:%p, cmd:%d, arg:%li\n",inode, file, cmd, arg));
 */
-	return video_usercopy(inode, file, cmd, arg, saa7146_video_do_ioctl);
+	return video_usercopy(file, cmd, arg, saa7146_video_do_ioctl);
 }
 
 static int fops_mmap(struct file *file, struct vm_area_struct * vma)

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

@@ -834,7 +834,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
  * copying is done already, arg is a kernel pointer.
  */
 
-static int __saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+int saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
 	struct saa7146_fh *fh  = file->private_data;
 	struct saa7146_dev *dev = fh->dev;
@@ -1216,17 +1216,11 @@ static int __saa7146_video_do_ioctl(struct file *file, unsigned int cmd, void *a
 #endif
 	default:
 		return v4l_compat_translate_ioctl(file, cmd, arg,
-						  __saa7146_video_do_ioctl);
+						  saa7146_video_do_ioctl);
 	}
 	return 0;
 }
 
-int saa7146_video_do_ioctl(struct inode *inode, struct file *file,
-				    unsigned int cmd, void *arg)
-{
-	return __saa7146_video_do_ioctl(file, cmd, arg);
-}
-
 /*********************************************************************************/
 /* buffer handling functions                                                  */
 

+ 3 - 3
drivers/media/common/tuners/mxl5005s.c

@@ -3598,7 +3598,7 @@ static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
 		76, 77, 91, 134, 135, 137, 147,
 		156, 166, 167, 168, 25 };
 
-	*count = sizeof(RegAddr) / sizeof(u8);
+	*count = ARRAY_SIZE(RegAddr);
 
 	status += MXL_BlockInit(fe);
 
@@ -3630,7 +3630,7 @@ static u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal,
 	*/
 #endif
 
-	*count = sizeof(RegAddr) / sizeof(u8);
+	*count = ARRAY_SIZE(RegAddr);
 
 	for (i = 0 ; i < *count; i++) {
 		RegNum[i] = RegAddr[i];
@@ -3648,7 +3648,7 @@ static u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum,
 
 	u8 RegAddr[] = {43, 136};
 
-	*count = sizeof(RegAddr) / sizeof(u8);
+	*count = ARRAY_SIZE(RegAddr);
 
 	for (i = 0; i < *count; i++) {
 		RegNum[i] = RegAddr[i];

+ 8 - 7
drivers/media/common/tuners/tda827x.c

@@ -80,10 +80,11 @@ static void tda827x_set_std(struct dvb_frontend *fe,
 		mode = "xx";
 	}
 
-	if (params->mode == V4L2_TUNER_RADIO)
+	if (params->mode == V4L2_TUNER_RADIO) {
 		priv->sgIF = 88; /* if frequency is 5.5 MHz */
-
-	dprintk("setting tda827x to system %s\n", mode);
+		dprintk("setting tda827x to radio FM\n");
+	} else
+		dprintk("setting tda827x to system %s\n", mode);
 }
 
 
@@ -199,7 +200,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
 		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(priv->i2c_adap, &msg, 1);
 
-	priv->frequency = tuner_freq - if_freq; // FIXME
+	priv->frequency = params->frequency;
 	priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
 
 	return 0;
@@ -304,7 +305,7 @@ static int tda827xo_set_analog_params(struct dvb_frontend *fe,
 	reg2[1] = 0x08;   /* Vsync en */
 	i2c_transfer(priv->i2c_adap, &msg, 1);
 
-	priv->frequency = freq * 62500;
+	priv->frequency = params->frequency;
 
 	return 0;
 }
@@ -591,7 +592,7 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
 		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(priv->i2c_adap, &msg, 1);
 
-	priv->frequency = tuner_freq - if_freq; // FIXME
+	priv->frequency = params->frequency;
 	priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
 
 	return 0;
@@ -691,7 +692,7 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe,
 	tuner_reg[1] = 0x19 + (priv->lpsel << 1);
 	i2c_transfer(priv->i2c_adap, &msg, 1);
 
-	priv->frequency = freq * 62500;
+	priv->frequency = params->frequency;
 
 	return 0;
 }

+ 53 - 10
drivers/media/common/tuners/tda8290.c

@@ -32,6 +32,9 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
+static int deemphasis_50;
+MODULE_PARM_DESC(deemphasis_50, "0 - 75us deemphasis; 1 - 50us deemphasis");
+
 /* ---------------------------------------------------------------------- */
 
 struct tda8290_priv {
@@ -139,9 +142,34 @@ static void set_audio(struct dvb_frontend *fe,
 		mode = "xx";
 	}
 
-	tuner_dbg("setting tda829x to system %s\n", mode);
+	if (params->mode == V4L2_TUNER_RADIO) {
+		priv->tda8290_easy_mode = 0x01;		/* Start with MN values */
+		tuner_dbg("setting to radio FM\n");
+	} else {
+		tuner_dbg("setting tda829x to system %s\n", mode);
+	}
 }
 
+struct {
+	unsigned char seq[2];
+} fm_mode[] = {
+	{ { 0x01, 0x81} },	/* Put device into expert mode */
+	{ { 0x03, 0x48} },	/* Disable NOTCH and VIDEO filters */
+	{ { 0x04, 0x04} },	/* Disable color carrier filter (SSIF) */
+	{ { 0x05, 0x04} },	/* ADC headroom */
+	{ { 0x06, 0x10} },	/* group delay flat */
+
+	{ { 0x07, 0x00} },	/* use the same radio DTO values as a tda8295 */
+	{ { 0x08, 0x00} },
+	{ { 0x09, 0x80} },
+	{ { 0x0a, 0xda} },
+	{ { 0x0b, 0x4b} },
+	{ { 0x0c, 0x68} },
+
+	{ { 0x0d, 0x00} },	/* PLL off, no video carrier detect */
+	{ { 0x14, 0x00} },	/* disable auto mute if no video */
+};
+
 static void tda8290_set_params(struct dvb_frontend *fe,
 			       struct analog_parameters *params)
 {
@@ -178,15 +206,30 @@ static void tda8290_set_params(struct dvb_frontend *fe,
 	tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
 	msleep(1);
 
-	expert_mode[1] = priv->tda8290_easy_mode + 0x80;
-	tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
-	if (priv->tda8290_easy_mode & 0x60)
-		tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
-	else
-		tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
+	if (params->mode == V4L2_TUNER_RADIO) {
+		int i;
+		unsigned char deemphasis[]  = { 0x13, 1 };
+
+		/* FIXME: allow using a different deemphasis */
+
+		if (deemphasis_50)
+			deemphasis[1] = 2;
+
+		for (i = 0; i < ARRAY_SIZE(fm_mode); i++)
+			tuner_i2c_xfer_send(&priv->i2c_props, fm_mode[i].seq, 2);
+
+		tuner_i2c_xfer_send(&priv->i2c_props, deemphasis, 2);
+	} else {
+		expert_mode[1] = priv->tda8290_easy_mode + 0x80;
+		tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
+		tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
+		tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
+		if (priv->tda8290_easy_mode & 0x60)
+			tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
+		else
+			tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
+		tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
+	}
 
 	tda8290_i2c_bridge(fe, 1);
 

+ 2 - 3
drivers/media/common/tuners/tda9887.c

@@ -180,11 +180,10 @@ static struct tvnorm tvnorms[] = {
 	},{
 		.std   = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
 		.name  = "SECAM-BGH",
-		.b     = ( cPositiveAmTV  |
+		.b     = ( cNegativeFmTV  |
 			   cQSS           ),
 		.c     = ( cTopDefault),
-		.e     = ( cGating_36	  |
-			   cAudioIF_5_5   |
+		.e     = ( cAudioIF_5_5   |
 			   cVideoIF_38_90 ),
 	},{
 		.std   = V4L2_STD_SECAM_L,

+ 35 - 0
drivers/media/common/tuners/tuner-xc2028.c

@@ -28,6 +28,12 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "enable verbose debug messages");
 
+static int no_poweroff;
+module_param(no_poweroff, int, 0644);
+MODULE_PARM_DESC(debug, "0 (default) powers device off when not used.\n"
+	"1 keep device energized and with tuner ready all the times.\n"
+	"  Faster, but consumes more power and keeps the device hotter\n");
+
 static char audio_std[8];
 module_param_string(audio_std, audio_std, sizeof(audio_std), 0);
 MODULE_PARM_DESC(audio_std,
@@ -1091,6 +1097,34 @@ static int xc2028_set_params(struct dvb_frontend *fe,
 				T_DIGITAL_TV, type, 0, demod);
 }
 
+static int xc2028_sleep(struct dvb_frontend *fe)
+{
+	struct xc2028_data *priv = fe->tuner_priv;
+	int rc = 0;
+
+	/* Avoid firmware reload on slow devices */
+	if (no_poweroff)
+		return 0;
+
+	tuner_dbg("Putting xc2028/3028 into poweroff mode.\n");
+	if (debug > 1) {
+		tuner_dbg("Printing sleep stack trace:\n");
+		dump_stack();
+	}
+
+	mutex_lock(&priv->lock);
+
+	if (priv->firm_version < 0x0202)
+		rc = send_seq(priv, {0x00, 0x08, 0x00, 0x00});
+	else
+		rc = send_seq(priv, {0x80, 0x08, 0x00, 0x00});
+
+	priv->cur_fw.type = 0;	/* need firmware reload */
+
+	mutex_unlock(&priv->lock);
+
+	return rc;
+}
 
 static int xc2028_dvb_release(struct dvb_frontend *fe)
 {
@@ -1171,6 +1205,7 @@ static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
 	.get_frequency     = xc2028_get_frequency,
 	.get_rf_strength   = xc2028_signal,
 	.set_params        = xc2028_set_params,
+	.sleep             = xc2028_sleep,
 };
 
 struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,

+ 0 - 7
drivers/media/common/tuners/xc5000.c

@@ -36,10 +36,6 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
-static int xc5000_load_fw_on_attach;
-module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644);
-MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
-
 static DEFINE_MUTEX(xc5000_list_mutex);
 static LIST_HEAD(hybrid_tuner_instance_list);
 
@@ -1017,9 +1013,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 	memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
 		sizeof(struct dvb_tuner_ops));
 
-	if (xc5000_load_fw_on_attach)
-		xc5000_init(fe);
-
 	return fe;
 fail:
 	mutex_unlock(&xc5000_list_mutex);

+ 13 - 0
drivers/media/dvb/Kconfig

@@ -2,6 +2,19 @@
 # DVB device configuration
 #
 
+config DVB_DYNAMIC_MINORS
+	bool "Dynamic DVB minor allocation"
+	depends on DVB_CORE
+	default n
+	help
+	  If you say Y here, the DVB subsystem will use dynamic minor
+	  allocation for any device that uses the DVB major number.
+	  This means that you can have more than 4 of a single type
+	  of device (like demuxes and frontends) per adapter, but udev
+	  will be required to manage the device nodes.
+
+	  If you are unsure about this, say N here.
+
 menuconfig DVB_CAPTURE_DRIVERS
 	bool "DVB/ATSC adapters"
 	depends on DVB_CORE

+ 1 - 0
drivers/media/dvb/b2c2/Kconfig

@@ -14,6 +14,7 @@ config DVB_B2C2_FLEXCOP
 	select DVB_ISL6421 if !DVB_FE_CUSTOMISE
 	select DVB_CX24123 if !DVB_FE_CUSTOMISE
 	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
+	select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE
 	help
 	  Support for the digital TV receiver chip made by B2C2 Inc. included in
 	  Technisats PCI cards and USB boxes.

+ 1 - 2
drivers/media/dvb/dm1105/dm1105.c

@@ -19,7 +19,6 @@
  *
  */
 
-#include <linux/version.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -368,7 +367,7 @@ static int __devinit dm1105dvb_dma_map(struct dm1105dvb *dm1105dvb)
 {
 	dm1105dvb->ts_buf = pci_alloc_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, &dm1105dvb->dma_addr);
 
-	return pci_dma_mapping_error(dm1105dvb->pdev, dm1105dvb->dma_addr);
+	return !dm1105dvb->ts_buf;
 }
 
 static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb)

+ 70 - 7
drivers/media/dvb/dvb-core/dvb_frontend.c

@@ -128,6 +128,7 @@ struct dvb_frontend_private {
 	unsigned int step_size;
 	int quality;
 	unsigned int check_wrapped;
+	enum dvbfe_search algo_status;
 };
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
@@ -516,6 +517,8 @@ static int dvb_frontend_thread(void *data)
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	unsigned long timeout;
 	fe_status_t s;
+	enum dvbfe_algo algo;
+
 	struct dvb_frontend_parameters *params;
 
 	dprintk("%s\n", __func__);
@@ -562,23 +565,80 @@ restart:
 
 		/* do an iteration of the tuning loop */
 		if (fe->ops.get_frontend_algo) {
-			if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
-				/* have we been asked to retune? */
-				params = NULL;
+			algo = fe->ops.get_frontend_algo(fe);
+			switch (algo) {
+			case DVBFE_ALGO_HW:
+				dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
+				params = NULL; /* have we been asked to RETUNE ? */
+
 				if (fepriv->state & FESTATE_RETUNE) {
+					dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
 					params = &fepriv->parameters;
 					fepriv->state = FESTATE_TUNED;
 				}
 
-				fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
-				if (s != fepriv->status) {
+				if (fe->ops.tune)
+					fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+
+				if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) {
+					dprintk("%s: state changed, adding current state\n", __func__);
 					dvb_frontend_add_event(fe, s);
 					fepriv->status = s;
 				}
-			} else
+				break;
+			case DVBFE_ALGO_SW:
+				dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__);
 				dvb_frontend_swzigzag(fe);
-		} else
+				break;
+			case DVBFE_ALGO_CUSTOM:
+				params = NULL; /* have we been asked to RETUNE ?	*/
+				dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
+				if (fepriv->state & FESTATE_RETUNE) {
+					dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
+					params = &fepriv->parameters;
+					fepriv->state = FESTATE_TUNED;
+				}
+				/* Case where we are going to search for a carrier
+				 * User asked us to retune again for some reason, possibly
+				 * requesting a search with a new set of parameters
+				 */
+				if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
+					if (fe->ops.search) {
+						fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters);
+						/* We did do a search as was requested, the flags are
+						 * now unset as well and has the flags wrt to search.
+						 */
+					} else {
+						fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN;
+					}
+				}
+				/* Track the carrier if the search was successful */
+				if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) {
+					if (fe->ops.track)
+						fe->ops.track(fe, &fepriv->parameters);
+				} else {
+					fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+					fepriv->delay = HZ / 2;
+				}
+				fe->ops.read_status(fe, &s);
+				if (s != fepriv->status) {
+					dvb_frontend_add_event(fe, s); /* update event list */
+					fepriv->status = s;
+					if (!(s & FE_HAS_LOCK)) {
+						fepriv->delay = HZ / 10;
+						fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+					} else {
+						fepriv->delay = 60 * HZ;
+					}
+				}
+				break;
+			default:
+				dprintk("%s: UNDEFINED ALGO !\n", __func__);
+				break;
+			}
+		} else {
 			dvb_frontend_swzigzag(fe);
+		}
 	}
 
 	if (dvb_powerdown_on_sleep) {
@@ -1226,6 +1286,9 @@ int dtv_property_process_set(struct dvb_frontend *fe, struct dtv_property *tvp,
 		dprintk("%s() Finalised property cache\n", __func__);
 		dtv_property_cache_submit(fe);
 
+		/* Request the search algorithm to search */
+		fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
 		r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND,
 			&fepriv->parameters);
 		break;

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

@@ -69,6 +69,125 @@ struct analog_parameters {
 	u64 std;
 };
 
+enum dvbfe_modcod {
+	DVBFE_MODCOD_DUMMY_PLFRAME	= 0,
+	DVBFE_MODCOD_QPSK_1_4,
+	DVBFE_MODCOD_QPSK_1_3,
+	DVBFE_MODCOD_QPSK_2_5,
+	DVBFE_MODCOD_QPSK_1_2,
+	DVBFE_MODCOD_QPSK_3_5,
+	DVBFE_MODCOD_QPSK_2_3,
+	DVBFE_MODCOD_QPSK_3_4,
+	DVBFE_MODCOD_QPSK_4_5,
+	DVBFE_MODCOD_QPSK_5_6,
+	DVBFE_MODCOD_QPSK_8_9,
+	DVBFE_MODCOD_QPSK_9_10,
+	DVBFE_MODCOD_8PSK_3_5,
+	DVBFE_MODCOD_8PSK_2_3,
+	DVBFE_MODCOD_8PSK_3_4,
+	DVBFE_MODCOD_8PSK_5_6,
+	DVBFE_MODCOD_8PSK_8_9,
+	DVBFE_MODCOD_8PSK_9_10,
+	DVBFE_MODCOD_16APSK_2_3,
+	DVBFE_MODCOD_16APSK_3_4,
+	DVBFE_MODCOD_16APSK_4_5,
+	DVBFE_MODCOD_16APSK_5_6,
+	DVBFE_MODCOD_16APSK_8_9,
+	DVBFE_MODCOD_16APSK_9_10,
+	DVBFE_MODCOD_32APSK_3_4,
+	DVBFE_MODCOD_32APSK_4_5,
+	DVBFE_MODCOD_32APSK_5_6,
+	DVBFE_MODCOD_32APSK_8_9,
+	DVBFE_MODCOD_32APSK_9_10,
+	DVBFE_MODCOD_RESERVED_1,
+	DVBFE_MODCOD_BPSK_1_3,
+	DVBFE_MODCOD_BPSK_1_4,
+	DVBFE_MODCOD_RESERVED_2
+};
+
+enum tuner_param {
+	DVBFE_TUNER_FREQUENCY		= (1 <<  0),
+	DVBFE_TUNER_TUNERSTEP		= (1 <<  1),
+	DVBFE_TUNER_IFFREQ		= (1 <<  2),
+	DVBFE_TUNER_BANDWIDTH		= (1 <<  3),
+	DVBFE_TUNER_REFCLOCK		= (1 <<  4),
+	DVBFE_TUNER_IQSENSE		= (1 <<  5),
+	DVBFE_TUNER_DUMMY		= (1 << 31)
+};
+
+/*
+ * ALGO_HW: (Hardware Algorithm)
+ * ----------------------------------------------------------------
+ * Devices that support this algorithm do everything in hardware
+ * and no software support is needed to handle them.
+ * Requesting these devices to LOCK is the only thing required,
+ * device is supposed to do everything in the hardware.
+ *
+ * ALGO_SW: (Software Algorithm)
+ * ----------------------------------------------------------------
+ * These are dumb devices, that require software to do everything
+ *
+ * ALGO_CUSTOM: (Customizable Agorithm)
+ * ----------------------------------------------------------------
+ * Devices having this algorithm can be customized to have specific
+ * algorithms in the frontend driver, rather than simply doing a
+ * software zig-zag. In this case the zigzag maybe hardware assisted
+ * or it maybe completely done in hardware. In all cases, usage of
+ * this algorithm, in conjunction with the search and track
+ * callbacks, utilizes the driver specific algorithm.
+ *
+ * ALGO_RECOVERY: (Recovery Algorithm)
+ * ----------------------------------------------------------------
+ * These devices have AUTO recovery capabilities from LOCK failure
+ */
+enum dvbfe_algo {
+	DVBFE_ALGO_HW			= (1 <<  0),
+	DVBFE_ALGO_SW			= (1 <<  1),
+	DVBFE_ALGO_CUSTOM		= (1 <<  2),
+	DVBFE_ALGO_RECOVERY		= (1 << 31)
+};
+
+struct tuner_state {
+	u32 frequency;
+	u32 tunerstep;
+	u32 ifreq;
+	u32 bandwidth;
+	u32 iqsense;
+	u32 refclock;
+};
+
+/*
+ * search callback possible return status
+ *
+ * DVBFE_ALGO_SEARCH_SUCCESS
+ * The frontend search algorithm completed and returned succesfully
+ *
+ * DVBFE_ALGO_SEARCH_ASLEEP
+ * The frontend search algorithm is sleeping
+ *
+ * DVBFE_ALGO_SEARCH_FAILED
+ * The frontend search for a signal failed
+ *
+ * DVBFE_ALGO_SEARCH_INVALID
+ * The frontend search algorith was probably supplied with invalid
+ * parameters and the search is an invalid one
+ *
+ * DVBFE_ALGO_SEARCH_ERROR
+ * The frontend search algorithm failed due to some error
+ *
+ * DVBFE_ALGO_SEARCH_AGAIN
+ * The frontend search algorithm was requested to search again
+ */
+enum dvbfe_search {
+	DVBFE_ALGO_SEARCH_SUCCESS	= (1 <<  0),
+	DVBFE_ALGO_SEARCH_ASLEEP	= (1 <<  1),
+	DVBFE_ALGO_SEARCH_FAILED	= (1 <<  2),
+	DVBFE_ALGO_SEARCH_INVALID	= (1 <<  3),
+	DVBFE_ALGO_SEARCH_AGAIN		= (1 <<  4),
+	DVBFE_ALGO_SEARCH_ERROR		= (1 << 31),
+};
+
+
 struct dvb_tuner_ops {
 
 	struct dvb_tuner_info info;
@@ -99,6 +218,13 @@ struct dvb_tuner_ops {
 	 * 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);
+
+	/*
+	 * These are provided seperately from set_params in order to facilitate silicon
+	 * tuners which require sophisticated tuning loops, controlling each parameter seperately.
+	 */
+	int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
+	int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
 };
 
 struct analog_demod_info {
@@ -142,7 +268,7 @@ struct dvb_frontend_ops {
 		    unsigned int *delay,
 		    fe_status_t *status);
 	/* get frontend tuning algorithm from the module */
-	int (*get_frontend_algo)(struct dvb_frontend *fe);
+	enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
 
 	/* these two are only used for the swzigzag code */
 	int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
@@ -167,6 +293,12 @@ struct dvb_frontend_ops {
 	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
 	int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
 
+	/* These callbacks are for devices that implement their own
+	 * tuning algorithms, rather than a simple swzigzag
+	 */
+	enum dvbfe_search (*search)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+	int (*track)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+
 	struct dvb_tuner_ops tuner_ops;
 	struct analog_demod_ops analog_ops;
 

+ 50 - 21
drivers/media/dvb/dvb-core/dvbdev.c

@@ -50,33 +50,27 @@ static const char * const dnames[] = {
 	"net", "osd"
 };
 
+#ifdef CONFIG_DVB_DYNAMIC_MINORS
+#define MAX_DVB_MINORS		256
+#define DVB_MAX_IDS		MAX_DVB_MINORS
+#else
 #define DVB_MAX_IDS		4
 #define nums2minor(num,type,id)	((num << 6) | (id << 4) | type)
 #define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64)
+#endif
 
 static struct class *dvb_class;
 
-static struct dvb_device* dvbdev_find_device (int minor)
-{
-	struct dvb_adapter *adap;
-
-	list_for_each_entry(adap, &dvb_adapter_list, list_head) {
-		struct dvb_device *dev;
-		list_for_each_entry(dev, &adap->device_list, list_head)
-			if (nums2minor(adap->num, dev->type, dev->id) == minor)
-				return dev;
-	}
-
-	return NULL;
-}
-
+static struct dvb_device *dvb_minors[MAX_DVB_MINORS];
+static DECLARE_RWSEM(minor_rwsem);
 
 static int dvb_device_open(struct inode *inode, struct file *file)
 {
 	struct dvb_device *dvbdev;
 
 	lock_kernel();
-	dvbdev = dvbdev_find_device (iminor(inode));
+	down_read(&minor_rwsem);
+	dvbdev = dvb_minors[iminor(inode)];
 
 	if (dvbdev && dvbdev->fops) {
 		int err = 0;
@@ -92,9 +86,11 @@ static int dvb_device_open(struct inode *inode, struct file *file)
 			file->f_op = fops_get(old_fops);
 		}
 		fops_put(old_fops);
+		up_read(&minor_rwsem);
 		unlock_kernel();
 		return err;
 	}
+	up_read(&minor_rwsem);
 	unlock_kernel();
 	return -ENODEV;
 }
@@ -192,6 +188,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 	struct dvb_device *dvbdev;
 	struct file_operations *dvbdevfops;
 	struct device *clsdev;
+	int minor;
 	int id;
 
 	mutex_lock(&dvbdev_register_lock);
@@ -231,11 +228,31 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 
 	list_add_tail (&dvbdev->list_head, &adap->device_list);
 
+	down_write(&minor_rwsem);
+#ifdef CONFIG_DVB_DYNAMIC_MINORS
+	for (minor = 0; minor < MAX_DVB_MINORS; minor++)
+		if (dvb_minors[minor] == NULL)
+			break;
+
+	if (minor == MAX_DVB_MINORS) {
+		kfree(dvbdevfops);
+		kfree(dvbdev);
+		mutex_unlock(&dvbdev_register_lock);
+		return -EINVAL;
+	}
+#else
+	minor = nums2minor(adap->num, type, id);
+#endif
+
+	dvbdev->minor = minor;
+	dvb_minors[minor] = dvbdev;
+	up_write(&minor_rwsem);
+
 	mutex_unlock(&dvbdev_register_lock);
 
 	clsdev = device_create(dvb_class, adap->device,
-			       MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
-			       NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
+			       MKDEV(DVB_MAJOR, minor),
+			       dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
 	if (IS_ERR(clsdev)) {
 		printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
 		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
@@ -243,8 +260,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 	}
 
 	dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
-		adap->num, dnames[type], id, nums2minor(adap->num, type, id),
-		nums2minor(adap->num, type, id));
+		adap->num, dnames[type], id, minor, minor);
 
 	return 0;
 }
@@ -256,8 +272,11 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
 	if (!dvbdev)
 		return;
 
-	device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
-		       dvbdev->type, dvbdev->id)));
+	down_write(&minor_rwsem);
+	dvb_minors[dvbdev->minor] = NULL;
+	up_write(&minor_rwsem);
+
+	device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
 
 	list_del (&dvbdev->list_head);
 	kfree (dvbdev->fops);
@@ -413,6 +432,15 @@ out:
 	return err;
 }
 
+static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct dvb_device *dvbdev = dev_get_drvdata(dev);
+
+	add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
+	add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
+	return 0;
+}
+
 static int __init init_dvbdev(void)
 {
 	int retval;
@@ -434,6 +462,7 @@ static int __init init_dvbdev(void)
 		retval = PTR_ERR(dvb_class);
 		goto error;
 	}
+	dvb_class->dev_uevent = dvb_uevent;
 	return 0;
 
 error:

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

@@ -74,6 +74,7 @@ struct dvb_device {
 	struct file_operations *fops;
 	struct dvb_adapter *adapter;
 	int type;
+	int minor;
 	u32 id;
 
 	/* in theory, 'users' can vanish now,

+ 30 - 3
drivers/media/dvb/dvb-usb/af9015.c

@@ -733,9 +733,19 @@ static int af9015_read_config(struct usb_device *udev)
 				af9015_config.ir_table_size =
 				  ARRAY_SIZE(af9015_ir_table_mygictv);
 				break;
+			case AF9015_REMOTE_DIGITTRADE_DVB_T:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_digittrade;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_digittrade);
+				af9015_config.ir_table =
+				  af9015_ir_table_digittrade;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_digittrade);
+				break;
 			}
 		} else {
-			switch (udev->descriptor.idVendor) {
+			switch (le16_to_cpu(udev->descriptor.idVendor)) {
 			case USB_VID_LEADTEK:
 				af9015_properties[i].rc_key_map =
 				  af9015_rc_keys_leadtek;
@@ -748,7 +758,7 @@ static int af9015_read_config(struct usb_device *udev)
 				break;
 			case USB_VID_VISIONPLUS:
 				if (udev->descriptor.idProduct ==
-				USB_PID_AZUREWAVE_AD_TU700) {
+				cpu_to_le16(USB_PID_AZUREWAVE_AD_TU700)) {
 					af9015_properties[i].rc_key_map =
 					  af9015_rc_keys_twinhan;
 					af9015_properties[i].rc_key_map_size =
@@ -800,6 +810,16 @@ static int af9015_read_config(struct usb_device *udev)
 					  ARRAY_SIZE(af9015_ir_table_msi);
 				}
 				break;
+			case USB_VID_AVERMEDIA:
+				af9015_properties[i].rc_key_map =
+				  af9015_rc_keys_avermedia;
+				af9015_properties[i].rc_key_map_size =
+				  ARRAY_SIZE(af9015_rc_keys_avermedia);
+				af9015_config.ir_table =
+				  af9015_ir_table_avermedia;
+				af9015_config.ir_table_size =
+				  ARRAY_SIZE(af9015_ir_table_avermedia);
+				break;
 			}
 		}
 	}
@@ -1191,6 +1211,7 @@ static struct usb_device_id af9015_usb_table[] = {
 	{USB_DEVICE(USB_VID_TELESTAR,  USB_PID_TELESTAR_STARSTICK_2)},
 	{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
 /* 15 */{USB_DEVICE(USB_VID_MSI_2,     USB_PID_MSI_DIGI_VOX_MINI_III)},
+	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_395U)},
 	{0},
 };
 MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1343,7 +1364,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
 
 		.i2c_algo = &af9015_i2c_algo,
 
-		.num_device_descs = 6,
+		.num_device_descs = 7,
 		.devices = {
 			{
 				.name = "Xtensions XD-380",
@@ -1375,6 +1396,12 @@ static struct dvb_usb_device_properties af9015_properties[] = {
 				.cold_ids = {&af9015_usb_table[15], NULL},
 				.warm_ids = {NULL},
 			},
+			{
+				.name = "KWorld USB DVB-T TV Stick II " \
+					"(VS-DVB-T 395U)",
+				.cold_ids = {&af9015_usb_table[16], NULL},
+				.warm_ids = {NULL},
+			},
 		}
 	}
 };

+ 140 - 0
drivers/media/dvb/dvb-usb/af9015.h

@@ -123,6 +123,7 @@ enum af9015_remote {
 	AF9015_REMOTE_A_LINK_DTU_M,
 	AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
 	AF9015_REMOTE_MYGICTV_U718,
+	AF9015_REMOTE_DIGITTRADE_DVB_T,
 };
 
 /* Leadtek WinFast DTV Dongle Gold */
@@ -520,4 +521,143 @@ static u8 af9015_ir_table_kworld[] = {
 	0x86, 0x6b, 0x23, 0xdc, 0x45, 0x07, 0x00,
 };
 
+/* AverMedia Volar X */
+static struct dvb_usb_rc_key af9015_rc_keys_avermedia[] = {
+	{ 0x05, 0x3d, KEY_PROG1 },       /* SOURCE */
+	{ 0x05, 0x12, KEY_POWER },       /* POWER */
+	{ 0x05, 0x1e, KEY_1 },           /* 1 */
+	{ 0x05, 0x1f, KEY_2 },           /* 2 */
+	{ 0x05, 0x20, KEY_3 },           /* 3 */
+	{ 0x05, 0x21, KEY_4 },           /* 4 */
+	{ 0x05, 0x22, KEY_5 },           /* 5 */
+	{ 0x05, 0x23, KEY_6 },           /* 6 */
+	{ 0x05, 0x24, KEY_7 },           /* 7 */
+	{ 0x05, 0x25, KEY_8 },           /* 8 */
+	{ 0x05, 0x26, KEY_9 },           /* 9 */
+	{ 0x05, 0x3f, KEY_LEFT },        /* L / DISPLAY */
+	{ 0x05, 0x27, KEY_0 },           /* 0 */
+	{ 0x05, 0x0f, KEY_RIGHT },       /* R / CH RTN */
+	{ 0x05, 0x18, KEY_PROG2 },       /* SNAP SHOT */
+	{ 0x05, 0x1c, KEY_PROG3 },       /* 16-CH PREV */
+	{ 0x05, 0x2d, KEY_VOLUMEDOWN },  /* VOL DOWN */
+	{ 0x05, 0x3e, KEY_ZOOM },        /* FULL SCREEN */
+	{ 0x05, 0x2e, KEY_VOLUMEUP },    /* VOL UP */
+	{ 0x05, 0x10, KEY_MUTE },        /* MUTE */
+	{ 0x05, 0x04, KEY_AUDIO },       /* AUDIO */
+	{ 0x05, 0x15, KEY_RECORD },      /* RECORD */
+	{ 0x05, 0x11, KEY_PLAY },        /* PLAY */
+	{ 0x05, 0x16, KEY_STOP },        /* STOP */
+	{ 0x05, 0x0c, KEY_PLAYPAUSE },   /* TIMESHIFT / PAUSE */
+	{ 0x05, 0x05, KEY_BACK },        /* << / RED */
+	{ 0x05, 0x09, KEY_FORWARD },     /* >> / YELLOW */
+	{ 0x05, 0x17, KEY_TEXT },        /* TELETEXT */
+	{ 0x05, 0x0a, KEY_EPG },         /* EPG */
+	{ 0x05, 0x13, KEY_MENU },        /* MENU */
+
+	{ 0x05, 0x0e, KEY_CHANNELUP },   /* CH UP */
+	{ 0x05, 0x0d, KEY_CHANNELDOWN }, /* CH DOWN */
+	{ 0x05, 0x19, KEY_FIRST },       /* |<< / GREEN */
+	{ 0x05, 0x08, KEY_LAST },        /* >>| / BLUE */
+};
+
+static u8 af9015_ir_table_avermedia[] = {
+	0x02, 0xfd, 0x00, 0xff, 0x12, 0x05, 0x00,
+	0x02, 0xfd, 0x01, 0xfe, 0x3d, 0x05, 0x00,
+	0x02, 0xfd, 0x03, 0xfc, 0x17, 0x05, 0x00,
+	0x02, 0xfd, 0x04, 0xfb, 0x0a, 0x05, 0x00,
+	0x02, 0xfd, 0x05, 0xfa, 0x1e, 0x05, 0x00,
+	0x02, 0xfd, 0x06, 0xf9, 0x1f, 0x05, 0x00,
+	0x02, 0xfd, 0x07, 0xf8, 0x20, 0x05, 0x00,
+	0x02, 0xfd, 0x09, 0xf6, 0x21, 0x05, 0x00,
+	0x02, 0xfd, 0x0a, 0xf5, 0x22, 0x05, 0x00,
+	0x02, 0xfd, 0x0b, 0xf4, 0x23, 0x05, 0x00,
+	0x02, 0xfd, 0x0d, 0xf2, 0x24, 0x05, 0x00,
+	0x02, 0xfd, 0x0e, 0xf1, 0x25, 0x05, 0x00,
+	0x02, 0xfd, 0x0f, 0xf0, 0x26, 0x05, 0x00,
+	0x02, 0xfd, 0x11, 0xee, 0x27, 0x05, 0x00,
+	0x02, 0xfd, 0x08, 0xf7, 0x04, 0x05, 0x00,
+	0x02, 0xfd, 0x0c, 0xf3, 0x3e, 0x05, 0x00,
+	0x02, 0xfd, 0x10, 0xef, 0x1c, 0x05, 0x00,
+	0x02, 0xfd, 0x12, 0xed, 0x3f, 0x05, 0x00,
+	0x02, 0xfd, 0x13, 0xec, 0x0f, 0x05, 0x00,
+	0x02, 0xfd, 0x14, 0xeb, 0x10, 0x05, 0x00,
+	0x02, 0xfd, 0x15, 0xea, 0x13, 0x05, 0x00,
+	0x02, 0xfd, 0x17, 0xe8, 0x18, 0x05, 0x00,
+	0x02, 0xfd, 0x18, 0xe7, 0x11, 0x05, 0x00,
+	0x02, 0xfd, 0x19, 0xe6, 0x15, 0x05, 0x00,
+	0x02, 0xfd, 0x1a, 0xe5, 0x0c, 0x05, 0x00,
+	0x02, 0xfd, 0x1b, 0xe4, 0x16, 0x05, 0x00,
+	0x02, 0xfd, 0x1c, 0xe3, 0x09, 0x05, 0x00,
+	0x02, 0xfd, 0x1d, 0xe2, 0x05, 0x05, 0x00,
+	0x02, 0xfd, 0x1e, 0xe1, 0x2d, 0x05, 0x00,
+	0x02, 0xfd, 0x1f, 0xe0, 0x2e, 0x05, 0x00,
+	0x03, 0xfc, 0x00, 0xff, 0x08, 0x05, 0x00,
+	0x03, 0xfc, 0x01, 0xfe, 0x19, 0x05, 0x00,
+	0x03, 0xfc, 0x02, 0xfd, 0x0d, 0x05, 0x00,
+	0x03, 0xfc, 0x03, 0xfc, 0x0e, 0x05, 0x00,
+};
+
+/* Digittrade DVB-T USB Stick */
+static struct dvb_usb_rc_key af9015_rc_keys_digittrade[] = {
+	{ 0x01, 0x0f, KEY_LAST },	/* RETURN */
+	{ 0x05, 0x17, KEY_TEXT },	/* TELETEXT */
+	{ 0x01, 0x08, KEY_EPG },	/* EPG */
+	{ 0x05, 0x13, KEY_POWER },	/* POWER */
+	{ 0x01, 0x09, KEY_ZOOM },	/* FULLSCREEN */
+	{ 0x00, 0x40, KEY_AUDIO },	/* DUAL SOUND */
+	{ 0x00, 0x2c, KEY_PRINT },	/* SNAPSHOT */
+	{ 0x05, 0x16, KEY_SUBTITLE },	/* SUBTITLE */
+	{ 0x00, 0x52, KEY_CHANNELUP },	/* CH Up */
+	{ 0x00, 0x51, KEY_CHANNELDOWN },/* Ch Dn */
+	{ 0x00, 0x57, KEY_VOLUMEUP },	/* Vol Up */
+	{ 0x00, 0x56, KEY_VOLUMEDOWN },	/* Vol Dn */
+	{ 0x01, 0x10, KEY_MUTE },	/* MUTE */
+	{ 0x00, 0x27, KEY_0 },
+	{ 0x00, 0x1e, KEY_1 },
+	{ 0x00, 0x1f, KEY_2 },
+	{ 0x00, 0x20, KEY_3 },
+	{ 0x00, 0x21, KEY_4 },
+	{ 0x00, 0x22, KEY_5 },
+	{ 0x00, 0x23, KEY_6 },
+	{ 0x00, 0x24, KEY_7 },
+	{ 0x00, 0x25, KEY_8 },
+	{ 0x00, 0x26, KEY_9 },
+	{ 0x01, 0x17, KEY_PLAYPAUSE },	/* TIMESHIFT */
+	{ 0x01, 0x15, KEY_RECORD },	/* RECORD */
+	{ 0x03, 0x13, KEY_PLAY },	/* PLAY */
+	{ 0x01, 0x16, KEY_STOP },	/* STOP */
+	{ 0x01, 0x13, KEY_PAUSE },	/* PAUSE */
+};
+
+static u8 af9015_ir_table_digittrade[] = {
+	0x00, 0xff, 0x06, 0xf9, 0x13, 0x05, 0x00,
+	0x00, 0xff, 0x4d, 0xb2, 0x17, 0x01, 0x00,
+	0x00, 0xff, 0x1f, 0xe0, 0x2c, 0x00, 0x00,
+	0x00, 0xff, 0x0a, 0xf5, 0x15, 0x01, 0x00,
+	0x00, 0xff, 0x0e, 0xf1, 0x16, 0x01, 0x00,
+	0x00, 0xff, 0x09, 0xf6, 0x09, 0x01, 0x00,
+	0x00, 0xff, 0x01, 0xfe, 0x08, 0x01, 0x00,
+	0x00, 0xff, 0x05, 0xfa, 0x10, 0x01, 0x00,
+	0x00, 0xff, 0x02, 0xfd, 0x56, 0x00, 0x00,
+	0x00, 0xff, 0x40, 0xbf, 0x57, 0x00, 0x00,
+	0x00, 0xff, 0x19, 0xe6, 0x52, 0x00, 0x00,
+	0x00, 0xff, 0x17, 0xe8, 0x51, 0x00, 0x00,
+	0x00, 0xff, 0x10, 0xef, 0x0f, 0x01, 0x00,
+	0x00, 0xff, 0x54, 0xab, 0x27, 0x00, 0x00,
+	0x00, 0xff, 0x1b, 0xe4, 0x1e, 0x00, 0x00,
+	0x00, 0xff, 0x11, 0xee, 0x1f, 0x00, 0x00,
+	0x00, 0xff, 0x15, 0xea, 0x20, 0x00, 0x00,
+	0x00, 0xff, 0x12, 0xed, 0x21, 0x00, 0x00,
+	0x00, 0xff, 0x16, 0xe9, 0x22, 0x00, 0x00,
+	0x00, 0xff, 0x4c, 0xb3, 0x23, 0x00, 0x00,
+	0x00, 0xff, 0x48, 0xb7, 0x24, 0x00, 0x00,
+	0x00, 0xff, 0x04, 0xfb, 0x25, 0x00, 0x00,
+	0x00, 0xff, 0x00, 0xff, 0x26, 0x00, 0x00,
+	0x00, 0xff, 0x1e, 0xe1, 0x13, 0x03, 0x00,
+	0x00, 0xff, 0x1a, 0xe5, 0x13, 0x01, 0x00,
+	0x00, 0xff, 0x03, 0xfc, 0x17, 0x05, 0x00,
+	0x00, 0xff, 0x0d, 0xf2, 0x16, 0x05, 0x00,
+	0x00, 0xff, 0x1d, 0xe2, 0x40, 0x00, 0x00,
+};
+
 #endif

+ 1 - 1
drivers/media/dvb/dvb-usb/anysee.c

@@ -153,7 +153,7 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
 	int num)
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int ret, inc, i = 0;
+	int ret = 0, inc, i = 0;
 
 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 		return -EAGAIN;

+ 1 - 2
drivers/media/dvb/dvb-usb/cinergyT2-core.c

@@ -32,7 +32,6 @@
 
 /* debug */
 int dvb_usb_cinergyt2_debug;
-int disable_remote;
 
 module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 "
@@ -45,7 +44,7 @@ struct cinergyt2_state {
 };
 
 /* We are missing a release hook with usb_device data */
-struct dvb_usb_device *cinergyt2_usb_device;
+static struct dvb_usb_device *cinergyt2_usb_device;
 
 static struct dvb_usb_device_properties cinergyt2_properties;
 

+ 5 - 5
drivers/media/dvb/dvb-usb/cinergyT2.h

@@ -70,11 +70,11 @@ struct dvbt_get_status_msg {
 	uint8_t bandwidth;
 	uint16_t tps;
 	uint8_t flags;
-	uint16_t gain;
+	__le16 gain;
 	uint8_t snr;
-	uint32_t viterbi_error_rate;
+	__le32 viterbi_error_rate;
 	uint32_t rs_error_rate;
-	uint32_t uncorrected_block_count;
+	__le32 uncorrected_block_count;
 	uint8_t lock_bits;
 	uint8_t prev_lock_bits;
 } __attribute__((packed));
@@ -82,9 +82,9 @@ struct dvbt_get_status_msg {
 
 struct dvbt_set_parameters_msg {
 	uint8_t cmd;
-	uint32_t freq;
+	__le32 freq;
 	uint8_t bandwidth;
-	uint16_t tps;
+	__le16 tps;
 	uint8_t flags;
 } __attribute__((packed));
 

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

@@ -96,6 +96,7 @@
 #define USB_PID_GRANDTEC_DVBT_USB_COLD			0x0fa0
 #define USB_PID_GRANDTEC_DVBT_USB_WARM			0x0fa1
 #define USB_PID_KWORLD_399U				0xe399
+#define USB_PID_KWORLD_395U				0xe396
 #define USB_PID_KWORLD_PC160_2T				0xc160
 #define USB_PID_KWORLD_VSTREAM_COLD			0x17de
 #define USB_PID_KWORLD_VSTREAM_WARM			0x17df

+ 12 - 3
drivers/media/dvb/dvb-usb/dw2102.c

@@ -9,7 +9,6 @@
 *
 * see Documentation/dvb/README.dvb-usb for more information
 */
-#include <linux/version.h>
 #include "dw2102.h"
 #include "si21xx.h"
 #include "stv0299.h"
@@ -27,6 +26,10 @@
 #define USB_PID_DW2104 0x2104
 #endif
 
+#ifndef USB_PID_CINERGY_S
+#define USB_PID_CINERGY_S 0x0064
+#endif
+
 #define DW210X_READ_MSG 0
 #define DW210X_WRITE_MSG 1
 
@@ -578,6 +581,7 @@ static struct usb_device_id dw2102_table[] = {
 	{USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
 	{USB_DEVICE(USB_VID_CYPRESS, 0x2104)},
 	{USB_DEVICE(0x9022, 0xd650)},
+	{USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
 	{ }
 };
 
@@ -647,6 +651,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
 			dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
 					DW210X_WRITE_MSG);
 			break;
+		case USB_PID_CINERGY_S:
 		case USB_PID_DW2102:
 			dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
 					DW210X_WRITE_MSG);
@@ -655,7 +660,7 @@ static int dw2102_load_firmware(struct usb_device *dev,
 			/* check STV0299 frontend  */
 			dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,
 					DW210X_READ_MSG);
-			if (reset16[0] == 0xa1) {
+			if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
 				dw2102_properties.i2c_algo = &dw2102_i2c_algo;
 				dw2102_properties.adapter->tuner_attach = &dw2102_tuner_attach;
 				break;
@@ -726,7 +731,7 @@ static struct dvb_usb_device_properties dw2102_properties = {
 			},
 		}
 	},
-	.num_device_descs = 2,
+	.num_device_descs = 3,
 	.devices = {
 		{"DVBWorld DVB-S 2102 USB2.0",
 			{&dw2102_table[0], NULL},
@@ -736,6 +741,10 @@ static struct dvb_usb_device_properties dw2102_properties = {
 			{&dw2102_table[1], NULL},
 			{NULL},
 		},
+		{"TerraTec Cinergy S USB",
+			{&dw2102_table[4], NULL},
+			{NULL},
+		},
 	}
 };
 

+ 114 - 26
drivers/media/dvb/dvb-usb/gp8psk-fe.c

@@ -25,6 +25,20 @@ struct gp8psk_fe_state {
 	unsigned long status_check_interval;
 };
 
+static int gp8psk_tuned_to_DCII(struct dvb_frontend *fe)
+{
+	struct gp8psk_fe_state *st = fe->demodulator_priv;
+	u8 status;
+	gp8psk_usb_in_op(st->d, GET_8PSK_CONFIG, 0, 0, &status, 1);
+	return status & bmDCtuned;
+}
+
+static int gp8psk_set_tuner_mode(struct dvb_frontend *fe, int mode)
+{
+	struct gp8psk_fe_state *state = fe->demodulator_priv;
+	return gp8psk_usb_out_op(state->d, SET_8PSK_CONFIG, mode, 0, NULL, 0);
+}
+
 static int gp8psk_fe_update_status(struct gp8psk_fe_state *st)
 {
 	u8 buf[6];
@@ -99,39 +113,114 @@ static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_front
 	return 0;
 }
 
+static int gp8psk_fe_set_property(struct dvb_frontend *fe,
+	struct dtv_property *tvp)
+{
+	deb_fe("%s(..)\n", __func__);
+	return 0;
+}
+
+static int gp8psk_fe_get_property(struct dvb_frontend *fe,
+	struct dtv_property *tvp)
+{
+	deb_fe("%s(..)\n", __func__);
+	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;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	u8 cmd[10];
 	u32 freq = fep->frequency * 1000;
+	int gp_product_id = le16_to_cpu(state->d->udev->descriptor.idProduct);
+
+	deb_fe("%s()\n", __func__);
 
 	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*/
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		/* Only QPSK is supported for DVB-S */
+		if (c->modulation != QPSK) {
+			deb_fe("%s: unsupported modulation selected (%d)\n",
+				__func__, c->modulation);
+			return -EOPNOTSUPP;
+		}
+		c->fec_inner = FEC_AUTO;
 		break;
+	case SYS_DVBS2:
+		deb_fe("%s: DVB-S2 delivery system selected\n", __func__);
+		break;
+
 	default:
-		// other modes are unsuported right now
-		cmd[0] = 0;
-		cmd[1] = 0;
-		cmd[2] = 0;
-		cmd[3] = 0;
-		cmd[8] = 0;
+		deb_fe("%s: unsupported delivery system selected (%d)\n",
+			__func__, c->delivery_system);
+		return -EOPNOTSUPP;
+	}
+
+	cmd[0] =  c->symbol_rate        & 0xff;
+	cmd[1] = (c->symbol_rate >>  8) & 0xff;
+	cmd[2] = (c->symbol_rate >> 16) & 0xff;
+	cmd[3] = (c->symbol_rate >> 24) & 0xff;
+	switch (c->modulation) {
+	case QPSK:
+		if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
+			if (gp8psk_tuned_to_DCII(fe))
+				gp8psk_bcm4500_reload(state->d);
+		switch (c->fec_inner) {
+		case FEC_1_2:
+			cmd[9] = 0; break;
+		case FEC_2_3:
+			cmd[9] = 1; break;
+		case FEC_3_4:
+			cmd[9] = 2; break;
+		case FEC_5_6:
+			cmd[9] = 3; break;
+		case FEC_7_8:
+			cmd[9] = 4; break;
+		case FEC_AUTO:
+			cmd[9] = 5; break;
+		default:
+			cmd[9] = 5; break;
+		}
+		cmd[8] = ADV_MOD_DVB_QPSK;
+		break;
+	case PSK_8: /* PSK_8 is for compatibility with DN */
+		cmd[8] = ADV_MOD_TURBO_8PSK;
+		switch (c->fec_inner) {
+		case FEC_2_3:
+			cmd[9] = 0; break;
+		case FEC_3_4:
+			cmd[9] = 1; break;
+		case FEC_3_5:
+			cmd[9] = 2; break;
+		case FEC_5_6:
+			cmd[9] = 3; break;
+		case FEC_8_9:
+			cmd[9] = 4; break;
+		default:
+			cmd[9] = 0; break;
+		}
+		break;
+	case QAM_16: /* QAM_16 is for compatibility with DN */
+		cmd[8] = ADV_MOD_TURBO_16QAM;
 		cmd[9] = 0;
 		break;
+	default: /* Unknown modulation */
+		deb_fe("%s: unsupported modulation selected (%d)\n",
+			__func__, c->modulation);
+		return -EOPNOTSUPP;
 	}
 
-	gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
+	if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
+		gp8psk_set_tuner_mode(fe, 0);
+	gp8psk_usb_out_op(state->d, TUNE_8PSK, 0, 0, cmd, 10);
 
 	state->lock = 0;
 	state->next_status_check = jiffies;
@@ -140,13 +229,6 @@ static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
 	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)
 {
@@ -261,9 +343,13 @@ static struct dvb_frontend_ops gp8psk_fe_ops = {
 		.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
+			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_QAM_16 is for compatibility
+			 * (Myth incorrectly detects Turbo-QPSK as plain QAM-16)
+			 */
+			FE_CAN_QPSK | FE_CAN_QAM_16
 	},
 
 	.release = gp8psk_fe_release,
@@ -271,8 +357,10 @@ static struct dvb_frontend_ops gp8psk_fe_ops = {
 	.init = NULL,
 	.sleep = NULL,
 
+	.set_property = gp8psk_fe_set_property,
+	.get_property = gp8psk_fe_get_property,
 	.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,

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

@@ -174,6 +174,22 @@ static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
 	return 0;
 }
 
+int gp8psk_bcm4500_reload(struct dvb_usb_device *d)
+{
+	u8 buf;
+	int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
+	/* Turn off 8psk power */
+	if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
+		return -EINVAL;
+	/* Turn On 8psk power */
+	if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
+		return -EINVAL;
+	/* load BCM4500 firmware */
+	if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
+		if (gp8psk_load_bcm4500fw(d))
+			return EINVAL;
+	return 0;
+}
 
 static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {

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

@@ -92,5 +92,6 @@ 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);
+extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d);
 
 #endif

+ 2 - 1
drivers/media/dvb/dvb-usb/usb-urb.c

@@ -156,7 +156,8 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream)
 				stream->props.u.bulk.buffersize,
 				usb_urb_complete, stream);
 
-		stream->urb_list[i]->transfer_flags = 0;
+		stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+		stream->urb_list[i]->transfer_dma = stream->dma_addr[i];
 		stream->urbs_initialized++;
 	}
 	return 0;

+ 53 - 0
drivers/media/dvb/frontends/Kconfig

@@ -12,6 +12,25 @@ config DVB_FE_CUSTOMISE
 
 	  If unsure say N.
 
+comment "Multistandard (satellite) frontends"
+	depends on DVB_CORE
+
+config DVB_STB0899
+	tristate "STB0899 based"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want
+	  to support this demodulator based frontends
+
+config DVB_STB6100
+	tristate "STB6100 based tuners"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A Silicon tuner from ST used in conjunction with the STB0899
+	  demodulator. Say Y when you want to support this tuner.
+
 comment "DVB-S (satellite) frontends"
 	depends on DVB_CORE
 
@@ -78,6 +97,13 @@ config DVB_TDA10086
 	help
 	  A DVB-S tuner module. Say Y when you want to support this frontend.
 
+config DVB_TDA8261
+	tristate "Philips TDA8261 based"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
 config DVB_VES1X93
 	tristate "VLSI VES1893 or VES1993 based"
 	depends on DVB_CORE && I2C
@@ -92,6 +118,14 @@ config DVB_TUNER_ITD1000
 	help
 	  A DVB-S tuner module. Say Y when you want to support this frontend.
 
+config DVB_TUNER_CX24113
+	tristate "Conexant CX24113/CX24128 tuner for DVB-S/DSS"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+
 config DVB_TDA826X
 	tristate "Philips TDA826X silicon tuner"
 	depends on DVB_CORE && I2C
@@ -345,6 +379,14 @@ config DVB_LGDT330X
 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
 	  to support this frontend.
 
+config DVB_LGDT3304
+	tristate "LG Electronics LGDT3304"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+	  to support this frontend.
+
 config DVB_S5H1409
 	tristate "Samsung S5H1409 based"
 	depends on DVB_CORE && I2C
@@ -369,6 +411,17 @@ config DVB_S5H1411
 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
 	  to support this frontend.
 
+comment "ISDB-T (terrestrial) frontends"
+	depends on DVB_CORE
+
+config DVB_S921
+	tristate "Sharp S921 tuner"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  AN ISDB-T DQPSK, QPSK, 16QAM and 64QAM 1seg tuner module.
+	  Say Y when you want to support this frontend.
+
 comment "Digital terrestrial only tuners/PLL"
 	depends on DVB_CORE
 

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

@@ -5,8 +5,13 @@
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
 EXTRA_CFLAGS += -Idrivers/media/common/tuners/
 
+s921-objs := s921_module.o s921_core.o
+stb0899-objs = stb0899_drv.o stb0899_algo.o
+
 obj-$(CONFIG_DVB_PLL) += dvb-pll.o
 obj-$(CONFIG_DVB_STV0299) += stv0299.o
+obj-$(CONFIG_DVB_STB0899) += stb0899.o
+obj-$(CONFIG_DVB_STB6100) += stb6100.o
 obj-$(CONFIG_DVB_SP8870) += sp8870.o
 obj-$(CONFIG_DVB_CX22700) += cx22700.o
 obj-$(CONFIG_DVB_CX24110) += cx24110.o
@@ -35,18 +40,21 @@ obj-$(CONFIG_DVB_OR51132) += or51132.o
 obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
 obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
 obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
+obj-$(CONFIG_DVB_LGDT3304) += lgdt3304.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
 obj-$(CONFIG_DVB_ISL6405) += isl6405.o
 obj-$(CONFIG_DVB_ISL6421) += isl6421.o
 obj-$(CONFIG_DVB_TDA10086) += tda10086.o
 obj-$(CONFIG_DVB_TDA826X) += tda826x.o
+obj-$(CONFIG_DVB_TDA8261) += tda8261.o
 obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
 obj-$(CONFIG_DVB_TUA6100) += tua6100.o
 obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
 obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
 obj-$(CONFIG_DVB_AU8522) += au8522.o
 obj-$(CONFIG_DVB_TDA10048) += tda10048.o
+obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
 obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
 obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o
 obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
@@ -55,3 +63,5 @@ obj-$(CONFIG_DVB_CX24116) += cx24116.o
 obj-$(CONFIG_DVB_SI21XX) += si21xx.o
 obj-$(CONFIG_DVB_STV0288) += stv0288.o
 obj-$(CONFIG_DVB_STB6000) += stb6000.o
+obj-$(CONFIG_DVB_S921) += s921.o
+

+ 7 - 7
drivers/media/dvb/frontends/af9013.c

@@ -223,12 +223,12 @@ static int af9013_set_coeff(struct af9013_state *state, fe_bandwidth_t bw)
 	int ret = 0;
 	u8 i = 0;
 	u8 buf[24];
-	u32 ns_coeff1_2048nu;
-	u32 ns_coeff1_8191nu;
-	u32 ns_coeff1_8192nu;
-	u32 ns_coeff1_8193nu;
-	u32 ns_coeff2_2k;
-	u32 ns_coeff2_8k;
+	u32 uninitialized_var(ns_coeff1_2048nu);
+	u32 uninitialized_var(ns_coeff1_8191nu);
+	u32 uninitialized_var(ns_coeff1_8192nu);
+	u32 uninitialized_var(ns_coeff1_8193nu);
+	u32 uninitialized_var(ns_coeff2_2k);
+	u32 uninitialized_var(ns_coeff2_8k);
 
 	deb_info("%s: adc_clock:%d bw:%d\n", __func__,
 		state->config.adc_clock, bw);
@@ -1009,7 +1009,7 @@ static int af9013_update_snr(struct dvb_frontend *fe)
 	int ret;
 	u8 buf[3], i, len;
 	u32 quant = 0;
-	struct snr_table *snr_table;
+	struct snr_table *uninitialized_var(snr_table);
 
 	/* check if quantizer ready (for snr) */
 	ret = af9013_read_reg_bits(state, 0xd2e1, 3, 1, &buf[0]);

+ 616 - 0
drivers/media/dvb/frontends/cx24113.c

@@ -0,0 +1,616 @@
+/*
+ *  Driver for Conexant CX24113/CX24128 Tuner (Satellite)
+ *
+ *  Copyright (C) 2007-8 Patrick Boettcher <pb@linuxtv.org>
+ *
+ *  Developed for BBTI / Technisat
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "dvb_frontend.h"
+#include "cx24113.h"
+
+static int debug;
+
+#define info(args...) do { printk(KERN_INFO "CX24113: " args); } while (0)
+#define err(args...)  do { printk(KERN_ERR  "CX24113: " args); } while (0)
+
+#define dprintk(args...) \
+	do { \
+		if (debug) { \
+			printk(KERN_DEBUG "CX24113: %s: ", __func__); \
+			printk(args); \
+		} \
+	} while (0)
+
+struct cx24113_state {
+	struct i2c_adapter *i2c;
+	const struct cx24113_config *config;
+
+#define REV_CX24113 0x23
+	u8 rev;
+	u8 ver;
+
+	u8 icp_mode:1;
+
+#define ICP_LEVEL1 0
+#define ICP_LEVEL2 1
+#define ICP_LEVEL3 2
+#define ICP_LEVEL4 3
+	u8 icp_man:2;
+	u8 icp_auto_low:2;
+	u8 icp_auto_mlow:2;
+	u8 icp_auto_mhi:2;
+	u8 icp_auto_hi:2;
+	u8 icp_dig;
+
+#define LNA_MIN_GAIN 0
+#define LNA_MID_GAIN 1
+#define LNA_MAX_GAIN 2
+	u8 lna_gain:2;
+
+	u8 acp_on:1;
+
+	u8 vco_mode:2;
+	u8 vco_shift:1;
+#define VCOBANDSEL_6 0x80
+#define VCOBANDSEL_5 0x01
+#define VCOBANDSEL_4 0x02
+#define VCOBANDSEL_3 0x04
+#define VCOBANDSEL_2 0x08
+#define VCOBANDSEL_1 0x10
+	u8 vco_band;
+
+#define VCODIV4 4
+#define VCODIV2 2
+	u8 vcodiv;
+
+	u8 bs_delay:4;
+	u16 bs_freqcnt:13;
+	u16 bs_rdiv;
+	u8 prescaler_mode:1;
+
+	u8 rfvga_bias_ctrl;
+
+	s16 tuner_gain_thres;
+	u8  gain_level;
+
+	u32 frequency;
+
+	u8 refdiv;
+
+	u8 Fwindow_enabled;
+};
+
+static int cx24113_writereg(struct cx24113_state *state, int reg, int data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->i2c_addr,
+		.flags = 0, .buf = buf, .len = 2 };
+	int err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
+		printk(KERN_DEBUG "%s: writereg error(err == %i, reg == 0x%02x,"
+			 " data == 0x%02x)\n", __func__, err, reg, data);
+		return err;
+	}
+
+	return 0;
+}
+
+static int cx24113_readreg(struct cx24113_state *state, u8 reg)
+{
+	int ret;
+	u8 b;
+	struct i2c_msg msg[] = {
+		{ .addr = state->config->i2c_addr,
+			.flags = 0, .buf = &reg, .len = 1 },
+		{ .addr = state->config->i2c_addr,
+			.flags = I2C_M_RD, .buf = &b, .len = 1 }
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		printk(KERN_DEBUG "%s: reg=0x%x (error=%d)\n",
+			__func__, reg, ret);
+		return ret;
+	}
+
+	return b;
+}
+
+static void cx24113_set_parameters(struct cx24113_state *state)
+{
+	u8 r;
+
+	r = cx24113_readreg(state, 0x10) & 0x82;
+	r |= state->icp_mode;
+	r |= state->icp_man << 4;
+	r |= state->icp_dig << 2;
+	r |= state->prescaler_mode << 5;
+	cx24113_writereg(state, 0x10, r);
+
+	r = (state->icp_auto_low  << 0) | (state->icp_auto_mlow << 2)
+		| (state->icp_auto_mhi << 4) | (state->icp_auto_hi << 6);
+	cx24113_writereg(state, 0x11, r);
+
+	if (state->rev == REV_CX24113) {
+		r = cx24113_readreg(state, 0x20) & 0xec;
+		r |= state->lna_gain;
+		r |= state->rfvga_bias_ctrl << 4;
+		cx24113_writereg(state, 0x20, r);
+	}
+
+	r = cx24113_readreg(state, 0x12) & 0x03;
+	r |= state->acp_on << 2;
+	r |= state->bs_delay << 4;
+	cx24113_writereg(state, 0x12, r);
+
+	r = cx24113_readreg(state, 0x18) & 0x40;
+	r |= state->vco_shift;
+	if (state->vco_band == VCOBANDSEL_6)
+		r |= (1 << 7);
+	else
+		r |= (state->vco_band << 1);
+	cx24113_writereg(state, 0x18, r);
+
+	r  = cx24113_readreg(state, 0x14) & 0x20;
+	r |= (state->vco_mode << 6) | ((state->bs_freqcnt >> 8) & 0x1f);
+	cx24113_writereg(state, 0x14, r);
+	cx24113_writereg(state, 0x15, (state->bs_freqcnt        & 0xff));
+
+	cx24113_writereg(state, 0x16, (state->bs_rdiv >> 4) & 0xff);
+	r = (cx24113_readreg(state, 0x17) & 0x0f) |
+		((state->bs_rdiv & 0x0f) << 4);
+	cx24113_writereg(state, 0x17, r);
+}
+
+#define VGA_0 0x00
+#define VGA_1 0x04
+#define VGA_2 0x02
+#define VGA_3 0x06
+#define VGA_4 0x01
+#define VGA_5 0x05
+#define VGA_6 0x03
+#define VGA_7 0x07
+
+#define RFVGA_0 0x00
+#define RFVGA_1 0x01
+#define RFVGA_2 0x02
+#define RFVGA_3 0x03
+
+static int cx24113_set_gain_settings(struct cx24113_state *state,
+		s16 power_estimation)
+{
+	u8 ampout = cx24113_readreg(state, 0x1d) & 0xf0,
+	   vga    = cx24113_readreg(state, 0x1f) & 0x3f,
+	   rfvga  = cx24113_readreg(state, 0x20) & 0xf3;
+	u8 gain_level = power_estimation >= state->tuner_gain_thres;
+
+	dprintk("power estimation: %d, thres: %d, gain_level: %d/%d\n",
+			power_estimation, state->tuner_gain_thres,
+			state->gain_level, gain_level);
+
+	if (gain_level == state->gain_level)
+		return 0; /* nothing to be done */
+
+	ampout |= 0xf;
+
+	if (gain_level) {
+		rfvga |= RFVGA_0 << 2;
+		vga   |= (VGA_7 << 3) | VGA_7;
+	} else {
+		rfvga |= RFVGA_2 << 2;
+		vga  |= (VGA_6 << 3) | VGA_2;
+	}
+	state->gain_level = gain_level;
+
+	cx24113_writereg(state, 0x1d, ampout);
+	cx24113_writereg(state, 0x1f, vga);
+	cx24113_writereg(state, 0x20, rfvga);
+
+	return 1; /* did something */
+}
+
+static int cx24113_set_Fref(struct cx24113_state *state, u8 high)
+{
+	u8 xtal = cx24113_readreg(state, 0x02);
+	if (state->rev == 0x43 && state->vcodiv == VCODIV4)
+		high = 1;
+
+	xtal &= ~0x2;
+	if (high)
+		xtal |= high << 1;
+	return cx24113_writereg(state, 0x02, xtal);
+}
+
+static int cx24113_enable(struct cx24113_state *state, u8 enable)
+{
+	u8 r21 = (cx24113_readreg(state, 0x21) & 0xc0) | enable;
+	if (state->rev == REV_CX24113)
+		r21 |= (1 << 1);
+	return cx24113_writereg(state, 0x21, r21);
+}
+
+static int cx24113_set_bandwidth(struct cx24113_state *state, u32 bandwidth_khz)
+{
+	u8 r;
+
+	if (bandwidth_khz <= 19000)
+		r = 0x03 << 6;
+	else if (bandwidth_khz <= 25000)
+		r = 0x02 << 6;
+	else
+		r = 0x01 << 6;
+
+	dprintk("bandwidth to be set: %d\n", bandwidth_khz);
+	bandwidth_khz *= 10;
+	bandwidth_khz -= 10000;
+	bandwidth_khz /= 1000;
+	bandwidth_khz += 5;
+	bandwidth_khz /= 10;
+
+	dprintk("bandwidth: %d %d\n", r >> 6, bandwidth_khz);
+
+	r |= bandwidth_khz & 0x3f;
+
+	return cx24113_writereg(state, 0x1e, r);
+}
+
+static int cx24113_set_clk_inversion(struct cx24113_state *state, u8 on)
+{
+	u8 r = (cx24113_readreg(state, 0x10) & 0x7f) | ((on & 0x1) << 7);
+	return cx24113_writereg(state, 0x10, r);
+}
+
+static int cx24113_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	u8 r = (cx24113_readreg(state, 0x10) & 0x02) >> 1;
+	if (r)
+		*status |= TUNER_STATUS_LOCKED;
+	dprintk("PLL locked: %d\n", r);
+	return 0;
+}
+
+static u8 cx24113_set_ref_div(struct cx24113_state *state, u8 refdiv)
+{
+	if (state->rev == 0x43 && state->vcodiv == VCODIV4)
+		refdiv = 2;
+	return state->refdiv = refdiv;
+}
+
+static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f)
+{
+	s32 N;
+	s64 F;
+	u8 R, r;
+	u8 vcodiv;
+	u8 factor;
+	s32 freq_hz = state->frequency * 1000;
+
+	if (state->config->xtal_khz < 20000)
+		factor = 1;
+	else
+		factor = 2;
+
+	if (state->rev == REV_CX24113) {
+		if (state->frequency >= 1100000)
+			vcodiv = VCODIV2;
+		else
+			vcodiv = VCODIV4;
+	} else {
+		if (state->frequency >= 1165000)
+			vcodiv = VCODIV2;
+		else
+			vcodiv = VCODIV4;
+	}
+	state->vcodiv = vcodiv;
+
+	dprintk("calculating N/F for %dHz with vcodiv %d\n", freq_hz, vcodiv);
+	R = 0;
+	do {
+		R = cx24113_set_ref_div(state, R + 1);
+
+		/* calculate tuner PLL settings: */
+		N =  (freq_hz / 100 * vcodiv) * R;
+		N /= (state->config->xtal_khz) * factor * 2;
+		N += 5;     /* For round up. */
+		N /= 10;
+		N -= 32;
+	} while (N < 6 && R < 3);
+
+	if (N < 6) {
+		err("strange frequency: N < 6\n");
+		return;
+	}
+	F = freq_hz;
+	F *= (u64) (R * vcodiv * 262144);
+	dprintk("1 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
+	do_div(F, state->config->xtal_khz*1000 * factor * 2);
+	dprintk("2 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
+	F -= (N + 32) * 262144;
+
+	dprintk("3 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
+
+	if (state->Fwindow_enabled) {
+		if (F > (262144 / 2 - 1638))
+			F = 262144 / 2 - 1638;
+		if (F < (-262144 / 2 + 1638))
+			F = -262144 / 2 + 1638;
+		if ((F < 3277 && F > 0) || (F > -3277 && F < 0)) {
+			F = 0;
+			r = cx24113_readreg(state, 0x10);
+			cx24113_writereg(state, 0x10, r | (1 << 6));
+		}
+	}
+	dprintk("4 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
+
+	*n = (u16) N;
+	*f = (s32) F;
+}
+
+
+static void cx24113_set_nfr(struct cx24113_state *state, u16 n, s32 f, u8 r)
+{
+	u8 reg;
+	cx24113_writereg(state, 0x19, (n >> 1) & 0xff);
+
+	reg = ((n & 0x1) << 7) | ((f >> 11) & 0x7f);
+	cx24113_writereg(state, 0x1a, reg);
+
+	cx24113_writereg(state, 0x1b, (f >> 3) & 0xff);
+
+	reg = cx24113_readreg(state, 0x1c) & 0x1f;
+	cx24113_writereg(state, 0x1c, reg | ((f & 0x7) << 5));
+
+	cx24113_set_Fref(state, r - 1);
+}
+
+static int cx24113_set_frequency(struct cx24113_state *state, u32 frequency)
+{
+	u8 r = 1; /* or 2 */
+	u16 n = 6;
+	s32 f = 0;
+
+	r = cx24113_readreg(state, 0x14);
+	cx24113_writereg(state, 0x14, r & 0x3f);
+
+	r = cx24113_readreg(state, 0x10);
+	cx24113_writereg(state, 0x10, r & 0xbf);
+
+	state->frequency = frequency;
+
+	dprintk("tuning to frequency: %d\n", frequency);
+
+	cx24113_calc_pll_nf(state, &n, &f);
+	cx24113_set_nfr(state, n, f, state->refdiv);
+
+	r = cx24113_readreg(state, 0x18) & 0xbf;
+	if (state->vcodiv != VCODIV2)
+		r |= 1 << 6;
+	cx24113_writereg(state, 0x18, r);
+
+	/* The need for this sleep is not clear. But helps in some cases */
+	msleep(5);
+
+	r = cx24113_readreg(state, 0x1c) & 0xef;
+	cx24113_writereg(state, 0x1c, r | (1 << 4));
+	return 0;
+}
+
+static int cx24113_init(struct dvb_frontend *fe)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	int ret;
+
+	state->tuner_gain_thres = -50;
+	state->gain_level = 255; /* to force a gain-setting initialization */
+	state->icp_mode = 0;
+
+	if (state->config->xtal_khz < 11000) {
+		state->icp_auto_hi  = ICP_LEVEL4;
+		state->icp_auto_mhi  = ICP_LEVEL4;
+		state->icp_auto_mlow = ICP_LEVEL3;
+		state->icp_auto_low = ICP_LEVEL3;
+	} else {
+		state->icp_auto_hi  = ICP_LEVEL4;
+		state->icp_auto_mhi  = ICP_LEVEL4;
+		state->icp_auto_mlow = ICP_LEVEL3;
+		state->icp_auto_low = ICP_LEVEL2;
+	}
+
+	state->icp_dig = ICP_LEVEL3;
+	state->icp_man = ICP_LEVEL1;
+	state->acp_on  = 1;
+	state->vco_mode = 0;
+	state->vco_shift = 0;
+	state->vco_band = VCOBANDSEL_1;
+	state->bs_delay = 8;
+	state->bs_freqcnt = 0x0fff;
+	state->bs_rdiv = 0x0fff;
+	state->prescaler_mode = 0;
+	state->lna_gain = LNA_MAX_GAIN;
+	state->rfvga_bias_ctrl = 1;
+	state->Fwindow_enabled = 1;
+
+	cx24113_set_Fref(state, 0);
+	cx24113_enable(state, 0x3d);
+	cx24113_set_parameters(state);
+
+	cx24113_set_gain_settings(state, -30);
+
+	cx24113_set_bandwidth(state, 18025);
+	cx24113_set_clk_inversion(state, 1);
+
+	if (state->config->xtal_khz >= 40000)
+		ret = cx24113_writereg(state, 0x02,
+			(cx24113_readreg(state, 0x02) & 0xfb) | (1 << 2));
+	else
+		ret = cx24113_writereg(state, 0x02,
+			(cx24113_readreg(state, 0x02) & 0xfb) | (0 << 2));
+
+	return ret;
+}
+
+static int cx24113_set_params(struct dvb_frontend *fe,
+		struct dvb_frontend_parameters *p)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	/* for a ROLL-OFF factor of 0.35, 0.2: 600, 0.25: 625 */
+	u32 roll_off = 675;
+	u32 bw;
+
+	bw  = ((p->u.qpsk.symbol_rate/100) * roll_off) / 1000;
+	bw += (10000000/100) + 5;
+	bw /= 10;
+	bw += 1000;
+	cx24113_set_bandwidth(state, bw);
+
+	cx24113_set_frequency(state, p->frequency);
+	msleep(5);
+	return cx24113_get_status(fe, &bw);
+}
+
+static s8 cx24113_agc_table[2][10] = {
+	{-54, -41, -35, -30, -25, -21, -16, -10,  -6,  -2},
+	{-39, -35, -30, -25, -19, -15, -11,  -5,   1,   9},
+};
+
+void cx24113_agc_callback(struct dvb_frontend *fe)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	s16 s, i;
+	if (!fe->ops.read_signal_strength)
+		return;
+
+	do {
+		/* this only works with the current CX24123 implementation */
+		fe->ops.read_signal_strength(fe, (u16 *) &s);
+		s >>= 8;
+		dprintk("signal strength: %d\n", s);
+		for (i = 0; i < sizeof(cx24113_agc_table[0]); i++)
+			if (cx24113_agc_table[state->gain_level][i] > s)
+				break;
+		s = -25 - i*5;
+	} while (cx24113_set_gain_settings(state, s));
+}
+EXPORT_SYMBOL(cx24113_agc_callback);
+
+static int cx24113_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	*frequency = state->frequency;
+	return 0;
+}
+
+static int cx24113_release(struct dvb_frontend *fe)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	dprintk("\n");
+	fe->tuner_priv = NULL;
+	kfree(state);
+	return 0;
+}
+
+static const struct dvb_tuner_ops cx24113_tuner_ops = {
+	.info = {
+		.name           = "Conexant CX24113",
+		.frequency_min  = 950000,
+		.frequency_max  = 2150000,
+		.frequency_step = 125,
+	},
+
+	.release       = cx24113_release,
+
+	.init          = cx24113_init,
+	.sleep         = NULL,
+
+	.set_params    = cx24113_set_params,
+	.get_frequency = cx24113_get_frequency,
+	.get_bandwidth = NULL,
+	.get_status    = cx24113_get_status,
+};
+
+struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
+		const struct cx24113_config *config, struct i2c_adapter *i2c)
+{
+	/* allocate memory for the internal state */
+	struct cx24113_state *state =
+		kzalloc(sizeof(struct cx24113_state), GFP_KERNEL);
+	int rc;
+	if (state == NULL) {
+		err("Unable to kmalloc\n");
+		goto error;
+	}
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	info("trying to detect myself\n");
+
+	/* making a dummy read, because of some expected troubles
+	 * after power on */
+	cx24113_readreg(state, 0x00);
+
+	rc = cx24113_readreg(state, 0x00);
+	if (rc < 0) {
+		info("CX24113 not found.\n");
+		goto error;
+	}
+	state->rev = rc;
+
+	switch (rc) {
+	case 0x43:
+		info("detected CX24113 variant\n");
+		break;
+	case REV_CX24113:
+		info("sucessfully detected\n");
+		break;
+	default:
+		err("unsupported device id: %x\n", state->rev);
+		goto error;
+	}
+	state->ver = cx24113_readreg(state, 0x01);
+	info("version: %x\n", state->ver);
+
+	/* create dvb_frontend */
+	memcpy(&fe->ops.tuner_ops, &cx24113_tuner_ops,
+			sizeof(struct dvb_tuner_ops));
+	fe->tuner_priv = state;
+	return fe;
+
+error:
+	kfree(state);
+
+	return NULL;
+}
+EXPORT_SYMBOL(cx24113_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+MODULE_AUTHOR("Patrick Boettcher <pb@linuxtv.org>");
+MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24113/CX24128hardware");
+MODULE_LICENSE("GPL");
+

+ 8 - 3
drivers/media/dvb/frontends/cx24113.h

@@ -16,7 +16,7 @@
  *
  *  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.=
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #ifndef CX24113_H
@@ -30,9 +30,13 @@ struct cx24113_config {
 	u32 xtal_khz;
 };
 
-/* TODO: #if defined(CONFIG_DVB_TUNER_CX24113) || \
- * (defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE)) */
+#if defined(CONFIG_DVB_TUNER_CX24113) || \
+	(defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE))
+extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *,
+	const struct cx24113_config *config, struct i2c_adapter *i2c);
 
+extern void cx24113_agc_callback(struct dvb_frontend *fe);
+#else
 static inline struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
 	const struct cx24113_config *config, struct i2c_adapter *i2c)
 {
@@ -44,5 +48,6 @@ static inline void cx24113_agc_callback(struct dvb_frontend *fe)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 }
+#endif
 
 #endif /* CX24113_H */

+ 33 - 10
drivers/media/dvb/frontends/cx24116.c

@@ -106,7 +106,7 @@ MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
 #define CX24116_HAS_SYNCLOCK (0x08)
 #define CX24116_HAS_UNKNOWN1 (0x10)
 #define CX24116_HAS_UNKNOWN2 (0x20)
-#define CX24116_STATUS_MASK  (0x3f)
+#define CX24116_STATUS_MASK  (0x0f)
 #define CX24116_SIGNAL_MASK  (0xc0)
 
 #define CX24116_DISEQC_TONEOFF   (0)    /* toneburst never sent */
@@ -160,6 +160,7 @@ struct cx24116_tuning {
 	fe_spectral_inversion_t inversion;
 	fe_code_rate_t fec;
 
+	fe_delivery_system_t delsys;
 	fe_modulation_t modulation;
 	fe_pilot_t pilot;
 	fe_rolloff_t rolloff;
@@ -411,14 +412,15 @@ struct cx24116_modfec {
 };
 
 static int cx24116_lookup_fecmod(struct cx24116_state *state,
-	fe_modulation_t m, fe_code_rate_t f)
+	fe_delivery_system_t d, fe_modulation_t m, fe_code_rate_t f)
 {
 	int i, ret = -EOPNOTSUPP;
 
 	dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
 
 	for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) {
-		if ((m == CX24116_MODFEC_MODES[i].modulation) &&
+		if ((d == CX24116_MODFEC_MODES[i].delivery_system) &&
+			(m == CX24116_MODFEC_MODES[i].modulation) &&
 			(f == CX24116_MODFEC_MODES[i].fec)) {
 				ret = i;
 				break;
@@ -429,13 +431,13 @@ static int cx24116_lookup_fecmod(struct cx24116_state *state,
 }
 
 static int cx24116_set_fec(struct cx24116_state *state,
-	fe_modulation_t mod, fe_code_rate_t fec)
+	fe_delivery_system_t delsys, fe_modulation_t mod, fe_code_rate_t fec)
 {
 	int ret = 0;
 
 	dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
 
-	ret = cx24116_lookup_fecmod(state, mod, fec);
+	ret = cx24116_lookup_fecmod(state, delsys, mod, fec);
 
 	if (ret < 0)
 		return ret;
@@ -679,7 +681,8 @@ static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 
-	int lock = cx24116_readreg(state, CX24116_REG_SSTATUS);
+	int lock = cx24116_readreg(state, CX24116_REG_SSTATUS) &
+		CX24116_STATUS_MASK;
 
 	dprintk("%s: status = 0x%02x\n", __func__, lock);
 
@@ -1205,7 +1208,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe,
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct cx24116_cmd cmd;
 	fe_status_t tunerstat;
-	int i, status, ret, retune;
+	int i, status, ret, retune = 1;
 
 	dprintk("%s()\n", __func__);
 
@@ -1222,7 +1225,6 @@ static int cx24116_set_frontend(struct dvb_frontend *fe,
 
 		/* Pilot doesn't exist in DVB-S, turn bit off */
 		state->dnxt.pilot_val = CX24116_PILOT_OFF;
-		retune = 1;
 
 		/* DVB-S only supports 0.35 */
 		if (c->rolloff != ROLLOFF_35) {
@@ -1250,7 +1252,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe,
 		case PILOT_AUTO:	/* Not supported but emulated */
 			state->dnxt.pilot_val = (c->modulation == QPSK)
 				? CX24116_PILOT_OFF : CX24116_PILOT_ON;
-			retune = 2;
+			retune++;
 			break;
 		case PILOT_OFF:
 			state->dnxt.pilot_val = CX24116_PILOT_OFF;
@@ -1287,6 +1289,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe,
 			__func__, c->delivery_system);
 		return -EOPNOTSUPP;
 	}
+	state->dnxt.delsys = c->delivery_system;
 	state->dnxt.modulation = c->modulation;
 	state->dnxt.frequency = c->frequency;
 	state->dnxt.pilot = c->pilot;
@@ -1297,7 +1300,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe,
 		return ret;
 
 	/* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
-	ret = cx24116_set_fec(state, c->modulation, c->fec_inner);
+	ret = cx24116_set_fec(state, c->delivery_system, c->modulation, c->fec_inner);
 	if (ret !=  0)
 		return ret;
 
@@ -1308,6 +1311,7 @@ static int cx24116_set_frontend(struct dvb_frontend *fe,
 	/* discard the 'current' tuning parameters and prepare to tune */
 	cx24116_clone_params(fe);
 
+	dprintk("%s:   delsys      = %d\n", __func__, state->dcur.delsys);
 	dprintk("%s:   modulation  = %d\n", __func__, state->dcur.modulation);
 	dprintk("%s:   frequency   = %d\n", __func__, state->dcur.frequency);
 	dprintk("%s:   pilot       = %d (val = 0x%02x)\n", __func__,
@@ -1427,6 +1431,23 @@ tuned:  /* Set/Reset B/W */
 	return ret;
 }
 
+static int cx24116_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *params,
+	unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
+{
+	*delay = HZ / 5;
+	if (params) {
+		int ret = cx24116_set_frontend(fe, params);
+		if (ret)
+			return ret;
+	}
+	return cx24116_read_status(fe, status);
+}
+
+static int cx24116_get_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_HW;
+}
+
 static struct dvb_frontend_ops cx24116_ops = {
 
 	.info = {
@@ -1458,6 +1479,8 @@ static struct dvb_frontend_ops cx24116_ops = {
 	.set_voltage = cx24116_set_voltage,
 	.diseqc_send_master_cmd = cx24116_send_diseqc_msg,
 	.diseqc_send_burst = cx24116_diseqc_send_burst,
+	.get_frontend_algo = cx24116_get_algo,
+	.tune = cx24116_tune,
 
 	.set_property = cx24116_set_property,
 	.get_property = cx24116_get_property,

+ 6 - 3
drivers/media/dvb/frontends/dib7000p.h

@@ -66,7 +66,8 @@ struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe,
 	return NULL;
 }
 
-extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
+static inline
+int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
 				    int no_of_demods, u8 default_addr,
 				    struct dib7000p_config cfg[])
 {
@@ -74,13 +75,15 @@ extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
 	return -ENODEV;
 }
 
-extern int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+static inline
+int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
 
-extern int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+static inline
+int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;

+ 6 - 6
drivers/media/dvb/frontends/drx397xD.c

@@ -39,7 +39,7 @@ static const char mod_name[] = "drx397xD";
 #define F_SET_0D4h	2
 
 enum fw_ix {
-#define _FW_ENTRY(a, b)		b
+#define _FW_ENTRY(a, b, c)	b
 #include "drx397xD_fw.h"
 };
 
@@ -72,11 +72,11 @@ static struct {
 	int refcnt;
 	const u8 *data[ARRAY_SIZE(blob_name)];
 } fw[] = {
-#define _FW_ENTRY(a, b)		{			\
-			.name	= a,			\
-			.file	= 0,			\
-			.lock	= RW_LOCK_UNLOCKED,	\
-			.refcnt = 0,			\
+#define _FW_ENTRY(a, b, c)	{					\
+			.name	= a,					\
+			.file	= 0,					\
+			.lock	= __RW_LOCK_UNLOCKED(fw[c].lock),	\
+			.refcnt = 0,					\
 			.data	= { }		}
 #include "drx397xD_fw.h"
 };

+ 2 - 2
drivers/media/dvb/frontends/drx397xD_fw.h

@@ -18,8 +18,8 @@
  */
 
 #ifdef _FW_ENTRY
-	_FW_ENTRY("drx397xD.A2.fw",	DRXD_FW_A2 = 0		),
-	_FW_ENTRY("drx397xD.B1.fw",	DRXD_FW_B1		),
+	_FW_ENTRY("drx397xD.A2.fw",	DRXD_FW_A2 = 0,	DRXD_FW_A2	),
+	_FW_ENTRY("drx397xD.B1.fw",	DRXD_FW_B1,	DRXD_FW_B1	),
 #undef _FW_ENTRY
 #endif /* _FW_ENTRY */
 

+ 1 - 1
drivers/media/dvb/frontends/dvb-pll.c

@@ -311,7 +311,7 @@ static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
 	.count = 4,
 	.entries = {
 		{ 1250000, 500, 0xc4, 0x00},
-		{ 1550000, 500, 0xc4, 0x40},
+		{ 1450000, 500, 0xc4, 0x40},
 		{ 2050000, 500, 0xc4, 0x80},
 		{ 2150000, 500, 0xc4, 0xc0},
 	},

+ 378 - 0
drivers/media/dvb/frontends/lgdt3304.c

@@ -0,0 +1,378 @@
+/*
+ * Driver for LG ATSC lgdt3304 driver
+ *
+ * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "lgdt3304.h"
+
+static  unsigned int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"lgdt3304 debugging (default off)");
+
+#define dprintk(fmt, args...) if (debug) do {\
+			printk("lgdt3304 debug: " fmt, ##args); } while (0)
+
+struct lgdt3304_state
+{
+	struct dvb_frontend frontend;
+	fe_modulation_t current_modulation;
+	__u32 snr;
+	__u32 current_frequency;
+	__u8 addr;
+	struct i2c_adapter *i2c;
+};
+
+static int i2c_write_demod_bytes (struct dvb_frontend *fe, __u8 *buf, int len)
+{
+	struct lgdt3304_state *state = fe->demodulator_priv;
+	struct i2c_msg i2cmsgs = {
+		.addr = state->addr,
+		.flags = 0,
+		.len = 3,
+		.buf = buf
+	};
+	int i;
+	int err;
+
+	for (i=0; i<len-1; i+=3){
+		if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
+			printk("%s i2c_transfer error %d\n", __FUNCTION__, err);
+			if (err < 0)
+				return err;
+			else
+				return -EREMOTEIO;
+		}
+		i2cmsgs.buf += 3;
+	}
+	return 0;
+}
+
+static int lgdt3304_i2c_read_reg(struct dvb_frontend *fe, unsigned int reg)
+{
+	struct lgdt3304_state *state = fe->demodulator_priv;
+	struct i2c_msg i2cmsgs[2];
+	int ret;
+	__u8 buf;
+
+	__u8 regbuf[2] = { reg>>8, reg&0xff };
+
+	i2cmsgs[0].addr = state->addr;
+	i2cmsgs[0].flags = 0;
+	i2cmsgs[0].len = 2;
+	i2cmsgs[0].buf = regbuf;
+
+	i2cmsgs[1].addr = state->addr;
+	i2cmsgs[1].flags = I2C_M_RD;
+	i2cmsgs[1].len = 1;
+	i2cmsgs[1].buf = &buf;
+
+	if((ret = i2c_transfer(state->i2c, i2cmsgs, 2))<0) {
+		printk("%s i2c_transfer error %d\n", __FUNCTION__, ret);
+		return ret;
+	}
+
+	return buf;
+}
+
+static int lgdt3304_i2c_write_reg(struct dvb_frontend *fe, int reg, int val)
+{
+	struct lgdt3304_state *state = fe->demodulator_priv;
+	char buffer[3] = { reg>>8, reg&0xff, val };
+	int ret;
+
+	struct i2c_msg i2cmsgs = {
+		.addr = state->addr,
+		.flags = 0,
+		.len = 3,
+		.buf=buffer
+	};
+	ret = i2c_transfer(state->i2c, &i2cmsgs, 1);
+	if (ret != 1) {
+		printk("%s i2c_transfer error %d\n", __FUNCTION__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+
+static int lgdt3304_soft_Reset(struct dvb_frontend *fe)
+{
+	lgdt3304_i2c_write_reg(fe, 0x0002, 0x9a);
+	lgdt3304_i2c_write_reg(fe, 0x0002, 0x9b);
+	mdelay(200);
+	return 0;
+}
+
+static int lgdt3304_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
+	int err = 0;
+
+	static __u8 lgdt3304_vsb8_data[] = {
+		/* 16bit  , 8bit */
+		/* regs   , val  */
+		0x00, 0x00, 0x02,
+		0x00, 0x00, 0x13,
+		0x00, 0x0d, 0x02,
+		0x00, 0x0e, 0x02,
+		0x00, 0x12, 0x32,
+		0x00, 0x13, 0xc4,
+		0x01, 0x12, 0x17,
+		0x01, 0x13, 0x15,
+		0x01, 0x14, 0x18,
+		0x01, 0x15, 0xff,
+		0x01, 0x16, 0x2c,
+		0x02, 0x14, 0x67,
+		0x02, 0x24, 0x8d,
+		0x04, 0x27, 0x12,
+		0x04, 0x28, 0x4f,
+		0x03, 0x08, 0x80,
+		0x03, 0x09, 0x00,
+		0x03, 0x0d, 0x00,
+		0x03, 0x0e, 0x1c,
+		0x03, 0x14, 0xe1,
+		0x05, 0x0e, 0x5b,
+	};
+
+	/* not yet tested .. */
+	static __u8 lgdt3304_qam64_data[] = {
+		/* 16bit  , 8bit */
+		/* regs   , val  */
+		0x00, 0x00, 0x18,
+		0x00, 0x0d, 0x02,
+		//0x00, 0x0e, 0x02,
+		0x00, 0x12, 0x2a,
+		0x00, 0x13, 0x00,
+		0x03, 0x14, 0xe3,
+		0x03, 0x0e, 0x1c,
+		0x03, 0x08, 0x66,
+		0x03, 0x09, 0x66,
+		0x03, 0x0a, 0x08,
+		0x03, 0x0b, 0x9b,
+		0x05, 0x0e, 0x5b,
+	};
+
+
+	/* tested with KWorld a340 */
+	static __u8 lgdt3304_qam256_data[] = {
+		/* 16bit  , 8bit */
+		/* regs   , val  */
+		0x00, 0x00, 0x01,  //0x19,
+		0x00, 0x12, 0x2a,
+		0x00, 0x13, 0x80,
+		0x00, 0x0d, 0x02,
+		0x03, 0x14, 0xe3,
+
+		0x03, 0x0e, 0x1c,
+		0x03, 0x08, 0x66,
+		0x03, 0x09, 0x66,
+		0x03, 0x0a, 0x08,
+		0x03, 0x0b, 0x9b,
+
+		0x03, 0x0d, 0x14,
+		//0x05, 0x0e, 0x5b,
+		0x01, 0x06, 0x4a,
+		0x01, 0x07, 0x3d,
+		0x01, 0x08, 0x70,
+		0x01, 0x09, 0xa3,
+
+		0x05, 0x04, 0xfd,
+
+		0x00, 0x0d, 0x82,
+
+		0x05, 0x0e, 0x5b,
+
+		0x05, 0x0e, 0x5b,
+
+		0x00, 0x02, 0x9a,
+
+		0x00, 0x02, 0x9b,
+
+		0x00, 0x00, 0x01,
+		0x00, 0x12, 0x2a,
+		0x00, 0x13, 0x80,
+		0x00, 0x0d, 0x02,
+		0x03, 0x14, 0xe3,
+
+		0x03, 0x0e, 0x1c,
+		0x03, 0x08, 0x66,
+		0x03, 0x09, 0x66,
+		0x03, 0x0a, 0x08,
+		0x03, 0x0b, 0x9b,
+
+		0x03, 0x0d, 0x14,
+		0x01, 0x06, 0x4a,
+		0x01, 0x07, 0x3d,
+		0x01, 0x08, 0x70,
+		0x01, 0x09, 0xa3,
+
+		0x05, 0x04, 0xfd,
+
+		0x00, 0x0d, 0x82,
+
+		0x05, 0x0e, 0x5b,
+	};
+
+	struct lgdt3304_state *state = fe->demodulator_priv;
+	if (state->current_modulation != param->u.vsb.modulation) {
+		switch(param->u.vsb.modulation) {
+		case VSB_8:
+			err = i2c_write_demod_bytes(fe, lgdt3304_vsb8_data,
+					sizeof(lgdt3304_vsb8_data));
+			break;
+		case QAM_64:
+			err = i2c_write_demod_bytes(fe, lgdt3304_qam64_data,
+					sizeof(lgdt3304_qam64_data));
+			break;
+		case QAM_256:
+			err = i2c_write_demod_bytes(fe, lgdt3304_qam256_data,
+					sizeof(lgdt3304_qam256_data));
+			break;
+		default:
+			break;
+		}
+
+		if (err) {
+			printk("%s error setting modulation\n", __FUNCTION__);
+		} else {
+			state->current_modulation = param->u.vsb.modulation;
+		}
+	}
+	state->current_frequency = param->frequency;
+
+	lgdt3304_soft_Reset(fe);
+
+
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe, param);
+
+	return 0;
+}
+
+static int lgdt3304_init(struct dvb_frontend *fe) {
+	return 0;
+}
+
+static int lgdt3304_sleep(struct dvb_frontend *fe) {
+	return 0;
+}
+
+
+static int lgdt3304_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct lgdt3304_state *state = fe->demodulator_priv;
+	int r011d;
+	int qam_lck;
+
+	*status = 0;
+	dprintk("lgdt read status\n");
+
+	r011d = lgdt3304_i2c_read_reg(fe, 0x011d);
+
+	dprintk("%02x\n", r011d);
+
+	switch(state->current_modulation) {
+	case VSB_8:
+		if (r011d & 0x80) {
+			dprintk("VSB Locked\n");
+			*status |= FE_HAS_CARRIER;
+			*status |= FE_HAS_LOCK;
+			*status |= FE_HAS_SYNC;
+			*status |= FE_HAS_SIGNAL;
+		}
+		break;
+	case QAM_64:
+	case QAM_256:
+		qam_lck = r011d & 0x7;
+		switch(qam_lck) {
+			case 0x0: dprintk("Unlock\n");
+				  break;
+			case 0x4: dprintk("1st Lock in acquisition state\n");
+				  break;
+			case 0x6: dprintk("2nd Lock in acquisition state\n");
+				  break;
+			case 0x7: dprintk("Final Lock in good reception state\n");
+				  *status |= FE_HAS_CARRIER;
+				  *status |= FE_HAS_LOCK;
+				  *status |= FE_HAS_SYNC;
+				  *status |= FE_HAS_SIGNAL;
+				  break;
+		}
+		break;
+	default:
+		printk("%s unhandled modulation\n", __FUNCTION__);
+	}
+
+
+	return 0;
+}
+
+static int lgdt3304_read_ber(struct dvb_frontend *fe, __u32 *ber)
+{
+	dprintk("read ber\n");
+	return 0;
+}
+
+static int lgdt3304_read_snr(struct dvb_frontend *fe, __u16 *snr)
+{
+	dprintk("read snr\n");
+	return 0;
+}
+
+static int lgdt3304_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
+{
+	dprintk("read ucblocks\n");
+	return 0;
+}
+
+static void lgdt3304_release(struct dvb_frontend *fe)
+{
+	struct lgdt3304_state *state = (struct lgdt3304_state *)fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops demod_lgdt3304={
+	.info = {
+		.name = "LG 3304",
+		.type = FE_ATSC,
+		.frequency_min = 54000000,
+		.frequency_max = 858000000,
+		.frequency_stepsize = 62500,
+		.symbol_rate_min = 5056941,
+		.symbol_rate_max = 10762000,
+		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+	.init = lgdt3304_init,
+	.sleep = lgdt3304_sleep,
+	.set_frontend = lgdt3304_set_parameters,
+	.read_snr = lgdt3304_read_snr,
+	.read_ber = lgdt3304_read_ber,
+	.read_status = lgdt3304_read_status,
+	.read_ucblocks = lgdt3304_read_ucblocks,
+	.release = lgdt3304_release,
+};
+
+struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
+					   struct i2c_adapter *i2c)
+{
+
+	struct lgdt3304_state *state;
+	state = kzalloc(sizeof(struct lgdt3304_state), GFP_KERNEL);
+	memset(state, 0x0, sizeof(struct lgdt3304_state));
+	state->addr = config->i2c_address;
+	state->i2c = i2c;
+
+	memcpy(&state->frontend.ops, &demod_lgdt3304, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+}
+
+EXPORT_SYMBOL_GPL(lgdt3304_attach);
+MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>");
+MODULE_DESCRIPTION("LGE LGDT3304 DVB-T demodulator driver");
+MODULE_LICENSE("GPL");

+ 45 - 0
drivers/media/dvb/frontends/lgdt3304.h

@@ -0,0 +1,45 @@
+/*
+ *  Driver for DVB-T lgdt3304 demodulator
+ *
+ *  Copyright (C) 2008 Markus Rechberger <mrechberger@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#ifndef LGDT3304_H
+#define LGDT3304_H
+
+#include <linux/dvb/frontend.h>
+
+struct lgdt3304_config
+{
+	/* demodulator's I2C address */
+	u8 i2c_address;
+};
+
+#if defined(CONFIG_DVB_LGDT3304) || (defined(CONFIG_DVB_LGDT3304_MODULE) && defined(MODULE))
+extern struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
+					   struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* lgdt3304_attach(const struct lgdt3304_config *config,
+					   struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_LGDT */
+
+#endif /* LGDT3304_H */

+ 3 - 0
drivers/media/dvb/frontends/s5h1411.c

@@ -874,6 +874,9 @@ struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
 	/* Note: Leaving the I2C gate open here. */
 	s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
 
+	/* Put the device into low-power mode until first use */
+	s5h1411_set_powerstate(&state->frontend, 1);
+
 	return &state->frontend;
 
 error:

+ 216 - 0
drivers/media/dvb/frontends/s921_core.c

@@ -0,0 +1,216 @@
+/*
+ * Driver for Sharp s921 driver
+ *
+ * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
+ *
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include "s921_core.h"
+
+static int s921_isdb_init(struct s921_isdb_t *dev);
+static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params);
+static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params);
+static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data);
+
+static u8 init_table[]={ 0x01, 0x40, 0x02, 0x00, 0x03, 0x40, 0x04, 0x01,
+			 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00,
+			 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x5a, 0x0c, 0x00,
+			 0x0d, 0x00, 0x0f, 0x00, 0x13, 0x1b, 0x14, 0x80,
+			 0x15, 0x40, 0x17, 0x70, 0x18, 0x01, 0x19, 0x12,
+			 0x1a, 0x01, 0x1b, 0x12, 0x1c, 0xa0, 0x1d, 0x00,
+			 0x1e, 0x0a, 0x1f, 0x08, 0x20, 0x40, 0x21, 0xff,
+			 0x22, 0x4c, 0x23, 0x4e, 0x24, 0x4c, 0x25, 0x00,
+			 0x26, 0x00, 0x27, 0xf4, 0x28, 0x60, 0x29, 0x88,
+			 0x2a, 0x40, 0x2b, 0x40, 0x2c, 0xff, 0x2d, 0x00,
+			 0x2e, 0xff, 0x2f, 0x00, 0x30, 0x20, 0x31, 0x06,
+			 0x32, 0x0c, 0x34, 0x0f, 0x37, 0xfe, 0x38, 0x00,
+			 0x39, 0x63, 0x3a, 0x10, 0x3b, 0x10, 0x47, 0x00,
+			 0x49, 0xe5, 0x4b, 0x00, 0x50, 0xc0, 0x52, 0x20,
+			 0x54, 0x5a, 0x55, 0x5b, 0x56, 0x40, 0x57, 0x70,
+			 0x5c, 0x50, 0x5d, 0x00, 0x62, 0x17, 0x63, 0x2f,
+			 0x64, 0x6f, 0x68, 0x00, 0x69, 0x89, 0x6a, 0x00,
+			 0x6b, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00,
+			 0x70, 0x00, 0x71, 0x00, 0x75, 0x00, 0x76, 0x30,
+			 0x77, 0x01, 0xaf, 0x00, 0xb0, 0xa0, 0xb2, 0x3d,
+			 0xb3, 0x25, 0xb4, 0x8b, 0xb5, 0x4b, 0xb6, 0x3f,
+			 0xb7, 0xff, 0xb8, 0xff, 0xb9, 0xfc, 0xba, 0x00,
+			 0xbb, 0x00, 0xbc, 0x00, 0xd0, 0x30, 0xe4, 0x84,
+			 0xf0, 0x48, 0xf1, 0x19, 0xf2, 0x5a, 0xf3, 0x8e,
+			 0xf4, 0x2d, 0xf5, 0x07, 0xf6, 0x5a, 0xf7, 0xba,
+			 0xf8, 0xd7 };
+
+static u8 c_table[]={ 0x58, 0x8a, 0x7b, 0x59, 0x8c, 0x7b, 0x5a, 0x8e, 0x5b,
+		      0x5b, 0x90, 0x5b, 0x5c, 0x92, 0x5b, 0x5d, 0x94, 0x5b,
+		      0x5e, 0x96, 0x5b, 0x5f, 0x98, 0x3b, 0x60, 0x9a, 0x3b,
+		      0x61, 0x9c, 0x3b, 0x62, 0x9e, 0x3b, 0x63, 0xa0, 0x3b,
+		      0x64, 0xa2, 0x1b, 0x65, 0xa4, 0x1b, 0x66, 0xa6, 0x1b,
+		      0x67, 0xa8, 0x1b, 0x68, 0xaa, 0x1b, 0x69, 0xac, 0x1b,
+		      0x6a, 0xae, 0x1b, 0x6b, 0xb0, 0x1b, 0x6c, 0xb2, 0x1b,
+		      0x6d, 0xb4, 0xfb, 0x6e, 0xb6, 0xfb, 0x6f, 0xb8, 0xfb,
+		      0x70, 0xba, 0xfb, 0x71, 0xbc, 0xdb, 0x72, 0xbe, 0xdb,
+		      0x73, 0xc0, 0xdb, 0x74, 0xc2, 0xdb, 0x75, 0xc4, 0xdb,
+		      0x76, 0xc6, 0xdb, 0x77, 0xc8, 0xbb, 0x78, 0xca, 0xbb,
+		      0x79, 0xcc, 0xbb, 0x7a, 0xce, 0xbb, 0x7b, 0xd0, 0xbb,
+		      0x7c, 0xd2, 0xbb, 0x7d, 0xd4, 0xbb, 0x7e, 0xd6, 0xbb,
+		      0x7f, 0xd8, 0xbb, 0x80, 0xda, 0x9b, 0x81, 0xdc, 0x9b,
+		      0x82, 0xde, 0x9b, 0x83, 0xe0, 0x9b, 0x84, 0xe2, 0x9b,
+		      0x85, 0xe4, 0x9b, 0x86, 0xe6, 0x9b, 0x87, 0xe8, 0x9b,
+		      0x88, 0xea, 0x9b, 0x89, 0xec, 0x9b };
+
+int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data) {
+	switch(cmd) {
+	case ISDB_T_CMD_INIT:
+		s921_isdb_init(dev);
+		break;
+	case ISDB_T_CMD_SET_PARAM:
+		s921_isdb_set_parameters(dev, data);
+		break;
+	case ISDB_T_CMD_TUNE:
+		s921_isdb_tune(dev, data);
+		break;
+	case ISDB_T_CMD_GET_STATUS:
+		s921_isdb_get_status(dev, data);
+		break;
+	default:
+		printk("unhandled command\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int s921_isdb_init(struct s921_isdb_t *dev) {
+	unsigned int i;
+	unsigned int ret;
+	printk("isdb_init\n");
+	for (i = 0; i < sizeof(init_table); i+=2) {
+		ret = dev->i2c_write(dev->priv_dev, init_table[i], init_table[i+1]);
+		if (ret != 0) {
+			printk("i2c write failed\n");
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params) {
+
+	int ret;
+	/* auto is sufficient for now, lateron this should be reflected in an extra interface */
+
+
+
+	ret = dev->i2c_write(dev->priv_dev, 0xb0, 0xa0); //mod_b2);
+	ret = dev->i2c_write(dev->priv_dev, 0xb2, 0x3d); //mod_b2);
+
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xb3, 0x25); //mod_b3);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xb4, 0x8b); //mod_b4);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xb5, 0x4b); //mod_b5);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xb6, 0x3f); //mod_b6);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xb7, 0x3f); //mod_b7);
+	if (ret < 0)
+		return -EINVAL;
+
+	return E_OK;
+}
+
+static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params) {
+
+	int ret;
+	int index;
+
+	index = (params->frequency - 473143000)/6000000;
+
+	if (index > 48) {
+		return -EINVAL;
+	}
+
+	dev->i2c_write(dev->priv_dev, 0x47, 0x60);
+
+	ret = dev->i2c_write(dev->priv_dev, 0x68, 0x00);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0x69, 0x89);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xf0, 0x48);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xf1, 0x19);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xf2, c_table[index*3]);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xf3, c_table[index*3+1]);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xf4, c_table[index*3+2]);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xf5, 0xae);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xf6, 0xb7);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xf7, 0xba);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0xf8, 0xd7);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0x68, 0x0a);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = dev->i2c_write(dev->priv_dev, 0x69, 0x09);
+	if (ret < 0)
+		return -EINVAL;
+
+	dev->i2c_write(dev->priv_dev, 0x01, 0x40);
+	return 0;
+}
+
+static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data) {
+	unsigned int *ret = (unsigned int*)data;
+	u8 ifagc_dt;
+	u8 rfagc_dt;
+
+	mdelay(10);
+	ifagc_dt = dev->i2c_read(dev->priv_dev, 0x81);
+	rfagc_dt = dev->i2c_read(dev->priv_dev, 0x82);
+	if (rfagc_dt == 0x40) {
+		*ret = 1;
+	}
+	return 0;
+}

+ 114 - 0
drivers/media/dvb/frontends/s921_core.h

@@ -0,0 +1,114 @@
+#ifndef _S921_CORE_H
+#define _S921_CORE_H
+//#define u8 unsigned int
+//#define u32 unsigned int
+
+
+
+//#define EINVAL -1
+#define E_OK 0
+
+struct s921_isdb_t {
+	void *priv_dev;
+	int (*i2c_write)(void *dev, u8 reg, u8 val);
+	int (*i2c_read)(void *dev, u8 reg);
+};
+
+#define ISDB_T_CMD_INIT       0
+#define ISDB_T_CMD_SET_PARAM  1
+#define ISDB_T_CMD_TUNE       2
+#define ISDB_T_CMD_GET_STATUS 3
+
+struct s921_isdb_t_tune_params {
+	u32 frequency;
+};
+
+struct s921_isdb_t_status {
+};
+
+struct s921_isdb_t_transmission_mode_params {
+	u8 mode;
+	u8 layer_a_mode;
+#define ISDB_T_LA_MODE_1 0
+#define ISDB_T_LA_MODE_2 1
+#define ISDB_T_LA_MODE_3 2
+	u8 layer_a_carrier_modulation;
+#define ISDB_T_LA_CM_DQPSK 0
+#define ISDB_T_LA_CM_QPSK  1
+#define ISDB_T_LA_CM_16QAM 2
+#define ISDB_T_LA_CM_64QAM 3
+#define ISDB_T_LA_CM_NOLAYER 4
+	u8 layer_a_code_rate;
+#define ISDB_T_LA_CR_1_2   0
+#define ISDB_T_LA_CR_2_3   1
+#define ISDB_T_LA_CR_3_4   2
+#define ISDB_T_LA_CR_5_6   4
+#define ISDB_T_LA_CR_7_8   8
+#define ISDB_T_LA_CR_NOLAYER   16
+	u8 layer_a_time_interleave;
+#define ISDB_T_LA_TI_0  0
+#define ISDB_T_LA_TI_1  1
+#define ISDB_T_LA_TI_2  2
+#define ISDB_T_LA_TI_4  4
+#define ISDB_T_LA_TI_8  8
+#define ISDB_T_LA_TI_16 16
+#define ISDB_T_LA_TI_32 32
+	u8 layer_a_nseg;
+
+	u8 layer_b_mode;
+#define ISDB_T_LB_MODE_1 0
+#define ISDB_T_LB_MODE_2 1
+#define ISDB_T_LB_MODE_3 2
+	u8 layer_b_carrier_modulation;
+#define ISDB_T_LB_CM_DQPSK 0
+#define ISDB_T_LB_CM_QPSK  1
+#define ISDB_T_LB_CM_16QAM 2
+#define ISDB_T_LB_CM_64QAM 3
+#define ISDB_T_LB_CM_NOLAYER 4
+	u8 layer_b_code_rate;
+#define ISDB_T_LB_CR_1_2   0
+#define ISDB_T_LB_CR_2_3   1
+#define ISDB_T_LB_CR_3_4   2
+#define ISDB_T_LB_CR_5_6   4
+#define ISDB_T_LB_CR_7_8   8
+#define ISDB_T_LB_CR_NOLAYER   16
+	u8 layer_b_time_interleave;
+#define ISDB_T_LB_TI_0  0
+#define ISDB_T_LB_TI_1  1
+#define ISDB_T_LB_TI_2  2
+#define ISDB_T_LB_TI_4  4
+#define ISDB_T_LB_TI_8  8
+#define ISDB_T_LB_TI_16 16
+#define ISDB_T_LB_TI_32 32
+	u8 layer_b_nseg;
+
+	u8 layer_c_mode;
+#define ISDB_T_LC_MODE_1 0
+#define ISDB_T_LC_MODE_2 1
+#define ISDB_T_LC_MODE_3 2
+	u8 layer_c_carrier_modulation;
+#define ISDB_T_LC_CM_DQPSK 0
+#define ISDB_T_LC_CM_QPSK  1
+#define ISDB_T_LC_CM_16QAM 2
+#define ISDB_T_LC_CM_64QAM 3
+#define ISDB_T_LC_CM_NOLAYER 4
+	u8 layer_c_code_rate;
+#define ISDB_T_LC_CR_1_2   0
+#define ISDB_T_LC_CR_2_3   1
+#define ISDB_T_LC_CR_3_4   2
+#define ISDB_T_LC_CR_5_6   4
+#define ISDB_T_LC_CR_7_8   8
+#define ISDB_T_LC_CR_NOLAYER   16
+	u8 layer_c_time_interleave;
+#define ISDB_T_LC_TI_0  0
+#define ISDB_T_LC_TI_1  1
+#define ISDB_T_LC_TI_2  2
+#define ISDB_T_LC_TI_4  4
+#define ISDB_T_LC_TI_8  8
+#define ISDB_T_LC_TI_16 16
+#define ISDB_T_LC_TI_32 32
+	u8 layer_c_nseg;
+};
+
+int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data);
+#endif

+ 190 - 0
drivers/media/dvb/frontends/s921_module.c

@@ -0,0 +1,190 @@
+/*
+ * Driver for Sharp s921 driver
+ *
+ * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
+ *
+ * All rights reserved.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "s921_module.h"
+#include "s921_core.h"
+
+static  unsigned int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"s921 debugging (default off)");
+
+#define dprintk(fmt, args...) if (debug) do {\
+			printk("s921 debug: " fmt, ##args); } while (0)
+
+struct s921_state
+{
+	struct dvb_frontend frontend;
+	fe_modulation_t current_modulation;
+	__u32 snr;
+	__u32 current_frequency;
+	__u8 addr;
+	struct s921_isdb_t dev;
+	struct i2c_adapter *i2c;
+};
+
+static int s921_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) {
+	struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
+	struct s921_isdb_t_transmission_mode_params params;
+	struct s921_isdb_t_tune_params tune_params;
+
+	tune_params.frequency = param->frequency;
+	s921_isdb_cmd(&state->dev, ISDB_T_CMD_SET_PARAM, &params);
+	s921_isdb_cmd(&state->dev, ISDB_T_CMD_TUNE, &tune_params);
+	mdelay(100);
+	return 0;
+}
+
+static int s921_init(struct dvb_frontend *fe) {
+	printk("s921 init\n");
+	return 0;
+}
+
+static int s921_sleep(struct dvb_frontend *fe) {
+	printk("s921 sleep\n");
+	return 0;
+}
+
+static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
+	unsigned int ret;
+	mdelay(5);
+	s921_isdb_cmd(&state->dev, ISDB_T_CMD_GET_STATUS, &ret);
+	*status = 0;
+
+	printk("status: %02x\n", ret);
+	if (ret == 1) {
+		*status |= FE_HAS_CARRIER;
+		*status |= FE_HAS_VITERBI;
+		*status |= FE_HAS_LOCK;
+		*status |= FE_HAS_SYNC;
+		*status |= FE_HAS_SIGNAL;
+	}
+
+	return 0;
+}
+
+static int s921_read_ber(struct dvb_frontend *fe, __u32 *ber)
+{
+	dprintk("read ber\n");
+	return 0;
+}
+
+static int s921_read_snr(struct dvb_frontend *fe, __u16 *snr)
+{
+	dprintk("read snr\n");
+	return 0;
+}
+
+static int s921_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks)
+{
+	dprintk("read ucblocks\n");
+	return 0;
+}
+
+static void s921_release(struct dvb_frontend *fe)
+{
+	struct s921_state *state = (struct s921_state *)fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops demod_s921={
+	.info = {
+		.name			= "SHARP S921",
+		.type			= FE_OFDM,
+		.frequency_min		= 473143000,
+		.frequency_max		= 767143000,
+		.frequency_stepsize	=   6000000,
+		.frequency_tolerance	= 0,
+		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+			FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
+			FE_CAN_MUTE_TS
+	},
+	.init = s921_init,
+	.sleep = s921_sleep,
+	.set_frontend = s921_set_parameters,
+	.read_snr = s921_read_snr,
+	.read_ber = s921_read_ber,
+	.read_status = s921_read_status,
+	.read_ucblocks = s921_read_ucblocks,
+	.release = s921_release,
+};
+
+static int s921_write(void *dev, u8 reg, u8 val) {
+	struct s921_state *state = dev;
+	char buf[2]={reg,val};
+	int err;
+	struct i2c_msg i2cmsgs = {
+		.addr = state->addr,
+		.flags = 0,
+		.len = 2,
+		.buf = buf
+	};
+
+	if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) {
+		printk("%s i2c_transfer error %d\n", __FUNCTION__, err);
+		if (err < 0)
+			return err;
+		else
+			return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int s921_read(void *dev, u8 reg) {
+	struct s921_state *state = dev;
+	u8 b1;
+	int ret;
+	struct i2c_msg msg[2] = { { .addr = state->addr,
+				    .flags = 0,
+				    .buf = &reg, .len = 1 },
+				  { .addr = state->addr,
+				    .flags = I2C_M_RD,
+				    .buf = &b1, .len = 1 } };
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret != 2)
+		return ret;
+	return b1;
+}
+
+struct dvb_frontend* s921_attach(const struct s921_config *config,
+					   struct i2c_adapter *i2c)
+{
+
+	struct s921_state *state;
+	state = kzalloc(sizeof(struct s921_state), GFP_KERNEL);
+	memset(state, 0x0, sizeof(struct s921_state));
+
+	state->addr = config->i2c_address;
+	state->i2c = i2c;
+	state->dev.i2c_write = &s921_write;
+	state->dev.i2c_read = &s921_read;
+	state->dev.priv_dev = state;
+
+	s921_isdb_cmd(&state->dev, ISDB_T_CMD_INIT, NULL);
+
+	memcpy(&state->frontend.ops, &demod_s921, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+}
+
+EXPORT_SYMBOL_GPL(s921_attach);
+MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>");
+MODULE_DESCRIPTION("Sharp S921 ISDB-T 1Seg");
+MODULE_LICENSE("GPL");

+ 49 - 0
drivers/media/dvb/frontends/s921_module.h

@@ -0,0 +1,49 @@
+/*
+ *  Driver for DVB-T s921 demodulator
+ *
+ *  Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; 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 S921_MODULE_H
+#define S921_MODULE_H
+
+#include <linux/dvb/frontend.h>
+#include "s921_core.h"
+
+int s921_isdb_init(struct s921_isdb_t *dev);
+int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data);
+
+struct s921_config
+{
+	/* demodulator's I2C address */
+	u8 i2c_address;
+};
+
+#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) && defined(MODULE))
+extern struct dvb_frontend* s921_attach(const struct s921_config *config,
+					   struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* s921_attach(const struct s921_config *config,
+					   struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_S921 */
+
+#endif /* S921_H */

+ 0 - 1
drivers/media/dvb/frontends/si21xx.c

@@ -8,7 +8,6 @@
 *	(at your option) any later version.
 *
 */
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>

+ 1519 - 0
drivers/media/dvb/frontends/stb0899_algo.c

@@ -0,0 +1,1519 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "stb0899_drv.h"
+#include "stb0899_priv.h"
+#include "stb0899_reg.h"
+
+inline u32 stb0899_do_div(u64 n, u32 d)
+{
+	/* wrap do_div() for ease of use */
+
+	do_div(n, d);
+	return n;
+}
+
+/*
+ * stb0899_calc_srate
+ * Compute symbol rate
+ */
+static u32 stb0899_calc_srate(u32 master_clk, u8 *sfr)
+{
+	u64 tmp;
+
+	/* srate = (SFR * master_clk) >> 20 */
+
+	/* sfr is of size 20 bit, stored with an offset of 4 bit */
+	tmp = (((u32)sfr[0]) << 16) | (((u32)sfr[1]) << 8) | sfr[2];
+	tmp &= ~0xf;
+	tmp *= master_clk;
+	tmp >>= 24;
+
+	return tmp;
+}
+
+/*
+ * stb0899_get_srate
+ * Get the current symbol rate
+ */
+u32 stb0899_get_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u8 sfr[3];
+
+	stb0899_read_regs(state, STB0899_SFRH, sfr, 3);
+
+	return stb0899_calc_srate(internal->master_clk, sfr);
+}
+
+/*
+ * stb0899_set_srate
+ * Set symbol frequency
+ * MasterClock: master clock frequency (hz)
+ * SymbolRate: symbol rate (bauds)
+ * return symbol frequency
+ */
+static u32 stb0899_set_srate(struct stb0899_state *state, u32 master_clk, u32 srate)
+{
+	u32 tmp;
+	u8 sfr[3];
+
+	dprintk(state->verbose, FE_DEBUG, 1, "-->");
+	/*
+	 * in order to have the maximum precision, the symbol rate entered into
+	 * the chip is computed as the closest value of the "true value".
+	 * In this purpose, the symbol rate value is rounded (1 is added on the bit
+	 * below the LSB )
+	 *
+	 * srate = (SFR * master_clk) >> 20
+	 *      <=>
+	 *   SFR = srate << 20 / master_clk
+	 *
+	 * rounded:
+	 *   SFR = (srate << 21 + master_clk) / (2 * master_clk)
+	 *
+	 * stored as 20 bit number with an offset of 4 bit:
+	 *   sfr = SFR << 4;
+	 */
+
+	tmp = stb0899_do_div((((u64)srate) << 21) + master_clk, 2 * master_clk);
+	tmp <<= 4;
+
+	sfr[0] = tmp >> 16;
+	sfr[1] = tmp >>  8;
+	sfr[2] = tmp;
+
+	stb0899_write_regs(state, STB0899_SFRH, sfr, 3);
+
+	return srate;
+}
+
+/*
+ * stb0899_calc_derot_time
+ * Compute the amount of time needed by the derotator to lock
+ * SymbolRate: Symbol rate
+ * return: derotator time constant (ms)
+ */
+static long stb0899_calc_derot_time(long srate)
+{
+	if (srate > 0)
+		return (100000 / (srate / 1000));
+	else
+		return 0;
+}
+
+/*
+ * stb0899_carr_width
+ * Compute the width of the carrier
+ * return: width of carrier (kHz or Mhz)
+ */
+long stb0899_carr_width(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	return (internal->srate + (internal->srate * internal->rolloff) / 100);
+}
+
+/*
+ * stb0899_first_subrange
+ * Compute the first subrange of the search
+ */
+static void stb0899_first_subrange(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_params *params		= &state->params;
+	struct stb0899_config *config		=  state->config;
+
+	int range = 0;
+	u32 bandwidth = 0;
+
+	if (config->tuner_get_bandwidth) {
+		stb0899_i2c_gate_ctrl(&state->frontend, 1);
+		config->tuner_get_bandwidth(&state->frontend, &bandwidth);
+		stb0899_i2c_gate_ctrl(&state->frontend, 0);
+		range = bandwidth - stb0899_carr_width(state) / 2;
+	}
+
+	if (range > 0)
+		internal->sub_range = MIN(internal->srch_range, range);
+	else
+		internal->sub_range = 0;
+
+	internal->freq = params->freq;
+	internal->tuner_offst = 0L;
+	internal->sub_dir = 1;
+}
+
+/*
+ * stb0899_check_tmg
+ * check for timing lock
+ * internal.Ttiming: time to wait for loop lock
+ */
+static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	int lock;
+	u8 reg;
+	s8 timing;
+
+	msleep(internal->t_derot);
+
+	stb0899_write_reg(state, STB0899_RTF, 0xf2);
+	reg = stb0899_read_reg(state, STB0899_TLIR);
+	lock = STB0899_GETFIELD(TLIR_TMG_LOCK_IND, reg);
+	timing = stb0899_read_reg(state, STB0899_RTF);
+
+	if (lock >= 42) {
+		if ((lock > 48) && (ABS(timing) >= 110)) {
+			internal->status = ANALOGCARRIER;
+			dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !");
+		} else {
+			internal->status = TIMINGOK;
+			dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK !");
+		}
+	} else {
+		internal->status = NOTIMING;
+		dprintk(state->verbose, FE_DEBUG, 1, "-->NO TIMING !");
+	}
+	return internal->status;
+}
+
+/*
+ * stb0899_search_tmg
+ * perform a fs/2 zig-zag to find timing
+ */
+static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	short int derot_step, derot_freq = 0, derot_limit, next_loop = 3;
+	int index = 0;
+	u8 cfr[2];
+
+	internal->status = NOTIMING;
+
+	/* timing loop computation & symbol rate optimisation	*/
+	derot_limit = (internal->sub_range / 2L) / internal->mclk;
+	derot_step = (params->srate / 2L) / internal->mclk;
+
+	while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) {
+		index++;
+		derot_freq += index * internal->direction * derot_step;	/* next derot zig zag position	*/
+
+		if (ABS(derot_freq) > derot_limit)
+			next_loop--;
+
+		if (next_loop) {
+			STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+			STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+			stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency		*/
+		}
+		internal->direction = -internal->direction;	/* Change zigzag direction		*/
+	}
+
+	if (internal->status == TIMINGOK) {
+		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency		*/
+		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+		dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK ! Derot Freq = %d", internal->derot_freq);
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_check_carrier
+ * Check for carrier found
+ */
+static enum stb0899_status stb0899_check_carrier(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u8 reg;
+
+	msleep(internal->t_derot); /* wait for derotator ok	*/
+
+	reg = stb0899_read_reg(state, STB0899_CFD);
+	STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+	stb0899_write_reg(state, STB0899_CFD, reg);
+
+	reg = stb0899_read_reg(state, STB0899_DSTATUS);
+	dprintk(state->verbose, FE_DEBUG, 1, "--------------------> STB0899_DSTATUS=[0x%02x]", reg);
+	if (STB0899_GETFIELD(CARRIER_FOUND, reg)) {
+		internal->status = CARRIEROK;
+		dprintk(state->verbose, FE_DEBUG, 1, "-------------> CARRIEROK !");
+	} else {
+		internal->status = NOCARRIER;
+		dprintk(state->verbose, FE_DEBUG, 1, "-------------> NOCARRIER !");
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_search_carrier
+ * Search for a QPSK carrier with the derotator
+ */
+static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3;
+	int index = 0;
+	u8 cfr[2];
+	u8 reg;
+
+	internal->status = NOCARRIER;
+	derot_limit = (internal->sub_range / 2L) / internal->mclk;
+	derot_freq = internal->derot_freq;
+
+	reg = stb0899_read_reg(state, STB0899_CFD);
+	STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+	stb0899_write_reg(state, STB0899_CFD, reg);
+
+	do {
+		dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk);
+		if (stb0899_check_carrier(state) == NOCARRIER) {
+			index++;
+			last_derot_freq = derot_freq;
+			derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */
+
+			if(ABS(derot_freq) > derot_limit)
+				next_loop--;
+
+			if (next_loop) {
+				reg = stb0899_read_reg(state, STB0899_CFD);
+				STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+				stb0899_write_reg(state, STB0899_CFD, reg);
+
+				STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+				STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+				stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency	*/
+			}
+		}
+
+		internal->direction = -internal->direction; /* Change zigzag direction */
+	} while ((internal->status != CARRIEROK) && next_loop);
+
+	if (internal->status == CARRIEROK) {
+		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */
+		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+		dprintk(state->verbose, FE_DEBUG, 1, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq);
+	} else {
+		internal->derot_freq = last_derot_freq;
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_check_data
+ * Check for data found
+ */
+static enum stb0899_status stb0899_check_data(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	int lock = 0, index = 0, dataTime = 500, loop;
+	u8 reg;
+
+	internal->status = NODATA;
+
+	/* RESET FEC	*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESACS, reg, 1);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+	msleep(1);
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESACS, reg, 0);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	if (params->srate <= 2000000)
+		dataTime = 2000;
+	else if (params->srate <= 5000000)
+		dataTime = 1500;
+	else if (params->srate <= 15000000)
+		dataTime = 1000;
+	else
+		dataTime = 500;
+
+	stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop	*/
+	while (1) {
+		/* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP	*/
+		reg = stb0899_read_reg(state, STB0899_VSTATUS);
+		lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg);
+		loop = STB0899_GETFIELD(VSTATUS_END_LOOPVIT, reg);
+
+		if (lock || loop || (index > dataTime))
+			break;
+		index++;
+	}
+
+	if (lock) {	/* DATA LOCK indicator	*/
+		internal->status = DATAOK;
+		dprintk(state->verbose, FE_DEBUG, 1, "-----------------> DATA OK !");
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_search_data
+ * Search for a QPSK carrier with the derotator
+ */
+static enum stb0899_status stb0899_search_data(struct stb0899_state *state)
+{
+	short int derot_freq, derot_step, derot_limit, next_loop = 3;
+	u8 cfr[2];
+	u8 reg;
+	int index = 1;
+
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	derot_step = (params->srate / 4L) / internal->mclk;
+	derot_limit = (internal->sub_range / 2L) / internal->mclk;
+	derot_freq = internal->derot_freq;
+
+	do {
+		if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) {
+
+			derot_freq += index * internal->direction * derot_step;	/* next zig zag derotator position */
+			if (ABS(derot_freq) > derot_limit)
+				next_loop--;
+
+			if (next_loop) {
+				dprintk(state->verbose, FE_DEBUG, 1, "Derot freq=%d, mclk=%d", derot_freq, internal->mclk);
+				reg = stb0899_read_reg(state, STB0899_CFD);
+				STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+				stb0899_write_reg(state, STB0899_CFD, reg);
+
+				STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+				STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+				stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency	*/
+
+				stb0899_check_carrier(state);
+				index++;
+			}
+		}
+		internal->direction = -internal->direction; /* change zig zag direction */
+	} while ((internal->status != DATAOK) && next_loop);
+
+	if (internal->status == DATAOK) {
+		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */
+		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+		dprintk(state->verbose, FE_DEBUG, 1, "------> DATAOK ! Derot Freq=%d", internal->derot_freq);
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_check_range
+ * check if the found frequency is in the correct range
+ */
+static enum stb0899_status stb0899_check_range(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	int range_offst, tp_freq;
+
+	range_offst = internal->srch_range / 2000;
+	tp_freq = internal->freq + (internal->derot_freq * internal->mclk) / 1000;
+
+	if ((tp_freq >= params->freq - range_offst) && (tp_freq <= params->freq + range_offst)) {
+		internal->status = RANGEOK;
+		dprintk(state->verbose, FE_DEBUG, 1, "----> RANGEOK !");
+	} else {
+		internal->status = OUTOFRANGE;
+		dprintk(state->verbose, FE_DEBUG, 1, "----> OUT OF RANGE !");
+	}
+
+	return internal->status;
+}
+
+/*
+ * NextSubRange
+ * Compute the next subrange of the search
+ */
+static void next_sub_range(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	long old_sub_range;
+
+	if (internal->sub_dir > 0) {
+		old_sub_range = internal->sub_range;
+		internal->sub_range = MIN((internal->srch_range / 2) -
+					  (internal->tuner_offst + internal->sub_range / 2),
+					   internal->sub_range);
+
+		if (internal->sub_range < 0)
+			internal->sub_range = 0;
+
+		internal->tuner_offst += (old_sub_range + internal->sub_range) / 2;
+	}
+
+	internal->freq = params->freq + (internal->sub_dir * internal->tuner_offst) / 1000;
+	internal->sub_dir = -internal->sub_dir;
+}
+
+/*
+ * stb0899_dvbs_algo
+ * Search for a signal, timing, carrier and data for a
+ * given frequency in a given range
+ */
+enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state)
+{
+	struct stb0899_params *params		= &state->params;
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_config *config		= state->config;
+
+	u8 bclc, reg;
+	u8 cfr[2];
+	u8 eq_const[10];
+	s32 clnI = 3;
+	u32 bandwidth = 0;
+
+	/* BETA values rated @ 99MHz	*/
+	s32 betaTab[5][4] = {
+	       /*  5   10   20   30MBps */
+		{ 37,  34,  32,  31 }, /* QPSK 1/2	*/
+		{ 37,  35,  33,  31 }, /* QPSK 2/3	*/
+		{ 37,  35,  33,  31 }, /* QPSK 3/4	*/
+		{ 37,  36,  33,	 32 }, /* QPSK 5/6	*/
+		{ 37,  36,  33,	 32 }  /* QPSK 7/8	*/
+	};
+
+	internal->direction = 1;
+
+	stb0899_set_srate(state, internal->master_clk, params->srate);
+	/* Carrier loop optimization versus symbol rate for acquisition*/
+	if (params->srate <= 5000000) {
+		stb0899_write_reg(state, STB0899_ACLC, 0x89);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x1c);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 0;
+	} else if (params->srate <= 15000000) {
+		stb0899_write_reg(state, STB0899_ACLC, 0xc9);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x22);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 1;
+	} else if(params->srate <= 25000000) {
+		stb0899_write_reg(state, STB0899_ACLC, 0x89);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x27);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 2;
+	} else {
+		stb0899_write_reg(state, STB0899_ACLC, 0xc8);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x29);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 3;
+	}
+
+	dprintk(state->verbose, FE_DEBUG, 1, "Set the timing loop to acquisition");
+	/* Set the timing loop to acquisition	*/
+	stb0899_write_reg(state, STB0899_RTC, 0x46);
+	stb0899_write_reg(state, STB0899_CFD, 0xee);
+
+	/* !! WARNING !!
+	 * Do not read any status variables while acquisition,
+	 * If any needed, read before the acquisition starts
+	 * querying status while acquiring causes the
+	 * acquisition to go bad and hence no locks.
+	 */
+	dprintk(state->verbose, FE_DEBUG, 1, "Derot Percent=%d Srate=%d mclk=%d",
+		internal->derot_percent, params->srate, internal->mclk);
+
+	/* Initial calculations	*/
+	internal->derot_step = internal->derot_percent * (params->srate / 1000L) / internal->mclk; /* DerotStep/1000 * Fsymbol	*/
+	internal->t_derot = stb0899_calc_derot_time(params->srate);
+	internal->t_data = 500;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "RESET stream merger");
+	/* RESET Stream merger	*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESRS, reg, 1);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	/*
+	 * Set KDIVIDER to an intermediate value between
+	 * 1/2 and 7/8 for acquisition
+	 */
+	reg = stb0899_read_reg(state, STB0899_DEMAPVIT);
+	STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 60);
+	stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
+
+	stb0899_write_reg(state, STB0899_EQON, 0x01); /* Equalizer OFF while acquiring */
+	stb0899_write_reg(state, STB0899_VITSYNC, 0x19);
+
+	stb0899_first_subrange(state);
+	do {
+		/* Initialisations */
+		cfr[0] = cfr[1] = 0;
+		stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* RESET derotator frequency	*/
+
+		stb0899_write_reg(state, STB0899_RTF, 0);
+		reg = stb0899_read_reg(state, STB0899_CFD);
+		STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+		stb0899_write_reg(state, STB0899_CFD, reg);
+
+		internal->derot_freq = 0;
+		internal->status = NOAGC1;
+
+		/* enable tuner I/O */
+		stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+		/* Move tuner to frequency */
+		dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency");
+		if (state->config->tuner_set_frequency)
+			state->config->tuner_set_frequency(&state->frontend, internal->freq);
+
+		if (state->config->tuner_get_frequency)
+			state->config->tuner_get_frequency(&state->frontend, &internal->freq);
+
+		msleep(internal->t_agc1 + internal->t_agc2 + internal->t_derot); /* AGC1, AGC2 and timing loop	*/
+		dprintk(state->verbose, FE_DEBUG, 1, "current derot freq=%d", internal->derot_freq);
+		internal->status = AGC1OK;
+
+		/* There is signal in the band	*/
+		if (config->tuner_get_bandwidth)
+			config->tuner_get_bandwidth(&state->frontend, &bandwidth);
+
+		/* disable tuner I/O */
+		stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+		if (params->srate <= bandwidth / 2)
+			stb0899_search_tmg(state); /* For low rates (SCPC)	*/
+		else
+			stb0899_check_tmg(state); /* For high rates (MCPC)	*/
+
+		if (internal->status == TIMINGOK) {
+			dprintk(state->verbose, FE_DEBUG, 1,
+				"TIMING OK ! Derot freq=%d, mclk=%d",
+				internal->derot_freq, internal->mclk);
+
+			if (stb0899_search_carrier(state) == CARRIEROK) {	/* Search for carrier	*/
+				dprintk(state->verbose, FE_DEBUG, 1,
+					"CARRIER OK ! Derot freq=%d, mclk=%d",
+					internal->derot_freq, internal->mclk);
+
+				if (stb0899_search_data(state) == DATAOK) {	/* Check for data	*/
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"DATA OK ! Derot freq=%d, mclk=%d",
+						internal->derot_freq, internal->mclk);
+
+					if (stb0899_check_range(state) == RANGEOK) {
+						dprintk(state->verbose, FE_DEBUG, 1,
+							"RANGE OK ! derot freq=%d, mclk=%d",
+							internal->derot_freq, internal->mclk);
+
+						internal->freq = params->freq + ((internal->derot_freq * internal->mclk) / 1000);
+						reg = stb0899_read_reg(state, STB0899_PLPARM);
+						internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg);
+						dprintk(state->verbose, FE_DEBUG, 1,
+							"freq=%d, internal resultant freq=%d",
+							params->freq, internal->freq);
+
+						dprintk(state->verbose, FE_DEBUG, 1,
+							"internal puncture rate=%d",
+							internal->fecrate);
+					}
+				}
+			}
+		}
+		if (internal->status != RANGEOK)
+			next_sub_range(state);
+
+	} while (internal->sub_range && internal->status != RANGEOK);
+
+	/* Set the timing loop to tracking	*/
+	stb0899_write_reg(state, STB0899_RTC, 0x33);
+	stb0899_write_reg(state, STB0899_CFD, 0xf7);
+	/* if locked and range ok, set Kdiv	*/
+	if (internal->status == RANGEOK) {
+		dprintk(state->verbose, FE_DEBUG, 1, "Locked & Range OK !");
+		stb0899_write_reg(state, STB0899_EQON, 0x41);		/* Equalizer OFF while acquiring	*/
+		stb0899_write_reg(state, STB0899_VITSYNC, 0x39);	/* SN to b'11 for acquisition		*/
+
+		/*
+		 * Carrier loop optimization versus
+		 * symbol Rate/Puncture Rate for Tracking
+		 */
+		reg = stb0899_read_reg(state, STB0899_BCLC);
+		switch (internal->fecrate) {
+		case STB0899_FEC_1_2:		/* 13	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 0x1a);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[0][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_2_3:		/* 18	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 44);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[1][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_3_4:		/* 21	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 60);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[2][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_5_6:		/* 24	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 75);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[3][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_6_7:		/* 25	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 88);
+			stb0899_write_reg(state, STB0899_ACLC, 0x88);
+			stb0899_write_reg(state, STB0899_BCLC, 0x9a);
+			break;
+		case STB0899_FEC_7_8:		/* 26	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 94);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[4][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		default:
+			dprintk(state->verbose, FE_DEBUG, 1, "Unsupported Puncture Rate");
+			break;
+		}
+		/* release stream merger RESET	*/
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESRS, reg, 0);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		/* disable carrier detector	*/
+		reg = stb0899_read_reg(state, STB0899_CFD);
+		STB0899_SETFIELD_VAL(CFD_ON, reg, 0);
+		stb0899_write_reg(state, STB0899_CFD, reg);
+
+		stb0899_read_regs(state, STB0899_EQUAI1, eq_const, 10);
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_dvbs2_config_uwp
+ * Configure UWP state machine
+ */
+static void stb0899_dvbs2_config_uwp(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+	u32 uwp1, uwp2, uwp3, reg;
+
+	uwp1 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1);
+	uwp2 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL2);
+	uwp3 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL3);
+
+	STB0899_SETFIELD_VAL(UWP_ESN0_AVE, uwp1, config->esno_ave);
+	STB0899_SETFIELD_VAL(UWP_ESN0_QUANT, uwp1, config->esno_quant);
+	STB0899_SETFIELD_VAL(UWP_TH_SOF, uwp1, config->uwp_threshold_sof);
+
+	STB0899_SETFIELD_VAL(FE_COARSE_TRK, uwp2, internal->av_frame_coarse);
+	STB0899_SETFIELD_VAL(FE_FINE_TRK, uwp2, internal->av_frame_fine);
+	STB0899_SETFIELD_VAL(UWP_MISS_TH, uwp2, config->miss_threshold);
+
+	STB0899_SETFIELD_VAL(UWP_TH_ACQ, uwp3, config->uwp_threshold_acq);
+	STB0899_SETFIELD_VAL(UWP_TH_TRACK, uwp3, config->uwp_threshold_track);
+
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL1, STB0899_OFF0_UWP_CNTRL1, uwp1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL2, STB0899_OFF0_UWP_CNTRL2, uwp2);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL3, STB0899_OFF0_UWP_CNTRL3, uwp3);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, SOF_SRCH_TO);
+	STB0899_SETFIELD_VAL(SOF_SEARCH_TIMEOUT, reg, config->sof_search_timeout);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_SOF_SRCH_TO, STB0899_OFF0_SOF_SRCH_TO, reg);
+}
+
+/*
+ * stb0899_dvbs2_config_csm_auto
+ * Set CSM to AUTO mode
+ */
+static void stb0899_dvbs2_config_csm_auto(struct stb0899_state *state)
+{
+	u32 reg;
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+	STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, reg, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, reg);
+}
+
+long Log2Int(int number)
+{
+	int i;
+
+	i = 0;
+	while ((1 << i) <= ABS(number))
+		i++;
+
+	if (number == 0)
+		i = 1;
+
+	return i - 1;
+}
+
+/*
+ * stb0899_dvbs2_calc_srate
+ * compute BTR_NOM_FREQ for the symbol rate
+ */
+static u32 stb0899_dvbs2_calc_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_config *config		= state->config;
+
+	u32 dec_ratio, dec_rate, decim, remain, intval, btr_nom_freq;
+	u32 master_clk, srate;
+
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+	dec_rate = Log2Int(dec_ratio);
+	decim = 1 << dec_rate;
+	master_clk = internal->master_clk / 1000;
+	srate = internal->srate / 1000;
+
+	if (decim <= 4) {
+		intval = (decim * (1 << (config->btr_nco_bits - 1))) / master_clk;
+		remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk;
+	} else {
+		intval = (1 << (config->btr_nco_bits - 1)) / (master_clk / 100) * decim / 100;
+		remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk;
+	}
+	btr_nom_freq = (intval * srate) + ((remain * srate) / master_clk);
+
+	return btr_nom_freq;
+}
+
+/*
+ * stb0899_dvbs2_calc_dev
+ * compute the correction to be applied to symbol rate
+ */
+static u32 stb0899_dvbs2_calc_dev(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u32 dec_ratio, correction, master_clk, srate;
+
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+
+	master_clk = internal->master_clk / 1000;	/* for integer Caculation*/
+	srate = internal->srate / 1000;	/* for integer Caculation*/
+	correction = (512 * master_clk) / (2 * dec_ratio * srate);
+
+	return	correction;
+}
+
+/*
+ * stb0899_dvbs2_set_srate
+ * Set DVBS2 symbol rate
+ */
+static void stb0899_dvbs2_set_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	u32 dec_ratio, dec_rate, win_sel, decim, f_sym, btr_nom_freq;
+	u32 correction, freq_adj, band_lim, decim_cntrl, reg;
+	u8 anti_alias;
+
+	/*set decimation to 1*/
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+	dec_rate = Log2Int(dec_ratio);
+
+	win_sel = 0;
+	if (dec_rate >= 5)
+		win_sel = dec_rate - 4;
+
+	decim = (1 << dec_rate);
+	/* (FSamp/Fsymbol *100) for integer Caculation */
+	f_sym = internal->master_clk / ((decim * internal->srate) / 1000);
+
+	if (f_sym <= 2250)	/* don't band limit signal going into btr block*/
+		band_lim = 1;
+	else
+		band_lim = 0;	/* band limit signal going into btr block*/
+
+	decim_cntrl = ((win_sel << 3) & 0x18) + ((band_lim << 5) & 0x20) + (dec_rate & 0x7);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DECIM_CNTRL, STB0899_OFF0_DECIM_CNTRL, decim_cntrl);
+
+	if (f_sym <= 3450)
+		anti_alias = 0;
+	else if (f_sym <= 4250)
+		anti_alias = 1;
+	else
+		anti_alias = 2;
+
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ANTI_ALIAS_SEL, STB0899_OFF0_ANTI_ALIAS_SEL, anti_alias);
+	btr_nom_freq = stb0899_dvbs2_calc_srate(state);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_NOM_FREQ, STB0899_OFF0_BTR_NOM_FREQ, btr_nom_freq);
+
+	correction = stb0899_dvbs2_calc_dev(state);
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL);
+	STB0899_SETFIELD_VAL(BTR_FREQ_CORR, reg, correction);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg);
+
+	/* scale UWP+CSM frequency to sample rate*/
+	freq_adj =  internal->srate / (internal->master_clk / 4096);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_FREQ_ADJ_SCALE, STB0899_OFF0_FREQ_ADJ_SCALE, freq_adj);
+}
+
+/*
+ * stb0899_dvbs2_set_btr_loopbw
+ * set bit timing loop bandwidth as a percentage of the symbol rate
+ */
+static void stb0899_dvbs2_set_btr_loopbw(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_config *config		= state->config;
+
+	u32 sym_peak = 23, zeta = 707, loopbw_percent = 60;
+	s32 dec_ratio, dec_rate, k_btr1_rshft, k_btr1, k_btr0_rshft;
+	s32 k_btr0, k_btr2_rshft, k_direct_shift, k_indirect_shift;
+	u32 decim, K, wn, k_direct, k_indirect;
+	u32 reg;
+
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+	dec_rate = Log2Int(dec_ratio);
+	decim = (1 << dec_rate);
+
+	sym_peak *= 576000;
+	K = (1 << config->btr_nco_bits) / (internal->master_clk / 1000);
+	K *= (internal->srate / 1000000) * decim; /*k=k 10^-8*/
+
+	if (K != 0) {
+		K = sym_peak / K;
+		wn = (4 * zeta * zeta) + 1000000;
+		wn = (2 * (loopbw_percent * 1000) * 40 * zeta) /wn;  /*wn =wn 10^-8*/
+
+		k_indirect = (wn * wn) / K;
+		k_indirect = k_indirect;	  /*kindirect = kindirect 10^-6*/
+		k_direct   = (2 * wn * zeta) / K;	/*kDirect = kDirect 10^-2*/
+		k_direct  *= 100;
+
+		k_direct_shift = Log2Int(k_direct) - Log2Int(10000) - 2;
+		k_btr1_rshft = (-1 * k_direct_shift) + config->btr_gain_shift_offset;
+		k_btr1 = k_direct / (1 << k_direct_shift);
+		k_btr1 /= 10000;
+
+		k_indirect_shift = Log2Int(k_indirect + 15) - 20 /*- 2*/;
+		k_btr0_rshft = (-1 * k_indirect_shift) + config->btr_gain_shift_offset;
+		k_btr0 = k_indirect * (1 << (-k_indirect_shift));
+		k_btr0 /= 1000000;
+
+		k_btr2_rshft = 0;
+		if (k_btr0_rshft > 15) {
+			k_btr2_rshft = k_btr0_rshft - 15;
+			k_btr0_rshft = 15;
+		}
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_LOOP_GAIN);
+		STB0899_SETFIELD_VAL(KBTR0_RSHFT, reg, k_btr0_rshft);
+		STB0899_SETFIELD_VAL(KBTR0, reg, k_btr0);
+		STB0899_SETFIELD_VAL(KBTR1_RSHFT, reg, k_btr1_rshft);
+		STB0899_SETFIELD_VAL(KBTR1, reg, k_btr1);
+		STB0899_SETFIELD_VAL(KBTR2_RSHFT, reg, k_btr2_rshft);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, reg);
+	} else
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, 0xc4c4f);
+}
+
+/*
+ * stb0899_dvbs2_set_carr_freq
+ * set nominal frequency for carrier search
+ */
+static void stb0899_dvbs2_set_carr_freq(struct stb0899_state *state, s32 carr_freq, u32 master_clk)
+{
+	struct stb0899_config *config = state->config;
+	s32 crl_nom_freq;
+	u32 reg;
+
+	crl_nom_freq = (1 << config->crl_nco_bits) / master_clk;
+	crl_nom_freq *= carr_freq;
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+	STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, crl_nom_freq);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
+}
+
+/*
+ * stb0899_dvbs2_init_calc
+ * Initialize DVBS2 UWP, CSM, carrier and timing loops
+ */
+static void stb0899_dvbs2_init_calc(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	s32 steps, step_size;
+	u32 range, reg;
+
+	/* config uwp and csm */
+	stb0899_dvbs2_config_uwp(state);
+	stb0899_dvbs2_config_csm_auto(state);
+
+	/* initialize BTR	*/
+	stb0899_dvbs2_set_srate(state);
+	stb0899_dvbs2_set_btr_loopbw(state);
+
+	if (internal->srate / 1000000 >= 15)
+		step_size = (1 << 17) / 5;
+	else if (internal->srate / 1000000 >= 10)
+		step_size = (1 << 17) / 7;
+	else if (internal->srate / 1000000 >= 5)
+		step_size = (1 << 17) / 10;
+	else
+		step_size = (1 << 17) / 4;
+
+	range = internal->srch_range / 1000000;
+	steps = (10 * range * (1 << 17)) / (step_size * (internal->srate / 1000000));
+	steps = (steps + 6) / 10;
+	steps = (steps == 0) ? 1 : steps;
+	if (steps % 2 == 0)
+		stb0899_dvbs2_set_carr_freq(state, internal->center_freq -
+					   (internal->step_size * (internal->srate / 20000000)),
+					   (internal->master_clk) / 1000000);
+	else
+		stb0899_dvbs2_set_carr_freq(state, internal->center_freq, (internal->master_clk) / 1000000);
+
+	/*Set Carrier Search params (zigzag, num steps and freq step size*/
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, ACQ_CNTRL2);
+	STB0899_SETFIELD_VAL(ZIGZAG, reg, 1);
+	STB0899_SETFIELD_VAL(NUM_STEPS, reg, steps);
+	STB0899_SETFIELD_VAL(FREQ_STEPSIZE, reg, step_size);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQ_CNTRL2, STB0899_OFF0_ACQ_CNTRL2, reg);
+}
+
+/*
+ * stb0899_dvbs2_btr_init
+ * initialize the timing loop
+ */
+static void stb0899_dvbs2_btr_init(struct stb0899_state *state)
+{
+	u32 reg;
+
+	/* set enable BTR loopback	*/
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL);
+	STB0899_SETFIELD_VAL(INTRP_PHS_SENSE, reg, 1);
+	STB0899_SETFIELD_VAL(BTR_ERR_ENA, reg, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg);
+
+	/* fix btr freq accum at 0	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x10000000);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x00000000);
+
+	/* fix btr freq accum at 0	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x10000000);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x00000000);
+}
+
+/*
+ * stb0899_dvbs2_reacquire
+ * trigger a DVB-S2 acquisition
+ */
+static void stb0899_dvbs2_reacquire(struct stb0899_state *state)
+{
+	u32 reg = 0;
+
+	/* demod soft reset	*/
+	STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg);
+
+	/*Reset Timing Loop	*/
+	stb0899_dvbs2_btr_init(state);
+
+	/* reset Carrier loop	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, (1 << 30));
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_LOOP_GAIN, STB0899_OFF0_CRL_LOOP_GAIN, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, (1 << 30));
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, 0);
+
+	/*release demod soft reset	*/
+	reg = 0;
+	STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg);
+
+	/* start acquisition process	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQUIRE_TRIG, STB0899_OFF0_ACQUIRE_TRIG, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_LOCK_LOST, STB0899_OFF0_LOCK_LOST, 0);
+
+	/* equalizer Init	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 1);
+
+	/*Start equilizer	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 0);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+	STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0);
+	STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 0);
+	STB0899_SETFIELD_VAL(EQ_DELAY, reg, 0x05);
+	STB0899_SETFIELD_VAL(EQ_ADAPT_MODE, reg, 0x01);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+
+	/* RESET Packet delineator	*/
+	stb0899_write_reg(state, STB0899_PDELCTRL, 0x4a);
+}
+
+/*
+ * stb0899_dvbs2_get_dmd_status
+ * get DVB-S2 Demod LOCK status
+ */
+static enum stb0899_status stb0899_dvbs2_get_dmd_status(struct stb0899_state *state, int timeout)
+{
+	int time = -10, lock = 0, uwp, csm;
+	u32 reg;
+
+	do {
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STATUS);
+		dprintk(state->verbose, FE_DEBUG, 1, "DMD_STATUS=[0x%02x]", reg);
+		if (STB0899_GETFIELD(IF_AGC_LOCK, reg))
+			dprintk(state->verbose, FE_DEBUG, 1, "------------->IF AGC LOCKED !");
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2);
+		dprintk(state->verbose, FE_DEBUG, 1, "----------->DMD STAT2=[0x%02x]", reg);
+		uwp = STB0899_GETFIELD(UWP_LOCK, reg);
+		csm = STB0899_GETFIELD(CSM_LOCK, reg);
+		if (uwp && csm)
+			lock = 1;
+
+		time += 10;
+		msleep(10);
+
+	} while ((!lock) && (time <= timeout));
+
+	if (lock) {
+		dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 LOCK !");
+		return DVBS2_DEMOD_LOCK;
+	} else {
+		return DVBS2_DEMOD_NOLOCK;
+	}
+}
+
+/*
+ * stb0899_dvbs2_get_data_lock
+ * get FEC status
+ */
+static int stb0899_dvbs2_get_data_lock(struct stb0899_state *state, int timeout)
+{
+	int time = 0, lock = 0;
+	u8 reg;
+
+	while ((!lock) && (time < timeout)) {
+		reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1);
+		dprintk(state->verbose, FE_DEBUG, 1, "---------> CFGPDELSTATUS=[0x%02x]", reg);
+		lock = STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg);
+		time++;
+	}
+
+	return lock;
+}
+
+/*
+ * stb0899_dvbs2_get_fec_status
+ * get DVB-S2 FEC LOCK status
+ */
+static enum stb0899_status stb0899_dvbs2_get_fec_status(struct stb0899_state *state, int timeout)
+{
+	int time = 0, Locked;
+
+	do {
+		Locked = stb0899_dvbs2_get_data_lock(state, 1);
+		time++;
+		msleep(1);
+
+	} while ((!Locked) && (time < timeout));
+
+	if (Locked) {
+		dprintk(state->verbose, FE_DEBUG, 1, "---------->DVB-S2 FEC LOCK !");
+		return DVBS2_FEC_LOCK;
+	} else {
+		return DVBS2_FEC_NOLOCK;
+	}
+}
+
+
+/*
+ * stb0899_dvbs2_init_csm
+ * set parameters for manual mode
+ */
+static void stb0899_dvbs2_init_csm(struct stb0899_state *state, int pilots, enum stb0899_modcod modcod)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	s32 dvt_tbl = 1, two_pass = 0, agc_gain = 6, agc_shift = 0, loop_shift = 0, phs_diff_thr = 0x80;
+	s32 gamma_acq, gamma_rho_acq, gamma_trk, gamma_rho_trk, lock_count_thr;
+	u32 csm1, csm2, csm3, csm4;
+
+	if (((internal->master_clk / internal->srate) <= 4) && (modcod <= 11) && (pilots == 1)) {
+		switch (modcod) {
+		case STB0899_QPSK_12:
+			gamma_acq		= 25;
+			gamma_rho_acq		= 2700;
+			gamma_trk		= 12;
+			gamma_rho_trk		= 180;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_35:
+			gamma_acq		= 38;
+			gamma_rho_acq		= 7182;
+			gamma_trk		= 14;
+			gamma_rho_trk		= 308;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_23:
+			gamma_acq		= 42;
+			gamma_rho_acq		= 9408;
+			gamma_trk		= 17;
+			gamma_rho_trk		= 476;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_34:
+			gamma_acq		= 53;
+			gamma_rho_acq		= 16642;
+			gamma_trk		= 19;
+			gamma_rho_trk		= 646;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_45:
+			gamma_acq		= 53;
+			gamma_rho_acq		= 17119;
+			gamma_trk		= 22;
+			gamma_rho_trk		= 880;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_56:
+			gamma_acq		= 55;
+			gamma_rho_acq		= 19250;
+			gamma_trk		= 23;
+			gamma_rho_trk		= 989;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_89:
+			gamma_acq		= 60;
+			gamma_rho_acq		= 24240;
+			gamma_trk		= 24;
+			gamma_rho_trk		= 1176;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_910:
+			gamma_acq		= 66;
+			gamma_rho_acq		= 29634;
+			gamma_trk		= 24;
+			gamma_rho_trk		= 1176;
+			lock_count_thr		= 8;
+			break;
+		default:
+			gamma_acq		= 66;
+			gamma_rho_acq		= 29634;
+			gamma_trk		= 24;
+			gamma_rho_trk		= 1176;
+			lock_count_thr		= 8;
+			break;
+		}
+
+		csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+		STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, csm1, 0);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+
+		csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+		csm2 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL2);
+		csm3 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL3);
+		csm4 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL4);
+
+		STB0899_SETFIELD_VAL(CSM_DVT_TABLE, csm1, dvt_tbl);
+		STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, two_pass);
+		STB0899_SETFIELD_VAL(CSM_AGC_GAIN, csm1, agc_gain);
+		STB0899_SETFIELD_VAL(CSM_AGC_SHIFT, csm1, agc_shift);
+		STB0899_SETFIELD_VAL(FE_LOOP_SHIFT, csm1, loop_shift);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_ACQ, csm2, gamma_acq);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_RHOACQ, csm2, gamma_rho_acq);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_TRACK, csm3, gamma_trk);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_RHOTRACK, csm3, gamma_rho_trk);
+		STB0899_SETFIELD_VAL(CSM_LOCKCOUNT_THRESH, csm4, lock_count_thr);
+		STB0899_SETFIELD_VAL(CSM_PHASEDIFF_THRESH, csm4, phs_diff_thr);
+
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL2, STB0899_OFF0_CSM_CNTRL2, csm2);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL3, STB0899_OFF0_CSM_CNTRL3, csm3);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL4, STB0899_OFF0_CSM_CNTRL4, csm4);
+	}
+}
+
+/*
+ * stb0899_dvbs2_get_srate
+ * get DVB-S2 Symbol Rate
+ */
+static u32 stb0899_dvbs2_get_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+
+	u32 bTrNomFreq, srate, decimRate, intval1, intval2, reg;
+	int div1, div2, rem1, rem2;
+
+	div1 = config->btr_nco_bits / 2;
+	div2 = config->btr_nco_bits - div1 - 1;
+
+	bTrNomFreq = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_NOM_FREQ);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DECIM_CNTRL);
+	decimRate = STB0899_GETFIELD(DECIM_RATE, reg);
+	decimRate = (1 << decimRate);
+
+	intval1 = internal->master_clk / (1 << div1);
+	intval2 = bTrNomFreq / (1 << div2);
+
+	rem1 = internal->master_clk % (1 << div1);
+	rem2 = bTrNomFreq % (1 << div2);
+	/* only for integer calculation	*/
+	srate = (intval1 * intval2) + ((intval1 * rem2) / (1 << div2)) + ((intval2 * rem1) / (1 << div1));
+	srate /= decimRate;	/*symbrate = (btrnomfreq_register_val*MasterClock)/2^(27+decim_rate_field) */
+
+	return	srate;
+}
+
+/*
+ * stb0899_dvbs2_algo
+ * Search for signal, timing, carrier and data for a given
+ * frequency in a given range
+ */
+enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	enum stb0899_modcod modcod;
+
+	s32 offsetfreq, searchTime, FecLockTime, pilots, iqSpectrum;
+	int i = 0;
+	u32 reg, csm1;
+
+	if (internal->srate <= 2000000) {
+		searchTime	= 5000;	/* 5000 ms max time to lock UWP and CSM, SYMB <= 2Mbs		*/
+		FecLockTime	= 350;	/* 350  ms max time to lock FEC, SYMB <= 2Mbs			*/
+	} else if (internal->srate <= 5000000) {
+		searchTime	= 2500;	/* 2500 ms max time to lock UWP and CSM, 2Mbs < SYMB <= 5Mbs	*/
+		FecLockTime	= 170;	/* 170  ms max time to lock FEC, 2Mbs< SYMB <= 5Mbs		*/
+	} else if (internal->srate <= 10000000) {
+		searchTime	= 1500;	/* 1500 ms max time to lock UWP and CSM, 5Mbs <SYMB <= 10Mbs	*/
+		FecLockTime	= 80;	/* 80  ms max time to lock FEC, 5Mbs< SYMB <= 10Mbs		*/
+	} else if (internal->srate <= 15000000) {
+		searchTime	= 500;	/* 500 ms max time to lock UWP and CSM, 10Mbs <SYMB <= 15Mbs	*/
+		FecLockTime	= 50;	/* 50  ms max time to lock FEC, 10Mbs< SYMB <= 15Mbs		*/
+	} else if (internal->srate <= 20000000) {
+		searchTime	= 300;	/* 300 ms max time to lock UWP and CSM, 15Mbs < SYMB <= 20Mbs	*/
+		FecLockTime	= 30;	/* 50  ms max time to lock FEC, 15Mbs< SYMB <= 20Mbs		*/
+	} else if (internal->srate <= 25000000) {
+		searchTime	= 250;	/* 250 ms max time to lock UWP and CSM, 20 Mbs < SYMB <= 25Mbs	*/
+		FecLockTime	= 25;	/* 25 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs		*/
+	} else {
+		searchTime	= 150;	/* 150 ms max time to lock UWP and CSM, SYMB > 25Mbs		*/
+		FecLockTime	= 20;	/* 20 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs		*/
+	}
+
+	/* Maintain Stream Merger in reset during acquisition	*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESRS, reg, 1);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	/* enable tuner I/O */
+	stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+	/* Move tuner to frequency	*/
+	if (state->config->tuner_set_frequency)
+		state->config->tuner_set_frequency(&state->frontend, internal->freq);
+	if (state->config->tuner_get_frequency)
+		state->config->tuner_get_frequency(&state->frontend, &internal->freq);
+
+	/* disable tuner I/O */
+	stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+	/* Set IF AGC to acquisition	*/
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+	STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg,  4);
+	STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 32);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2);
+	STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg);
+
+	/* Initialisation	*/
+	stb0899_dvbs2_init_calc(state);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+	switch (internal->inversion) {
+	case IQ_SWAP_OFF:
+		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 0);
+		break;
+	case IQ_SWAP_ON:
+		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
+		break;
+	case IQ_SWAP_AUTO:	/* use last successful search first	*/
+		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
+		break;
+	}
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
+	stb0899_dvbs2_reacquire(state);
+
+	/* Wait for demod lock (UWP and CSM)	*/
+	internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
+
+	if (internal->status == DVBS2_DEMOD_LOCK) {
+		dprintk(state->verbose, FE_DEBUG, 1, "------------> DVB-S2 DEMOD LOCK !");
+		i = 0;
+		/* Demod Locked, check FEC status	*/
+		internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+
+		/*If false lock (UWP and CSM Locked but no FEC) try 3 time max*/
+		while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+			/*	Read the frequency offset*/
+			offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+			/* Set the Nominal frequency to the found frequency offset for the next reacquire*/
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+			STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq);
+			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
+			stb0899_dvbs2_reacquire(state);
+			internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
+			i++;
+		}
+	}
+
+	if (internal->status != DVBS2_FEC_LOCK) {
+		if (internal->inversion == IQ_SWAP_AUTO) {
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+			iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg);
+			/* IQ Spectrum Inversion	*/
+			STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum);
+			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
+			/* start acquistion process	*/
+			stb0899_dvbs2_reacquire(state);
+
+			/* Wait for demod lock (UWP and CSM)	*/
+			internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
+			if (internal->status == DVBS2_DEMOD_LOCK) {
+				i = 0;
+				/* Demod Locked, check FEC	*/
+				internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+				/*try thrice for false locks, (UWP and CSM Locked but no FEC)	*/
+				while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+					/*	Read the frequency offset*/
+					offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+					/* Set the Nominal frequency to the found frequency offset for the next reacquire*/
+					reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+					STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq);
+					stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
+
+					stb0899_dvbs2_reacquire(state);
+					internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
+					i++;
+				}
+			}
+/*
+			if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED)
+				pParams->IQLocked = !iqSpectrum;
+*/
+		}
+	}
+	if (internal->status == DVBS2_FEC_LOCK) {
+		dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 FEC Lock !");
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+		modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2;
+		pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01;
+
+		if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) &&
+		      (INRANGE(STB0899_QPSK_23, modcod, STB0899_QPSK_910)) &&
+		      (pilots == 1)) {
+
+			stb0899_dvbs2_init_csm(state, pilots, modcod);
+			/* Wait for UWP,CSM and data LOCK 20ms max	*/
+			internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+
+			i = 0;
+			while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+				csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+				STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 1);
+				stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+				csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+				STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 0);
+				stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+
+				internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+				i++;
+			}
+		}
+
+		if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) &&
+		      (INRANGE(STB0899_QPSK_12, modcod, STB0899_QPSK_35)) &&
+		      (pilots == 1)) {
+
+			/* Equalizer Disable update	 */
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+			STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 1);
+			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+		}
+
+		/* slow down the Equalizer once locked	*/
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+		STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0x02);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+
+		/* Store signal parameters	*/
+		offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+		offsetfreq = offsetfreq / ((1 << 30) / 1000);
+		offsetfreq *= (internal->master_clk / 1000000);
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+		if (STB0899_GETFIELD(SPECTRUM_INVERT, reg))
+			offsetfreq *= -1;
+
+		internal->freq = internal->freq - offsetfreq;
+		internal->srate = stb0899_dvbs2_get_srate(state);
+
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+		internal->modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2;
+		internal->pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01;
+		internal->frame_length = (STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 1) & 0x01;
+
+		 /* Set IF AGC to tracking	*/
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+		STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg,  3);
+
+		/* if QPSK 1/2,QPSK 3/5 or QPSK 2/3 set IF AGC reference to 16 otherwise 32*/
+		if (INRANGE(STB0899_QPSK_12, internal->modcod, STB0899_QPSK_23))
+			STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 16);
+
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2);
+		STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 7);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg);
+	}
+
+	/* Release Stream Merger Reset		*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESRS, reg, 0);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	return internal->status;
+}

+ 287 - 0
drivers/media/dvb/frontends/stb0899_cfg.h

@@ -0,0 +1,287 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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 __STB0899_CFG_H
+#define __STB0899_CFG_H
+
+static const struct stb0899_s2_reg  stb0899_s2_init_2[] = {
+
+	{ STB0899_OFF0_DMD_STATUS	, STB0899_BASE_DMD_STATUS	, 0x00000103 },	/* DMDSTATUS	*/
+	{ STB0899_OFF0_CRL_FREQ		, STB0899_BASE_CRL_FREQ		, 0x3ed1da56 },	/* CRLFREQ	*/
+	{ STB0899_OFF0_BTR_FREQ		, STB0899_BASE_BTR_FREQ		, 0x00004000 },	/* BTRFREQ	*/
+	{ STB0899_OFF0_IF_AGC_GAIN	, STB0899_BASE_IF_AGC_GAIN	, 0x00002ade },	/* IFAGCGAIN	*/
+	{ STB0899_OFF0_BB_AGC_GAIN	, STB0899_BASE_BB_AGC_GAIN	, 0x000001bc },	/* BBAGCGAIN	*/
+	{ STB0899_OFF0_DC_OFFSET	, STB0899_BASE_DC_OFFSET	, 0x00000200 },	/* DCOFFSET	*/
+	{ STB0899_OFF0_DMD_CNTRL	, STB0899_BASE_DMD_CNTRL	, 0x0000000f },	/* DMDCNTRL	*/
+
+	{ STB0899_OFF0_IF_AGC_CNTRL	, STB0899_BASE_IF_AGC_CNTRL	, 0x03fb4a20 },	/* IFAGCCNTRL	*/
+	{ STB0899_OFF0_BB_AGC_CNTRL	, STB0899_BASE_BB_AGC_CNTRL	, 0x00200c97 },	/* BBAGCCNTRL	*/
+
+	{ STB0899_OFF0_CRL_CNTRL	, STB0899_BASE_CRL_CNTRL	, 0x00000016 },	/* CRLCNTRL	*/
+	{ STB0899_OFF0_CRL_PHS_INIT	, STB0899_BASE_CRL_PHS_INIT	, 0x00000000 },	/* CRLPHSINIT	*/
+	{ STB0899_OFF0_CRL_FREQ_INIT	, STB0899_BASE_CRL_FREQ_INIT	, 0x00000000 },	/* CRLFREQINIT	*/
+	{ STB0899_OFF0_CRL_LOOP_GAIN	, STB0899_BASE_CRL_LOOP_GAIN	, 0x00000000 },	/* CRLLOOPGAIN	*/
+	{ STB0899_OFF0_CRL_NOM_FREQ	, STB0899_BASE_CRL_NOM_FREQ	, 0x3ed097b6 },	/* CRLNOMFREQ	*/
+	{ STB0899_OFF0_CRL_SWP_RATE	, STB0899_BASE_CRL_SWP_RATE	, 0x00000000 },	/* CRLSWPRATE	*/
+	{ STB0899_OFF0_CRL_MAX_SWP	, STB0899_BASE_CRL_MAX_SWP	, 0x00000000 },	/* CRLMAXSWP	*/
+	{ STB0899_OFF0_CRL_LK_CNTRL	, STB0899_BASE_CRL_LK_CNTRL	, 0x0f6cdc01 },	/* CRLLKCNTRL	*/
+	{ STB0899_OFF0_DECIM_CNTRL	, STB0899_BASE_DECIM_CNTRL	, 0x00000000 },	/* DECIMCNTRL	*/
+	{ STB0899_OFF0_BTR_CNTRL	, STB0899_BASE_BTR_CNTRL	, 0x00003993 },	/* BTRCNTRL	*/
+	{ STB0899_OFF0_BTR_LOOP_GAIN	, STB0899_BASE_BTR_LOOP_GAIN	, 0x000d3c6f },	/* BTRLOOPGAIN	*/
+	{ STB0899_OFF0_BTR_PHS_INIT	, STB0899_BASE_BTR_PHS_INIT	, 0x00000000 },	/* BTRPHSINIT	*/
+	{ STB0899_OFF0_BTR_FREQ_INIT	, STB0899_BASE_BTR_FREQ_INIT	, 0x00000000 },	/* BTRFREQINIT	*/
+	{ STB0899_OFF0_BTR_NOM_FREQ	, STB0899_BASE_BTR_NOM_FREQ	, 0x0238e38e },	/* BTRNOMFREQ	*/
+	{ STB0899_OFF0_BTR_LK_CNTRL	, STB0899_BASE_BTR_LK_CNTRL	, 0x00000000 },	/* BTRLKCNTRL	*/
+	{ STB0899_OFF0_DECN_CNTRL	, STB0899_BASE_DECN_CNTRL	, 0x00000000 },	/* DECNCNTRL	*/
+	{ STB0899_OFF0_TP_CNTRL		, STB0899_BASE_TP_CNTRL		, 0x00000000 },	/* TPCNTRL	*/
+	{ STB0899_OFF0_TP_BUF_STATUS	, STB0899_BASE_TP_BUF_STATUS	, 0x00000000 },	/* TPBUFSTATUS	*/
+	{ STB0899_OFF0_DC_ESTIM		, STB0899_BASE_DC_ESTIM		, 0x00000000 },	/* DCESTIM	*/
+	{ STB0899_OFF0_FLL_CNTRL	, STB0899_BASE_FLL_CNTRL	, 0x00000000 },	/* FLLCNTRL	*/
+	{ STB0899_OFF0_FLL_FREQ_WD	, STB0899_BASE_FLL_FREQ_WD	, 0x40070000 },	/* FLLFREQWD	*/
+	{ STB0899_OFF0_ANTI_ALIAS_SEL	, STB0899_BASE_ANTI_ALIAS_SEL	, 0x00000001 },	/* ANTIALIASSEL */
+	{ STB0899_OFF0_RRC_ALPHA	, STB0899_BASE_RRC_ALPHA	, 0x00000002 },	/* RRCALPHA	*/
+	{ STB0899_OFF0_DC_ADAPT_LSHFT	, STB0899_BASE_DC_ADAPT_LSHFT	, 0x00000000 },	/* DCADAPTISHFT */
+	{ STB0899_OFF0_IMB_OFFSET	, STB0899_BASE_IMB_OFFSET	, 0x0000fe01 },	/* IMBOFFSET	*/
+	{ STB0899_OFF0_IMB_ESTIMATE	, STB0899_BASE_IMB_ESTIMATE	, 0x00000000 },	/* IMBESTIMATE	*/
+	{ STB0899_OFF0_IMB_CNTRL	, STB0899_BASE_IMB_CNTRL	, 0x00000001 },	/* IMBCNTRL	*/
+	{ STB0899_OFF0_IF_AGC_CNTRL2	, STB0899_BASE_IF_AGC_CNTRL2	, 0x00005007 },	/* IFAGCCNTRL2	*/
+	{ STB0899_OFF0_DMD_CNTRL2	, STB0899_BASE_DMD_CNTRL2	, 0x00000002 },	/* DMDCNTRL2	*/
+	{ STB0899_OFF0_TP_BUFFER	, STB0899_BASE_TP_BUFFER	, 0x00000000 },	/* TPBUFFER	*/
+	{ STB0899_OFF0_TP_BUFFER1	, STB0899_BASE_TP_BUFFER1	, 0x00000000 },	/* TPBUFFER1	*/
+	{ STB0899_OFF0_TP_BUFFER2	, STB0899_BASE_TP_BUFFER2	, 0x00000000 },	/* TPBUFFER2	*/
+	{ STB0899_OFF0_TP_BUFFER3	, STB0899_BASE_TP_BUFFER3	, 0x00000000 },	/* TPBUFFER3	*/
+	{ STB0899_OFF0_TP_BUFFER4	, STB0899_BASE_TP_BUFFER4	, 0x00000000 },	/* TPBUFFER4	*/
+	{ STB0899_OFF0_TP_BUFFER5	, STB0899_BASE_TP_BUFFER5	, 0x00000000 },	/* TPBUFFER5	*/
+	{ STB0899_OFF0_TP_BUFFER6	, STB0899_BASE_TP_BUFFER6	, 0x00000000 },	/* TPBUFFER6	*/
+	{ STB0899_OFF0_TP_BUFFER7	, STB0899_BASE_TP_BUFFER7	, 0x00000000 },	/* TPBUFFER7	*/
+	{ STB0899_OFF0_TP_BUFFER8	, STB0899_BASE_TP_BUFFER8	, 0x00000000 },	/* TPBUFFER8	*/
+	{ STB0899_OFF0_TP_BUFFER9	, STB0899_BASE_TP_BUFFER9	, 0x00000000 },	/* TPBUFFER9	*/
+	{ STB0899_OFF0_TP_BUFFER10	, STB0899_BASE_TP_BUFFER10	, 0x00000000 },	/* TPBUFFER10	*/
+	{ STB0899_OFF0_TP_BUFFER11	, STB0899_BASE_TP_BUFFER11	, 0x00000000 },	/* TPBUFFER11	*/
+	{ STB0899_OFF0_TP_BUFFER12	, STB0899_BASE_TP_BUFFER12	, 0x00000000 },	/* TPBUFFER12	*/
+	{ STB0899_OFF0_TP_BUFFER13	, STB0899_BASE_TP_BUFFER13	, 0x00000000 },	/* TPBUFFER13	*/
+	{ STB0899_OFF0_TP_BUFFER14	, STB0899_BASE_TP_BUFFER14	, 0x00000000 },	/* TPBUFFER14	*/
+	{ STB0899_OFF0_TP_BUFFER15	, STB0899_BASE_TP_BUFFER15	, 0x00000000 },	/* TPBUFFER15	*/
+	{ STB0899_OFF0_TP_BUFFER16	, STB0899_BASE_TP_BUFFER16	, 0x0000ff00 },	/* TPBUFFER16	*/
+	{ STB0899_OFF0_TP_BUFFER17	, STB0899_BASE_TP_BUFFER17	, 0x00000100 },	/* TPBUFFER17	*/
+	{ STB0899_OFF0_TP_BUFFER18	, STB0899_BASE_TP_BUFFER18	, 0x0000fe01 },	/* TPBUFFER18	*/
+	{ STB0899_OFF0_TP_BUFFER19	, STB0899_BASE_TP_BUFFER19	, 0x000004fe },	/* TPBUFFER19	*/
+	{ STB0899_OFF0_TP_BUFFER20	, STB0899_BASE_TP_BUFFER20	, 0x0000cfe7 },	/* TPBUFFER20	*/
+	{ STB0899_OFF0_TP_BUFFER21	, STB0899_BASE_TP_BUFFER21	, 0x0000bec6 },	/* TPBUFFER21	*/
+	{ STB0899_OFF0_TP_BUFFER22	, STB0899_BASE_TP_BUFFER22	, 0x0000c2bf },	/* TPBUFFER22	*/
+	{ STB0899_OFF0_TP_BUFFER23	, STB0899_BASE_TP_BUFFER23	, 0x0000c1c1 },	/* TPBUFFER23	*/
+	{ STB0899_OFF0_TP_BUFFER24	, STB0899_BASE_TP_BUFFER24	, 0x0000c1c1 },	/* TPBUFFER24	*/
+	{ STB0899_OFF0_TP_BUFFER25	, STB0899_BASE_TP_BUFFER25	, 0x0000c1c1 },	/* TPBUFFER25	*/
+	{ STB0899_OFF0_TP_BUFFER26	, STB0899_BASE_TP_BUFFER26	, 0x0000c1c1 },	/* TPBUFFER26	*/
+	{ STB0899_OFF0_TP_BUFFER27	, STB0899_BASE_TP_BUFFER27	, 0x0000c1c0 },	/* TPBUFFER27	*/
+	{ STB0899_OFF0_TP_BUFFER28	, STB0899_BASE_TP_BUFFER28	, 0x0000c0c0 },	/* TPBUFFER28	*/
+	{ STB0899_OFF0_TP_BUFFER29	, STB0899_BASE_TP_BUFFER29	, 0x0000c1c1 },	/* TPBUFFER29	*/
+	{ STB0899_OFF0_TP_BUFFER30	, STB0899_BASE_TP_BUFFER30	, 0x0000c1c1 },	/* TPBUFFER30	*/
+	{ STB0899_OFF0_TP_BUFFER31	, STB0899_BASE_TP_BUFFER31	, 0x0000c0c1 },	/* TPBUFFER31	*/
+	{ STB0899_OFF0_TP_BUFFER32	, STB0899_BASE_TP_BUFFER32	, 0x0000c0c1 },	/* TPBUFFER32	*/
+	{ STB0899_OFF0_TP_BUFFER33	, STB0899_BASE_TP_BUFFER33	, 0x0000c1c1 },	/* TPBUFFER33	*/
+	{ STB0899_OFF0_TP_BUFFER34	, STB0899_BASE_TP_BUFFER34	, 0x0000c1c1 },	/* TPBUFFER34	*/
+	{ STB0899_OFF0_TP_BUFFER35	, STB0899_BASE_TP_BUFFER35	, 0x0000c0c1 },	/* TPBUFFER35	*/
+	{ STB0899_OFF0_TP_BUFFER36	, STB0899_BASE_TP_BUFFER36	, 0x0000c1c1 },	/* TPBUFFER36	*/
+	{ STB0899_OFF0_TP_BUFFER37	, STB0899_BASE_TP_BUFFER37	, 0x0000c0c1 },	/* TPBUFFER37	*/
+	{ STB0899_OFF0_TP_BUFFER38	, STB0899_BASE_TP_BUFFER38	, 0x0000c1c1 },	/* TPBUFFER38	*/
+	{ STB0899_OFF0_TP_BUFFER39	, STB0899_BASE_TP_BUFFER39	, 0x0000c0c0 },	/* TPBUFFER39	*/
+	{ STB0899_OFF0_TP_BUFFER40	, STB0899_BASE_TP_BUFFER40	, 0x0000c1c0 },	/* TPBUFFER40	*/
+	{ STB0899_OFF0_TP_BUFFER41	, STB0899_BASE_TP_BUFFER41	, 0x0000c1c1 },	/* TPBUFFER41	*/
+	{ STB0899_OFF0_TP_BUFFER42	, STB0899_BASE_TP_BUFFER42	, 0x0000c0c0 },	/* TPBUFFER42	*/
+	{ STB0899_OFF0_TP_BUFFER43	, STB0899_BASE_TP_BUFFER43	, 0x0000c1c0 },	/* TPBUFFER43	*/
+	{ STB0899_OFF0_TP_BUFFER44	, STB0899_BASE_TP_BUFFER44	, 0x0000c0c1 },	/* TPBUFFER44	*/
+	{ STB0899_OFF0_TP_BUFFER45	, STB0899_BASE_TP_BUFFER45	, 0x0000c1be },	/* TPBUFFER45	*/
+	{ STB0899_OFF0_TP_BUFFER46	, STB0899_BASE_TP_BUFFER46	, 0x0000c1c9 },	/* TPBUFFER46	*/
+	{ STB0899_OFF0_TP_BUFFER47	, STB0899_BASE_TP_BUFFER47	, 0x0000c0da },	/* TPBUFFER47	*/
+	{ STB0899_OFF0_TP_BUFFER48	, STB0899_BASE_TP_BUFFER48	, 0x0000c0ba },	/* TPBUFFER48	*/
+	{ STB0899_OFF0_TP_BUFFER49	, STB0899_BASE_TP_BUFFER49	, 0x0000c1c4 },	/* TPBUFFER49	*/
+	{ STB0899_OFF0_TP_BUFFER50	, STB0899_BASE_TP_BUFFER50	, 0x0000c1bf },	/* TPBUFFER50	*/
+	{ STB0899_OFF0_TP_BUFFER51	, STB0899_BASE_TP_BUFFER51	, 0x0000c0c1 },	/* TPBUFFER51	*/
+	{ STB0899_OFF0_TP_BUFFER52	, STB0899_BASE_TP_BUFFER52	, 0x0000c1c0 },	/* TPBUFFER52	*/
+	{ STB0899_OFF0_TP_BUFFER53	, STB0899_BASE_TP_BUFFER53	, 0x0000c0c1 },	/* TPBUFFER53	*/
+	{ STB0899_OFF0_TP_BUFFER54	, STB0899_BASE_TP_BUFFER54	, 0x0000c1c1 },	/* TPBUFFER54	*/
+	{ STB0899_OFF0_TP_BUFFER55	, STB0899_BASE_TP_BUFFER55	, 0x0000c1c1 },	/* TPBUFFER55	*/
+	{ STB0899_OFF0_TP_BUFFER56	, STB0899_BASE_TP_BUFFER56	, 0x0000c1c1 },	/* TPBUFFER56	*/
+	{ STB0899_OFF0_TP_BUFFER57	, STB0899_BASE_TP_BUFFER57	, 0x0000c1c1 },	/* TPBUFFER57	*/
+	{ STB0899_OFF0_TP_BUFFER58	, STB0899_BASE_TP_BUFFER58	, 0x0000c1c1 },	/* TPBUFFER58	*/
+	{ STB0899_OFF0_TP_BUFFER59	, STB0899_BASE_TP_BUFFER59	, 0x0000c1c1 },	/* TPBUFFER59	*/
+	{ STB0899_OFF0_TP_BUFFER60	, STB0899_BASE_TP_BUFFER60	, 0x0000c1c1 },	/* TPBUFFER60	*/
+	{ STB0899_OFF0_TP_BUFFER61	, STB0899_BASE_TP_BUFFER61	, 0x0000c1c1 },	/* TPBUFFER61	*/
+	{ STB0899_OFF0_TP_BUFFER62	, STB0899_BASE_TP_BUFFER62	, 0x0000c1c1 },	/* TPBUFFER62	*/
+	{ STB0899_OFF0_TP_BUFFER63	, STB0899_BASE_TP_BUFFER63	, 0x0000c1c0 },	/* TPBUFFER63	*/
+	{ STB0899_OFF0_RESET_CNTRL	, STB0899_BASE_RESET_CNTRL	, 0x00000001 },	/* RESETCNTRL	*/
+	{ STB0899_OFF0_ACM_ENABLE	, STB0899_BASE_ACM_ENABLE	, 0x00005654 },	/* ACMENABLE	*/
+	{ STB0899_OFF0_DESCR_CNTRL	, STB0899_BASE_DESCR_CNTRL	, 0x00000000 },	/* DESCRCNTRL	*/
+	{ STB0899_OFF0_CSM_CNTRL1	, STB0899_BASE_CSM_CNTRL1	, 0x00020019 },	/* CSMCNTRL1	*/
+	{ STB0899_OFF0_CSM_CNTRL2	, STB0899_BASE_CSM_CNTRL2	, 0x004b3237 },	/* CSMCNTRL2	*/
+	{ STB0899_OFF0_CSM_CNTRL3	, STB0899_BASE_CSM_CNTRL3	, 0x0003dd17 },	/* CSMCNTRL3	*/
+	{ STB0899_OFF0_CSM_CNTRL4	, STB0899_BASE_CSM_CNTRL4	, 0x00008008 },	/* CSMCNTRL4	*/
+	{ STB0899_OFF0_UWP_CNTRL1	, STB0899_BASE_UWP_CNTRL1	, 0x002a3106 },	/* UWPCNTRL1	*/
+	{ STB0899_OFF0_UWP_CNTRL2	, STB0899_BASE_UWP_CNTRL2	, 0x0006140a },	/* UWPCNTRL2	*/
+	{ STB0899_OFF0_UWP_STAT1	, STB0899_BASE_UWP_STAT1	, 0x00008000 },	/* UWPSTAT1	*/
+	{ STB0899_OFF0_UWP_STAT2	, STB0899_BASE_UWP_STAT2	, 0x00000000 },	/* UWPSTAT2	*/
+	{ STB0899_OFF0_DMD_STAT2	, STB0899_BASE_DMD_STAT2	, 0x00000000 },	/* DMDSTAT2	*/
+	{ STB0899_OFF0_FREQ_ADJ_SCALE	, STB0899_BASE_FREQ_ADJ_SCALE	, 0x00000471 },	/* FREQADJSCALE */
+	{ STB0899_OFF0_UWP_CNTRL3	, STB0899_BASE_UWP_CNTRL3	, 0x017b0465 },	/* UWPCNTRL3	*/
+	{ STB0899_OFF0_SYM_CLK_SEL	, STB0899_BASE_SYM_CLK_SEL	, 0x00000002 },	/* SYMCLKSEL	*/
+	{ STB0899_OFF0_SOF_SRCH_TO	, STB0899_BASE_SOF_SRCH_TO	, 0x00196464 },	/* SOFSRCHTO	*/
+	{ STB0899_OFF0_ACQ_CNTRL1	, STB0899_BASE_ACQ_CNTRL1	, 0x00000603 },	/* ACQCNTRL1	*/
+	{ STB0899_OFF0_ACQ_CNTRL2	, STB0899_BASE_ACQ_CNTRL2	, 0x02046666 },	/* ACQCNTRL2	*/
+	{ STB0899_OFF0_ACQ_CNTRL3	, STB0899_BASE_ACQ_CNTRL3	, 0x10046583 },	/* ACQCNTRL3	*/
+	{ STB0899_OFF0_FE_SETTLE	, STB0899_BASE_FE_SETTLE	, 0x00010404 },	/* FESETTLE	*/
+	{ STB0899_OFF0_AC_DWELL		, STB0899_BASE_AC_DWELL		, 0x0002aa8a },	/* ACDWELL	*/
+	{ STB0899_OFF0_ACQUIRE_TRIG	, STB0899_BASE_ACQUIRE_TRIG	, 0x00000000 },	/* ACQUIRETRIG	*/
+	{ STB0899_OFF0_LOCK_LOST	, STB0899_BASE_LOCK_LOST	, 0x00000001 },	/* LOCKLOST	*/
+	{ STB0899_OFF0_ACQ_STAT1	, STB0899_BASE_ACQ_STAT1	, 0x00000500 },	/* ACQSTAT1	*/
+	{ STB0899_OFF0_ACQ_TIMEOUT	, STB0899_BASE_ACQ_TIMEOUT	, 0x0028a0a0 },	/* ACQTIMEOUT	*/
+	{ STB0899_OFF0_ACQ_TIME		, STB0899_BASE_ACQ_TIME		, 0x00000000 },	/* ACQTIME	*/
+	{ STB0899_OFF0_FINAL_AGC_CNTRL	, STB0899_BASE_FINAL_AGC_CNTRL	, 0x00800c17 },	/* FINALAGCCNTRL*/
+	{ STB0899_OFF0_FINAL_AGC_GAIN	, STB0899_BASE_FINAL_AGC_GAIN	, 0x00000000 },	/* FINALAGCCGAIN*/
+	{ STB0899_OFF0_EQUALIZER_INIT	, STB0899_BASE_EQUALIZER_INIT	, 0x00000000 },	/* EQUILIZERINIT*/
+	{ STB0899_OFF0_EQ_CNTRL		, STB0899_BASE_EQ_CNTRL		, 0x00054802 },	/* EQCNTL	*/
+	{ STB0899_OFF0_EQ_I_INIT_COEFF_0, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF0 */
+	{ STB0899_OFF1_EQ_I_INIT_COEFF_1, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF1 */
+	{ STB0899_OFF2_EQ_I_INIT_COEFF_2, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF2 */
+	{ STB0899_OFF3_EQ_I_INIT_COEFF_3, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF3 */
+	{ STB0899_OFF4_EQ_I_INIT_COEFF_4, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF4 */
+	{ STB0899_OFF5_EQ_I_INIT_COEFF_5, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000400 },	/* EQIINITCOEFF5 */
+	{ STB0899_OFF6_EQ_I_INIT_COEFF_6, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF6 */
+	{ STB0899_OFF7_EQ_I_INIT_COEFF_7, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF7 */
+	{ STB0899_OFF8_EQ_I_INIT_COEFF_8, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF8 */
+	{ STB0899_OFF9_EQ_I_INIT_COEFF_9, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF9 */
+	{ STB0899_OFFa_EQ_I_INIT_COEFF_10,STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF10*/
+	{ STB0899_OFF0_EQ_Q_INIT_COEFF_0, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF0 */
+	{ STB0899_OFF1_EQ_Q_INIT_COEFF_1, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF1 */
+	{ STB0899_OFF2_EQ_Q_INIT_COEFF_2, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF2 */
+	{ STB0899_OFF3_EQ_Q_INIT_COEFF_3, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF3 */
+	{ STB0899_OFF4_EQ_Q_INIT_COEFF_4, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF4 */
+	{ STB0899_OFF5_EQ_Q_INIT_COEFF_5, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF5 */
+	{ STB0899_OFF6_EQ_Q_INIT_COEFF_6, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF6 */
+	{ STB0899_OFF7_EQ_Q_INIT_COEFF_7, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF7 */
+	{ STB0899_OFF8_EQ_Q_INIT_COEFF_8, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF8 */
+	{ STB0899_OFF9_EQ_Q_INIT_COEFF_9, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF9 */
+	{ STB0899_OFFa_EQ_Q_INIT_COEFF_10,STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF10*/
+	{ STB0899_OFF0_EQ_I_OUT_COEFF_0	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT0 */
+	{ STB0899_OFF1_EQ_I_OUT_COEFF_1	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT1 */
+	{ STB0899_OFF2_EQ_I_OUT_COEFF_2	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT2 */
+	{ STB0899_OFF3_EQ_I_OUT_COEFF_3	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT3 */
+	{ STB0899_OFF4_EQ_I_OUT_COEFF_4	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT4 */
+	{ STB0899_OFF5_EQ_I_OUT_COEFF_5	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT5 */
+	{ STB0899_OFF6_EQ_I_OUT_COEFF_6	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT6 */
+	{ STB0899_OFF7_EQ_I_OUT_COEFF_7	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT7 */
+	{ STB0899_OFF8_EQ_I_OUT_COEFF_8	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT8 */
+	{ STB0899_OFF9_EQ_I_OUT_COEFF_9	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT9 */
+	{ STB0899_OFFa_EQ_I_OUT_COEFF_10,STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT10*/
+	{ STB0899_OFF0_EQ_Q_OUT_COEFF_0	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT0 */
+	{ STB0899_OFF1_EQ_Q_OUT_COEFF_1	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT1 */
+	{ STB0899_OFF2_EQ_Q_OUT_COEFF_2	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT2 */
+	{ STB0899_OFF3_EQ_Q_OUT_COEFF_3	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT3 */
+	{ STB0899_OFF4_EQ_Q_OUT_COEFF_4	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT4 */
+	{ STB0899_OFF5_EQ_Q_OUT_COEFF_5	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT5 */
+	{ STB0899_OFF6_EQ_Q_OUT_COEFF_6 , STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT6 */
+	{ STB0899_OFF7_EQ_Q_OUT_COEFF_7	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT7 */
+	{ STB0899_OFF8_EQ_Q_OUT_COEFF_8	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT8 */
+	{ STB0899_OFF9_EQ_Q_OUT_COEFF_9	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT9 */
+	{ STB0899_OFFa_EQ_Q_OUT_COEFF_10, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT10*/
+	{ 0xffff			, 0xffffffff			, 0xffffffff },
+};
+static const struct stb0899_s2_reg stb0899_s2_init_4[] = {
+	{ STB0899_OFF0_BLOCK_LNGTH	, STB0899_BASE_BLOCK_LNGTH	, 0x00000008 },	/* BLOCKLNGTH	*/
+	{ STB0899_OFF0_ROW_STR		, STB0899_BASE_ROW_STR		, 0x000000b4 },	/* ROWSTR	*/
+	{ STB0899_OFF0_BN_END_ADDR	, STB0899_BASE_BN_END_ADDR	, 0x000004b5 },	/* BNANDADDR	*/
+	{ STB0899_OFF0_CN_END_ADDR	, STB0899_BASE_CN_END_ADDR	, 0x00000b4b },	/* CNANDADDR	*/
+	{ STB0899_OFF0_INFO_LENGTH	, STB0899_BASE_INFO_LENGTH	, 0x00000078 },	/* INFOLENGTH	*/
+	{ STB0899_OFF0_BOT_ADDR		, STB0899_BASE_BOT_ADDR		, 0x000001e0 },	/* BOT_ADDR	*/
+	{ STB0899_OFF0_BCH_BLK_LN	, STB0899_BASE_BCH_BLK_LN	, 0x0000a8c0 },	/* BCHBLKLN	*/
+	{ STB0899_OFF0_BCH_T		, STB0899_BASE_BCH_T		, 0x0000000c },	/* BCHT		*/
+	{ STB0899_OFF0_CNFG_MODE	, STB0899_BASE_CNFG_MODE	, 0x00000001 },	/* CNFGMODE	*/
+	{ STB0899_OFF0_LDPC_STAT	, STB0899_BASE_LDPC_STAT	, 0x0000000d },	/* LDPCSTAT	*/
+	{ STB0899_OFF0_ITER_SCALE	, STB0899_BASE_ITER_SCALE	, 0x00000040 },	/* ITERSCALE	*/
+	{ STB0899_OFF0_INPUT_MODE	, STB0899_BASE_INPUT_MODE	, 0x00000000 },	/* INPUTMODE	*/
+	{ STB0899_OFF0_LDPCDECRST	, STB0899_BASE_LDPCDECRST	, 0x00000000 },	/* LDPCDECRST	*/
+	{ STB0899_OFF0_CLK_PER_BYTE_RW	, STB0899_BASE_CLK_PER_BYTE_RW	, 0x00000008 },	/* CLKPERBYTE	*/
+	{ STB0899_OFF0_BCH_ERRORS	, STB0899_BASE_BCH_ERRORS	, 0x00000000 },	/* BCHERRORS	*/
+	{ STB0899_OFF0_LDPC_ERRORS	, STB0899_BASE_LDPC_ERRORS	, 0x00000000 },	/* LDPCERRORS	*/
+	{ STB0899_OFF0_BCH_MODE		, STB0899_BASE_BCH_MODE		, 0x00000000 },	/* BCHMODE	*/
+	{ STB0899_OFF0_ERR_ACC_PER	, STB0899_BASE_ERR_ACC_PER	, 0x00000008 },	/* ERRACCPER	*/
+	{ STB0899_OFF0_BCH_ERR_ACC	, STB0899_BASE_BCH_ERR_ACC	, 0x00000000 },	/* BCHERRACC	*/
+	{ STB0899_OFF0_FEC_TP_SEL	, STB0899_BASE_FEC_TP_SEL	, 0x00000000 },	/* FECTPSEL	*/
+	{ 0xffff			, 0xffffffff			, 0xffffffff },
+};
+
+static const struct stb0899_s1_reg stb0899_s1_init_5[] = {
+	{ STB0899_TSTCK		, 0x00 },
+	{ STB0899_TSTRES	, 0x00 },
+	{ STB0899_TSTOUT	, 0x00 },
+	{ STB0899_TSTIN		, 0x00 },
+	{ STB0899_TSTSYS	, 0x00 },
+	{ STB0899_TSTCHIP	, 0x00 },
+	{ STB0899_TSTFREE	, 0x00 },
+	{ STB0899_TSTI2C	, 0x00 },
+	{ STB0899_BITSPEEDM	, 0x00 },
+	{ STB0899_BITSPEEDL	, 0x00 },
+	{ STB0899_TBUSBIT	, 0x00 },
+	{ STB0899_TSTDIS	, 0x00 },
+	{ STB0899_TSTDISRX	, 0x00 },
+	{ STB0899_TSTJETON	, 0x00 },
+	{ STB0899_TSTDCADJ	, 0x00 },
+	{ STB0899_TSTAGC1	, 0x00 },
+	{ STB0899_TSTAGC1N	, 0x00 },
+	{ STB0899_TSTPOLYPH	, 0x00 },
+	{ STB0899_TSTR		, 0x00 },
+	{ STB0899_TSTAGC2	, 0x00 },
+	{ STB0899_TSTCTL1	, 0x00 },
+	{ STB0899_TSTCTL2	, 0x00 },
+	{ STB0899_TSTCTL3	, 0x00 },
+	{ STB0899_TSTDEMAP	, 0x00 },
+	{ STB0899_TSTDEMAP2	, 0x00 },
+	{ STB0899_TSTDEMMON	, 0x00 },
+	{ STB0899_TSTRATE	, 0x00 },
+	{ STB0899_TSTSELOUT	, 0x00 },
+	{ STB0899_TSYNC		, 0x00 },
+	{ STB0899_TSTERR	, 0x00 },
+	{ STB0899_TSTRAM1	, 0x00 },
+	{ STB0899_TSTVSELOUT	, 0x00 },
+	{ STB0899_TSTFORCEIN	, 0x00 },
+	{ STB0899_TSTRS1	, 0x00 },
+	{ STB0899_TSTRS2	, 0x00 },
+	{ STB0899_TSTRS3	, 0x00 },
+	{ STB0899_GHOSTREG	, 0x81 },
+	{ 0xffff		, 0xff },
+};
+
+#define STB0899_DVBS2_ESNO_AVE			3
+#define STB0899_DVBS2_ESNO_QUANT		32
+#define STB0899_DVBS2_AVFRAMES_COARSE		10
+#define STB0899_DVBS2_AVFRAMES_FINE		20
+#define STB0899_DVBS2_MISS_THRESHOLD		6
+#define STB0899_DVBS2_UWP_THRESHOLD_ACQ		1125
+#define STB0899_DVBS2_UWP_THRESHOLD_TRACK	758
+#define STB0899_DVBS2_UWP_THRESHOLD_SOF		1350
+#define STB0899_DVBS2_SOF_SEARCH_TIMEOUT	1664100
+
+#define STB0899_DVBS2_BTR_NCO_BITS		28
+#define STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET	15
+#define STB0899_DVBS2_CRL_NCO_BITS		30
+#define STB0899_DVBS2_LDPC_MAX_ITER		70
+
+#endif //__STB0899_CFG_H

+ 1684 - 0
drivers/media/dvb/frontends/stb0899_drv.c

@@ -0,0 +1,1684 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#include "stb0899_drv.h"
+#include "stb0899_priv.h"
+#include "stb0899_reg.h"
+
+static unsigned int verbose = 0;//1;
+module_param(verbose, int, 0644);
+
+/* C/N in dB/10, NIRM/NIRL */
+static const struct stb0899_tab stb0899_cn_tab[] = {
+	{ 200,	2600 },
+	{ 190,	2700 },
+	{ 180,	2860 },
+	{ 170,	3020 },
+	{ 160,	3210 },
+	{ 150,	3440 },
+	{ 140,	3710 },
+	{ 130,	4010 },
+	{ 120,	4360 },
+	{ 110,	4740 },
+	{ 100,	5190 },
+	{ 90,	5670 },
+	{ 80,	6200 },
+	{ 70,	6770 },
+	{ 60,	7360 },
+	{ 50,	7970 },
+	{ 40,	8250 },
+	{ 30,	9000 },
+	{ 20,	9450 },
+	{ 15,	9600 },
+};
+
+/* DVB-S AGCIQ_VALUE vs. signal level in dBm/10.
+ * As measured, connected to a modulator.
+ * -8.0 to -50.0 dBm directly connected,
+ * -52.0 to -74.8 with extra attenuation.
+ * Cut-off to AGCIQ_VALUE = 0x80 below -74.8dBm.
+ * Crude linear extrapolation below -84.8dBm and above -8.0dBm.
+ */
+static const struct stb0899_tab stb0899_dvbsrf_tab[] = {
+	{ -950,	-128 },
+	{ -748,	 -94 },
+	{ -745,	 -92 },
+	{ -735,	 -90 },
+	{ -720,	 -87 },
+	{ -670,	 -77 },
+	{ -640,	 -70 },
+	{ -610,	 -62 },
+	{ -600,	 -60 },
+	{ -590,	 -56 },
+	{ -560,	 -41 },
+	{ -540,	 -25 },
+	{ -530,	 -17 },
+	{ -520,	 -11 },
+	{ -500,	   1 },
+	{ -490,	   6 },
+	{ -480,	  10 },
+	{ -440,	  22 },
+	{ -420,	  27 },
+	{ -400,	  31 },
+	{ -380,	  34 },
+	{ -340,	  40 },
+	{ -320,	  43 },
+	{ -280,	  48 },
+	{ -250,	  52 },
+	{ -230,	  55 },
+	{ -180,	  61 },
+	{ -140,	  66 },
+	{  -90,	  73 },
+	{  -80,	  74 },
+	{  500,	 127 }
+};
+
+/* DVB-S2 IF_AGC_GAIN vs. signal level in dBm/10.
+ * As measured, connected to a modulator.
+ * -8.0 to -50.1 dBm directly connected,
+ * -53.0 to -76.6 with extra attenuation.
+ * Cut-off to IF_AGC_GAIN = 0x3fff below -76.6dBm.
+ * Crude linear extrapolation below -76.6dBm and above -8.0dBm.
+ */
+static const struct stb0899_tab stb0899_dvbs2rf_tab[] = {
+	{  700,	    0 },
+	{  -80,	 3217 },
+	{ -150,	 3893 },
+	{ -190,	 4217 },
+	{ -240,	 4621 },
+	{ -280,	 4945 },
+	{ -320,	 5273 },
+	{ -350,	 5545 },
+	{ -370,	 5741 },
+	{ -410,	 6147 },
+	{ -450,	 6671 },
+	{ -490,	 7413 },
+	{ -501,	 7665 },
+	{ -530,	 8767 },
+	{ -560,	10219 },
+	{ -580,	10939 },
+	{ -590,	11518 },
+	{ -600,	11723 },
+	{ -650,	12659 },
+	{ -690,	13219 },
+	{ -730,	13645 },
+	{ -750,	13909 },
+	{ -766,	14153 },
+	{ -999,	16383 }
+};
+
+/* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/
+struct stb0899_tab stb0899_quant_tab[] = {
+	{    0,	    0 },
+	{    0,	  100 },
+	{  600,	  200 },
+	{  950,	  299 },
+	{ 1200,	  398 },
+	{ 1400,	  501 },
+	{ 1560,	  603 },
+	{ 1690,	  700 },
+	{ 1810,	  804 },
+	{ 1910,	  902 },
+	{ 2000,	 1000 },
+	{ 2080,	 1096 },
+	{ 2160,	 1202 },
+	{ 2230,	 1303 },
+	{ 2350,	 1496 },
+	{ 2410,	 1603 },
+	{ 2460,	 1698 },
+	{ 2510,	 1799 },
+	{ 2600,	 1995 },
+	{ 2650,	 2113 },
+	{ 2690,  2213 },
+	{ 2720,	 2291 },
+	{ 2760,	 2399 },
+	{ 2800,	 2512 },
+	{ 2860,	 2692 },
+	{ 2930,	 2917 },
+	{ 2960,	 3020 },
+	{ 3010,	 3199 },
+	{ 3040,	 3311 },
+	{ 3060,	 3388 },
+	{ 3120,	 3631 },
+	{ 3190,	 3936 },
+	{ 3400,	 5012 },
+	{ 3610,	 6383 },
+	{ 3800,	 7943 },
+	{ 4210,	12735 },
+	{ 4500,	17783 },
+	{ 4690,	22131 },
+	{ 4810,	25410 }
+};
+
+/* DVB-S2 Es/N0 estimate in dB/100 vs read value */
+struct stb0899_tab stb0899_est_tab[] = {
+	{    0,	     0 },
+	{    0,	     1 },
+	{  301,	     2 },
+	{ 1204,	    16 },
+	{ 1806,	    64 },
+	{ 2408,	   256 },
+	{ 2709,	   512 },
+	{ 3010,	  1023 },
+	{ 3311,	  2046 },
+	{ 3612,	  4093 },
+	{ 3823,	  6653 },
+	{ 3913,	  8185 },
+	{ 4010,	 10233 },
+	{ 4107,	 12794 },
+	{ 4214,	 16368 },
+	{ 4266,	 18450 },
+	{ 4311,	 20464 },
+	{ 4353,	 22542 },
+	{ 4391,	 24604 },
+	{ 4425,	 26607 },
+	{ 4457,	 28642 },
+	{ 4487,	 30690 },
+	{ 4515,	 32734 },
+	{ 4612,	 40926 },
+	{ 4692,	 49204 },
+	{ 4816,	 65464 },
+	{ 4913,	 81846 },
+	{ 4993,	 98401 },
+	{ 5060,	114815 },
+	{ 5118,	131220 },
+	{ 5200,	158489 },
+	{ 5300,	199526 },
+	{ 5400,	251189 },
+	{ 5500,	316228 },
+	{ 5600,	398107 },
+	{ 5720,	524807 },
+	{ 5721,	526017 },
+};
+
+int _stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
+{
+	int ret;
+
+	u8 b0[] = { reg >> 8, reg & 0xff };
+	u8 buf;
+
+	struct i2c_msg msg[] = {
+		{
+			.addr	= state->config->demod_address,
+			.flags	= 0,
+			.buf	= b0,
+			.len	= 2
+		},{
+			.addr	= state->config->demod_address,
+			.flags	= I2C_M_RD,
+			.buf	= &buf,
+			.len	= 1
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret != 2) {
+		if (ret != -ERESTARTSYS)
+			dprintk(state->verbose, FE_ERROR, 1,
+				"Read error, Reg=[0x%02x], Status=%d",
+				reg, ret);
+
+		return ret < 0 ? ret : -EREMOTEIO;
+	}
+	if (unlikely(*state->verbose >= FE_DEBUGREG))
+		dprintk(state->verbose, FE_ERROR, 1, "Reg=[0x%02x], data=%02x",
+			reg, buf);
+
+	return (unsigned int)buf;
+}
+
+int stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
+{
+	int result;
+
+	result = _stb0899_read_reg(state, reg);
+	/*
+	 * Bug ID 9:
+	 * access to 0xf2xx/0xf6xx
+	 * must be followed by read from 0xf2ff/0xf6ff.
+	 */
+	if ((reg != 0xf2ff) && (reg != 0xf6ff) &&
+	    (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+		_stb0899_read_reg(state, (reg | 0x00ff));
+
+	return result;
+}
+
+u32 _stb0899_read_s2reg(struct stb0899_state *state,
+			u32 stb0899_i2cdev,
+			u32 stb0899_base_addr,
+			u16 stb0899_reg_offset)
+{
+	int status;
+	u32 data;
+	u8 buf[7] = { 0 };
+	u16 tmpaddr;
+
+	u8 buf_0[] = {
+		GETBYTE(stb0899_i2cdev, BYTE1),		/* 0xf3	S2 Base Address (MSB)	*/
+		GETBYTE(stb0899_i2cdev, BYTE0),		/* 0xfc	S2 Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE0),	/* 0x00	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE1),	/* 0x04	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE2),	/* 0x00	Base Address (MSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE3),	/* 0x00	Base Address (MSB)	*/
+	};
+	u8 buf_1[] = {
+		0x00,	/* 0xf3	Reg Offset	*/
+		0x00,	/* 0x44	Reg Offset	*/
+	};
+
+	struct i2c_msg msg_0 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_0,
+		.len	= 6
+	};
+
+	struct i2c_msg msg_1 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_1,
+		.len	= 2
+	};
+
+	struct i2c_msg msg_r = {
+		.addr	= state->config->demod_address,
+		.flags	= I2C_M_RD,
+		.buf	= buf,
+		.len	= 4
+	};
+
+	tmpaddr = stb0899_reg_offset & 0xff00;
+	if (!(stb0899_reg_offset & 0x8))
+		tmpaddr = stb0899_reg_offset | 0x20;
+
+	buf_1[0] = GETBYTE(tmpaddr, BYTE1);
+	buf_1[1] = GETBYTE(tmpaddr, BYTE0);
+
+	status = i2c_transfer(state->i2c, &msg_0, 1);
+	if (status < 1) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR(1), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+
+		goto err;
+	}
+
+	/* Dummy	*/
+	status = i2c_transfer(state->i2c, &msg_1, 1);
+	if (status < 1)
+		goto err;
+
+	status = i2c_transfer(state->i2c, &msg_r, 1);
+	if (status < 1)
+		goto err;
+
+	buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
+	buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);
+
+	/* Actual	*/
+	status = i2c_transfer(state->i2c, &msg_1, 1);
+	if (status < 1) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR(2), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+		goto err;
+	}
+
+	status = i2c_transfer(state->i2c, &msg_r, 1);
+	if (status < 1) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR(3), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+		return status < 0 ? status : -EREMOTEIO;
+	}
+
+	data = MAKEWORD32(buf[3], buf[2], buf[1], buf[0]);
+	if (unlikely(*state->verbose >= FE_DEBUGREG))
+		printk(KERN_DEBUG "%s Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n",
+		       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, data);
+
+	return data;
+
+err:
+	return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_write_s2reg(struct stb0899_state *state,
+			u32 stb0899_i2cdev,
+			u32 stb0899_base_addr,
+			u16 stb0899_reg_offset,
+			u32 stb0899_data)
+{
+	int status;
+
+	/* Base Address Setup	*/
+	u8 buf_0[] = {
+		GETBYTE(stb0899_i2cdev, BYTE1),		/* 0xf3	S2 Base Address (MSB)	*/
+		GETBYTE(stb0899_i2cdev, BYTE0),		/* 0xfc	S2 Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE0),	/* 0x00	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE1),	/* 0x04	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE2),	/* 0x00	Base Address (MSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE3),	/* 0x00	Base Address (MSB)	*/
+	};
+	u8 buf_1[] = {
+		0x00,	/* 0xf3	Reg Offset	*/
+		0x00,	/* 0x44	Reg Offset	*/
+		0x00,	/* data			*/
+		0x00,	/* data			*/
+		0x00,	/* data			*/
+		0x00,	/* data			*/
+	};
+
+	struct i2c_msg msg_0 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_0,
+		.len	= 6
+	};
+
+	struct i2c_msg msg_1 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_1,
+		.len	= 6
+	};
+
+	buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
+	buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);
+	buf_1[2] = GETBYTE(stb0899_data, BYTE0);
+	buf_1[3] = GETBYTE(stb0899_data, BYTE1);
+	buf_1[4] = GETBYTE(stb0899_data, BYTE2);
+	buf_1[5] = GETBYTE(stb0899_data, BYTE3);
+
+	if (unlikely(*state->verbose >= FE_DEBUGREG))
+		printk(KERN_DEBUG "%s Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n",
+		       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data);
+
+	status = i2c_transfer(state->i2c, &msg_0, 1);
+	if (unlikely(status < 1)) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR (1), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status);
+		goto err;
+	}
+	status = i2c_transfer(state->i2c, &msg_1, 1);
+	if (unlikely(status < 1)) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR (2), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status);
+
+		return status < 0 ? status : -EREMOTEIO;
+	}
+
+	return 0;
+
+err:
+	return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_read_regs(struct stb0899_state *state, unsigned int reg, u8 *buf, u32 count)
+{
+	int status;
+
+	u8 b0[] = { reg >> 8, reg & 0xff };
+
+	struct i2c_msg msg[] = {
+		{
+			.addr	= state->config->demod_address,
+			.flags	= 0,
+			.buf	= b0,
+			.len	= 2
+		},{
+			.addr	= state->config->demod_address,
+			.flags	= I2C_M_RD,
+			.buf	= buf,
+			.len	= count
+		}
+	};
+
+	status = i2c_transfer(state->i2c, msg, 2);
+	if (status != 2) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s Read error, Reg=[0x%04x], Count=%u, Status=%d\n",
+			       __func__, reg, count, status);
+		goto err;
+	}
+	/*
+	 * Bug ID 9:
+	 * access to 0xf2xx/0xf6xx
+	 * must be followed by read from 0xf2ff/0xf6ff.
+	 */
+	if ((reg != 0xf2ff) && (reg != 0xf6ff) &&
+	    (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+		_stb0899_read_reg(state, (reg | 0x00ff));
+
+	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+		int i;
+
+		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+		for (i = 0; i < count; i++) {
+			printk(" %02x", buf[i]);
+		}
+		printk("\n");
+	}
+
+	return 0;
+err:
+	return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, u32 count)
+{
+	int ret;
+	u8 buf[2 + count];
+	struct i2c_msg i2c_msg = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf,
+		.len	= 2 + count
+	};
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xff;
+	memcpy(&buf[2], data, count);
+
+	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+		int i;
+
+		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+		for (i = 0; i < count; i++)
+			printk(" %02x", data[i]);
+		printk("\n");
+	}
+	ret = i2c_transfer(state->i2c, &i2c_msg, 1);
+
+	/*
+	 * Bug ID 9:
+	 * access to 0xf2xx/0xf6xx
+	 * must be followed by read from 0xf2ff/0xf6ff.
+	 */
+	if ((((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+		stb0899_read_reg(state, (reg | 0x00ff));
+
+	if (ret != 1) {
+		if (ret != -ERESTARTSYS)
+			dprintk(state->verbose, FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d",
+				reg, data[0], count, ret);
+		return ret < 0 ? ret : -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data)
+{
+	return stb0899_write_regs(state, reg, &data, 1);
+}
+
+/*
+ * stb0899_get_mclk
+ * Get STB0899 master clock frequency
+ * ExtClk: external clock frequency (Hz)
+ */
+static u32 stb0899_get_mclk(struct stb0899_state *state)
+{
+	u32 mclk = 0, div = 0;
+
+	div = stb0899_read_reg(state, STB0899_NCOARSE);
+	mclk = (div + 1) * state->config->xtal_freq / 6;
+	dprintk(state->verbose, FE_DEBUG, 1, "div=%d, mclk=%d", div, mclk);
+
+	return mclk;
+}
+
+/*
+ * stb0899_set_mclk
+ * Set STB0899 master Clock frequency
+ * Mclk: demodulator master clock
+ * ExtClk: external clock frequency (Hz)
+ */
+static void stb0899_set_mclk(struct stb0899_state *state, u32 Mclk)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u8 mdiv = 0;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "state->config=%p", state->config);
+	mdiv = ((6 * Mclk) / state->config->xtal_freq) - 1;
+	dprintk(state->verbose, FE_DEBUG, 1, "mdiv=%d", mdiv);
+
+	stb0899_write_reg(state, STB0899_NCOARSE, mdiv);
+	internal->master_clk = stb0899_get_mclk(state);
+
+	dprintk(state->verbose, FE_DEBUG, 1, "MasterCLOCK=%d", internal->master_clk);
+}
+
+static int stb0899_postproc(struct stb0899_state *state, u8 ctl, int enable)
+{
+	struct stb0899_config *config		= state->config;
+	const struct stb0899_postproc *postproc	= config->postproc;
+
+	/* post process event */
+	if (postproc) {
+		if (enable) {
+			if (postproc[ctl].level == STB0899_GPIOPULLUP)
+				stb0899_write_reg(state, postproc[ctl].gpio, 0x02);
+			else
+				stb0899_write_reg(state, postproc[ctl].gpio, 0x82);
+		} else {
+			if (postproc[ctl].level == STB0899_GPIOPULLUP)
+				stb0899_write_reg(state, postproc[ctl].gpio, 0x82);
+			else
+				stb0899_write_reg(state, postproc[ctl].gpio, 0x02);
+		}
+	}
+	return 0;
+}
+
+static void stb0899_release(struct dvb_frontend *fe)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
+	/* post process event */
+	stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
+	kfree(state);
+}
+
+/*
+ * stb0899_get_alpha
+ * return: rolloff
+ */
+static int stb0899_get_alpha(struct stb0899_state *state)
+{
+	u8 mode_coeff;
+
+	mode_coeff = stb0899_read_reg(state, STB0899_DEMOD);
+
+	if (STB0899_GETFIELD(MODECOEFF, mode_coeff) == 1)
+		return 20;
+	else
+		return 35;
+}
+
+/*
+ * stb0899_init_calc
+ */
+static void stb0899_init_calc(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	int master_clk;
+	u8 agc[2];
+	u8 agc1cn;
+	u32 reg;
+
+	/* Read registers (in burst mode)	*/
+	agc1cn = stb0899_read_reg(state, STB0899_AGC1CN);
+	stb0899_read_regs(state, STB0899_AGC1REF, agc, 2); /* AGC1R and AGC2O	*/
+
+	/* Initial calculations	*/
+	master_clk			= stb0899_get_mclk(state);
+	internal->t_agc1		= 0;
+	internal->t_agc2		= 0;
+	internal->master_clk		= master_clk;
+	internal->mclk			= master_clk / 65536L;
+	internal->rolloff		= stb0899_get_alpha(state);
+
+	/* DVBS2 Initial calculations	*/
+	/* Set AGC value to the middle	*/
+	internal->agc_gain		= 8154;
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+	STB0899_SETFIELD_VAL(IF_GAIN_INIT, reg, internal->agc_gain);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, RRC_ALPHA);
+	internal->rrc_alpha		= STB0899_GETFIELD(RRC_ALPHA, reg);
+
+	internal->center_freq		= 0;
+	internal->av_frame_coarse	= 10;
+	internal->av_frame_fine		= 20;
+	internal->step_size		= 2;
+/*
+	if ((pParams->SpectralInv == FE_IQ_NORMAL) || (pParams->SpectralInv == FE_IQ_AUTO))
+		pParams->IQLocked = 0;
+	else
+		pParams->IQLocked = 1;
+*/
+}
+
+static int stb0899_wait_diseqc_fifo_empty(struct stb0899_state *state, int timeout)
+{
+	u8 reg = 0;
+	unsigned long start = jiffies;
+
+	while (1) {
+		reg = stb0899_read_reg(state, STB0899_DISSTATUS);
+		if (!STB0899_GETFIELD(FIFOFULL, reg))
+			break;
+		if ((jiffies - start) > timeout) {
+			dprintk(state->verbose, FE_ERROR, 1, "timed out !!");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	u8 reg, i;
+
+	if (cmd->msg_len > 8)
+		return -EINVAL;
+
+	/* enable FIFO precharge	*/
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 1);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+	for (i = 0; i < cmd->msg_len; i++) {
+		/* wait for FIFO empty	*/
+		if (stb0899_wait_diseqc_fifo_empty(state, 10) < 0)
+			return -ETIMEDOUT;
+
+		stb0899_write_reg(state, STB0899_DISFIFO, cmd->msg[i]);
+	}
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+
+	return 0;
+}
+
+static int stb0899_wait_diseqc_rxidle(struct stb0899_state *state, int timeout)
+{
+	u8 reg = 0;
+	unsigned long start = jiffies;
+
+	while (!STB0899_GETFIELD(RXEND, reg)) {
+		reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
+		if (jiffies - start > timeout) {
+			dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
+			return -ETIMEDOUT;
+		}
+		msleep(10);
+	}
+
+	return 0;
+}
+
+static int stb0899_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	u8 reg, length = 0, i;
+	int result;
+
+	if (stb0899_wait_diseqc_rxidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
+	if (STB0899_GETFIELD(RXEND, reg)) {
+
+		reg = stb0899_read_reg(state, STB0899_DISRX_ST1);
+		length = STB0899_GETFIELD(FIFOBYTENBR, reg);
+
+		if (length > sizeof (reply->msg)) {
+			result = -EOVERFLOW;
+			goto exit;
+		}
+		reply->msg_len = length;
+
+		/* extract data */
+		for (i = 0; i < length; i++)
+			reply->msg[i] = stb0899_read_reg(state, STB0899_DISFIFO);
+	}
+
+	return 0;
+exit:
+
+	return result;
+}
+
+static int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout)
+{
+	u8 reg = 0;
+	unsigned long start = jiffies;
+
+	while (!STB0899_GETFIELD(TXIDLE, reg)) {
+		reg = stb0899_read_reg(state, STB0899_DISSTATUS);
+		if (jiffies - start > timeout) {
+			dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
+			return -ETIMEDOUT;
+		}
+		msleep(10);
+	}
+	return 0;
+}
+
+static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	u8 reg, old_state;
+
+	/* wait for diseqc idle	*/
+	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	old_state = reg;
+	/* set to burst mode	*/
+	STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x02);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+	switch (burst) {
+	case SEC_MINI_A:
+		/* unmodulated	*/
+		stb0899_write_reg(state, STB0899_DISFIFO, 0x00);
+		break;
+	case SEC_MINI_B:
+		/* modulated	*/
+		stb0899_write_reg(state, STB0899_DISFIFO, 0xff);
+		break;
+	}
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x00);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+	/* wait for diseqc idle	*/
+	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	/* restore state	*/
+	stb0899_write_reg(state, STB0899_DISCNTRL1, old_state);
+
+	return 0;
+}
+
+static int stb0899_diseqc_init(struct stb0899_state *state)
+{
+	struct dvb_diseqc_master_cmd tx_data;
+/*
+	struct dvb_diseqc_slave_reply rx_data;
+*/
+	u8 f22_tx, f22_rx, reg;
+
+	u32 mclk, tx_freq = 22000;/* count = 0, i; */
+	tx_data.msg[0] = 0xe2;
+	tx_data.msg_len = 3;
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL2);
+	STB0899_SETFIELD_VAL(ONECHIP_TRX, reg, 0);
+	stb0899_write_reg(state, STB0899_DISCNTRL2, reg);
+
+	/* disable Tx spy	*/
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISEQCRESET, reg, 1);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISEQCRESET, reg, 0);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+
+	mclk = stb0899_get_mclk(state);
+	f22_tx = mclk / (tx_freq * 32);
+	stb0899_write_reg(state, STB0899_DISF22, f22_tx); /* DiSEqC Tx freq	*/
+	state->rx_freq = 20000;
+	f22_rx = mclk / (state->rx_freq * 32);
+
+	return 0;
+}
+
+static int stb0899_sleep(struct dvb_frontend *fe)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+/*
+	u8 reg;
+*/
+	dprintk(state->verbose, FE_DEBUG, 1, "Going to Sleep .. (Really tired .. :-))");
+	/* post process event */
+	stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
+
+	return 0;
+}
+
+static int stb0899_wakeup(struct dvb_frontend *fe)
+{
+	int rc;
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	if ((rc = stb0899_write_reg(state, STB0899_SYNTCTRL, STB0899_SELOSCI)))
+		return rc;
+	/* Activate all clocks; DVB-S2 registers are inaccessible otherwise. */
+	if ((rc = stb0899_write_reg(state, STB0899_STOPCLK1, 0x00)))
+		return rc;
+	if ((rc = stb0899_write_reg(state, STB0899_STOPCLK2, 0x00)))
+		return rc;
+
+	/* post process event */
+	stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 1);
+
+	return 0;
+}
+
+static int stb0899_init(struct dvb_frontend *fe)
+{
+	int i;
+	struct stb0899_state *state = fe->demodulator_priv;
+	struct stb0899_config *config = state->config;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "Initializing STB0899 ... ");
+
+	/* init device		*/
+	dprintk(state->verbose, FE_DEBUG, 1, "init device");
+	for (i = 0; config->init_dev[i].address != 0xffff; i++)
+		stb0899_write_reg(state, config->init_dev[i].address, config->init_dev[i].data);
+
+	dprintk(state->verbose, FE_DEBUG, 1, "init S2 demod");
+	/* init S2 demod	*/
+	for (i = 0; config->init_s2_demod[i].offset != 0xffff; i++)
+		stb0899_write_s2reg(state, STB0899_S2DEMOD,
+				    config->init_s2_demod[i].base_address,
+				    config->init_s2_demod[i].offset,
+				    config->init_s2_demod[i].data);
+
+	dprintk(state->verbose, FE_DEBUG, 1, "init S1 demod");
+	/* init S1 demod	*/
+	for (i = 0; config->init_s1_demod[i].address != 0xffff; i++)
+		stb0899_write_reg(state, config->init_s1_demod[i].address, config->init_s1_demod[i].data);
+
+	dprintk(state->verbose, FE_DEBUG, 1, "init S2 FEC");
+	/* init S2 fec		*/
+	for (i = 0; config->init_s2_fec[i].offset != 0xffff; i++)
+		stb0899_write_s2reg(state, STB0899_S2FEC,
+				    config->init_s2_fec[i].base_address,
+				    config->init_s2_fec[i].offset,
+				    config->init_s2_fec[i].data);
+
+	dprintk(state->verbose, FE_DEBUG, 1, "init TST");
+	/* init test		*/
+	for (i = 0; config->init_tst[i].address != 0xffff; i++)
+		stb0899_write_reg(state, config->init_tst[i].address, config->init_tst[i].data);
+
+	stb0899_init_calc(state);
+	stb0899_diseqc_init(state);
+
+	return 0;
+}
+
+static int stb0899_table_lookup(const struct stb0899_tab *tab, int max, int val)
+{
+	int res = 0;
+	int min = 0, med;
+
+	if (val < tab[min].read)
+		res = tab[min].real;
+	else if (val >= tab[max].read)
+		res = tab[max].real;
+	else {
+		while ((max - min) > 1) {
+			med = (max + min) / 2;
+			if (val >= tab[min].read && val < tab[med].read)
+				max = med;
+			else
+				min = med;
+		}
+		res = ((val - tab[min].read) *
+		       (tab[max].real - tab[min].real) /
+		       (tab[max].read - tab[min].read)) +
+			tab[min].real;
+	}
+
+	return res;
+}
+
+static int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	int val;
+	u32 reg;
+	switch (state->delsys) {
+	case SYS_DVBS:
+	case SYS_DSS:
+		if (internal->lock) {
+			reg  = stb0899_read_reg(state, STB0899_VSTATUS);
+			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+
+				reg = stb0899_read_reg(state, STB0899_AGCIQIN);
+				val = (s32)(s8)STB0899_GETFIELD(AGCIQVALUE, reg);
+
+				*strength = stb0899_table_lookup(stb0899_dvbsrf_tab, ARRAY_SIZE(stb0899_dvbsrf_tab) - 1, val);
+				*strength += 750;
+				dprintk(state->verbose, FE_DEBUG, 1, "AGCIQVALUE = 0x%02x, C = %d * 0.1 dBm",
+					val & 0xff, *strength);
+			}
+		}
+		break;
+	case SYS_DVBS2:
+		if (internal->lock) {
+			reg = STB0899_READ_S2REG(STB0899_DEMOD, IF_AGC_GAIN);
+			val = STB0899_GETFIELD(IF_AGC_GAIN, reg);
+
+			*strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val);
+			*strength += 750;
+			dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm",
+				val & 0x3fff, *strength);
+		}
+		break;
+	default:
+		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	unsigned int val, quant, quantn = -1, est, estn = -1;
+	u8 buf[2];
+	u32 reg;
+
+	reg  = stb0899_read_reg(state, STB0899_VSTATUS);
+	switch (state->delsys) {
+	case SYS_DVBS:
+	case SYS_DSS:
+		if (internal->lock) {
+			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+
+				stb0899_read_regs(state, STB0899_NIRM, buf, 2);
+				val = MAKEWORD16(buf[0], buf[1]);
+
+				*snr = stb0899_table_lookup(stb0899_cn_tab, ARRAY_SIZE(stb0899_cn_tab) - 1, val);
+				dprintk(state->verbose, FE_DEBUG, 1, "NIR = 0x%02x%02x = %u, C/N = %d * 0.1 dBm\n",
+					buf[0], buf[1], val, *snr);
+			}
+		}
+		break;
+	case SYS_DVBS2:
+		if (internal->lock) {
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1);
+			quant = STB0899_GETFIELD(UWP_ESN0_QUANT, reg);
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+			est = STB0899_GETFIELD(ESN0_EST, reg);
+			if (est == 1)
+				val = 301; /* C/N = 30.1 dB */
+			else if (est == 2)
+				val = 270; /* C/N = 27.0 dB */
+			else {
+				/* quantn = 100 * log(quant^2) */
+				quantn = stb0899_table_lookup(stb0899_quant_tab, ARRAY_SIZE(stb0899_quant_tab) - 1, quant * 100);
+				/* estn = 100 * log(est) */
+				estn = stb0899_table_lookup(stb0899_est_tab, ARRAY_SIZE(stb0899_est_tab) - 1, est);
+				/* snr(dBm/10) = -10*(log(est)-log(quant^2)) => snr(dBm/10) = (100*log(quant^2)-100*log(est))/10 */
+				val = (quantn - estn) / 10;
+			}
+			*snr = val;
+			dprintk(state->verbose, FE_DEBUG, 1, "Es/N0 quant = %d (%d) estimate = %u (%d), C/N = %d * 0.1 dBm",
+				quant, quantn, est, estn, val);
+		}
+		break;
+	default:
+		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+	u8 reg;
+	*status = 0;
+
+	switch (state->delsys) {
+	case SYS_DVBS:
+	case SYS_DSS:
+		dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S/DSS");
+		if (internal->lock) {
+			reg  = stb0899_read_reg(state, STB0899_VSTATUS);
+			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+				dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK");
+				*status |= FE_HAS_CARRIER | FE_HAS_LOCK;
+
+				reg = stb0899_read_reg(state, STB0899_PLPARM);
+				if (STB0899_GETFIELD(VITCURPUN, reg)) {
+					dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_VITERBI | FE_HAS_SYNC");
+					*status |= FE_HAS_VITERBI | FE_HAS_SYNC;
+					/* post process event */
+					stb0899_postproc(state, STB0899_POSTPROC_GPIO_LOCK, 1);
+				}
+			}
+		}
+		break;
+	case SYS_DVBS2:
+		dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S2");
+		if (internal->lock) {
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2);
+			if (STB0899_GETFIELD(UWP_LOCK, reg) && STB0899_GETFIELD(CSM_LOCK, reg)) {
+				*status |= FE_HAS_CARRIER;
+				dprintk(state->verbose, FE_DEBUG, 1,
+					"UWP & CSM Lock ! ---> DVB-S2 FE_HAS_CARRIER");
+
+				reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1);
+				if (STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg)) {
+					*status |= FE_HAS_LOCK;
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"Packet Delineator Locked ! -----> DVB-S2 FE_HAS_LOCK");
+
+				}
+				if (STB0899_GETFIELD(CONTINUOUS_STREAM, reg)) {
+					*status |= FE_HAS_VITERBI;
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"Packet Delineator found VITERBI ! -----> DVB-S2 FE_HAS_VITERBI");
+				}
+				if (STB0899_GETFIELD(ACCEPTED_STREAM, reg)) {
+					*status |= FE_HAS_SYNC;
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"Packet Delineator found SYNC ! -----> DVB-S2 FE_HAS_SYNC");
+					/* post process event */
+					stb0899_postproc(state, STB0899_POSTPROC_GPIO_LOCK, 1);
+				}
+			}
+		}
+		break;
+	default:
+		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * stb0899_get_error
+ * viterbi error for DVB-S/DSS
+ * packet error for DVB-S2
+ * Bit Error Rate or Packet Error Rate * 10 ^ 7
+ */
+static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	u8  lsb, msb;
+	u32 i;
+
+	*ber = 0;
+
+	switch (state->delsys) {
+	case SYS_DVBS:
+	case SYS_DSS:
+		if (internal->lock) {
+			/* average 5 BER values	*/
+			for (i = 0; i < 5; i++) {
+				msleep(100);
+				lsb = stb0899_read_reg(state, STB0899_ECNT1L);
+				msb = stb0899_read_reg(state, STB0899_ECNT1M);
+				*ber += MAKEWORD16(msb, lsb);
+			}
+			*ber /= 5;
+			/* Viterbi Check	*/
+			if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) {
+				/* Error Rate		*/
+				*ber *= 9766;
+				/* ber = ber * 10 ^ 7	*/
+				*ber /= (-1 + (1 << (2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
+				*ber /= 8;
+			}
+		}
+		break;
+	case SYS_DVBS2:
+		if (internal->lock) {
+			/* Average 5 PER values	*/
+			for (i = 0; i < 5; i++) {
+				msleep(100);
+				lsb = stb0899_read_reg(state, STB0899_ECNT1L);
+				msb = stb0899_read_reg(state, STB0899_ECNT1M);
+				*ber += MAKEWORD16(msb, lsb);
+			}
+			/* ber = ber * 10 ^ 7	*/
+			*ber *= 10000000;
+			*ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
+		}
+		break;
+	default:
+		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82);
+		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02);
+		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x00);
+		break;
+	case SEC_VOLTAGE_18:
+		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x02);
+		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02);
+		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82);
+		break;
+	case SEC_VOLTAGE_OFF:
+		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82);
+		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x82);
+		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	struct stb0899_internal *internal = &state->internal;
+
+	u8 div, reg;
+
+	/* wait for diseqc idle	*/
+	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		div = (internal->master_clk / 100) / 5632;
+		div = (div + 5) / 10;
+		stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x66);
+		reg = stb0899_read_reg(state, STB0899_ACRPRESC);
+		STB0899_SETFIELD_VAL(ACRPRESC, reg, 0x03);
+		stb0899_write_reg(state, STB0899_ACRPRESC, reg);
+		stb0899_write_reg(state, STB0899_ACRDIV1, div);
+		break;
+	case SEC_TONE_OFF:
+		stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x20);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int stb0899_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	int i2c_stat;
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	i2c_stat = stb0899_read_reg(state, STB0899_I2CRPT);
+	if (i2c_stat < 0)
+		goto err;
+
+	if (enable) {
+		dprintk(state->verbose, FE_DEBUG, 1, "Enabling I2C Repeater ...");
+		i2c_stat |=  STB0899_I2CTON;
+		if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0)
+			goto err;
+	} else {
+		dprintk(state->verbose, FE_DEBUG, 1, "Disabling I2C Repeater ...");
+		i2c_stat &= ~STB0899_I2CTON;
+		if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	dprintk(state->verbose, FE_ERROR, 1, "I2C Repeater control failed");
+	return -EREMOTEIO;
+}
+
+
+static inline void CONVERT32(u32 x, char *str)
+{
+	*str++	= (x >> 24) & 0xff;
+	*str++	= (x >> 16) & 0xff;
+	*str++	= (x >>  8) & 0xff;
+	*str++	= (x >>  0) & 0xff;
+	*str	= '\0';
+}
+
+int stb0899_get_dev_id(struct stb0899_state *state)
+{
+	u8 chip_id, release;
+	u16 id;
+	u32 demod_ver = 0, fec_ver = 0;
+	char demod_str[5] = { 0 };
+	char fec_str[5] = { 0 };
+
+	id = stb0899_read_reg(state, STB0899_DEV_ID);
+	dprintk(state->verbose, FE_DEBUG, 1, "ID reg=[0x%02x]", id);
+	chip_id = STB0899_GETFIELD(CHIP_ID, id);
+	release = STB0899_GETFIELD(CHIP_REL, id);
+
+	dprintk(state->verbose, FE_ERROR, 1, "Device ID=[%d], Release=[%d]",
+		chip_id, release);
+
+	CONVERT32(STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CORE_ID), (char *)&demod_str);
+
+	demod_ver = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_VERSION_ID);
+	dprintk(state->verbose, FE_ERROR, 1, "Demodulator Core ID=[%s], Version=[%d]", (char *) &demod_str, demod_ver);
+	CONVERT32(STB0899_READ_S2REG(STB0899_S2FEC, FEC_CORE_ID_REG), (char *)&fec_str);
+	fec_ver = STB0899_READ_S2REG(STB0899_S2FEC, FEC_VER_ID_REG);
+	if (! (chip_id > 0)) {
+		dprintk(state->verbose, FE_ERROR, 1, "couldn't find a STB 0899");
+
+		return -ENODEV;
+	}
+	dprintk(state->verbose, FE_ERROR, 1, "FEC Core ID=[%s], Version=[%d]", (char*) &fec_str, fec_ver);
+
+	return 0;
+}
+
+static void stb0899_set_delivery(struct stb0899_state *state)
+{
+	u8 reg;
+	u8 stop_clk[2];
+
+	stop_clk[0] = stb0899_read_reg(state, STB0899_STOPCLK1);
+	stop_clk[1] = stb0899_read_reg(state, STB0899_STOPCLK2);
+
+	switch (state->delsys) {
+	case SYS_DVBS:
+		dprintk(state->verbose, FE_DEBUG, 1, "Delivery System -- DVB-S");
+		/* FECM/Viterbi ON	*/
+		reg = stb0899_read_reg(state, STB0899_FECM);
+		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0);
+		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1);
+		stb0899_write_reg(state, STB0899_FECM, reg);
+
+		stb0899_write_reg(state, STB0899_RSULC, 0xb1);
+		stb0899_write_reg(state, STB0899_TSULC, 0x40);
+		stb0899_write_reg(state, STB0899_RSLLC, 0x42);
+		stb0899_write_reg(state, STB0899_TSLPL, 0x12);
+
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESLDPC, reg, 1);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1);
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1);
+		break;
+	case SYS_DVBS2:
+		/* FECM/Viterbi OFF	*/
+		reg = stb0899_read_reg(state, STB0899_FECM);
+		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0);
+		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 0);
+		stb0899_write_reg(state, STB0899_FECM, reg);
+
+		stb0899_write_reg(state, STB0899_RSULC, 0xb1);
+		stb0899_write_reg(state, STB0899_TSULC, 0x42);
+		stb0899_write_reg(state, STB0899_RSLLC, 0x40);
+		stb0899_write_reg(state, STB0899_TSLPL, 0x02);
+
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESLDPC, reg, 0);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 0);
+		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 0);
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 0);
+		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 0);
+		break;
+	case SYS_DSS:
+		/* FECM/Viterbi ON	*/
+		reg = stb0899_read_reg(state, STB0899_FECM);
+		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 1);
+		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1);
+		stb0899_write_reg(state, STB0899_FECM, reg);
+
+		stb0899_write_reg(state, STB0899_RSULC, 0xa1);
+		stb0899_write_reg(state, STB0899_TSULC, 0x61);
+		stb0899_write_reg(state, STB0899_RSLLC, 0x42);
+
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESLDPC, reg, 1);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1);
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1);
+		break;
+	default:
+		dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system");
+		break;
+	}
+	STB0899_SETFIELD_VAL(STOP_CKADCI108, stop_clk[0], 0);
+	stb0899_write_regs(state, STB0899_STOPCLK1, stop_clk, 2);
+}
+
+/*
+ * stb0899_set_iterations
+ * set the LDPC iteration scale function
+ */
+static void stb0899_set_iterations(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+
+	s32 iter_scale;
+	u32 reg;
+
+	iter_scale = 17 * (internal->master_clk / 1000);
+	iter_scale += 410000;
+	iter_scale /= (internal->srate / 1000000);
+	iter_scale /= 1000;
+
+	if (iter_scale > config->ldpc_max_iter)
+		iter_scale = config->ldpc_max_iter;
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, MAX_ITER);
+	STB0899_SETFIELD_VAL(MAX_ITERATIONS, reg, iter_scale);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
+}
+
+static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	struct stb0899_params *i_params = &state->params;
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+	struct dtv_frontend_properties *props = &fe->dtv_property_cache;
+
+	u32 SearchRange, gain;
+
+	i_params->freq	= p->frequency;
+	i_params->srate = p->u.qpsk.symbol_rate;
+	state->delsys = props->delivery_system;
+	dprintk(state->verbose, FE_DEBUG, 1, "delivery system=%d", state->delsys);
+
+	SearchRange = 10000000;
+	dprintk(state->verbose, FE_DEBUG, 1, "Frequency=%d, Srate=%d", i_params->freq, i_params->srate);
+	/* checking Search Range is meaningless for a fixed 3 Mhz			*/
+	if (INRANGE(i_params->srate, 1000000, 45000000)) {
+		dprintk(state->verbose, FE_DEBUG, 1, "Parameters IN RANGE");
+		stb0899_set_delivery(state);
+
+		if (state->config->tuner_set_rfsiggain) {
+			if (internal->srate > 15000000)
+				gain =  8; /* 15Mb < srate < 45Mb, gain = 8dB	*/
+			else if (internal->srate > 5000000)
+				gain = 12; /*  5Mb < srate < 15Mb, gain = 12dB	*/
+			else
+				gain = 14; /*  1Mb < srate <  5Mb, gain = 14db	*/
+			state->config->tuner_set_rfsiggain(fe, gain);
+		}
+
+		if (i_params->srate <= 5000000)
+			stb0899_set_mclk(state, config->lo_clk);
+		else
+			stb0899_set_mclk(state, config->hi_clk);
+
+		switch (state->delsys) {
+		case SYS_DVBS:
+		case SYS_DSS:
+			dprintk(state->verbose, FE_DEBUG, 1, "DVB-S delivery system");
+			internal->freq	= i_params->freq;
+			internal->srate	= i_params->srate;
+			/*
+			 * search = user search range +
+			 *	    500Khz +
+			 *	    2 * Tuner_step_size +
+			 *	    10% of the symbol rate
+			 */
+			internal->srch_range	= SearchRange + 1500000 + (i_params->srate / 5);
+			internal->derot_percent	= 30;
+
+			/* What to do for tuners having no bandwidth setup ?	*/
+			/* enable tuner I/O */
+			stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+			if (state->config->tuner_set_bandwidth)
+				state->config->tuner_set_bandwidth(fe, (13 * (stb0899_carr_width(state) + SearchRange)) / 10);
+			if (state->config->tuner_get_bandwidth)
+				state->config->tuner_get_bandwidth(fe, &internal->tuner_bw);
+
+			/* disable tuner I/O */
+			stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+			/* Set DVB-S1 AGC		*/
+			stb0899_write_reg(state, STB0899_AGCRFCFG, 0x11);
+
+			/* Run the search algorithm	*/
+			dprintk(state->verbose, FE_DEBUG, 1, "running DVB-S search algo ..");
+			if (stb0899_dvbs_algo(state)	== RANGEOK) {
+				internal->lock		= 1;
+				dprintk(state->verbose, FE_DEBUG, 1,
+					"-------------------------------------> DVB-S LOCK !");
+
+//				stb0899_write_reg(state, STB0899_ERRCTRL1, 0x3d); /* Viterbi Errors	*/
+//				internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS);
+//				internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1);
+//				dprintk(state->verbose, FE_DEBUG, 1, "VSTATUS=0x%02x", internal->v_status);
+//				dprintk(state->verbose, FE_DEBUG, 1, "ERR_CTRL=0x%02x", internal->err_ctrl);
+
+				return DVBFE_ALGO_SEARCH_SUCCESS;
+			} else {
+				internal->lock		= 0;
+
+				return DVBFE_ALGO_SEARCH_FAILED;
+			}
+			break;
+		case SYS_DVBS2:
+			internal->freq			= i_params->freq;
+			internal->srate			= i_params->srate;
+			internal->srch_range		= SearchRange;
+
+			/* enable tuner I/O */
+			stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+			if (state->config->tuner_set_bandwidth)
+				state->config->tuner_set_bandwidth(fe, (stb0899_carr_width(state) + SearchRange));
+			if (state->config->tuner_get_bandwidth)
+				state->config->tuner_get_bandwidth(fe, &internal->tuner_bw);
+
+			/* disable tuner I/O */
+			stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+//			pParams->SpectralInv		= pSearch->IQ_Inversion;
+
+			/* Set DVB-S2 AGC		*/
+			stb0899_write_reg(state, STB0899_AGCRFCFG, 0x1c);
+
+			/* Set IterScale =f(MCLK,SYMB)	*/
+			stb0899_set_iterations(state);
+
+			/* Run the search algorithm	*/
+			dprintk(state->verbose, FE_DEBUG, 1, "running DVB-S2 search algo ..");
+			if (stb0899_dvbs2_algo(state)	== DVBS2_FEC_LOCK) {
+				internal->lock		= 1;
+				dprintk(state->verbose, FE_DEBUG, 1,
+					"-------------------------------------> DVB-S2 LOCK !");
+
+//				stb0899_write_reg(state, STB0899_ERRCTRL1, 0xb6); /* Packet Errors	*/
+//				internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS);
+//				internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1);
+
+				return DVBFE_ALGO_SEARCH_SUCCESS;
+			} else {
+				internal->lock		= 0;
+
+				return DVBFE_ALGO_SEARCH_FAILED;
+			}
+			break;
+		default:
+			dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system");
+			return DVBFE_ALGO_SEARCH_INVALID;
+		}
+	}
+
+	return DVBFE_ALGO_SEARCH_ERROR;
+}
+/*
+ * stb0899_track
+ * periodically check the signal level against a specified
+ * threshold level and perform derotator centering.
+ * called once we have a lock from a succesful search
+ * event.
+ *
+ * Will be called periodically called to maintain the
+ * lock.
+ *
+ * Will be used to get parameters as well as info from
+ * the decoded baseband header
+ *
+ * Once a new lock has established, the internal state
+ * frequency (internal->freq) is updated
+ */
+static int stb0899_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	return 0;
+}
+
+static int stb0899_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "Get params");
+	p->u.qpsk.symbol_rate = internal->srate;
+
+	return 0;
+}
+
+static enum dvbfe_algo stb0899_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static struct dvb_frontend_ops stb0899_ops = {
+
+	.info = {
+		.name 			= "STB0899 Multistandard",
+		.type 			= FE_QPSK,
+		.frequency_min		= 950000,
+		.frequency_max 		= 2150000,
+		.frequency_stepsize	= 0,
+		.frequency_tolerance	= 0,
+		.symbol_rate_min 	=  5000000,
+		.symbol_rate_max 	= 45000000,
+
+		.caps 			= FE_CAN_INVERSION_AUTO	|
+					  FE_CAN_FEC_AUTO	|
+					  FE_CAN_QPSK
+	},
+
+	.release			= stb0899_release,
+	.init				= stb0899_init,
+	.sleep				= stb0899_sleep,
+//	.wakeup				= stb0899_wakeup,
+
+	.i2c_gate_ctrl			= stb0899_i2c_gate_ctrl,
+
+	.get_frontend_algo		= stb0899_frontend_algo,
+	.search				= stb0899_search,
+	.track				= stb0899_track,
+	.get_frontend			= stb0899_get_frontend,
+
+
+	.read_status			= stb0899_read_status,
+	.read_snr			= stb0899_read_snr,
+	.read_signal_strength		= stb0899_read_signal_strength,
+	.read_ber			= stb0899_read_ber,
+
+	.set_voltage			= stb0899_set_voltage,
+	.set_tone			= stb0899_set_tone,
+
+	.diseqc_send_master_cmd		= stb0899_send_diseqc_msg,
+	.diseqc_recv_slave_reply	= stb0899_recv_slave_reply,
+	.diseqc_send_burst		= stb0899_send_diseqc_burst,
+};
+
+struct dvb_frontend *stb0899_attach(struct stb0899_config *config, struct i2c_adapter *i2c)
+{
+	struct stb0899_state *state = NULL;
+	enum stb0899_inversion inversion;
+
+	state = kzalloc(sizeof (struct stb0899_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	inversion				= config->inversion;
+	state->verbose				= &verbose;
+	state->config				= config;
+	state->i2c				= i2c;
+	state->frontend.ops			= stb0899_ops;
+	state->frontend.demodulator_priv	= state;
+	state->internal.inversion		= inversion;
+
+	stb0899_wakeup(&state->frontend);
+	if (stb0899_get_dev_id(state) == -ENODEV) {
+		printk("%s: Exiting .. !\n", __func__);
+		goto error;
+	}
+
+	printk("%s: Attaching STB0899 \n", __func__);
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(stb0899_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STB0899 Multi-Std frontend");
+MODULE_LICENSE("GPL");

+ 162 - 0
drivers/media/dvb/frontends/stb0899_drv.h

@@ -0,0 +1,162 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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 __STB0899_DRV_H
+#define __STB0899_DRV_H
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "dvb_frontend.h"
+
+#define STB0899_TSMODE_SERIAL		1
+#define STB0899_CLKPOL_FALLING		2
+#define STB0899_CLKNULL_PARITY		3
+#define STB0899_SYNC_FORCED		4
+#define STB0899_FECMODE_DSS		5
+
+struct stb0899_s1_reg {
+	u16	address;
+	u8	data;
+};
+
+struct stb0899_s2_reg {
+	u16	offset;
+	u32	base_address;
+	u32	data;
+};
+
+enum stb0899_inversion {
+	IQ_SWAP_OFF	= 0,
+	IQ_SWAP_ON,
+	IQ_SWAP_AUTO
+};
+
+#define STB0899_GPIO00				0xf140
+#define STB0899_GPIO01				0xf141
+#define STB0899_GPIO02				0xf142
+#define STB0899_GPIO03				0xf143
+#define STB0899_GPIO04				0xf144
+#define STB0899_GPIO05				0xf145
+#define STB0899_GPIO06				0xf146
+#define STB0899_GPIO07				0xf147
+#define STB0899_GPIO08				0xf148
+#define STB0899_GPIO09				0xf149
+#define STB0899_GPIO10				0xf14a
+#define STB0899_GPIO11				0xf14b
+#define STB0899_GPIO12				0xf14c
+#define STB0899_GPIO13				0xf14d
+#define STB0899_GPIO14				0xf14e
+#define STB0899_GPIO15				0xf14f
+#define STB0899_GPIO16				0xf150
+#define STB0899_GPIO17				0xf151
+#define STB0899_GPIO18				0xf152
+#define STB0899_GPIO19				0xf153
+#define STB0899_GPIO20				0xf154
+
+#define STB0899_GPIOPULLUP			0x01 /* Output device is connected to Vdd */
+#define STB0899_GPIOPULLDN			0x00 /* Output device is connected to Vss */
+
+#define STB0899_POSTPROC_GPIO_POWER		0x00
+#define STB0899_POSTPROC_GPIO_LOCK		0x01
+
+/*
+ * Post process output configuration control
+ * 1. POWER ON/OFF		(index 0)
+ * 2. FE_HAS_LOCK/LOCK_LOSS	(index 1)
+ *
+ * @gpio 	= one of the above listed GPIO's
+ * @level	= output state: pulled up or low
+ */
+struct stb0899_postproc {
+	u16	gpio;
+	u8	level;
+};
+
+struct stb0899_config {
+	const struct stb0899_s1_reg	*init_dev;
+	const struct stb0899_s2_reg	*init_s2_demod;
+	const struct stb0899_s1_reg	*init_s1_demod;
+	const struct stb0899_s2_reg	*init_s2_fec;
+	const struct stb0899_s1_reg	*init_tst;
+
+	const struct stb0899_postproc	*postproc;
+
+	enum stb0899_inversion		inversion;
+
+	u32	xtal_freq;
+
+	u8	demod_address;
+	u8	ts_output_mode;
+	u8	block_sync_mode;
+	u8	ts_pfbit_toggle;
+
+	u8	clock_polarity;
+	u8	data_clk_parity;
+	u8	fec_mode;
+	u8	data_output_ctl;
+	u8	data_fifo_mode;
+	u8	out_rate_comp;
+	u8	i2c_repeater;
+//	int	inversion;
+	int	lo_clk;
+	int	hi_clk;
+
+	u32	esno_ave;
+	u32	esno_quant;
+	u32	avframes_coarse;
+	u32	avframes_fine;
+	u32	miss_threshold;
+	u32	uwp_threshold_acq;
+	u32	uwp_threshold_track;
+	u32	uwp_threshold_sof;
+	u32	sof_search_timeout;
+
+	u32	btr_nco_bits;
+	u32	btr_gain_shift_offset;
+	u32	crl_nco_bits;
+	u32	ldpc_max_iter;
+
+	int (*tuner_set_frequency)(struct dvb_frontend *fe, u32 frequency);
+	int (*tuner_get_frequency)(struct dvb_frontend *fe, u32 *frequency);
+	int (*tuner_set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+	int (*tuner_get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+	int (*tuner_set_rfsiggain)(struct dvb_frontend *fe, u32 rf_gain);
+};
+
+#if defined(CONFIG_DVB_STB0899) || (defined(CONFIG_DVB_STB0899_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *stb0899_attach(struct stb0899_config *config,
+					   struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *stb0899_attach(struct stb0899_config *config,
+						  struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif //CONFIG_DVB_STB0899
+
+
+#endif

+ 267 - 0
drivers/media/dvb/frontends/stb0899_priv.h

@@ -0,0 +1,267 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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 __STB0899_PRIV_H
+#define __STB0899_PRIV_H
+
+#include "dvb_frontend.h"
+#include "stb0899_drv.h"
+
+#define FE_ERROR				0
+#define FE_NOTICE				1
+#define FE_INFO					2
+#define FE_DEBUG				3
+#define FE_DEBUGREG				4
+
+#define dprintk(x, y, z, format, arg...) do {						\
+	if (z) {									\
+		if	((*x > FE_ERROR) && (*x > y))					\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((*x > FE_NOTICE) && (*x > y))					\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((*x > FE_INFO) && (*x > y))					\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((*x > FE_DEBUG) && (*x > y))					\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (*x > y)								\
+			printk(format, ##arg);						\
+	}										\
+} while(0)
+
+#define INRANGE(val, x, y)			(((x <= val) && (val <= y)) ||		\
+						 ((y <= val) && (val <= x)) ? 1 : 0)
+
+#define BYTE0					0
+#define BYTE1					8
+#define BYTE2					16
+#define BYTE3					24
+
+#define GETBYTE(x, y)				(((x) >> (y)) & 0xff)
+#define MAKEWORD32(a, b, c, d)			(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
+#define MAKEWORD16(a, b)			(((a) << 8) | (b))
+
+#define MIN(x, y)				((x) <= (y) ? (x) : (y))
+#define MAX(x, y)				((x) >= (y) ? (x) : (y))
+#define ABS(x)					((x) >= 0 ? (x) : -(x))
+
+#define LSB(x)					((x & 0xff))
+#define MSB(y)					((y >> 8) & 0xff)
+
+
+#define STB0899_GETFIELD(bitf, val)		((val >> STB0899_OFFST_##bitf) & ((1 << STB0899_WIDTH_##bitf) - 1))
+
+
+#define STB0899_SETFIELD(mask, val, width, offset)      (mask & (~(((1 << width) - 1) <<	\
+							 offset))) | ((val &			\
+							 ((1 << width) - 1)) << offset)
+
+#define STB0899_SETFIELD_VAL(bitf, mask, val)	(mask = (mask & (~(((1 << STB0899_WIDTH_##bitf) - 1) <<\
+							 STB0899_OFFST_##bitf))) | \
+							 (val << STB0899_OFFST_##bitf))
+
+
+enum stb0899_status {
+	NOAGC1	= 0,
+	AGC1OK,
+	NOTIMING,
+	ANALOGCARRIER,
+	TIMINGOK,
+	NOAGC2,
+	AGC2OK,
+	NOCARRIER,
+	CARRIEROK,
+	NODATA,
+	FALSELOCK,
+	DATAOK,
+	OUTOFRANGE,
+	RANGEOK,
+	DVBS2_DEMOD_LOCK,
+	DVBS2_DEMOD_NOLOCK,
+	DVBS2_FEC_LOCK,
+	DVBS2_FEC_NOLOCK
+};
+
+enum stb0899_modcod {
+	STB0899_DUMMY_PLF,
+	STB0899_QPSK_14,
+	STB0899_QPSK_13,
+	STB0899_QPSK_25,
+	STB0899_QPSK_12,
+	STB0899_QPSK_35,
+	STB0899_QPSK_23,
+	STB0899_QPSK_34,
+	STB0899_QPSK_45,
+	STB0899_QPSK_56,
+	STB0899_QPSK_89,
+	STB0899_QPSK_910,
+	STB0899_8PSK_35,
+	STB0899_8PSK_23,
+	STB0899_8PSK_34,
+	STB0899_8PSK_56,
+	STB0899_8PSK_89,
+	STB0899_8PSK_910,
+	STB0899_16APSK_23,
+	STB0899_16APSK_34,
+	STB0899_16APSK_45,
+	STB0899_16APSK_56,
+	STB0899_16APSK_89,
+	STB0899_16APSK_910,
+	STB0899_32APSK_34,
+	STB0899_32APSK_45,
+	STB0899_32APSK_56,
+	STB0899_32APSK_89,
+	STB0899_32APSK_910
+};
+
+enum stb0899_frame {
+	STB0899_LONG_FRAME,
+	STB0899_SHORT_FRAME
+};
+
+enum stb0899_alpha {
+	RRC_20,
+	RRC_25,
+	RRC_35
+};
+
+struct stb0899_tab {
+	s32 real;
+	s32 read;
+};
+
+enum stb0899_fec {
+	STB0899_FEC_1_2			= 13,
+	STB0899_FEC_2_3			= 18,
+	STB0899_FEC_3_4			= 21,
+	STB0899_FEC_5_6			= 24,
+	STB0899_FEC_6_7			= 25,
+	STB0899_FEC_7_8			= 26
+};
+
+struct stb0899_params {
+	u32	freq;					/* Frequency	*/
+	u32	srate;					/* Symbol rate	*/
+	enum fe_code_rate fecrate;
+};
+
+struct stb0899_internal {
+	u32			master_clk;
+	u32			freq;			/* Demod internal Frequency		*/
+	u32			srate;			/* Demod internal Symbol rate		*/
+	enum stb0899_fec	fecrate;		/* Demod internal FEC rate		*/
+	u32			srch_range;		/* Demod internal Search Range		*/
+	u32			sub_range;		/* Demod current sub range (Hz)		*/
+	u32			tuner_step;		/* Tuner step (Hz)			*/
+	u32			tuner_offst;		/* Relative offset to carrier (Hz)	*/
+	u32			tuner_bw;		/* Current bandwidth of the tuner (Hz)	*/
+
+	s32			mclk;			/* Masterclock Divider factor (binary)	*/
+	s32			rolloff;		/* Current RollOff of the filter (x100)	*/
+
+	s16			derot_freq;		/* Current derotator frequency (Hz)	*/
+	s16			derot_percent;
+
+	s16			direction;		/* Current derotator search direction	*/
+	s16			derot_step;		/* Derotator step (binary value)	*/
+	s16			t_derot;		/* Derotator time constant (ms)		*/
+	s16			t_data;			/* Data recovery time constant (ms)	*/
+	s16			sub_dir;		/* Direction of the next sub range	*/
+
+	s16			t_agc1;			/* Agc1 time constant (ms)		*/
+	s16			t_agc2;			/* Agc2 time constant (ms)		*/
+
+	u32			lock;			/* Demod internal lock state		*/
+	enum stb0899_status	status;			/* Demod internal status		*/
+
+	/* DVB-S2 */
+	s32			agc_gain;		/* RF AGC Gain				*/
+	s32			center_freq;		/* Nominal carrier frequency		*/
+	s32			av_frame_coarse;	/* Coarse carrier freq search frames	*/
+	s32			av_frame_fine;		/* Fine carrier freq search frames	*/
+
+	s16			step_size;		/* Carrier frequency search step size	*/
+
+	enum stb0899_alpha	rrc_alpha;
+	enum stb0899_inversion	inversion;
+	enum stb0899_modcod	modcod;
+	u8			pilots;			/* Pilots found				*/
+
+	enum stb0899_frame	frame_length;
+	u8			v_status;		/* VSTATUS				*/
+	u8			err_ctrl;		/* ERRCTRLn				*/
+};
+
+struct stb0899_state {
+	struct i2c_adapter		*i2c;
+	struct stb0899_config		*config;
+	struct dvb_frontend		frontend;
+
+	u32				*verbose;	/* Cached module verbosity level	*/
+
+	struct stb0899_internal		internal;	/* Device internal parameters		*/
+
+	/*	cached params from API	*/
+	enum fe_delivery_system		delsys;
+	struct stb0899_params		params;
+
+	u32				rx_freq;	/* DiSEqC 2.0 receiver freq		*/
+	struct mutex			search_lock;
+};
+/* stb0899.c		*/
+extern int stb0899_read_reg(struct stb0899_state *state,
+			    unsigned int reg);
+
+extern u32 _stb0899_read_s2reg(struct stb0899_state *state,
+			       u32 stb0899_i2cdev,
+			       u32 stb0899_base_addr,
+			       u16 stb0899_reg_offset);
+
+extern int stb0899_read_regs(struct stb0899_state *state,
+			     unsigned int reg, u8 *buf,
+			     u32 count);
+
+extern int stb0899_write_regs(struct stb0899_state *state,
+			      unsigned int reg, u8 *data,
+			      u32 count);
+
+extern int stb0899_write_reg(struct stb0899_state *state,
+			     unsigned int reg,
+			     u8 data);
+
+extern int stb0899_write_s2reg(struct stb0899_state *state,
+			       u32 stb0899_i2cdev,
+			       u32 stb0899_base_addr,
+			       u16 stb0899_reg_offset,
+			       u32 stb0899_data);
+
+extern int stb0899_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
+
+
+#define STB0899_READ_S2REG(DEVICE, REG) 	(_stb0899_read_s2reg(state, DEVICE, STB0899_BASE_##REG, STB0899_OFF0_##REG))
+//#define STB0899_WRITE_S2REG(DEVICE, REG, DATA)	(_stb0899_write_s2reg(state, DEVICE, STB0899_BASE_##REG, STB0899_OFF0_##REG, DATA))
+
+/* stb0899_algo.c	*/
+extern enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state);
+extern enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state);
+extern long stb0899_carr_width(struct stb0899_state *state);
+
+#endif //__STB0899_PRIV_H

+ 2027 - 0
drivers/media/dvb/frontends/stb0899_reg.h

@@ -0,0 +1,2027 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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 __STB0899_REG_H
+#define __STB0899_REG_H
+
+/*	S1	*/
+#define STB0899_DEV_ID				0xf000
+#define STB0899_CHIP_ID				(0x0f << 4)
+#define STB0899_OFFST_CHIP_ID			4
+#define STB0899_WIDTH_CHIP_ID			4
+#define STB0899_CHIP_REL			(0x0f << 0)
+#define STB0899_OFFST_CHIP_REL			0
+#define STB0899_WIDTH_CHIP_REL			4
+
+#define STB0899_DEMOD				0xf40e
+#define STB0899_MODECOEFF			(0x01 << 0)
+#define STB0899_OFFST_MODECOEFF			0
+#define STB0899_WIDTH_MODECOEFF			1
+
+#define STB0899_RCOMPC				0xf410
+#define STB0899_AGC1CN				0xf412
+#define STB0899_AGC1REF				0xf413
+#define STB0899_RTC				0xf417
+#define STB0899_TMGCFG				0xf418
+#define STB0899_AGC2REF				0xf419
+#define STB0899_TLSR				0xf41a
+
+#define STB0899_CFD				0xf41b
+#define STB0899_CFD_ON				(0x01 << 7)
+#define STB0899_OFFST_CFD_ON			7
+#define STB0899_WIDTH_CFD_ON			1
+
+#define STB0899_ACLC				0xf41c
+
+#define STB0899_BCLC				0xf41d
+#define STB0899_OFFST_ALGO			6
+#define STB0899_WIDTH_ALGO_QPSK2		2
+#define STB0899_ALGO_QPSK2			(2 << 6)
+#define STB0899_ALGO_QPSK1			(1 << 6)
+#define STB0899_ALGO_BPSK			(0 << 6)
+#define STB0899_OFFST_BETA			0
+#define STB0899_WIDTH_BETA			6
+
+#define STB0899_EQON				0xf41e
+#define STB0899_LDT				0xf41f
+#define STB0899_LDT2				0xf420
+#define STB0899_EQUALREF			0xf425
+#define STB0899_TMGRAMP				0xf426
+#define STB0899_TMGTHD				0xf427
+#define STB0899_IDCCOMP				0xf428
+#define STB0899_QDCCOMP				0xf429
+#define STB0899_POWERI				0xf42a
+#define STB0899_POWERQ				0xf42b
+#define STB0899_RCOMP				0xf42c
+
+#define STB0899_AGCIQIN				0xf42e
+#define STB0899_AGCIQVALUE			(0xff << 0)
+#define STB0899_OFFST_AGCIQVALUE		0
+#define STB0899_WIDTH_AGCIQVALUE		8
+
+#define STB0899_AGC2I1				0xf436
+#define STB0899_AGC2I2				0xf437
+
+#define STB0899_TLIR				0xf438
+#define STB0899_TLIR_TMG_LOCK_IND		(0xff << 0)
+#define STB0899_OFFST_TLIR_TMG_LOCK_IND		0
+#define STB0899_WIDTH_TLIR_TMG_LOCK_IND		8
+
+#define STB0899_RTF				0xf439
+#define STB0899_RTF_TIMING_LOOP_FREQ		(0xff << 0)
+#define STB0899_OFFST_RTF_TIMING_LOOP_FREQ	0
+#define STB0899_WIDTH_RTF_TIMING_LOOP_FREQ	8
+
+#define STB0899_DSTATUS				0xf43a
+#define STB0899_CARRIER_FOUND			(0x01 << 7)
+#define STB0899_OFFST_CARRIER_FOUND		7
+#define STB0899_WIDTH_CARRIER_FOUND		1
+#define STB0899_TMG_LOCK			(0x01 << 6)
+#define STB0899_OFFST_TMG_LOCK			6
+#define STB0899_WIDTH_TMG_LOCK			1
+#define STB0899_DEMOD_LOCK			(0x01 << 5)
+#define STB0899_OFFST_DEMOD_LOCK		5
+#define STB0899_WIDTH_DEMOD_LOCK		1
+#define STB0899_TMG_AUTO			(0x01 << 4)
+#define STB0899_OFFST_TMG_AUTO			4
+#define STB0899_WIDTH_TMG_AUTO			1
+#define STB0899_END_MAIN			(0x01 << 3)
+#define STB0899_OFFST_END_MAIN			3
+#define STB0899_WIDTH_END_MAIN			1
+
+#define STB0899_LDI				0xf43b
+#define STB0899_OFFST_LDI			0
+#define STB0899_WIDTH_LDI			8
+
+#define STB0899_CFRM				0xf43e
+#define STB0899_OFFST_CFRM			0
+#define STB0899_WIDTH_CFRM			8
+
+#define STB0899_CFRL				0xf43f
+#define STB0899_OFFST_CFRL			0
+#define STB0899_WIDTH_CFRL			8
+
+#define STB0899_NIRM				0xf440
+#define STB0899_OFFST_NIRM			0
+#define STB0899_WIDTH_NIRM			8
+
+#define STB0899_NIRL				0xf441
+#define STB0899_OFFST_NIRL			0
+#define STB0899_WIDTH_NIRL			8
+
+#define STB0899_ISYMB				0xf444
+#define STB0899_QSYMB				0xf445
+
+#define STB0899_SFRH				0xf446
+#define STB0899_OFFST_SFRH			0
+#define STB0899_WIDTH_SFRH			8
+
+#define STB0899_SFRM				0xf447
+#define STB0899_OFFST_SFRM			0
+#define STB0899_WIDTH_SFRM			8
+
+#define STB0899_SFRL				0xf448
+#define STB0899_OFFST_SFRL			4
+#define STB0899_WIDTH_SFRL			4
+
+#define STB0899_SFRUPH				0xf44c
+#define STB0899_SFRUPM				0xf44d
+#define STB0899_SFRUPL				0xf44e
+
+#define STB0899_EQUAI1				0xf4e0
+#define STB0899_EQUAQ1				0xf4e1
+#define STB0899_EQUAI2				0xf4e2
+#define STB0899_EQUAQ2				0xf4e3
+#define STB0899_EQUAI3				0xf4e4
+#define STB0899_EQUAQ3				0xf4e5
+#define STB0899_EQUAI4				0xf4e6
+#define STB0899_EQUAQ4				0xf4e7
+#define STB0899_EQUAI5				0xf4e8
+#define STB0899_EQUAQ5				0xf4e9
+
+#define STB0899_DSTATUS2			0xf50c
+#define STB0899_DS2_TMG_AUTOSRCH		(0x01 << 7)
+#define STB8999_OFFST_DS2_TMG_AUTOSRCH		7
+#define STB0899_WIDTH_DS2_TMG_AUTOSRCH		1
+#define STB0899_DS2_END_MAINLOOP		(0x01 << 6)
+#define STB0899_OFFST_DS2_END_MAINLOOP		6
+#define STB0899_WIDTH_DS2_END_MAINLOOP		1
+#define STB0899_DS2_CFSYNC			(0x01 << 5)
+#define STB0899_OFFST_DS2_CFSYNC		5
+#define STB0899_WIDTH_DS2_CFSYNC		1
+#define STB0899_DS2_TMGLOCK			(0x01 << 4)
+#define STB0899_OFFST_DS2_TMGLOCK		4
+#define STB0899_WIDTH_DS2_TMGLOCK		1
+#define STB0899_DS2_DEMODWAIT			(0x01 << 3)
+#define STB0899_OFFST_DS2_DEMODWAIT		3
+#define STB0899_WIDTH_DS2_DEMODWAIT		1
+#define STB0899_DS2_FECON			(0x01 << 1)
+#define STB0899_OFFST_DS2_FECON			1
+#define STB0899_WIDTH_DS2_FECON			1
+
+/*	S1 FEC	*/
+#define STB0899_VSTATUS				0xf50d
+#define STB0899_VSTATUS_VITERBI_ON		(0x01 << 7)
+#define STB0899_OFFST_VSTATUS_VITERBI_ON	7
+#define STB0899_WIDTH_VSTATUS_VITERBI_ON	1
+#define STB0899_VSTATUS_END_LOOPVIT		(0x01 << 6)
+#define STB0899_OFFST_VSTATUS_END_LOOPVIT	6
+#define STB0899_WIDTH_VSTATUS_END_LOOPVIT	1
+#define STB0899_VSTATUS_PRFVIT			(0x01 << 4)
+#define STB0899_OFFST_VSTATUS_PRFVIT		4
+#define STB0899_WIDTH_VSTATUS_PRFVIT		1
+#define STB0899_VSTATUS_LOCKEDVIT		(0x01 << 3)
+#define STB0899_OFFST_VSTATUS_LOCKEDVIT		3
+#define STB0899_WIDTH_VSTATUS_LOCKEDVIT		1
+
+#define STB0899_VERROR				0xf50f
+
+#define STB0899_IQSWAP				0xf523
+#define STB0899_SYM				(0x01 << 3)
+#define STB0899_OFFST_SYM			3
+#define STB0899_WIDTH_SYM			1
+
+#define STB0899_FECAUTO1			0xf530
+#define STB0899_DSSSRCH				(0x01 << 3)
+#define STB0899_OFFST_DSSSRCH			3
+#define STB0899_WIDTH_DSSSRCH			1
+#define STB0899_SYMSRCH				(0x01 << 2)
+#define STB0899_OFFST_SYMSRCH			2
+#define STB0899_WIDTH_SYMSRCH			1
+#define STB0899_QPSKSRCH			(0x01 << 1)
+#define STB0899_OFFST_QPSKSRCH			1
+#define STB0899_WIDTH_QPSKSRCH			1
+#define STB0899_BPSKSRCH			(0x01 << 0)
+#define STB0899_OFFST_BPSKSRCH			0
+#define STB0899_WIDTH_BPSKSRCH			1
+
+#define STB0899_FECM				0xf533
+#define STB0899_FECM_NOT_DVB			(0x01 << 7)
+#define STB0899_OFFST_FECM_NOT_DVB		7
+#define STB0899_WIDTH_FECM_NOT_DVB		1
+#define STB0899_FECM_RSVD1			(0x07 << 4)
+#define STB0899_OFFST_FECM_RSVD1		4
+#define STB0899_WIDTH_FECM_RSVD1		3
+#define STB0899_FECM_VITERBI_ON			(0x01 << 3)
+#define STB0899_OFFST_FECM_VITERBI_ON		3
+#define STB0899_WIDTH_FECM_VITERBI_ON		1
+#define STB0899_FECM_RSVD0			(0x01 << 2)
+#define STB0899_OFFST_FECM_RSVD0		2
+#define STB0899_WIDTH_FECM_RSVD0		1
+#define STB0899_FECM_SYNCDIS			(0x01 << 1)
+#define STB0899_OFFST_FECM_SYNCDIS		1
+#define STB0899_WIDTH_FECM_SYNCDIS		1
+#define STB0899_FECM_SYMI			(0x01 << 0)
+#define STB0899_OFFST_FECM_SYMI			0
+#define STB0899_WIDTH_FECM_SYMI			1
+
+#define STB0899_VTH12				0xf534
+#define STB0899_VTH23				0xf535
+#define STB0899_VTH34				0xf536
+#define STB0899_VTH56				0xf537
+#define STB0899_VTH67				0xf538
+#define STB0899_VTH78				0xf539
+
+#define STB0899_PRVIT				0xf53c
+#define STB0899_PR_7_8				(0x01 << 5)
+#define STB0899_OFFST_PR_7_8			5
+#define STB0899_WIDTH_PR_7_8			1
+#define STB0899_PR_6_7				(0x01 << 4)
+#define STB0899_OFFST_PR_6_7			4
+#define STB0899_WIDTH_PR_6_7			1
+#define STB0899_PR_5_6				(0x01 << 3)
+#define STB0899_OFFST_PR_5_6			3
+#define STB0899_WIDTH_PR_5_6			1
+#define STB0899_PR_3_4				(0x01 << 2)
+#define STB0899_OFFST_PR_3_4			2
+#define STB0899_WIDTH_PR_3_4			1
+#define STB0899_PR_2_3				(0x01 << 1)
+#define STB0899_OFFST_PR_2_3			1
+#define STB0899_WIDTH_PR_2_3			1
+#define STB0899_PR_1_2				(0x01 << 0)
+#define STB0899_OFFST_PR_1_2			0
+#define STB0899_WIDTH_PR_1_2			1
+
+#define STB0899_VITSYNC				0xf53d
+#define STB0899_AM				(0x01 << 7)
+#define STB0899_OFFST_AM			7
+#define STB0899_WIDTH_AM			1
+#define STB0899_FREEZE				(0x01 << 6)
+#define STB0899_OFFST_FREEZE			6
+#define STB0899_WIDTH_FREEZE			1
+#define STB0899_SN_65536			(0x03 << 4)
+#define STB0899_OFFST_SN_65536			4
+#define STB0899_WIDTH_SN_65536			2
+#define STB0899_SN_16384			(0x01 << 5)
+#define STB0899_OFFST_SN_16384			5
+#define STB0899_WIDTH_SN_16384			1
+#define STB0899_SN_4096				(0x01 << 4)
+#define STB0899_OFFST_SN_4096			4
+#define STB0899_WIDTH_SN_4096			1
+#define STB0899_SN_1024				(0x00 << 4)
+#define STB0899_OFFST_SN_1024			4
+#define STB0899_WIDTH_SN_1024			0
+#define STB0899_TO_128				(0x03 << 2)
+#define STB0899_OFFST_TO_128			2
+#define STB0899_WIDTH_TO_128			2
+#define STB0899_TO_64				(0x01 << 3)
+#define STB0899_OFFST_TO_64			3
+#define STB0899_WIDTH_TO_64			1
+#define STB0899_TO_32				(0x01 << 2)
+#define STB0899_OFFST_TO_32			2
+#define STB0899_WIDTH_TO_32			1
+#define STB0899_TO_16				(0x00 << 2)
+#define STB0899_OFFST_TO_16			2
+#define STB0899_WIDTH_TO_16			0
+#define STB0899_HYST_128			(0x03 << 1)
+#define STB0899_OFFST_HYST_128			1
+#define STB0899_WIDTH_HYST_128			2
+#define STB0899_HYST_64				(0x01 << 1)
+#define STB0899_OFFST_HYST_64			1
+#define STB0899_WIDTH_HYST_64			1
+#define STB0899_HYST_32				(0x01 << 0)
+#define STB0899_OFFST_HYST_32			0
+#define STB0899_WIDTH_HYST_32			1
+#define STB0899_HYST_16				(0x00 << 0)
+#define STB0899_OFFST_HYST_16			0
+#define STB0899_WIDTH_HYST_16			0
+
+#define STB0899_RSULC				0xf548
+#define STB0899_ULDIL_ON			(0x01 << 7)
+#define STB0899_OFFST_ULDIL_ON			7
+#define STB0899_WIDTH_ULDIL_ON			1
+#define STB0899_ULAUTO_ON			(0x01 << 6)
+#define STB0899_OFFST_ULAUTO_ON			6
+#define STB0899_WIDTH_ULAUTO_ON			1
+#define STB0899_ULRS_ON				(0x01 << 5)
+#define STB0899_OFFST_ULRS_ON			5
+#define STB0899_WIDTH_ULRS_ON			1
+#define STB0899_ULDESCRAM_ON			(0x01 << 4)
+#define STB0899_OFFST_ULDESCRAM_ON		4
+#define STB0899_WIDTH_ULDESCRAM_ON		1
+#define STB0899_UL_DISABLE			(0x01 << 2)
+#define STB0899_OFFST_UL_DISABLE		2
+#define STB0899_WIDTH_UL_DISABLE		1
+#define STB0899_NOFTHRESHOLD			(0x01 << 0)
+#define STB0899_OFFST_NOFTHRESHOLD		0
+#define STB0899_WIDTH_NOFTHRESHOLD		1
+
+#define STB0899_RSLLC				0xf54a
+#define STB0899_DEMAPVIT			0xf583
+#define STB0899_DEMAPVIT_RSVD			(0x01 << 7)
+#define STB0899_OFFST_DEMAPVIT_RSVD		7
+#define STB0899_WIDTH_DEMAPVIT_RSVD		1
+#define STB0899_DEMAPVIT_KDIVIDER		(0x7f << 0)
+#define STB0899_OFFST_DEMAPVIT_KDIVIDER		0
+#define STB0899_WIDTH_DEMAPVIT_KDIVIDER		7
+
+#define STB0899_PLPARM				0xf58c
+#define STB0899_VITMAPPING			(0x07 << 5)
+#define STB0899_OFFST_VITMAPPING		5
+#define STB0899_WIDTH_VITMAPPING		3
+#define STB0899_VITMAPPING_BPSK			(0x01 << 5)
+#define STB0899_OFFST_VITMAPPING_BPSK		5
+#define STB0899_WIDTH_VITMAPPING_BPSK		1
+#define STB0899_VITMAPPING_QPSK			(0x00 << 5)
+#define STB0899_OFFST_VITMAPPING_QPSK		5
+#define STB0899_WIDTH_VITMAPPING_QPSK		0
+#define STB0899_VITCURPUN			(0x1f << 0)
+#define STB0899_OFFST_VITCURPUN			0
+#define STB0899_WIDTH_VITCURPUN			5
+#define STB0899_VITCURPUN_1_2			(0x0d << 0)
+#define STB0899_VITCURPUN_2_3			(0x12 << 0)
+#define STB0899_VITCURPUN_3_4			(0x15 << 0)
+#define STB0899_VITCURPUN_5_6			(0x18 << 0)
+#define STB0899_VITCURPUN_6_7			(0x19 << 0)
+#define STB0899_VITCURPUN_7_8			(0x1a << 0)
+
+/*	S2 DEMOD	*/
+#define STB0899_OFF0_DMD_STATUS			0xf300
+#define STB0899_BASE_DMD_STATUS			0x00000000
+#define STB0899_IF_AGC_LOCK			(0x01 << 8)
+#define STB0899_OFFST_IF_AGC_LOCK		0
+#define STB0899_WIDTH_IF_AGC_LOCK		1
+
+#define STB0899_OFF0_CRL_FREQ			0xf304
+#define STB0899_BASE_CRL_FREQ			0x00000000
+#define STB0899_CARR_FREQ			(0x3fffffff << 0)
+#define STB0899_OFFST_CARR_FREQ			0
+#define STB0899_WIDTH_CARR_FREQ			30
+
+#define STB0899_OFF0_BTR_FREQ			0xf308
+#define STB0899_BASE_BTR_FREQ			0x00000000
+#define STB0899_BTR_FREQ			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_FREQ			0
+#define STB0899_WIDTH_BTR_FREQ			28
+
+#define STB0899_OFF0_IF_AGC_GAIN		0xf30c
+#define STB0899_BASE_IF_AGC_GAIN		0x00000000
+#define STB0899_IF_AGC_GAIN			(0x3fff < 0)
+#define STB0899_OFFST_IF_AGC_GAIN		0
+#define STB0899_WIDTH_IF_AGC_GAIN		14
+
+#define STB0899_OFF0_BB_AGC_GAIN		0xf310
+#define STB0899_BASE_BB_AGC_GAIN		0x00000000
+#define STB0899_BB_AGC_GAIN			(0x3fff < 0)
+#define STB0899_OFFST_BB_AGC_GAIN		0
+#define STB0899_WIDTH_BB_AGC_GAIN		14
+
+#define STB0899_OFF0_DC_OFFSET			0xf314
+#define STB0899_BASE_DC_OFFSET			0x00000000
+#define STB0899_I				(0xff < 8)
+#define STB0899_OFFST_I				8
+#define STB0899_WIDTH_I				8
+#define STB0899_Q				(0xff < 0)
+#define STB0899_OFFST_Q				8
+#define STB0899_WIDTH_Q				8
+
+#define STB0899_OFF0_DMD_CNTRL			0xf31c
+#define STB0899_BASE_DMD_CNTRL			0x00000000
+#define STB0899_ADC0_PINS1IN			(0x01 << 6)
+#define STB0899_OFFST_ADC0_PINS1IN              6
+#define STB0899_WIDTH_ADC0_PINS1IN              1
+#define STB0899_IN2COMP1_OFFBIN0		(0x01 << 3)
+#define STB0899_OFFST_IN2COMP1_OFFBIN0          3
+#define STB0899_WIDTH_IN2COMP1_OFFBIN0          1
+#define STB0899_DC_COMP				(0x01 << 2)
+#define STB0899_OFFST_DC_COMP			2
+#define STB0899_WIDTH_DC_COMP			1
+#define STB0899_MODMODE				(0x03 << 0)
+#define STB0899_OFFST_MODMODE			0
+#define STB0899_WIDTH_MODMODE			2
+
+#define STB0899_OFF0_IF_AGC_CNTRL		0xf320
+#define STB0899_BASE_IF_AGC_CNTRL		0x00000000
+#define STB0899_IF_GAIN_INIT			(0x3fff << 13)
+#define STB0899_OFFST_IF_GAIN_INIT		13
+#define STB0899_WIDTH_IF_GAIN_INIT		14
+#define STB0899_IF_GAIN_SENSE			(0x01 << 12)
+#define STB0899_OFFST_IF_GAIN_SENSE		12
+#define STB0899_WIDTH_IF_GAIN_SENSE		1
+#define STB0899_IF_LOOP_GAIN			(0x0f << 8)
+#define STB0899_OFFST_IF_LOOP_GAIN		8
+#define STB0899_WIDTH_IF_LOOP_GAIN		4
+#define STB0899_IF_LD_GAIN_INIT			(0x01 << 7)
+#define STB0899_OFFST_IF_LD_GAIN_INIT		7
+#define STB0899_WIDTH_IF_LD_GAIN_INIT		1
+#define STB0899_IF_AGC_REF			(0x7f << 0)
+#define STB0899_OFFST_IF_AGC_REF		0
+#define STB0899_WIDTH_IF_AGC_REF		7
+
+#define STB0899_OFF0_BB_AGC_CNTRL		0xf324
+#define STB0899_BASE_BB_AGC_CNTRL		0x00000000
+#define STB0899_BB_GAIN_INIT			(0x3fff << 12)
+#define STB0899_OFFST_BB_GAIN_INIT		12
+#define STB0899_WIDTH_BB_GAIN_INIT		14
+#define STB0899_BB_LOOP_GAIN			(0x0f << 8)
+#define STB0899_OFFST_BB_LOOP_GAIN		8
+#define STB0899_WIDTH_BB_LOOP_GAIN		4
+#define STB0899_BB_LD_GAIN_INIT			(0x01 << 7)
+#define STB0899_OFFST_BB_LD_GAIN_INIT		7
+#define STB0899_WIDTH_BB_LD_GAIN_INIT		1
+#define STB0899_BB_AGC_REF			(0x7f << 0)
+#define STB0899_OFFST_BB_AGC_REF		0
+#define STB0899_WIDTH_BB_AGC_REF		7
+
+#define STB0899_OFF0_CRL_CNTRL			0xf328
+#define STB0899_BASE_CRL_CNTRL			0x00000000
+#define STB0899_CRL_LOCK_CLEAR			(0x01 << 5)
+#define STB0899_OFFST_CRL_LOCK_CLEAR		5
+#define STB0899_WIDTH_CRL_LOCK_CLEAR		1
+#define STB0899_CRL_SWPR_CLEAR			(0x01 << 4)
+#define STB0899_OFFST_CRL_SWPR_CLEAR		4
+#define STB0899_WIDTH_CRL_SWPR_CLEAR		1
+#define STB0899_CRL_SWP_ENA			(0x01 << 3)
+#define STB0899_OFFST_CRL_SWP_ENA		3
+#define STB0899_WIDTH_CRL_SWP_ENA		1
+#define STB0899_CRL_DET_SEL			(0x01 << 2)
+#define STB0899_OFFST_CRL_DET_SEL		2
+#define STB0899_WIDTH_CRL_DET_SEL		1
+#define STB0899_CRL_SENSE			(0x01 << 1)
+#define STB0899_OFFST_CRL_SENSE			1
+#define STB0899_WIDTH_CRL_SENSE			1
+#define STB0899_CRL_PHSERR_CLEAR		(0x01 << 0)
+#define STB0899_OFFST_CRL_PHSERR_CLEAR		0
+#define STB0899_WIDTH_CRL_PHSERR_CLEAR		1
+
+#define STB0899_OFF0_CRL_PHS_INIT		0xf32c
+#define STB0899_BASE_CRL_PHS_INIT		0x00000000
+#define STB0899_CRL_PHS_INIT_31			(0x1 << 30)
+#define STB0899_OFFST_CRL_PHS_INIT_31		30
+#define STB0899_WIDTH_CRL_PHS_INIT_31		1
+#define STB0899_CRL_LD_INIT_PHASE		(0x1 << 24)
+#define STB0899_OFFST_CRL_LD_INIT_PHASE		24
+#define STB0899_WIDTH_CRL_LD_INIT_PHASE		1
+#define STB0899_CRL_INIT_PHASE			(0xffffff << 0)
+#define STB0899_OFFST_CRL_INIT_PHASE		0
+#define STB0899_WIDTH_CRL_INIT_PHASE		24
+
+#define STB0899_OFF0_CRL_FREQ_INIT		0xf330
+#define STB0899_BASE_CRL_FREQ_INIT		0x00000000
+#define STB0899_CRL_FREQ_INIT_31		(0x1 << 30)
+#define STB0899_OFFST_CRL_FREQ_INIT_31		30
+#define STB0899_WIDTH_CRL_FREQ_INIT_31		1
+#define STB0899_CRL_LD_FREQ_INIT		(0x1 << 24)
+#define STB0899_OFFST_CRL_LD_FREQ_INIT		24
+#define STB0899_WIDTH_CRL_LD_FREQ_INIT		1
+#define STB0899_CRL_FREQ_INIT			(0xffffff << 0)
+#define STB0899_OFFST_CRL_FREQ_INIT		0
+#define STB0899_WIDTH_CRL_FREQ_INIT		24
+
+#define STB0899_OFF0_CRL_LOOP_GAIN		0xf334
+#define STB0899_BASE_CRL_LOOP_GAIN		0x00000000
+#define STB0899_KCRL2_RSHFT			(0xf << 16)
+#define STB0899_OFFST_KCRL2_RSHFT		16
+#define STB0899_WIDTH_KCRL2_RSHFT		4
+#define STB0899_KCRL1				(0xf << 12)
+#define STB0899_OFFST_KCRL1			12
+#define STB0899_WIDTH_KCRL1			4
+#define STB0899_KCRL1_RSHFT			(0xf << 8)
+#define STB0899_OFFST_KCRL1_RSHFT		8
+#define STB0899_WIDTH_KCRL1_RSHFT		4
+#define STB0899_KCRL0				(0xf << 4)
+#define STB0899_OFFST_KCRL0			4
+#define STB0899_WIDTH_KCRL0			4
+#define STB0899_KCRL0_RSHFT			(0xf << 0)
+#define STB0899_OFFST_KCRL0_RSHFT		0
+#define STB0899_WIDTH_KCRL0_RSHFT		4
+
+#define STB0899_OFF0_CRL_NOM_FREQ		0xf338
+#define STB0899_BASE_CRL_NOM_FREQ		0x00000000
+#define STB0899_CRL_NOM_FREQ			(0x3fffffff << 0)
+#define STB0899_OFFST_CRL_NOM_FREQ		0
+#define STB0899_WIDTH_CRL_NOM_FREQ		30
+
+#define STB0899_OFF0_CRL_SWP_RATE		0xf33c
+#define STB0899_BASE_CRL_SWP_RATE		0x00000000
+#define STB0899_CRL_SWP_RATE			(0x3fffffff << 0)
+#define STB0899_OFFST_CRL_SWP_RATE		0
+#define STB0899_WIDTH_CRL_SWP_RATE		30
+
+#define STB0899_OFF0_CRL_MAX_SWP		0xf340
+#define STB0899_BASE_CRL_MAX_SWP		0x00000000
+#define STB0899_CRL_MAX_SWP			(0x3fffffff << 0)
+#define STB0899_OFFST_CRL_MAX_SWP		0
+#define STB0899_WIDTH_CRL_MAX_SWP		30
+
+#define STB0899_OFF0_CRL_LK_CNTRL		0xf344
+#define STB0899_BASE_CRL_LK_CNTRL		0x00000000
+
+#define STB0899_OFF0_DECIM_CNTRL		0xf348
+#define STB0899_BASE_DECIM_CNTRL		0x00000000
+#define STB0899_BAND_LIMIT_B			(0x01 << 5)
+#define STB0899_OFFST_BAND_LIMIT_B		5
+#define STB0899_WIDTH_BAND_LIMIT_B		1
+#define STB0899_WIN_SEL				(0x03 << 3)
+#define STB0899_OFFST_WIN_SEL			3
+#define STB0899_WIDTH_WIN_SEL			2
+#define STB0899_DECIM_RATE			(0x07 << 0)
+#define STB0899_OFFST_DECIM_RATE		0
+#define STB0899_WIDTH_DECIM_RATE		3
+
+#define STB0899_OFF0_BTR_CNTRL			0xf34c
+#define STB0899_BASE_BTR_CNTRL			0x00000000
+#define STB0899_BTR_FREQ_CORR			(0x7ff << 4)
+#define STB0899_OFFST_BTR_FREQ_CORR		4
+#define STB0899_WIDTH_BTR_FREQ_CORR		11
+#define STB0899_BTR_CLR_LOCK			(0x01 << 3)
+#define STB0899_OFFST_BTR_CLR_LOCK		3
+#define STB0899_WIDTH_BTR_CLR_LOCK		1
+#define STB0899_BTR_SENSE			(0x01 << 2)
+#define STB0899_OFFST_BTR_SENSE			2
+#define STB0899_WIDTH_BTR_SENSE			1
+#define STB0899_BTR_ERR_ENA			(0x01 << 1)
+#define STB0899_OFFST_BTR_ERR_ENA		1
+#define STB0899_WIDTH_BTR_ERR_ENA		1
+#define STB0899_INTRP_PHS_SENSE			(0x01 << 0)
+#define STB0899_OFFST_INTRP_PHS_SENSE		0
+#define STB0899_WIDTH_INTRP_PHS_SENSE		1
+
+#define STB0899_OFF0_BTR_LOOP_GAIN		0xf350
+#define STB0899_BASE_BTR_LOOP_GAIN		0x00000000
+#define STB0899_KBTR2_RSHFT			(0x0f << 16)
+#define STB0899_OFFST_KBTR2_RSHFT		16
+#define STB0899_WIDTH_KBTR2_RSHFT		4
+#define STB0899_KBTR1				(0x0f << 12)
+#define STB0899_OFFST_KBTR1			12
+#define STB0899_WIDTH_KBTR1			4
+#define STB0899_KBTR1_RSHFT			(0x0f << 8)
+#define STB0899_OFFST_KBTR1_RSHFT		8
+#define STB0899_WIDTH_KBTR1_RSHFT		4
+#define STB0899_KBTR0				(0x0f << 4)
+#define STB0899_OFFST_KBTR0			4
+#define STB0899_WIDTH_KBTR0			4
+#define STB0899_KBTR0_RSHFT			(0x0f << 0)
+#define STB0899_OFFST_KBTR0_RSHFT		0
+#define STB0899_WIDTH_KBTR0_RSHFT		4
+
+#define STB0899_OFF0_BTR_PHS_INIT		0xf354
+#define STB0899_BASE_BTR_PHS_INIT		0x00000000
+#define STB0899_BTR_LD_PHASE_INIT		(0x01 << 28)
+#define STB0899_OFFST_BTR_LD_PHASE_INIT		28
+#define STB0899_WIDTH_BTR_LD_PHASE_INIT		1
+#define STB0899_BTR_INIT_PHASE			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_INIT_PHASE		0
+#define STB0899_WIDTH_BTR_INIT_PHASE		28
+
+#define STB0899_OFF0_BTR_FREQ_INIT		0xf358
+#define STB0899_BASE_BTR_FREQ_INIT		0x00000000
+#define STB0899_BTR_LD_FREQ_INIT		(1 << 28)
+#define STB0899_OFFST_BTR_LD_FREQ_INIT		28
+#define STB0899_WIDTH_BTR_LD_FREQ_INIT		1
+#define STB0899_BTR_FREQ_INIT			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_FREQ_INIT		0
+#define STB0899_WIDTH_BTR_FREQ_INIT		28
+
+#define STB0899_OFF0_BTR_NOM_FREQ		0xf35c
+#define STB0899_BASE_BTR_NOM_FREQ		0x00000000
+#define STB0899_BTR_NOM_FREQ			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_NOM_FREQ		0
+#define STB0899_WIDTH_BTR_NOM_FREQ		28
+
+#define STB0899_OFF0_BTR_LK_CNTRL		0xf360
+#define STB0899_BASE_BTR_LK_CNTRL		0x00000000
+#define STB0899_BTR_MIN_ENERGY			(0x0f << 24)
+#define STB0899_OFFST_BTR_MIN_ENERGY		24
+#define STB0899_WIDTH_BTR_MIN_ENERGY		4
+#define STB0899_BTR_LOCK_TH_LO			(0xff << 16)
+#define STB0899_OFFST_BTR_LOCK_TH_LO		16
+#define STB0899_WIDTH_BTR_LOCK_TH_LO		8
+#define STB0899_BTR_LOCK_TH_HI			(0xff << 8)
+#define STB0899_OFFST_BTR_LOCK_TH_HI		8
+#define STB0899_WIDTH_BTR_LOCK_TH_HI		8
+#define STB0899_BTR_LOCK_GAIN			(0x03 << 6)
+#define STB0899_OFFST_BTR_LOCK_GAIN		6
+#define STB0899_WIDTH_BTR_LOCK_GAIN		2
+#define STB0899_BTR_LOCK_LEAK			(0x3f << 0)
+#define STB0899_OFFST_BTR_LOCK_LEAK		0
+#define STB0899_WIDTH_BTR_LOCK_LEAK		6
+
+#define STB0899_OFF0_DECN_CNTRL			0xf364
+#define STB0899_BASE_DECN_CNTRL			0x00000000
+
+#define STB0899_OFF0_TP_CNTRL			0xf368
+#define STB0899_BASE_TP_CNTRL			0x00000000
+
+#define STB0899_OFF0_TP_BUF_STATUS		0xf36c
+#define STB0899_BASE_TP_BUF_STATUS		0x00000000
+#define STB0899_TP_BUFFER_FULL                  (1 << 0)
+
+#define STB0899_OFF0_DC_ESTIM			0xf37c
+#define STB0899_BASE_DC_ESTIM			0x0000
+#define STB0899_I_DC_ESTIMATE			(0xff << 8)
+#define STB0899_OFFST_I_DC_ESTIMATE		8
+#define STB0899_WIDTH_I_DC_ESTIMATE		8
+#define STB0899_Q_DC_ESTIMATE			(0xff << 0)
+#define STB0899_OFFST_Q_DC_ESTIMATE		0
+#define STB0899_WIDTH_Q_DC_ESTIMATE		8
+
+#define STB0899_OFF0_FLL_CNTRL			0xf310
+#define STB0899_BASE_FLL_CNTRL			0x00000020
+#define STB0899_CRL_FLL_ACC			(0x01 << 4)
+#define STB0899_OFFST_CRL_FLL_ACC		4
+#define STB0899_WIDTH_CRL_FLL_ACC		1
+#define STB0899_FLL_AVG_PERIOD			(0x0f << 0)
+#define STB0899_OFFST_FLL_AVG_PERIOD		0
+#define STB0899_WIDTH_FLL_AVG_PERIOD		4
+
+#define STB0899_OFF0_FLL_FREQ_WD		0xf314
+#define STB0899_BASE_FLL_FREQ_WD		0x00000020
+#define STB0899_FLL_FREQ_WD			(0xffffffff << 0)
+#define STB0899_OFFST_FLL_FREQ_WD		0
+#define STB0899_WIDTH_FLL_FREQ_WD		32
+
+#define STB0899_OFF0_ANTI_ALIAS_SEL		0xf358
+#define STB0899_BASE_ANTI_ALIAS_SEL		0x00000020
+#define STB0899_ANTI_ALIAS_SELB			(0x03 << 0)
+#define STB0899_OFFST_ANTI_ALIAS_SELB		0
+#define STB0899_WIDTH_ANTI_ALIAS_SELB		2
+
+#define STB0899_OFF0_RRC_ALPHA			0xf35c
+#define STB0899_BASE_RRC_ALPHA			0x00000020
+#define STB0899_RRC_ALPHA			(0x03 << 0)
+#define STB0899_OFFST_RRC_ALPHA			0
+#define STB0899_WIDTH_RRC_ALPHA			2
+
+#define STB0899_OFF0_DC_ADAPT_LSHFT		0xf360
+#define STB0899_BASE_DC_ADAPT_LSHFT		0x00000020
+#define STB0899_DC_ADAPT_LSHFT			(0x077 << 0)
+#define STB0899_OFFST_DC_ADAPT_LSHFT		0
+#define STB0899_WIDTH_DC_ADAPT_LSHFT		3
+
+#define STB0899_OFF0_IMB_OFFSET			0xf364
+#define STB0899_BASE_IMB_OFFSET			0x00000020
+#define STB0899_PHS_IMB_COMP			(0xff << 8)
+#define STB0899_OFFST_PHS_IMB_COMP		8
+#define STB0899_WIDTH_PHS_IMB_COMP		8
+#define STB0899_AMPL_IMB_COMP			(0xff << 0)
+#define STB0899_OFFST_AMPL_IMB_COMP		0
+#define STB0899_WIDTH_AMPL_IMB_COMP		8
+
+#define STB0899_OFF0_IMB_ESTIMATE		0xf368
+#define STB0899_BASE_IMB_ESTIMATE		0x00000020
+#define STB0899_PHS_IMB_ESTIMATE		(0xff << 8)
+#define STB0899_OFFST_PHS_IMB_ESTIMATE		8
+#define STB0899_WIDTH_PHS_IMB_ESTIMATE		8
+#define STB0899_AMPL_IMB_ESTIMATE		(0xff << 0)
+#define STB0899_OFFST_AMPL_IMB_ESTIMATE		0
+#define STB0899_WIDTH_AMPL_IMB_ESTIMATE		8
+
+#define STB0899_OFF0_IMB_CNTRL			0xf36c
+#define STB0899_BASE_IMB_CNTRL			0x00000020
+#define STB0899_PHS_ADAPT_LSHFT			(0x07 << 4)
+#define STB0899_OFFST_PHS_ADAPT_LSHFT		4
+#define STB0899_WIDTH_PHS_ADAPT_LSHFT		3
+#define STB0899_AMPL_ADAPT_LSHFT		(0x07 << 1)
+#define STB0899_OFFST_AMPL_ADAPT_LSHFT		1
+#define STB0899_WIDTH_AMPL_ADAPT_LSHFT		3
+#define STB0899_IMB_COMP			(0x01 << 0)
+#define STB0899_OFFST_IMB_COMP			0
+#define STB0899_WIDTH_IMB_COMP			1
+
+#define STB0899_OFF0_IF_AGC_CNTRL2		0xf374
+#define STB0899_BASE_IF_AGC_CNTRL2		0x00000020
+#define STB0899_IF_AGC_LOCK_TH			(0xff << 11)
+#define STB0899_OFFST_IF_AGC_LOCK_TH		11
+#define STB0899_WIDTH_IF_AGC_LOCK_TH		8
+#define STB0899_IF_AGC_SD_DIV			(0xff << 3)
+#define STB0899_OFFST_IF_AGC_SD_DIV		3
+#define STB0899_WIDTH_IF_AGC_SD_DIV		8
+#define STB0899_IF_AGC_DUMP_PER			(0x07 << 0)
+#define STB0899_OFFST_IF_AGC_DUMP_PER		0
+#define STB0899_WIDTH_IF_AGC_DUMP_PER		3
+
+#define STB0899_OFF0_DMD_CNTRL2			0xf378
+#define STB0899_BASE_DMD_CNTRL2			0x00000020
+#define STB0899_SPECTRUM_INVERT			(0x01 << 2)
+#define STB0899_OFFST_SPECTRUM_INVERT		2
+#define STB0899_WIDTH_SPECTRUM_INVERT		1
+#define STB0899_AGC_MODE			(0x01 << 1)
+#define STB0899_OFFST_AGC_MODE			1
+#define STB0899_WIDTH_AGC_MODE			1
+#define STB0899_CRL_FREQ_ADJ			(0x01 << 0)
+#define STB0899_OFFST_CRL_FREQ_ADJ		0
+#define STB0899_WIDTH_CRL_FREQ_ADJ		1
+
+#define STB0899_OFF0_TP_BUFFER			0xf300
+#define STB0899_BASE_TP_BUFFER			0x00000040
+#define STB0899_TP_BUFFER_IN			(0xffff << 0)
+#define STB0899_OFFST_TP_BUFFER_IN		0
+#define STB0899_WIDTH_TP_BUFFER_IN		16
+
+#define STB0899_OFF0_TP_BUFFER1			0xf304
+#define STB0899_BASE_TP_BUFFER1			0x00000040
+#define STB0899_OFF0_TP_BUFFER2			0xf308
+#define STB0899_BASE_TP_BUFFER2			0x00000040
+#define STB0899_OFF0_TP_BUFFER3			0xf30c
+#define STB0899_BASE_TP_BUFFER3			0x00000040
+#define STB0899_OFF0_TP_BUFFER4			0xf310
+#define STB0899_BASE_TP_BUFFER4			0x00000040
+#define STB0899_OFF0_TP_BUFFER5			0xf314
+#define STB0899_BASE_TP_BUFFER5			0x00000040
+#define STB0899_OFF0_TP_BUFFER6			0xf318
+#define STB0899_BASE_TP_BUFFER6			0x00000040
+#define STB0899_OFF0_TP_BUFFER7			0xf31c
+#define STB0899_BASE_TP_BUFFER7			0x00000040
+#define STB0899_OFF0_TP_BUFFER8			0xf320
+#define STB0899_BASE_TP_BUFFER8			0x00000040
+#define STB0899_OFF0_TP_BUFFER9			0xf324
+#define STB0899_BASE_TP_BUFFER9			0x00000040
+#define STB0899_OFF0_TP_BUFFER10		0xf328
+#define STB0899_BASE_TP_BUFFER10		0x00000040
+#define STB0899_OFF0_TP_BUFFER11		0xf32c
+#define STB0899_BASE_TP_BUFFER11		0x00000040
+#define STB0899_OFF0_TP_BUFFER12		0xf330
+#define STB0899_BASE_TP_BUFFER12		0x00000040
+#define STB0899_OFF0_TP_BUFFER13		0xf334
+#define STB0899_BASE_TP_BUFFER13		0x00000040
+#define STB0899_OFF0_TP_BUFFER14		0xf338
+#define STB0899_BASE_TP_BUFFER14		0x00000040
+#define STB0899_OFF0_TP_BUFFER15		0xf33c
+#define STB0899_BASE_TP_BUFFER15		0x00000040
+#define STB0899_OFF0_TP_BUFFER16		0xf340
+#define STB0899_BASE_TP_BUFFER16		0x00000040
+#define STB0899_OFF0_TP_BUFFER17		0xf344
+#define STB0899_BASE_TP_BUFFER17		0x00000040
+#define STB0899_OFF0_TP_BUFFER18		0xf348
+#define STB0899_BASE_TP_BUFFER18		0x00000040
+#define STB0899_OFF0_TP_BUFFER19		0xf34c
+#define STB0899_BASE_TP_BUFFER19		0x00000040
+#define STB0899_OFF0_TP_BUFFER20		0xf350
+#define STB0899_BASE_TP_BUFFER20		0x00000040
+#define STB0899_OFF0_TP_BUFFER21		0xf354
+#define STB0899_BASE_TP_BUFFER21		0x00000040
+#define STB0899_OFF0_TP_BUFFER22		0xf358
+#define STB0899_BASE_TP_BUFFER22		0x00000040
+#define STB0899_OFF0_TP_BUFFER23		0xf35c
+#define STB0899_BASE_TP_BUFFER23		0x00000040
+#define STB0899_OFF0_TP_BUFFER24		0xf360
+#define STB0899_BASE_TP_BUFFER24		0x00000040
+#define STB0899_OFF0_TP_BUFFER25		0xf364
+#define STB0899_BASE_TP_BUFFER25		0x00000040
+#define STB0899_OFF0_TP_BUFFER26		0xf368
+#define STB0899_BASE_TP_BUFFER26		0x00000040
+#define STB0899_OFF0_TP_BUFFER27		0xf36c
+#define STB0899_BASE_TP_BUFFER27		0x00000040
+#define STB0899_OFF0_TP_BUFFER28		0xf370
+#define STB0899_BASE_TP_BUFFER28		0x00000040
+#define STB0899_OFF0_TP_BUFFER29		0xf374
+#define STB0899_BASE_TP_BUFFER29		0x00000040
+#define STB0899_OFF0_TP_BUFFER30		0xf378
+#define STB0899_BASE_TP_BUFFER30		0x00000040
+#define STB0899_OFF0_TP_BUFFER31		0xf37c
+#define STB0899_BASE_TP_BUFFER31		0x00000040
+#define STB0899_OFF0_TP_BUFFER32		0xf300
+#define STB0899_BASE_TP_BUFFER32		0x00000060
+#define STB0899_OFF0_TP_BUFFER33		0xf304
+#define STB0899_BASE_TP_BUFFER33		0x00000060
+#define STB0899_OFF0_TP_BUFFER34		0xf308
+#define STB0899_BASE_TP_BUFFER34		0x00000060
+#define STB0899_OFF0_TP_BUFFER35		0xf30c
+#define STB0899_BASE_TP_BUFFER35		0x00000060
+#define STB0899_OFF0_TP_BUFFER36		0xf310
+#define STB0899_BASE_TP_BUFFER36		0x00000060
+#define STB0899_OFF0_TP_BUFFER37		0xf314
+#define STB0899_BASE_TP_BUFFER37		0x00000060
+#define STB0899_OFF0_TP_BUFFER38		0xf318
+#define STB0899_BASE_TP_BUFFER38		0x00000060
+#define STB0899_OFF0_TP_BUFFER39		0xf31c
+#define STB0899_BASE_TP_BUFFER39		0x00000060
+#define STB0899_OFF0_TP_BUFFER40		0xf320
+#define STB0899_BASE_TP_BUFFER40		0x00000060
+#define STB0899_OFF0_TP_BUFFER41		0xf324
+#define STB0899_BASE_TP_BUFFER41		0x00000060
+#define STB0899_OFF0_TP_BUFFER42		0xf328
+#define STB0899_BASE_TP_BUFFER42		0x00000060
+#define STB0899_OFF0_TP_BUFFER43		0xf32c
+#define STB0899_BASE_TP_BUFFER43		0x00000060
+#define STB0899_OFF0_TP_BUFFER44		0xf330
+#define STB0899_BASE_TP_BUFFER44		0x00000060
+#define STB0899_OFF0_TP_BUFFER45		0xf334
+#define STB0899_BASE_TP_BUFFER45		0x00000060
+#define STB0899_OFF0_TP_BUFFER46		0xf338
+#define STB0899_BASE_TP_BUFFER46		0x00000060
+#define STB0899_OFF0_TP_BUFFER47		0xf33c
+#define STB0899_BASE_TP_BUFFER47		0x00000060
+#define STB0899_OFF0_TP_BUFFER48		0xf340
+#define STB0899_BASE_TP_BUFFER48		0x00000060
+#define STB0899_OFF0_TP_BUFFER49		0xf344
+#define STB0899_BASE_TP_BUFFER49		0x00000060
+#define STB0899_OFF0_TP_BUFFER50		0xf348
+#define STB0899_BASE_TP_BUFFER50		0x00000060
+#define STB0899_OFF0_TP_BUFFER51		0xf34c
+#define STB0899_BASE_TP_BUFFER51		0x00000060
+#define STB0899_OFF0_TP_BUFFER52		0xf350
+#define STB0899_BASE_TP_BUFFER52		0x00000060
+#define STB0899_OFF0_TP_BUFFER53		0xf354
+#define STB0899_BASE_TP_BUFFER53		0x00000060
+#define STB0899_OFF0_TP_BUFFER54		0xf358
+#define STB0899_BASE_TP_BUFFER54		0x00000060
+#define STB0899_OFF0_TP_BUFFER55		0xf35c
+#define STB0899_BASE_TP_BUFFER55		0x00000060
+#define STB0899_OFF0_TP_BUFFER56		0xf360
+#define STB0899_BASE_TP_BUFFER56		0x00000060
+#define STB0899_OFF0_TP_BUFFER57		0xf364
+#define STB0899_BASE_TP_BUFFER57		0x00000060
+#define STB0899_OFF0_TP_BUFFER58		0xf368
+#define STB0899_BASE_TP_BUFFER58		0x00000060
+#define STB0899_OFF0_TP_BUFFER59		0xf36c
+#define STB0899_BASE_TP_BUFFER59		0x00000060
+#define STB0899_OFF0_TP_BUFFER60		0xf370
+#define STB0899_BASE_TP_BUFFER60		0x00000060
+#define STB0899_OFF0_TP_BUFFER61		0xf374
+#define STB0899_BASE_TP_BUFFER61		0x00000060
+#define STB0899_OFF0_TP_BUFFER62		0xf378
+#define STB0899_BASE_TP_BUFFER62		0x00000060
+#define STB0899_OFF0_TP_BUFFER63		0xf37c
+#define STB0899_BASE_TP_BUFFER63		0x00000060
+
+#define STB0899_OFF0_RESET_CNTRL		0xf300
+#define STB0899_BASE_RESET_CNTRL		0x00000400
+#define STB0899_DVBS2_RESET			(0x01 << 0)
+#define STB0899_OFFST_DVBS2_RESET		0
+#define STB0899_WIDTH_DVBS2_RESET		1
+
+#define STB0899_OFF0_ACM_ENABLE			0xf304
+#define STB0899_BASE_ACM_ENABLE			0x00000400
+#define STB0899_ACM_ENABLE			1
+
+#define STB0899_OFF0_DESCR_CNTRL		0xf30c
+#define STB0899_BASE_DESCR_CNTRL		0x00000400
+#define STB0899_OFFST_DESCR_CNTRL               0
+#define STB0899_WIDTH_DESCR_CNTRL               16
+
+#define STB0899_OFF0_UWP_CNTRL1			0xf320
+#define STB0899_BASE_UWP_CNTRL1			0x00000400
+#define STB0899_UWP_TH_SOF			(0x7fff << 11)
+#define STB0899_OFFST_UWP_TH_SOF		11
+#define STB0899_WIDTH_UWP_TH_SOF		15
+#define STB0899_UWP_ESN0_QUANT			(0xff << 3)
+#define STB0899_OFFST_UWP_ESN0_QUANT		3
+#define STB0899_WIDTH_UWP_ESN0_QUANT		8
+#define STB0899_UWP_ESN0_AVE			(0x03 << 1)
+#define STB0899_OFFST_UWP_ESN0_AVE		1
+#define STB0899_WIDTH_UWP_ESN0_AVE		2
+#define STB0899_UWP_START			(0x01 << 0)
+#define STB0899_OFFST_UWP_START			0
+#define STB0899_WIDTH_UWP_START			1
+
+#define STB0899_OFF0_UWP_CNTRL2			0xf324
+#define STB0899_BASE_UWP_CNTRL2			0x00000400
+#define STB0899_UWP_MISS_TH			(0xff << 16)
+#define STB0899_OFFST_UWP_MISS_TH		16
+#define STB0899_WIDTH_UWP_MISS_TH		8
+#define STB0899_FE_FINE_TRK			(0xff << 8)
+#define STB0899_OFFST_FE_FINE_TRK		8
+#define STB0899_WIDTH_FE_FINE_TRK		8
+#define STB0899_FE_COARSE_TRK			(0xff << 0)
+#define STB0899_OFFST_FE_COARSE_TRK		0
+#define STB0899_WIDTH_FE_COARSE_TRK		8
+
+#define STB0899_OFF0_UWP_STAT1			0xf328
+#define STB0899_BASE_UWP_STAT1			0x00000400
+#define STB0899_UWP_STATE			(0x03ff << 15)
+#define STB0899_OFFST_UWP_STATE			15
+#define STB0899_WIDTH_UWP_STATE			10
+#define STB0899_UW_MAX_PEAK			(0x7fff << 0)
+#define STB0899_OFFST_UW_MAX_PEAK		0
+#define STB0899_WIDTH_UW_MAX_PEAK		15
+
+#define STB0899_OFF0_UWP_STAT2			0xf32c
+#define STB0899_BASE_UWP_STAT2			0x00000400
+#define STB0899_ESNO_EST			(0x07ffff << 7)
+#define STB0899_OFFST_ESN0_EST			7
+#define STB0899_WIDTH_ESN0_EST			19
+#define STB0899_UWP_DECODE_MOD			(0x7f << 0)
+#define STB0899_OFFST_UWP_DECODE_MOD		0
+#define STB0899_WIDTH_UWP_DECODE_MOD		7
+
+#define STB0899_OFF0_DMD_CORE_ID		0xf334
+#define STB0899_BASE_DMD_CORE_ID		0x00000400
+#define STB0899_CORE_ID				(0xffffffff << 0)
+#define STB0899_OFFST_CORE_ID			0
+#define STB0899_WIDTH_CORE_ID			32
+
+#define STB0899_OFF0_DMD_VERSION_ID		0xf33c
+#define STB0899_BASE_DMD_VERSION_ID		0x00000400
+#define STB0899_VERSION_ID			(0xff << 0)
+#define STB0899_OFFST_VERSION_ID		0
+#define STB0899_WIDTH_VERSION_ID		8
+
+#define STB0899_OFF0_DMD_STAT2			0xf340
+#define STB0899_BASE_DMD_STAT2			0x00000400
+#define STB0899_CSM_LOCK			(0x01 << 1)
+#define STB0899_OFFST_CSM_LOCK			1
+#define STB0899_WIDTH_CSM_LOCK			1
+#define STB0899_UWP_LOCK			(0x01 << 0)
+#define STB0899_OFFST_UWP_LOCK			0
+#define STB0899_WIDTH_UWP_LOCK			1
+
+#define STB0899_OFF0_FREQ_ADJ_SCALE		0xf344
+#define STB0899_BASE_FREQ_ADJ_SCALE		0x00000400
+#define STB0899_FREQ_ADJ_SCALE			(0x0fff << 0)
+#define STB0899_OFFST_FREQ_ADJ_SCALE		0
+#define STB0899_WIDTH_FREQ_ADJ_SCALE		12
+
+#define STB0899_OFF0_UWP_CNTRL3			0xf34c
+#define STB0899_BASE_UWP_CNTRL3			0x00000400
+#define STB0899_UWP_TH_TRACK			(0x7fff << 15)
+#define STB0899_OFFST_UWP_TH_TRACK		15
+#define STB0899_WIDTH_UWP_TH_TRACK		15
+#define STB0899_UWP_TH_ACQ			(0x7fff << 0)
+#define STB0899_OFFST_UWP_TH_ACQ		0
+#define STB0899_WIDTH_UWP_TH_ACQ		15
+
+#define STB0899_OFF0_SYM_CLK_SEL		0xf350
+#define STB0899_BASE_SYM_CLK_SEL		0x00000400
+#define STB0899_SYM_CLK_SEL			(0x03 << 0)
+#define STB0899_OFFST_SYM_CLK_SEL		0
+#define STB0899_WIDTH_SYM_CLK_SEL		2
+
+#define STB0899_OFF0_SOF_SRCH_TO		0xf354
+#define STB0899_BASE_SOF_SRCH_TO		0x00000400
+#define STB0899_SOF_SEARCH_TIMEOUT		(0x3fffff << 0)
+#define STB0899_OFFST_SOF_SEARCH_TIMEOUT	0
+#define STB0899_WIDTH_SOF_SEARCH_TIMEOUT	22
+
+#define STB0899_OFF0_ACQ_CNTRL1			0xf358
+#define STB0899_BASE_ACQ_CNTRL1			0x00000400
+#define STB0899_FE_FINE_ACQ			(0xff << 8)
+#define STB0899_OFFST_FE_FINE_ACQ		8
+#define STB0899_WIDTH_FE_FINE_ACQ		8
+#define STB0899_FE_COARSE_ACQ			(0xff << 0)
+#define STB0899_OFFST_FE_COARSE_ACQ		0
+#define STB0899_WIDTH_FE_COARSE_ACQ		8
+
+#define STB0899_OFF0_ACQ_CNTRL2			0xf35c
+#define STB0899_BASE_ACQ_CNTRL2			0x00000400
+#define STB0899_ZIGZAG				(0x01 << 25)
+#define STB0899_OFFST_ZIGZAG			25
+#define STB0899_WIDTH_ZIGZAG			1
+#define STB0899_NUM_STEPS			(0xff << 17)
+#define STB0899_OFFST_NUM_STEPS			17
+#define STB0899_WIDTH_NUM_STEPS			8
+#define STB0899_FREQ_STEPSIZE			(0x1ffff << 0)
+#define STB0899_OFFST_FREQ_STEPSIZE		0
+#define STB0899_WIDTH_FREQ_STEPSIZE		17
+
+#define STB0899_OFF0_ACQ_CNTRL3			0xf360
+#define STB0899_BASE_ACQ_CNTRL3			0x00000400
+#define STB0899_THRESHOLD_SCL			(0x3f << 23)
+#define STB0899_OFFST_THRESHOLD_SCL		23
+#define STB0899_WIDTH_THRESHOLD_SCL		6
+#define STB0899_UWP_TH_SRCH			(0x7fff << 8)
+#define STB0899_OFFST_UWP_TH_SRCH		8
+#define STB0899_WIDTH_UWP_TH_SRCH		15
+#define STB0899_AUTO_REACQUIRE			(0x01 << 7)
+#define STB0899_OFFST_AUTO_REACQUIRE		7
+#define STB0899_WIDTH_AUTO_REACQUIRE		1
+#define STB0899_TRACK_LOCK_SEL			(0x01 << 6)
+#define STB0899_OFFST_TRACK_LOCK_SEL		6
+#define STB0899_WIDTH_TRACK_LOCK_SEL		1
+#define STB0899_ACQ_SEARCH_MODE			(0x03 << 4)
+#define STB0899_OFFST_ACQ_SEARCH_MODE		4
+#define STB0899_WIDTH_ACQ_SEARCH_MODE		2
+#define STB0899_CONFIRM_FRAMES			(0x0f << 0)
+#define STB0899_OFFST_CONFIRM_FRAMES		0
+#define STB0899_WIDTH_CONFIRM_FRAMES		4
+
+#define STB0899_OFF0_FE_SETTLE			0xf364
+#define STB0899_BASE_FE_SETTLE			0x00000400
+#define STB0899_SETTLING_TIME			(0x3fffff << 0)
+#define STB0899_OFFST_SETTLING_TIME		0
+#define STB0899_WIDTH_SETTLING_TIME		22
+
+#define STB0899_OFF0_AC_DWELL			0xf368
+#define STB0899_BASE_AC_DWELL			0x00000400
+#define STB0899_DWELL_TIME			(0x3fffff << 0)
+#define STB0899_OFFST_DWELL_TIME		0
+#define STB0899_WIDTH_DWELL_TIME		22
+
+#define STB0899_OFF0_ACQUIRE_TRIG		0xf36c
+#define STB0899_BASE_ACQUIRE_TRIG		0x00000400
+#define STB0899_ACQUIRE				(0x01 << 0)
+#define STB0899_OFFST_ACQUIRE			0
+#define STB0899_WIDTH_ACQUIRE			1
+
+#define STB0899_OFF0_LOCK_LOST			0xf370
+#define STB0899_BASE_LOCK_LOST			0x00000400
+#define STB0899_LOCK_LOST			(0x01 << 0)
+#define STB0899_OFFST_LOCK_LOST			0
+#define STB0899_WIDTH_LOCK_LOST			1
+
+#define STB0899_OFF0_ACQ_STAT1			0xf374
+#define STB0899_BASE_ACQ_STAT1			0x00000400
+#define STB0899_STEP_FREQ			(0x1fffff << 11)
+#define STB0899_OFFST_STEP_FREQ			11
+#define STB0899_WIDTH_STEP_FREQ			21
+#define STB0899_ACQ_STATE			(0x07 << 8)
+#define STB0899_OFFST_ACQ_STATE			8
+#define STB0899_WIDTH_ACQ_STATE			3
+#define STB0899_UW_DETECT_COUNT			(0xff << 0)
+#define STB0899_OFFST_UW_DETECT_COUNT		0
+#define STB0899_WIDTH_UW_DETECT_COUNT		8
+
+#define STB0899_OFF0_ACQ_TIMEOUT		0xf378
+#define STB0899_BASE_ACQ_TIMEOUT		0x00000400
+#define STB0899_ACQ_TIMEOUT			(0x3fffff << 0)
+#define STB0899_OFFST_ACQ_TIMEOUT		0
+#define STB0899_WIDTH_ACQ_TIMEOUT		22
+
+#define STB0899_OFF0_ACQ_TIME			0xf37c
+#define STB0899_BASE_ACQ_TIME			0x00000400
+#define STB0899_ACQ_TIME_SYM			(0xffffff << 0)
+#define STB0899_OFFST_ACQ_TIME_SYM		0
+#define STB0899_WIDTH_ACQ_TIME_SYM		24
+
+#define STB0899_OFF0_FINAL_AGC_CNTRL		0xf308
+#define STB0899_BASE_FINAL_AGC_CNTRL		0x00000440
+#define STB0899_FINAL_GAIN_INIT			(0x3fff << 12)
+#define STB0899_OFFST_FINAL_GAIN_INIT		12
+#define STB0899_WIDTH_FINAL_GAIN_INIT		14
+#define STB0899_FINAL_LOOP_GAIN			(0x0f << 8)
+#define STB0899_OFFST_FINAL_LOOP_GAIN		8
+#define STB0899_WIDTH_FINAL_LOOP_GAIN		4
+#define STB0899_FINAL_LD_GAIN_INIT		(0x01 << 7)
+#define STB0899_OFFST_FINAL_LD_GAIN_INIT	7
+#define STB0899_WIDTH_FINAL_LD_GAIN_INIT	1
+#define STB0899_FINAL_AGC_REF			(0x7f << 0)
+#define STB0899_OFFST_FINAL_AGC_REF		0
+#define STB0899_WIDTH_FINAL_AGC_REF		7
+
+#define STB0899_OFF0_FINAL_AGC_GAIN		0xf30c
+#define STB0899_BASE_FINAL_AGC_GAIN		0x00000440
+#define STB0899_FINAL_AGC_GAIN			(0x3fff << 0)
+#define STB0899_OFFST_FINAL_AGC_GAIN		0
+#define STB0899_WIDTH_FINAL_AGC_GAIN		14
+
+#define STB0899_OFF0_EQUALIZER_INIT		0xf310
+#define STB0899_BASE_EQUALIZER_INIT		0x00000440
+#define STB0899_EQ_SRST				(0x01 << 1)
+#define STB0899_OFFST_EQ_SRST			1
+#define STB0899_WIDTH_EQ_SRST			1
+#define STB0899_EQ_INIT				(0x01 << 0)
+#define STB0899_OFFST_EQ_INIT			0
+#define STB0899_WIDTH_EQ_INIT			1
+
+#define STB0899_OFF0_EQ_CNTRL			0xf314
+#define STB0899_BASE_EQ_CNTRL			0x00000440
+#define STB0899_EQ_ADAPT_MODE			(0x01 << 18)
+#define STB0899_OFFST_EQ_ADAPT_MODE		18
+#define STB0899_WIDTH_EQ_ADAPT_MODE		1
+#define STB0899_EQ_DELAY			(0x0f << 14)
+#define STB0899_OFFST_EQ_DELAY			14
+#define STB0899_WIDTH_EQ_DELAY			4
+#define STB0899_EQ_QUANT_LEVEL			(0xff << 6)
+#define STB0899_OFFST_EQ_QUANT_LEVEL		6
+#define STB0899_WIDTH_EQ_QUANT_LEVEL		8
+#define STB0899_EQ_DISABLE_UPDATE		(0x01 << 5)
+#define STB0899_OFFST_EQ_DISABLE_UPDATE		5
+#define STB0899_WIDTH_EQ_DISABLE_UPDATE		1
+#define STB0899_EQ_BYPASS			(0x01 << 4)
+#define STB0899_OFFST_EQ_BYPASS			4
+#define STB0899_WIDTH_EQ_BYPASS			1
+#define STB0899_EQ_SHIFT			(0x0f << 0)
+#define STB0899_OFFST_EQ_SHIFT			0
+#define STB0899_WIDTH_EQ_SHIFT			4
+
+#define STB0899_OFF0_EQ_I_INIT_COEFF_0		0xf320
+#define STB0899_OFF1_EQ_I_INIT_COEFF_1		0xf324
+#define STB0899_OFF2_EQ_I_INIT_COEFF_2		0xf328
+#define STB0899_OFF3_EQ_I_INIT_COEFF_3		0xf32c
+#define STB0899_OFF4_EQ_I_INIT_COEFF_4		0xf330
+#define STB0899_OFF5_EQ_I_INIT_COEFF_5		0xf334
+#define STB0899_OFF6_EQ_I_INIT_COEFF_6		0xf338
+#define STB0899_OFF7_EQ_I_INIT_COEFF_7		0xf33c
+#define STB0899_OFF8_EQ_I_INIT_COEFF_8		0xf340
+#define STB0899_OFF9_EQ_I_INIT_COEFF_9		0xf344
+#define STB0899_OFFa_EQ_I_INIT_COEFF_10		0xf348
+#define STB0899_BASE_EQ_I_INIT_COEFF_N		0x00000440
+#define STB0899_EQ_I_INIT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_I_INIT_COEFF_N		0
+#define STB0899_WIDTH_EQ_I_INIT_COEFF_N		12
+
+#define STB0899_OFF0_EQ_Q_INIT_COEFF_0		0xf350
+#define STB0899_OFF1_EQ_Q_INIT_COEFF_1		0xf354
+#define STB0899_OFF2_EQ_Q_INIT_COEFF_2		0xf358
+#define STB0899_OFF3_EQ_Q_INIT_COEFF_3		0xf35c
+#define STB0899_OFF4_EQ_Q_INIT_COEFF_4		0xf360
+#define STB0899_OFF5_EQ_Q_INIT_COEFF_5		0xf364
+#define STB0899_OFF6_EQ_Q_INIT_COEFF_6		0xf368
+#define STB0899_OFF7_EQ_Q_INIT_COEFF_7		0xf36c
+#define STB0899_OFF8_EQ_Q_INIT_COEFF_8		0xf370
+#define STB0899_OFF9_EQ_Q_INIT_COEFF_9		0xf374
+#define STB0899_OFFa_EQ_Q_INIT_COEFF_10		0xf378
+#define STB0899_BASE_EQ_Q_INIT_COEFF_N		0x00000440
+#define STB0899_EQ_Q_INIT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_Q_INIT_COEFF_N		0
+#define STB0899_WIDTH_EQ_Q_INIT_COEFF_N		12
+
+#define STB0899_OFF0_EQ_I_OUT_COEFF_0		0xf300
+#define STB0899_OFF1_EQ_I_OUT_COEFF_1		0xf304
+#define STB0899_OFF2_EQ_I_OUT_COEFF_2		0xf308
+#define STB0899_OFF3_EQ_I_OUT_COEFF_3		0xf30c
+#define STB0899_OFF4_EQ_I_OUT_COEFF_4		0xf310
+#define STB0899_OFF5_EQ_I_OUT_COEFF_5		0xf314
+#define STB0899_OFF6_EQ_I_OUT_COEFF_6		0xf318
+#define STB0899_OFF7_EQ_I_OUT_COEFF_7		0xf31c
+#define STB0899_OFF8_EQ_I_OUT_COEFF_8		0xf320
+#define STB0899_OFF9_EQ_I_OUT_COEFF_9		0xf324
+#define STB0899_OFFa_EQ_I_OUT_COEFF_10		0xf328
+#define STB0899_BASE_EQ_I_OUT_COEFF_N		0x00000460
+#define STB0899_EQ_I_OUT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_I_OUT_COEFF_N		0
+#define STB0899_WIDTH_EQ_I_OUT_COEFF_N		12
+
+#define STB0899_OFF0_EQ_Q_OUT_COEFF_0		0xf330
+#define STB0899_OFF1_EQ_Q_OUT_COEFF_1		0xf334
+#define STB0899_OFF2_EQ_Q_OUT_COEFF_2		0xf338
+#define STB0899_OFF3_EQ_Q_OUT_COEFF_3		0xf33c
+#define STB0899_OFF4_EQ_Q_OUT_COEFF_4		0xf340
+#define STB0899_OFF5_EQ_Q_OUT_COEFF_5		0xf344
+#define STB0899_OFF6_EQ_Q_OUT_COEFF_6		0xf348
+#define STB0899_OFF7_EQ_Q_OUT_COEFF_7		0xf34c
+#define STB0899_OFF8_EQ_Q_OUT_COEFF_8		0xf350
+#define STB0899_OFF9_EQ_Q_OUT_COEFF_9		0xf354
+#define STB0899_OFFa_EQ_Q_OUT_COEFF_10		0xf358
+#define STB0899_BASE_EQ_Q_OUT_COEFF_N		0x00000460
+#define STB0899_EQ_Q_OUT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_Q_OUT_COEFF_N		0
+#define STB0899_WIDTH_EQ_Q_OUT_COEFF_N		12
+
+/*	S2 FEC	*/
+#define STB0899_OFF0_BLOCK_LNGTH		0xfa04
+#define STB0899_BASE_BLOCK_LNGTH		0x00000000
+#define STB0899_BLOCK_LENGTH			(0xff << 0)
+#define STB0899_OFFST_BLOCK_LENGTH		0
+#define STB0899_WIDTH_BLOCK_LENGTH		8
+
+#define STB0899_OFF0_ROW_STR			0xfa08
+#define STB0899_BASE_ROW_STR			0x00000000
+#define STB0899_ROW_STRIDE			(0xff << 0)
+#define STB0899_OFFST_ROW_STRIDE		0
+#define STB0899_WIDTH_ROW_STRIDE		8
+
+#define STB0899_OFF0_MAX_ITER			0xfa0c
+#define STB0899_BASE_MAX_ITER			0x00000000
+#define STB0899_MAX_ITERATIONS			(0xff << 0)
+#define STB0899_OFFST_MAX_ITERATIONS		0
+#define STB0899_WIDTH_MAX_ITERATIONS		8
+
+#define STB0899_OFF0_BN_END_ADDR		0xfa10
+#define STB0899_BASE_BN_END_ADDR		0x00000000
+#define STB0899_BN_END_ADDR			(0x0fff << 0)
+#define STB0899_OFFST_BN_END_ADDR		0
+#define STB0899_WIDTH_BN_END_ADDR		12
+
+#define STB0899_OFF0_CN_END_ADDR		0xfa14
+#define STB0899_BASE_CN_END_ADDR		0x00000000
+#define STB0899_CN_END_ADDR			(0x0fff << 0)
+#define STB0899_OFFST_CN_END_ADDR		0
+#define STB0899_WIDTH_CN_END_ADDR		12
+
+#define STB0899_OFF0_INFO_LENGTH		0xfa1c
+#define STB0899_BASE_INFO_LENGTH		0x00000000
+#define STB0899_INFO_LENGTH			(0xff << 0)
+#define STB0899_OFFST_INFO_LENGTH		0
+#define STB0899_WIDTH_INFO_LENGTH		8
+
+#define STB0899_OFF0_BOT_ADDR			0xfa20
+#define STB0899_BASE_BOT_ADDR			0x00000000
+#define STB0899_BOTTOM_BASE_ADDR		(0x03ff << 0)
+#define STB0899_OFFST_BOTTOM_BASE_ADDR		0
+#define STB0899_WIDTH_BOTTOM_BASE_ADDR		10
+
+#define STB0899_OFF0_BCH_BLK_LN			0xfa24
+#define STB0899_BASE_BCH_BLK_LN			0x00000000
+#define STB0899_BCH_BLOCK_LENGTH		(0xffff << 0)
+#define STB0899_OFFST_BCH_BLOCK_LENGTH		0
+#define STB0899_WIDTH_BCH_BLOCK_LENGTH		16
+
+#define STB0899_OFF0_BCH_T			0xfa28
+#define STB0899_BASE_BCH_T			0x00000000
+#define STB0899_BCH_T				(0x0f << 0)
+#define STB0899_OFFST_BCH_T			0
+#define STB0899_WIDTH_BCH_T			4
+
+#define STB0899_OFF0_CNFG_MODE			0xfa00
+#define STB0899_BASE_CNFG_MODE			0x00000800
+#define STB0899_MODCOD				(0x1f << 2)
+#define STB0899_OFFST_MODCOD			2
+#define STB0899_WIDTH_MODCOD			5
+#define STB0899_MODCOD_SEL			(0x01 << 1)
+#define STB0899_OFFST_MODCOD_SEL		1
+#define STB0899_WIDTH_MODCOD_SEL		1
+#define STB0899_CONFIG_MODE			(0x01 << 0)
+#define STB0899_OFFST_CONFIG_MODE		0
+#define STB0899_WIDTH_CONFIG_MODE		1
+
+#define STB0899_OFF0_LDPC_STAT			0xfa04
+#define STB0899_BASE_LDPC_STAT			0x00000800
+#define STB0899_ITERATION			(0xff << 3)
+#define STB0899_OFFST_ITERATION			3
+#define STB0899_WIDTH_ITERATION			8
+#define STB0899_LDPC_DEC_STATE			(0x07 << 0)
+#define STB0899_OFFST_LDPC_DEC_STATE		0
+#define STB0899_WIDTH_LDPC_DEC_STATE		3
+
+#define STB0899_OFF0_ITER_SCALE			0xfa08
+#define STB0899_BASE_ITER_SCALE			0x00000800
+#define STB0899_ITERATION_SCALE			(0xff << 0)
+#define STB0899_OFFST_ITERATION_SCALE		0
+#define STB0899_WIDTH_ITERATION_SCALE		8
+
+#define STB0899_OFF0_INPUT_MODE			0xfa0c
+#define STB0899_BASE_INPUT_MODE			0x00000800
+#define STB0899_SD_BLOCK1_STREAM0		(0x01 << 0)
+#define STB0899_OFFST_SD_BLOCK1_STREAM0		0
+#define STB0899_WIDTH_SD_BLOCK1_STREAM0		1
+
+#define STB0899_OFF0_LDPCDECRST			0xfa10
+#define STB0899_BASE_LDPCDECRST			0x00000800
+#define STB0899_LDPC_DEC_RST			(0x01 << 0)
+#define STB0899_OFFST_LDPC_DEC_RST		0
+#define STB0899_WIDTH_LDPC_DEC_RST		1
+
+#define STB0899_OFF0_CLK_PER_BYTE_RW		0xfa14
+#define STB0899_BASE_CLK_PER_BYTE_RW		0x00000800
+#define STB0899_CLKS_PER_BYTE			(0x0f << 0)
+#define STB0899_OFFST_CLKS_PER_BYTE		0
+#define STB0899_WIDTH_CLKS_PER_BYTE		5
+
+#define STB0899_OFF0_BCH_ERRORS			0xfa18
+#define STB0899_BASE_BCH_ERRORS			0x00000800
+#define STB0899_BCH_ERRORS			(0x0f << 0)
+#define STB0899_OFFST_BCH_ERRORS		0
+#define STB0899_WIDTH_BCH_ERRORS		4
+
+#define STB0899_OFF0_LDPC_ERRORS		0xfa1c
+#define STB0899_BASE_LDPC_ERRORS		0x00000800
+#define STB0899_LDPC_ERRORS			(0xffff << 0)
+#define STB0899_OFFST_LDPC_ERRORS		0
+#define STB0899_WIDTH_LDPC_ERRORS		16
+
+#define STB0899_OFF0_BCH_MODE			0xfa20
+#define STB0899_BASE_BCH_MODE			0x00000800
+#define STB0899_BCH_CORRECT_N			(0x01 << 1)
+#define STB0899_OFFST_BCH_CORRECT_N		1
+#define STB0899_WIDTH_BCH_CORRECT_N		1
+#define STB0899_FULL_BYPASS			(0x01 << 0)
+#define STB0899_OFFST_FULL_BYPASS		0
+#define STB0899_WIDTH_FULL_BYPASS		1
+
+#define STB0899_OFF0_ERR_ACC_PER		0xfa24
+#define STB0899_BASE_ERR_ACC_PER		0x00000800
+#define STB0899_BCH_ERR_ACC_PERIOD		(0x0f << 0)
+#define STB0899_OFFST_BCH_ERR_ACC_PERIOD	0
+#define STB0899_WIDTH_BCH_ERR_ACC_PERIOD	4
+
+#define STB0899_OFF0_BCH_ERR_ACC		0xfa28
+#define STB0899_BASE_BCH_ERR_ACC		0x00000800
+#define STB0899_BCH_ERR_ACCUM			(0xff << 0)
+#define STB0899_OFFST_BCH_ERR_ACCUM		0
+#define STB0899_WIDTH_BCH_ERR_ACCUM		8
+
+#define STB0899_OFF0_FEC_CORE_ID_REG		0xfa2c
+#define STB0899_BASE_FEC_CORE_ID_REG		0x00000800
+#define STB0899_FEC_CORE_ID			(0xffffffff << 0)
+#define STB0899_OFFST_FEC_CORE_ID		0
+#define STB0899_WIDTH_FEC_CORE_ID		32
+
+#define STB0899_OFF0_FEC_VER_ID_REG		0xfa34
+#define STB0899_BASE_FEC_VER_ID_REG		0x00000800
+#define STB0899_FEC_VER_ID			(0xff << 0)
+#define STB0899_OFFST_FEC_VER_ID		0
+#define STB0899_WIDTH_FEC_VER_ID		8
+
+#define STB0899_OFF0_FEC_TP_SEL			0xfa38
+#define STB0899_BASE_FEC_TP_SEL			0x00000800
+
+#define STB0899_OFF0_CSM_CNTRL1			0xf310
+#define STB0899_BASE_CSM_CNTRL1			0x00000400
+#define STB0899_CSM_FORCE_FREQLOCK		(0x01 << 19)
+#define STB0899_OFFST_CSM_FORCE_FREQLOCK	19
+#define STB0899_WIDTH_CSM_FORCE_FREQLOCK	1
+#define STB0899_CSM_FREQ_LOCKSTATE		(0x01 << 18)
+#define STB0899_OFFST_CSM_FREQ_LOCKSTATE	18
+#define STB0899_WIDTH_CSM_FREQ_LOCKSTATE	1
+#define STB0899_CSM_AUTO_PARAM			(0x01 << 17)
+#define STB0899_OFFST_CSM_AUTO_PARAM		17
+#define STB0899_WIDTH_CSM_AUTO_PARAM		1
+#define STB0899_FE_LOOP_SHIFT			(0x07 << 14)
+#define STB0899_OFFST_FE_LOOP_SHIFT		14
+#define STB0899_WIDTH_FE_LOOP_SHIFT		3
+#define STB0899_CSM_AGC_SHIFT			(0x07 << 11)
+#define STB0899_OFFST_CSM_AGC_SHIFT		11
+#define STB0899_WIDTH_CSM_AGC_SHIFT		3
+#define STB0899_CSM_AGC_GAIN			(0x1ff << 2)
+#define STB0899_OFFST_CSM_AGC_GAIN		2
+#define STB0899_WIDTH_CSM_AGC_GAIN		9
+#define STB0899_CSM_TWO_PASS			(0x01 << 1)
+#define STB0899_OFFST_CSM_TWO_PASS		1
+#define STB0899_WIDTH_CSM_TWO_PASS		1
+#define STB0899_CSM_DVT_TABLE			(0x01 << 0)
+#define STB0899_OFFST_CSM_DVT_TABLE		0
+#define STB0899_WIDTH_CSM_DVT_TABLE		1
+
+#define STB0899_OFF0_CSM_CNTRL2			0xf314
+#define STB0899_BASE_CSM_CNTRL2			0x00000400
+#define STB0899_CSM_GAMMA_RHO_ACQ		(0x1ff << 9)
+#define STB0899_OFFST_CSM_GAMMA_RHOACQ		9
+#define STB0899_WIDTH_CSM_GAMMA_RHOACQ		9
+#define STB0899_CSM_GAMMA_ACQ			(0x1ff << 0)
+#define STB0899_OFFST_CSM_GAMMA_ACQ		0
+#define STB0899_WIDTH_CSM_GAMMA_ACQ		9
+
+#define STB0899_OFF0_CSM_CNTRL3			0xf318
+#define STB0899_BASE_CSM_CNTRL3			0x00000400
+#define STB0899_CSM_GAMMA_RHO_TRACK		(0x1ff << 9)
+#define STB0899_OFFST_CSM_GAMMA_RHOTRACK	9
+#define STB0899_WIDTH_CSM_GAMMA_RHOTRACK	9
+#define STB0899_CSM_GAMMA_TRACK			(0x1ff << 0)
+#define STB0899_OFFST_CSM_GAMMA_TRACK		0
+#define STB0899_WIDTH_CSM_GAMMA_TRACK		9
+
+#define STB0899_OFF0_CSM_CNTRL4			0xf31c
+#define STB0899_BASE_CSM_CNTRL4			0x00000400
+#define STB0899_CSM_PHASEDIFF_THRESH		(0x0f << 8)
+#define STB0899_OFFST_CSM_PHASEDIFF_THRESH	8
+#define STB0899_WIDTH_CSM_PHASEDIFF_THRESH	4
+#define STB0899_CSM_LOCKCOUNT_THRESH		(0xff << 0)
+#define STB0899_OFFST_CSM_LOCKCOUNT_THRESH	0
+#define STB0899_WIDTH_CSM_LOCKCOUNT_THRESH	8
+
+/*	Check on chapter 8 page 42	*/
+#define STB0899_ERRCTRL1			0xf574
+#define STB0899_ERRCTRL2			0xf575
+#define STB0899_ERRCTRL3			0xf576
+#define STB0899_ERR_SRC_S1			(0x1f << 3)
+#define STB0899_OFFST_ERR_SRC_S1		3
+#define STB0899_WIDTH_ERR_SRC_S1		5
+#define STB0899_ERR_SRC_S2			(0x0f << 0)
+#define STB0899_OFFST_ERR_SRC_S2		0
+#define STB0899_WIDTH_ERR_SRC_S2		4
+#define STB0899_NOE				(0x07 << 0)
+#define STB0899_OFFST_NOE			0
+#define STB0899_WIDTH_NOE			3
+
+#define STB0899_ECNT1M				0xf524
+#define STB0899_ECNT1L				0xf525
+#define STB0899_ECNT2M				0xf526
+#define STB0899_ECNT2L				0xf527
+#define STB0899_ECNT3M				0xf528
+#define STB0899_ECNT3L				0xf529
+
+#define STB0899_DMONMSK1			0xf57b
+#define STB0899_DMONMSK1_WAIT_1STEP		(1 << 7)
+#define STB0899_DMONMSK1_FREE_14		(1 << 6)
+#define STB0899_DMONMSK1_AVRGVIT_CALC		(1 << 5)
+#define STB0899_DMONMSK1_FREE_12		(1 << 4)
+#define STB0899_DMONMSK1_FREE_11		(1 << 3)
+#define STB0899_DMONMSK1_B0DIV_CALC		(1 << 2)
+#define STB0899_DMONMSK1_KDIVB1_CALC		(1 << 1)
+#define STB0899_DMONMSK1_KDIVB2_CALC		(1 << 0)
+
+#define STB0899_DMONMSK0			0xf57c
+#define STB0899_DMONMSK0_SMOTTH_CALC		(1 << 7)
+#define STB0899_DMONMSK0_FREE_6			(1 << 6)
+#define STB0899_DMONMSK0_SIGPOWER_CALC		(1 << 5)
+#define STB0899_DMONMSK0_QSEUIL_CALC		(1 << 4)
+#define STB0899_DMONMSK0_FREE_3			(1 << 3)
+#define STB0899_DMONMSK0_FREE_2			(1 << 2)
+#define STB0899_DMONMSK0_KVDIVB1_CALC		(1 << 1)
+#define STB0899_DMONMSK0_KVDIVB2_CALC		(1 << 0)
+
+#define STB0899_TSULC				0xf549
+#define STB0899_ULNOSYNCBYTES			(0x01 << 7)
+#define STB0899_OFFST_ULNOSYNCBYTES		7
+#define STB0899_WIDTH_ULNOSYNCBYTES		1
+#define STB0899_ULPARITY_ON			(0x01 << 6)
+#define STB0899_OFFST_ULPARITY_ON		6
+#define STB0899_WIDTH_ULPARITY_ON		1
+#define STB0899_ULSYNCOUTRS			(0x01 << 5)
+#define STB0899_OFFST_ULSYNCOUTRS		5
+#define STB0899_WIDTH_ULSYNCOUTRS		1
+#define STB0899_ULDSS_PACKETS			(0x01 << 0)
+#define STB0899_OFFST_ULDSS_PACKETS		0
+#define STB0899_WIDTH_ULDSS_PACKETS		1
+
+#define STB0899_TSLPL				0xf54b
+#define STB0899_LLDVBS2_MODE			(0x01 << 4)
+#define STB0899_OFFST_LLDVBS2_MODE		4
+#define STB0899_WIDTH_LLDVBS2_MODE		1
+#define STB0899_LLISSYI_ON			(0x01 << 3)
+#define STB0899_OFFST_LLISSYI_ON		3
+#define STB0899_WIDTH_LLISSYI_ON		1
+#define STB0899_LLNPD_ON			(0x01 << 2)
+#define STB0899_OFFST_LLNPD_ON			2
+#define STB0899_WIDTH_LLNPD_ON			1
+#define STB0899_LLCRC8_ON			(0x01 << 1)
+#define STB0899_OFFST_LLCRC8_ON			1
+#define STB0899_WIDTH_LLCRC8_ON			1
+
+#define STB0899_TSCFGH				0xf54c
+#define STB0899_OUTRS_PS			(0x01 << 6)
+#define STB0899_OFFST_OUTRS_PS			6
+#define STB0899_WIDTH_OUTRS_PS			1
+#define STB0899_SYNCBYTE			(0x01 << 5)
+#define STB0899_OFFST_SYNCBYTE			5
+#define STB0899_WIDTH_SYNCBYTE			1
+#define STB0899_PFBIT				(0x01 << 4)
+#define STB0899_OFFST_PFBIT			4
+#define STB0899_WIDTH_PFBIT			1
+#define STB0899_ERR_BIT				(0x01 << 3)
+#define STB0899_OFFST_ERR_BIT			3
+#define STB0899_WIDTH_ERR_BIT			1
+#define STB0899_MPEG				(0x01 << 2)
+#define STB0899_OFFST_MPEG			2
+#define STB0899_WIDTH_MPEG			1
+#define STB0899_CLK_POL				(0x01 << 1)
+#define STB0899_OFFST_CLK_POL			1
+#define STB0899_WIDTH_CLK_POL			1
+#define STB0899_FORCE0				(0x01 << 0)
+#define STB0899_OFFST_FORCE0			0
+#define STB0899_WIDTH_FORCE0			1
+
+#define STB0899_TSCFGM				0xf54d
+#define STB0899_LLPRIORITY			(0x01 << 3)
+#define STB0899_OFFST_LLPRIORIY			3
+#define STB0899_WIDTH_LLPRIORITY		1
+#define STB0899_EN188				(0x01 << 2)
+#define STB0899_OFFST_EN188			2
+#define STB0899_WIDTH_EN188			1
+
+#define STB0899_TSCFGL				0xf54e
+#define STB0899_DEL_ERRPCK			(0x01 << 7)
+#define STB0899_OFFST_DEL_ERRPCK		7
+#define STB0899_WIDTH_DEL_ERRPCK		1
+#define STB0899_ERRFLAGSTD			(0x01 << 5)
+#define STB0899_OFFST_ERRFLAGSTD		5
+#define STB0899_WIDTH_ERRFLAGSTD		1
+#define STB0899_MPEGERR				(0x01 << 4)
+#define STB0899_OFFST_MPEGERR			4
+#define STB0899_WIDTH_MPEGERR			1
+#define STB0899_BCH_CHK				(0x01 << 3)
+#define STB0899_OFFST_BCH_CHK			5
+#define STB0899_WIDTH_BCH_CHK			1
+#define STB0899_CRC8CHK				(0x01 << 2)
+#define STB0899_OFFST_CRC8CHK			2
+#define STB0899_WIDTH_CRC8CHK			1
+#define STB0899_SPEC_INFO			(0x01 << 1)
+#define STB0899_OFFST_SPEC_INFO			1
+#define STB0899_WIDTH_SPEC_INFO			1
+#define STB0899_LOW_PRIO_CLK			(0x01 << 0)
+#define STB0899_OFFST_LOW_PRIO_CLK		0
+#define STB0899_WIDTH_LOW_PRIO_CLK		1
+#define STB0899_ERROR_NORM			(0x00 << 0)
+#define STB0899_OFFST_ERROR_NORM		0
+#define STB0899_WIDTH_ERROR_NORM		0
+
+#define STB0899_TSOUT				0xf54f
+#define STB0899_RSSYNCDEL			0xf550
+#define STB0899_TSINHDELH			0xf551
+#define STB0899_TSINHDELM			0xf552
+#define STB0899_TSINHDELL			0xf553
+#define STB0899_TSLLSTKM			0xf55a
+#define STB0899_TSLLSTKL			0xf55b
+#define STB0899_TSULSTKM			0xf55c
+#define STB0899_TSULSTKL			0xf55d
+#define STB0899_TSSTATUS			0xf561
+
+#define STB0899_PDELCTRL			0xf600
+#define STB0899_INVERT_RES			(0x01 << 7)
+#define STB0899_OFFST_INVERT_RES		7
+#define STB0899_WIDTH_INVERT_RES		1
+#define STB0899_FORCE_ACCEPTED			(0x01 << 6)
+#define STB0899_OFFST_FORCE_ACCEPTED		6
+#define STB0899_WIDTH_FORCE_ACCEPTED		1
+#define STB0899_FILTER_EN			(0x01 << 5)
+#define STB0899_OFFST_FILTER_EN			5
+#define STB0899_WIDTH_FILTER_EN			1
+#define STB0899_LOCKFALL_THRESH			(0x01 << 4)
+#define STB0899_OFFST_LOCKFALL_THRESH		4
+#define STB0899_WIDTH_LOCKFALL_THRESH		1
+#define STB0899_HYST_EN				(0x01 << 3)
+#define STB0899_OFFST_HYST_EN			3
+#define STB0899_WIDTH_HYST_EN			1
+#define STB0899_HYST_SWRST			(0x01 << 2)
+#define STB0899_OFFST_HYST_SWRST		2
+#define STB0899_WIDTH_HYST_SWRST		1
+#define STB0899_ALGO_EN				(0x01 << 1)
+#define STB0899_OFFST_ALGO_EN			1
+#define STB0899_WIDTH_ALGO_EN			1
+#define STB0899_ALGO_SWRST			(0x01 << 0)
+#define STB0899_OFFST_ALGO_SWRST		0
+#define STB0899_WIDTH_ALGO_SWRST		1
+
+#define STB0899_PDELCTRL2			0xf601
+#define STB0899_BBHCTRL1			0xf602
+#define STB0899_BBHCTRL2			0xf603
+#define STB0899_HYSTTHRESH			0xf604
+
+#define STB0899_MATCSTM				0xf605
+#define STB0899_MATCSTL				0xf606
+#define STB0899_UPLCSTM				0xf607
+#define STB0899_UPLCSTL				0xf608
+#define STB0899_DFLCSTM				0xf609
+#define STB0899_DFLCSTL				0xf60a
+#define STB0899_SYNCCST				0xf60b
+#define STB0899_SYNCDCSTM			0xf60c
+#define STB0899_SYNCDCSTL			0xf60d
+#define STB0899_ISI_ENTRY			0xf60e
+#define STB0899_ISI_BIT_EN			0xf60f
+#define STB0899_MATSTRM				0xf610
+#define STB0899_MATSTRL				0xf611
+#define STB0899_UPLSTRM				0xf612
+#define STB0899_UPLSTRL				0xf613
+#define STB0899_DFLSTRM				0xf614
+#define STB0899_DFLSTRL				0xf615
+#define STB0899_SYNCSTR				0xf616
+#define STB0899_SYNCDSTRM			0xf617
+#define STB0899_SYNCDSTRL			0xf618
+
+#define STB0899_CFGPDELSTATUS1			0xf619
+#define STB0899_BADDFL				(0x01 << 6)
+#define STB0899_OFFST_BADDFL			6
+#define STB0899_WIDTH_BADDFL			1
+#define STB0899_CONTINUOUS_STREAM		(0x01 << 5)
+#define STB0899_OFFST_CONTINUOUS_STREAM		5
+#define STB0899_WIDTH_CONTINUOUS_STREAM		1
+#define STB0899_ACCEPTED_STREAM			(0x01 << 4)
+#define STB0899_OFFST_ACCEPTED_STREAM		4
+#define STB0899_WIDTH_ACCEPTED_STREAM		1
+#define STB0899_BCH_ERRFLAG			(0x01 << 3)
+#define STB0899_OFFST_BCH_ERRFLAG		3
+#define STB0899_WIDTH_BCH_ERRFLAG		1
+#define STB0899_CRCRES				(0x01 << 2)
+#define STB0899_OFFST_CRCRES			2
+#define STB0899_WIDTH_CRCRES			1
+#define STB0899_CFGPDELSTATUS_LOCK		(0x01 << 1)
+#define STB0899_OFFST_CFGPDELSTATUS_LOCK	1
+#define STB0899_WIDTH_CFGPDELSTATUS_LOCK	1
+#define STB0899_1STLOCK				(0x01 << 0)
+#define STB0899_OFFST_1STLOCK			0
+#define STB0899_WIDTH_1STLOCK			1
+
+#define STB0899_CFGPDELSTATUS2			0xf61a
+#define STB0899_BBFERRORM			0xf61b
+#define STB0899_BBFERRORL			0xf61c
+#define STB0899_UPKTERRORM			0xf61d
+#define STB0899_UPKTERRORL			0xf61e
+
+#define STB0899_TSTCK				0xff10
+
+#define STB0899_TSTRES				0xff11
+#define STB0899_FRESLDPC			(0x01 << 7)
+#define STB0899_OFFST_FRESLDPC			7
+#define STB0899_WIDTH_FRESLDPC			1
+#define STB0899_FRESRS				(0x01 << 6)
+#define STB0899_OFFST_FRESRS			6
+#define STB0899_WIDTH_FRESRS			1
+#define STB0899_FRESVIT				(0x01 << 5)
+#define STB0899_OFFST_FRESVIT			5
+#define STB0899_WIDTH_FRESVIT			1
+#define STB0899_FRESMAS1_2			(0x01 << 4)
+#define STB0899_OFFST_FRESMAS1_2		4
+#define STB0899_WIDTH_FRESMAS1_2		1
+#define STB0899_FRESACS				(0x01 << 3)
+#define STB0899_OFFST_FRESACS			3
+#define STB0899_WIDTH_FRESACS			1
+#define STB0899_FRESSYM				(0x01 << 2)
+#define STB0899_OFFST_FRESSYM			2
+#define STB0899_WIDTH_FRESSYM			1
+#define STB0899_FRESMAS				(0x01 << 1)
+#define STB0899_OFFST_FRESMAS			1
+#define STB0899_WIDTH_FRESMAS			1
+#define STB0899_FRESINT				(0x01 << 0)
+#define STB0899_OFFST_FRESINIT			0
+#define STB0899_WIDTH_FRESINIT			1
+
+#define STB0899_TSTOUT				0xff12
+#define STB0899_EN_SIGNATURE			(0x01 << 7)
+#define STB0899_OFFST_EN_SIGNATURE		7
+#define STB0899_WIDTH_EN_SIGNATURE		1
+#define STB0899_BCLK_CLK			(0x01 << 6)
+#define STB0899_OFFST_BCLK_CLK			6
+#define STB0899_WIDTH_BCLK_CLK			1
+#define STB0899_SGNL_OUT			(0x01 << 5)
+#define STB0899_OFFST_SGNL_OUT			5
+#define STB0899_WIDTH_SGNL_OUT			1
+#define STB0899_TS				(0x01 << 4)
+#define STB0899_OFFST_TS			4
+#define STB0899_WIDTH_TS			1
+#define STB0899_CTEST				(0x01 << 0)
+#define STB0899_OFFST_CTEST			0
+#define STB0899_WIDTH_CTEST			1
+
+#define STB0899_TSTIN				0xff13
+#define STB0899_TEST_IN				(0x01 << 7)
+#define STB0899_OFFST_TEST_IN			7
+#define STB0899_WIDTH_TEST_IN			1
+#define STB0899_EN_ADC				(0x01 << 6)
+#define STB0899_OFFST_EN_ADC			6
+#define STB0899_WIDTH_ENADC			1
+#define STB0899_SGN_ADC				(0x01 << 5)
+#define STB0899_OFFST_SGN_ADC			5
+#define STB0899_WIDTH_SGN_ADC			1
+#define STB0899_BCLK_IN				(0x01 << 4)
+#define STB0899_OFFST_BCLK_IN			4
+#define STB0899_WIDTH_BCLK_IN			1
+#define STB0899_JETONIN_MODE			(0x01 << 3)
+#define STB0899_OFFST_JETONIN_MODE		3
+#define STB0899_WIDTH_JETONIN_MODE		1
+#define STB0899_BCLK_VALUE			(0x01 << 2)
+#define STB0899_OFFST_BCLK_VALUE		2
+#define STB0899_WIDTH_BCLK_VALUE		1
+#define STB0899_SGNRST_T12			(0x01 << 1)
+#define STB0899_OFFST_SGNRST_T12		1
+#define STB0899_WIDTH_SGNRST_T12		1
+#define STB0899_LOWSP_ENAX			(0x01 << 0)
+#define STB0899_OFFST_LOWSP_ENAX		0
+#define STB0899_WIDTH_LOWSP_ENAX		1
+
+#define STB0899_TSTSYS				0xff14
+#define STB0899_TSTCHIP				0xff15
+#define STB0899_TSTFREE				0xff16
+#define STB0899_TSTI2C				0xff17
+#define STB0899_BITSPEEDM			0xff1c
+#define STB0899_BITSPEEDL			0xff1d
+#define STB0899_TBUSBIT				0xff1e
+#define STB0899_TSTDIS				0xff24
+#define STB0899_TSTDISRX			0xff25
+#define STB0899_TSTJETON			0xff28
+#define STB0899_TSTDCADJ			0xff40
+#define STB0899_TSTAGC1				0xff41
+#define STB0899_TSTAGC1N			0xff42
+#define STB0899_TSTPOLYPH			0xff48
+#define STB0899_TSTR				0xff49
+#define STB0899_TSTAGC2				0xff4a
+#define STB0899_TSTCTL1				0xff4b
+#define STB0899_TSTCTL2				0xff4c
+#define STB0899_TSTCTL3				0xff4d
+#define STB0899_TSTDEMAP			0xff50
+#define STB0899_TSTDEMAP2			0xff51
+#define STB0899_TSTDEMMON			0xff52
+#define STB0899_TSTRATE				0xff53
+#define STB0899_TSTSELOUT			0xff54
+#define STB0899_TSYNC				0xff55
+#define STB0899_TSTERR				0xff56
+#define STB0899_TSTRAM1				0xff58
+#define STB0899_TSTVSELOUT			0xff59
+#define STB0899_TSTFORCEIN			0xff5a
+#define STB0899_TSTRS1				0xff5c
+#define STB0899_TSTRS2				0xff5d
+#define STB0899_TSTRS3				0xff53
+
+#define STB0899_INTBUFSTATUS			0xf200
+#define STB0899_INTBUFCTRL			0xf201
+#define STB0899_PCKLENUL			0xf55e
+#define STB0899_PCKLENLL			0xf55f
+#define STB0899_RSPCKLEN			0xf560
+
+/*	2 registers	*/
+#define STB0899_SYNCDCST			0xf60c
+
+/*	DiSEqC	*/
+#define STB0899_DISCNTRL1			0xf0a0
+#define STB0899_TIMOFF				(0x01 << 7)
+#define STB0899_OFFST_TIMOFF			7
+#define STB0899_WIDTH_TIMOFF			1
+#define STB0899_DISEQCRESET			(0x01 << 6)
+#define STB0899_OFFST_DISEQCRESET		6
+#define STB0899_WIDTH_DISEQCRESET		1
+#define STB0899_TIMCMD				(0x03 << 4)
+#define STB0899_OFFST_TIMCMD			4
+#define STB0899_WIDTH_TIMCMD			2
+#define STB0899_DISPRECHARGE			(0x01 << 2)
+#define STB0899_OFFST_DISPRECHARGE		2
+#define STB0899_WIDTH_DISPRECHARGE		1
+#define STB0899_DISEQCMODE			(0x03 << 0)
+#define STB0899_OFFST_DISEQCMODE		0
+#define STB0899_WIDTH_DISEQCMODE		2
+
+#define STB0899_DISCNTRL2			0xf0a1
+#define STB0899_RECEIVER_ON			(0x01 << 7)
+#define STB0899_OFFST_RECEIVER_ON		7
+#define STB0899_WIDTH_RECEIVER_ON		1
+#define STB0899_IGNO_SHORT_22K			(0x01 << 6)
+#define STB0899_OFFST_IGNO_SHORT_22K		6
+#define STB0899_WIDTH_IGNO_SHORT_22K		1
+#define STB0899_ONECHIP_TRX			(0x01 << 5)
+#define STB0899_OFFST_ONECHIP_TRX		5
+#define STB0899_WIDTH_ONECHIP_TRX		1
+#define STB0899_EXT_ENVELOP			(0x01 << 4)
+#define STB0899_OFFST_EXT_ENVELOP		4
+#define STB0899_WIDTH_EXT_ENVELOP		1
+#define STB0899_PIN_SELECT			(0x03 << 2)
+#define STB0899_OFFST_PIN_SELCT			2
+#define STB0899_WIDTH_PIN_SELCT			2
+#define STB0899_IRQ_RXEND			(0x01 << 1)
+#define STB0899_OFFST_IRQ_RXEND			1
+#define STB0899_WIDTH_IRQ_RXEND			1
+#define STB0899_IRQ_4NBYTES			(0x01 << 0)
+#define STB0899_OFFST_IRQ_4NBYTES		0
+#define STB0899_WIDTH_IRQ_4NBYTES		1
+
+#define STB0899_DISRX_ST0			0xf0a4
+#define STB0899_RXEND				(0x01 << 7)
+#define STB0899_OFFST_RXEND			7
+#define STB0899_WIDTH_RXEND			1
+#define STB0899_RXACTIVE			(0x01 << 6)
+#define STB0899_OFFST_RXACTIVE			6
+#define STB0899_WIDTH_RXACTIVE			1
+#define STB0899_SHORT22K			(0x01 << 5)
+#define STB0899_OFFST_SHORT22K			5
+#define STB0899_WIDTH_SHORT22K			1
+#define STB0899_CONTTONE			(0x01 << 4)
+#define STB0899_OFFST_CONTTONE			4
+#define STB0899_WIDTH_CONTONE			1
+#define STB0899_4BFIFOREDY			(0x01 << 3)
+#define STB0899_OFFST_4BFIFOREDY		3
+#define STB0899_WIDTH_4BFIFOREDY		1
+#define STB0899_FIFOEMPTY			(0x01 << 2)
+#define STB0899_OFFST_FIFOEMPTY			2
+#define STB0899_WIDTH_FIFOEMPTY			1
+#define STB0899_ABORTTRX			(0x01 << 0)
+#define STB0899_OFFST_ABORTTRX			0
+#define STB0899_WIDTH_ABORTTRX			1
+
+#define STB0899_DISRX_ST1			0xf0a5
+#define STB0899_RXFAIL				(0x01 << 7)
+#define STB0899_OFFST_RXFAIL			7
+#define STB0899_WIDTH_RXFAIL			1
+#define STB0899_FIFOPFAIL			(0x01 << 6)
+#define STB0899_OFFST_FIFOPFAIL			6
+#define STB0899_WIDTH_FIFOPFAIL			1
+#define STB0899_RXNONBYTES			(0x01 << 5)
+#define STB0899_OFFST_RXNONBYTES		5
+#define STB0899_WIDTH_RXNONBYTES		1
+#define STB0899_FIFOOVF				(0x01 << 4)
+#define STB0899_OFFST_FIFOOVF			4
+#define STB0899_WIDTH_FIFOOVF			1
+#define STB0899_FIFOBYTENBR			(0x0f << 0)
+#define STB0899_OFFST_FIFOBYTENBR		0
+#define STB0899_WIDTH_FIFOBYTENBR		4
+
+#define STB0899_DISPARITY			0xf0a6
+
+#define STB0899_DISFIFO				0xf0a7
+
+#define STB0899_DISSTATUS			0xf0a8
+#define STB0899_FIFOFULL			(0x01 << 6)
+#define STB0899_OFFST_FIFOFULL			6
+#define STB0899_WIDTH_FIFOFULL			1
+#define STB0899_TXIDLE				(0x01 << 5)
+#define STB0899_OFFST_TXIDLE			5
+#define STB0899_WIDTH_TXIDLE			1
+#define STB0899_GAPBURST			(0x01 << 4)
+#define STB0899_OFFST_GAPBURST			4
+#define STB0899_WIDTH_GAPBURST			1
+#define STB0899_TXFIFOBYTES			(0x0f << 0)
+#define STB0899_OFFST_TXFIFOBYTES		0
+#define STB0899_WIDTH_TXFIFOBYTES		4
+#define STB0899_DISF22				0xf0a9
+
+#define STB0899_DISF22RX			0xf0aa
+
+/*	General Purpose	*/
+#define STB0899_SYSREG				0xf101
+#define STB0899_ACRPRESC			0xf110
+#define STB0899_OFFST_RSVD2			7
+#define STB0899_WIDTH_RSVD2			1
+#define STB0899_OFFST_ACRPRESC			4
+#define STB0899_WIDTH_ACRPRESC			3
+#define STB0899_OFFST_RSVD1			3
+#define STB0899_WIDTH_RSVD1			1
+#define STB0899_OFFST_ACRPRESC2			0
+#define STB0899_WIDTH_ACRPRESC2			3
+
+#define STB0899_ACRDIV1				0xf111
+#define STB0899_ACRDIV2				0xf112
+#define STB0899_DACR1				0xf113
+#define STB0899_DACR2				0xf114
+#define STB0899_OUTCFG				0xf11c
+#define STB0899_MODECFG				0xf11d
+#define STB0899_NCOARSE				0xf1b3
+
+#define STB0899_SYNTCTRL			0xf1b6
+#define STB0899_STANDBY				(0x01 << 7)
+#define STB0899_OFFST_STANDBY			7
+#define STB0899_WIDTH_STANDBY			1
+#define STB0899_BYPASSPLL			(0x01 << 6)
+#define STB0899_OFFST_BYPASSPLL			6
+#define STB0899_WIDTH_BYPASSPLL			1
+#define STB0899_SEL1XRATIO			(0x01 << 5)
+#define STB0899_OFFST_SEL1XRATIO		5
+#define STB0899_WIDTH_SEL1XRATIO		1
+#define STB0899_SELOSCI				(0x01 << 1)
+#define STB0899_OFFST_SELOSCI			1
+#define STB0899_WIDTH_SELOSCI			1
+
+#define STB0899_FILTCTRL			0xf1b7
+#define STB0899_SYSCTRL				0xf1b8
+
+#define STB0899_STOPCLK1			0xf1c2
+#define STB0899_STOP_CKINTBUF108		(0x01 << 7)
+#define STB0899_OFFST_STOP_CKINTBUF108		7
+#define STB0899_WIDTH_STOP_CKINTBUF108		1
+#define STB0899_STOP_CKINTBUF216		(0x01 << 6)
+#define STB0899_OFFST_STOP_CKINTBUF216		6
+#define STB0899_WIDTH_STOP_CKINTBUF216		1
+#define STB0899_STOP_CHK8PSK			(0x01 << 5)
+#define STB0899_OFFST_STOP_CHK8PSK		5
+#define STB0899_WIDTH_STOP_CHK8PSK		1
+#define STB0899_STOP_CKFEC108			(0x01 << 4)
+#define STB0899_OFFST_STOP_CKFEC108		4
+#define STB0899_WIDTH_STOP_CKFEC108		1
+#define STB0899_STOP_CKFEC216			(0x01 << 3)
+#define STB0899_OFFST_STOP_CKFEC216		3
+#define STB0899_WIDTH_STOP_CKFEC216		1
+#define STB0899_STOP_CKCORE216			(0x01 << 2)
+#define STB0899_OFFST_STOP_CKCORE216		2
+#define STB0899_WIDTH_STOP_CKCORE216		1
+#define STB0899_STOP_CKADCI108			(0x01 << 1)
+#define STB0899_OFFST_STOP_CKADCI108		1
+#define STB0899_WIDTH_STOP_CKADCI108		1
+#define STB0899_STOP_INVCKADCI108		(0x01 << 0)
+#define STB0899_OFFST_STOP_INVCKADCI108		0
+#define STB0899_WIDTH_STOP_INVCKADCI108		1
+
+#define STB0899_STOPCLK2			0xf1c3
+#define STB0899_STOP_CKS2DMD108			(0x01 << 2)
+#define STB0899_OFFST_STOP_CKS2DMD108		2
+#define STB0899_WIDTH_STOP_CKS2DMD108		1
+#define STB0899_STOP_CKPKDLIN108		(0x01 << 1)
+#define STB0899_OFFST_STOP_CKPKDLIN108		1
+#define STB0899_WIDTH_STOP_CKPKDLIN108		1
+#define STB0899_STOP_CKPKDLIN216		(0x01 << 0)
+#define STB0899_OFFST_STOP_CKPKDLIN216		0
+#define STB0899_WIDTH_STOP_CKPKDLIN216		1
+
+#define STB0899_TSTTNR1				0xf1e0
+#define STB0899_BYPASS_ADC			(0x01 << 7)
+#define STB0899_OFFST_BYPASS_ADC		7
+#define STB0899_WIDTH_BYPASS_ADC		1
+#define STB0899_INVADCICKOUT			(0x01 << 6)
+#define STB0899_OFFST_INVADCICKOUT		6
+#define STB0899_WIDTH_INVADCICKOUT		1
+#define STB0899_ADCTEST_VOLTAGE			(0x03 << 4)
+#define STB0899_OFFST_ADCTEST_VOLTAGE		4
+#define STB0899_WIDTH_ADCTEST_VOLTAGE		1
+#define STB0899_ADC_RESET			(0x01 << 3)
+#define STB0899_OFFST_ADC_RESET			3
+#define STB0899_WIDTH_ADC_RESET			1
+#define STB0899_TSTTNR1_2			(0x01 << 2)
+#define STB0899_OFFST_TSTTNR1_2			2
+#define STB0899_WIDTH_TSTTNR1_2			1
+#define STB0899_ADCPON				(0x01 << 1)
+#define STB0899_OFFST_ADCPON			1
+#define STB0899_WIDTH_ADCPON			1
+#define STB0899_ADCIN_MODE			(0x01 << 0)
+#define STB0899_OFFST_ADCIN_MODE		0
+#define STB0899_WIDTH_ADCIN_MODE		1
+
+#define STB0899_TSTTNR2				0xf1e1
+#define STB0899_TSTTNR2_7			(0x01 << 7)
+#define STB0899_OFFST_TSTTNR2_7			7
+#define STB0899_WIDTH_TSTTNR2_7			1
+#define STB0899_NOT_DISRX_WIRED			(0x01 << 6)
+#define STB0899_OFFST_NOT_DISRX_WIRED		6
+#define STB0899_WIDTH_NOT_DISRX_WIRED		1
+#define STB0899_DISEQC_DCURRENT			(0x01 << 5)
+#define STB0899_OFFST_DISEQC_DCURRENT		5
+#define STB0899_WIDTH_DISEQC_DCURRENT		1
+#define STB0899_DISEQC_ZCURRENT			(0x01 << 4)
+#define STB0899_OFFST_DISEQC_ZCURRENT		4
+#define STB0899_WIDTH_DISEQC_ZCURRENT		1
+#define STB0899_DISEQC_SINC_SOURCE		(0x03 << 2)
+#define STB0899_OFFST_DISEQC_SINC_SOURCE	2
+#define STB0899_WIDTH_DISEQC_SINC_SOURCE	2
+#define STB0899_SELIQSRC			(0x03 << 0)
+#define STB0899_OFFST_SELIQSRC			0
+#define STB0899_WIDTH_SELIQSRC			2
+
+#define STB0899_TSTTNR3				0xf1e2
+
+#define STB0899_I2CCFG				0xf129
+#define STB0899_I2CCFGRSVD			(0x0f << 4)
+#define STB0899_OFFST_I2CCFGRSVD		4
+#define STB0899_WIDTH_I2CCFGRSVD		4
+#define STB0899_I2CFASTMODE			(0x01 << 3)
+#define STB0899_OFFST_I2CFASTMODE		3
+#define STB0899_WIDTH_I2CFASTMODE		1
+#define STB0899_STATUSWR			(0x01 << 2)
+#define STB0899_OFFST_STATUSWR			2
+#define STB0899_WIDTH_STATUSWR			1
+#define STB0899_I2CADDRINC			(0x03 << 0)
+#define STB0899_OFFST_I2CADDRINC		0
+#define STB0899_WIDTH_I2CADDRINC		2
+
+#define STB0899_I2CRPT				0xf12a
+#define STB0899_I2CTON				(0x01 << 7)
+#define STB0899_OFFST_I2CTON			7
+#define STB0899_WIDTH_I2CTON			1
+#define STB0899_ENARPTLEVEL			(0x01 << 6)
+#define STB0899_OFFST_ENARPTLEVEL		6
+#define STB0899_WIDTH_ENARPTLEVEL		2
+#define STB0899_SCLTDELAY			(0x01 << 3)
+#define STB0899_OFFST_SCLTDELAY			3
+#define STB0899_WIDTH_SCLTDELAY			1
+#define STB0899_STOPENA				(0x01 << 2)
+#define STB0899_OFFST_STOPENA			2
+#define STB0899_WIDTH_STOPENA			1
+#define STB0899_STOPSDAT2SDA			(0x01 << 1)
+#define STB0899_OFFST_STOPSDAT2SDA		1
+#define STB0899_WIDTH_STOPSDAT2SDA		1
+
+#define STB0899_IOPVALUE8			0xf136
+#define STB0899_IOPVALUE7			0xf137
+#define STB0899_IOPVALUE6			0xf138
+#define STB0899_IOPVALUE5			0xf139
+#define STB0899_IOPVALUE4			0xf13a
+#define STB0899_IOPVALUE3			0xf13b
+#define STB0899_IOPVALUE2			0xf13c
+#define STB0899_IOPVALUE1			0xf13d
+#define STB0899_IOPVALUE0			0xf13e
+
+#define STB0899_GPIO00CFG			0xf140
+
+#define STB0899_GPIO01CFG			0xf141
+#define STB0899_GPIO02CFG			0xf142
+#define STB0899_GPIO03CFG			0xf143
+#define STB0899_GPIO04CFG			0xf144
+#define STB0899_GPIO05CFG			0xf145
+#define STB0899_GPIO06CFG			0xf146
+#define STB0899_GPIO07CFG			0xf147
+#define STB0899_GPIO08CFG			0xf148
+#define STB0899_GPIO09CFG			0xf149
+#define STB0899_GPIO10CFG			0xf14a
+#define STB0899_GPIO11CFG			0xf14b
+#define STB0899_GPIO12CFG			0xf14c
+#define STB0899_GPIO13CFG			0xf14d
+#define STB0899_GPIO14CFG			0xf14e
+#define STB0899_GPIO15CFG			0xf14f
+#define STB0899_GPIO16CFG			0xf150
+#define STB0899_GPIO17CFG			0xf151
+#define STB0899_GPIO18CFG			0xf152
+#define STB0899_GPIO19CFG			0xf153
+#define STB0899_GPIO20CFG			0xf154
+
+#define STB0899_SDATCFG				0xf155
+#define STB0899_SCLTCFG				0xf156
+#define STB0899_AGCRFCFG			0xf157
+#define STB0899_GPIO22				0xf158	/* AGCBB2CFG	*/
+#define STB0899_GPIO21				0xf159  /* AGCBB1CFG	*/
+#define STB0899_DIRCLKCFG			0xf15a
+#define STB0899_CLKOUT27CFG			0xf15b
+#define STB0899_STDBYCFG			0xf15c
+#define STB0899_CS0CFG				0xf15d
+#define STB0899_CS1CFG				0xf15e
+#define STB0899_DISEQCOCFG			0xf15f
+
+#define STB0899_GPIO32CFG			0xf160
+#define STB0899_GPIO33CFG			0xf161
+#define STB0899_GPIO34CFG			0xf162
+#define STB0899_GPIO35CFG			0xf163
+#define STB0899_GPIO36CFG			0xf164
+#define STB0899_GPIO37CFG			0xf165
+#define STB0899_GPIO38CFG			0xf166
+#define STB0899_GPIO39CFG			0xf167
+
+#define STB0899_IRQSTATUS_3			0xf120
+#define STB0899_IRQSTATUS_2			0xf121
+#define STB0899_IRQSTATUS_1			0xf122
+#define STB0899_IRQSTATUS_0			0xf123
+
+#define STB0899_IRQMSK_3			0xf124
+#define STB0899_IRQMSK_2			0xf125
+#define STB0899_IRQMSK_1			0xf126
+#define STB0899_IRQMSK_0			0xf127
+
+#define STB0899_IRQCFG				0xf128
+
+#define STB0899_GHOSTREG			0xf000
+
+#define STB0899_S2DEMOD				0xf3fc
+#define STB0899_S2FEC				0xfafc
+
+
+#endif

+ 545 - 0
drivers/media/dvb/frontends/stb6100.c

@@ -0,0 +1,545 @@
+/*
+	STB6100 Silicon Tuner
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "dvb_frontend.h"
+#include "stb6100.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+
+
+#define FE_ERROR		0
+#define FE_NOTICE		1
+#define FE_INFO			2
+#define FE_DEBUG		3
+
+#define dprintk(x, y, z, format, arg...) do {						\
+	if (z) {									\
+		if	((x > FE_ERROR) && (x > y))					\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((x > FE_NOTICE) && (x > y))					\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((x > FE_INFO) && (x > y))					\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((x > FE_DEBUG) && (x > y))					\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (x > y)								\
+			printk(format, ##arg);						\
+	}										\
+} while(0)
+
+struct stb6100_lkup {
+	u32 val_low;
+	u32 val_high;
+	u8   reg;
+};
+
+static int stb6100_release(struct dvb_frontend *fe);
+
+static const struct stb6100_lkup lkup[] = {
+	{       0,  950000, 0x0a },
+	{  950000, 1000000, 0x0a },
+	{ 1000000, 1075000, 0x0c },
+	{ 1075000, 1200000, 0x00 },
+	{ 1200000, 1300000, 0x01 },
+	{ 1300000, 1370000, 0x02 },
+	{ 1370000, 1470000, 0x04 },
+	{ 1470000, 1530000, 0x05 },
+	{ 1530000, 1650000, 0x06 },
+	{ 1650000, 1800000, 0x08 },
+	{ 1800000, 1950000, 0x0a },
+	{ 1950000, 2150000, 0x0c },
+	{ 2150000, 9999999, 0x0c },
+	{       0,       0, 0x00 }
+};
+
+/* Register names for easy debugging.	*/
+static const char *stb6100_regnames[] = {
+	[STB6100_LD]		= "LD",
+	[STB6100_VCO]		= "VCO",
+	[STB6100_NI]		= "NI",
+	[STB6100_NF_LSB]	= "NF",
+	[STB6100_K]		= "K",
+	[STB6100_G]		= "G",
+	[STB6100_F]		= "F",
+	[STB6100_DLB]		= "DLB",
+	[STB6100_TEST1]		= "TEST1",
+	[STB6100_FCCK]		= "FCCK",
+	[STB6100_LPEN]		= "LPEN",
+	[STB6100_TEST3]		= "TEST3",
+};
+
+/* Template for normalisation, i.e. setting unused or undocumented
+ * bits as required according to the documentation.
+ */
+struct stb6100_regmask {
+	u8 mask;
+	u8 set;
+};
+
+static const struct stb6100_regmask stb6100_template[] = {
+	[STB6100_LD]		= { 0xff, 0x00 },
+	[STB6100_VCO]		= { 0xff, 0x00 },
+	[STB6100_NI]		= { 0xff, 0x00 },
+	[STB6100_NF_LSB]	= { 0xff, 0x00 },
+	[STB6100_K]		= { 0xc7, 0x38 },
+	[STB6100_G]		= { 0xef, 0x10 },
+	[STB6100_F]		= { 0x1f, 0xc0 },
+	[STB6100_DLB]		= { 0x38, 0xc4 },
+	[STB6100_TEST1]		= { 0x00, 0x8f },
+	[STB6100_FCCK]		= { 0x40, 0x0d },
+	[STB6100_LPEN]		= { 0xf0, 0x0b },
+	[STB6100_TEST3]		= { 0x00, 0xde },
+};
+
+static void stb6100_normalise_regs(u8 regs[])
+{
+	int i;
+
+	for (i = 0; i < STB6100_NUMREGS; i++)
+		regs[i] = (regs[i] & stb6100_template[i].mask) | stb6100_template[i].set;
+}
+
+static int stb6100_read_regs(struct stb6100_state *state, u8 regs[])
+{
+	int rc;
+	struct i2c_msg msg = {
+		.addr	= state->config->tuner_address,
+		.flags	= I2C_M_RD,
+		.buf	= regs,
+		.len	= STB6100_NUMREGS
+	};
+
+	rc = i2c_transfer(state->i2c, &msg, 1);
+	if (unlikely(rc != 1)) {
+		dprintk(verbose, FE_ERROR, 1, "Read (0x%x) err, rc=[%d]",
+			state->config->tuner_address, rc);
+
+		return -EREMOTEIO;
+	}
+	if (unlikely(verbose > FE_DEBUG)) {
+		int i;
+
+		dprintk(verbose, FE_DEBUG, 1, "    Read from 0x%02x", state->config->tuner_address);
+		for (i = 0; i < STB6100_NUMREGS; i++)
+			dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[i], regs[i]);
+	}
+	return 0;
+}
+
+static int stb6100_read_reg(struct stb6100_state *state, u8 reg)
+{
+	u8 regs[STB6100_NUMREGS];
+	int rc;
+
+	if (unlikely(reg >= STB6100_NUMREGS)) {
+		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
+		return -EINVAL;
+	}
+	if ((rc = stb6100_read_regs(state, regs)) < 0)
+		return rc;
+	return (unsigned int)regs[reg];
+}
+
+static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int start, int len)
+{
+	int rc;
+	u8 cmdbuf[len + 1];
+	struct i2c_msg msg = {
+		.addr	= state->config->tuner_address,
+		.flags	= 0,
+		.buf	= cmdbuf,
+		.len	= len + 1
+	};
+
+	if (unlikely(start < 1 || start + len > STB6100_NUMREGS)) {
+		dprintk(verbose, FE_ERROR, 1, "Invalid register range %d:%d",
+			start, len);
+		return -EINVAL;
+	}
+	memcpy(&cmdbuf[1], buf, len);
+	cmdbuf[0] = start;
+
+	if (unlikely(verbose > FE_DEBUG)) {
+		int i;
+
+		dprintk(verbose, FE_DEBUG, 1, "    Write @ 0x%02x: [%d:%d]", state->config->tuner_address, start, len);
+		for (i = 0; i < len; i++)
+			dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[start + i], buf[i]);
+	}
+	rc = i2c_transfer(state->i2c, &msg, 1);
+	if (unlikely(rc != 1)) {
+		dprintk(verbose, FE_ERROR, 1, "(0x%x) write err [%d:%d], rc=[%d]",
+			(unsigned int)state->config->tuner_address, start, len,	rc);
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
+{
+	if (unlikely(reg >= STB6100_NUMREGS)) {
+		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
+		return -EREMOTEIO;
+	}
+	data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
+	return stb6100_write_reg_range(state, &data, reg, 1);
+}
+
+static int stb6100_write_regs(struct stb6100_state *state, u8 regs[])
+{
+	stb6100_normalise_regs(regs);
+	return stb6100_write_reg_range(state, &regs[1], 1, STB6100_NUMREGS - 1);
+}
+
+static int stb6100_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	int rc;
+	struct stb6100_state *state = fe->tuner_priv;
+
+	if ((rc = stb6100_read_reg(state, STB6100_LD)) < 0)
+		return rc;
+
+	return (rc & STB6100_LD_LOCK) ? TUNER_STATUS_LOCKED : 0;
+}
+
+static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	int rc;
+	u8 f;
+	struct stb6100_state *state = fe->tuner_priv;
+
+	if ((rc = stb6100_read_reg(state, STB6100_F)) < 0)
+		return rc;
+	f = rc & STB6100_F_F;
+
+	state->status.bandwidth = (f + 5) * 2000;	/* x2 for ZIF	*/
+
+	*bandwidth = state->bandwidth = state->status.bandwidth * 1000;
+	dprintk(verbose, FE_DEBUG, 1, "bandwidth = %u Hz", state->bandwidth);
+	return 0;
+}
+
+static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+	u32 tmp;
+	int rc;
+	struct stb6100_state *state = fe->tuner_priv;
+
+	dprintk(verbose, FE_DEBUG, 1, "set bandwidth to %u Hz", bandwidth);
+
+	bandwidth /= 2; /* ZIF */
+
+	if (bandwidth >= 36000000)	/* F[4:0] BW/2 max =31+5=36 mhz for F=31	*/
+		tmp = 31;
+	else if (bandwidth <= 5000000)	/* bw/2 min = 5Mhz for F=0			*/
+		tmp = 0;
+	else				/* if 5 < bw/2 < 36				*/
+		tmp = (bandwidth + 500000) / 1000000 - 5;
+
+	/* Turn on LPF bandwidth setting clock control,
+	 * set bandwidth, wait 10ms, turn off.
+	 */
+	if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK)) < 0)
+		return rc;
+	if ((rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp)) < 0)
+		return rc;
+	msleep(1);
+	if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d)) < 0)
+		return rc;
+
+	return 0;
+}
+
+static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	int rc;
+	u32 nint, nfrac, fvco;
+	int psd2, odiv;
+	struct stb6100_state *state = fe->tuner_priv;
+	u8 regs[STB6100_NUMREGS];
+
+	if ((rc = stb6100_read_regs(state, regs)) < 0)
+		return rc;
+
+	odiv = (regs[STB6100_VCO] & STB6100_VCO_ODIV) >> STB6100_VCO_ODIV_SHIFT;
+	psd2 = (regs[STB6100_K] & STB6100_K_PSD2) >> STB6100_K_PSD2_SHIFT;
+	nint = regs[STB6100_NI];
+	nfrac = ((regs[STB6100_K] & STB6100_K_NF_MSB) << 8) | regs[STB6100_NF_LSB];
+	fvco = (nfrac * state->reference >> (9 - psd2)) + (nint * state->reference << psd2);
+	*frequency = state->frequency = fvco >> (odiv + 1);
+
+	dprintk(verbose, FE_DEBUG, 1,
+		"frequency = %u kHz, odiv = %u, psd2 = %u, fxtal = %u kHz, fvco = %u kHz, N(I) = %u, N(F) = %u",
+		state->frequency, odiv, psd2, state->reference,	fvco, nint, nfrac);
+	return 0;
+}
+
+
+static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	int rc;
+	const struct stb6100_lkup *ptr;
+	struct stb6100_state *state = fe->tuner_priv;
+	struct dvb_frontend_parameters p;
+
+	u32 srate = 0, fvco, nint, nfrac;
+	u8 regs[STB6100_NUMREGS];
+	u8 g, psd2, odiv;
+
+	if ((rc = stb6100_read_regs(state, regs)) < 0)
+		return rc;
+
+	if (fe->ops.get_frontend) {
+		dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters");
+		fe->ops.get_frontend(fe, &p);
+	}
+	srate = p.u.qpsk.symbol_rate;
+
+	regs[STB6100_DLB] = 0xdc;
+	/* Disable LPEN */
+	regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN; /* PLL Loop disabled */
+
+	if ((rc = stb6100_write_regs(state, regs)) < 0)
+		return rc;
+
+	/* Baseband gain.	*/
+	if (srate >= 15000000)
+		g = 9;  //  +4 dB
+	else if (srate >= 5000000)
+		g = 11; //  +8 dB
+	else
+		g = 14; // +14 dB
+
+	regs[STB6100_G] = (regs[STB6100_G] & ~STB6100_G_G) | g;
+	regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */
+	regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */
+
+	/* VCO divide ratio (LO divide ratio, VCO prescaler enable).	*/
+	if (frequency <= 1075000)
+		odiv = 1;
+	else
+		odiv = 0;
+	regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_ODIV) | (odiv << STB6100_VCO_ODIV_SHIFT);
+
+	if ((frequency > 1075000) && (frequency <= 1325000))
+		psd2 = 0;
+	else
+		psd2 = 1;
+	regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT);
+
+	/* OSM	*/
+	for (ptr = lkup;
+	     (ptr->val_high != 0) && !CHKRANGE(frequency, ptr->val_low, ptr->val_high);
+	     ptr++);
+	if (ptr->val_high == 0) {
+		printk(KERN_ERR "%s: frequency out of range: %u kHz\n", __func__, frequency);
+		return -EINVAL;
+	}
+	regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_OSM) | ptr->reg;
+
+	/* F(VCO) = F(LO) * (ODIV == 0 ? 2 : 4)			*/
+	fvco = frequency << (1 + odiv);
+	/* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1)))	*/
+	nint = fvco / (state->reference << psd2);
+	/* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9	*/
+	nfrac = (((fvco - (nint * state->reference << psd2)) << (9 - psd2)) + state->reference / 2) / state->reference;
+	dprintk(verbose, FE_DEBUG, 1,
+		"frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u",
+		frequency, srate, (unsigned int)g, (unsigned int)odiv,
+		(unsigned int)psd2, state->reference,
+		ptr->reg, fvco, nint, nfrac);
+	regs[STB6100_NI] = nint;
+	regs[STB6100_NF_LSB] = nfrac;
+	regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB);
+	regs[STB6100_VCO] |= STB6100_VCO_OSCH;		/* VCO search enabled		*/
+	regs[STB6100_VCO] |= STB6100_VCO_OCK;		/* VCO search clock off		*/
+	regs[STB6100_FCCK] |= STB6100_FCCK_FCCK;	/* LPF BW setting clock enabled	*/
+	regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN;	/* PLL loop disabled		*/
+	/* Power up. */
+	regs[STB6100_LPEN] |= STB6100_LPEN_SYNP	| STB6100_LPEN_OSCP | STB6100_LPEN_BEN;
+
+	msleep(2);
+	if ((rc = stb6100_write_regs(state, regs)) < 0)
+		return rc;
+
+	msleep(2);
+	regs[STB6100_LPEN] |= STB6100_LPEN_LPEN;	/* PLL loop enabled		*/
+	if ((rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN])) < 0)
+		return rc;
+
+	regs[STB6100_VCO] &= ~STB6100_VCO_OCK;		/* VCO fast search		*/
+	if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0)
+		return rc;
+
+	msleep(10);					/* wait for LO to lock		*/
+	regs[STB6100_VCO] &= ~STB6100_VCO_OSCH;		/* vco search disabled		*/
+	regs[STB6100_VCO] |= STB6100_VCO_OCK;		/* search clock off		*/
+	if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0)
+		return rc;
+	regs[STB6100_FCCK] &= ~STB6100_FCCK_FCCK;       /* LPF BW clock disabled	*/
+	stb6100_normalise_regs(regs);
+	if ((rc = stb6100_write_reg_range(state, &regs[1], 1, STB6100_NUMREGS - 3)) < 0)
+		return rc;
+
+	msleep(100);
+
+	return 0;
+}
+
+static int stb6100_sleep(struct dvb_frontend *fe)
+{
+	/* TODO: power down	*/
+	return 0;
+}
+
+static int stb6100_init(struct dvb_frontend *fe)
+{
+	struct stb6100_state *state = fe->tuner_priv;
+	struct tuner_state *status = &state->status;
+
+	status->tunerstep	= 125000;
+	status->ifreq		= 0;
+	status->refclock	= 27000000;	/* Hz	*/
+	status->iqsense		= 1;
+	status->bandwidth	= 36000;	/* kHz	*/
+	state->bandwidth	= status->bandwidth * 1000;	/* MHz	*/
+	state->reference	= status->refclock / 1000;	/* kHz	*/
+
+	/* Set default bandwidth.	*/
+	return stb6100_set_bandwidth(fe, status->bandwidth);
+}
+
+static int stb6100_get_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *state)
+{
+	switch (param) {
+	case DVBFE_TUNER_FREQUENCY:
+		stb6100_get_frequency(fe, &state->frequency);
+		break;
+	case DVBFE_TUNER_TUNERSTEP:
+		break;
+	case DVBFE_TUNER_IFFREQ:
+		break;
+	case DVBFE_TUNER_BANDWIDTH:
+		stb6100_get_bandwidth(fe, &state->bandwidth);
+		break;
+	case DVBFE_TUNER_REFCLOCK:
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int stb6100_set_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *state)
+{
+	struct stb6100_state *tstate = fe->tuner_priv;
+
+	switch (param) {
+	case DVBFE_TUNER_FREQUENCY:
+		stb6100_set_frequency(fe, state->frequency);
+		tstate->frequency = state->frequency;
+		break;
+	case DVBFE_TUNER_TUNERSTEP:
+		break;
+	case DVBFE_TUNER_IFFREQ:
+		break;
+	case DVBFE_TUNER_BANDWIDTH:
+		stb6100_set_bandwidth(fe, state->bandwidth);
+		tstate->bandwidth = state->bandwidth;
+		break;
+	case DVBFE_TUNER_REFCLOCK:
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static struct dvb_tuner_ops stb6100_ops = {
+	.info = {
+		.name			= "STB6100 Silicon Tuner",
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_step		= 0,
+	},
+
+	.init		= stb6100_init,
+	.sleep          = stb6100_sleep,
+	.get_status	= stb6100_get_status,
+	.get_state	= stb6100_get_state,
+	.set_state	= stb6100_set_state,
+	.release	= stb6100_release
+};
+
+struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+				    struct stb6100_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct stb6100_state *state = NULL;
+
+	state = kzalloc(sizeof (struct stb6100_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->config		= config;
+	state->i2c		= i2c;
+	state->frontend		= fe;
+	state->reference	= config->refclock / 1000; /* kHz */
+	fe->tuner_priv		= state;
+	fe->ops.tuner_ops	= stb6100_ops;
+
+	printk("%s: Attaching STB6100 \n", __func__);
+	return fe;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static int stb6100_release(struct dvb_frontend *fe)
+{
+	struct stb6100_state *state = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(state);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(stb6100_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STB6100 Silicon tuner");
+MODULE_LICENSE("GPL");

+ 115 - 0
drivers/media/dvb/frontends/stb6100.h

@@ -0,0 +1,115 @@
+/*
+	STB6100 Silicon Tuner
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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 __STB_6100_REG_H
+#define __STB_6100_REG_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#define STB6100_LD			0x00
+#define STB6100_LD_LOCK			(1 << 0)
+
+#define STB6100_VCO			0x01
+#define STB6100_VCO_OSCH		(0x01 << 7)
+#define STB6100_VCO_OSCH_SHIFT		7
+#define STB6100_VCO_OCK			(0x03 << 5)
+#define STB6100_VCO_OCK_SHIFT		5
+#define STB6100_VCO_ODIV		(0x01 << 4)
+#define STB6100_VCO_ODIV_SHIFT		4
+#define STB6100_VCO_OSM			(0x0f << 0)
+
+#define STB6100_NI			0x02
+#define STB6100_NF_LSB			0x03
+
+#define STB6100_K			0x04
+#define STB6100_K_PSD2			(0x01 << 2)
+#define STB6100_K_PSD2_SHIFT            2
+#define STB6100_K_NF_MSB		(0x03 << 0)
+
+#define STB6100_G			0x05
+#define STB6100_G_G			(0x0f << 0)
+#define STB6100_G_GCT			(0x07 << 5)
+
+#define STB6100_F			0x06
+#define STB6100_F_F			(0x1f << 0)
+
+#define STB6100_DLB			0x07
+
+#define STB6100_TEST1			0x08
+
+#define STB6100_FCCK			0x09
+#define STB6100_FCCK_FCCK		(0x01 << 6)
+
+#define STB6100_LPEN			0x0a
+#define STB6100_LPEN_LPEN		(0x01 << 4)
+#define STB6100_LPEN_SYNP		(0x01 << 5)
+#define STB6100_LPEN_OSCP		(0x01 << 6)
+#define STB6100_LPEN_BEN		(0x01 << 7)
+
+#define STB6100_TEST3			0x0b
+
+#define STB6100_NUMREGS                 0x0c
+
+
+#define INRANGE(val, x, y)		(((x <= val) && (val <= y)) ||		\
+					 ((y <= val) && (val <= x)) ? 1 : 0)
+
+#define CHKRANGE(val, x, y)		(((val >= x) && (val < y)) ? 1 : 0)
+
+struct stb6100_config {
+	u8	tuner_address;
+	u32	refclock;
+};
+
+struct stb6100_state {
+	struct i2c_adapter *i2c;
+
+	const struct stb6100_config	*config;
+	struct dvb_tuner_ops		ops;
+	struct dvb_frontend		*frontend;
+	struct tuner_state		status;
+
+	u32 frequency;
+	u32 srate;
+	u32 bandwidth;
+	u32 reference;
+};
+
+#if defined(CONFIG_DVB_STB6100) || (defined(CONFIG_DVB_STB6100_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+					   struct stb6100_config *config,
+					   struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+						  struct stb6100_config *config,
+						  struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif //CONFIG_DVB_STB6100
+
+#endif

+ 108 - 0
drivers/media/dvb/frontends/stb6100_cfg.h

@@ -0,0 +1,108 @@
+/*
+	STB6100 Silicon Tuner
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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.
+*/
+
+static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_state) {
+		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+		*frequency = t_state.frequency;
+		printk("%s: Frequency=%d\n", __func__, t_state.frequency);
+	}
+	return 0;
+}
+
+static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	t_state.frequency = frequency;
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->set_state) {
+		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+	}
+	printk("%s: Frequency=%d\n", __func__, t_state.frequency);
+	return 0;
+}
+
+static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_state) {
+		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+		*bandwidth = t_state.bandwidth;
+	}
+	printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
+	return 0;
+}
+
+static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	t_state.bandwidth = bandwidth;
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->set_state) {
+		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+	}
+	printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
+	return 0;
+}

+ 230 - 0
drivers/media/dvb/frontends/tda8261.c

@@ -0,0 +1,230 @@
+/*
+	TDA8261 8PSK/QPSK tuner driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "dvb_frontend.h"
+#include "tda8261.h"
+
+struct tda8261_state {
+	struct dvb_frontend		*fe;
+	struct i2c_adapter		*i2c;
+	const struct tda8261_config	*config;
+
+	/* state cache */
+	u32 frequency;
+	u32 bandwidth;
+};
+
+static int tda8261_read(struct tda8261_state *state, u8 *buf)
+{
+	const struct tda8261_config *config = state->config;
+	int err = 0;
+	struct i2c_msg msg = { .addr	= config->addr, .flags = I2C_M_RD,.buf = buf,  .len = 2 };
+
+	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
+		printk("%s: read error, err=%d\n", __func__, err);
+
+	return err;
+}
+
+static int tda8261_write(struct tda8261_state *state, u8 *buf)
+{
+	const struct tda8261_config *config = state->config;
+	int err = 0;
+	struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = 4 };
+
+	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
+		printk("%s: write error, err=%d\n", __func__, err);
+
+	return err;
+}
+
+static int tda8261_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct tda8261_state *state = fe->tuner_priv;
+	u8 result = 0;
+	int err = 0;
+
+	*status = 0;
+
+	if ((err = tda8261_read(state, &result)) < 0) {
+		printk("%s: I/O Error\n", __func__);
+		return err;
+	}
+	if ((result >> 6) & 0x01) {
+		printk("%s: Tuner Phase Locked\n", __func__);
+		*status = 1;
+	}
+
+	return err;
+}
+
+static const u32 div_tab[] = { 2000, 1000,  500,  250,  125 }; /* kHz */
+static const u8  ref_div[] = { 0x00, 0x01, 0x02, 0x05, 0x07 };
+
+static int tda8261_get_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *tstate)
+{
+	struct tda8261_state *state = fe->tuner_priv;
+	int err = 0;
+
+	switch (param) {
+	case DVBFE_TUNER_FREQUENCY:
+		tstate->frequency = state->frequency;
+		break;
+	case DVBFE_TUNER_BANDWIDTH:
+		tstate->bandwidth = 40000000; /* FIXME! need to calculate Bandwidth */
+		break;
+	default:
+		printk("%s: Unknown parameter (param=%d)\n", __func__, param);
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+static int tda8261_set_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *tstate)
+{
+	struct tda8261_state *state = fe->tuner_priv;
+	const struct tda8261_config *config = state->config;
+	u32 frequency, N, status = 0;
+	u8 buf[4];
+	int err = 0;
+
+	if (param & DVBFE_TUNER_FREQUENCY) {
+		/**
+		 * N = Max VCO Frequency / Channel Spacing
+		 * Max VCO Frequency = VCO frequency + (channel spacing - 1)
+		 * (to account for half channel spacing on either side)
+		 */
+		frequency = tstate->frequency;
+		if ((frequency < 950000) || (frequency > 2150000)) {
+			printk("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
+			return -EINVAL;
+		}
+		N = (frequency + (div_tab[config->step_size] - 1)) / div_tab[config->step_size];
+		printk("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n",
+			__func__, config->step_size, div_tab[config->step_size], N, N);
+
+		buf[0] = (N >> 8) & 0xff;
+		buf[1] = N & 0xff;
+		buf[2] = (0x01 << 7) | ((ref_div[config->step_size] & 0x07) << 1);
+
+		if (frequency < 1450000)
+			buf[3] = 0x00;
+		if (frequency < 2000000)
+			buf[3] = 0x40;
+		if (frequency < 2150000)
+			buf[3] = 0x80;
+
+		/* Set params */
+		if ((err = tda8261_write(state, buf)) < 0) {
+			printk("%s: I/O Error\n", __func__);
+			return err;
+		}
+		/* sleep for some time */
+		printk("%s: Waiting to Phase LOCK\n", __func__);
+		msleep(20);
+		/* check status */
+		if ((err = tda8261_get_status(fe, &status)) < 0) {
+			printk("%s: I/O Error\n", __func__);
+			return err;
+		}
+		if (status == 1) {
+			printk("%s: Tuner Phase locked: status=%d\n", __func__, status);
+			state->frequency = frequency; /* cache successful state */
+		} else {
+			printk("%s: No Phase lock: status=%d\n", __func__, status);
+		}
+	} else {
+		printk("%s: Unknown parameter (param=%d)\n", __func__, param);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tda8261_release(struct dvb_frontend *fe)
+{
+	struct tda8261_state *state = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(state);
+	return 0;
+}
+
+static struct dvb_tuner_ops tda8261_ops = {
+
+	.info = {
+		.name		= "TDA8261",
+//		.tuner_name	= NULL,
+		.frequency_min	=  950000,
+		.frequency_max	= 2150000,
+		.frequency_step = 0
+	},
+
+	.set_state	= tda8261_set_state,
+	.get_state	= tda8261_get_state,
+	.get_status	= tda8261_get_status,
+	.release	= tda8261_release
+};
+
+struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
+				    const struct tda8261_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct tda8261_state *state = NULL;
+
+	if ((state = kzalloc(sizeof (struct tda8261_state), GFP_KERNEL)) == NULL)
+		goto exit;
+
+	state->config		= config;
+	state->i2c		= i2c;
+	state->fe		= fe;
+	fe->tuner_priv		= state;
+	fe->ops.tuner_ops	= tda8261_ops;
+
+	fe->ops.tuner_ops.info.frequency_step = div_tab[config->step_size];
+//	fe->ops.tuner_ops.tuner_name	 = &config->buf;
+
+//	printk("%s: Attaching %s TDA8261 8PSK/QPSK tuner\n",
+//		__func__, fe->ops.tuner_ops.tuner_name);
+	printk("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__);
+
+	return fe;
+
+exit:
+	kfree(state);
+	return NULL;
+}
+
+EXPORT_SYMBOL(tda8261_attach);
+MODULE_PARM_DESC(verbose, "Set verbosity level");
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner");
+MODULE_LICENSE("GPL");

+ 55 - 0
drivers/media/dvb/frontends/tda8261.h

@@ -0,0 +1,55 @@
+/*
+	TDA8261 8PSK/QPSK tuner driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __TDA8261_H
+#define __TDA8261_H
+
+enum tda8261_step {
+	TDA8261_STEP_2000 = 0,	/* 2000 kHz */
+	TDA8261_STEP_1000,	/* 1000 kHz */
+	TDA8261_STEP_500,	/*  500 kHz */
+	TDA8261_STEP_250,	/*  250 kHz */
+	TDA8261_STEP_125	/*  125 kHz */
+};
+
+struct tda8261_config {
+//	u8			buf[16];
+	u8			addr;
+	enum tda8261_step	step_size;
+};
+
+#if defined(CONFIG_DVB_TDA8261) || (defined(CONFIG_DVB_TDA8261_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
+					   const struct tda8261_config *config,
+					   struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
+						  const struct tda8261_config *config,
+						  struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif //CONFIG_DVB_TDA8261
+
+#endif// __TDA8261_H

+ 84 - 0
drivers/media/dvb/frontends/tda8261_cfg.h

@@ -0,0 +1,84 @@
+/*
+	TDA8261 8PSK/QPSK tuner driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_state) {
+		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+		*frequency = t_state.frequency;
+		printk("%s: Frequency=%d\n", __func__, t_state.frequency);
+	}
+	return 0;
+}
+
+static int tda8261_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	t_state.frequency = frequency;
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->set_state) {
+		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+	}
+	printk("%s: Frequency=%d\n", __func__, t_state.frequency);
+	return 0;
+}
+
+static int tda8261_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_state) {
+		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+		*bandwidth = t_state.bandwidth;
+	}
+	printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
+	return 0;
+}

+ 3 - 0
drivers/media/dvb/frontends/zl10353.c

@@ -220,15 +220,18 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
 		/* These are extrapolated from the 7 and 8MHz values */
 		zl10353_single_write(fe, MCLK_RATIO, 0x97);
 		zl10353_single_write(fe, 0x64, 0x34);
+		zl10353_single_write(fe, 0xcc, 0xdd);
 		break;
 	case BANDWIDTH_7_MHZ:
 		zl10353_single_write(fe, MCLK_RATIO, 0x86);
 		zl10353_single_write(fe, 0x64, 0x35);
+		zl10353_single_write(fe, 0xcc, 0x73);
 		break;
 	case BANDWIDTH_8_MHZ:
 	default:
 		zl10353_single_write(fe, MCLK_RATIO, 0x75);
 		zl10353_single_write(fe, 0x64, 0x36);
+		zl10353_single_write(fe, 0xcc, 0x73);
 	}
 
 	zl10353_calc_nominal_rate(fe, op->bandwidth, &nominal_rate);

+ 110 - 0
drivers/media/dvb/siano/sms-cards.c

@@ -38,6 +38,16 @@ struct usb_device_id smsusb_id_table[] = {
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A },
 	{ USB_DEVICE(0x2040, 0x1801),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B },
+	{ USB_DEVICE(0x2040, 0x2000),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
+	{ USB_DEVICE(0x2040, 0x2009),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 },
+	{ USB_DEVICE(0x2040, 0x200a),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
+	{ USB_DEVICE(0x2040, 0x2010),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
+	{ USB_DEVICE(0x2040, 0x2019),
+		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD },
 	{ USB_DEVICE(0x2040, 0x5500),
 		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
 	{ USB_DEVICE(0x2040, 0x5510),
@@ -96,6 +106,21 @@ static struct sms_board sms_boards[] = {
 		.name	= "Hauppauge WinTV MiniStick",
 		.type	= SMS_NOVA_B0,
 		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.led_power = 26,
+		.led_lo    = 27,
+		.led_hi    = 28,
+	},
+	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = {
+		.name	= "Hauppauge WinTV MiniCard",
+		.type	= SMS_NOVA_B0,
+		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.lna_ctrl  = 29,
+	},
+	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = {
+		.name	= "Hauppauge WinTV MiniCard",
+		.type	= SMS_NOVA_B0,
+		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.lna_ctrl  = 1,
 	},
 };
 
@@ -106,3 +131,88 @@ struct sms_board *sms_get_board(int id)
 	return &sms_boards[id];
 }
 
+static int sms_set_gpio(struct smscore_device_t *coredev, u32 pin, int enable)
+{
+	int ret;
+	struct smscore_gpio_config gpioconfig = {
+		.direction            = SMS_GPIO_DIRECTION_OUTPUT,
+		.pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
+		.inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
+		.outputslewrate       = SMS_GPIO_OUTPUTSLEWRATE_FAST,
+		.outputdriving        = SMS_GPIO_OUTPUTDRIVING_4mA,
+	};
+
+	if (pin == 0)
+		return -EINVAL;
+
+	ret = smscore_configure_gpio(coredev, pin, &gpioconfig);
+
+	if (ret < 0)
+		return ret;
+
+	return smscore_set_gpio(coredev, pin, enable);
+}
+
+int sms_board_setup(struct smscore_device_t *coredev)
+{
+	int board_id = smscore_get_board_id(coredev);
+	struct sms_board *board = sms_get_board(board_id);
+
+	switch (board_id) {
+	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+		/* turn off all LEDs */
+		sms_set_gpio(coredev, board->led_power, 0);
+		sms_set_gpio(coredev, board->led_hi, 0);
+		sms_set_gpio(coredev, board->led_lo, 0);
+		break;
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+		/* turn off LNA */
+		sms_set_gpio(coredev, board->lna_ctrl, 0);
+		break;
+	}
+	return 0;
+}
+
+int sms_board_power(struct smscore_device_t *coredev, int onoff)
+{
+	int board_id = smscore_get_board_id(coredev);
+	struct sms_board *board = sms_get_board(board_id);
+
+	switch (board_id) {
+	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+		/* power LED */
+		sms_set_gpio(coredev,
+			     board->led_power, onoff ? 1 : 0);
+		break;
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+		/* LNA */
+		sms_set_gpio(coredev,
+			     board->lna_ctrl, onoff ? 1 : 0);
+		break;
+	}
+	return 0;
+}
+
+int sms_board_led_feedback(struct smscore_device_t *coredev, int led)
+{
+	int board_id = smscore_get_board_id(coredev);
+	struct sms_board *board = sms_get_board(board_id);
+
+	/* dont touch GPIO if LEDs are already set */
+	if (smscore_led_state(coredev, -1) == led)
+		return 0;
+
+	switch (board_id) {
+	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+		sms_set_gpio(coredev,
+			     board->led_lo, (led & SMS_LED_LO) ? 1 : 0);
+		sms_set_gpio(coredev,
+			     board->led_hi, (led & SMS_LED_HI) ? 1 : 0);
+
+		smscore_led_state(coredev, led);
+		break;
+	}
+	return 0;
+}

+ 13 - 0
drivers/media/dvb/siano/sms-cards.h

@@ -32,14 +32,27 @@
 #define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A 6
 #define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B 7
 #define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8
+#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9
+#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10
 
 struct sms_board {
 	enum sms_device_type_st type;
 	char *name, *fw[DEVICE_MODE_MAX];
+
+	/* gpios */
+	int led_power, led_hi, led_lo, lna_ctrl;
 };
 
 struct sms_board *sms_get_board(int id);
 
+int sms_board_setup(struct smscore_device_t *coredev);
+
+#define SMS_LED_OFF 0
+#define SMS_LED_LO  1
+#define SMS_LED_HI  2
+int sms_board_led_feedback(struct smscore_device_t *coredev, int led);
+int sms_board_power(struct smscore_device_t *coredev, int onoff);
+
 extern struct usb_device_id smsusb_id_table[];
 
 #endif /* __SMS_CARDS_H__ */

+ 78 - 0
drivers/media/dvb/siano/smscoreapi.c

@@ -91,6 +91,7 @@ struct smscore_device_t {
 	struct completion init_device_done, reload_start_done, resume_done;
 
 	int board_id;
+	int led_state;
 };
 
 void smscore_set_board_id(struct smscore_device_t *core, int id)
@@ -98,6 +99,13 @@ void smscore_set_board_id(struct smscore_device_t *core, int id)
 	core->board_id = id;
 }
 
+int smscore_led_state(struct smscore_device_t *core, int led)
+{
+	if (led >= 0)
+		core->led_state = led;
+	return core->led_state;
+}
+
 int smscore_get_board_id(struct smscore_device_t *core)
 {
 	return core->board_id;
@@ -1187,6 +1195,76 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 }
 
 
+int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
+			   struct smscore_gpio_config *pinconfig)
+{
+	struct {
+		struct SmsMsgHdr_ST hdr;
+		u32 data[6];
+	} msg;
+
+	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
+		msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+		msg.hdr.msgDstId = HIF_TASK;
+		msg.hdr.msgFlags = 0;
+		msg.hdr.msgType  = MSG_SMS_GPIO_CONFIG_EX_REQ;
+		msg.hdr.msgLength = sizeof(msg);
+
+		msg.data[0] = pin;
+		msg.data[1] = pinconfig->pullupdown;
+
+		/* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */
+		msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0;
+
+		switch (pinconfig->outputdriving) {
+		case SMS_GPIO_OUTPUTDRIVING_16mA:
+			msg.data[3] = 7; /* Nova - 16mA */
+			break;
+		case SMS_GPIO_OUTPUTDRIVING_12mA:
+			msg.data[3] = 5; /* Nova - 11mA */
+			break;
+		case SMS_GPIO_OUTPUTDRIVING_8mA:
+			msg.data[3] = 3; /* Nova - 7mA */
+			break;
+		case SMS_GPIO_OUTPUTDRIVING_4mA:
+		default:
+			msg.data[3] = 2; /* Nova - 4mA */
+			break;
+		}
+
+		msg.data[4] = pinconfig->direction;
+		msg.data[5] = 0;
+	} else /* TODO: SMS_DEVICE_FAMILY1 */
+		return -EINVAL;
+
+	return coredev->sendrequest_handler(coredev->context,
+					    &msg, sizeof(msg));
+}
+
+int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
+{
+	struct {
+		struct SmsMsgHdr_ST hdr;
+		u32 data[3];
+	} msg;
+
+	if (pin > MAX_GPIO_PIN_NUMBER)
+		return -EINVAL;
+
+	msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	msg.hdr.msgDstId = HIF_TASK;
+	msg.hdr.msgFlags = 0;
+	msg.hdr.msgType  = MSG_SMS_GPIO_SET_LEVEL_REQ;
+	msg.hdr.msgLength = sizeof(msg);
+
+	msg.data[0] = pin;
+	msg.data[1] = level ? 1 : 0;
+	msg.data[2] = 0;
+
+	return coredev->sendrequest_handler(coredev->context,
+					    &msg, sizeof(msg));
+}
+
 static int __init smscore_module_init(void)
 {
 	int rc = 0;

+ 35 - 1
drivers/media/dvb/siano/smscoreapi.h

@@ -186,6 +186,8 @@ struct smsclient_params_t {
 #define MSG_SW_RELOAD_EXEC_REQ				704
 #define MSG_SW_RELOAD_EXEC_RES				705
 #define MSG_SMS_SPI_INT_LINE_SET_REQ		710
+#define MSG_SMS_GPIO_CONFIG_EX_REQ			712
+#define MSG_SMS_GPIO_CONFIG_EX_RES			713
 #define MSG_SMS_ISDBT_TUNE_REQ				776
 #define MSG_SMS_ISDBT_TUNE_RES				777
 
@@ -341,6 +343,32 @@ struct SmsMsgStatisticsInfo_ST {
 };
 
 
+struct smscore_gpio_config {
+#define SMS_GPIO_DIRECTION_INPUT  0
+#define SMS_GPIO_DIRECTION_OUTPUT 1
+	u8 direction;
+
+#define SMS_GPIO_PULLUPDOWN_NONE     0
+#define SMS_GPIO_PULLUPDOWN_PULLDOWN 1
+#define SMS_GPIO_PULLUPDOWN_PULLUP   2
+#define SMS_GPIO_PULLUPDOWN_KEEPER   3
+	u8 pullupdown;
+
+#define SMS_GPIO_INPUTCHARACTERISTICS_NORMAL  0
+#define SMS_GPIO_INPUTCHARACTERISTICS_SCHMITT 1
+	u8 inputcharacteristics;
+
+#define SMS_GPIO_OUTPUTSLEWRATE_FAST 0
+#define SMS_GPIO_OUTPUTSLEWRATE_SLOW 1
+	u8 outputslewrate;
+
+#define SMS_GPIO_OUTPUTDRIVING_4mA  0
+#define SMS_GPIO_OUTPUTDRIVING_8mA  1
+#define SMS_GPIO_OUTPUTDRIVING_12mA 2
+#define SMS_GPIO_OUTPUTDRIVING_16mA 3
+	u8 outputdriving;
+};
+
 struct smsdvb_client_t {
 	struct list_head entry;
 
@@ -353,7 +381,7 @@ struct smsdvb_client_t {
 	struct dvb_frontend	frontend;
 
 	fe_status_t		fe_status;
-	int			fe_ber, fe_snr, fe_signal_strength;
+	int			fe_ber, fe_snr, fe_unc, fe_signal_strength;
 
 	struct completion	tune_done, stat_done;
 
@@ -396,9 +424,15 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev);
 extern void smscore_putbuffer(struct smscore_device_t *coredev,
 			      struct smscore_buffer_t *cb);
 
+int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
+			   struct smscore_gpio_config *pinconfig);
+int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
+
 void smscore_set_board_id(struct smscore_device_t *core, int id);
 int smscore_get_board_id(struct smscore_device_t *core);
 
+int smscore_led_state(struct smscore_device_t *core, int led);
+
 /* smsdvb.c */
 int smsdvb_register(void);
 void smsdvb_unregister(void);

+ 54 - 2
drivers/media/dvb/siano/smsdvb.c

@@ -60,6 +60,7 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
 
 			client->fe_snr = p->Stat.SNR;
 			client->fe_ber = p->Stat.BER;
+			client->fe_unc = p->Stat.BERErrorCount;
 
 			if (p->Stat.InBandPwr < -95)
 				client->fe_signal_strength = 0;
@@ -72,6 +73,7 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
 			client->fe_status = 0;
 			client->fe_snr =
 			client->fe_ber =
+			client->fe_unc =
 			client->fe_signal_strength = 0;
 		}
 
@@ -165,8 +167,18 @@ static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
 	struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
 			     DVBT_BDA_CONTROL_MSG_ID,
 			     HIF_TASK, sizeof(struct SmsMsgHdr_ST), 0 };
-	return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-					   &client->stat_done);
+	int ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+					      &client->stat_done);
+	if (ret < 0)
+		return ret;
+
+	if (client->fe_status & FE_HAS_LOCK)
+		sms_board_led_feedback(client->coredev,
+				       (client->fe_unc == 0) ?
+				       SMS_LED_HI : SMS_LED_LO);
+	else
+		sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+	return ret;
 }
 
 static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
@@ -217,6 +229,18 @@ static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
 	return rc;
 }
 
+static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+	int rc = smsdvb_send_statistics_request(client);
+
+	if (!rc)
+		*ucblocks = client->fe_unc;
+
+	return rc;
+}
+
 static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
 				    struct dvb_frontend_tune_settings *tune)
 {
@@ -273,6 +297,28 @@ static int smsdvb_get_frontend(struct dvb_frontend *fe,
 	/* todo: */
 	memcpy(fep, &client->fe_params,
 	       sizeof(struct dvb_frontend_parameters));
+
+	return 0;
+}
+
+static int smsdvb_init(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	sms_board_power(client->coredev, 1);
+
+	return 0;
+}
+
+static int smsdvb_sleep(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+	sms_board_power(client->coredev, 0);
+
 	return 0;
 }
 
@@ -308,6 +354,10 @@ static struct dvb_frontend_ops smsdvb_fe_ops = {
 	.read_ber = smsdvb_read_ber,
 	.read_signal_strength = smsdvb_read_signal_strength,
 	.read_snr = smsdvb_read_snr,
+	.read_ucblocks = smsdvb_read_ucblocks,
+
+	.init = smsdvb_init,
+	.sleep = smsdvb_sleep,
 };
 
 static int smsdvb_hotplug(struct smscore_device_t *coredev,
@@ -402,6 +452,8 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 
 	sms_info("success");
 
+	sms_board_setup(coredev);
+
 	return 0;
 
 client_error:

+ 45 - 0
drivers/media/dvb/siano/smsusb.c

@@ -432,11 +432,56 @@ static void smsusb_disconnect(struct usb_interface *intf)
 	smsusb_term_device(intf);
 }
 
+static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg)
+{
+	struct smsusb_device_t *dev =
+		(struct smsusb_device_t *)usb_get_intfdata(intf);
+	printk(KERN_INFO "%s  Entering status %d.\n", __func__, msg.event);
+	smsusb_stop_streaming(dev);
+	return 0;
+}
+
+static int smsusb_resume(struct usb_interface *intf)
+{
+	int rc, i;
+	struct smsusb_device_t *dev =
+		(struct smsusb_device_t *)usb_get_intfdata(intf);
+	struct usb_device *udev = interface_to_usbdev(intf);
+
+	printk(KERN_INFO "%s  Entering.\n", __func__);
+	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
+	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
+
+	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
+		printk(KERN_INFO "endpoint %d %02x %02x %d\n", i,
+		       intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
+		       intf->cur_altsetting->endpoint[i].desc.bmAttributes,
+		       intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
+
+	if (intf->num_altsetting > 0) {
+		rc = usb_set_interface(udev,
+				       intf->cur_altsetting->desc.
+				       bInterfaceNumber, 0);
+		if (rc < 0) {
+			printk(KERN_INFO
+			       "%s usb_set_interface failed, rc %d\n",
+			       __func__, rc);
+			return rc;
+		}
+	}
+
+	smsusb_start_streaming(dev);
+	return 0;
+}
+
 static struct usb_driver smsusb_driver = {
 	.name			= "sms1xxx",
 	.probe			= smsusb_probe,
 	.disconnect		= smsusb_disconnect,
 	.id_table		= smsusb_id_table,
+
+	.suspend		= smsusb_suspend,
+	.resume			= smsusb_resume,
 };
 
 int smsusb_register(void)

+ 4 - 0
drivers/media/dvb/ttpci/Kconfig

@@ -104,6 +104,8 @@ config DVB_BUDGET_CI
 	select DVB_STV0297 if !DVB_FE_CUSTOMISE
 	select DVB_STV0299 if !DVB_FE_CUSTOMISE
 	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+	select DVB_STB0899 if !DVB_FE_CUSTOMISE
+	select DVB_STB6100 if !DVB_FE_CUSTOMISE
 	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
 	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
 	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE
@@ -131,6 +133,8 @@ config DVB_BUDGET_AV
 	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
 	select DVB_TDA10021 if !DVB_FE_CUSTOMISE
 	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+	select DVB_STB0899 if !DVB_FE_CUSTOMISE
+	select DVB_TDA8261 if !DVB_FE_CUSTOMISE
 	select DVB_TUA6100 if !DVB_FE_CUSTOMISE
 	help
 	  Support for simple SAA7146 based DVB cards

+ 298 - 0
drivers/media/dvb/ttpci/budget-av.c

@@ -35,6 +35,11 @@
 
 #include "budget.h"
 #include "stv0299.h"
+#include "stb0899_drv.h"
+#include "stb0899_reg.h"
+#include "stb0899_cfg.h"
+#include "tda8261.h"
+#include "tda8261_cfg.h"
 #include "tda1002x.h"
 #include "tda1004x.h"
 #include "tua6100.h"
@@ -882,6 +887,281 @@ static struct stv0299_config philips_sd1878_config = {
 	.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
 };
 
+/* KNC1 DVB-S (STB0899) Inittab	*/
+static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = {
+
+	{ STB0899_DEV_ID		, 0x81 },
+	{ STB0899_DISCNTRL1		, 0x32 },
+	{ STB0899_DISCNTRL2		, 0x80 },
+	{ STB0899_DISRX_ST0		, 0x04 },
+	{ STB0899_DISRX_ST1		, 0x00 },
+	{ STB0899_DISPARITY		, 0x00 },
+	{ STB0899_DISFIFO		, 0x00 },
+	{ STB0899_DISSTATUS		, 0x20 },
+	{ STB0899_DISF22		, 0x8c },
+	{ STB0899_DISF22RX		, 0x9a },
+	{ STB0899_SYSREG		, 0x0b },
+	{ STB0899_ACRPRESC		, 0x11 },
+	{ STB0899_ACRDIV1		, 0x0a },
+	{ STB0899_ACRDIV2		, 0x05 },
+	{ STB0899_DACR1			, 0x00 },
+	{ STB0899_DACR2			, 0x00 },
+	{ STB0899_OUTCFG		, 0x00 },
+	{ STB0899_MODECFG		, 0x00 },
+	{ STB0899_IRQSTATUS_3		, 0x30 },
+	{ STB0899_IRQSTATUS_2		, 0x00 },
+	{ STB0899_IRQSTATUS_1		, 0x00 },
+	{ STB0899_IRQSTATUS_0		, 0x00 },
+	{ STB0899_IRQMSK_3		, 0xf3 },
+	{ STB0899_IRQMSK_2		, 0xfc },
+	{ STB0899_IRQMSK_1		, 0xff },
+	{ STB0899_IRQMSK_0		, 0xff },
+	{ STB0899_IRQCFG		, 0x00 },
+	{ STB0899_I2CCFG		, 0x88 },
+	{ STB0899_I2CRPT		, 0x58 }, /* Repeater=8, Stop=disabled */
+	{ STB0899_IOPVALUE5		, 0x00 },
+	{ STB0899_IOPVALUE4		, 0x20 },
+	{ STB0899_IOPVALUE3		, 0xc9 },
+	{ STB0899_IOPVALUE2		, 0x90 },
+	{ STB0899_IOPVALUE1		, 0x40 },
+	{ STB0899_IOPVALUE0		, 0x00 },
+	{ STB0899_GPIO00CFG		, 0x82 },
+	{ STB0899_GPIO01CFG		, 0x82 },
+	{ STB0899_GPIO02CFG		, 0x82 },
+	{ STB0899_GPIO03CFG		, 0x82 },
+	{ STB0899_GPIO04CFG		, 0x82 },
+	{ STB0899_GPIO05CFG		, 0x82 },
+	{ STB0899_GPIO06CFG		, 0x82 },
+	{ STB0899_GPIO07CFG		, 0x82 },
+	{ STB0899_GPIO08CFG		, 0x82 },
+	{ STB0899_GPIO09CFG		, 0x82 },
+	{ STB0899_GPIO10CFG		, 0x82 },
+	{ STB0899_GPIO11CFG		, 0x82 },
+	{ STB0899_GPIO12CFG		, 0x82 },
+	{ STB0899_GPIO13CFG		, 0x82 },
+	{ STB0899_GPIO14CFG		, 0x82 },
+	{ STB0899_GPIO15CFG		, 0x82 },
+	{ STB0899_GPIO16CFG		, 0x82 },
+	{ STB0899_GPIO17CFG		, 0x82 },
+	{ STB0899_GPIO18CFG		, 0x82 },
+	{ STB0899_GPIO19CFG		, 0x82 },
+	{ STB0899_GPIO20CFG		, 0x82 },
+	{ STB0899_SDATCFG		, 0xb8 },
+	{ STB0899_SCLTCFG		, 0xba },
+	{ STB0899_AGCRFCFG		, 0x08 }, /* 0x1c */
+	{ STB0899_GPIO22		, 0x82 }, /* AGCBB2CFG */
+	{ STB0899_GPIO21		, 0x91 }, /* AGCBB1CFG */
+	{ STB0899_DIRCLKCFG		, 0x82 },
+	{ STB0899_CLKOUT27CFG		, 0x7e },
+	{ STB0899_STDBYCFG		, 0x82 },
+	{ STB0899_CS0CFG		, 0x82 },
+	{ STB0899_CS1CFG		, 0x82 },
+	{ STB0899_DISEQCOCFG		, 0x20 },
+	{ STB0899_GPIO32CFG		, 0x82 },
+	{ STB0899_GPIO33CFG		, 0x82 },
+	{ STB0899_GPIO34CFG		, 0x82 },
+	{ STB0899_GPIO35CFG		, 0x82 },
+	{ STB0899_GPIO36CFG		, 0x82 },
+	{ STB0899_GPIO37CFG		, 0x82 },
+	{ STB0899_GPIO38CFG		, 0x82 },
+	{ STB0899_GPIO39CFG		, 0x82 },
+	{ STB0899_NCOARSE		, 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
+	{ STB0899_SYNTCTRL		, 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
+	{ STB0899_FILTCTRL		, 0x00 },
+	{ STB0899_SYSCTRL		, 0x00 },
+	{ STB0899_STOPCLK1		, 0x20 },
+	{ STB0899_STOPCLK2		, 0x00 },
+	{ STB0899_INTBUFSTATUS		, 0x00 },
+	{ STB0899_INTBUFCTRL		, 0x0a },
+	{ 0xffff			, 0xff },
+};
+
+static const struct stb0899_s1_reg knc1_stb0899_s1_init_3[] = {
+	{ STB0899_DEMOD			, 0x00 },
+	{ STB0899_RCOMPC		, 0xc9 },
+	{ STB0899_AGC1CN		, 0x41 },
+	{ STB0899_AGC1REF		, 0x08 },
+	{ STB0899_RTC			, 0x7a },
+	{ STB0899_TMGCFG		, 0x4e },
+	{ STB0899_AGC2REF		, 0x33 },
+	{ STB0899_TLSR			, 0x84 },
+	{ STB0899_CFD			, 0xee },
+	{ STB0899_ACLC			, 0x87 },
+	{ STB0899_BCLC			, 0x94 },
+	{ STB0899_EQON			, 0x41 },
+	{ STB0899_LDT			, 0xdd },
+	{ STB0899_LDT2			, 0xc9 },
+	{ STB0899_EQUALREF		, 0xb4 },
+	{ STB0899_TMGRAMP		, 0x10 },
+	{ STB0899_TMGTHD		, 0x30 },
+	{ STB0899_IDCCOMP		, 0xfb },
+	{ STB0899_QDCCOMP		, 0x03 },
+	{ STB0899_POWERI		, 0x3b },
+	{ STB0899_POWERQ		, 0x3d },
+	{ STB0899_RCOMP			, 0x81 },
+	{ STB0899_AGCIQIN		, 0x80 },
+	{ STB0899_AGC2I1		, 0x04 },
+	{ STB0899_AGC2I2		, 0xf5 },
+	{ STB0899_TLIR			, 0x25 },
+	{ STB0899_RTF			, 0x80 },
+	{ STB0899_DSTATUS		, 0x00 },
+	{ STB0899_LDI			, 0xca },
+	{ STB0899_CFRM			, 0xf1 },
+	{ STB0899_CFRL			, 0xf3 },
+	{ STB0899_NIRM			, 0x2a },
+	{ STB0899_NIRL			, 0x05 },
+	{ STB0899_ISYMB			, 0x17 },
+	{ STB0899_QSYMB			, 0xfa },
+	{ STB0899_SFRH			, 0x2f },
+	{ STB0899_SFRM			, 0x68 },
+	{ STB0899_SFRL			, 0x40 },
+	{ STB0899_SFRUPH		, 0x2f },
+	{ STB0899_SFRUPM		, 0x68 },
+	{ STB0899_SFRUPL		, 0x40 },
+	{ STB0899_EQUAI1		, 0xfd },
+	{ STB0899_EQUAQ1		, 0x04 },
+	{ STB0899_EQUAI2		, 0x0f },
+	{ STB0899_EQUAQ2		, 0xff },
+	{ STB0899_EQUAI3		, 0xdf },
+	{ STB0899_EQUAQ3		, 0xfa },
+	{ STB0899_EQUAI4		, 0x37 },
+	{ STB0899_EQUAQ4		, 0x0d },
+	{ STB0899_EQUAI5		, 0xbd },
+	{ STB0899_EQUAQ5		, 0xf7 },
+	{ STB0899_DSTATUS2		, 0x00 },
+	{ STB0899_VSTATUS		, 0x00 },
+	{ STB0899_VERROR		, 0xff },
+	{ STB0899_IQSWAP		, 0x2a },
+	{ STB0899_ECNT1M		, 0x00 },
+	{ STB0899_ECNT1L		, 0x00 },
+	{ STB0899_ECNT2M		, 0x00 },
+	{ STB0899_ECNT2L		, 0x00 },
+	{ STB0899_ECNT3M		, 0x00 },
+	{ STB0899_ECNT3L		, 0x00 },
+	{ STB0899_FECAUTO1		, 0x06 },
+	{ STB0899_FECM			, 0x01 },
+	{ STB0899_VTH12			, 0xf0 },
+	{ STB0899_VTH23			, 0xa0 },
+	{ STB0899_VTH34			, 0x78 },
+	{ STB0899_VTH56			, 0x4e },
+	{ STB0899_VTH67			, 0x48 },
+	{ STB0899_VTH78			, 0x38 },
+	{ STB0899_PRVIT			, 0xff },
+	{ STB0899_VITSYNC		, 0x19 },
+	{ STB0899_RSULC			, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+	{ STB0899_TSULC			, 0x42 },
+	{ STB0899_RSLLC			, 0x40 },
+	{ STB0899_TSLPL			, 0x12 },
+	{ STB0899_TSCFGH		, 0x0c },
+	{ STB0899_TSCFGM		, 0x00 },
+	{ STB0899_TSCFGL		, 0x0c },
+	{ STB0899_TSOUT			, 0x0d }, /* 0x0d for CAM */
+	{ STB0899_RSSYNCDEL		, 0x00 },
+	{ STB0899_TSINHDELH		, 0x02 },
+	{ STB0899_TSINHDELM		, 0x00 },
+	{ STB0899_TSINHDELL		, 0x00 },
+	{ STB0899_TSLLSTKM		, 0x00 },
+	{ STB0899_TSLLSTKL		, 0x00 },
+	{ STB0899_TSULSTKM		, 0x00 },
+	{ STB0899_TSULSTKL		, 0xab },
+	{ STB0899_PCKLENUL		, 0x00 },
+	{ STB0899_PCKLENLL		, 0xcc },
+	{ STB0899_RSPCKLEN		, 0xcc },
+	{ STB0899_TSSTATUS		, 0x80 },
+	{ STB0899_ERRCTRL1		, 0xb6 },
+	{ STB0899_ERRCTRL2		, 0x96 },
+	{ STB0899_ERRCTRL3		, 0x89 },
+	{ STB0899_DMONMSK1		, 0x27 },
+	{ STB0899_DMONMSK0		, 0x03 },
+	{ STB0899_DEMAPVIT		, 0x5c },
+	{ STB0899_PLPARM		, 0x1f },
+	{ STB0899_PDELCTRL		, 0x48 },
+	{ STB0899_PDELCTRL2		, 0x00 },
+	{ STB0899_BBHCTRL1		, 0x00 },
+	{ STB0899_BBHCTRL2		, 0x00 },
+	{ STB0899_HYSTTHRESH		, 0x77 },
+	{ STB0899_MATCSTM		, 0x00 },
+	{ STB0899_MATCSTL		, 0x00 },
+	{ STB0899_UPLCSTM		, 0x00 },
+	{ STB0899_UPLCSTL		, 0x00 },
+	{ STB0899_DFLCSTM		, 0x00 },
+	{ STB0899_DFLCSTL		, 0x00 },
+	{ STB0899_SYNCCST		, 0x00 },
+	{ STB0899_SYNCDCSTM		, 0x00 },
+	{ STB0899_SYNCDCSTL		, 0x00 },
+	{ STB0899_ISI_ENTRY		, 0x00 },
+	{ STB0899_ISI_BIT_EN		, 0x00 },
+	{ STB0899_MATSTRM		, 0x00 },
+	{ STB0899_MATSTRL		, 0x00 },
+	{ STB0899_UPLSTRM		, 0x00 },
+	{ STB0899_UPLSTRL		, 0x00 },
+	{ STB0899_DFLSTRM		, 0x00 },
+	{ STB0899_DFLSTRL		, 0x00 },
+	{ STB0899_SYNCSTR		, 0x00 },
+	{ STB0899_SYNCDSTRM		, 0x00 },
+	{ STB0899_SYNCDSTRL		, 0x00 },
+	{ STB0899_CFGPDELSTATUS1	, 0x10 },
+	{ STB0899_CFGPDELSTATUS2	, 0x00 },
+	{ STB0899_BBFERRORM		, 0x00 },
+	{ STB0899_BBFERRORL		, 0x00 },
+	{ STB0899_UPKTERRORM		, 0x00 },
+	{ STB0899_UPKTERRORL		, 0x00 },
+	{ 0xffff			, 0xff },
+};
+
+/* STB0899 demodulator config for the KNC1 and clones */
+static struct stb0899_config knc1_dvbs2_config = {
+	.init_dev		= knc1_stb0899_s1_init_1,
+	.init_s2_demod		= stb0899_s2_init_2,
+	.init_s1_demod		= knc1_stb0899_s1_init_3,
+	.init_s2_fec		= stb0899_s2_init_4,
+	.init_tst		= stb0899_s1_init_5,
+
+	.postproc		= NULL,
+
+	.demod_address		= 0x68,
+//	.ts_output_mode		= STB0899_OUT_PARALLEL,	/* types = SERIAL/PARALLEL	*/
+	.block_sync_mode	= STB0899_SYNC_FORCED,	/* DSS, SYNC_FORCED/UNSYNCED	*/
+//	.ts_pfbit_toggle	= STB0899_MPEG_NORMAL,	/* DirecTV, MPEG toggling seq	*/
+
+	.xtal_freq		= 27000000,
+	.inversion		= IQ_SWAP_OFF, /* 1 */
+
+	.lo_clk			= 76500000,
+	.hi_clk			= 90000000,
+
+	.esno_ave		= STB0899_DVBS2_ESNO_AVE,
+	.esno_quant		= STB0899_DVBS2_ESNO_QUANT,
+	.avframes_coarse	= STB0899_DVBS2_AVFRAMES_COARSE,
+	.avframes_fine		= STB0899_DVBS2_AVFRAMES_FINE,
+	.miss_threshold		= STB0899_DVBS2_MISS_THRESHOLD,
+	.uwp_threshold_acq	= STB0899_DVBS2_UWP_THRESHOLD_ACQ,
+	.uwp_threshold_track	= STB0899_DVBS2_UWP_THRESHOLD_TRACK,
+	.uwp_threshold_sof	= STB0899_DVBS2_UWP_THRESHOLD_SOF,
+	.sof_search_timeout	= STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
+
+	.btr_nco_bits		= STB0899_DVBS2_BTR_NCO_BITS,
+	.btr_gain_shift_offset	= STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+	.crl_nco_bits		= STB0899_DVBS2_CRL_NCO_BITS,
+	.ldpc_max_iter		= STB0899_DVBS2_LDPC_MAX_ITER,
+
+	.tuner_get_frequency	= tda8261_get_frequency,
+	.tuner_set_frequency	= tda8261_set_frequency,
+	.tuner_set_bandwidth	= NULL,
+	.tuner_get_bandwidth	= tda8261_get_bandwidth,
+	.tuner_set_rfsiggain	= NULL
+};
+
+/*
+ * SD1878/SHA tuner config
+ * 1F, Single I/P, Horizontal mount, High Sensitivity
+ */
+static const struct tda8261_config sd1878c_config = {
+//	.name		= "SD1878/SHA",
+	.addr		= 0x60,
+	.step_size	= TDA8261_STEP_1000 /* kHz */
+};
+
 static u8 read_pwm(struct budget_av *budget_av)
 {
 	u8 b = 0xff;
@@ -905,8 +1185,11 @@ static u8 read_pwm(struct budget_av *budget_av)
 #define SUBID_DVBS_TV_STAR		0x0014
 #define SUBID_DVBS_TV_STAR_PLUS_X4	0x0015
 #define SUBID_DVBS_TV_STAR_CI		0x0016
+#define SUBID_DVBS2_KNC1		0x0018
+#define SUBID_DVBS2_KNC1_OEM		0x0019
 #define SUBID_DVBS_EASYWATCH_1  	0x001a
 #define SUBID_DVBS_EASYWATCH_2  	0x001b
+#define SUBID_DVBS2_EASYWATCH		0x001d
 #define SUBID_DVBS_EASYWATCH		0x001e
 
 #define SUBID_DVBC_EASYWATCH		0x002a
@@ -941,6 +1224,9 @@ static void frontend_init(struct budget_av *budget_av)
 		case SUBID_DVBT_KNC1_PLUS:
 		case SUBID_DVBC_EASYWATCH:
 		case SUBID_DVBC_KNC1_PLUS_MK3:
+		case SUBID_DVBS2_KNC1:
+		case SUBID_DVBS2_KNC1_OEM:
+		case SUBID_DVBS2_EASYWATCH:
 			saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
 			break;
 	}
@@ -993,7 +1279,14 @@ static void frontend_init(struct budget_av *budget_av)
 			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
 		}
 		break;
+	case SUBID_DVBS2_KNC1:
+	case SUBID_DVBS2_KNC1_OEM:
+	case SUBID_DVBS2_EASYWATCH:
+		budget_av->reinitialise_demod = 1;
+		if ((fe = dvb_attach(stb0899_attach, &knc1_dvbs2_config, &budget_av->budget.i2c_adap)))
+			dvb_attach(tda8261_attach, fe, &sd1878c_config, &budget_av->budget.i2c_adap);
 
+		break;
 	case SUBID_DVBS_CINERGY1200:
 		fe = dvb_attach(stv0299_attach, &cinergy_1200s_config,
 				    &budget_av->budget.i2c_adap);
@@ -1260,6 +1553,8 @@ static struct saa7146_ext_vv vv_data = {
 static struct saa7146_extension budget_extension;
 
 MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
+MAKE_BUDGET_INFO(knc1s2,"KNC1 DVB-S2", BUDGET_KNC1S2);
+MAKE_BUDGET_INFO(sates2,"Satelco EasyWatch DVB-S2", BUDGET_KNC1S2);
 MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
 MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
 MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
@@ -1290,6 +1585,9 @@ static struct pci_device_id pci_tbl[] = {
 	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
 	MAKE_EXTENSION_PCI(knc1spx4, 0x1894, 0x0015),
 	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
+	MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0018),
+	MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0019),
+	MAKE_EXTENSION_PCI(sates2, 0x1894, 0x001d),
 	MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
 	MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
 	MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b),

+ 311 - 0
drivers/media/dvb/ttpci/budget-ci.c

@@ -43,6 +43,11 @@
 #include "stv0299.h"
 #include "stv0297.h"
 #include "tda1004x.h"
+#include "stb0899_drv.h"
+#include "stb0899_reg.h"
+#include "stb0899_cfg.h"
+#include "stb6100.h"
+#include "stb6100_cfg.h"
 #include "lnbp21.h"
 #include "bsbe1.h"
 #include "bsru6.h"
@@ -1071,7 +1076,271 @@ static struct tda10023_config tda10023_config = {
 	.deltaf = 0xa511,
 };
 
+/* TT S2-3200 DVB-S (STB0899) Inittab */
+static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
+
+	{ STB0899_DEV_ID		, 0x81 },
+	{ STB0899_DISCNTRL1		, 0x32 },
+	{ STB0899_DISCNTRL2     	, 0x80 },
+	{ STB0899_DISRX_ST0     	, 0x04 },
+	{ STB0899_DISRX_ST1     	, 0x00 },
+	{ STB0899_DISPARITY     	, 0x00 },
+	{ STB0899_DISFIFO       	, 0x00 },
+	{ STB0899_DISSTATUS		, 0x20 },
+	{ STB0899_DISF22        	, 0x8c },
+	{ STB0899_DISF22RX      	, 0x9a },
+	{ STB0899_SYSREG		, 0x0b },
+	{ STB0899_ACRPRESC      	, 0x11 },
+	{ STB0899_ACRDIV1       	, 0x0a },
+	{ STB0899_ACRDIV2       	, 0x05 },
+	{ STB0899_DACR1         	, 0x00 },
+	{ STB0899_DACR2         	, 0x00 },
+	{ STB0899_OUTCFG        	, 0x00 },
+	{ STB0899_MODECFG       	, 0x00 },
+	{ STB0899_IRQSTATUS_3		, 0x30 },
+	{ STB0899_IRQSTATUS_2		, 0x00 },
+	{ STB0899_IRQSTATUS_1		, 0x00 },
+	{ STB0899_IRQSTATUS_0		, 0x00 },
+	{ STB0899_IRQMSK_3      	, 0xf3 },
+	{ STB0899_IRQMSK_2      	, 0xfc },
+	{ STB0899_IRQMSK_1      	, 0xff },
+	{ STB0899_IRQMSK_0		, 0xff },
+	{ STB0899_IRQCFG		, 0x00 },
+	{ STB0899_I2CCFG        	, 0x88 },
+	{ STB0899_I2CRPT        	, 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
+	{ STB0899_IOPVALUE5		, 0x00 },
+	{ STB0899_IOPVALUE4		, 0x20 },
+	{ STB0899_IOPVALUE3		, 0xc9 },
+	{ STB0899_IOPVALUE2		, 0x90 },
+	{ STB0899_IOPVALUE1		, 0x40 },
+	{ STB0899_IOPVALUE0		, 0x00 },
+	{ STB0899_GPIO00CFG     	, 0x82 },
+	{ STB0899_GPIO01CFG     	, 0x82 },
+	{ STB0899_GPIO02CFG     	, 0x82 },
+	{ STB0899_GPIO03CFG     	, 0x82 },
+	{ STB0899_GPIO04CFG     	, 0x82 },
+	{ STB0899_GPIO05CFG     	, 0x82 },
+	{ STB0899_GPIO06CFG     	, 0x82 },
+	{ STB0899_GPIO07CFG     	, 0x82 },
+	{ STB0899_GPIO08CFG     	, 0x82 },
+	{ STB0899_GPIO09CFG     	, 0x82 },
+	{ STB0899_GPIO10CFG     	, 0x82 },
+	{ STB0899_GPIO11CFG     	, 0x82 },
+	{ STB0899_GPIO12CFG     	, 0x82 },
+	{ STB0899_GPIO13CFG     	, 0x82 },
+	{ STB0899_GPIO14CFG     	, 0x82 },
+	{ STB0899_GPIO15CFG     	, 0x82 },
+	{ STB0899_GPIO16CFG     	, 0x82 },
+	{ STB0899_GPIO17CFG     	, 0x82 },
+	{ STB0899_GPIO18CFG     	, 0x82 },
+	{ STB0899_GPIO19CFG     	, 0x82 },
+	{ STB0899_GPIO20CFG     	, 0x82 },
+	{ STB0899_SDATCFG       	, 0xb8 },
+	{ STB0899_SCLTCFG       	, 0xba },
+	{ STB0899_AGCRFCFG      	, 0x1c }, /* 0x11 */
+	{ STB0899_GPIO22        	, 0x82 }, /* AGCBB2CFG */
+	{ STB0899_GPIO21        	, 0x91 }, /* AGCBB1CFG */
+	{ STB0899_DIRCLKCFG     	, 0x82 },
+	{ STB0899_CLKOUT27CFG   	, 0x7e },
+	{ STB0899_STDBYCFG      	, 0x82 },
+	{ STB0899_CS0CFG        	, 0x82 },
+	{ STB0899_CS1CFG        	, 0x82 },
+	{ STB0899_DISEQCOCFG    	, 0x20 },
+	{ STB0899_GPIO32CFG		, 0x82 },
+	{ STB0899_GPIO33CFG		, 0x82 },
+	{ STB0899_GPIO34CFG		, 0x82 },
+	{ STB0899_GPIO35CFG		, 0x82 },
+	{ STB0899_GPIO36CFG		, 0x82 },
+	{ STB0899_GPIO37CFG		, 0x82 },
+	{ STB0899_GPIO38CFG		, 0x82 },
+	{ STB0899_GPIO39CFG		, 0x82 },
+	{ STB0899_NCOARSE       	, 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
+	{ STB0899_SYNTCTRL      	, 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
+	{ STB0899_FILTCTRL      	, 0x00 },
+	{ STB0899_SYSCTRL       	, 0x00 },
+	{ STB0899_STOPCLK1      	, 0x20 },
+	{ STB0899_STOPCLK2      	, 0x00 },
+	{ STB0899_INTBUFSTATUS		, 0x00 },
+	{ STB0899_INTBUFCTRL    	, 0x0a },
+	{ 0xffff			, 0xff },
+};
+
+static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
+	{ STB0899_DEMOD         	, 0x00 },
+	{ STB0899_RCOMPC        	, 0xc9 },
+	{ STB0899_AGC1CN        	, 0x41 },
+	{ STB0899_AGC1REF       	, 0x10 },
+	{ STB0899_RTC			, 0x7a },
+	{ STB0899_TMGCFG        	, 0x4e },
+	{ STB0899_AGC2REF       	, 0x34 },
+	{ STB0899_TLSR          	, 0x84 },
+	{ STB0899_CFD           	, 0xc7 },
+	{ STB0899_ACLC			, 0x87 },
+	{ STB0899_BCLC          	, 0x94 },
+	{ STB0899_EQON          	, 0x41 },
+	{ STB0899_LDT           	, 0xdd },
+	{ STB0899_LDT2          	, 0xc9 },
+	{ STB0899_EQUALREF      	, 0xb4 },
+	{ STB0899_TMGRAMP       	, 0x10 },
+	{ STB0899_TMGTHD        	, 0x30 },
+	{ STB0899_IDCCOMP		, 0xfb },
+	{ STB0899_QDCCOMP		, 0x03 },
+	{ STB0899_POWERI		, 0x3b },
+	{ STB0899_POWERQ		, 0x3d },
+	{ STB0899_RCOMP			, 0x81 },
+	{ STB0899_AGCIQIN		, 0x80 },
+	{ STB0899_AGC2I1		, 0x04 },
+	{ STB0899_AGC2I2		, 0xf5 },
+	{ STB0899_TLIR			, 0x25 },
+	{ STB0899_RTF			, 0x80 },
+	{ STB0899_DSTATUS		, 0x00 },
+	{ STB0899_LDI			, 0xca },
+	{ STB0899_CFRM			, 0xf1 },
+	{ STB0899_CFRL			, 0xf3 },
+	{ STB0899_NIRM			, 0x2a },
+	{ STB0899_NIRL			, 0x05 },
+	{ STB0899_ISYMB			, 0x17 },
+	{ STB0899_QSYMB			, 0xfa },
+	{ STB0899_SFRH          	, 0x2f },
+	{ STB0899_SFRM          	, 0x68 },
+	{ STB0899_SFRL          	, 0x40 },
+	{ STB0899_SFRUPH        	, 0x2f },
+	{ STB0899_SFRUPM        	, 0x68 },
+	{ STB0899_SFRUPL        	, 0x40 },
+	{ STB0899_EQUAI1		, 0xfd },
+	{ STB0899_EQUAQ1		, 0x04 },
+	{ STB0899_EQUAI2		, 0x0f },
+	{ STB0899_EQUAQ2		, 0xff },
+	{ STB0899_EQUAI3		, 0xdf },
+	{ STB0899_EQUAQ3		, 0xfa },
+	{ STB0899_EQUAI4		, 0x37 },
+	{ STB0899_EQUAQ4		, 0x0d },
+	{ STB0899_EQUAI5		, 0xbd },
+	{ STB0899_EQUAQ5		, 0xf7 },
+	{ STB0899_DSTATUS2		, 0x00 },
+	{ STB0899_VSTATUS       	, 0x00 },
+	{ STB0899_VERROR		, 0xff },
+	{ STB0899_IQSWAP		, 0x2a },
+	{ STB0899_ECNT1M		, 0x00 },
+	{ STB0899_ECNT1L		, 0x00 },
+	{ STB0899_ECNT2M		, 0x00 },
+	{ STB0899_ECNT2L		, 0x00 },
+	{ STB0899_ECNT3M		, 0x00 },
+	{ STB0899_ECNT3L		, 0x00 },
+	{ STB0899_FECAUTO1      	, 0x06 },
+	{ STB0899_FECM			, 0x01 },
+	{ STB0899_VTH12         	, 0xf0 },
+	{ STB0899_VTH23         	, 0xa0 },
+	{ STB0899_VTH34			, 0x78 },
+	{ STB0899_VTH56         	, 0x4e },
+	{ STB0899_VTH67         	, 0x48 },
+	{ STB0899_VTH78         	, 0x38 },
+	{ STB0899_PRVIT         	, 0xff },
+	{ STB0899_VITSYNC       	, 0x19 },
+	{ STB0899_RSULC         	, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+	{ STB0899_TSULC         	, 0x42 },
+	{ STB0899_RSLLC         	, 0x40 },
+	{ STB0899_TSLPL			, 0x12 },
+	{ STB0899_TSCFGH        	, 0x0c },
+	{ STB0899_TSCFGM        	, 0x00 },
+	{ STB0899_TSCFGL        	, 0x0c },
+	{ STB0899_TSOUT			, 0x0d }, /* 0x0d for CAM */
+	{ STB0899_RSSYNCDEL     	, 0x00 },
+	{ STB0899_TSINHDELH     	, 0x02 },
+	{ STB0899_TSINHDELM		, 0x00 },
+	{ STB0899_TSINHDELL		, 0x00 },
+	{ STB0899_TSLLSTKM		, 0x00 },
+	{ STB0899_TSLLSTKL		, 0x00 },
+	{ STB0899_TSULSTKM		, 0x00 },
+	{ STB0899_TSULSTKL		, 0xab },
+	{ STB0899_PCKLENUL		, 0x00 },
+	{ STB0899_PCKLENLL		, 0xcc },
+	{ STB0899_RSPCKLEN		, 0xcc },
+	{ STB0899_TSSTATUS		, 0x80 },
+	{ STB0899_ERRCTRL1      	, 0xb6 },
+	{ STB0899_ERRCTRL2      	, 0x96 },
+	{ STB0899_ERRCTRL3      	, 0x89 },
+	{ STB0899_DMONMSK1		, 0x27 },
+	{ STB0899_DMONMSK0		, 0x03 },
+	{ STB0899_DEMAPVIT      	, 0x5c },
+	{ STB0899_PLPARM		, 0x1f },
+	{ STB0899_PDELCTRL      	, 0x48 },
+	{ STB0899_PDELCTRL2     	, 0x00 },
+	{ STB0899_BBHCTRL1      	, 0x00 },
+	{ STB0899_BBHCTRL2      	, 0x00 },
+	{ STB0899_HYSTTHRESH    	, 0x77 },
+	{ STB0899_MATCSTM		, 0x00 },
+	{ STB0899_MATCSTL		, 0x00 },
+	{ STB0899_UPLCSTM		, 0x00 },
+	{ STB0899_UPLCSTL		, 0x00 },
+	{ STB0899_DFLCSTM		, 0x00 },
+	{ STB0899_DFLCSTL		, 0x00 },
+	{ STB0899_SYNCCST		, 0x00 },
+	{ STB0899_SYNCDCSTM		, 0x00 },
+	{ STB0899_SYNCDCSTL		, 0x00 },
+	{ STB0899_ISI_ENTRY		, 0x00 },
+	{ STB0899_ISI_BIT_EN		, 0x00 },
+	{ STB0899_MATSTRM		, 0x00 },
+	{ STB0899_MATSTRL		, 0x00 },
+	{ STB0899_UPLSTRM		, 0x00 },
+	{ STB0899_UPLSTRL		, 0x00 },
+	{ STB0899_DFLSTRM		, 0x00 },
+	{ STB0899_DFLSTRL		, 0x00 },
+	{ STB0899_SYNCSTR		, 0x00 },
+	{ STB0899_SYNCDSTRM		, 0x00 },
+	{ STB0899_SYNCDSTRL		, 0x00 },
+	{ STB0899_CFGPDELSTATUS1	, 0x10 },
+	{ STB0899_CFGPDELSTATUS2	, 0x00 },
+	{ STB0899_BBFERRORM		, 0x00 },
+	{ STB0899_BBFERRORL		, 0x00 },
+	{ STB0899_UPKTERRORM		, 0x00 },
+	{ STB0899_UPKTERRORL		, 0x00 },
+	{ 0xffff			, 0xff },
+};
 
+static struct stb0899_config tt3200_config = {
+	.init_dev		= tt3200_stb0899_s1_init_1,
+	.init_s2_demod		= stb0899_s2_init_2,
+	.init_s1_demod		= tt3200_stb0899_s1_init_3,
+	.init_s2_fec		= stb0899_s2_init_4,
+	.init_tst		= stb0899_s1_init_5,
+
+	.postproc		= NULL,
+
+	.demod_address 		= 0x68,
+
+	.xtal_freq		= 27000000,
+	.inversion		= IQ_SWAP_ON, /* 1 */
+
+	.lo_clk			= 76500000,
+	.hi_clk			= 99000000,
+
+	.esno_ave		= STB0899_DVBS2_ESNO_AVE,
+	.esno_quant		= STB0899_DVBS2_ESNO_QUANT,
+	.avframes_coarse	= STB0899_DVBS2_AVFRAMES_COARSE,
+	.avframes_fine		= STB0899_DVBS2_AVFRAMES_FINE,
+	.miss_threshold		= STB0899_DVBS2_MISS_THRESHOLD,
+	.uwp_threshold_acq	= STB0899_DVBS2_UWP_THRESHOLD_ACQ,
+	.uwp_threshold_track	= STB0899_DVBS2_UWP_THRESHOLD_TRACK,
+	.uwp_threshold_sof	= STB0899_DVBS2_UWP_THRESHOLD_SOF,
+	.sof_search_timeout	= STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
+
+	.btr_nco_bits		= STB0899_DVBS2_BTR_NCO_BITS,
+	.btr_gain_shift_offset	= STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+	.crl_nco_bits		= STB0899_DVBS2_CRL_NCO_BITS,
+	.ldpc_max_iter		= STB0899_DVBS2_LDPC_MAX_ITER,
+
+	.tuner_get_frequency	= stb6100_get_frequency,
+	.tuner_set_frequency	= stb6100_set_frequency,
+	.tuner_set_bandwidth	= stb6100_set_bandwidth,
+	.tuner_get_bandwidth	= stb6100_get_bandwidth,
+	.tuner_set_rfsiggain	= NULL
+};
+
+struct stb6100_config tt3200_stb6100_config = {
+	.tuner_address	= 0x60,
+	.refclock	= 27000000,
+};
 
 static void frontend_init(struct budget_ci *budget_ci)
 {
@@ -1152,6 +1421,46 @@ static void frontend_init(struct budget_ci *budget_ci)
 			}
 		}
 		break;
+
+	case 0x1019:		// TT S2-3200 PCI
+		/*
+		 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
+		 * to settle, aka LOCK. On the older revisions of the chip, we don't see
+		 * this, as a result on the newer chips the entire clock tree, will not
+		 * be stable after a freshly POWER 'ed up situation.
+		 * In this case, we should RESET the STB0899 (Active LOW) and wait for
+		 * PLL stabilization.
+		 *
+		 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
+		 * connected to the SAA7146 GPIO, GPIO2, Pin 142
+		 */
+		/* Reset Demodulator */
+		saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
+		/* Wait for everything to die */
+		msleep(50);
+		/* Pull it up out of Reset state */
+		saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
+		/* Wait for PLL to stabilize */
+		msleep(250);
+		/*
+		 * PLL state should be stable now. Ideally, we should check
+		 * for PLL LOCK status. But well, never mind!
+		 */
+		budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
+		if (budget_ci->budget.dvb_frontend) {
+			if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
+				if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
+					printk("%s: No LNBP21 found!\n", __FUNCTION__);
+					dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+					budget_ci->budget.dvb_frontend = NULL;
+				}
+			} else {
+					dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+					budget_ci->budget.dvb_frontend = NULL;
+			}
+		}
+		break;
+
 	}
 
 	if (budget_ci->budget.dvb_frontend == NULL) {
@@ -1242,6 +1551,7 @@ MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T	 PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
 
 static struct pci_device_id pci_tbl[] = {
 	MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
@@ -1251,6 +1561,7 @@ static struct pci_device_id pci_tbl[] = {
 	MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
 	MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
 	MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
+	MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
 	{
 	 .vendor = 0,
 	 }

+ 1 - 0
drivers/media/dvb/ttpci/budget.h

@@ -103,6 +103,7 @@ static struct saa7146_pci_extension_data x_var = { \
 #define BUDGET_CIN1200C_MK3	   15
 #define BUDGET_KNC1C_MK3	   16
 #define BUDGET_KNC1CP_MK3	   17
+#define BUDGET_KNC1S2              18
 
 #define BUDGET_VIDEO_PORTA         0
 #define BUDGET_VIDEO_PORTB         1

+ 290 - 91
drivers/media/radio/dsbr100.c

@@ -1,5 +1,5 @@
-/* A driver for the D-Link DSB-R100 USB radio.  The R100 plugs
- into both the USB and an analog audio input, so this thing
+/* A driver for the D-Link DSB-R100 USB radio and Gemtek USB Radio 21.
+ The device plugs into both the USB and an analog audio input, so this thing
  only deals with initialisation and frequency setting, the
  audio data has to be handled by a sound driver.
 
@@ -33,6 +33,10 @@
 
  History:
 
+ Version 0.44:
+	Add suspend/resume functions, fix unplug of device,
+	a lot of cleanups and fixes by Alexey Klimov <klimov.linux@gmail.com>
+
  Version 0.43:
 	Oliver Neukum: avoided DMA coherency issue
 
@@ -93,8 +97,8 @@
  */
 #include <linux/version.h>	/* for KERNEL_VERSION MACRO	*/
 
-#define DRIVER_VERSION "v0.41"
-#define RADIO_VERSION KERNEL_VERSION(0,4,1)
+#define DRIVER_VERSION "v0.44"
+#define RADIO_VERSION KERNEL_VERSION(0, 4, 4)
 
 static struct v4l2_queryctrl radio_qctrl[] = {
 	{
@@ -104,7 +108,27 @@ static struct v4l2_queryctrl radio_qctrl[] = {
 		.maximum       = 1,
 		.default_value = 1,
 		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	}
+	},
+/* HINT: the disabled controls are only here to satify kradio and such apps */
+	{       .id             = V4L2_CID_AUDIO_VOLUME,
+		.flags          = V4L2_CTRL_FLAG_DISABLED,
+	},
+	{
+		.id             = V4L2_CID_AUDIO_BALANCE,
+		.flags          = V4L2_CTRL_FLAG_DISABLED,
+	},
+	{
+		.id             = V4L2_CID_AUDIO_BASS,
+		.flags          = V4L2_CTRL_FLAG_DISABLED,
+	},
+	{
+		.id             = V4L2_CID_AUDIO_TREBLE,
+		.flags          = V4L2_CTRL_FLAG_DISABLED,
+	},
+	{
+		.id             = V4L2_CID_AUDIO_LOUDNESS,
+		.flags          = V4L2_CTRL_FLAG_DISABLED,
+	},
 };
 
 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
@@ -125,12 +149,16 @@ devices, that would be 76 and 91.  */
 #define FREQ_MAX 108.0
 #define FREQ_MUL 16000
 
+#define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev)
 
 static int usb_dsbr100_probe(struct usb_interface *intf,
 			     const struct usb_device_id *id);
 static void usb_dsbr100_disconnect(struct usb_interface *intf);
 static int usb_dsbr100_open(struct inode *inode, struct file *file);
 static int usb_dsbr100_close(struct inode *inode, struct file *file);
+static int usb_dsbr100_suspend(struct usb_interface *intf,
+						pm_message_t message);
+static int usb_dsbr100_resume(struct usb_interface *intf);
 
 static int radio_nr = -1;
 module_param(radio_nr, int, 0);
@@ -138,8 +166,9 @@ module_param(radio_nr, int, 0);
 /* Data for one (physical) device */
 struct dsbr100_device {
 	struct usb_device *usbdev;
-	struct video_device *videodev;
+	struct video_device videodev;
 	u8 *transfer_buffer;
+	struct mutex lock;	/* buffer locking */
 	int curfreq;
 	int stereo;
 	int users;
@@ -147,7 +176,6 @@ struct dsbr100_device {
 	int muted;
 };
 
-
 static struct usb_device_id usb_dsbr100_device_table [] = {
 	{ USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
 	{ }						/* Terminating entry */
@@ -157,10 +185,14 @@ MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
 
 /* USB subsystem interface */
 static struct usb_driver usb_dsbr100_driver = {
-	.name =		"dsbr100",
-	.probe =	usb_dsbr100_probe,
-	.disconnect =	usb_dsbr100_disconnect,
-	.id_table =	usb_dsbr100_device_table,
+	.name			= "dsbr100",
+	.probe			= usb_dsbr100_probe,
+	.disconnect		= usb_dsbr100_disconnect,
+	.id_table		= usb_dsbr100_device_table,
+	.suspend		= usb_dsbr100_suspend,
+	.resume			= usb_dsbr100_resume,
+	.reset_resume		= usb_dsbr100_resume,
+	.supports_autosuspend	= 0,
 };
 
 /* Low-level device interface begins here */
@@ -168,95 +200,190 @@ static struct usb_driver usb_dsbr100_driver = {
 /* switch on radio */
 static int dsbr100_start(struct dsbr100_device *radio)
 {
-	if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-			USB_REQ_GET_STATUS,
-			USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			0x00, 0xC7, radio->transfer_buffer, 8, 300) < 0 ||
-	usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-			DSB100_ONOFF,
-			USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			0x01, 0x00, radio->transfer_buffer, 8, 300) < 0)
-		return -1;
-	radio->muted=0;
+	int retval;
+	int request;
+
+	mutex_lock(&radio->lock);
+
+	retval = usb_control_msg(radio->usbdev,
+		usb_rcvctrlpipe(radio->usbdev, 0),
+		USB_REQ_GET_STATUS,
+		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+		0x00, 0xC7, radio->transfer_buffer, 8, 300);
+
+	if (retval < 0) {
+		request = USB_REQ_GET_STATUS;
+		goto usb_control_msg_failed;
+	}
+
+	retval = usb_control_msg(radio->usbdev,
+		usb_rcvctrlpipe(radio->usbdev, 0),
+		DSB100_ONOFF,
+		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+		0x01, 0x00, radio->transfer_buffer, 8, 300);
+
+	if (retval < 0) {
+		request = DSB100_ONOFF;
+		goto usb_control_msg_failed;
+	}
+
+	radio->muted = 0;
+	mutex_unlock(&radio->lock);
 	return (radio->transfer_buffer)[0];
-}
 
+usb_control_msg_failed:
+	mutex_unlock(&radio->lock);
+	dev_err(&radio->usbdev->dev,
+		"%s - usb_control_msg returned %i, request %i\n",
+			__func__, retval, request);
+	return retval;
+
+}
 
 /* switch off radio */
 static int dsbr100_stop(struct dsbr100_device *radio)
 {
-	if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-			USB_REQ_GET_STATUS,
-			USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			0x16, 0x1C, radio->transfer_buffer, 8, 300) < 0 ||
-	usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-			DSB100_ONOFF,
-			USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			0x00, 0x00, radio->transfer_buffer, 8, 300) < 0)
-		return -1;
-	radio->muted=1;
+	int retval;
+	int request;
+
+	mutex_lock(&radio->lock);
+
+	retval = usb_control_msg(radio->usbdev,
+		usb_rcvctrlpipe(radio->usbdev, 0),
+		USB_REQ_GET_STATUS,
+		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+		0x16, 0x1C, radio->transfer_buffer, 8, 300);
+
+	if (retval < 0) {
+		request = USB_REQ_GET_STATUS;
+		goto usb_control_msg_failed;
+	}
+
+	retval = usb_control_msg(radio->usbdev,
+		usb_rcvctrlpipe(radio->usbdev, 0),
+		DSB100_ONOFF,
+		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+		0x00, 0x00, radio->transfer_buffer, 8, 300);
+
+	if (retval < 0) {
+		request = DSB100_ONOFF;
+		goto usb_control_msg_failed;
+	}
+
+	radio->muted = 1;
+	mutex_unlock(&radio->lock);
 	return (radio->transfer_buffer)[0];
+
+usb_control_msg_failed:
+	mutex_unlock(&radio->lock);
+	dev_err(&radio->usbdev->dev,
+		"%s - usb_control_msg returned %i, request %i\n",
+			__func__, retval, request);
+	return retval;
+
 }
 
 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
 static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
 {
+	int retval;
+	int request;
+
 	freq = (freq / 16 * 80) / 1000 + 856;
-	if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-			DSB100_TUNE,
-			USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			(freq >> 8) & 0x00ff, freq & 0xff,
-			radio->transfer_buffer, 8, 300) < 0 ||
-	   usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-			USB_REQ_GET_STATUS,
-			USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			0x96, 0xB7, radio->transfer_buffer, 8, 300) < 0 ||
-	usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
-			USB_REQ_GET_STATUS,
-			USB_TYPE_VENDOR | USB_RECIP_DEVICE |  USB_DIR_IN,
-			0x00, 0x24, radio->transfer_buffer, 8, 300) < 0) {
-		radio->stereo = -1;
-		return -1;
+	mutex_lock(&radio->lock);
+
+	retval = usb_control_msg(radio->usbdev,
+		usb_rcvctrlpipe(radio->usbdev, 0),
+		DSB100_TUNE,
+		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+		(freq >> 8) & 0x00ff, freq & 0xff,
+		radio->transfer_buffer, 8, 300);
+
+	if (retval < 0) {
+		request = DSB100_TUNE;
+		goto usb_control_msg_failed;
 	}
+
+	retval = usb_control_msg(radio->usbdev,
+		usb_rcvctrlpipe(radio->usbdev, 0),
+		USB_REQ_GET_STATUS,
+		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+		0x96, 0xB7, radio->transfer_buffer, 8, 300);
+
+	if (retval < 0) {
+		request = USB_REQ_GET_STATUS;
+		goto usb_control_msg_failed;
+	}
+
+	retval = usb_control_msg(radio->usbdev,
+		usb_rcvctrlpipe(radio->usbdev, 0),
+		USB_REQ_GET_STATUS,
+		USB_TYPE_VENDOR | USB_RECIP_DEVICE |  USB_DIR_IN,
+		0x00, 0x24, radio->transfer_buffer, 8, 300);
+
+	if (retval < 0) {
+		request = USB_REQ_GET_STATUS;
+		goto usb_control_msg_failed;
+	}
+
 	radio->stereo = !((radio->transfer_buffer)[0] & 0x01);
+	mutex_unlock(&radio->lock);
 	return (radio->transfer_buffer)[0];
+
+usb_control_msg_failed:
+	radio->stereo = -1;
+	mutex_unlock(&radio->lock);
+	dev_err(&radio->usbdev->dev,
+		"%s - usb_control_msg returned %i, request %i\n",
+			__func__, retval, request);
+	return retval;
 }
 
 /* return the device status.  This is, in effect, just whether it
 sees a stereo signal or not.  Pity. */
 static void dsbr100_getstat(struct dsbr100_device *radio)
 {
-	if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
+	int retval;
+
+	mutex_lock(&radio->lock);
+
+	retval = usb_control_msg(radio->usbdev,
+		usb_rcvctrlpipe(radio->usbdev, 0),
 		USB_REQ_GET_STATUS,
 		USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-		0x00 , 0x24, radio->transfer_buffer, 8, 300) < 0)
+		0x00 , 0x24, radio->transfer_buffer, 8, 300);
+
+	if (retval < 0) {
 		radio->stereo = -1;
-	else
+		dev_err(&radio->usbdev->dev,
+			"%s - usb_control_msg returned %i, request %i\n",
+				__func__, retval, USB_REQ_GET_STATUS);
+	} else {
 		radio->stereo = !(radio->transfer_buffer[0] & 0x01);
-}
+	}
 
+	mutex_unlock(&radio->lock);
+}
 
 /* USB subsystem interface begins here */
 
-/* handle unplugging of the device, release data structures
-if nothing keeps us from doing it.  If something is still
-keeping us busy, the release callback of v4l will take care
-of releasing it. */
+/*
+ * Handle unplugging of the device.
+ * We call video_unregister_device in any case.
+ * The last function called in this procedure is
+ * usb_dsbr100_video_device_release
+ */
 static void usb_dsbr100_disconnect(struct usb_interface *intf)
 {
 	struct dsbr100_device *radio = usb_get_intfdata(intf);
 
 	usb_set_intfdata (intf, NULL);
-	if (radio) {
-		video_unregister_device(radio->videodev);
-		radio->videodev = NULL;
-		if (radio->users) {
-			kfree(radio->transfer_buffer);
-			kfree(radio);
-		} else {
-			radio->removed = 1;
-		}
-	}
+
+	mutex_lock(&radio->lock);
+	radio->removed = 1;
+	mutex_unlock(&radio->lock);
+
+	video_unregister_device(&radio->videodev);
 }
 
 
@@ -276,6 +403,10 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 {
 	struct dsbr100_device *radio = video_drvdata(file);
 
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	if (v->index > 0)
 		return -EINVAL;
 
@@ -297,6 +428,12 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 static int vidioc_s_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
+	struct dsbr100_device *radio = video_drvdata(file);
+
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	if (v->index > 0)
 		return -EINVAL;
 
@@ -307,9 +444,15 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 				struct v4l2_frequency *f)
 {
 	struct dsbr100_device *radio = video_drvdata(file);
+	int retval;
+
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
 
 	radio->curfreq = f->frequency;
-	if (dsbr100_setfreq(radio, radio->curfreq) == -1)
+	retval = dsbr100_setfreq(radio, radio->curfreq);
+	if (retval < 0)
 		dev_warn(&radio->usbdev->dev, "Set frequency failed\n");
 	return 0;
 }
@@ -319,6 +462,10 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 {
 	struct dsbr100_device *radio = video_drvdata(file);
 
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = radio->curfreq;
 	return 0;
@@ -343,6 +490,10 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 {
 	struct dsbr100_device *radio = video_drvdata(file);
 
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		ctrl->value = radio->muted;
@@ -355,17 +506,24 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
 	struct dsbr100_device *radio = video_drvdata(file);
+	int retval;
+
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		if (ctrl->value) {
-			if (dsbr100_stop(radio) == -1) {
+			retval = dsbr100_stop(radio);
+			if (retval < 0) {
 				dev_warn(&radio->usbdev->dev,
 					 "Radio did not respond properly\n");
 				return -EBUSY;
 			}
 		} else {
-			if (dsbr100_start(radio) == -1) {
+			retval = dsbr100_start(radio);
+			if (retval < 0) {
 				dev_warn(&radio->usbdev->dev,
 					 "Radio did not respond properly\n");
 				return -EBUSY;
@@ -417,7 +575,8 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file)
 	radio->users = 1;
 	radio->muted = 1;
 
-	if (dsbr100_start(radio) < 0) {
+	retval = dsbr100_start(radio);
+	if (retval < 0) {
 		dev_warn(&radio->usbdev->dev,
 			 "Radio did not start up properly\n");
 		radio->users = 0;
@@ -426,9 +585,9 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file)
 	}
 
 	retval = dsbr100_setfreq(radio, radio->curfreq);
-
-	if (retval == -1)
-		printk(KERN_WARNING KBUILD_MODNAME ": Set frequency failed\n");
+	if (retval < 0)
+		dev_warn(&radio->usbdev->dev,
+			"set frequency failed\n");
 
 	unlock_kernel();
 	return 0;
@@ -437,17 +596,62 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file)
 static int usb_dsbr100_close(struct inode *inode, struct file *file)
 {
 	struct dsbr100_device *radio = video_drvdata(file);
+	int retval;
 
 	if (!radio)
 		return -ENODEV;
+
 	radio->users = 0;
-	if (radio->removed) {
-		kfree(radio->transfer_buffer);
-		kfree(radio);
+	if (!radio->removed) {
+		retval = dsbr100_stop(radio);
+		if (retval < 0) {
+			dev_warn(&radio->usbdev->dev,
+				"dsbr100_stop failed\n");
+		}
+
 	}
 	return 0;
 }
 
+/* Suspend device - stop device. */
+static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct dsbr100_device *radio = usb_get_intfdata(intf);
+	int retval;
+
+	retval = dsbr100_stop(radio);
+	if (retval < 0)
+		dev_warn(&intf->dev, "dsbr100_stop failed\n");
+
+	dev_info(&intf->dev, "going into suspend..\n");
+
+	return 0;
+}
+
+/* Resume device - start device. */
+static int usb_dsbr100_resume(struct usb_interface *intf)
+{
+	struct dsbr100_device *radio = usb_get_intfdata(intf);
+	int retval;
+
+	retval = dsbr100_start(radio);
+	if (retval < 0)
+		dev_warn(&intf->dev, "dsbr100_start failed\n");
+
+	dev_info(&intf->dev, "coming out of suspend..\n");
+
+	return 0;
+}
+
+/* free data structures */
+static void usb_dsbr100_video_device_release(struct video_device *videodev)
+{
+	struct dsbr100_device *radio = videodev_to_radio(videodev);
+
+	kfree(radio->transfer_buffer);
+	kfree(radio);
+}
+
 /* File system interface */
 static const struct file_operations usb_dsbr100_fops = {
 	.owner		= THIS_MODULE,
@@ -476,19 +680,19 @@ static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = {
 };
 
 /* V4L2 interface */
-static struct video_device dsbr100_videodev_template = {
+static struct video_device dsbr100_videodev_data = {
 	.name		= "D-Link DSB-R 100",
 	.fops		= &usb_dsbr100_fops,
 	.ioctl_ops 	= &usb_dsbr100_ioctl_ops,
-	.release	= video_device_release,
+	.release	= usb_dsbr100_video_device_release,
 };
 
-/* check if the device is present and register with v4l and
-usb if it is */
+/* check if the device is present and register with v4l and usb if it is */
 static int usb_dsbr100_probe(struct usb_interface *intf,
 				const struct usb_device_id *id)
 {
 	struct dsbr100_device *radio;
+	int retval;
 
 	radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL);
 
@@ -501,23 +705,18 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
 		kfree(radio);
 		return -ENOMEM;
 	}
-	radio->videodev = video_device_alloc();
 
-	if (!(radio->videodev)) {
-		kfree(radio->transfer_buffer);
-		kfree(radio);
-		return -ENOMEM;
-	}
-	memcpy(radio->videodev, &dsbr100_videodev_template,
-		sizeof(dsbr100_videodev_template));
+	mutex_init(&radio->lock);
+	radio->videodev = dsbr100_videodev_data;
+
 	radio->removed = 0;
 	radio->users = 0;
 	radio->usbdev = interface_to_usbdev(intf);
 	radio->curfreq = FREQ_MIN * FREQ_MUL;
-	video_set_drvdata(radio->videodev, radio);
-	if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr) < 0) {
-		dev_warn(&intf->dev, "Could not register video device\n");
-		video_device_release(radio->videodev);
+	video_set_drvdata(&radio->videodev, radio);
+	retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, radio_nr);
+	if (retval < 0) {
+		dev_err(&intf->dev, "couldn't register video device\n");
 		kfree(radio->transfer_buffer);
 		kfree(radio);
 		return -EIO;

+ 1 - 1
drivers/media/radio/radio-aimslab.c

@@ -1,7 +1,7 @@
 /* radiotrack (radioreveal) driver for Linux radio support
  * (c) 1997 M. Kirkwood
  * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
- * Converted to new API by Alan Cox <Alan.Cox@linux.org>
+ * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
  * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
  *
  * History:

+ 1 - 1
drivers/media/radio/radio-cadet.c

@@ -23,7 +23,7 @@
  * 2002-01-17	Adam Belay <ambx1@neo.rr.com>
  *		Updated to latest pnp code
  *
- * 2003-01-31	Alan Cox <alan@redhat.com>
+ * 2003-01-31	Alan Cox <alan@lxorguk.ukuu.org.uk>
  *		Cleaned up locking, delay code, general odds and ends
  *
  * 2006-07-30	Hans J. Koch <koch@hjk-az.de>

+ 1 - 1
drivers/media/radio/radio-gemtek.c

@@ -8,7 +8,7 @@
  *    RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
  *
  *    Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
- *    Converted to new API by Alan Cox <Alan.Cox@linux.org>
+ *    Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
  *    Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
  *
  * TODO: Allow for more than one of these foolish entities :-)

+ 91 - 32
drivers/media/radio/radio-mr800.c

@@ -72,6 +72,11 @@ MODULE_LICENSE("GPL");
 #define USB_AMRADIO_VENDOR 0x07ca
 #define USB_AMRADIO_PRODUCT 0xb800
 
+/* dev_warn macro with driver name */
+#define MR800_DRIVER_NAME "radio-mr800"
+#define amradio_dev_warn(dev, fmt, arg...)				\
+		dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
+
 /* Probably USB_TIMEOUT should be modified in module parameter */
 #define BUFFER_LENGTH 8
 #define USB_TIMEOUT 500
@@ -154,14 +159,14 @@ MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
 
 /* USB subsystem interface */
 static struct usb_driver usb_amradio_driver = {
-	.name			= "radio-mr800",
+	.name			= MR800_DRIVER_NAME,
 	.probe			= usb_amradio_probe,
 	.disconnect		= usb_amradio_disconnect,
 	.suspend		= usb_amradio_suspend,
 	.resume			= usb_amradio_resume,
 	.reset_resume		= usb_amradio_resume,
 	.id_table		= usb_amradio_device_table,
-	.supports_autosuspend	= 1,
+	.supports_autosuspend	= 0,
 };
 
 /* switch on radio. Send 8 bytes to device. */
@@ -202,6 +207,10 @@ static int amradio_stop(struct amradio_device *radio)
 	int retval;
 	int size;
 
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	mutex_lock(&radio->lock);
 
 	radio->buffer[0] = 0x00;
@@ -235,6 +244,10 @@ static int amradio_setfreq(struct amradio_device *radio, int freq)
 	int size;
 	unsigned short freq_send = 0x13 + (freq >> 3) / 25;
 
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	mutex_lock(&radio->lock);
 
 	radio->buffer[0] = 0x00;
@@ -288,18 +301,12 @@ static void usb_amradio_disconnect(struct usb_interface *intf)
 {
 	struct amradio_device *radio = usb_get_intfdata(intf);
 
-	usb_set_intfdata(intf, NULL);
+	mutex_lock(&radio->lock);
+	radio->removed = 1;
+	mutex_unlock(&radio->lock);
 
-	if (radio) {
-		video_unregister_device(radio->videodev);
-		radio->videodev = NULL;
-		if (radio->users) {
-			kfree(radio->buffer);
-			kfree(radio);
-		} else {
-			radio->removed = 1;
-		}
-	}
+	usb_set_intfdata(intf, NULL);
+	video_unregister_device(radio->videodev);
 }
 
 /* vidioc_querycap - query device capabilities */
@@ -320,6 +327,10 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	if (v->index > 0)
 		return -EINVAL;
 
@@ -346,6 +357,12 @@ static int vidioc_g_tuner(struct file *file, void *priv,
 static int vidioc_s_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
+	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	if (v->index > 0)
 		return -EINVAL;
 	return 0;
@@ -357,9 +374,14 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	radio->curfreq = f->frequency;
 	if (amradio_setfreq(radio, radio->curfreq) < 0)
-		warn("Set frequency failed");
+		amradio_dev_warn(&radio->videodev->dev,
+			"set frequency failed\n");
 	return 0;
 }
 
@@ -369,6 +391,10 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = radio->curfreq;
 	return 0;
@@ -382,8 +408,7 @@ static int vidioc_queryctrl(struct file *file, void *priv,
 
 	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
 		if (qc->id && qc->id == radio_qctrl[i].id) {
-			memcpy(qc, &(radio_qctrl[i]),
-						sizeof(*qc));
+			memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
 			return 0;
 		}
 	}
@@ -396,6 +421,10 @@ static int vidioc_g_ctrl(struct file *file, void *priv,
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		ctrl->value = radio->muted;
@@ -410,16 +439,22 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
 
+	/* safety check */
+	if (radio->removed)
+		return -EIO;
+
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		if (ctrl->value) {
 			if (amradio_stop(radio) < 0) {
-				warn("amradio_stop() failed");
+				amradio_dev_warn(&radio->videodev->dev,
+					"amradio_stop failed\n");
 				return -1;
 			}
 		} else {
 			if (amradio_start(radio) < 0) {
-				warn("amradio_start() failed");
+				amradio_dev_warn(&radio->videodev->dev,
+					"amradio_start failed\n");
 				return -1;
 			}
 		}
@@ -475,30 +510,38 @@ static int usb_amradio_open(struct inode *inode, struct file *file)
 	radio->muted = 1;
 
 	if (amradio_start(radio) < 0) {
-		warn("Radio did not start up properly");
+		amradio_dev_warn(&radio->videodev->dev,
+			"radio did not start up properly\n");
 		radio->users = 0;
 		unlock_kernel();
 		return -EIO;
 	}
 	if (amradio_setfreq(radio, radio->curfreq) < 0)
-		warn("Set frequency failed");
+		amradio_dev_warn(&radio->videodev->dev,
+			"set frequency failed\n");
 
 	unlock_kernel();
 	return 0;
 }
 
-/*close device - free driver structures */
+/*close device */
 static int usb_amradio_close(struct inode *inode, struct file *file)
 {
 	struct amradio_device *radio = video_get_drvdata(video_devdata(file));
+	int retval;
 
 	if (!radio)
 		return -ENODEV;
+
 	radio->users = 0;
-	if (radio->removed) {
-		kfree(radio->buffer);
-		kfree(radio);
+
+	if (!radio->removed) {
+		retval = amradio_stop(radio);
+		if (retval < 0)
+			amradio_dev_warn(&radio->videodev->dev,
+				"amradio_stop failed\n");
 	}
+
 	return 0;
 }
 
@@ -508,9 +551,9 @@ static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
 	struct amradio_device *radio = usb_get_intfdata(intf);
 
 	if (amradio_stop(radio) < 0)
-		warn("amradio_stop() failed");
+		dev_warn(&intf->dev, "amradio_stop failed\n");
 
-	info("radio-mr800: Going into suspend..");
+	dev_info(&intf->dev, "going into suspend..\n");
 
 	return 0;
 }
@@ -521,9 +564,9 @@ static int usb_amradio_resume(struct usb_interface *intf)
 	struct amradio_device *radio = usb_get_intfdata(intf);
 
 	if (amradio_start(radio) < 0)
-		warn("amradio_start() failed");
+		dev_warn(&intf->dev, "amradio_start failed\n");
 
-	info("radio-mr800: Coming out of suspend..");
+	dev_info(&intf->dev, "coming out of suspend..\n");
 
 	return 0;
 }
@@ -555,12 +598,24 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
 	.vidioc_s_input     = vidioc_s_input,
 };
 
+static void usb_amradio_device_release(struct video_device *videodev)
+{
+	struct amradio_device *radio = video_get_drvdata(videodev);
+
+	/* we call v4l to free radio->videodev */
+	video_device_release(videodev);
+
+	/* free rest memory */
+	kfree(radio->buffer);
+	kfree(radio);
+}
+
 /* V4L2 interface */
 static struct video_device amradio_videodev_template = {
 	.name		= "AverMedia MR 800 USB FM Radio",
 	.fops		= &usb_amradio_fops,
 	.ioctl_ops 	= &usb_amradio_ioctl_ops,
-	.release	= video_device_release,
+	.release	= usb_amradio_device_release,
 };
 
 /* check if the device is present and register with v4l and
@@ -602,7 +657,7 @@ static int usb_amradio_probe(struct usb_interface *intf,
 
 	video_set_drvdata(radio->videodev, radio);
 	if (video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr)) {
-		warn("Could not register video device");
+		dev_warn(&intf->dev, "could not register video device\n");
 		video_device_release(radio->videodev);
 		kfree(radio->buffer);
 		kfree(radio);
@@ -617,9 +672,13 @@ static int __init amradio_init(void)
 {
 	int retval = usb_register(&usb_amradio_driver);
 
-	info(DRIVER_VERSION " " DRIVER_DESC);
+	pr_info(KBUILD_MODNAME
+		": version " DRIVER_VERSION " " DRIVER_DESC "\n");
+
 	if (retval)
-		err("usb_register failed. Error number %d", retval);
+		pr_err(KBUILD_MODNAME
+			": usb_register failed. Error number %d\n", retval);
+
 	return retval;
 }
 

+ 1 - 1
drivers/media/radio/radio-rtrack2.c

@@ -1,7 +1,7 @@
 /* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
  *
  * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
- * Converted to new API by Alan Cox <Alan.Cox@linux.org>
+ * Converted to new API by Alan Cox <alan@lxorguk.ukuu.org.uk>
  * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
  *
  * TODO: Allow for more than one of these foolish entities :-)

+ 1 - 1
drivers/media/radio/radio-sf16fmi.c

@@ -3,7 +3,7 @@
  * (c) 1997 M. Kirkwood
  * (c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz
  *
- * Fitted to new interface by Alan Cox <alan.cox@linux.org>
+ * Fitted to new interface by Alan Cox <alan@lxorguk.ukuu.org.uk>
  * Made working and cleaned up functions <mikael.hedin@irf.se>
  * Support for ISAPnP by Ladislav Michl <ladis@psi.cz>
  *

+ 42 - 6
drivers/media/video/Kconfig

@@ -184,7 +184,7 @@ config VIDEO_MSP3400
 
 config VIDEO_CS5345
 	tristate "Cirrus Logic CS5345 audio ADC"
-	depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for the Cirrus Logic CS5345 24-bit, 192 kHz
 	  stereo A/D converter.
@@ -204,7 +204,7 @@ config VIDEO_CS53L32A
 
 config VIDEO_M52790
        tristate "Mitsubishi M52790 A/V switch"
-       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+       depends on VIDEO_V4L2 && I2C
        ---help---
 	 Support for the Mitsubishi M52790 A/V switch.
 
@@ -242,7 +242,7 @@ config VIDEO_WM8739
 
 config VIDEO_VP27SMPX
 	tristate "Panasonic VP27s internal MPX"
-	depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+	depends on VIDEO_V4L2 && I2C
 	---help---
 	  Support for the internal MPX of the Panasonic VP27s tuner.
 
@@ -361,6 +361,17 @@ config VIDEO_SAA7191
 	  To compile this driver as a module, choose M here: the
 	  module will be called saa7191.
 
+config VIDEO_TVP514X
+	tristate "Texas Instruments TVP514x video decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the TI TVP5146/47
+	  decoder. It is currently working with the TI OMAP3 camera
+	  controller.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tvp514x.
+
 config VIDEO_TVP5150
 	tristate "Texas Instruments TVP5150 video decoder"
 	depends on VIDEO_V4L2 && I2C
@@ -387,7 +398,7 @@ comment "MPEG video encoders"
 
 config VIDEO_CX2341X
 	tristate "Conexant CX2341x MPEG encoders"
-	depends on VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_COMMON
+	depends on VIDEO_V4L2 && VIDEO_V4L2_COMMON
 	---help---
 	  Support for the Conexant CX23416 MPEG encoders
 	  and CX23415 MPEG encoder/decoders.
@@ -725,10 +736,16 @@ config MT9M001_PCA9536_SWITCH
 	  extender to switch between 8 and 10 bit datawidth modes
 
 config SOC_CAMERA_MT9M111
-	tristate "mt9m111 support"
+	tristate "mt9m111 and mt9m112 support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This driver supports MT9M111 and MT9M112 cameras from Micron
+
+config SOC_CAMERA_MT9T031
+	tristate "mt9t031 support"
 	depends on SOC_CAMERA && I2C
 	help
-	  This driver supports MT9M111 cameras from Micron
+	  This driver supports MT9T031 cameras from Micron.
 
 config SOC_CAMERA_MT9V022
 	tristate "mt9v022 support"
@@ -744,12 +761,24 @@ config MT9V022_PCA9536_SWITCH
 	  Select this if your MT9V022 camera uses a PCA9536 I2C GPIO
 	  extender to switch between 8 and 10 bit datawidth modes
 
+config SOC_CAMERA_TW9910
+	tristate "tw9910 support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a tw9910 video driver
+
 config SOC_CAMERA_PLATFORM
 	tristate "platform camera support"
 	depends on SOC_CAMERA
 	help
 	  This is a generic SoC camera platform driver, useful for testing
 
+config SOC_CAMERA_OV772X
+	tristate "ov772x camera support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a ov772x camera driver
+
 config VIDEO_PXA27x
 	tristate "PXA27x Quick Capture Interface driver"
 	depends on VIDEO_DEV && PXA27x && SOC_CAMERA
@@ -764,6 +793,13 @@ config VIDEO_SH_MOBILE_CEU
 	---help---
 	  This is a v4l2 driver for the SuperH Mobile CEU Interface
 
+config VIDEO_OMAP2
+	tristate "OMAP2 Camera Capture Interface driver"
+	depends on VIDEO_DEV && ARCH_OMAP2
+	select VIDEOBUF_DMA_SG
+	---help---
+	  This is a v4l2 driver for the TI OMAP2 camera capture interface
+
 #
 # USB Multimedia device configuration
 #

+ 10 - 2
drivers/media/video/Makefile

@@ -8,9 +8,11 @@ msp3400-objs	:=	msp3400-driver.o msp3400-kthreads.o
 
 stkwebcam-objs	:=	stk-webcam.o stk-sensor.o
 
-videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o
+omap2cam-objs	:=	omap24xxcam.o omap24xxcam-dma.o
 
-obj-$(CONFIG_VIDEO_DEV) += videodev.o compat_ioctl32.o v4l2-int-device.o
+videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-subdev.o
+
+obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-compat-ioctl32.o v4l2-int-device.o
 
 obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
 
@@ -25,6 +27,7 @@ obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
 obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
 obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
 obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
+obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
 
 obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
 obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
@@ -66,6 +69,7 @@ obj-$(CONFIG_VIDEO_CX88) += cx88/
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
 obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
+obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
 obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
@@ -129,11 +133,15 @@ obj-$(CONFIG_VIDEO_CX23885) += cx23885/
 
 obj-$(CONFIG_VIDEO_PXA27x)	+= pxa_camera.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)	+= sh_mobile_ceu_camera.o
+obj-$(CONFIG_VIDEO_OMAP2)		+= omap2cam.o
 obj-$(CONFIG_SOC_CAMERA)	+= soc_camera.o
 obj-$(CONFIG_SOC_CAMERA_MT9M001)	+= mt9m001.o
 obj-$(CONFIG_SOC_CAMERA_MT9M111)	+= mt9m111.o
+obj-$(CONFIG_SOC_CAMERA_MT9T031)	+= mt9t031.o
 obj-$(CONFIG_SOC_CAMERA_MT9V022)	+= mt9v022.o
+obj-$(CONFIG_SOC_CAMERA_OV772X)		+= ov772x.o
 obj-$(CONFIG_SOC_CAMERA_PLATFORM)	+= soc_camera_platform.o
+obj-$(CONFIG_SOC_CAMERA_TW9910)		+= tw9910.o
 
 obj-$(CONFIG_VIDEO_AU0828) += au0828/
 

+ 2 - 3
drivers/media/video/arv.c

@@ -396,8 +396,7 @@ out_up:
 	return ret;
 }
 
-static int ar_do_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, void *arg)
+static int ar_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct ar_device *ar = video_get_drvdata(dev);
@@ -543,7 +542,7 @@ static int ar_do_ioctl(struct inode *inode, struct file *file,
 static int ar_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 		    unsigned long arg)
 {
-	return video_usercopy(inode, file, cmd, arg, ar_do_ioctl);
+	return video_usercopy(file, cmd, arg, ar_do_ioctl);
 }
 
 #if USE_INT

+ 0 - 274
drivers/media/video/bt8xx/bt832.c

@@ -1,274 +0,0 @@
-/* Driver for Bt832 CMOS Camera Video Processor
-    i2c-addresses: 0x88 or 0x8a
-
-  The BT832 interfaces to a Quartzsight Digital Camera (352x288, 25 or 30 fps)
-  via a 9 pin connector ( 4-wire SDATA, 2-wire i2c, SCLK, VCC, GND).
-  It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly
-  connected to bt848/bt878 GPIO pins on this purpose.
-  (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets)
-
-  Supported Cards:
-  -  Pixelview Rev.4E: 0x8a
-		GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 !
-
-  (c) Gunther Mayer, 2002
-
-  STATUS:
-  - detect chip and hexdump
-  - reset chip and leave low power mode
-  - detect camera present
-
-  TODO:
-  - make it work (find correct setup for Bt832 and Bt878)
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/types.h>
-#include <linux/videodev.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <media/v4l2-common.h>
-
-#include "bttv.h"
-#include "bt832.h"
-
-MODULE_LICENSE("GPL");
-
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { I2C_ADDR_BT832_ALT1>>1, I2C_ADDR_BT832_ALT2>>1,
-				       I2C_CLIENT_END };
-I2C_CLIENT_INSMOD;
-
-int debug;    /* debug output */
-module_param(debug,            int, 0644);
-
-/* ---------------------------------------------------------------------- */
-
-static int bt832_detach(struct i2c_client *client);
-
-
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
-struct bt832 {
-	struct i2c_client client;
-};
-
-int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf)
-{
-	int i,rc;
-	buf[0]=0x80; // start at register 0 with auto-increment
-	if (1 != (rc = i2c_master_send(i2c_client_s,buf,1)))
-		v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 1)\n",rc);
-
-	for(i=0;i<65;i++)
-		buf[i]=0;
-	if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65)))
-		v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 65)\n",rc);
-
-	// Note: On READ the first byte is the current index
-	//  (e.g. 0x80, what we just wrote)
-
-	if(debug>1) {
-		int i;
-		v4l_dbg(2, debug,i2c_client_s,"hexdump:");
-		for(i=1;i<65;i++) {
-			if(i!=1) {
-				if(((i-1)%8)==0) printk(" ");
-				if(((i-1)%16)==0) {
-					printk("\n");
-					v4l_dbg(2, debug,i2c_client_s,"hexdump:");
-				}
-			}
-			printk(" %02x",buf[i]);
-		}
-		printk("\n");
-	}
-	return 0;
-}
-
-// Return: 1 (is a bt832), 0 (No bt832 here)
-int bt832_init(struct i2c_client *i2c_client_s)
-{
-	unsigned char *buf;
-	int rc;
-
-	buf=kmalloc(65,GFP_KERNEL);
-	if (!buf) {
-		v4l_err(&t->client,
-			"Unable to allocate memory. Detaching.\n");
-		return 0;
-	}
-	bt832_hexdump(i2c_client_s,buf);
-
-	if(buf[0x40] != 0x31) {
-		v4l_err(i2c_client_s,"This i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
-		kfree(buf);
-		return 0;
-	}
-
-	v4l_err(i2c_client_s,"Write 0 tp VPSTATUS\n");
-	buf[0]=BT832_VP_STATUS; // Reg.52
-	buf[1]= 0x00;
-	if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
-		v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc);
-
-	bt832_hexdump(i2c_client_s,buf);
-
-
-	// Leave low power mode:
-	v4l_err(i2c_client_s,"leave low power mode.\n");
-	buf[0]=BT832_CAM_SETUP0; //0x39 57
-	buf[1]=0x08;
-	if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
-		v4l_err(i2c_client_s,"i2c i/o error LLPM: rc == %d (should be 2)\n",rc);
-
-	bt832_hexdump(i2c_client_s,buf);
-
-	v4l_info(i2c_client_s,"Write 0 tp VPSTATUS\n");
-	buf[0]=BT832_VP_STATUS; // Reg.52
-	buf[1]= 0x00;
-	if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
-		v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc);
-
-	bt832_hexdump(i2c_client_s,buf);
-
-
-	// Enable Output
-	v4l_info(i2c_client_s,"Enable Output\n");
-	buf[0]=BT832_VP_CONTROL1; // Reg.40
-	buf[1]= 0x27 & (~0x01); // Default | !skip
-	if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
-		v4l_err(i2c_client_s,"i2c i/o error EO: rc == %d (should be 2)\n",rc);
-
-	bt832_hexdump(i2c_client_s,buf);
-
-
-	// for testing (even works when no camera attached)
-	v4l_info(i2c_client_s,"*** Generate NTSC M Bars *****\n");
-	buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42
-	buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally
-	if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
-		v4l_info(i2c_client_s,"i2c i/o error MBAR: rc == %d (should be 2)\n",rc);
-
-	v4l_info(i2c_client_s,"Camera Present: %s\n",
-		(buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no");
-
-	bt832_hexdump(i2c_client_s,buf);
-	kfree(buf);
-	return 1;
-}
-
-
-
-static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
-{
-	struct bt832 *t;
-
-	client_template.adapter = adap;
-	client_template.addr    = addr;
-
-	if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL)))
-		return -ENOMEM;
-	t->client = client_template;
-	i2c_set_clientdata(&t->client, t);
-	i2c_attach_client(&t->client);
-
-	v4l_info(&t->client,"chip found @ 0x%x\n", addr<<1);
-
-	if(! bt832_init(&t->client)) {
-		bt832_detach(&t->client);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int bt832_probe(struct i2c_adapter *adap)
-{
-	if (adap->class & I2C_CLASS_TV_ANALOG)
-		return i2c_probe(adap, &addr_data, bt832_attach);
-	return 0;
-}
-
-static int bt832_detach(struct i2c_client *client)
-{
-	struct bt832 *t = i2c_get_clientdata(client);
-
-	v4l_info(&t->client,"dettach\n");
-	i2c_detach_client(client);
-	kfree(t);
-	return 0;
-}
-
-static int
-bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-	struct bt832 *t = i2c_get_clientdata(client);
-
-	if (debug>1)
-		v4l_i2c_print_ioctl(&t->client,cmd);
-
-	switch (cmd) {
-		case BT832_HEXDUMP: {
-			unsigned char *buf;
-			buf = kmalloc(65, GFP_KERNEL);
-			if (!buf) {
-				v4l_err(&t->client,
-					"Unable to allocate memory\n");
-				break;
-			}
-			bt832_hexdump(&t->client,buf);
-			kfree(buf);
-		}
-		break;
-		case BT832_REATTACH:
-			v4l_info(&t->client,"re-attach\n");
-			i2c_del_driver(&driver);
-			i2c_add_driver(&driver);
-		break;
-	}
-	return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_driver driver = {
-	.driver = {
-		.name   = "bt832",
-	},
-	.id             = 0, /* FIXME */
-	.attach_adapter = bt832_probe,
-	.detach_client  = bt832_detach,
-	.command        = bt832_command,
-};
-static struct i2c_client client_template =
-{
-	.name       = "bt832",
-	.driver     = &driver,
-};
-
-
-static int __init bt832_init_module(void)
-{
-	return i2c_add_driver(&driver);
-}
-
-static void __exit bt832_cleanup_module(void)
-{
-	i2c_del_driver(&driver);
-}
-
-module_init(bt832_init_module);
-module_exit(bt832_cleanup_module);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */

+ 0 - 305
drivers/media/video/bt8xx/bt832.h

@@ -1,305 +0,0 @@
-/* Bt832 CMOS Camera Video Processor (VP)
-
- The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS
-  color digital camera directly to video capture devices via an 8-bit,
-  4:2:2 YUV or YCrCb video interface.
-
- i2c addresses: 0x88 or 0x8a
- */
-
-/* The 64 registers: */
-
-// Input Processor
-#define BT832_OFFSET 0
-#define BT832_RCOMP	1
-#define BT832_G1COMP	2
-#define BT832_G2COMP	3
-#define BT832_BCOMP	4
-// Exposures:
-#define BT832_FINEH	5
-#define BT832_FINEL	6
-#define BT832_COARSEH	7
-#define BT832_COARSEL   8
-#define BT832_CAMGAIN	9
-// Main Processor:
-#define BT832_M00	10
-#define BT832_M01	11
-#define BT832_M02	12
-#define BT832_M10	13
-#define BT832_M11	14
-#define BT832_M12	15
-#define BT832_M20	16
-#define BT832_M21	17
-#define BT832_M22	18
-#define BT832_APCOR	19
-#define BT832_GAMCOR	20
-// Level Accumulator Inputs
-#define BT832_VPCONTROL2	21
-#define BT832_ZONECODE0	22
-#define BT832_ZONECODE1	23
-#define BT832_ZONECODE2	24
-#define BT832_ZONECODE3	25
-// Level Accumulator Outputs:
-#define BT832_RACC	26
-#define BT832_GACC	27
-#define BT832_BACC	28
-#define BT832_BLACKACC	29
-#define BT832_EXP_AGC	30
-#define BT832_LACC0	31
-#define BT832_LACC1	32
-#define BT832_LACC2	33
-#define BT832_LACC3	34
-#define BT832_LACC4	35
-#define BT832_LACC5	36
-#define BT832_LACC6	37
-#define BT832_LACC7	38
-// System:
-#define BT832_VP_CONTROL0	39
-#define BT832_VP_CONTROL1	40
-#define BT832_THRESH	41
-#define BT832_VP_TESTCONTROL0	42
-#define BT832_VP_DMCODE	43
-#define BT832_ACB_CONFIG	44
-#define BT832_ACB_GNBASE	45
-#define BT832_ACB_MU	46
-#define BT832_CAM_TEST0	47
-#define BT832_AEC_CONFIG	48
-#define BT832_AEC_TL	49
-#define BT832_AEC_TC	50
-#define BT832_AEC_TH	51
-// Status:
-#define BT832_VP_STATUS	52
-#define BT832_VP_LINECOUNT	53
-#define BT832_CAM_DEVICEL	54 // e.g. 0x19
-#define BT832_CAM_DEVICEH	55 // e.g. 0x40  == 0x194 Mask0, 0x194 = 404 decimal (VVL-404 camera)
-#define BT832_CAM_STATUS		56
- #define BT832_56_CAMERA_PRESENT 0x20
-//Camera Setups:
-#define BT832_CAM_SETUP0	57
-#define BT832_CAM_SETUP1	58
-#define BT832_CAM_SETUP2	59
-#define BT832_CAM_SETUP3	60
-// System:
-#define BT832_DEFCOR		61
-#define BT832_VP_TESTCONTROL1	62
-#define BT832_DEVICE_ID		63
-# define BT832_DEVICE_ID__31		0x31 // Bt832 has ID 0x31
-
-/* STMicroelectronivcs VV5404 camera module
-   i2c: 0x20: sensor address
-   i2c: 0xa0: eeprom for ccd defect map
- */
-#define VV5404_device_h		0x00  // 0x19
-#define VV5404_device_l		0x01  // 0x40
-#define VV5404_status0		0x02
-#define VV5404_linecountc	0x03 // current line counter
-#define VV5404_linecountl	0x04
-#define VV5404_setup0		0x10
-#define VV5404_setup1		0x11
-#define VV5404_setup2		0x12
-#define VV5404_setup4		0x14
-#define VV5404_setup5		0x15
-#define VV5404_fine_h		0x20  // fine exposure
-#define VV5404_fine_l		0x21
-#define VV5404_coarse_h		0x22  //coarse exposure
-#define VV5404_coarse_l		0x23
-#define VV5404_gain		0x24 // ADC pre-amp gain setting
-#define VV5404_clk_div		0x25
-#define VV5404_cr		0x76 // control register
-#define VV5404_as0		0x77 // ADC setup register
-
-
-// IOCTL
-#define BT832_HEXDUMP   _IOR('b',1,int)
-#define BT832_REATTACH	_IOR('b',2,int)
-
-/* from BT8x8VXD/capdrv/dialogs.cpp */
-
-/*
-typedef enum { SVI, Logitech, Rockwell } CAMERA;
-
-static COMBOBOX_ENTRY gwCameraOptions[] =
-{
-   { SVI,      "Silicon Vision 512N" },
-   { Logitech, "Logitech VideoMan 1.3"  },
-   { Rockwell, "Rockwell QuartzSight PCI 1.0"   }
-};
-
-// SRAM table values
-//===========================================================================
-typedef enum { TGB_NTSC624, TGB_NTSC780, TGB_NTSC858, TGB_NTSC392 } TimeGenByte;
-
-BYTE SRAMTable[][ 60 ] =
-{
-   // TGB_NTSC624
-   {
-      0x33, // size of table = 51
-      0x0E, 0xC0, 0x00, 0x00, 0x90, 0x02, 0x03, 0x10, 0x03, 0x06,
-      0x10, 0x04, 0x12, 0x12, 0x05, 0x02, 0x13, 0x04, 0x19, 0x00,
-      0x04, 0x39, 0x00, 0x06, 0x59, 0x08, 0x03, 0x85, 0x08, 0x07,
-      0x03, 0x50, 0x00, 0x91, 0x40, 0x00, 0x11, 0x01, 0x01, 0x4D,
-      0x0D, 0x02, 0x03, 0x11, 0x01, 0x05, 0x37, 0x00, 0x37, 0x21, 0x00
-   },
-   // TGB_NTSC780
-   {
-      0x33, // size of table = 51
-      0x0e, 0xc0, 0x00, 0x00, 0x90, 0xe2, 0x03, 0x10, 0x03, 0x06,
-      0x10, 0x34, 0x12, 0x12, 0x65, 0x02, 0x13, 0x24, 0x19, 0x00,
-      0x24, 0x39, 0x00, 0x96, 0x59, 0x08, 0x93, 0x85, 0x08, 0x97,
-      0x03, 0x50, 0x50, 0xaf, 0x40, 0x30, 0x5f, 0x01, 0xf1, 0x7f,
-      0x0d, 0xf2, 0x03, 0x11, 0xf1, 0x05, 0x37, 0x30, 0x85, 0x21, 0x50
-   },
-   // TGB_NTSC858
-   {
-      0x33, // size of table = 51
-      0x0c, 0xc0, 0x00, 0x00, 0x90, 0xc2, 0x03, 0x10, 0x03, 0x06,
-      0x10, 0x34, 0x12, 0x12, 0x65, 0x02, 0x13, 0x24, 0x19, 0x00,
-      0x24, 0x39, 0x00, 0x96, 0x59, 0x08, 0x93, 0x83, 0x08, 0x97,
-      0x03, 0x50, 0x30, 0xc0, 0x40, 0x30, 0x86, 0x01, 0x01, 0xa6,
-      0x0d, 0x62, 0x03, 0x11, 0x61, 0x05, 0x37, 0x30, 0xac, 0x21, 0x50
-   },
-   // TGB_NTSC392
-   // This table has been modified to be used for Fusion Rev D
-   {
-      0x2A, // size of table = 42
-      0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24,
-      0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10,
-      0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00,
-      0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3,
-      0x20, 0x00
-   }
-};
-
-//===========================================================================
-// This is the structure of the camera specifications
-//===========================================================================
-typedef struct tag_cameraSpec
-{
-   SignalFormat signal;       // which digital signal format the camera has
-   VideoFormat  vidFormat;    // video standard
-   SyncVideoRef syncRef;      // which sync video reference is used
-   State        syncOutput;   // enable sync output for sync video input?
-   DecInputClk  iClk;         // which input clock is used
-   TimeGenByte  tgb;          // which timing generator byte does the camera use
-   int          HReset;       // select 64, 48, 32, or 16 CLKx1 for HReset
-   PLLFreq      pllFreq;      // what synthesized frequency to set PLL to
-   VSIZEPARMS   vSize;        // video size the camera produces
-   int          lineCount;    // expected total number of half-line per frame - 1
-   BOOL         interlace;    // interlace signal?
-} CameraSpec;
-
-//===========================================================================
-// <UPDATE REQUIRED>
-// Camera specifications database. Update this table whenever camera spec
-// has been changed or added/deleted supported camera models
-//===========================================================================
-static CameraSpec dbCameraSpec[ N_CAMERAOPTIONS ] =
-{  // Silicon Vision 512N
-   { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC624, 64, KHz19636,
-      // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace
-   {         512,           0x64,       480,    0x13,      240 },         0,       TRUE
-   },
-   // Logitech VideoMan 1.3
-   { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC780, 64, KHz24545,
-      // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace
-      {      640,           0x80,       480,    0x1A,      240 },         0,       TRUE
-   },
-   // Rockwell QuartzSight
-   // Note: Fusion Rev D (rev ID 0x02) and later supports 16 pixels for HReset which is preferable.
-   //       Use 32 for earlier version of hardware. Clkx1_HDELAY also changed from 0x27 to 0x20.
-   { Signal_CCIR656, VFormat_NTSC, VRef_alignedCb, Off, DecClk_GPCLK, TGB_NTSC392, 16, KHz28636,
-      // Clkx1_HACTIVE, Clkx1_HDELAY, VActive, VDelay, linesPerField; lineCount, Interlace
-      {      352,           0x20,       576,    0x08,      288 },       607,       FALSE
-   }
-};
-*/
-
-/*
-The corresponding APIs required to be invoked are:
-SetConnector( ConCamera, TRUE/FALSE );
-SetSignalFormat( spec.signal );
-SetVideoFormat( spec.vidFormat );
-SetSyncVideoRef( spec.syncRef );
-SetEnableSyncOutput( spec.syncOutput );
-SetTimGenByte( SRAMTable[ spec.tgb ], SRAMTableSize[ spec.tgb ] );
-SetHReset( spec.HReset );
-SetPLL( spec.pllFreq );
-SetDecInputClock( spec.iClk );
-SetVideoInfo( spec.vSize );
-SetTotalLineCount( spec.lineCount );
-SetInterlaceMode( spec.interlace );
-*/
-
-/* from web:
- Video Sampling
-Digital video is a sampled form of analog video. The most common sampling schemes in use today are:
-		  Pixel Clock   Horiz    Horiz    Vert
-		   Rate         Total    Active
-NTSC square pixel  12.27 MHz    780      640      525
-NTSC CCIR-601      13.5  MHz    858      720      525
-NTSC 4FSc          14.32 MHz    910      768      525
-PAL  square pixel  14.75 MHz    944      768      625
-PAL  CCIR-601      13.5  MHz    864      720      625
-PAL  4FSc          17.72 MHz   1135      948      625
-
-For the CCIR-601 standards, the sampling is based on a static orthogonal sampling grid. The luminance component (Y) is sampled at 13.5 MHz, while the two color difference signals, Cr and Cb are sampled at half that, or 6.75 MHz. The Cr and Cb samples are colocated with alternate Y samples, and they are taken at the same position on each line, such that one sample is coincident with the 50% point of the falling edge of analog sync. The samples are coded to either 8 or 10 bits per component.
-*/
-
-/* from DScaler:*/
-/*
-//===========================================================================
-// CCIR656 Digital Input Support: The tables were taken from DScaler proyect
-//
-// 13 Dec 2000 - Michael Eskin, Conexant Systems - Initial version
-//
-
-//===========================================================================
-// Timing generator SRAM table values for CCIR601 720x480 NTSC
-//===========================================================================
-// For NTSC CCIR656
-BYTE BtCard::SRAMTable_NTSC[] =
-{
-    // SRAM Timing Table for NTSC
-    0x0c, 0xc0, 0x00,
-    0x00, 0x90, 0xc2,
-    0x03, 0x10, 0x03,
-    0x06, 0x10, 0x34,
-    0x12, 0x12, 0x65,
-    0x02, 0x13, 0x24,
-    0x19, 0x00, 0x24,
-    0x39, 0x00, 0x96,
-    0x59, 0x08, 0x93,
-    0x83, 0x08, 0x97,
-    0x03, 0x50, 0x30,
-    0xc0, 0x40, 0x30,
-    0x86, 0x01, 0x01,
-    0xa6, 0x0d, 0x62,
-    0x03, 0x11, 0x61,
-    0x05, 0x37, 0x30,
-    0xac, 0x21, 0x50
-};
-
-//===========================================================================
-// Timing generator SRAM table values for CCIR601 720x576 NTSC
-//===========================================================================
-// For PAL CCIR656
-BYTE BtCard::SRAMTable_PAL[] =
-{
-    // SRAM Timing Table for PAL
-    0x36, 0x11, 0x01,
-    0x00, 0x90, 0x02,
-    0x05, 0x10, 0x04,
-    0x16, 0x14, 0x05,
-    0x11, 0x00, 0x04,
-    0x12, 0xc0, 0x00,
-    0x31, 0x00, 0x06,
-    0x51, 0x08, 0x03,
-    0x89, 0x08, 0x07,
-    0xc0, 0x44, 0x00,
-    0x81, 0x01, 0x01,
-    0xa9, 0x0d, 0x02,
-    0x02, 0x50, 0x03,
-    0x37, 0x3d, 0x00,
-    0xaf, 0x21, 0x00,
-};
-*/

+ 54 - 18
drivers/media/video/bt8xx/bttv-cards.c

@@ -44,7 +44,6 @@
 
 /* fwd decl */
 static void boot_msp34xx(struct bttv *btv, int pin);
-static void boot_bt832(struct bttv *btv);
 static void hauppauge_eeprom(struct bttv *btv);
 static void avermedia_eeprom(struct bttv *btv);
 static void osprey_eeprom(struct bttv *btv, const u8 ee[256]);
@@ -2217,9 +2216,9 @@ struct tvcard bttv_tvcards[] = {
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 	},
-	[BTTV_BOARD_VD009X1_MINIDIN] = {
+	[BTTV_BOARD_VD009X1_VD011_MINIDIN] = {
 		/* M.Klahr@phytec.de */
-		.name           = "PHYTEC VD-009-X1 MiniDIN (bt878)",
+		.name           = "PHYTEC VD-009-X1 VD-011 MiniDIN (bt878)",
 		.video_inputs   = 4,
 		.audio_inputs   = 0,
 		.tuner          = UNSET, /* card has no tuner */
@@ -2227,14 +2226,14 @@ struct tvcard bttv_tvcards[] = {
 		.gpiomask       = 0x00,
 		.muxsel         = { 2, 3, 1, 0 },
 		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
-		.needs_tvaudio  = 1,
+		.needs_tvaudio  = 0,
 		.pll            = PLL_28,
 		.tuner_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 	},
-	[BTTV_BOARD_VD009X1_COMBI] = {
-		.name           = "PHYTEC VD-009-X1 Combi (bt878)",
+	[BTTV_BOARD_VD009X1_VD011_COMBI] = {
+		.name           = "PHYTEC VD-009-X1 VD-011 Combi (bt878)",
 		.video_inputs   = 4,
 		.audio_inputs   = 0,
 		.tuner          = UNSET, /* card has no tuner */
@@ -2242,7 +2241,7 @@ struct tvcard bttv_tvcards[] = {
 		.gpiomask       = 0x00,
 		.muxsel         = { 2, 3, 1, 1 },
 		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
-		.needs_tvaudio  = 1,
+		.needs_tvaudio  = 0,
 		.pll            = PLL_28,
 		.tuner_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
@@ -3061,6 +3060,54 @@ struct tvcard bttv_tvcards[] = {
 		.pll            = PLL_28,
 		.has_radio      = 1,
 		.has_remote     = 1,
+	},
+		[BTTV_BOARD_VD012] = {
+		/* D.Heer@Phytec.de */
+		.name           = "PHYTEC VD-012 (bt878)",
+		.video_inputs   = 4,
+		.audio_inputs   = 0,
+		.tuner          = UNSET, /* card has no tuner */
+		.svhs           = UNSET, /* card has no s-video */
+		.gpiomask       = 0x00,
+		.muxsel         = { 0, 2, 3, 1 },
+		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+		.needs_tvaudio  = 0,
+		.pll            = PLL_28,
+		.tuner_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+	},
+		[BTTV_BOARD_VD012_X1] = {
+		/* D.Heer@Phytec.de */
+		.name           = "PHYTEC VD-012-X1 (bt878)",
+		.video_inputs   = 4,
+		.audio_inputs   = 0,
+		.tuner          = UNSET, /* card has no tuner */
+		.svhs           = 3,
+		.gpiomask       = 0x00,
+		.muxsel         = { 2, 3, 1 },
+		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+		.needs_tvaudio  = 0,
+		.pll            = PLL_28,
+		.tuner_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+	},
+		[BTTV_BOARD_VD012_X2] = {
+		/* D.Heer@Phytec.de */
+		.name           = "PHYTEC VD-012-X2 (bt878)",
+		.video_inputs   = 4,
+		.audio_inputs   = 0,
+		.tuner          = UNSET, /* card has no tuner */
+		.svhs           = 3,
+		.gpiomask       = 0x00,
+		.muxsel         = { 3, 2, 1 },
+		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+		.needs_tvaudio  = 0,
+		.pll            = PLL_28,
+		.tuner_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
 	}
 };
 
@@ -3673,13 +3720,6 @@ void __devinit bttv_init_card2(struct bttv *btv)
 	if (bttv_tvcards[btv->c.type].audio_mode_gpio)
 		btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio;
 
-	if (bttv_tvcards[btv->c.type].digital_mode == DIGITAL_MODE_CAMERA) {
-		/* detect Bt832 chip for quartzsight digital camera */
-		if ((bttv_I2CRead(btv, I2C_ADDR_BT832_ALT1, "Bt832") >=0) ||
-		    (bttv_I2CRead(btv, I2C_ADDR_BT832_ALT2, "Bt832") >=0))
-			boot_bt832(btv);
-	}
-
 	if (!autoload)
 		return;
 
@@ -4075,10 +4115,6 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin)
 		       "init [%d]\n", btv->c.nr, pin);
 }
 
-static void __devinit boot_bt832(struct bttv *btv)
-{
-}
-
 /* ----------------------------------------------------------------------- */
 /*  Imagenation L-Model PXC200 Framegrabber */
 /*  This is basically the same procedure as

+ 3 - 4
drivers/media/video/bt8xx/bttv-gpio.c

@@ -42,7 +42,7 @@ static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
 	struct bttv_sub_driver *sub = to_bttv_sub_drv(drv);
 	int len = strlen(sub->wanted);
 
-	if (0 == strncmp(dev->bus_id, sub->wanted, len))
+	if (0 == strncmp(dev_name(dev), sub->wanted, len))
 		return 1;
 	return 0;
 }
@@ -91,15 +91,14 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
 	sub->dev.parent  = &core->pci->dev;
 	sub->dev.bus     = &bttv_sub_bus_type;
 	sub->dev.release = release_sub_device;
-	snprintf(sub->dev.bus_id,sizeof(sub->dev.bus_id),"%s%d",
-		 name, core->nr);
+	dev_set_name(&sub->dev, "%s%d", name, core->nr);
 
 	err = device_register(&sub->dev);
 	if (0 != err) {
 		kfree(sub);
 		return err;
 	}
-	printk("bttv%d: add subdevice \"%s\"\n", core->nr, sub->dev.bus_id);
+	printk("bttv%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
 	list_add_tail(&sub->list,&core->subs);
 	return 0;
 }

+ 7 - 3
drivers/media/video/bt8xx/bttv.h

@@ -130,8 +130,8 @@
 #define BTTV_BOARD_XGUARD                  0x67
 #define BTTV_BOARD_NEBULA_DIGITV           0x68
 #define BTTV_BOARD_PV143                   0x69
-#define BTTV_BOARD_VD009X1_MINIDIN         0x6a
-#define BTTV_BOARD_VD009X1_COMBI           0x6b
+#define BTTV_BOARD_VD009X1_VD011_MINIDIN   0x6a
+#define BTTV_BOARD_VD009X1_VD011_COMBI     0x6b
 #define BTTV_BOARD_VD009_MINIDIN           0x6c
 #define BTTV_BOARD_VD009_COMBI             0x6d
 #define BTTV_BOARD_IVC100                  0x6e
@@ -177,6 +177,10 @@
 #define BTTV_BOARD_GEOVISION_GV600	   0x96
 #define BTTV_BOARD_KOZUMI_KTV_01C          0x97
 #define BTTV_BOARD_ENLTV_FM_2		   0x98
+#define BTTV_BOARD_VD012		   0x99
+#define BTTV_BOARD_VD012_X1		   0x9a
+#define BTTV_BOARD_VD012_X2		   0x9b
+
 
 /* more card-specific defines */
 #define PT2254_L_CHANNEL 0x10
@@ -308,7 +312,7 @@ struct bttv_sub_device {
 
 struct bttv_sub_driver {
 	struct device_driver   drv;
-	char                   wanted[BUS_ID_SIZE];
+	char                   wanted[20];
 	int                    (*probe)(struct bttv_sub_device *sub);
 	void                   (*remove)(struct bttv_sub_device *sub);
 };

+ 1 - 1
drivers/media/video/bt8xx/bttvp.h

@@ -459,7 +459,7 @@ struct bttv {
 };
 
 /* our devices */
-#define BTTV_MAX 16
+#define BTTV_MAX 32
 extern unsigned int bttv_num;
 extern struct bttv bttvs[BTTV_MAX];
 

+ 2 - 3
drivers/media/video/bw-qcam.c

@@ -706,8 +706,7 @@ static long qc_capture(struct qcam_device * q, char __user *buf, unsigned long l
  *	Video4linux interfacing
  */
 
-static int qcam_do_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, void *arg)
+static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct qcam_device *qcam=(struct qcam_device *)dev;
@@ -867,7 +866,7 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
 static int qcam_ioctl(struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
-	return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
+	return video_usercopy(file, cmd, arg, qcam_do_ioctl);
 }
 
 static ssize_t qcam_read(struct file *file, char __user *buf,

+ 3 - 4
drivers/media/video/c-qcam.c

@@ -500,8 +500,7 @@ static long qc_capture(struct qcam_device *q, char __user *buf, unsigned long le
  *	Video4linux interfacing
  */
 
-static int qcam_do_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, void *arg)
+static int qcam_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct qcam_device *qcam=(struct qcam_device *)dev;
@@ -667,9 +666,9 @@ static int qcam_do_ioctl(struct inode *inode, struct file *file,
 }
 
 static int qcam_ioctl(struct inode *inode, struct file *file,
-		     unsigned int cmd, unsigned long arg)
+		      unsigned int cmd, unsigned long arg)
 {
-	return video_usercopy(inode, file, cmd, arg, qcam_do_ioctl);
+	return video_usercopy(file, cmd, arg, qcam_do_ioctl);
 }
 
 static ssize_t qcam_read(struct file *file, char __user *buf,

+ 4 - 5
drivers/media/video/cpia.c

@@ -3333,8 +3333,7 @@ static ssize_t cpia_read(struct file *file, char __user *buf,
 	return cam->decompressed_frame.count;
 }
 
-static int cpia_do_ioctl(struct inode *inode, struct file *file,
-			 unsigned int ioctlnr, void *arg)
+static int cpia_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
 	struct video_device *dev = file->private_data;
 	struct cam_data *cam = video_get_drvdata(dev);
@@ -3347,9 +3346,9 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
 	if (mutex_lock_interruptible(&cam->busy_lock))
 		return -EINTR;
 
-	//DBG("cpia_ioctl: %u\n", ioctlnr);
+	/* DBG("cpia_ioctl: %u\n", cmd); */
 
-	switch (ioctlnr) {
+	switch (cmd) {
 	/* query capabilities */
 	case VIDIOCGCAP:
 	{
@@ -3724,7 +3723,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file,
 static int cpia_ioctl(struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
-	return video_usercopy(inode, file, cmd, arg, cpia_do_ioctl);
+	return video_usercopy(file, cmd, arg, cpia_do_ioctl);
 }
 
 

+ 1 - 1
drivers/media/video/cpia2/cpia2_core.c

@@ -25,7 +25,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  Stripped of 2.4 stuff ready for main kernel submit by
- *		Alan Cox <alan@redhat.com>
+ *		Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
  ****************************************************************************/
 

+ 1 - 1
drivers/media/video/cpia2/cpia2_usb.c

@@ -25,7 +25,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  Stripped of 2.4 stuff ready for main kernel submit by
- *		Alan Cox <alan@redhat.com>
+ *		Alan Cox <alan@lxorguk.ukuu.org.uk>
  ****************************************************************************/
 
 #include <linux/kernel.h>

+ 7 - 8
drivers/media/video/cpia2/cpia2_v4l.c

@@ -26,7 +26,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  Stripped of 2.4 stuff ready for main kernel submit by
- *		Alan Cox <alan@redhat.com>
+ *		Alan Cox <alan@lxorguk.ukuu.org.uk>
  ****************************************************************************/
 
 #include <linux/version.h>
@@ -1572,8 +1572,7 @@ static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file)
  *  cpia2_ioctl
  *
  *****************************************************************************/
-static int cpia2_do_ioctl(struct inode *inode, struct file *file,
-			  unsigned int ioctl_nr, void *arg)
+static int cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 {
 	struct camera_data *cam = video_drvdata(file);
 	int retval = 0;
@@ -1591,7 +1590,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
 	}
 
 	/* Priority check */
-	switch (ioctl_nr) {
+	switch (cmd) {
 	case VIDIOCSWIN:
 	case VIDIOCMCAPTURE:
 	case VIDIOC_S_FMT:
@@ -1618,7 +1617,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
 		break;
 	}
 
-	switch (ioctl_nr) {
+	switch (cmd) {
 	case VIDIOCGCAP:	/* query capabilities */
 		retval = ioctl_cap_query(arg, cam);
 		break;
@@ -1683,7 +1682,7 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
 	case VIDIOC_ENUMINPUT:
 	case VIDIOC_G_INPUT:
 	case VIDIOC_S_INPUT:
-		retval = ioctl_input(ioctl_nr, arg,cam);
+		retval = ioctl_input(cmd, arg, cam);
 		break;
 
 	case VIDIOC_ENUM_FMT:
@@ -1843,9 +1842,9 @@ static int cpia2_do_ioctl(struct inode *inode, struct file *file,
 }
 
 static int cpia2_ioctl(struct inode *inode, struct file *file,
-		       unsigned int ioctl_nr, unsigned long iarg)
+		       unsigned int cmd, unsigned long arg)
 {
-	return video_usercopy(inode, file, ioctl_nr, iarg, cpia2_do_ioctl);
+	return video_usercopy(file, cmd, arg, cpia2_do_ioctl);
 }
 
 /******************************************************************************

Деякі файли не було показано, через те що забагато файлів було змінено