All of lore.kernel.org
 help / color / mirror / Atom feed
* DTV2000 H Plus issues
@ 2010-01-02 16:10 Raena Lea-Shannon
  2010-01-02 16:57 ` istvan_v
  0 siblings, 1 reply; 30+ messages in thread
From: Raena Lea-Shannon @ 2010-01-02 16:10 UTC (permalink / raw)
  To: linux-media

I have 2 TV Cards. The DTV2000 H Plus and a Technisat. The Technisat 
works very well. I am trying to get the DVT working for other video 
input devices such as VCR to make copies of old Videos and an inteface 
for my N95 video out.

I do not seem to be able to get it to find a tuner. Seems to be problem 
finding the card. Any suggestions wold be greatly appreciated.

Here is part of an mplayer -verbose output


Selected driver: v4l2
  name: Video 4 Linux 2 input
  author: Martin Olschewski <olschewski@zpr.uni-koeln.de>
  comment: first try, more to come ;-)
Selected device: UNKNOWN/GENERIC
  Capabilites:  video capture  VBI capture device  read/write  streaming
  supported norms: 0 = NTSC-M; 1 = NTSC-M-JP; 2 = NTSC-443; 3 = PAL-BG; 
4 = PAL-I; 5 = PAL-DK; 6 = PAL-M; 7 = PAL-N; 8 = PAL-Nc; 9 = PAL-60; 10 
= SECAM-B; 11 = SECAM-G; 12 = SECAM-H; 13 = SECAM-DK; 14 = SECAM-L; 

  inputs: 0 = Composite1; 1 = Composite2; 2 = Composite3; 3 = Composite4;

I am running Kubuntu Karmic 2.6.31-16-generic on AMD64 quadcore. I have 
latest mercurial of v4l installed.

Here is the Lspci info and dmesg etc
5:05.0 Network controller [0280]: Techsan Electronics Co Ltd B2C2 
FlexCopII DVB chip / Technisat SkyStar2 DVB card [13d0:2103] (rev 02) 
 

         Subsystem: Techsan Electronics Co Ltd B2C2 FlexCopII DVB chip / 
Technisat SkyStar2 DVB card [13d0:2103]
         Flags: bus master, slow devsel, latency 64, IRQ 20 

         Memory at fbff0000 (32-bit, non-prefetchable) [size=64K] 

         I/O ports at ec00 [size=32] 

         Kernel driver in use: b2c2_flexcop_pci 

         Kernel modules: b2c2-flexcop-pci

05:06.0 Multimedia video controller [0400]: Conexant Systems, Inc. 
CX23880/1/2/3 PCI Video and Audio Decoder [14f1:8800] (rev 05)
         Subsystem: LeadTek Research Inc. Device [107d:6f42]
         Flags: bus master, medium devsel, latency 64, IRQ 21
         Memory at f8000000 (32-bit, non-prefetchable) [size=16M]
         Capabilities: <access denied>
         Kernel driver in use: cx8800
         Kernel modules: cx8800

05:06.1 Multimedia controller [0480]: Conexant Systems, Inc. 
CX23880/1/2/3 PCI Video and Audio Decoder [Audio Port] [14f1:8801] (rev 05)
         Subsystem: LeadTek Research Inc. Device [107d:6f42]
         Flags: bus master, medium devsel, latency 64, IRQ 21
         Memory at f9000000 (32-bit, non-prefetchable) [size=16M]
         Capabilities: <access denied>
         Kernel driver in use: cx88_audio
         Kernel modules: cx88-alsa

05:06.2 Multimedia controller [0480]: Conexant Systems, Inc. 
CX23880/1/2/3 PCI Video and Audio Decoder [MPEG Port] [14f1:8802] (rev 05)
         Subsystem: LeadTek Research Inc. Device [107d:6f42]
         Flags: bus master, medium devsel, latency 64, IRQ 10
         Memory at fa000000 (32-bit, non-prefetchable) [size=16M]
         Capabilities: <access denied>
         Kernel modules: cx8802

dmesg in part here:
[snip]

[   20.387650] b2c2-flexcop: B2C2 FlexcopII/II(b)/III digital TV 
receiver chip loaded successfully
[   20.390596] EDAC MC: Ver: 2.1.0 Dec  8 2009 

[   20.392347] flexcop-pci: will use the HW PID filter. 

[   20.392351] flexcop-pci: card revision 2 

[   20.392359]   alloc irq_desc for 20 on node 0 

[   20.392361]   alloc kstat_irqs on node 0 

[   20.392366] b2c2_flexcop_pci 0000:05:05.0: PCI INT A -> GSI 20 
(level, low) -> IRQ 20
[   20.403400] EDAC amd64_edac:  Ver: 3.2.0 Dec  8 2009 

[   20.404070] EDAC amd64: This node reports that Memory ECC is 
currently disabled.
[   20.404073] EDAC amd64: bit 0x400000 in register F3x44 of the 
MISC_CONTROL device (0000:00:18.3) should be enabled
[   20.404076] EDAC amd64: WARNING: ECC is NOT currently enabled by the 
BIOS. Module will NOT be loaded.
[   20.404077]     Either Enable ECC in the BIOS, or use the 
'ecc_enable_override' parameter.
[   20.404078]     Might be a BIOS bug, if BIOS says ECC is enabled 

[   20.404078]     Use of the override can cause unknown side effects. 

[   20.404541] amd64_edac: probe of 0000:00:18.2 failed with error -22 

[   20.425278] HDA Intel 0000:00:14.2: PCI INT A -> GSI 16 (level, low) 
-> IRQ 16
[   20.430203] DVB: registering new adapter (FlexCop Digital TV device) 

[   20.431702] b2c2-flexcop: MAC address = 00:d0:d7:16:5d:8f 

[   20.432308] CX24123: cx24123_i2c_readreg: reg=0x0 (error=-121) 

[   20.432311] CX24123: wrong demod revision: 87 

[   20.547542] Linux video capture interface: v2.00 

[   20.555291] HDA Intel 0000:01:00.1: PCI INT B -> GSI 19 (level, low) 
-> IRQ 19
[   20.555310] HDA Intel 0000:01:00.1: setting latency timer to 64 

[   20.608776] EXT3 FS on sda1, internal journal 

[   20.857754] cx88/0: cx2388x v4l2 driver version 0.0.7 loaded 

[   20.859425] cx88/2: cx2388x MPEG-TS Driver Manager version 0.0.7 
loaded
[   20.859959] b2c2-flexcop: found 'Zarlink MT352 DVB-T' . 

[   20.859963] DVB: registering adapter 0 frontend 0 (Zarlink MT352 
DVB-T)...
[   20.860017] b2c2-flexcop: initialization of 'Air2PC/AirStar 2 DVB-T' 
at the 'PCI' bus controlled by a 'FlexCopIIb' complete
[   20.861717] cx2388x alsa driver version 0.0.7 loaded 

[   20.862371]   alloc irq_desc for 21 on node 0 

[   20.862373]   alloc kstat_irqs on node 0 

[   20.862379] cx8800 0000:05:06.0: PCI INT A -> GSI 21 (level, low) -> 
IRQ 21
[   20.862549] cx88[0]: Your board isn't known (yet) to the driver.  You 
can
[   20.862550] cx88[0]: try to pick one of the existing card configs via 

[   20.862551] cx88[0]: card=<n> insmod option.  Updating to the latest 

[   20.862552] cx88[0]: version might help as well. 

[   20.862554] cx88[0]: Here is a list of valid choices for the card=<n> 
insmod option:
[   20.862556] cx88[0]:    card=0 -> UNKNOWN/GENERIC 

[   20.862558] cx88[0]:    card=1 -> Hauppauge WinTV 34xxx models 

[   20.862559] cx88[0]:    card=2 -> GDI Black Gold 

[   20.862561] cx88[0]:    card=3 -> PixelView 

[   20.862562] cx88[0]:    card=4 -> ATI TV Wonder Pro 

[   20.862563] cx88[0]:    card=5 -> Leadtek Winfast 2000XP Expert 

[   20.862565] cx88[0]:    card=6 -> AverTV Studio 303 (M126) 

[   20.862566] cx88[0]:    card=7 -> MSI TV-@nywhere Master 

[   20.862568] cx88[0]:    card=8 -> Leadtek Winfast DV2000 

[   20.862569] cx88[0]:    card=9 -> Leadtek PVR 2000 

[   20.862571] cx88[0]:    card=10 -> IODATA GV-VCP3/PCI 

[   20.862572] cx88[0]:    card=11 -> Prolink PlayTV PVR 

[   20.862574] cx88[0]:    card=12 -> ASUS PVR-416 

[   20.862575] cx88[0]:    card=13 -> MSI TV-@nywhere 

[   20.862577] cx88[0]:    card=14 -> KWorld/VStream XPert DVB-T 

[   20.862578] cx88[0]:    card=15 -> DViCO FusionHDTV DVB-T1 

[   20.862580] cx88[0]:    card=16 -> KWorld LTV883RF 

[   20.862581] cx88[0]:    card=17 -> DViCO FusionHDTV 3 Gold-Q 

[   20.862583] cx88[0]:    card=18 -> Hauppauge Nova-T DVB-T 

[   20.862584] cx88[0]:    card=19 -> Conexant DVB-T reference design 

[   20.862586] cx88[0]:    card=20 -> Provideo PV259 

[   20.862587] cx88[0]:    card=21 -> DViCO FusionHDTV DVB-T Plus 

[   20.862589] cx88[0]:    card=22 -> pcHDTV HD3000 HDTV 

[   20.862590] cx88[0]:    card=23 -> digitalnow DNTV Live! DVB-T 

[   20.862592] cx88[0]:    card=24 -> Hauppauge WinTV 28xxx (Roslyn) 
models
[   20.862593] cx88[0]:    card=25 -> Digital-Logic MICROSPACE 
Entertainment Center (MEC)
[   20.862595] cx88[0]:    card=26 -> IODATA GV/BCTV7E 

[   20.862597] cx88[0]:    card=27 -> PixelView PlayTV Ultra Pro 
(Stereo)
[   20.862598] cx88[0]:    card=28 -> DViCO FusionHDTV 3 Gold-T 

[   20.862600] cx88[0]:    card=29 -> ADS Tech Instant TV DVB-T PCI 

[   20.862601] cx88[0]:    card=30 -> TerraTec Cinergy 1400 DVB-T 

[   20.862603] cx88[0]:    card=31 -> DViCO FusionHDTV 5 Gold 

[   20.862604] cx88[0]:    card=32 -> AverMedia UltraTV Media Center PCI 
550
[   20.862606] cx88[0]:    card=33 -> Kworld V-Stream Xpert DVD 

[   20.862607] cx88[0]:    card=34 -> ATI HDTV Wonder 

[   20.862609] cx88[0]:    card=35 -> WinFast DTV1000-T 

[   20.862610] cx88[0]:    card=36 -> AVerTV 303 (M126) 

[   20.862611] cx88[0]:    card=37 -> Hauppauge Nova-S-Plus DVB-S 

[   20.862613] cx88[0]:    card=38 -> Hauppauge Nova-SE2 DVB-S 

[   20.862614] cx88[0]:    card=39 -> KWorld DVB-S 100 

[   20.862616] cx88[0]:    card=40 -> Hauppauge WinTV-HVR1100 
DVB-T/Hybrid
[   20.862618] cx88[0]:    card=41 -> Hauppauge WinTV-HVR1100 
DVB-T/Hybrid (Low Profile)
[   20.862619] cx88[0]:    card=42 -> digitalnow DNTV Live! DVB-T Pro 

[   20.862621] cx88[0]:    card=43 -> KWorld/VStream XPert DVB-T with 
cx22702
[   20.862623] cx88[0]:    card=44 -> DViCO FusionHDTV DVB-T Dual 
Digital
[   20.862624] cx88[0]:    card=45 -> KWorld HardwareMpegTV XPert 

[   20.862626] cx88[0]:    card=46 -> DViCO FusionHDTV DVB-T Hybrid 

[   20.862627] cx88[0]:    card=47 -> pcHDTV HD5500 HDTV 

[   20.862628] cx88[0]:    card=48 -> Kworld MCE 200 Deluxe 

[   20.862630] cx88[0]:    card=49 -> PixelView PlayTV P7000 

[   20.862631] cx88[0]:    card=50 -> NPG Tech Real TV FM Top 10 

[   20.862633] cx88[0]:    card=51 -> WinFast DTV2000 H 

[   20.862634] cx88[0]:    card=52 -> Geniatech DVB-S 

[   20.862636] cx88[0]:    card=53 -> Hauppauge WinTV-HVR3000 TriMode 
Analog/DVB-S/DVB-T
[   20.862637] cx88[0]:    card=54 -> Norwood Micro TV Tuner 

[   20.862639] cx88[0]:    card=55 -> Shenzhen Tungsten Ages Tech 
TE-DTV-250 / Swann OEM
[   20.862641] cx88[0]:    card=56 -> Hauppauge WinTV-HVR1300 
DVB-T/Hybrid MPEG Encoder
[   20.862643] cx88[0]:    card=57 -> ADS Tech Instant Video PCI 

[   20.862644] cx88[0]:    card=58 -> Pinnacle PCTV HD 800i 

[   20.862645] cx88[0]:    card=59 -> DViCO FusionHDTV 5 PCI nano 

[   20.862647] cx88[0]:    card=60 -> Pinnacle Hybrid PCTV 

[   20.862648] cx88[0]:    card=61 -> Leadtek TV2000 XP Global 

[   20.862650] cx88[0]:    card=62 -> PowerColor RA330 

[   20.862651] cx88[0]:    card=63 -> Geniatech X8000-MT DVBT 

[   20.862653] cx88[0]:    card=64 -> DViCO FusionHDTV DVB-T PRO 

[   20.862654] cx88[0]:    card=65 -> DViCO FusionHDTV 7 Gold 

[   20.862656] cx88[0]:    card=66 -> Prolink Pixelview MPEG 8000GT 

[   20.862657] cx88[0]:    card=67 -> Kworld PlusTV HD PCI 120 (ATSC 
120)
[   20.862659] cx88[0]:    card=68 -> Hauppauge WinTV-HVR4000 
DVB-S/S2/T/Hybrid
[   20.862661] cx88[0]:    card=69 -> Hauppauge WinTV-HVR4000(Lite) 
DVB-S/S2
[   20.862662] cx88[0]:    card=70 -> TeVii S460 DVB-S/S2 

[   20.862664] cx88[0]:    card=71 -> Omicom SS4 DVB-S/S2 PCI 

[   20.862665] cx88[0]:    card=72 -> TBS 8920 DVB-S/S2 

[   20.862666] cx88[0]:    card=73 -> TeVii S420 DVB-S 

[   20.862668] cx88[0]:    card=74 -> Prolink Pixelview Global Extreme 

[   20.862669] cx88[0]:    card=75 -> PROF 7300 DVB-S/S2 

[   20.862671] cx88[0]:    card=76 -> SATTRADE ST4200 DVB-S/S2 

[   20.862672] cx88[0]:    card=77 -> TBS 8910 DVB-S 

[   20.862674] cx88[0]:    card=78 -> Prof 6200 DVB-S 

[   20.862675] cx88[0]:    card=79 -> Terratec Cinergy HT PCI MKII 

[   20.862677] cx88[0]:    card=80 -> Hauppauge WinTV-IR Only 

[   20.862678] cx88[0]:    card=81 -> Leadtek WinFast DTV1800 Hybrid 

[   20.862680] cx88[0]:    card=82 -> WinFast DTV2000 H rev. J 

[   20.862681] cx88[0]:    card=83 -> Prof 7301 DVB-S/S2 

[   20.862683] cx88[0]: subsystem: 107d:6f42, board: UNKNOWN/GENERIC 
[card=0,autodetected], frontend(s): 0
[   20.862685] cx88[0]: TV tuner type -1, Radio tuner type -1 

[   21.020478] tuner 3-0061: chip found @ 0xc2 (cx88[0]) 

[   21.065392] cx88[0]/0: found at 0000:05:06.0, rev: 5, irq: 21, 
latency: 64, mmio: 0xf8000000
[   21.065403] IRQ 21/cx88[0]: IRQF_DISABLED is not guaranteed on shared 
IRQs
[   21.065461] cx88[0]/0: registered device video0 [v4l2] 

[   21.065480] cx88[0]/0: registered device vbi0 

[   21.065489] tuner 3-0061: tuner type not set 

[   21.074373] cx88[0]/2: cx2388x 8802 Driver Manager 

[   21.074759] cx88_audio 0000:05:06.1: PCI INT A -> GSI 21 (level, low) 
-> IRQ 21
[   21.074767] IRQ 21/cx88[0]: IRQF_DISABLED is not guaranteed on shared 
IRQs
[   21.074786] cx88[0]/1: CX88x/0: ALSA support for cx2388x boards

23.773910] tun: Universal TUN/TAP device driver, 1.6
[   23.773912] tun: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
[   23.774358] tun0: Disabled Privacy Extensions

[snip]
  162.841498] tuner 3-0061: tuner type not set


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-01-02 16:10 DTV2000 H Plus issues Raena Lea-Shannon
@ 2010-01-02 16:57 ` istvan_v
  2010-01-03  8:21   ` Raena Lea-Shannon
  0 siblings, 1 reply; 30+ messages in thread
From: istvan_v @ 2010-01-02 16:57 UTC (permalink / raw)
  To: linux-media

On 01/02/2010 05:10 PM, Raena Lea-Shannon wrote:

> I have 2 TV Cards. The DTV2000 H Plus and a Technisat. The Technisat
> works very well. I am trying to get the DVT working for other video
> input devices such as VCR to make copies of old Videos and an inteface
> for my N95 video out.
> 
> I do not seem to be able to get it to find a tuner. Seems to be problem
> finding the card. Any suggestions wold be greatly appreciated.

This card uses an Xceive XC4000 tuner, which is not supported yet.
However, a driver for the tuner chip is being developed at
kernellabs.com, so the card may become supported in the future.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-01-02 16:57 ` istvan_v
@ 2010-01-03  8:21   ` Raena Lea-Shannon
  2010-01-03 11:31     ` Samuel Rakitnican
  2010-01-04 16:48     ` istvan_v
  0 siblings, 2 replies; 30+ messages in thread
From: Raena Lea-Shannon @ 2010-01-03  8:21 UTC (permalink / raw)
  To: istvan_v; +Cc: linux-media



istvan_v@mailbox.hu wrote:
> On 01/02/2010 05:10 PM, Raena Lea-Shannon wrote:
> 
>> I have 2 TV Cards. The DTV2000 H Plus and a Technisat. The Technisat
>> works very well. I am trying to get the DVT working for other video
>> input devices such as VCR to make copies of old Videos and an inteface
>> for my N95 video out.
>>
>> I do not seem to be able to get it to find a tuner. Seems to be problem
>> finding the card. Any suggestions wold be greatly appreciated.
> 
> This card uses an Xceive XC4000 tuner, which is not supported yet.
> However, a driver for the tuner chip is being developed at
> kernellabs.com, so the card may become supported in the future.
> --
[snip]

That seems odd. This patch on the LinuxTv site
http://www.linuxtv.org/pipermail/linux-dvb/2008-June/026379.html
seems to be using the cx88 drivers?
Has anyone tried this patch?

Ta
Raena

# HG changeset patch
# User plr.vincent at gmail.com
# Date 1212398724 -7200
# Node ID 78a011dfba127b593b6d01ea6a0010fcc29c94ad
# Parent  398b07fdfe79ff66a8c1bf2874de424ce29b9c78
WinFast DTV2000 H: add support for missing analog inputs

From: Vincent Pelletier <plr.vincent at gmail.com>

Add support for the following inputs:
  - radio tuner
  - composite 1 & 2 (only 1 is physicaly available, but composite 2 is also
    advertised by windows driver)
  - svideo

Signed-off-by: Vincent Pelletier <plr.vincent at gmail.com>

diff -r 398b07fdfe79 -r 78a011dfba12 
linux/drivers/media/video/cx88/cx88-cards.c
--- a/linux/drivers/media/video/cx88/cx88-cards.c       Wed May 28 
17:55:13 2008 -0300
+++ b/linux/drivers/media/video/cx88/cx88-cards.c       Mon Jun 02 
11:25:24 2008 +0200
@@ -1297,7 +1297,35 @@
                         .gpio1  = 0x00008203,
                         .gpio2  = 0x00017304,
                         .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0001D701,
+                       .gpio1  = 0x0000B207,
+                       .gpio2  = 0x0001D701,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE2,
+                       .vmux   = 2,
+                       .gpio0  = 0x0001D503,
+                       .gpio1  = 0x0000B207,
+                       .gpio2  = 0x0001D503,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 3,
+                       .gpio0  = 0x0001D701,
+                       .gpio1  = 0x0000B207,
+                       .gpio2  = 0x0001D701,
+                       .gpio3  = 0x02000000,
                 }},
+               .radio = {
+                        .type  = CX88_RADIO,
+                        .gpio0 = 0x00015702,
+                        .gpio1 = 0x0000F207,
+                        .gpio2 = 0x00015702,
+                        .gpio3 = 0x02000000,
+               },
                 .mpeg           = CX88_MPEG_DVB,
         },
         [CX88_BOARD_GENIATECH_DVBS] = {

> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-01-03  8:21   ` Raena Lea-Shannon
@ 2010-01-03 11:31     ` Samuel Rakitnican
  2010-01-04 13:01       ` Raena Lea-Shannon
  2010-01-04 16:48     ` istvan_v
  1 sibling, 1 reply; 30+ messages in thread
From: Samuel Rakitnican @ 2010-01-03 11:31 UTC (permalink / raw)
  To: Raena Lea-Shannon; +Cc: linux-media

On Sun, 03 Jan 2010 09:21:21 +0100, Raena Lea-Shannon  
<raen@internode.on.net> wrote:

>
>
> istvan_v@mailbox.hu wrote:
>> On 01/02/2010 05:10 PM, Raena Lea-Shannon wrote:
>>
>>> I have 2 TV Cards. The DTV2000 H Plus and a Technisat. The Technisat
>>> works very well. I am trying to get the DVT working for other video
>>> input devices such as VCR to make copies of old Videos and an inteface
>>> for my N95 video out.
>>>
>>> I do not seem to be able to get it to find a tuner. Seems to be problem
>>> finding the card. Any suggestions wold be greatly appreciated.
>>  This card uses an Xceive XC4000 tuner, which is not supported yet.
>> However, a driver for the tuner chip is being developed at
>> kernellabs.com, so the card may become supported in the future.
>> --
> [snip]
>
> That seems odd. This patch on the LinuxTv site
> http://www.linuxtv.org/pipermail/linux-dvb/2008-June/026379.html
> seems to be using the cx88 drivers?

[...]

Hi,

I'm not a developer, but I think that your device uses both of these  
chips. cx88 is the bridge chip, while the Xceive is the tuner chip. So,  
both of them needs to be supported in order for a device to work properly.

Please see the following link for reference:
	http://www.kernellabs.com/blog/?p=1045

Regards

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-01-03 11:31     ` Samuel Rakitnican
@ 2010-01-04 13:01       ` Raena Lea-Shannon
  0 siblings, 0 replies; 30+ messages in thread
From: Raena Lea-Shannon @ 2010-01-04 13:01 UTC (permalink / raw)
  To: Samuel Rakitnican; +Cc: linux-media



Samuel Rakitnican wrote:
> On Sun, 03 Jan 2010 09:21:21 +0100, Raena Lea-Shannon 
> <raen@internode.on.net> wrote:
> 
>>
>>
>> istvan_v@mailbox.hu wrote:
>>> On 01/02/2010 05:10 PM, Raena Lea-Shannon wrote:
>>>
>>>> I have 2 TV Cards. The DTV2000 H Plus and a Technisat. The Technisat
>>>> works very well. I am trying to get the DVT working for other video
>>>> input devices such as VCR to make copies of old Videos and an inteface
>>>> for my N95 video out.
>>>>
>>>> I do not seem to be able to get it to find a tuner. Seems to be problem
>>>> finding the card. Any suggestions wold be greatly appreciated.
>>>  This card uses an Xceive XC4000 tuner, which is not supported yet.
>>> However, a driver for the tuner chip is being developed at
>>> kernellabs.com, so the card may become supported in the future.
>>> -- 
>> [snip]
>>
>> That seems odd. This patch on the LinuxTv site
>> http://www.linuxtv.org/pipermail/linux-dvb/2008-June/026379.html
>> seems to be using the cx88 drivers?
> 
> [...]
> 
> Hi,
> 
> I'm not a developer, but I think that your device uses both of these 
> chips. cx88 is the bridge chip, while the Xceive is the tuner chip. So, 
> both of them needs to be supported in order for a device to work properly.
> 
> Please see the following link for reference:
>     http://www.kernellabs.com/blog/?p=1045
> 
> Regards
> -- 
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
Thanks

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-01-03  8:21   ` Raena Lea-Shannon
  2010-01-03 11:31     ` Samuel Rakitnican
@ 2010-01-04 16:48     ` istvan_v
  2010-01-05  1:25       ` Raena Lea-Shannon
  1 sibling, 1 reply; 30+ messages in thread
From: istvan_v @ 2010-01-04 16:48 UTC (permalink / raw)
  To: linux-media

On 01/03/2010 09:21 AM, Raena Lea-Shannon wrote:

> That seems odd. This patch on the LinuxTv site
> http://www.linuxtv.org/pipermail/linux-dvb/2008-June/026379.html
> seems to be using the cx88 drivers?

Unfortunately, this patch is for the older DTV 2000H (not Plus)
card, which uses a Philips FMD1216 tuner. The main change on the
"Plus" card is the replacement of the tuner with the XC4000, and
that is why it is not supported yet. However, an XC4000 driver
is already under development, and - compiling V4L from source -
you could get the card working in the near future. In fact, code
that implements support for this card already exists, but it is
only for development/testing at the moment.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-01-04 16:48     ` istvan_v
@ 2010-01-05  1:25       ` Raena Lea-Shannon
  2010-01-07 19:49         ` istvan_v
  0 siblings, 1 reply; 30+ messages in thread
From: Raena Lea-Shannon @ 2010-01-05  1:25 UTC (permalink / raw)
  To: istvan_v; +Cc: linux-media



istvan_v@mailbox.hu wrote:
> On 01/03/2010 09:21 AM, Raena Lea-Shannon wrote:
> 
>> That seems odd. This patch on the LinuxTv site
>> http://www.linuxtv.org/pipermail/linux-dvb/2008-June/026379.html
>> seems to be using the cx88 drivers?
> 
> Unfortunately, this patch is for the older DTV 2000H (not Plus)
> card, which uses a Philips FMD1216 tuner. The main change on the
> "Plus" card is the replacement of the tuner with the XC4000, and
> that is why it is not supported yet. However, an XC4000 driver
> is already under development, and - compiling V4L from source -
> you could get the card working in the near future. In fact, code
> that implements support for this card already exists, but it is
> only for development/testing at the moment.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
Thanks. Will try again later.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-01-05  1:25       ` Raena Lea-Shannon
@ 2010-01-07 19:49         ` istvan_v
  2010-01-07 20:00           ` Devin Heitmueller
  2010-02-09 17:35           ` istvan_v
  0 siblings, 2 replies; 30+ messages in thread
From: istvan_v @ 2010-01-07 19:49 UTC (permalink / raw)
  To: linux-media

On 01/05/2010 02:25 AM, Raena Lea-Shannon wrote:

> Thanks. Will try again later.

By the way, for those who would like to test it, here is a patch based
on Devin Heitmueller's XC4000 driver and Mirek Slugen's older patch,
that adds support for this card:
  http://www.sharemation.com/IstvanV/v4l/dtv2000h+.patch
It can be applied to this version of the v4l-dvb code:
  http://linuxtv.org/hg/v4l-dvb/archive/75c97b2d1a2a.tar.bz2
This is experimental code, so use it at your own risk. The analogue
parts (TV and FM radio) basically work, although there are some minor
issues to be fixed. Digital TV is not tested yet, but is theoretically
implemented; reports on whether it actually works are welcome.
The XC4000 driver also requires a firmware file:
  http://www.sharemation.com/IstvanV/v4l/dvb-fe-xc4000-1.4.1.fw

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-01-07 19:49         ` istvan_v
@ 2010-01-07 20:00           ` Devin Heitmueller
  2010-01-07 21:07             ` istvan_v
  2010-02-09 17:35           ` istvan_v
  1 sibling, 1 reply; 30+ messages in thread
From: Devin Heitmueller @ 2010-01-07 20:00 UTC (permalink / raw)
  To: istvan_v; +Cc: linux-media

On Thu, Jan 7, 2010 at 2:49 PM, istvan_v@mailbox.hu <istvan_v@mailbox.hu> wrote:
> On 01/05/2010 02:25 AM, Raena Lea-Shannon wrote:
>
>> Thanks. Will try again later.
>
> By the way, for those who would like to test it, here is a patch based
> on Devin Heitmueller's XC4000 driver and Mirek Slugen's older patch,
> that adds support for this card:
>  http://www.sharemation.com/IstvanV/v4l/dtv2000h+.patch
> It can be applied to this version of the v4l-dvb code:
>  http://linuxtv.org/hg/v4l-dvb/archive/75c97b2d1a2a.tar.bz2
> This is experimental code, so use it at your own risk. The analogue
> parts (TV and FM radio) basically work, although there are some minor
> issues to be fixed. Digital TV is not tested yet, but is theoretically
> implemented; reports on whether it actually works are welcome.
> The XC4000 driver also requires a firmware file:
>  http://www.sharemation.com/IstvanV/v4l/dvb-fe-xc4000-1.4.1.fw
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Istan_v,

Could you please do me a favor and rename your firmware file, both in
the patch and the file you are redistributing (perhaps as
dvb-fe-xc4000-1.4.1-istanv.fw)?  I worry that by redistributing a file
with the exact same name as the "official" release, people are going
to get confused and it will make it harder for me to debug problems
given my assumptions about what firmware image they are using is
incorrect.

Thanks,

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-01-07 20:00           ` Devin Heitmueller
@ 2010-01-07 21:07             ` istvan_v
  0 siblings, 0 replies; 30+ messages in thread
From: istvan_v @ 2010-01-07 21:07 UTC (permalink / raw)
  To: Devin Heitmueller; +Cc: linux-media

On 01/07/2010 09:00 PM, Devin Heitmueller wrote:

> Could you please do me a favor and rename your firmware file, both in
> the patch and the file you are redistributing (perhaps as
> dvb-fe-xc4000-1.4.1-istanv.fw)?  I worry that by redistributing a file
> with the exact same name as the "official" release, people are going
> to get confused and it will make it harder for me to debug problems
> given my assumptions about what firmware image they are using is
> incorrect.

OK, I have renamed the firmware file. The download links are now:
  http://www.sharemation.com/IstvanV/v4l/dtv2000h+.patch
  http://www.sharemation.com/IstvanV/v4l/xc4000-dtv2000hp-1.4.1.fw

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-01-07 19:49         ` istvan_v
  2010-01-07 20:00           ` Devin Heitmueller
@ 2010-02-09 17:35           ` istvan_v
  2010-02-11 19:16             ` istvan_v
  1 sibling, 1 reply; 30+ messages in thread
From: istvan_v @ 2010-02-09 17:35 UTC (permalink / raw)
  To: linux-media

I have an updated version now, with these changes:
  - the firmware file name can be specified with the "firmware_name"
    module parameter; it defaults to "xc4000.fw"
  - there is another new module parameter ("audio_std") for configuring
    the audio standard (NICAM, A2, etc.), and switching FM radio to
    using input 1 (i.e. cable TV instead of FM antenna). This is an
    integer value which can be the sum of:
      1: use NICAM/B or A2/B instead of NICAM/A or A2/A
      2: use A2 instead of NICAM or BTSC
      4: use SECAM K3 instead of K1
      8: in SECAM D/K mode, set the IF frequency and audio mode as for
         SECAM-L (this hack fixed the one SECAM channel I can receive)
     16: use FM radio input 1 instead of input 2
     32: mono TV audio (does not seem to work, so it is useless)
  - "struct xc4000_config" has a new member ("card_type") for specifying
    the card type
  - some code changes to allow for loading the new firmware files below
In addition to analog TV and FM radio, I have tested the IR as well, and
it apparently works. DVB-T is still untested, however.

There are two separate patches for v4l-dvb revision 28f5eca12bb0: the
first one adds the XC4000 driver, while the second one adds support for
the Leadtek WinFast DTV2000H Plus card in the CX88 driver.

http://www.sharemation.com/IstvanV/v4l/xc4000-28f5eca12bb0.patch
http://www.sharemation.com/IstvanV/v4l/cx88-dtv2000h+-28f5eca12bb0.patch

These new firmware files are more complete than the previous ones, but
are not compatible with the original driver. Both version 1.2 and 1.4
are available:

http://www.sharemation.com/IstvanV/v4l/xc4000-1.2.fw
http://www.sharemation.com/IstvanV/v4l/xc4000-1.4.fw

Note that the 1.4 firmware could have two different versions of DTV6,
which only differ in the audio mode register: 0x8002 (as in v1.2) vs.
0x8003. However, the above file includes only the latter one.

The following simple utility was used for creating the firmware files.
It can extract the firmware data from a Windows driver file (e.g.
hcw85bda.sys from Hauppauge, wfeaglxt.sys from Leadtek, etc.;
dvb7700all.sys from Pinnacle will not work, however), and supports both
v1.2 and v1.4 firmware. The tables at the beginning of the code are not
necessarily fully correct, though, and may need some fixing.

http://www.sharemation.com/IstvanV/v4l/xc4000fw.c

On 01/07/2010 08:49 PM, istvan_v@mailbox.hu wrote:

> On 01/05/2010 02:25 AM, Raena Lea-Shannon wrote:
> 
>> Thanks. Will try again later.
> 
> By the way, for those who would like to test it, here is a patch based
> on Devin Heitmueller's XC4000 driver and Mirek Slugen's older patch,
> that adds support for this card:
>   http://www.sharemation.com/IstvanV/v4l/dtv2000h+.patch
> It can be applied to this version of the v4l-dvb code:
>   http://linuxtv.org/hg/v4l-dvb/archive/75c97b2d1a2a.tar.bz2
> This is experimental code, so use it at your own risk. The analogue
> parts (TV and FM radio) basically work, although there are some minor
> issues to be fixed. Digital TV is not tested yet, but is theoretically
> implemented; reports on whether it actually works are welcome.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-02-09 17:35           ` istvan_v
@ 2010-02-11 19:16             ` istvan_v
  2010-02-11 19:21               ` Devin Heitmueller
                                 ` (2 more replies)
  0 siblings, 3 replies; 30+ messages in thread
From: istvan_v @ 2010-02-11 19:16 UTC (permalink / raw)
  To: linux-media

[-- Attachment #1: Type: text/plain, Size: 1103 bytes --]

Update: the following patch, which should be applied after the previous
ones, makes a few additional changes to the XC4000 driver:
  - adds support for DTV7
  - implements power management
  - adds a mutex and locking for tuner operations
  - some unused or unneeded code has been removed

On 02/09/2010 06:35 PM, istvan_v@mailbox.hu wrote:

> There are two separate patches for v4l-dvb revision 28f5eca12bb0: the
> first one adds the XC4000 driver, while the second one adds support for
> the Leadtek WinFast DTV2000H Plus card in the CX88 driver.
> 
> http://www.sharemation.com/IstvanV/v4l/xc4000-28f5eca12bb0.patch
> http://www.sharemation.com/IstvanV/v4l/cx88-dtv2000h+-28f5eca12bb0.patch
> 
> These new firmware files are more complete than the previous ones, but
> are not compatible with the original driver. Both version 1.2 and 1.4
> are available:
> 
> http://www.sharemation.com/IstvanV/v4l/xc4000-1.2.fw
> http://www.sharemation.com/IstvanV/v4l/xc4000-1.4.fw
> 
> The following simple utility was used for creating the firmware files.
> 
> http://www.sharemation.com/IstvanV/v4l/xc4000fw.c

[-- Attachment #2: xc4000-2-28f5eca12bb0.patch --]
[-- Type: text/x-patch, Size: 15143 bytes --]

diff -r -d -N -U4 v4l-dvb-28f5eca12bb0.old/linux/drivers/media/common/tuners/xc4000.c v4l-dvb-28f5eca12bb0/linux/drivers/media/common/tuners/xc4000.c
--- v4l-dvb-28f5eca12bb0.old/linux/drivers/media/common/tuners/xc4000.c	2010-02-11 20:08:39.000000000 +0100
+++ v4l-dvb-28f5eca12bb0/linux/drivers/media/common/tuners/xc4000.c	2010-02-11 20:05:01.000000000 +0100
@@ -27,8 +27,9 @@
 #include <linux/videodev2.h>
 #include <linux/delay.h>
 #include <linux/dvb/frontend.h>
 #include <linux/i2c.h>
+#include <linux/mutex.h>
 #include <asm/unaligned.h>
 
 #include "dvb_frontend.h"
 
@@ -61,9 +62,9 @@
 	"The valid values are a sum of:\n"
 	" 1: use NICAM/B and A2/B instead of NICAM/A and A2/A\n"
 	" 2: use A2 instead of NICAM or BTSC\n"
 	" 4: use SECAM/K3 instead of K1\n"
-	" 8: force SECAM-L audio\n"
+	" 8: use PAL-D/K audio for SECAM-D/K\n"
 	"16: use FM radio input 1 instead of input 2\n"
 	"32: use mono audio (the lower three bits are ignored)\n");
 
 #define XC4000_DEFAULT_FIRMWARE "xc4000.fw"
@@ -108,18 +109,20 @@
 	u32	bandwidth;
 	u8	video_standard;
 	u8	rf_mode;
 	u8	card_type;
+	u8	ignore_i2c_write_errors;
  /*	struct xc2028_ctrl	ctrl; */
 	struct firmware_properties cur_fw;
 	__u16	hwmodel;
 	__u16	hwvers;
-	u8	ignore_i2c_write_errors;
+	struct mutex	lock;
 };
 
 /* Misc Defines */
 #define MAX_TV_STANDARD			24
 #define XC_MAX_I2C_WRITE_LENGTH		64
+#define XC_POWERED_DOWN			0x80000000U
 
 /* Signal Types */
 #define XC_RF_MODE_AIR			0
 #define XC_RF_MODE_CABLE		1
@@ -240,9 +243,9 @@
 	{"D/K-PAL-MONO",	0x0078, 0x8049, 6500},
 	{"D/K-SECAM-A2 DK1",	0x0000, 0x8049, 6340},
 	{"D/K-SECAM-A2 L/DK3",	0x0000, 0x8049, 6000},
 	{"D/K-SECAM-A2 MONO",	0x0078, 0x8049, 6500},
-	{"D/K-SECAM-NICAM",	0x8080, 0x8049, 6200},
+	{"D/K-SECAM-NICAM",	0x0080, 0x8049, 6200},
 	{"L-SECAM-NICAM",	0x8080, 0x0009, 6200},
 	{"L'-SECAM-NICAM",	0x8080, 0x4009, 6200},
 	{"DTV6",		0x00C0, 0x8002,    0},
 	{"DTV8",		0x00C0, 0x800B,    0},
@@ -251,11 +254,8 @@
 	{"FM Radio-INPUT2",	0x0008, 0x9800,10700},
 	{"FM Radio-INPUT1",	0x0008, 0x9000,10700}
 };
 
-#if 0
-static int xc4000_is_firmware_loaded(struct dvb_frontend *fe);
-#endif
 static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val);
 static int xc4000_TunerReset(struct dvb_frontend *fe);
 
 static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
@@ -275,25 +275,8 @@
 	}
 	return XC_RESULT_SUCCESS;
 }
 
-/* This routine is never used because the only time we read data from the
-   i2c bus is when we read registers, and we want that to be an atomic i2c
-   transaction in case we are on a multi-master bus */
-#if 0
-static int xc_read_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
-{
-	struct i2c_msg msg = { .addr = priv->i2c_props.addr,
-		.flags = I2C_M_RD, .buf = buf, .len = len };
-
-	if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
-		printk(KERN_ERR "xc4000 I2C read failed (len=%i)\n", len);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-#endif
-
 static void xc_wait(int wait_ms)
 {
 	msleep(wait_ms);
 }
@@ -444,17 +427,8 @@
 	   only be used for fast scanning for channel lock) */
 	return xc_write_reg(priv, XREG_RF_FREQ, freq_code); /* WAS: XREG_FINERFREQ */
 }
 
-#if 0
-/* We'll probably need these for analog support */
-static int xc_set_Xtal_frequency(struct xc4000_priv *priv, u32 xtalFreqInKHz)
-{
-	u16 xtalRatio = (32000 * 0x8000)/xtalFreqInKHz;
-	return xc_write_reg(priv, XREG_XTALFREQ, xtalRatio);
-}
-#endif
-
 static int xc_get_ADC_Envelope(struct xc4000_priv *priv, u16 *adc_envelope)
 {
 	return xc4000_readreg(priv, XREG_ADC_ENV, adc_envelope);
 }
@@ -1134,8 +1108,11 @@
 	u16	quality;
 	u8	hw_majorversion = 0, hw_minorversion = 0;
 	u8	fw_majorversion = 0, fw_minorversion = 0;
 
+	if (!(priv->cur_fw.type & BASE))
+		return;
+
 	/* Wait for stats to stabilize.
 	 * Frame Lines needs two frame times after initial lock
 	 * before it is valid.
 	 */
@@ -1174,12 +1151,14 @@
 	struct dvb_frontend_parameters *params)
 {
 	struct xc4000_priv *priv = fe->tuner_priv;
 	unsigned int type;
-	int ret;
+	int	ret = -EREMOTEIO;
 
 	dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
 
+	mutex_lock(&priv->lock);
+
 	if (fe->ops.info.type == FE_ATSC) {
 		dprintk(1, "%s() ATSC\n", __func__);
 		switch (params->u.vsb.modulation) {
 		case VSB_8:
@@ -1201,9 +1180,10 @@
 			priv->video_standard = XC4000_DTV6;
 			type = DTV6;
 			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
+			goto fail;
 		}
 	} else if (fe->ops.info.type == FE_OFDM) {
 		dprintk(1, "%s() OFDM\n", __func__);
 		switch (params->u.ofdm.bandwidth) {
@@ -1213,44 +1193,56 @@
 			priv->freq_hz = params->frequency - 1750000;
 			type = DTV6;
 			break;
 		case BANDWIDTH_7_MHZ:
-			printk(KERN_ERR "xc4000 bandwidth 7MHz not supported\n");
+			priv->bandwidth = BANDWIDTH_7_MHZ;
+			priv->video_standard = XC4000_DTV7;
+			priv->freq_hz = params->frequency - 2250000;
 			type = DTV7;
-			return -EINVAL;
+			break;
 		case BANDWIDTH_8_MHZ:
 			priv->bandwidth = BANDWIDTH_8_MHZ;
 			priv->video_standard = XC4000_DTV8;
 			priv->freq_hz = params->frequency - 2750000;
 			type = DTV8;
 			break;
+		case BANDWIDTH_AUTO:
+			if (params->frequency < 400000000) {
+				priv->bandwidth = BANDWIDTH_7_MHZ;
+				priv->freq_hz = params->frequency - 2250000;
+			} else {
+				priv->bandwidth = BANDWIDTH_8_MHZ;
+				priv->freq_hz = params->frequency - 2750000;
+			}
+			priv->video_standard = XC4000_DTV7_8;
+			type = DTV78;
+			break;
 		default:
 			printk(KERN_ERR "xc4000 bandwidth not set!\n");
-			return -EINVAL;
+			ret = -EINVAL;
+			goto fail;
 		}
 		priv->rf_mode = XC_RF_MODE_AIR;
 	} else {
 		printk(KERN_ERR "xc4000 modulation type not supported!\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto fail;
 	}
 
 	dprintk(1, "%s() frequency=%d (compensated)\n",
 		__func__, priv->freq_hz);
 
 	/* Make sure the correct firmware type is loaded */
-	if (check_firmware(fe, type, 0, priv->if_khz) != XC_RESULT_SUCCESS) {
-		return -EREMOTEIO;
-	}
+	if (check_firmware(fe, type, 0, priv->if_khz) != XC_RESULT_SUCCESS)
+		goto fail;
 
 	ret = xc_SetSignalSource(priv, priv->rf_mode);
 	if (ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR
-			"xc4000: xc_SetSignalSource(%d) failed\n",
-			priv->rf_mode);
-		return -EREMOTEIO;
-	}
-
-	{
+		       "xc4000: xc_SetSignalSource(%d) failed\n",
+		       priv->rf_mode);
+		goto fail;
+	} else {
 		u16	video_mode, audio_mode;
 		video_mode = XC4000_Standard[priv->video_standard].VideoMode;
 		audio_mode = XC4000_Standard[priv->video_standard].AudioMode;
 		if (type == DTV6 && priv->firm_version != 0x0102)
@@ -1258,79 +1250,52 @@
 		ret = xc_SetTVStandard(priv, video_mode, audio_mode);
 		if (ret != XC_RESULT_SUCCESS) {
 			printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n");
 			/* DJH - do not return when it fails... */
-			/* return -EREMOTEIO; */
+			/* goto fail; */
 		}
 	}
 
 	if (priv->card_type == XC4000_CARD_DTV2000H_PLUS) {
-		ret = 0;
-		if (xc_write_reg(priv, XREG_D_CODE, 0) != 0)
-			ret = -EREMOTEIO;
+		if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
+			ret = 0;
 		if (xc_write_reg(priv, XREG_AMPLITUDE,
 				 (priv->firm_version == 0x0102 ? 132 : 134))
 		    != 0)
 			ret = -EREMOTEIO;
 		if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
 			ret = -EREMOTEIO;
 		if (ret != 0) {
 			printk(KERN_ERR "xc4000: setting registers failed\n");
-			/* return ret; */
+			/* goto fail; */
 		}
 	}
 
-#ifdef DJH_DEBUG
-	ret = xc_set_IF_frequency(priv, priv->if_khz);
-	if (ret != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR "xc4000: xc_Set_IF_frequency(%d) failed\n",
-		       priv->if_khz);
-		return -EIO;
-	}
-#endif
 	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
 
 	if (debug)
 		xc_debug_dump(priv);
+	ret = 0;
 
-	return 0;
-}
-
-#if 0
-static int xc4000_is_firmware_loaded(struct dvb_frontend *fe)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	int ret;
-	u16 id;
-
-	ret = xc4000_readreg(priv, XREG_PRODUCT_ID, &id);
-	if (ret == XC_RESULT_SUCCESS) {
-		if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
-			ret = XC_RESULT_RESET_FAILURE;
-		else
-			ret = XC_RESULT_SUCCESS;
-	}
+fail:
+	mutex_unlock(&priv->lock);
 
-	dprintk(1, "%s() returns %s id = 0x%x\n", __func__,
-		ret == XC_RESULT_SUCCESS ? "True" : "False", id);
 	return ret;
 }
-#endif
 
 static int xc4000_set_analog_params(struct dvb_frontend *fe,
 	struct analog_parameters *params)
 {
 	struct xc4000_priv *priv = fe->tuner_priv;
 	unsigned int type = 0;
-	int	ret;
-
-	/* Fix me: it could be air. */
-	priv->rf_mode = XC_RF_MODE_CABLE;
+	int	ret = -EREMOTEIO;
 
 	if (params->mode == V4L2_TUNER_RADIO) {
 		dprintk(1, "%s() frequency=%d (in units of 62.5Hz)\n",
 			__func__, params->frequency);
 
+		mutex_lock(&priv->lock);
+
 		params->std = 0;
 		priv->freq_hz = params->frequency * 125L / 2;
 
 		if (audio_std & XC4000_AUDIO_STD_INPUT1) {
@@ -1346,8 +1311,10 @@
 
 	dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
 		__func__, params->frequency);
 
+	mutex_lock(&priv->lock);
+
 	/* params->frequency is in units of 62.5khz */
 	priv->freq_hz = params->frequency * 62500;
 
 	/* if std is not defined, choose one */
@@ -1454,24 +1421,24 @@
 		goto tune_channel;
 	}
 
 tune_channel:
+	/* Fix me: it could be air. */
+	priv->rf_mode = XC_RF_MODE_CABLE;
 
 	if (check_firmware(fe, type, params->std,
 			   XC4000_Standard[priv->video_standard].int_freq)
 	    != XC_RESULT_SUCCESS) {
-		return -EREMOTEIO;
+		goto fail;
 	}
 
 	ret = xc_SetSignalSource(priv, priv->rf_mode);
 	if (ret != XC_RESULT_SUCCESS) {
 		printk(KERN_ERR
 			"xc4000: xc_SetSignalSource(%d) failed\n",
 			priv->rf_mode);
-		return -EREMOTEIO;
-	}
-
-	{
+		goto fail;
+	} else {
 		u16	video_mode, audio_mode;
 		video_mode = XC4000_Standard[priv->video_standard].VideoMode;
 		audio_mode = XC4000_Standard[priv->video_standard].AudioMode;
 		if (priv->video_standard < XC4000_BG_PAL_A2) {
@@ -1486,49 +1453,58 @@
 		}
 		ret = xc_SetTVStandard(priv, video_mode, audio_mode);
 		if (ret != XC_RESULT_SUCCESS) {
 			printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n");
-			return -EREMOTEIO;
+			goto fail;
 		}
 	}
 
 	if (priv->card_type == XC4000_CARD_DTV2000H_PLUS) {
-		ret = 0;
-		if (xc_write_reg(priv, XREG_D_CODE, 0) != 0)
-			ret = -EREMOTEIO;
+		if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
+			ret = 0;
 		if (xc_write_reg(priv, XREG_AMPLITUDE, 1) != 0)
 			ret = -EREMOTEIO;
 		if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
 			ret = -EREMOTEIO;
 		if (ret != 0) {
 			printk(KERN_ERR "xc4000: setting registers failed\n");
-			return ret;
+			goto fail;
 		}
 	}
 
 	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
 
 	if (debug)
 		xc_debug_dump(priv);
+	ret = 0;
 
-	return 0;
+fail:
+	mutex_unlock(&priv->lock);
+
+	return ret;
 }
 
 static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
 {
 	struct xc4000_priv *priv = fe->tuner_priv;
 
 	*freq = priv->freq_hz;
 
-	if (debug && (priv->cur_fw.type
-		      & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) {
-		u16	snr = 0;
-		if (xc4000_readreg(priv, XREG_SNR, &snr) == 0) {
-			dprintk(1, "%s() freq = %u, SNR = %d\n",
-				__func__, *freq, snr);
-			return 0;
+	if (debug) {
+		mutex_lock(&priv->lock);
+		if ((priv->cur_fw.type
+		     & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) {
+			u16	snr = 0;
+			if (xc4000_readreg(priv, XREG_SNR, &snr) == 0) {
+				mutex_unlock(&priv->lock);
+				dprintk(1, "%s() freq = %u, SNR = %d\n",
+					__func__, *freq, snr);
+				return 0;
+			}
 		}
+		mutex_unlock(&priv->lock);
 	}
+
 	dprintk(1, "%s()\n", __func__);
 
 	return 0;
 }
@@ -1546,58 +1522,57 @@
 {
 	struct xc4000_priv *priv = fe->tuner_priv;
 	u16	lock_status = 0;
 
-	xc_get_lock_status(priv, &lock_status);
+	mutex_lock(&priv->lock);
 
-	dprintk(2, "%s() lock_status = %d\n", __func__, lock_status);
+	if (priv->cur_fw.type & BASE)
+		xc_get_lock_status(priv, &lock_status);
 
 	*status = (lock_status == 1 ?
 		   TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO : 0);
+	if (priv->cur_fw.type & (DTV6 | DTV7 | DTV78 | DTV8))
+		*status &= (~TUNER_STATUS_STEREO);
+
+	mutex_unlock(&priv->lock);
+
+	dprintk(2, "%s() lock_status = %d\n", __func__, lock_status);
 
 	return 0;
 }
 
 static int xc4000_sleep(struct dvb_frontend *fe)
 {
-	/* FIXME: djh disable this for now... */
-	return XC_RESULT_SUCCESS;
-#if 0
-	int ret;
+	struct xc4000_priv *priv = fe->tuner_priv;
+	int	ret = XC_RESULT_SUCCESS;
 
 	dprintk(1, "%s()\n", __func__);
 
+	mutex_lock(&priv->lock);
+
 	/* Avoid firmware reload on slow devices */
-	if (no_poweroff)
-		return 0;
+	if (!no_poweroff && priv->cur_fw.type != XC_POWERED_DOWN) {
+		/* force reset and firmware reload */
+		priv->cur_fw.type = XC_POWERED_DOWN;
 
-	/* According to Xceive technical support, the "powerdown" register
-	   was removed in newer versions of the firmware.  The "supported"
-	   way to sleep the tuner is to pull the reset pin low for 10ms */
-	ret = xc4000_TunerReset(fe);
-	if (ret != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR
-			"xc4000: %s() unable to shutdown tuner\n",
-			__func__);
-		return -EREMOTEIO;
-	} else
-		return XC_RESULT_SUCCESS;
-#endif
+		if (xc_write_reg(priv, XREG_POWER_DOWN, 0)
+		    != XC_RESULT_SUCCESS) {
+			printk(KERN_ERR
+			       "xc4000: %s() unable to shutdown tuner\n",
+			       __func__);
+			ret = -EREMOTEIO;
+		}
+	}
+
+	mutex_unlock(&priv->lock);
+
+	return ret;
 }
 
 static int xc4000_init(struct dvb_frontend *fe)
 {
-	struct xc4000_priv *priv = fe->tuner_priv;
 	dprintk(1, "%s()\n", __func__);
 
-	if (check_firmware(fe, DTV8, 0, priv->if_khz) != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR "xc4000: Unable to initialise tuner\n");
-		return -EREMOTEIO;
-	}
-
-	if (debug)
-		xc_debug_dump(priv);
-
 	return 0;
 }
 
 static int xc4000_release(struct dvb_frontend *fe)
@@ -1641,10 +1616,10 @@
 				   struct i2c_adapter *i2c,
 				   struct xc4000_config *cfg)
 {
 	struct xc4000_priv *priv = NULL;
-	int instance;
-	u16 id = 0;
+	int	instance;
+	u16	id = 0;
 
 	if (cfg->card_type != XC4000_CARD_GENERIC) {
 		if (cfg->card_type == XC4000_CARD_DTV2000H_PLUS) {
 			cfg->i2c_address = 0x61;
@@ -1671,8 +1646,9 @@
 		break;
 	case 1:
 		/* new tuner instance */
 		priv->bandwidth = BANDWIDTH_6_MHZ;
+		mutex_init(&priv->lock);
 		fe->tuner_priv = priv;
 		break;
 	default:
 		/* existing tuner instance */
@@ -1690,10 +1666,17 @@
 	/* Check if firmware has been loaded. It is possible that another
 	   instance of the driver has loaded the firmware.
 	 */
 
-	if (xc4000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS)
+	if (instance == 1) {
+		if (xc4000_readreg(priv, XREG_PRODUCT_ID, &id)
+		    != XC_RESULT_SUCCESS)
 			goto fail;
+	}
+	else {
+		id = ((priv->cur_fw.type & BASE) == 0 ?
+		      XC_PRODUCT_ID_FW_NOT_LOADED : XC_PRODUCT_ID_FW_LOADED);
+	}
 
 	switch (id) {
 	case XC_PRODUCT_ID_FW_LOADED:
 		printk(KERN_INFO
@@ -1720,12 +1703,8 @@
 
 	memcpy(&fe->ops.tuner_ops, &xc4000_tuner_ops,
 		sizeof(struct dvb_tuner_ops));
 
-	/* FIXME: For now, load the firmware at startup.  We will remove this
-	   before the code goes to production... */
-	check_firmware(fe, DTV8, 0, priv->if_khz);
-
 	return fe;
 fail:
 	mutex_unlock(&xc4000_list_mutex);
 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-02-11 19:16             ` istvan_v
@ 2010-02-11 19:21               ` Devin Heitmueller
  2010-02-11 19:35                 ` istvan_v
  2010-02-12 18:26               ` istvan_v
  2010-02-17 18:06               ` [PATCH] " istvan_v
  2 siblings, 1 reply; 30+ messages in thread
From: Devin Heitmueller @ 2010-02-11 19:21 UTC (permalink / raw)
  To: istvan_v; +Cc: linux-media

Hi Istanv,

On Thu, Feb 11, 2010 at 2:16 PM, istvan_v@mailbox.hu
<istvan_v@mailbox.hu> wrote:
> Update: the following patch, which should be applied after the previous
> ones, makes a few additional changes to the XC4000 driver:
>  - adds support for DTV7
>  - implements power management
>  - adds a mutex and locking for tuner operations
>  - some unused or unneeded code has been removed

Is the DTV7 support actually tested?  Or are you just blindly adding
the code in the hope that it works?  I'm just asking because the last
time I spoke to you, you actually didn't have access to a DVB-T signal
source.

Also, I'm not sure I'm comfortable with the way the mutex is
implemented here.  Is this logic copied from some other driver (and if
so, which one), or did you come up with it yourself?

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-02-11 19:21               ` Devin Heitmueller
@ 2010-02-11 19:35                 ` istvan_v
  0 siblings, 0 replies; 30+ messages in thread
From: istvan_v @ 2010-02-11 19:35 UTC (permalink / raw)
  To: linux-media

On 02/11/2010 08:21 PM, Devin Heitmueller wrote:

> Is the DTV7 support actually tested?  Or are you just blindly adding
> the code in the hope that it works?  I'm just asking because the last
> time I spoke to you, you actually didn't have access to a DVB-T signal
> source.

Hi! It is indeed not tested yet, and the other DTV modes are not
either. Is there anything that needs to be done additionally to make
the DTV7 mode work, other than the already added different frequency
offset ((-7000000/2)+1250000=-2250000), firmware type (DTV7), and
video standard (XC4000_DTV7) ?

> Also, I'm not sure I'm comfortable with the way the mutex is
> implemented here.  Is this logic copied from some other driver (and if
> so, which one), or did you come up with it yourself?

The mutex idea is from the XC3028 driver. Since the code is organized
differently there, it is not implemented exactly the same way, but it
is similar.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-02-11 19:16             ` istvan_v
  2010-02-11 19:21               ` Devin Heitmueller
@ 2010-02-12 18:26               ` istvan_v
  2010-02-12 18:34                 ` istvan_v
  2010-02-17 18:06               ` [PATCH] " istvan_v
  2 siblings, 1 reply; 30+ messages in thread
From: istvan_v @ 2010-02-12 18:26 UTC (permalink / raw)
  To: linux-media

[-- Attachment #1: Type: text/plain, Size: 128 bytes --]

Here is another patch, with a few minor changes. It depends on the
previously posted patches, so those should be applied first.

[-- Attachment #2: xc4000-3-28f5eca12bb0.patch --]
[-- Type: text/x-patch, Size: 5412 bytes --]

diff -r -d -N -U4 v4l-dvb-28f5eca12bb0.old/linux/drivers/media/common/tuners/xc4000.c v4l-dvb-28f5eca12bb0/linux/drivers/media/common/tuners/xc4000.c
--- v4l-dvb-28f5eca12bb0.old/linux/drivers/media/common/tuners/xc4000.c	2010-02-12 19:14:24.000000000 +0100
+++ v4l-dvb-28f5eca12bb0/linux/drivers/media/common/tuners/xc4000.c	2010-02-12 19:20:35.000000000 +0100
@@ -256,8 +256,9 @@
 };
 
 static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val);
 static int xc4000_TunerReset(struct dvb_frontend *fe);
+static void xc_debug_dump(struct xc4000_priv *priv);
 
 static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
 {
 	struct i2c_msg msg = { .addr = priv->i2c_props.addr,
@@ -332,12 +333,14 @@
 		(i2c_sequence[index + 1] != 0xFF)) {
 		len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
 		if (len == 0x0000) {
 			/* RESET command */
-			result = xc4000_TunerReset(fe);
 			index += 2;
+#if 0			/* not needed, as already called by check_firmware() */
+			result = xc4000_TunerReset(fe);
 			if (result != XC_RESULT_SUCCESS)
 				return result;
+#endif
 		} else if (len & 0x8000) {
 			/* WAIT command */
 			xc_wait(len & 0x7FFF);
 			index += 2;
@@ -472,14 +475,8 @@
 
 	return 0;
 }
 
-/* WAS THERE
-static int xc_get_buildversion(struct xc4000_priv *priv, u16 *buildrev)
-{
-	return xc4000_readreg(priv, XREG_BUILD, buildrev);
-}*/
-
 static int xc_get_hsync_freq(struct xc4000_priv *priv, u32 *hsync_freq_hz)
 {
 	u16 regData;
 	int result;
@@ -516,14 +513,12 @@
 	}
 	return lockState;
 }
 
-#define XC_TUNE_ANALOG  0
-#define XC_TUNE_DIGITAL 1
-static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz, int mode)
+static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz)
 {
-	int found = 0;
-	int result = 0;
+	int	found = 1;
+	int	result;
 
 	dprintk(1, "%s(%u)\n", __func__, freq_hz);
 
 	/* Don't complain when the request fails because of i2c stretching */
@@ -533,13 +528,23 @@
 
 	if (result != XC_RESULT_SUCCESS)
 		return 0;
 
-	if (mode == XC_TUNE_ANALOG) {
-		if (WaitForLock(priv) == 1)
-			found = 1;
+	/* wait for lock only in analog TV mode */
+	if ((priv->cur_fw.type & (FM | DTV6 | DTV7 | DTV78 | DTV8)) == 0) {
+		if (WaitForLock(priv) == 0)
+			found = 0;
 	}
 
+	/* Wait for stats to stabilize.
+	 * Frame Lines needs two frame times after initial lock
+	 * before it is valid.
+	 */
+	xc_wait(debug ? 100 : 10);
+
+	if (debug)
+		xc_debug_dump(priv);
+
 	return found;
 }
 
 static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val)
@@ -1108,17 +1113,8 @@
 	u16	quality;
 	u8	hw_majorversion = 0, hw_minorversion = 0;
 	u8	fw_majorversion = 0, fw_minorversion = 0;
 
-	if (!(priv->cur_fw.type & BASE))
-		return;
-
-	/* Wait for stats to stabilize.
-	 * Frame Lines needs two frame times after initial lock
-	 * before it is valid.
-	 */
-	xc_wait(100);
-
 	xc_get_ADC_Envelope(priv, &adc_envelope);
 	dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
 
 	xc_get_frequency_error(priv, &freq_error_hz);
@@ -1269,12 +1265,10 @@
 			/* goto fail; */
 		}
 	}
 
-	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
+	xc_tune_channel(priv, priv->freq_hz);
 
-	if (debug)
-		xc_debug_dump(priv);
 	ret = 0;
 
 fail:
 	mutex_unlock(&priv->lock);
@@ -1470,12 +1464,10 @@
 			goto fail;
 		}
 	}
 
-	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
+	xc_tune_channel(priv, priv->freq_hz);
 
-	if (debug)
-		xc_debug_dump(priv);
 	ret = 0;
 
 fail:
 	mutex_unlock(&priv->lock);
@@ -1549,9 +1541,9 @@
 
 	mutex_lock(&priv->lock);
 
 	/* Avoid firmware reload on slow devices */
-	if (!no_poweroff && priv->cur_fw.type != XC_POWERED_DOWN) {
+	if (!no_poweroff && (priv->cur_fw.type & BASE) != 0) {
 		/* force reset and firmware reload */
 		priv->cur_fw.type = XC_POWERED_DOWN;
 
 		if (xc_write_reg(priv, XREG_POWER_DOWN, 0)
@@ -1560,8 +1552,9 @@
 			       "xc4000: %s() unable to shutdown tuner\n",
 			       __func__);
 			ret = -EREMOTEIO;
 		}
+		xc_wait(20);
 	}
 
 	mutex_unlock(&priv->lock);
 
@@ -1638,9 +1631,10 @@
 
 	instance = hybrid_tuner_request_state(struct xc4000_priv, priv,
 					      hybrid_tuner_instance_list,
 					      i2c, cfg->i2c_address, "xc4000");
-	priv->card_type = cfg->card_type;
+	if (cfg->card_type != XC4000_CARD_GENERIC)
+		priv->card_type = cfg->card_type;
 	switch (instance) {
 	case 0:
 		goto fail;
 		break;
@@ -1703,12 +1697,21 @@
 
 	memcpy(&fe->ops.tuner_ops, &xc4000_tuner_ops,
 		sizeof(struct dvb_tuner_ops));
 
+	if (instance == 1) {
+		int	ret;
+		mutex_lock(&priv->lock);
+		ret = xc4000_fwupload(fe);
+		mutex_unlock(&priv->lock);
+		if (ret != XC_RESULT_SUCCESS)
+			goto fail2;
+	}
+
 	return fe;
 fail:
 	mutex_unlock(&xc4000_list_mutex);
-
+fail2:
 	xc4000_release(fe);
 	return NULL;
 }
 EXPORT_SYMBOL(xc4000_attach);
diff -r -d -N -U4 v4l-dvb-28f5eca12bb0.old/linux/drivers/media/video/tuner-core.c v4l-dvb-28f5eca12bb0/linux/drivers/media/video/tuner-core.c
--- v4l-dvb-28f5eca12bb0.old/linux/drivers/media/video/tuner-core.c	2010-02-12 19:14:07.000000000 +0100
+++ v4l-dvb-28f5eca12bb0/linux/drivers/media/video/tuner-core.c	2010-02-12 19:15:07.000000000 +0100
@@ -441,8 +441,9 @@
 		break;
 	}
 	case TUNER_XC4000:
 	{
+		xc4000_cfg.card_type	  = XC4000_CARD_GENERIC;
 		xc4000_cfg.i2c_address	  = t->i2c->addr;
 		/* if_khz will be set when the digital dvb_attach() occurs */
 		xc4000_cfg.if_khz	  = 0;
 		if (!dvb_attach(xc4000_attach,

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: DTV2000 H Plus issues
  2010-02-12 18:26               ` istvan_v
@ 2010-02-12 18:34                 ` istvan_v
  0 siblings, 0 replies; 30+ messages in thread
From: istvan_v @ 2010-02-12 18:34 UTC (permalink / raw)
  To: linux-media

A correction to the previous post: this line:
		if (WaitForLock(priv) == 0)
should actually be:
		if (WaitForLock(priv) != 1)
It does not have an effect on the operation of the driver, though,
since the value set depending on this line is not used.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-02-11 19:16             ` istvan_v
  2010-02-11 19:21               ` Devin Heitmueller
  2010-02-12 18:26               ` istvan_v
@ 2010-02-17 18:06               ` istvan_v
  2010-02-17 23:51                 ` Mauro Carvalho Chehab
  2 siblings, 1 reply; 30+ messages in thread
From: istvan_v @ 2010-02-17 18:06 UTC (permalink / raw)
  To: linux-media

[-- Attachment #1: Type: text/plain, Size: 1654 bytes --]

The attached new patches contain all the previous changes merged, and
are against the latest v4l-dvb revision.

By the way, someone on a forum reported having a DTV1800 H card with
a PCI ID of 107d:6f38. This seems to differ from the already supported
DTV1800 H version (107d:6654) by having an XC4000 tuner instead of
XC3028. From the Windows INF files it seems this card is very similar
to the DTV2000 H Plus, but there is no GPIO for selecting antenna/cable
input.

On 02/11/2010 08:16 PM, istvan_v@mailbox.hu wrote:

> Update: the following patch, which should be applied after the previous
> ones, makes a few additional changes to the XC4000 driver:
>   - adds support for DTV7
>   - implements power management
>   - adds a mutex and locking for tuner operations
>   - some unused or unneeded code has been removed
> 
> On 02/09/2010 06:35 PM, istvan_v@mailbox.hu wrote:
> 
>> There are two separate patches for v4l-dvb revision 28f5eca12bb0: the
>> first one adds the XC4000 driver, while the second one adds support for
>> the Leadtek WinFast DTV2000H Plus card in the CX88 driver.
>>
>> http://www.sharemation.com/IstvanV/v4l/xc4000-28f5eca12bb0.patch
>> http://www.sharemation.com/IstvanV/v4l/cx88-dtv2000h+-28f5eca12bb0.patch
>>
>> These new firmware files are more complete than the previous ones, but
>> are not compatible with the original driver. Both version 1.2 and 1.4
>> are available:
>>
>> http://www.sharemation.com/IstvanV/v4l/xc4000-1.2.fw
>> http://www.sharemation.com/IstvanV/v4l/xc4000-1.4.fw
>>
>> The following simple utility was used for creating the firmware files.
>>
>> http://www.sharemation.com/IstvanV/v4l/xc4000fw.c

[-- Attachment #2: xc4000-14021dfc00f3.patch --]
[-- Type: text/x-patch, Size: 54041 bytes --]

diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/common/tuners/Kconfig v4l-dvb-14021dfc00f3/linux/drivers/media/common/tuners/Kconfig
--- v4l-dvb-14021dfc00f3.old/linux/drivers/media/common/tuners/Kconfig	2010-02-12 02:11:30.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/drivers/media/common/tuners/Kconfig	2010-02-17 17:18:11.000000000 +0100
@@ -22,8 +22,9 @@
 	default VIDEO_MEDIA && I2C
 	depends on VIDEO_MEDIA && I2C
 	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE
@@ -150,8 +151,17 @@
 	  A driver for the silicon tuner XC5000 from Xceive.
 	  This device is only used inside a SiP called together with a
 	  demodulator for now.
 
+config MEDIA_TUNER_XC4000
+	tristate "Xceive XC4000 silicon tuner"
+	depends on VIDEO_MEDIA && I2C
+	default m if MEDIA_TUNER_CUSTOMISE
+	help
+	  A driver for the silicon tuner XC4000 from Xceive.
+	  This device is only used inside a SiP called together with a
+	  demodulator for now.
+
 config MEDIA_TUNER_MXL5005S
 	tristate "MaxLinear MSL5005S silicon tuner"
 	depends on VIDEO_MEDIA && I2C
 	default m if MEDIA_TUNER_CUSTOMISE
diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/common/tuners/Makefile v4l-dvb-14021dfc00f3/linux/drivers/media/common/tuners/Makefile
--- v4l-dvb-14021dfc00f3.old/linux/drivers/media/common/tuners/Makefile	2010-02-12 02:11:30.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/drivers/media/common/tuners/Makefile	2010-02-17 17:18:11.000000000 +0100
@@ -15,8 +15,9 @@
 obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o
 obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
 obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
 obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
+obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
 obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
 obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
 obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
 obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/common/tuners/tuner-types.c v4l-dvb-14021dfc00f3/linux/drivers/media/common/tuners/tuner-types.c
--- v4l-dvb-14021dfc00f3.old/linux/drivers/media/common/tuners/tuner-types.c	2010-02-12 02:11:30.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/drivers/media/common/tuners/tuner-types.c	2010-02-17 17:18:11.000000000 +0100
@@ -1762,8 +1762,12 @@
 	[TUNER_XC5000] = { /* Xceive 5000 */
 		.name   = "Xceive 5000 tuner",
 		/* see xc5000.c for details */
 	},
+	[TUNER_XC4000] = { /* Xceive 4000 */
+		.name   = "Xceive 4000 tuner",
+		/* see xc4000.c for details */
+	},
 	[TUNER_TCL_MF02GIP_5N] = { /* TCL tuner MF02GIP-5N-E */
 		.name   = "TCL tuner MF02GIP-5N-E",
 		.params = tuner_tcl_mf02gip_5n_params,
 		.count  = ARRAY_SIZE(tuner_tcl_mf02gip_5n_params),
diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/common/tuners/xc4000.c v4l-dvb-14021dfc00f3/linux/drivers/media/common/tuners/xc4000.c
--- v4l-dvb-14021dfc00f3.old/linux/drivers/media/common/tuners/xc4000.c	1970-01-01 01:00:00.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/drivers/media/common/tuners/xc4000.c	2010-02-17 17:18:32.000000000 +0100
@@ -0,0 +1,1721 @@
+/*
+ *  Driver for Xceive XC4000 "QAM/8VSB single chip tuner"
+ *
+ *  Copyright (c) 2007 Xceive Corporation
+ *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
+ *  Copyright (c) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
+ *  Copyright (c) 2009 Davide Ferri <d.ferri@zero11.it>
+ *
+ *  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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <asm/unaligned.h>
+
+#include "dvb_frontend.h"
+
+#include "xc4000.h"
+#include "tuner-i2c.h"
+#include "tuner-xc2028-types.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+static int no_poweroff;
+module_param(no_poweroff, int, 0644);
+MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n"
+	"\t\t1 keep device energized and with tuner ready all the times.\n"
+	"\t\tFaster, but consumes more power and keeps the device hotter");
+
+#define XC4000_AUDIO_STD_B		 1
+#define XC4000_AUDIO_STD_A2		 2
+#define XC4000_AUDIO_STD_K3		 4
+#define XC4000_AUDIO_STD_L		 8
+#define XC4000_AUDIO_STD_INPUT1		16
+#define XC4000_AUDIO_STD_MONO		32
+
+static int audio_std;
+module_param(audio_std, int, 0644);
+MODULE_PARM_DESC(audio_std, "Audio standard. XC4000 audio decoder explicitly "
+	"needs to know what audio\n"
+	"standard is needed for some video standards with audio A2 or NICAM.\n"
+	"The valid values are a sum of:\n"
+	" 1: use NICAM/B and A2/B instead of NICAM/A and A2/A\n"
+	" 2: use A2 instead of NICAM or BTSC\n"
+	" 4: use SECAM/K3 instead of K1\n"
+	" 8: use PAL-D/K audio for SECAM-D/K\n"
+	"16: use FM radio input 1 instead of input 2\n"
+	"32: use mono audio (the lower three bits are ignored)\n");
+
+#define XC4000_DEFAULT_FIRMWARE "xc4000.fw"
+
+static char firmware_name[30];
+module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
+MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
+				"default firmware name\n");
+
+static DEFINE_MUTEX(xc4000_list_mutex);
+static LIST_HEAD(hybrid_tuner_instance_list);
+
+#define dprintk(level, fmt, arg...) if (debug >= level) \
+	printk(KERN_INFO "%s: " fmt, "xc4000", ## arg)
+
+/* struct for storing firmware table */
+struct firmware_description {
+	unsigned int  type;
+	v4l2_std_id   id;
+	__u16         int_freq;
+	unsigned char *ptr;
+	unsigned int  size;
+};
+
+struct firmware_properties {
+	unsigned int	type;
+	v4l2_std_id	id;
+	v4l2_std_id	std_req;
+	__u16		int_freq;
+	unsigned int	scode_table;
+	int 		scode_nr;
+};
+
+struct xc4000_priv {
+	struct tuner_i2c_props i2c_props;
+	struct list_head hybrid_tuner_instance_list;
+	struct firmware_description *firm;
+	int	firm_size;
+	__u16	firm_version;
+	u32	if_khz;
+	u32	freq_hz;
+	u32	bandwidth;
+	u8	video_standard;
+	u8	rf_mode;
+	u8	card_type;
+	u8	ignore_i2c_write_errors;
+ /*	struct xc2028_ctrl	ctrl; */
+	struct firmware_properties cur_fw;
+	__u16	hwmodel;
+	__u16	hwvers;
+	struct mutex	lock;
+};
+
+/* Misc Defines */
+#define MAX_TV_STANDARD			24
+#define XC_MAX_I2C_WRITE_LENGTH		64
+#define XC_POWERED_DOWN			0x80000000U
+
+/* Signal Types */
+#define XC_RF_MODE_AIR			0
+#define XC_RF_MODE_CABLE		1
+
+/* Result codes */
+#define XC_RESULT_SUCCESS		0
+#define XC_RESULT_RESET_FAILURE		1
+#define XC_RESULT_I2C_WRITE_FAILURE	2
+#define XC_RESULT_I2C_READ_FAILURE	3
+#define XC_RESULT_OUT_OF_RANGE		5
+
+/* Product id */
+#define XC_PRODUCT_ID_FW_NOT_LOADED	0x2000
+#define XC_PRODUCT_ID_FW_LOADED 	0x0FA0
+
+/* Registers (Write-only) */
+#define XREG_INIT         0x00
+#define XREG_VIDEO_MODE   0x01
+#define XREG_AUDIO_MODE   0x02
+#define XREG_RF_FREQ      0x03
+#define XREG_D_CODE       0x04
+#define XREG_DIRECTSITTING_MODE 0x05
+#define XREG_SEEK_MODE    0x06
+#define XREG_POWER_DOWN   0x08
+#define XREG_SIGNALSOURCE 0x0A
+#define XREG_SMOOTHEDCVBS 0x0E
+#define XREG_AMPLITUDE    0x10
+
+/* Registers (Read-only) */
+#define XREG_ADC_ENV      0x00
+#define XREG_QUALITY      0x01
+#define XREG_FRAME_LINES  0x02
+#define XREG_HSYNC_FREQ   0x03
+#define XREG_LOCK         0x04
+#define XREG_FREQ_ERROR   0x05
+#define XREG_SNR          0x06
+#define XREG_VERSION      0x07
+#define XREG_PRODUCT_ID   0x08
+
+/*
+   Basic firmware description. This will remain with
+   the driver for documentation purposes.
+
+   This represents an I2C firmware file encoded as a
+   string of unsigned char. Format is as follows:
+
+   char[0  ]=len0_MSB  -> len = len_MSB * 256 + len_LSB
+   char[1  ]=len0_LSB  -> length of first write transaction
+   char[2  ]=data0 -> first byte to be sent
+   char[3  ]=data1
+   char[4  ]=data2
+   char[   ]=...
+   char[M  ]=dataN  -> last byte to be sent
+   char[M+1]=len1_MSB  -> len = len_MSB * 256 + len_LSB
+   char[M+2]=len1_LSB  -> length of second write transaction
+   char[M+3]=data0
+   char[M+4]=data1
+   ...
+   etc.
+
+   The [len] value should be interpreted as follows:
+
+   len= len_MSB _ len_LSB
+   len=1111_1111_1111_1111   : End of I2C_SEQUENCE
+   len=0000_0000_0000_0000   : Reset command: Do hardware reset
+   len=0NNN_NNNN_NNNN_NNNN   : Normal transaction: number of bytes = {1:32767)
+   len=1WWW_WWWW_WWWW_WWWW   : Wait command: wait for {1:32767} ms
+
+   For the RESET and WAIT commands, the two following bytes will contain
+   immediately the length of the following transaction.
+*/
+
+struct XC_TV_STANDARD {
+	const char  *Name;
+	u16	    AudioMode;
+	u16	    VideoMode;
+	u16	    int_freq;
+};
+
+/* Tuner standards */
+#define XC4000_MN_NTSC_PAL_BTSC		0
+#define XC4000_MN_NTSC_PAL_A2		1
+#define XC4000_MN_NTSC_PAL_EIAJ		2
+#define XC4000_MN_NTSC_PAL_Mono		3
+#define XC4000_BG_PAL_A2		4
+#define XC4000_BG_PAL_NICAM		5
+#define XC4000_BG_PAL_MONO		6
+#define XC4000_I_PAL_NICAM		7
+#define XC4000_I_PAL_NICAM_MONO		8
+#define XC4000_DK_PAL_A2		9
+#define XC4000_DK_PAL_NICAM		10
+#define XC4000_DK_PAL_MONO		11
+#define XC4000_DK_SECAM_A2DK1		12
+#define XC4000_DK_SECAM_A2LDK3 		13
+#define XC4000_DK_SECAM_A2MONO 		14
+#define XC4000_DK_SECAM_NICAM		15
+#define XC4000_L_SECAM_NICAM		16
+#define XC4000_LC_SECAM_NICAM		17
+#define XC4000_DTV6			18
+#define XC4000_DTV8			19
+#define XC4000_DTV7_8			20
+#define XC4000_DTV7			21
+#define XC4000_FM_Radio_INPUT2 		22
+#define XC4000_FM_Radio_INPUT1  	23
+
+static struct XC_TV_STANDARD XC4000_Standard[MAX_TV_STANDARD] = {
+	{"M/N-NTSC/PAL-BTSC",	0x0000, 0x80A0, 4500},
+	{"M/N-NTSC/PAL-A2",	0x0000, 0x80A0, 4600},
+	{"M/N-NTSC/PAL-EIAJ",	0x0040, 0x80A0, 4500},
+	{"M/N-NTSC/PAL-Mono",	0x0078, 0x80A0, 4500},
+	{"B/G-PAL-A2",		0x0000, 0x8159, 5640},
+	{"B/G-PAL-NICAM",	0x0004, 0x8159, 5740},
+	{"B/G-PAL-MONO",	0x0078, 0x8159, 5500},
+	{"I-PAL-NICAM",		0x0080, 0x8049, 6240},
+	{"I-PAL-NICAM-MONO",	0x0078, 0x8049, 6000},
+	{"D/K-PAL-A2",		0x0000, 0x8049, 6380},
+	{"D/K-PAL-NICAM",	0x0080, 0x8049, 6200},
+	{"D/K-PAL-MONO",	0x0078, 0x8049, 6500},
+	{"D/K-SECAM-A2 DK1",	0x0000, 0x8049, 6340},
+	{"D/K-SECAM-A2 L/DK3",	0x0000, 0x8049, 6000},
+	{"D/K-SECAM-A2 MONO",	0x0078, 0x8049, 6500},
+	{"D/K-SECAM-NICAM",	0x0080, 0x8049, 6200},
+	{"L-SECAM-NICAM",	0x8080, 0x0009, 6200},
+	{"L'-SECAM-NICAM",	0x8080, 0x4009, 6200},
+	{"DTV6",		0x00C0, 0x8002,    0},
+	{"DTV8",		0x00C0, 0x800B,    0},
+	{"DTV7/8",		0x00C0, 0x801B,    0},
+	{"DTV7",		0x00C0, 0x8007,    0},
+	{"FM Radio-INPUT2",	0x0008, 0x9800,10700},
+	{"FM Radio-INPUT1",	0x0008, 0x9000,10700}
+};
+
+static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val);
+static int xc4000_TunerReset(struct dvb_frontend *fe);
+static void xc_debug_dump(struct xc4000_priv *priv);
+
+static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
+{
+	struct i2c_msg msg = { .addr = priv->i2c_props.addr,
+			       .flags = 0, .buf = buf, .len = len };
+	if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
+		if (priv->ignore_i2c_write_errors == 0) {
+			printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n",
+			       len);
+			if (len == 4) {
+				printk("bytes %02x %02x %02x %02x\n", buf[0],
+				       buf[1], buf[2], buf[3]);
+			}
+			return XC_RESULT_I2C_WRITE_FAILURE;
+		}
+	}
+	return XC_RESULT_SUCCESS;
+}
+
+static void xc_wait(int wait_ms)
+{
+	msleep(wait_ms);
+}
+
+static int xc4000_TunerReset(struct dvb_frontend *fe)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+	int ret;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (fe->callback) {
+		ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
+					   fe->dvb->priv :
+					   priv->i2c_props.adap->algo_data,
+					   DVB_FRONTEND_COMPONENT_TUNER,
+					   XC4000_TUNER_RESET, 0);
+		if (ret) {
+			printk(KERN_ERR "xc4000: reset failed\n");
+			return XC_RESULT_RESET_FAILURE;
+		}
+	} else {
+		printk(KERN_ERR "xc4000: no tuner reset callback function, fatal\n");
+		return XC_RESULT_RESET_FAILURE;
+	}
+	return XC_RESULT_SUCCESS;
+}
+
+static int xc_write_reg(struct xc4000_priv *priv, u16 regAddr, u16 i2cData)
+{
+	u8 buf[4];
+	int result;
+
+	buf[0] = (regAddr >> 8) & 0xFF;
+	buf[1] = regAddr & 0xFF;
+	buf[2] = (i2cData >> 8) & 0xFF;
+	buf[3] = i2cData & 0xFF;
+	result = xc_send_i2c_data(priv, buf, 4);
+
+	return result;
+}
+
+static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+
+	int i, nbytes_to_send, result;
+	unsigned int len, pos, index;
+	u8 buf[XC_MAX_I2C_WRITE_LENGTH];
+
+	index = 0;
+	while ((i2c_sequence[index] != 0xFF) ||
+		(i2c_sequence[index + 1] != 0xFF)) {
+		len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
+		if (len == 0x0000) {
+			/* RESET command */
+			index += 2;
+#if 0			/* not needed, as already called by check_firmware() */
+			result = xc4000_TunerReset(fe);
+			if (result != XC_RESULT_SUCCESS)
+				return result;
+#endif
+		} else if (len & 0x8000) {
+			/* WAIT command */
+			xc_wait(len & 0x7FFF);
+			index += 2;
+		} else {
+			/* Send i2c data whilst ensuring individual transactions
+			 * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
+			 */
+			index += 2;
+			buf[0] = i2c_sequence[index];
+			buf[1] = i2c_sequence[index + 1];
+			pos = 2;
+			while (pos < len) {
+				if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
+					nbytes_to_send =
+						XC_MAX_I2C_WRITE_LENGTH;
+				else
+					nbytes_to_send = (len - pos + 2);
+				for (i = 2; i < nbytes_to_send; i++) {
+					buf[i] = i2c_sequence[index + pos +
+						i - 2];
+				}
+				result = xc_send_i2c_data(priv, buf,
+					nbytes_to_send);
+
+				if (result != XC_RESULT_SUCCESS)
+					return result;
+
+				pos += nbytes_to_send - 2;
+			}
+			index += len;
+		}
+	}
+	return XC_RESULT_SUCCESS;
+}
+
+static int xc_SetTVStandard(struct xc4000_priv *priv,
+	u16 VideoMode, u16 AudioMode)
+{
+	int ret;
+	dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
+	dprintk(1, "%s() Standard = %s\n",
+		__func__,
+		XC4000_Standard[priv->video_standard].Name);
+
+	/* Don't complain when the request fails because of i2c stretching */
+	priv->ignore_i2c_write_errors = 1;
+
+	ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
+	if (ret == XC_RESULT_SUCCESS)
+		ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode);
+
+	priv->ignore_i2c_write_errors = 0;
+
+	return ret;
+}
+
+static int xc_SetSignalSource(struct xc4000_priv *priv, u16 rf_mode)
+{
+	dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
+		rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
+
+	if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
+		rf_mode = XC_RF_MODE_CABLE;
+		printk(KERN_ERR
+			"%s(), Invalid mode, defaulting to CABLE",
+			__func__);
+	}
+	return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
+}
+
+static const struct dvb_tuner_ops xc4000_tuner_ops;
+
+static int xc_set_RF_frequency(struct xc4000_priv *priv, u32 freq_hz)
+{
+	u16 freq_code;
+
+	dprintk(1, "%s(%u)\n", __func__, freq_hz);
+
+	if ((freq_hz > xc4000_tuner_ops.info.frequency_max) ||
+		(freq_hz < xc4000_tuner_ops.info.frequency_min))
+		return XC_RESULT_OUT_OF_RANGE;
+
+	freq_code = (u16)(freq_hz / 15625);
+
+	/* WAS: Starting in firmware version 1.1.44, Xceive recommends using the
+	   FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
+	   only be used for fast scanning for channel lock) */
+	return xc_write_reg(priv, XREG_RF_FREQ, freq_code); /* WAS: XREG_FINERFREQ */
+}
+
+static int xc_get_ADC_Envelope(struct xc4000_priv *priv, u16 *adc_envelope)
+{
+	return xc4000_readreg(priv, XREG_ADC_ENV, adc_envelope);
+}
+
+static int xc_get_frequency_error(struct xc4000_priv *priv, u32 *freq_error_hz)
+{
+	int result;
+	u16 regData;
+	u32 tmp;
+
+	result = xc4000_readreg(priv, XREG_FREQ_ERROR, &regData);
+	if (result != XC_RESULT_SUCCESS)
+		return result;
+
+	tmp = (u32)regData & 0xFFFFU;
+	tmp = (tmp < 0x8000U ? tmp : 0x10000U - tmp);
+	(*freq_error_hz) = tmp * 15625;
+	return result;
+}
+
+static int xc_get_lock_status(struct xc4000_priv *priv, u16 *lock_status)
+{
+	return xc4000_readreg(priv, XREG_LOCK, lock_status);
+}
+
+static int xc_get_version(struct xc4000_priv *priv,
+	u8 *hw_majorversion, u8 *hw_minorversion,
+	u8 *fw_majorversion, u8 *fw_minorversion)
+{
+	u16 data;
+	int result;
+
+	result = xc4000_readreg(priv, XREG_VERSION, &data);
+	if (result != XC_RESULT_SUCCESS)
+		return result;
+
+	(*hw_majorversion) = (data >> 12) & 0x0F;
+	(*hw_minorversion) = (data >>  8) & 0x0F;
+	(*fw_majorversion) = (data >>  4) & 0x0F;
+	(*fw_minorversion) = data & 0x0F;
+
+	return 0;
+}
+
+static int xc_get_hsync_freq(struct xc4000_priv *priv, u32 *hsync_freq_hz)
+{
+	u16 regData;
+	int result;
+
+	result = xc4000_readreg(priv, XREG_HSYNC_FREQ, &regData);
+	if (result != XC_RESULT_SUCCESS)
+		return result;
+
+	(*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
+	return result;
+}
+
+static int xc_get_frame_lines(struct xc4000_priv *priv, u16 *frame_lines)
+{
+	return xc4000_readreg(priv, XREG_FRAME_LINES, frame_lines);
+}
+
+static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
+{
+	return xc4000_readreg(priv, XREG_QUALITY, quality);
+}
+
+static u16 WaitForLock(struct xc4000_priv *priv)
+{
+	u16 lockState = 0;
+	int watchDogCount = 40;
+
+	while ((lockState == 0) && (watchDogCount > 0)) {
+		xc_get_lock_status(priv, &lockState);
+		if (lockState != 1) {
+			xc_wait(5);
+			watchDogCount--;
+		}
+	}
+	return lockState;
+}
+
+static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz)
+{
+	int	found = 1;
+	int	result;
+
+	dprintk(1, "%s(%u)\n", __func__, freq_hz);
+
+	/* Don't complain when the request fails because of i2c stretching */
+	priv->ignore_i2c_write_errors = 1;
+	result = xc_set_RF_frequency(priv, freq_hz);
+	priv->ignore_i2c_write_errors = 0;
+
+	if (result != XC_RESULT_SUCCESS)
+		return 0;
+
+	/* wait for lock only in analog TV mode */
+	if ((priv->cur_fw.type & (FM | DTV6 | DTV7 | DTV78 | DTV8)) == 0) {
+		if (WaitForLock(priv) != 1)
+			found = 0;
+	}
+
+	/* Wait for stats to stabilize.
+	 * Frame Lines needs two frame times after initial lock
+	 * before it is valid.
+	 */
+	xc_wait(debug ? 100 : 10);
+
+	if (debug)
+		xc_debug_dump(priv);
+
+	return found;
+}
+
+static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val)
+{
+	u8 buf[2] = { reg >> 8, reg & 0xff };
+	u8 bval[2] = { 0, 0 };
+	struct i2c_msg msg[2] = {
+		{ .addr = priv->i2c_props.addr,
+			.flags = 0, .buf = &buf[0], .len = 2 },
+		{ .addr = priv->i2c_props.addr,
+			.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
+	};
+
+	if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
+		printk(KERN_WARNING "xc4000: I2C read failed\n");
+		return -EREMOTEIO;
+	}
+
+	*val = (bval[0] << 8) | bval[1];
+	return XC_RESULT_SUCCESS;
+}
+
+#define dump_firm_type(t) 	dump_firm_type_and_int_freq(t, 0)
+static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
+{
+	 if (type & BASE)
+		printk("BASE ");
+	 if (type & INIT1)
+		printk("INIT1 ");
+	 if (type & F8MHZ)
+		printk("F8MHZ ");
+	 if (type & MTS)
+		printk("MTS ");
+	 if (type & D2620)
+		printk("D2620 ");
+	 if (type & D2633)
+		printk("D2633 ");
+	 if (type & DTV6)
+		printk("DTV6 ");
+	 if (type & QAM)
+		printk("QAM ");
+	 if (type & DTV7)
+		printk("DTV7 ");
+	 if (type & DTV78)
+		printk("DTV78 ");
+	 if (type & DTV8)
+		printk("DTV8 ");
+	 if (type & FM)
+		printk("FM ");
+	 if (type & INPUT1)
+		printk("INPUT1 ");
+	 if (type & LCD)
+		printk("LCD ");
+	 if (type & NOGD)
+		printk("NOGD ");
+	 if (type & MONO)
+		printk("MONO ");
+	 if (type & ATSC)
+		printk("ATSC ");
+	 if (type & IF)
+		printk("IF ");
+	 if (type & LG60)
+		printk("LG60 ");
+	 if (type & ATI638)
+		printk("ATI638 ");
+	 if (type & OREN538)
+		printk("OREN538 ");
+	 if (type & OREN36)
+		printk("OREN36 ");
+	 if (type & TOYOTA388)
+		printk("TOYOTA388 ");
+	 if (type & TOYOTA794)
+		printk("TOYOTA794 ");
+	 if (type & DIBCOM52)
+		printk("DIBCOM52 ");
+	 if (type & ZARLINK456)
+		printk("ZARLINK456 ");
+	 if (type & CHINA)
+		printk("CHINA ");
+	 if (type & F6MHZ)
+		printk("F6MHZ ");
+	 if (type & INPUT2)
+		printk("INPUT2 ");
+	 if (type & SCODE)
+		printk("SCODE ");
+	 if (type & HAS_IF)
+		printk("HAS_IF_%d ", int_freq);
+}
+
+static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
+			 v4l2_std_id *id)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+	int		i, best_i = -1;
+	unsigned int	best_nr_diffs = 255U;
+
+	if (!priv->firm) {
+		printk("Error! firmware not loaded\n");
+		return -EINVAL;
+	}
+
+	if (((type & ~SCODE) == 0) && (*id == 0))
+		*id = V4L2_STD_PAL;
+
+	/* Seek for generic video standard match */
+	for (i = 0; i < priv->firm_size; i++) {
+		v4l2_std_id	id_diff_mask =
+			(priv->firm[i].id ^ (*id)) & (*id);
+		unsigned int	type_diff_mask =
+			(priv->firm[i].type ^ type)
+			& (BASE_TYPES | DTV_TYPES | LCD | NOGD | MONO | SCODE);
+		unsigned int	nr_diffs;
+
+		if (type_diff_mask
+		    & (BASE | INIT1 | FM | DTV6 | DTV7 | DTV78 | DTV8 | SCODE))
+			continue;
+
+		nr_diffs = hweight64(id_diff_mask) + hweight32(type_diff_mask);
+		if (!nr_diffs)	/* Supports all the requested standards */
+			goto found;
+
+		if (nr_diffs < best_nr_diffs) {
+			best_nr_diffs = nr_diffs;
+			best_i = i;
+		}
+	}
+
+	/* FIXME: Would make sense to seek for type "hint" match ? */
+	if (best_i < 0) {
+		i = -ENOENT;
+		goto ret;
+	}
+
+	if (best_nr_diffs > 0U) {
+		printk("Selecting best matching firmware (%u bits differ) for "
+		       "type=", best_nr_diffs);
+		printk("(%x), id %016llx:\n", type, (unsigned long long)*id);
+		i = best_i;
+	}
+
+found:
+	*id = priv->firm[i].id;
+
+ret:
+	if (debug) {
+		printk("%s firmware for type=", (i < 0) ? "Can't find" :
+		       "Found");
+		dump_firm_type(type);
+		printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+	}
+	return i;
+}
+
+static int load_firmware(struct dvb_frontend *fe, unsigned int type,
+			 v4l2_std_id *id)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+	int                pos, rc;
+	unsigned char      *p;
+
+	pos = seek_firmware(fe, type, id);
+	if (pos < 0)
+		return pos;
+
+	p = priv->firm[pos].ptr;
+
+	/* Don't complain when the request fails because of i2c stretching */
+	priv->ignore_i2c_write_errors = 1;
+
+	rc = xc_load_i2c_sequence(fe, p);
+
+	priv->ignore_i2c_write_errors = 0;
+
+	return rc;
+}
+
+static int xc4000_fwupload(struct dvb_frontend *fe)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+	const struct firmware *fw   = NULL;
+	const unsigned char   *p, *endp;
+	int                   rc = 0;
+	int		      n, n_array;
+	char		      name[33];
+	const char	      *fname;
+
+	if (firmware_name[0] != '\0')
+		fname = firmware_name;
+	else
+		fname = XC4000_DEFAULT_FIRMWARE;
+
+	printk("Reading firmware %s\n",  fname);
+	rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
+	if (rc < 0) {
+		if (rc == -ENOENT)
+			printk("Error: firmware %s not found.\n",
+				   fname);
+		else
+			printk("Error %d while requesting firmware %s \n",
+				   rc, fname);
+
+		return rc;
+	}
+	p = fw->data;
+	endp = p + fw->size;
+
+	if (fw->size < sizeof(name) - 1 + 2 + 2) {
+		printk("Error: firmware file %s has invalid size!\n",
+			  fname);
+		goto corrupt;
+	}
+
+	memcpy(name, p, sizeof(name) - 1);
+	name[sizeof(name) - 1] = 0;
+	p += sizeof(name) - 1;
+
+	priv->firm_version = get_unaligned_le16(p);
+	p += 2;
+
+	n_array = get_unaligned_le16(p);
+	p += 2;
+
+	dprintk(1, "Loading %d firmware images from %s, type: %s, ver %d.%d\n",
+		n_array, fname, name,
+		priv->firm_version >> 8, priv->firm_version & 0xff);
+
+	priv->firm = kzalloc(sizeof(*priv->firm) * n_array, GFP_KERNEL);
+	if (priv->firm == NULL) {
+		printk("Not enough memory to load firmware file.\n");
+		rc = -ENOMEM;
+		goto err;
+	}
+	priv->firm_size = n_array;
+
+	n = -1;
+	while (p < endp) {
+		__u32 type, size;
+		v4l2_std_id id;
+		__u16 int_freq = 0;
+
+		n++;
+		if (n >= n_array) {
+			printk("More firmware images in file than "
+			       "were expected!\n");
+			goto corrupt;
+		}
+
+		/* Checks if there's enough bytes to read */
+		if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
+			goto header;
+
+		type = get_unaligned_le32(p);
+		p += sizeof(type);
+
+		id = get_unaligned_le64(p);
+		p += sizeof(id);
+
+		if (type & HAS_IF) {
+			int_freq = get_unaligned_le16(p);
+			p += sizeof(int_freq);
+			if (endp - p < sizeof(size))
+				goto header;
+		}
+
+		size = get_unaligned_le32(p);
+		p += sizeof(size);
+
+		if (!size || size > endp - p) {
+			printk("Firmware type (%x), id %llx is corrupted "
+			       "(size=%d, expected %d)\n",
+			       type, (unsigned long long)id,
+			       (unsigned)(endp - p), size);
+			goto corrupt;
+		}
+
+		priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
+		if (priv->firm[n].ptr == NULL) {
+			printk("Not enough memory to load firmware file.\n");
+			rc = -ENOMEM;
+			goto err;
+		}
+
+		if (debug) {
+			printk("Reading firmware type ");
+			dump_firm_type_and_int_freq(type, int_freq);
+			printk("(%x), id %llx, size=%d.\n",
+			       type, (unsigned long long)id, size);
+		}
+
+		memcpy(priv->firm[n].ptr, p, size);
+		priv->firm[n].type = type;
+		priv->firm[n].id   = id;
+		priv->firm[n].size = size;
+		priv->firm[n].int_freq = int_freq;
+
+		p += size;
+	}
+
+	if (n + 1 != priv->firm_size) {
+		printk("Firmware file is incomplete!\n");
+		goto corrupt;
+	}
+
+	goto done;
+
+header:
+	printk("Firmware header is incomplete!\n");
+corrupt:
+	rc = -EINVAL;
+	printk("Error: firmware file is corrupted!\n");
+
+err:
+	printk("Releasing partially loaded firmware file.\n");
+
+done:
+	release_firmware(fw);
+	if (rc == 0)
+		dprintk(1, "Firmware files loaded.\n");
+
+	return rc;
+}
+
+static int load_scode(struct dvb_frontend *fe, unsigned int type,
+			 v4l2_std_id *id, __u16 int_freq, int scode)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+	int                pos, rc;
+	unsigned char	   *p;
+	u8 scode_buf[13];
+	u8 indirect_mode[5];
+
+	dprintk(1, "%s called int_freq=%d\n", __func__, int_freq);
+
+	if (!int_freq) {
+		pos = seek_firmware(fe, type, id);
+		if (pos < 0)
+			return pos;
+	} else {
+		for (pos = 0; pos < priv->firm_size; pos++) {
+			if ((priv->firm[pos].int_freq == int_freq) &&
+			    (priv->firm[pos].type & HAS_IF))
+				break;
+		}
+		if (pos == priv->firm_size)
+			return -ENOENT;
+	}
+
+	p = priv->firm[pos].ptr;
+
+	if (priv->firm[pos].size != 12 * 16 || scode >= 16)
+		return -EINVAL;
+	p += 12 * scode;
+
+	tuner_info("Loading SCODE for type=");
+	dump_firm_type_and_int_freq(priv->firm[pos].type,
+				    priv->firm[pos].int_freq);
+	printk("(%x), id %016llx.\n", priv->firm[pos].type,
+	       (unsigned long long)*id);
+
+	scode_buf[0] = 0x00;
+	memcpy(&scode_buf[1], p, 12);
+
+	/* Enter direct-mode */
+	rc = xc_write_reg(priv, XREG_DIRECTSITTING_MODE, 0);
+	if (rc < 0) {
+		printk("failed to put device into direct mode!\n");
+		return -EIO;
+	}
+
+	rc = xc_send_i2c_data(priv, scode_buf, 13);
+	if (rc != XC_RESULT_SUCCESS) {
+		/* Even if the send failed, make sure we set back to indirect
+		   mode */
+		printk("Failed to set scode %d\n", rc);
+	}
+
+	/* Switch back to indirect-mode */
+	memset(indirect_mode, 0, sizeof(indirect_mode));
+	indirect_mode[4] = 0x88;
+	xc_send_i2c_data(priv, indirect_mode, sizeof(indirect_mode));
+	msleep(10);
+
+	return 0;
+}
+
+static int check_firmware(struct dvb_frontend *fe, unsigned int type,
+			  v4l2_std_id std, __u16 int_freq)
+{
+	struct xc4000_priv         *priv = fe->tuner_priv;
+	struct firmware_properties new_fw;
+	int			   rc = 0, is_retry = 0;
+	u16			   version = 0, hwmodel;
+	v4l2_std_id		   std0;
+	u8 			   hw_major, hw_minor, fw_major, fw_minor;
+
+	dprintk(1, "%s called\n", __func__);
+
+	if (!priv->firm) {
+		rc = xc4000_fwupload(fe);
+		if (rc < 0)
+			return rc;
+	}
+
+#ifdef DJH_DEBUG
+	if (priv->ctrl.mts && !(type & FM))
+		type |= MTS;
+#endif
+
+retry:
+	new_fw.type = type;
+	new_fw.id = std;
+	new_fw.std_req = std;
+	new_fw.scode_table = SCODE /* | priv->ctrl.scode_table */;
+	new_fw.scode_nr = 0;
+	new_fw.int_freq = int_freq;
+
+	dprintk(1, "checking firmware, user requested type=");
+	if (debug) {
+		dump_firm_type(new_fw.type);
+		printk("(%x), id %016llx, ", new_fw.type,
+		       (unsigned long long)new_fw.std_req);
+		if (!int_freq) {
+			printk("scode_tbl ");
+#ifdef DJH_DEBUG
+			dump_firm_type(priv->ctrl.scode_table);
+			printk("(%x), ", priv->ctrl.scode_table);
+#endif
+		} else
+			printk("int_freq %d, ", new_fw.int_freq);
+		printk("scode_nr %d\n", new_fw.scode_nr);
+	}
+
+	/* No need to reload base firmware if it matches */
+	if (priv->cur_fw.type & BASE) {
+		dprintk(1, "BASE firmware not changed.\n");
+		goto skip_base;
+	}
+
+	/* Updating BASE - forget about all currently loaded firmware */
+	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+
+	/* Reset is needed before loading firmware */
+	rc = xc4000_TunerReset(fe);
+	if (rc < 0)
+		goto fail;
+
+	/* BASE firmwares are all std0 */
+	std0 = 0;
+	rc = load_firmware(fe, BASE, &std0);
+	if (rc < 0) {
+		printk("Error %d while loading base firmware\n", rc);
+		goto fail;
+	}
+
+	/* Load INIT1, if needed */
+	dprintk(1, "Load init1 firmware, if exists\n");
+
+	rc = load_firmware(fe, BASE | INIT1, &std0);
+	if (rc == -ENOENT)
+		rc = load_firmware(fe, BASE | INIT1, &std0);
+	if (rc < 0 && rc != -ENOENT) {
+		tuner_err("Error %d while loading init1 firmware\n",
+			  rc);
+		goto fail;
+	}
+
+skip_base:
+	/*
+	 * No need to reload standard specific firmware if base firmware
+	 * was not reloaded and requested video standards have not changed.
+	 */
+	if (priv->cur_fw.type == (BASE | new_fw.type) &&
+	    priv->cur_fw.std_req == std) {
+		dprintk(1, "Std-specific firmware already loaded.\n");
+		goto skip_std_specific;
+	}
+
+	/* Reloading std-specific firmware forces a SCODE update */
+	priv->cur_fw.scode_table = 0;
+
+	/* Load the standard firmware */
+	rc = load_firmware(fe, new_fw.type, &new_fw.id);
+
+	if (rc < 0)
+		goto fail;
+
+skip_std_specific:
+	if (priv->cur_fw.scode_table == new_fw.scode_table &&
+	    priv->cur_fw.scode_nr == new_fw.scode_nr) {
+		dprintk(1, "SCODE firmware already loaded.\n");
+		goto check_device;
+	}
+
+	/* Load SCODE firmware, if exists */
+	rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
+			new_fw.int_freq, new_fw.scode_nr);
+	if (rc != XC_RESULT_SUCCESS)
+		dprintk(1, "load scode failed %d\n", rc);
+
+check_device:
+	rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel);
+
+	if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major,
+			   &fw_minor) != XC_RESULT_SUCCESS) {
+		printk("Unable to read tuner registers.\n");
+		goto fail;
+	}
+
+	dprintk(1, "Device is Xceive %d version %d.%d, "
+		"firmware version %d.%d\n",
+		hwmodel, hw_major, hw_minor, fw_major, fw_minor);
+
+	/* Check firmware version against what we downloaded. */
+#ifdef DJH_DEBUG
+	if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
+		printk("Incorrect readback of firmware version %x.\n",
+		       (version & 0xff));
+		goto fail;
+	}
+#endif
+
+	/* Check that the tuner hardware model remains consistent over time. */
+	if (priv->hwmodel == 0 && hwmodel == 4000) {
+		priv->hwmodel = hwmodel;
+		priv->hwvers  = version & 0xff00;
+	} else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
+		   priv->hwvers != (version & 0xff00)) {
+		printk("Read invalid device hardware information - tuner "
+		       "hung?\n");
+		goto fail;
+	}
+
+	memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
+
+	/*
+	 * By setting BASE in cur_fw.type only after successfully loading all
+	 * firmwares, we can:
+	 * 1. Identify that BASE firmware with type=0 has been loaded;
+	 * 2. Tell whether BASE firmware was just changed the next time through.
+	 */
+	priv->cur_fw.type |= BASE;
+
+	return 0;
+
+fail:
+	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
+	if (!is_retry) {
+		msleep(50);
+		is_retry = 1;
+		dprintk(1, "Retrying firmware load\n");
+		goto retry;
+	}
+
+	if (rc == -ENOENT)
+		rc = -EINVAL;
+	return rc;
+}
+
+static void xc_debug_dump(struct xc4000_priv *priv)
+{
+	u16	adc_envelope;
+	u32	freq_error_hz = 0;
+	u16	lock_status;
+	u32	hsync_freq_hz = 0;
+	u16	frame_lines;
+	u16	quality;
+	u8	hw_majorversion = 0, hw_minorversion = 0;
+	u8	fw_majorversion = 0, fw_minorversion = 0;
+
+	xc_get_ADC_Envelope(priv, &adc_envelope);
+	dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
+
+	xc_get_frequency_error(priv, &freq_error_hz);
+	dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
+
+	xc_get_lock_status(priv, &lock_status);
+	dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
+		lock_status);
+
+	xc_get_version(priv, &hw_majorversion, &hw_minorversion,
+		       &fw_majorversion, &fw_minorversion);
+	dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
+		hw_majorversion, hw_minorversion,
+		fw_majorversion, fw_minorversion);
+
+	if (priv->video_standard < XC4000_FM_Radio_INPUT2) {
+		xc_get_hsync_freq(priv, &hsync_freq_hz);
+		dprintk(1, "*** Horizontal sync frequency = %d Hz\n",
+			hsync_freq_hz);
+
+		xc_get_frame_lines(priv, &frame_lines);
+		dprintk(1, "*** Frame lines = %d\n", frame_lines);
+	}
+
+	xc_get_quality(priv, &quality);
+	dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
+}
+
+static int xc4000_set_params(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+	unsigned int type;
+	int	ret = -EREMOTEIO;
+
+	dprintk(1, "%s() frequency=%d (Hz)\n", __func__, params->frequency);
+
+	mutex_lock(&priv->lock);
+
+	if (fe->ops.info.type == FE_ATSC) {
+		dprintk(1, "%s() ATSC\n", __func__);
+		switch (params->u.vsb.modulation) {
+		case VSB_8:
+		case VSB_16:
+			dprintk(1, "%s() VSB modulation\n", __func__);
+			priv->rf_mode = XC_RF_MODE_AIR;
+			priv->freq_hz = params->frequency - 1750000;
+			priv->bandwidth = BANDWIDTH_6_MHZ;
+			priv->video_standard = XC4000_DTV6;
+			type = DTV6;
+			break;
+		case QAM_64:
+		case QAM_256:
+		case QAM_AUTO:
+			dprintk(1, "%s() QAM modulation\n", __func__);
+			priv->rf_mode = XC_RF_MODE_CABLE;
+			priv->freq_hz = params->frequency - 1750000;
+			priv->bandwidth = BANDWIDTH_6_MHZ;
+			priv->video_standard = XC4000_DTV6;
+			type = DTV6;
+			break;
+		default:
+			ret = -EINVAL;
+			goto fail;
+		}
+	} else if (fe->ops.info.type == FE_OFDM) {
+		dprintk(1, "%s() OFDM\n", __func__);
+		switch (params->u.ofdm.bandwidth) {
+		case BANDWIDTH_6_MHZ:
+			priv->bandwidth = BANDWIDTH_6_MHZ;
+			priv->video_standard = XC4000_DTV6;
+			priv->freq_hz = params->frequency - 1750000;
+			type = DTV6;
+			break;
+		case BANDWIDTH_7_MHZ:
+			priv->bandwidth = BANDWIDTH_7_MHZ;
+			priv->video_standard = XC4000_DTV7;
+			priv->freq_hz = params->frequency - 2250000;
+			type = DTV7;
+			break;
+		case BANDWIDTH_8_MHZ:
+			priv->bandwidth = BANDWIDTH_8_MHZ;
+			priv->video_standard = XC4000_DTV8;
+			priv->freq_hz = params->frequency - 2750000;
+			type = DTV8;
+			break;
+		case BANDWIDTH_AUTO:
+			if (params->frequency < 400000000) {
+				priv->bandwidth = BANDWIDTH_7_MHZ;
+				priv->freq_hz = params->frequency - 2250000;
+			} else {
+				priv->bandwidth = BANDWIDTH_8_MHZ;
+				priv->freq_hz = params->frequency - 2750000;
+			}
+			priv->video_standard = XC4000_DTV7_8;
+			type = DTV78;
+			break;
+		default:
+			printk(KERN_ERR "xc4000 bandwidth not set!\n");
+			ret = -EINVAL;
+			goto fail;
+		}
+		priv->rf_mode = XC_RF_MODE_AIR;
+	} else {
+		printk(KERN_ERR "xc4000 modulation type not supported!\n");
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	dprintk(1, "%s() frequency=%d (compensated)\n",
+		__func__, priv->freq_hz);
+
+	/* Make sure the correct firmware type is loaded */
+	if (check_firmware(fe, type, 0, priv->if_khz) != XC_RESULT_SUCCESS)
+		goto fail;
+
+	ret = xc_SetSignalSource(priv, priv->rf_mode);
+	if (ret != XC_RESULT_SUCCESS) {
+		printk(KERN_ERR
+		       "xc4000: xc_SetSignalSource(%d) failed\n",
+		       priv->rf_mode);
+		goto fail;
+	} else {
+		u16	video_mode, audio_mode;
+		video_mode = XC4000_Standard[priv->video_standard].VideoMode;
+		audio_mode = XC4000_Standard[priv->video_standard].AudioMode;
+		if (type == DTV6 && priv->firm_version != 0x0102)
+			video_mode |= 0x0001;
+		ret = xc_SetTVStandard(priv, video_mode, audio_mode);
+		if (ret != XC_RESULT_SUCCESS) {
+			printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n");
+			/* DJH - do not return when it fails... */
+			/* goto fail; */
+		}
+	}
+
+	if (priv->card_type == XC4000_CARD_DTV2000H_PLUS) {
+		if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
+			ret = 0;
+		if (xc_write_reg(priv, XREG_AMPLITUDE,
+				 (priv->firm_version == 0x0102 ? 132 : 134))
+		    != 0)
+			ret = -EREMOTEIO;
+		if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
+			ret = -EREMOTEIO;
+		if (ret != 0) {
+			printk(KERN_ERR "xc4000: setting registers failed\n");
+			/* goto fail; */
+		}
+	}
+
+	xc_tune_channel(priv, priv->freq_hz);
+
+	ret = 0;
+
+fail:
+	mutex_unlock(&priv->lock);
+
+	return ret;
+}
+
+static int xc4000_set_analog_params(struct dvb_frontend *fe,
+	struct analog_parameters *params)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+	unsigned int type = 0;
+	int	ret = -EREMOTEIO;
+
+	if (params->mode == V4L2_TUNER_RADIO) {
+		dprintk(1, "%s() frequency=%d (in units of 62.5Hz)\n",
+			__func__, params->frequency);
+
+		mutex_lock(&priv->lock);
+
+		params->std = 0;
+		priv->freq_hz = params->frequency * 125L / 2;
+
+		if (audio_std & XC4000_AUDIO_STD_INPUT1) {
+			priv->video_standard = XC4000_FM_Radio_INPUT1;
+			type = FM | INPUT1;
+		} else {
+			priv->video_standard = XC4000_FM_Radio_INPUT2;
+			type = FM | INPUT2;
+		}
+
+		goto tune_channel;
+	}
+
+	dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
+		__func__, params->frequency);
+
+	mutex_lock(&priv->lock);
+
+	/* params->frequency is in units of 62.5khz */
+	priv->freq_hz = params->frequency * 62500;
+
+	/* if std is not defined, choose one */
+	if (!params->std)
+		params->std = V4L2_STD_PAL_BG;
+
+	params->std &= V4L2_STD_ALL;
+	if (audio_std & XC4000_AUDIO_STD_MONO)
+		type = MONO;
+
+	if (params->std & V4L2_STD_MN) {
+		params->std = V4L2_STD_MN;
+		if (audio_std & XC4000_AUDIO_STD_MONO) {
+			priv->video_standard = XC4000_MN_NTSC_PAL_Mono;
+		} else if (audio_std & XC4000_AUDIO_STD_A2) {
+			params->std |= V4L2_STD_A2;
+			priv->video_standard = XC4000_MN_NTSC_PAL_A2;
+		} else {
+			params->std |= V4L2_STD_BTSC;
+			priv->video_standard = XC4000_MN_NTSC_PAL_BTSC;
+		}
+		goto tune_channel;
+	}
+
+	if (params->std & V4L2_STD_PAL_BG) {
+		params->std = V4L2_STD_PAL_BG;
+		if (audio_std & XC4000_AUDIO_STD_MONO) {
+			priv->video_standard = XC4000_BG_PAL_MONO;
+		} else if (!(audio_std & XC4000_AUDIO_STD_A2)) {
+			if (!(audio_std & XC4000_AUDIO_STD_B)) {
+				params->std |= V4L2_STD_NICAM_A;
+				priv->video_standard = XC4000_BG_PAL_NICAM;
+			} else {
+				params->std |= V4L2_STD_NICAM_B;
+				priv->video_standard = XC4000_BG_PAL_NICAM;
+			}
+		} else {
+			if (!(audio_std & XC4000_AUDIO_STD_B)) {
+				params->std |= V4L2_STD_A2_A;
+				priv->video_standard = XC4000_BG_PAL_A2;
+			} else {
+				params->std |= V4L2_STD_A2_B;
+				priv->video_standard = XC4000_BG_PAL_A2;
+			}
+		}
+		goto tune_channel;
+	}
+
+	if (params->std & V4L2_STD_PAL_I) {
+		/* default to NICAM audio standard */
+		params->std = V4L2_STD_PAL_I | V4L2_STD_NICAM;
+		if (audio_std & XC4000_AUDIO_STD_MONO) {
+			priv->video_standard = XC4000_I_PAL_NICAM_MONO;
+		} else {
+			priv->video_standard = XC4000_I_PAL_NICAM;
+		}
+		goto tune_channel;
+	}
+
+	if (params->std & V4L2_STD_PAL_DK) {
+		params->std = V4L2_STD_PAL_DK;
+		if (audio_std & XC4000_AUDIO_STD_MONO) {
+			priv->video_standard = XC4000_DK_PAL_MONO;
+		} else if (audio_std & XC4000_AUDIO_STD_A2) {
+			params->std |= V4L2_STD_A2;
+			priv->video_standard = XC4000_DK_PAL_A2;
+		} else {
+			params->std |= V4L2_STD_NICAM;
+			priv->video_standard = XC4000_DK_PAL_NICAM;
+		}
+		goto tune_channel;
+	}
+
+	if (params->std & V4L2_STD_SECAM_DK) {
+		/* default to A2 audio standard */
+		params->std = V4L2_STD_SECAM_DK | V4L2_STD_A2;
+		if (audio_std & XC4000_AUDIO_STD_L) {
+			type = 0;
+			priv->video_standard = XC4000_DK_SECAM_NICAM;
+		} else if (audio_std & XC4000_AUDIO_STD_MONO) {
+			priv->video_standard = XC4000_DK_SECAM_A2MONO;
+		} else if (audio_std & XC4000_AUDIO_STD_K3) {
+			params->std |= V4L2_STD_SECAM_K3;
+			priv->video_standard = XC4000_DK_SECAM_A2LDK3;
+		} else {
+			priv->video_standard = XC4000_DK_SECAM_A2DK1;
+		}
+		goto tune_channel;
+	}
+
+	if (params->std & V4L2_STD_SECAM_L) {
+		/* default to NICAM audio standard */
+		type = 0;
+		params->std = V4L2_STD_SECAM_L | V4L2_STD_NICAM;
+		priv->video_standard = XC4000_L_SECAM_NICAM;
+		goto tune_channel;
+	}
+
+	if (params->std & V4L2_STD_SECAM_LC) {
+		/* default to NICAM audio standard */
+		type = 0;
+		params->std = V4L2_STD_SECAM_LC | V4L2_STD_NICAM;
+		priv->video_standard = XC4000_LC_SECAM_NICAM;
+		goto tune_channel;
+	}
+
+tune_channel:
+	/* Fix me: it could be air. */
+	priv->rf_mode = XC_RF_MODE_CABLE;
+
+	if (check_firmware(fe, type, params->std,
+			   XC4000_Standard[priv->video_standard].int_freq)
+	    != XC_RESULT_SUCCESS) {
+		goto fail;
+	}
+
+	ret = xc_SetSignalSource(priv, priv->rf_mode);
+	if (ret != XC_RESULT_SUCCESS) {
+		printk(KERN_ERR
+			"xc4000: xc_SetSignalSource(%d) failed\n",
+			priv->rf_mode);
+		goto fail;
+	} else {
+		u16	video_mode, audio_mode;
+		video_mode = XC4000_Standard[priv->video_standard].VideoMode;
+		audio_mode = XC4000_Standard[priv->video_standard].AudioMode;
+		if (priv->video_standard < XC4000_BG_PAL_A2) {
+			if (type & NOGD)
+				video_mode &= 0xFF7F;
+		} else if (priv->video_standard < XC4000_I_PAL_NICAM) {
+			if (priv->card_type == XC4000_CARD_DTV2000H_PLUS &&
+			    priv->firm_version == 0x0102)
+				video_mode &= 0xFEFF;
+			if (audio_std & XC4000_AUDIO_STD_B)
+				video_mode |= 0x0080;
+		}
+		ret = xc_SetTVStandard(priv, video_mode, audio_mode);
+		if (ret != XC_RESULT_SUCCESS) {
+			printk(KERN_ERR "xc4000: xc_SetTVStandard failed\n");
+			goto fail;
+		}
+	}
+
+	if (priv->card_type == XC4000_CARD_DTV2000H_PLUS) {
+		if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
+			ret = 0;
+		if (xc_write_reg(priv, XREG_AMPLITUDE, 1) != 0)
+			ret = -EREMOTEIO;
+		if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
+			ret = -EREMOTEIO;
+		if (ret != 0) {
+			printk(KERN_ERR "xc4000: setting registers failed\n");
+			goto fail;
+		}
+	}
+
+	xc_tune_channel(priv, priv->freq_hz);
+
+	ret = 0;
+
+fail:
+	mutex_unlock(&priv->lock);
+
+	return ret;
+}
+
+static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+
+	*freq = priv->freq_hz;
+
+	if (debug) {
+		mutex_lock(&priv->lock);
+		if ((priv->cur_fw.type
+		     & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) {
+			u16	snr = 0;
+			if (xc4000_readreg(priv, XREG_SNR, &snr) == 0) {
+				mutex_unlock(&priv->lock);
+				dprintk(1, "%s() freq = %u, SNR = %d\n",
+					__func__, *freq, snr);
+				return 0;
+			}
+		}
+		mutex_unlock(&priv->lock);
+	}
+
+	dprintk(1, "%s()\n", __func__);
+
+	return 0;
+}
+
+static int xc4000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+	dprintk(1, "%s()\n", __func__);
+
+	*bw = priv->bandwidth;
+	return 0;
+}
+
+static int xc4000_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+	u16	lock_status = 0;
+
+	mutex_lock(&priv->lock);
+
+	if (priv->cur_fw.type & BASE)
+		xc_get_lock_status(priv, &lock_status);
+
+	*status = (lock_status == 1 ?
+		   TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO : 0);
+	if (priv->cur_fw.type & (DTV6 | DTV7 | DTV78 | DTV8))
+		*status &= (~TUNER_STATUS_STEREO);
+
+	mutex_unlock(&priv->lock);
+
+	dprintk(2, "%s() lock_status = %d\n", __func__, lock_status);
+
+	return 0;
+}
+
+static int xc4000_sleep(struct dvb_frontend *fe)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+	int	ret = XC_RESULT_SUCCESS;
+
+	dprintk(1, "%s()\n", __func__);
+
+	mutex_lock(&priv->lock);
+
+	/* Avoid firmware reload on slow devices */
+	if (!no_poweroff && (priv->cur_fw.type & BASE) != 0) {
+		/* force reset and firmware reload */
+		priv->cur_fw.type = XC_POWERED_DOWN;
+
+		if (xc_write_reg(priv, XREG_POWER_DOWN, 0)
+		    != XC_RESULT_SUCCESS) {
+			printk(KERN_ERR
+			       "xc4000: %s() unable to shutdown tuner\n",
+			       __func__);
+			ret = -EREMOTEIO;
+		}
+		xc_wait(20);
+	}
+
+	mutex_unlock(&priv->lock);
+
+	return ret;
+}
+
+static int xc4000_init(struct dvb_frontend *fe)
+{
+	dprintk(1, "%s()\n", __func__);
+
+	return 0;
+}
+
+static int xc4000_release(struct dvb_frontend *fe)
+{
+	struct xc4000_priv *priv = fe->tuner_priv;
+
+	dprintk(1, "%s()\n", __func__);
+
+	mutex_lock(&xc4000_list_mutex);
+
+	if (priv)
+		hybrid_tuner_release_state(priv);
+
+	mutex_unlock(&xc4000_list_mutex);
+
+	fe->tuner_priv = NULL;
+
+	return 0;
+}
+
+static const struct dvb_tuner_ops xc4000_tuner_ops = {
+	.info = {
+		.name           = "Xceive XC4000",
+		.frequency_min  =    1000000,
+		.frequency_max  = 1023000000,
+		.frequency_step =      50000,
+	},
+
+	.release	   = xc4000_release,
+	.init		   = xc4000_init,
+	.sleep		   = xc4000_sleep,
+
+	.set_params	   = xc4000_set_params,
+	.set_analog_params = xc4000_set_analog_params,
+	.get_frequency	   = xc4000_get_frequency,
+	.get_bandwidth	   = xc4000_get_bandwidth,
+	.get_status	   = xc4000_get_status
+};
+
+struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
+				   struct i2c_adapter *i2c,
+				   struct xc4000_config *cfg)
+{
+	struct xc4000_priv *priv = NULL;
+	int	instance;
+	u16	id = 0;
+
+	if (cfg->card_type != XC4000_CARD_GENERIC) {
+		if (cfg->card_type == XC4000_CARD_DTV2000H_PLUS) {
+			cfg->i2c_address = 0x61;
+			cfg->if_khz = 4560;
+		} else {			/* default to PCTV 340E */
+			cfg->i2c_address = 0x61;
+			cfg->if_khz = 5400;
+		}
+	}
+
+	dprintk(1, "%s(%d-%04x)\n", __func__,
+		i2c ? i2c_adapter_id(i2c) : -1,
+		cfg ? cfg->i2c_address : -1);
+
+	mutex_lock(&xc4000_list_mutex);
+
+	instance = hybrid_tuner_request_state(struct xc4000_priv, priv,
+					      hybrid_tuner_instance_list,
+					      i2c, cfg->i2c_address, "xc4000");
+	if (cfg->card_type != XC4000_CARD_GENERIC)
+		priv->card_type = cfg->card_type;
+	switch (instance) {
+	case 0:
+		goto fail;
+		break;
+	case 1:
+		/* new tuner instance */
+		priv->bandwidth = BANDWIDTH_6_MHZ;
+		mutex_init(&priv->lock);
+		fe->tuner_priv = priv;
+		break;
+	default:
+		/* existing tuner instance */
+		fe->tuner_priv = priv;
+		break;
+	}
+
+	if (priv->if_khz == 0) {
+		/* If the IF hasn't been set yet, use the value provided by
+		   the caller (occurs in hybrid devices where the analog
+		   call to xc4000_attach occurs before the digital side) */
+		priv->if_khz = cfg->if_khz;
+	}
+
+	/* Check if firmware has been loaded. It is possible that another
+	   instance of the driver has loaded the firmware.
+	 */
+
+	if (instance == 1) {
+		if (xc4000_readreg(priv, XREG_PRODUCT_ID, &id)
+		    != XC_RESULT_SUCCESS)
+			goto fail;
+	}
+	else {
+		id = ((priv->cur_fw.type & BASE) == 0 ?
+		      XC_PRODUCT_ID_FW_NOT_LOADED : XC_PRODUCT_ID_FW_LOADED);
+	}
+
+	switch (id) {
+	case XC_PRODUCT_ID_FW_LOADED:
+		printk(KERN_INFO
+			"xc4000: Successfully identified at address 0x%02x\n",
+			cfg->i2c_address);
+		printk(KERN_INFO
+			"xc4000: Firmware has been loaded previously\n");
+		break;
+	case XC_PRODUCT_ID_FW_NOT_LOADED:
+		printk(KERN_INFO
+			"xc4000: Successfully identified at address 0x%02x\n",
+			cfg->i2c_address);
+		printk(KERN_INFO
+			"xc4000: Firmware has not been loaded previously\n");
+		break;
+	default:
+		printk(KERN_ERR
+			"xc4000: Device not found at addr 0x%02x (0x%x)\n",
+			cfg->i2c_address, id);
+		goto fail;
+	}
+
+	mutex_unlock(&xc4000_list_mutex);
+
+	memcpy(&fe->ops.tuner_ops, &xc4000_tuner_ops,
+		sizeof(struct dvb_tuner_ops));
+
+	if (instance == 1) {
+		int	ret;
+		mutex_lock(&priv->lock);
+		ret = xc4000_fwupload(fe);
+		mutex_unlock(&priv->lock);
+		if (ret != XC_RESULT_SUCCESS)
+			goto fail2;
+	}
+
+	return fe;
+fail:
+	mutex_unlock(&xc4000_list_mutex);
+fail2:
+	xc4000_release(fe);
+	return NULL;
+}
+EXPORT_SYMBOL(xc4000_attach);
+
+MODULE_AUTHOR("Steven Toth, Davide Ferri");
+MODULE_DESCRIPTION("Xceive xc4000 silicon tuner driver");
+MODULE_LICENSE("GPL");
diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/common/tuners/xc4000.h v4l-dvb-14021dfc00f3/linux/drivers/media/common/tuners/xc4000.h
--- v4l-dvb-14021dfc00f3.old/linux/drivers/media/common/tuners/xc4000.h	1970-01-01 01:00:00.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/drivers/media/common/tuners/xc4000.h	2010-02-17 17:18:11.000000000 +0100
@@ -0,0 +1,66 @@
+/*
+ *  Driver for Xceive XC4000 "QAM/8VSB single chip tuner"
+ *
+ *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __XC4000_H__
+#define __XC4000_H__
+
+#include <linux/firmware.h>
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+#define XC4000_CARD_GENERIC		0
+#define XC4000_CARD_PCTV_340E		1
+#define XC4000_CARD_DTV2000H_PLUS	2
+
+struct xc4000_config {
+	u8	card_type;	/* if card type is not generic, all other */
+	u8	i2c_address;	/* parameters are automatically set */
+	u32	if_khz;
+};
+
+/* xc4000 callback command */
+#define XC4000_TUNER_RESET		0
+
+/* For each bridge framework, when it attaches either analog or digital,
+ * it has to store a reference back to its _core equivalent structure,
+ * so that it can service the hardware by steering gpio's etc.
+ * Each bridge implementation is different so cast devptr accordingly.
+ * The xc4000 driver cares not for this value, other than ensuring
+ * it's passed back to a bridge during tuner_callback().
+ */
+
+#if defined(CONFIG_MEDIA_TUNER_XC4000) || \
+    (defined(CONFIG_MEDIA_TUNER_XC4000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
+					  struct i2c_adapter *i2c,
+					  struct xc4000_config *cfg);
+#else
+static inline struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
+						 struct i2c_adapter *i2c,
+						 struct xc4000_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/tuner-core.c v4l-dvb-14021dfc00f3/linux/drivers/media/video/tuner-core.c
--- v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/tuner-core.c	2010-02-12 02:11:30.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/drivers/media/video/tuner-core.c	2010-02-17 17:18:32.000000000 +0100
@@ -29,8 +29,9 @@
 #include "tuner-xc2028.h"
 #include "tuner-simple.h"
 #include "tda9887.h"
 #include "xc5000.h"
+#include "xc4000.h"
 #include "tda18271.h"
 
 #define UNSET (-1U)
 
@@ -324,8 +325,9 @@
 	}
 }
 
 static struct xc5000_config xc5000_cfg;
+static struct xc4000_config xc4000_cfg;
 
 static void set_type(struct i2c_client *c, unsigned int type,
 		     unsigned int new_mode_mask, unsigned int new_config,
 		     int (*tuner_callback) (void *dev, int component, int cmd, int arg))
@@ -437,8 +439,20 @@
 			goto attach_failed;
 		tune_now = 0;
 		break;
 	}
+	case TUNER_XC4000:
+	{
+		xc4000_cfg.card_type	  = XC4000_CARD_GENERIC;
+		xc4000_cfg.i2c_address	  = t->i2c->addr;
+		/* if_khz will be set when the digital dvb_attach() occurs */
+		xc4000_cfg.if_khz	  = 0;
+		if (!dvb_attach(xc4000_attach,
+				&t->fe, t->i2c->adapter, &xc4000_cfg))
+			goto attach_failed;
+		tune_now = 0;
+		break;
+	}
 	case TUNER_NXP_TDA18271:
 	{
 		struct tda18271_config cfg = {
 			.config = t->config,
diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/include/media/tuner.h v4l-dvb-14021dfc00f3/linux/include/media/tuner.h
--- v4l-dvb-14021dfc00f3.old/linux/include/media/tuner.h	2010-02-12 02:11:30.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/include/media/tuner.h	2010-02-17 17:18:11.000000000 +0100
@@ -128,8 +128,9 @@
 #define TUNER_PHILIPS_FQ1216LME_MK3	80	/* Active loopthrough, no FM */
 #define TUNER_PARTSNIC_PTI_5NF05	81
 #define TUNER_PHILIPS_CU1216L           82
 #define TUNER_NXP_TDA18271		83
+#define TUNER_XC4000			84	/* Xceive Silicon Tuner */
 
 /* tv card specific */
 #define TDA9887_PRESENT 		(1<<0)
 #define TDA9887_PORT1_INACTIVE 		(1<<1)

[-- Attachment #3: cx88-dtv2000h+-14021dfc00f3.patch --]
[-- Type: text/x-patch, Size: 9355 bytes --]

diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-cards.c v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-cards.c
--- v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-cards.c	2010-02-12 02:11:30.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-cards.c	2010-02-17 17:18:17.000000000 +0100
@@ -27,8 +27,9 @@
 
 #include "compat.h"
 #include "cx88.h"
 #include "tea5767.h"
+#include "xc4000.h"
 
 static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
 static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
 static unsigned int card[]  = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
@@ -2119,8 +2120,60 @@
 			.vmux   = 0,
 		} },
 		.mpeg           = CX88_MPEG_DVB,
 	},
+	[CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
+		.name           = "WinFast DTV2000 H PLUS",
+		.tuner_type     = TUNER_XC4000,
+		.radio_type     = TUNER_XC4000,
+		.tuner_addr     = 0x61,
+		.radio_addr     = 0x61,
+		/*
+		 * GPIO
+		 *   2: 1: mute audio
+		 *  12: 0: reset XC4000
+		 *  13: 1: audio input is line in (0: tuner)
+		 *  14: 0: FM radio
+		 *  16: 0: RF input is cable
+		 */
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0403,
+			.gpio1  = 0xF0D7,
+			.gpio2  = 0x0101,
+			.gpio3  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_CABLE,
+			.vmux   = 0,
+			.gpio0  = 0x0403,
+			.gpio1  = 0xF0D7,
+			.gpio2  = 0x0100,
+			.gpio3  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0403,	/* was 0x0407 */
+			.gpio1  = 0xF0F7,
+			.gpio2  = 0x0101,
+			.gpio3  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0403,	/* was 0x0407 */
+			.gpio1  = 0xF0F7,
+			.gpio2  = 0x0101,
+			.gpio3  = 0x0000,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x0403,
+			.gpio1  = 0xF097,
+			.gpio2  = 0x0100,
+			.gpio3  = 0x0000,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+	},
 };
 
 /* ------------------------------------------------------------------ */
 /* PCI subsystem IDs                                                  */
@@ -2545,8 +2598,12 @@
 		.subvendor = 0x107d,
 		.subdevice = 0x6654,
 		.card      = CX88_BOARD_WINFAST_DTV1800H,
 	}, {
+		.subvendor = 0x107d,
+		.subdevice = 0x6f42,
+		.card      = CX88_BOARD_WINFAST_DTV2000H_PLUS,
+	}, {
 		/* PVR2000 PAL Model [107d:6630] */
 		.subvendor = 0x107d,
 		.subdevice = 0x6630,
 		.card      = CX88_BOARD_LEADTEK_PVR2000,
@@ -2803,8 +2860,25 @@
 	}
 	return -EINVAL;
 }
 
+static int cx88_xc4000_winfast2000h_plus_callback(struct cx88_core *core,
+						  int command, int arg)
+{
+	switch (command) {
+	case XC4000_TUNER_RESET:
+		/* GPIO 12 (xc4000 tuner reset) */
+		cx_set(MO_GP1_IO, 0x1010);
+		mdelay(50);
+		cx_clear(MO_GP1_IO, 0x10);
+		mdelay(50);
+		cx_set(MO_GP1_IO, 0x10);
+		mdelay(50);
+		return 0;
+	}
+	return -EINVAL;
+}
+
 /* ------------------------------------------------------------------- */
 /* some Divco specific stuff                                           */
 static int cx88_pv_8000gt_callback(struct cx88_core *core,
 				   int command, int arg)
@@ -2905,8 +2979,20 @@
 	}
 	return -EINVAL;
 }
 
+static int cx88_xc4000_tuner_callback(struct cx88_core *core,
+				      int command, int arg)
+{
+	/* Board-specific callbacks */
+	switch (core->boardnr) {
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+		return cx88_xc4000_winfast2000h_plus_callback(core,
+							      command, arg);
+	}
+	return -EINVAL;
+}
+
 /* ----------------------------------------------------------------------- */
 /* Tuner callback function. Currently only needed for the Pinnacle 	   *
  * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both	   *
  * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c)    */
@@ -2979,8 +3065,11 @@
 	switch (core->board.tuner_type) {
 		case TUNER_XC2028:
 			info_printk(core, "Calling XC2028/3028 callback\n");
 			return cx88_xc2028_tuner_callback(core, command, arg);
+		case TUNER_XC4000:
+			info_printk(core, "Calling XC4000 callback\n");
+			return cx88_xc4000_tuner_callback(core, command, arg);
 		case TUNER_XC5000:
 			info_printk(core, "Calling XC5000 callback\n");
 			return cx88_xc5000_tuner_callback(core, command, arg);
 	}
@@ -3066,9 +3155,10 @@
 		break;
 
 	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
 	case CX88_BOARD_WINFAST_DTV1800H:
-		/* GPIO 12 (xc3028 tuner reset) */
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+		/* GPIO 12 (xc3028/xc4000 tuner reset) */
 		cx_set(MO_GP1_IO, 0x1010);
 		mdelay(50);
 		cx_clear(MO_GP1_IO, 0x10);
 		mdelay(50);
diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-dvb.c v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-dvb.c
--- v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-dvb.c	2010-02-12 02:11:30.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-dvb.c	2010-02-17 17:18:17.000000000 +0100
@@ -41,8 +41,9 @@
 #include "cx22702.h"
 #include "or51132.h"
 #include "lgdt330x.h"
 #include "s5h1409.h"
+#include "xc4000.h"
 #include "xc5000.h"
 #include "nxt200x.h"
 #include "cx24123.h"
 #include "isl6421.h"
@@ -573,8 +574,47 @@
 
 	return 0;
 }
 
+static int attach_xc4000(struct cx8802_dev *dev, u8 card_type)
+{
+	struct dvb_frontend *fe;
+	struct videobuf_dvb_frontend *fe0 = NULL;
+	struct xc4000_config cfg = {
+		.card_type	= card_type,
+		.i2c_address	= 0x61,	  /* these will be set by xc4000.c */
+		.if_khz		= 5400
+	};
+
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+	if (!fe0)
+		return -EINVAL;
+
+	if (!fe0->dvb.frontend) {
+		printk(KERN_ERR "%s/2: dvb frontend not attached. "
+				"Can't attach xc4000\n",
+		       dev->core->name);
+		return -EINVAL;
+	}
+
+	fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap,
+			&cfg);
+	if (!fe) {
+		printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+		       dev->core->name);
+		dvb_frontend_detach(fe0->dvb.frontend);
+		dvb_unregister_frontend(fe0->dvb.frontend);
+		fe0->dvb.frontend = NULL;
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "%s/2: xc4000 attached\n",
+	       dev->core->name);
+
+	return 0;
+}
+
 static int cx24116_set_ts_param(struct dvb_frontend *fe,
 	int is_punctured)
 {
 	struct cx8802_dev *dev = fe->dvb->priv;
@@ -1049,9 +1089,9 @@
 			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
 				fe->ops.tuner_ops.set_config(fe, &ctl);
 		}
 		break;
-	 case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+	case CX88_BOARD_PINNACLE_HYBRID_PCTV:
 	case CX88_BOARD_WINFAST_DTV1800H:
 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &cx88_pinnacle_hybrid_pctv,
 					       &core->i2c_adap);
@@ -1060,18 +1100,28 @@
 			if (attach_xc3028(0x61, dev) < 0)
 				goto frontend_detach;
 		}
 		break;
-	 case CX88_BOARD_GENIATECH_X8000_MT:
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &cx88_pinnacle_hybrid_pctv,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+			if (attach_xc4000(dev, XC4000_CARD_DTV2000H_PLUS) < 0)
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_GENIATECH_X8000_MT:
 		dev->ts_gen_cntrl = 0x00;
 
 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &cx88_geniatech_x8000_mt,
 					       &core->i2c_adap);
 		if (attach_xc3028(0x61, dev) < 0)
 			goto frontend_detach;
 		break;
-	 case CX88_BOARD_KWORLD_ATSC_120:
+	case CX88_BOARD_KWORLD_ATSC_120:
 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 					       &kworld_atsc_120_config,
 					       &core->i2c_adap);
 		if (attach_xc3028(0x61, dev) < 0)
diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88.h v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88.h
--- v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88.h	2010-02-12 02:11:30.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88.h	2010-02-17 17:18:17.000000000 +0100
@@ -239,8 +239,9 @@
 #define CX88_BOARD_HAUPPAUGE_IRONLY        80
 #define CX88_BOARD_WINFAST_DTV1800H        81
 #define CX88_BOARD_WINFAST_DTV2000H_J      82
 #define CX88_BOARD_PROF_7301               83
+#define CX88_BOARD_WINFAST_DTV2000H_PLUS   84
 
 enum cx88_itype {
 	CX88_VMUX_COMPOSITE1 = 1,
 	CX88_VMUX_COMPOSITE2,
diff -r -d -N -U4 v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-input.c v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-input.c
--- v4l-dvb-14021dfc00f3.old/linux/drivers/media/video/cx88/cx88-input.c	2010-02-12 02:11:30.000000000 +0100
+++ v4l-dvb-14021dfc00f3/linux/drivers/media/video/cx88/cx88-input.c	2010-02-17 17:18:17.000000000 +0100
@@ -92,8 +92,9 @@
 		gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
 		break;
 	case CX88_BOARD_WINFAST_DTV1000:
 	case CX88_BOARD_WINFAST_DTV1800H:
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
 	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
 		gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
 		auxgpio = gpio;
 		break;
@@ -236,8 +237,9 @@
 		break;
 	case CX88_BOARD_WINFAST_DTV2000H:
 	case CX88_BOARD_WINFAST_DTV2000H_J:
 	case CX88_BOARD_WINFAST_DTV1800H:
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
 		ir_codes = &ir_codes_winfast_table;
 		ir->gpio_addr = MO_GP0_IO;
 		ir->mask_keycode = 0x8f8;
 		ir->mask_keyup = 0x100;

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-02-17 18:06               ` [PATCH] " istvan_v
@ 2010-02-17 23:51                 ` Mauro Carvalho Chehab
  2010-02-17 23:59                   ` Devin Heitmueller
  0 siblings, 1 reply; 30+ messages in thread
From: Mauro Carvalho Chehab @ 2010-02-17 23:51 UTC (permalink / raw)
  To: istvan_v; +Cc: linux-media

Hi Istvan,

istvan_v@mailbox.hu wrote:
> The attached new patches contain all the previous changes merged, and
> are against the latest v4l-dvb revision.

Please provide your Signed-off-by. This is a basic requirement for your
driver to be accepted. Please read:
	http://linuxtv.org/hg/v4l-dvb/raw-file/tip/README.patches

for instructions on how to submit a patch.

Cheers,
Mauro.

> 
> By the way, someone on a forum reported having a DTV1800 H card with
> a PCI ID of 107d:6f38. This seems to differ from the already supported
> DTV1800 H version (107d:6654) by having an XC4000 tuner instead of
> XC3028. From the Windows INF files it seems this card is very similar
> to the DTV2000 H Plus, but there is no GPIO for selecting antenna/cable
> input.
> 
> On 02/11/2010 08:16 PM, istvan_v@mailbox.hu wrote:
> 
>> Update: the following patch, which should be applied after the previous
>> ones, makes a few additional changes to the XC4000 driver:
>>   - adds support for DTV7
>>   - implements power management
>>   - adds a mutex and locking for tuner operations
>>   - some unused or unneeded code has been removed
>>
>> On 02/09/2010 06:35 PM, istvan_v@mailbox.hu wrote:
>>
>>> There are two separate patches for v4l-dvb revision 28f5eca12bb0: the
>>> first one adds the XC4000 driver, while the second one adds support for
>>> the Leadtek WinFast DTV2000H Plus card in the CX88 driver.
>>>
>>> http://www.sharemation.com/IstvanV/v4l/xc4000-28f5eca12bb0.patch
>>> http://www.sharemation.com/IstvanV/v4l/cx88-dtv2000h+-28f5eca12bb0.patch
>>>
>>> These new firmware files are more complete than the previous ones, but
>>> are not compatible with the original driver. Both version 1.2 and 1.4
>>> are available:
>>>
>>> http://www.sharemation.com/IstvanV/v4l/xc4000-1.2.fw
>>> http://www.sharemation.com/IstvanV/v4l/xc4000-1.4.fw
>>>
>>> The following simple utility was used for creating the firmware files.
>>>
>>> http://www.sharemation.com/IstvanV/v4l/xc4000fw.c


-- 

Cheers,
Mauro

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-02-17 23:51                 ` Mauro Carvalho Chehab
@ 2010-02-17 23:59                   ` Devin Heitmueller
  2010-02-18  0:08                     ` Mauro Carvalho Chehab
  2010-02-19 19:54                     ` istvan_v
  0 siblings, 2 replies; 30+ messages in thread
From: Devin Heitmueller @ 2010-02-17 23:59 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: istvan_v, linux-media

On Wed, Feb 17, 2010 at 6:51 PM, Mauro Carvalho Chehab
<mchehab@redhat.com> wrote:
> Hi Istvan,
>
> istvan_v@mailbox.hu wrote:
>> The attached new patches contain all the previous changes merged, and
>> are against the latest v4l-dvb revision.
>
> Please provide your Signed-off-by. This is a basic requirement for your
> driver to be accepted. Please read:
>        http://linuxtv.org/hg/v4l-dvb/raw-file/tip/README.patches
>
> for instructions on how to submit a patch.

Hi Mauro,

I would hate to come across as a jerk here, but he cannot provide his
SOB for this patch, as I wrote about 95% of the code here.  It's
derived from a tree I have been working on for the PCTV 340e:

http://kernellabs.com/hg/~dheitmueller/pctv-340e-2/

I know that istvan wants to see the support merged, but he is going to
have to wait a bit longer since he is not the author or maintainer of
the driver in question.

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-02-17 23:59                   ` Devin Heitmueller
@ 2010-02-18  0:08                     ` Mauro Carvalho Chehab
  2010-02-18  0:11                       ` Devin Heitmueller
  2010-03-14 17:50                       ` istvan_v
  2010-02-19 19:54                     ` istvan_v
  1 sibling, 2 replies; 30+ messages in thread
From: Mauro Carvalho Chehab @ 2010-02-18  0:08 UTC (permalink / raw)
  To: Devin Heitmueller; +Cc: istvan_v, linux-media

Devin Heitmueller wrote:
> On Wed, Feb 17, 2010 at 6:51 PM, Mauro Carvalho Chehab
> <mchehab@redhat.com> wrote:
>> Hi Istvan,
>>
>> istvan_v@mailbox.hu wrote:
>>> The attached new patches contain all the previous changes merged, and
>>> are against the latest v4l-dvb revision.
>> Please provide your Signed-off-by. This is a basic requirement for your
>> driver to be accepted. Please read:
>>        http://linuxtv.org/hg/v4l-dvb/raw-file/tip/README.patches
>>
>> for instructions on how to submit a patch.
> 
> Hi Mauro,
> 
> I would hate to come across as a jerk here, but he cannot provide his
> SOB for this patch, as I wrote about 95% of the code here.  It's
> derived from a tree I have been working on for the PCTV 340e:
> 
> http://kernellabs.com/hg/~dheitmueller/pctv-340e-2/
> 
> I know that istvan wants to see the support merged, but he is going to
> have to wait a bit longer since he is not the author or maintainer of
> the driver in question.

OK. Then, I need your SOB for the 95% of the code, and his SOB for the
remaining ;)

-- 

Cheers,
Mauro

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-02-18  0:08                     ` Mauro Carvalho Chehab
@ 2010-02-18  0:11                       ` Devin Heitmueller
  2010-03-14 17:58                         ` istvan_v
  2010-03-14 17:50                       ` istvan_v
  1 sibling, 1 reply; 30+ messages in thread
From: Devin Heitmueller @ 2010-02-18  0:11 UTC (permalink / raw)
  To: Mauro Carvalho Chehab; +Cc: istvan_v, linux-media

On Wed, Feb 17, 2010 at 7:08 PM, Mauro Carvalho Chehab
<mchehab@redhat.com> wrote:
> OK. Then, I need your SOB for the 95% of the code, and his SOB for the
> remaining ;)

Yeah, my plan at this point was to submit a PULL request once I felt
the driver is stable (and I had already offered to apply his
incremental patches onto my tree before said pull request).

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-02-17 23:59                   ` Devin Heitmueller
  2010-02-18  0:08                     ` Mauro Carvalho Chehab
@ 2010-02-19 19:54                     ` istvan_v
  2010-03-10 23:17                       ` istvan_v
  1 sibling, 1 reply; 30+ messages in thread
From: istvan_v @ 2010-02-19 19:54 UTC (permalink / raw)
  To: linux-media

Well, it is not really a problem, if it is not merged, so this updated
version is only for those who want to test it:

http://www.sharemation.com/IstvanV/v4l/xc4000-winfast-14021dfc00f3.patch

  - in xc4000.c, power management may default to on or off depending on
    the card type
  - autodetects and (hopefully) supports cards with the following PCI
    IDs, based on Windows INF files:
      107D:6619  WinFast TV2000 XP Global (this is actually the same as
                 6618 and 6F18)
      107D:6F36  WinFast TV2000 XP Global with XC4100 (analog-only
                 XC4000 ?) tuner
      107D:6F38  WinFast DTV1800 H with XC4000 tuner
      107D:6F42  WinFast DTV2000 H Plus
      107D:6F43  WinFast TV2000 XP Global with XC4100 tuner and
                 different GPIOs
    Not all of these card versions may actually exist in practice,
    though, only 6F38 and 6F42 are confirmed so far.
  - added a new "sharpness" control to the CX88 driver

On 02/18/2010 12:59 AM, Devin Heitmueller wrote:

> I would hate to come across as a jerk here, but he cannot provide his
> SOB for this patch, as I wrote about 95% of the code here.  It's
> derived from a tree I have been working on for the PCTV 340e:

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-02-19 19:54                     ` istvan_v
@ 2010-03-10 23:17                       ` istvan_v
  0 siblings, 0 replies; 30+ messages in thread
From: istvan_v @ 2010-03-10 23:17 UTC (permalink / raw)
  To: linux-media

I have finally received some feedback on DVB-T, and it reportedly works,
although with a minor bug: it was necessary to use the "cable" connector
instead of the "antenna" one. There is an updated patch at the web page
http://www.sharemation.com/IstvanV/v4l/xc4000.html that attempts to
correct this problem. It also includes a few CX88 changes that are not
related to adding support for XC4000 based cards, and could possibly be
released as separate patches:
 - implements a "sharpness" control using the CX2388x peaking filter
   and changing the notch filter
 - in two places (cx88-core.c and cx88-video.c) code that checked for
   CX88_VMUX_TELEVISION did not also check for CX88_VMUX_CABLE; this
   was the reason why selecting the audio standard did not work for the
   cable input
 - in cx88-mpeg.c, there was code that set core->input to CX88_VMUX_DVB;
   this does not seem to make sense, since core->input is an index to an
   array (core->board.input), while the CX88_VMUX_* values are not
   intended to be used as indexes, but rather values of the 'type'
   member of struct cx88_input. But it is also not obvious if this has
   any actual effect other than what is reported as the current input
   when queried by an application. In any case, I changed the code to
   search for an input of type CX88_VMUX_DVB, or set the input to 0 if
   it is not found

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-02-18  0:08                     ` Mauro Carvalho Chehab
  2010-02-18  0:11                       ` Devin Heitmueller
@ 2010-03-14 17:50                       ` istvan_v
  1 sibling, 0 replies; 30+ messages in thread
From: istvan_v @ 2010-03-14 17:50 UTC (permalink / raw)
  Cc: linux-media

OK, so should I write a new xc4000.c/h from scratch and sign that off ?

On 02/18/2010 01:08 AM, Mauro Carvalho Chehab wrote:

> Devin Heitmueller wrote:
>> On Wed, Feb 17, 2010 at 6:51 PM, Mauro Carvalho Chehab
>> <mchehab@redhat.com> wrote:
>>> Hi Istvan,
>>>
>>> istvan_v@mailbox.hu wrote:
>>>> The attached new patches contain all the previous changes merged, and
>>>> are against the latest v4l-dvb revision.
>>> Please provide your Signed-off-by. This is a basic requirement for your
>>> driver to be accepted. Please read:
>>>        http://linuxtv.org/hg/v4l-dvb/raw-file/tip/README.patches
>>>
>>> for instructions on how to submit a patch.
>>
>> Hi Mauro,
>>
>> I would hate to come across as a jerk here, but he cannot provide his
>> SOB for this patch, as I wrote about 95% of the code here.  It's
>> derived from a tree I have been working on for the PCTV 340e:
>>
>> http://kernellabs.com/hg/~dheitmueller/pctv-340e-2/
>>
>> I know that istvan wants to see the support merged, but he is going to
>> have to wait a bit longer since he is not the author or maintainer of
>> the driver in question.
> 
> OK. Then, I need your SOB for the 95% of the code, and his SOB for the
> remaining ;)

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-02-18  0:11                       ` Devin Heitmueller
@ 2010-03-14 17:58                         ` istvan_v
  2010-03-15  4:15                           ` Devin Heitmueller
  0 siblings, 1 reply; 30+ messages in thread
From: istvan_v @ 2010-03-14 17:58 UTC (permalink / raw)
  Cc: linux-media

On 02/18/2010 01:11 AM, Devin Heitmueller wrote:

> Yeah, my plan at this point was to submit a PULL request once I felt
> the driver is stable

For those particular cards that my patch adds support for, it seems to
be stable, and I have been using it for months. Perhaps stability issues
in xc4000.c are specific to the PCTV 340e and its dib0700 I2C problems ?

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-03-14 17:58                         ` istvan_v
@ 2010-03-15  4:15                           ` Devin Heitmueller
  2010-03-16 18:24                             ` istvan_v
  2010-03-22 18:33                             ` istvan_v
  0 siblings, 2 replies; 30+ messages in thread
From: Devin Heitmueller @ 2010-03-15  4:15 UTC (permalink / raw)
  To: istvan_v; +Cc: linux-media

On Sun, Mar 14, 2010 at 1:58 PM, istvan_v@mailbox.hu
<istvan_v@mailbox.hu> wrote:
> On 02/18/2010 01:11 AM, Devin Heitmueller wrote:
>
>> Yeah, my plan at this point was to submit a PULL request once I felt
>> the driver is stable
>
> For those particular cards that my patch adds support for, it seems to
> be stable, and I have been using it for months. Perhaps stability issues
> in xc4000.c are specific to the PCTV 340e and its dib0700 I2C problems ?

Different people have different standards of quality.  For example,
I've done essentially no analysis into the tuning performance of the
current driver - validating different frequency ranges and modulation
types or bandwidths.  I've done no testing of tuning lock time,
minimal application validation, and no effort toward making sure the
power management works.

Sure, I can just throw the driver upstream as-is, but I've been
hesitant to merge something with questionable quality, as it reflects
poorly on my reputation.  Right now it's in a development tree because
it's what I would consider "alpha quality", where only advanced users
will install it and they know to "proceed at your own risk".

And none of the above is related to the problem with the dib0700 i2c master.

All that said, the situation hasn't been helped by the fact that I'm
working on five different projects currently (as102, drx-d, xc4000,
em28xx, and now ngene), nor the fact that I'm also the maintainer for
a variety of other tuner products (and the significant support burden
that creates).

Bear in mind that I am aware of the frustration that when someone has
patches and cannot get the maintainer to find the time to
review/comment/merge.  I've been in that situation myself more than
once.

I'll try to go through my tree and see if I can get something upstream
this week which you could build on.  Once that is done, you will need
to break up your huge patch into a series of small incremental patches
(with proper descriptions for the changes), since there is no way a
single patch is going to be accepted upstream which has all of your
changes.

Also, you should *not* be submitting board profiles that are
completely unvalidated.  I saw your email on Feb 19th, where you
dumped out a list of tuners that you think might *possibly* work.  You
should only submit board definitions for devices that either you have
tested or you have gotten a user to test.  It is far worse to have
broken code in there (creating the illusion of a product being
supported), then for there to be no support at all.  When users
complain about a particular board not working, you can work with them
to get it supported.

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-03-15  4:15                           ` Devin Heitmueller
@ 2010-03-16 18:24                             ` istvan_v
  2010-03-22 18:33                             ` istvan_v
  1 sibling, 0 replies; 30+ messages in thread
From: istvan_v @ 2010-03-16 18:24 UTC (permalink / raw)
  Cc: linux-media

On 03/15/2010 05:15 AM, Devin Heitmueller wrote:

> I've done essentially no analysis into the tuning performance of the
> current driver - validating different frequency ranges and modulation
> types or bandwidths.  I've done no testing of tuning lock time,
> minimal application validation

Well, so far it definitely seems usable and not apparently worse
than on Windows. If more developers can test and review it, then it
is more likely that any issues can be found and fixed or improved.

> and no effort toward making sure the power management works.

I did implement power management (by writing to register 8, and
setting a flag that forces resetting the tuner and reloading all
firmware data on the next use), although it is disabled by default
for the cards that I added support for (it is apparently not used
on Windows, either).

> I'll try to go through my tree and see if I can get something upstream
> this week which you could build on.

I think adding xc4000.c/h and the few changes shown at the end of this
post to incorporate XC4000 as a tuner type should be enough. Did you
review the changes I made to the XC4000 driver ? Is there something
that is unneeded or should be done differently ? Do you have a fixed
firmware file, or are the ones I created usable ?

> Once that is done, you will need to break up your huge patch into a series
> of small incremental patches (with proper descriptions for the changes),
> since there is no way a single patch is going to be accepted upstream
> which has all of your changes.

OK. Should I also create patches for any of the unrelated cx88
fixes/changes ?

> Also, you should *not* be submitting board profiles that are
> completely unvalidated.  I saw your email on Feb 19th, where you
> dumped out a list of tuners that you think might *possibly* work.  You
> should only submit board definitions for devices that either you have
> tested or you have gotten a user to test.  It is far worse to have
> broken code in there (creating the illusion of a product being
> supported), then for there to be no support at all.  When users
> complain about a particular board not working, you can work with them
> to get it supported.

Of the additional boards, 107d:6f38 (WinFast DTV1800 H with XC4000 tuner
instead of XC3028) has been reported by one user to work in analog mode,
while DVB was untested. Is that enough to keep the board profile ?
I have 107d:6f42 (DTV2000 H Plus), and tested it extensively in analog
and FM radio mode; another user tested DVB-T, and reported it to work
well (I have got no information about details like bandwidth used,
though). As far as I know, the only difference between the above two
cards that is relevant to drivers is that the latter has an additional
GPIO for selecting the antenna/cable RF input.
I have no problems with removing the various TV2000 XP Global revisions
from the patches, as I do not even know if anyone actually has one of
those cards.

------------------------------------------------------------------------

diff -r -d -N -U4
v4l-dvb-7a58d924fb04.old/linux/drivers/media/common/tuners/Kconfig
v4l-dvb-7a58d924fb04/linux/drivers/media/common/tuners/Kconfig
--- v4l-dvb-7a58d924fb04.old/linux/drivers/media/common/tuners/Kconfig
2010-03-10 03:00:59.000000000 +0100
+++ v4l-dvb-7a58d924fb04/linux/drivers/media/common/tuners/Kconfig
2010-03-10 17:12:02.000000000 +0100
@@ -22,8 +22,9 @@
 	default VIDEO_MEDIA && I2C
 	depends on VIDEO_MEDIA && I2C
 	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE
@@ -150,8 +151,17 @@
 	  A driver for the silicon tuner XC5000 from Xceive.
 	  This device is only used inside a SiP called together with a
 	  demodulator for now.

+config MEDIA_TUNER_XC4000
+	tristate "Xceive XC4000 silicon tuner"
+	depends on VIDEO_MEDIA && I2C
+	default m if MEDIA_TUNER_CUSTOMISE
+	help
+	  A driver for the silicon tuner XC4000 from Xceive.
+	  This device is only used inside a SiP called together with a
+	  demodulator for now.
+
 config MEDIA_TUNER_MXL5005S
 	tristate "MaxLinear MSL5005S silicon tuner"
 	depends on VIDEO_MEDIA && I2C
 	default m if MEDIA_TUNER_CUSTOMISE
diff -r -d -N -U4
v4l-dvb-7a58d924fb04.old/linux/drivers/media/common/tuners/Makefile
v4l-dvb-7a58d924fb04/linux/drivers/media/common/tuners/Makefile
--- v4l-dvb-7a58d924fb04.old/linux/drivers/media/common/tuners/Makefile
2010-03-10 03:00:59.000000000 +0100
+++ v4l-dvb-7a58d924fb04/linux/drivers/media/common/tuners/Makefile
2010-03-10 17:12:02.000000000 +0100
@@ -15,8 +15,9 @@
 obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o
 obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
 obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
 obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
+obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
 obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
 obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
 obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
 obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
diff -r -d -N -U4
v4l-dvb-7a58d924fb04.old/linux/drivers/media/common/tuners/tuner-types.c
v4l-dvb-7a58d924fb04/linux/drivers/media/common/tuners/tuner-types.c
---
v4l-dvb-7a58d924fb04.old/linux/drivers/media/common/tuners/tuner-types.c	2010-03-10
03:00:59.000000000 +0100
+++
v4l-dvb-7a58d924fb04/linux/drivers/media/common/tuners/tuner-types.c
2010-03-10 17:12:02.000000000 +0100
@@ -1778,8 +1778,12 @@
 	[TUNER_XC5000] = { /* Xceive 5000 */
 		.name   = "Xceive 5000 tuner",
 		/* see xc5000.c for details */
 	},
+	[TUNER_XC4000] = { /* Xceive 4000 */
+		.name   = "Xceive 4000 tuner",
+		/* see xc4000.c for details */
+	},
 	[TUNER_TCL_MF02GIP_5N] = { /* TCL tuner MF02GIP-5N-E */
 		.name   = "TCL tuner MF02GIP-5N-E",
 		.params = tuner_tcl_mf02gip_5n_params,
 		.count  = ARRAY_SIZE(tuner_tcl_mf02gip_5n_params),
diff -r -d -N -U4
v4l-dvb-7a58d924fb04.old/linux/drivers/media/video/tuner-core.c
v4l-dvb-7a58d924fb04/linux/drivers/media/video/tuner-core.c
--- v4l-dvb-7a58d924fb04.old/linux/drivers/media/video/tuner-core.c
2010-03-10 03:00:59.000000000 +0100
+++ v4l-dvb-7a58d924fb04/linux/drivers/media/video/tuner-core.c
2010-03-10 17:12:02.000000000 +0100
@@ -29,8 +29,9 @@
 #include "tuner-xc2028.h"
 #include "tuner-simple.h"
 #include "tda9887.h"
 #include "xc5000.h"
+#include "xc4000.h"
 #include "tda18271.h"

 #define UNSET (-1U)

@@ -324,8 +325,9 @@
 	}
 }

 static struct xc5000_config xc5000_cfg;
+static struct xc4000_config xc4000_cfg;

 static void set_type(struct i2c_client *c, unsigned int type,
 		     unsigned int new_mode_mask, unsigned int new_config,
 		     int (*tuner_callback) (void *dev, int component, int cmd, int arg))
@@ -437,8 +439,21 @@
 			goto attach_failed;
 		tune_now = 0;
 		break;
 	}
+	case TUNER_XC4000:
+	{
+		/* card_type and if_khz will be set when the digital
+		   dvb_attach() occurs */
+		xc4000_cfg.card_type	  = XC4000_CARD_WINFAST_CX88;
+		xc4000_cfg.i2c_address	  = t->i2c->addr;
+		xc4000_cfg.if_khz	  = 0;
+		if (!dvb_attach(xc4000_attach,
+				&t->fe, t->i2c->adapter, &xc4000_cfg))
+			goto attach_failed;
+		tune_now = 0;
+		break;
+	}
 	case TUNER_NXP_TDA18271:
 	{
 		struct tda18271_config cfg = {
 			.config = t->config,
diff -r -d -N -U4 v4l-dvb-7a58d924fb04.old/linux/include/media/tuner.h
v4l-dvb-7a58d924fb04/linux/include/media/tuner.h
--- v4l-dvb-7a58d924fb04.old/linux/include/media/tuner.h	2010-03-10
03:00:59.000000000 +0100
+++ v4l-dvb-7a58d924fb04/linux/include/media/tuner.h	2010-03-10
17:12:02.000000000 +0100
@@ -129,8 +129,9 @@
 #define TUNER_PARTSNIC_PTI_5NF05	81
 #define TUNER_PHILIPS_CU1216L           82
 #define TUNER_NXP_TDA18271		83
 #define TUNER_SONY_BTF_PXN01Z		84
+#define TUNER_XC4000			85	/* Xceive Silicon Tuner */

 /* tv card specific */
 #define TDA9887_PRESENT 		(1<<0)
 #define TDA9887_PORT1_INACTIVE 		(1<<1)

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-03-15  4:15                           ` Devin Heitmueller
  2010-03-16 18:24                             ` istvan_v
@ 2010-03-22 18:33                             ` istvan_v
  2010-03-24 11:38                               ` istvan_v
  1 sibling, 1 reply; 30+ messages in thread
From: istvan_v @ 2010-03-22 18:33 UTC (permalink / raw)
  Cc: linux-media

On 03/15/2010 05:15 AM, Devin Heitmueller wrote:

> I'll try to go through my tree and see if I can get something upstream
> this week which you could build on.

Are there any news on this ?

By the way, I have just received this mail from Mirek Slugen, with a
patch for PxDVR3200 with XC4000 tuner. Should that patch also be
submitted ?

On 03/22/2010 04:40 PM, Mirek Slugeň wrote:

> First I would like to thank you for your work on XC4000 Leadtek
> tuners, analog TV, analog FM and DVB-T works great.
>
> I created patch for new revision of Leadtek DVR3200 (xc4000) based on
> your patch and it works also (patch is included).
>
> After long testing I found only one small bug, signal strength is not
> working on DVB-T XC4000 based tuners, so i will try to fix it.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH] DTV2000 H Plus issues
  2010-03-22 18:33                             ` istvan_v
@ 2010-03-24 11:38                               ` istvan_v
  0 siblings, 0 replies; 30+ messages in thread
From: istvan_v @ 2010-03-24 11:38 UTC (permalink / raw)
  To: linux-media

An updated patch that includes the PxDVR3200 H (107d:6f39) support is
now available at http://istvanv.users.sourceforge.net/v4l/xc4000.html.

On 03/22/2010 07:33 PM, istvan_v@mailbox.hu wrote:
> On 03/15/2010 05:15 AM, Devin Heitmueller wrote:
> 
>> I'll try to go through my tree and see if I can get something upstream
>> this week which you could build on.
> 
> Are there any news on this ?
> 
> By the way, I have just received this mail from Mirek Slugen, with a
> patch for PxDVR3200 with XC4000 tuner. Should that patch also be
> submitted ?
> 
> On 03/22/2010 04:40 PM, Mirek Slugeň wrote:
> 
>> First I would like to thank you for your work on XC4000 Leadtek
>> tuners, analog TV, analog FM and DVB-T works great.
>>
>> I created patch for new revision of Leadtek DVR3200 (xc4000) based on
>> your patch and it works also (patch is included).
>>
>> After long testing I found only one small bug, signal strength is not
>> working on DVB-T XC4000 based tuners, so i will try to fix it.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* DTV2000 H Plus issues
@ 2010-01-02 16:23 Raena Lea-Shannon
  0 siblings, 0 replies; 30+ messages in thread
From: Raena Lea-Shannon @ 2010-01-02 16:23 UTC (permalink / raw)
  To: linux-media

PS:

I have tried modprobe and insmode card=51 and card=82 and card=0 with no 
luck.



^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2010-03-24 11:32 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-01-02 16:10 DTV2000 H Plus issues Raena Lea-Shannon
2010-01-02 16:57 ` istvan_v
2010-01-03  8:21   ` Raena Lea-Shannon
2010-01-03 11:31     ` Samuel Rakitnican
2010-01-04 13:01       ` Raena Lea-Shannon
2010-01-04 16:48     ` istvan_v
2010-01-05  1:25       ` Raena Lea-Shannon
2010-01-07 19:49         ` istvan_v
2010-01-07 20:00           ` Devin Heitmueller
2010-01-07 21:07             ` istvan_v
2010-02-09 17:35           ` istvan_v
2010-02-11 19:16             ` istvan_v
2010-02-11 19:21               ` Devin Heitmueller
2010-02-11 19:35                 ` istvan_v
2010-02-12 18:26               ` istvan_v
2010-02-12 18:34                 ` istvan_v
2010-02-17 18:06               ` [PATCH] " istvan_v
2010-02-17 23:51                 ` Mauro Carvalho Chehab
2010-02-17 23:59                   ` Devin Heitmueller
2010-02-18  0:08                     ` Mauro Carvalho Chehab
2010-02-18  0:11                       ` Devin Heitmueller
2010-03-14 17:58                         ` istvan_v
2010-03-15  4:15                           ` Devin Heitmueller
2010-03-16 18:24                             ` istvan_v
2010-03-22 18:33                             ` istvan_v
2010-03-24 11:38                               ` istvan_v
2010-03-14 17:50                       ` istvan_v
2010-02-19 19:54                     ` istvan_v
2010-03-10 23:17                       ` istvan_v
2010-01-02 16:23 Raena Lea-Shannon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.