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

* git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (509 commits)
  V4L/DVB (7078): radio: fix sf16fmi section mismatch
  V4L/DVB (7077): bt878: remove handcrafted PCI subsystem ID check
  V4L/DVB (7075): Make a local function static
  V4L/DVB (7074): DiB7000P: correct tuning problem for 7MHz channel
  V4L/DVB (7073): DiB7070: Reception quality improved
  V4L/DVB (7072): sets the MT2060 IF1 frequency according to EEPROM
  V4L/DVB (7071): DiB0700: Start streaming the right way
  V4L/DVB (7070): Fix some tuning problems
  V4L/DVB (7069):  Support for myTV.t
  V4L/DVB (7068): Add support for WinTV Nova-T-CE driver
  V4L/DVB (7067): fix autoserach in the Hauppauge NOVA-T 500
  V4L/DVB (7066):  ASUS My Cinema U3000 Mini DVBT Tuner
  V4L/DVB (7065): Artec T14BR patches
  V4L/DVB (7063): xc5000: Fix OOPS caused by missing firmware
  V4L/DVB (7062): radio-si570x: Some fixes and new USB ID addition
  V4L/DVB (7061): radio-si470x: Some cleanups
  V4L/DVB (7060): em28xx: remove has_tuner
  V4L/DVB (7059): cx88: Ensure the tuner is reset correctly
  V4L/DVB (7058): IR corrections for the Pinnacle 800i
  V4L/DVB (7056): tuner: suppress obsolete tuner i2c address warning for XC5000 tuners
  ...
This commit is contained in:
Linus Torvalds 2008-01-25 13:59:51 -08:00
commit b31fde6db2
269 changed files with 29994 additions and 12100 deletions

View File

@ -96,7 +96,6 @@ static struct video_device my_radio
{
"My radio",
VID_TYPE_TUNER,
VID_HARDWARE_MYRADIO,
radio_open.
radio_close,
NULL, /* no read */
@ -118,13 +117,6 @@ static struct video_device my_radio
indicates that the device can be tuned. Clearly our radio is going to have some
way to change channel so it is tuneable.
</para>
<para>
The VID_HARDWARE_ types are unique to each device. Numbers are assigned by
<email>alan@redhat.com</email> when device drivers are going to be released. Until then you
can pull a suitably large number out of your hat and use it. 10000 should be
safe for a very long time even allowing for the huge number of vendors
making new and different radio cards at the moment.
</para>
<para>
We declare an open and close routine, but we do not need read or write,
which are used to read and write video data to or from the card itself. As
@ -844,7 +836,6 @@ static struct video_device my_camera
"My Camera",
VID_TYPE_OVERLAY|VID_TYPE_SCALES|\
VID_TYPE_CAPTURE|VID_TYPE_CHROMAKEY,
VID_HARDWARE_MYCAMERA,
camera_open.
camera_close,
camera_read, /* no read */

View File

@ -78,6 +78,18 @@ Example:
For a full list of card ID's please see Documentation/video4linux/CARDLIST.bttv.
In case of further problems please subscribe and send questions to the mailing list: linux-dvb@linuxtv.org.
2c) Probing the cards with broken PCI subsystem ID
--------------------------------------------------
There are some TwinHan cards that the EEPROM has become corrupted for some
reason. The cards do not have correct PCI subsystem ID. But we can force
probing the cards with broken PCI subsystem ID
$ echo 109e 0878 $subvendor $subdevice > \
/sys/bus/pci/drivers/bt878/new_id
109e: PCI_VENDOR_ID_BROOKTREE
0878: PCI_DEVICE_ID_BROOKTREE_878
Authors: Richard Walker,
Jamie Honan,
Michael Hunold,

View File

@ -1,5 +1,7 @@
0 -> UNKNOWN/GENERIC [0070:3400]
1 -> Hauppauge WinTV-HVR1800lp [0070:7600]
2 -> Hauppauge WinTV-HVR1800 [0070:7800,0070:7801]
2 -> Hauppauge WinTV-HVR1800 [0070:7800,0070:7801,0070:7809]
3 -> Hauppauge WinTV-HVR1250 [0070:7911]
4 -> DViCO FusionHDTV5 Express [18ac:d500]
5 -> Hauppauge WinTV-HVR1500Q [0070:7790,0070:7797]
6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717]

View File

@ -56,3 +56,4 @@
55 -> Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM [c180:c980]
56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder [0070:9600,0070:9601,0070:9602]
57 -> ADS Tech Instant Video PCI [1421:0390]
58 -> Pinnacle PCTV HD 800i [11bd:0051]

View File

@ -1,14 +1,17 @@
0 -> Unknown EM2800 video grabber (em2800) [eb1a:2800]
1 -> Unknown EM2820/2840 video grabber (em2820/em2840)
1 -> Unknown EM2750/28xx video grabber (em2820/em2840) [eb1a:2750,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
2 -> Terratec Cinergy 250 USB (em2820/em2840) [0ccd:0036]
3 -> Pinnacle PCTV USB 2 (em2820/em2840) [2304:0208]
4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200]
5 -> MSI VOX USB 2.0 (em2820/em2840) [eb1a:2820]
4 -> Hauppauge WinTV USB 2 (em2820/em2840) [2040:4200,2040:4201]
5 -> MSI VOX USB 2.0 (em2820/em2840)
6 -> Terratec Cinergy 200 USB (em2800)
7 -> Leadtek Winfast USB II (em2800)
8 -> Kworld USB2800 (em2800)
9 -> Pinnacle Dazzle DVC 90 (em2820/em2840) [2304:0207]
10 -> Hauppauge WinTV HVR 900 (em2880)
11 -> Terratec Hybrid XS (em2880)
9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a]
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
13 -> Terratec Prodigy XS (em2880)
13 -> Terratec Prodigy XS (em2880) [0ccd:0047]
14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
15 -> V-Gear PocketTV (em2800)
16 -> Hauppauge WinTV HVR 950 (em2880) [2040:6513]

View File

@ -16,3 +16,9 @@
16 -> GOTVIEW PCI DVD2 Deluxe [ffac:0600]
17 -> Yuan MPC622 [ff01:d998]
18 -> Digital Cowboy DCT-MTVP1 [1461:bfff]
19 -> Yuan PG600V2/GotView PCI DVD Lite [ffab:0600,ffad:0600]
20 -> Club3D ZAP-TV1x01 [ffab:0600]
21 -> AverTV MCE 116 Plus [1461:c439]
22 -> ASUS Falcon2 [1043:4b66,1043:462e,1043:4b2e]
23 -> AverMedia PVR-150 Plus [1461:c035]
24 -> AverMedia EZMaker PCI Deluxe [1461:c03f]

View File

@ -80,7 +80,7 @@
79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)
80 -> ASUS Digimatrix TV [1043:0210]
81 -> Philips Tiger reference design [1131:2018]
82 -> MSI TV@Anywhere plus [1462:6231]
82 -> MSI TV@Anywhere plus [1462:6231,1462:8624]
83 -> Terratec Cinergy 250 PCI TV [153b:1160]
84 -> LifeView FlyDVB Trio [5168:0319]
85 -> AverTV DVB-T 777 [1461:2c05,1461:2c05]
@ -102,7 +102,7 @@
101 -> Pinnacle PCTV 310i [11bd:002f]
102 -> Avermedia AVerTV Studio 507 [1461:9715]
103 -> Compro Videomate DVB-T200A
104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid [0070:6701]
104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid [0070:6700,0070:6701,0070:6702,0070:6703,0070:6704,0070:6705]
105 -> Terratec Cinergy HT PCMCIA [153b:1172]
106 -> Encore ENLTV [1131:2342,1131:2341,3016:2344]
107 -> Encore ENLTV-FM [1131:230f]
@ -116,3 +116,16 @@
115 -> Sabrent PCMCIA TV-PCB05 [0919:2003]
116 -> 10MOONS TM300 TV Card [1131:2304]
117 -> Avermedia Super 007 [1461:f01d]
118 -> Beholder BeholdTV 401 [0000:4016]
119 -> Beholder BeholdTV 403 [0000:4036]
120 -> Beholder BeholdTV 403 FM [0000:4037]
121 -> Beholder BeholdTV 405 [0000:4050]
122 -> Beholder BeholdTV 405 FM [0000:4051]
123 -> Beholder BeholdTV 407 [0000:4070]
124 -> Beholder BeholdTV 407 FM [0000:4071]
125 -> Beholder BeholdTV 409 [0000:4090]
126 -> Beholder BeholdTV 505 FM/RDS [0000:5051,0000:505B,5ace:5050]
127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090]
128 -> Beholder BeholdTV Columbus TVFM [0000:5201]
129 -> Beholder BeholdTV 607 / BeholdTV 609 [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093]
130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193]

View File

@ -52,7 +52,7 @@ tuner=50 - TCL 2002N
tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3)
tuner=52 - Thomson DTT 7610 (ATSC/NTSC)
tuner=53 - Philips FQ1286
tuner=54 - tda8290+75
tuner=54 - Philips/NXP TDA 8290/8295 + 8275/8275A/18271
tuner=55 - TCL 2002MB
tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4)
tuner=57 - Philips FQ1236A MK4
@ -69,7 +69,8 @@ tuner=67 - Philips TD1316 Hybrid Tuner
tuner=68 - Philips TUV1236D ATSC/NTSC dual in
tuner=69 - Tena TNF 5335 and similar models
tuner=70 - Samsung TCPN 2121P30A
tuner=71 - Xceive xc3028
tuner=71 - Xceive xc2028/xc3028 tuner
tuner=72 - Thomson FE6600
tuner=73 - Samsung TCPG 6121P30A
tuner=75 - Philips TEA5761 FM Radio
tuner=76 - Xceive 5000 tuner

View File

@ -62,3 +62,4 @@
61 -> Pinnacle Studio Linx Video input cable (PAL) [2304:0301]
62 -> Pinnacle PCTV Bungee USB (PAL) FM [2304:0419]
63 -> Hauppauge WinTv-USB [2400:4200]
64 -> Pinnacle Studio PCTV USB (NTSC) FM V3 [2304:0113]

View File

@ -0,0 +1,926 @@
#!/usr/bin/perl
# Copyright (c) Mauro Carvalho Chehab <mchehab@infradead.org>
# Released under GPLv2
#
# In order to use, you need to:
# 1) Download the windows driver with something like:
# wget http://www.steventoth.net/linux/xc5000/HVR-12x0-14x0-17x0_1_25_25271_WHQL.zip
# 2) Extract the file hcw85bda.sys from the zip into the current dir:
# unzip -j HVR-12x0-14x0-17x0_1_25_25271_WHQL.zip Driver85/hcw85bda.sys
# 3) run the script:
# ./extract_xc3028.pl
# 4) copy the generated file:
# cp xc3028-v27.fw /lib/firmware
#use strict;
use IO::Handle;
my $debug=0;
sub verify ($$)
{
my ($filename, $hash) = @_;
my ($testhash);
if (system("which md5sum > /dev/null 2>&1")) {
die "This firmware requires the md5sum command - see http://www.gnu.org/software/coreutils/\n";
}
open(CMD, "md5sum ".$filename."|");
$testhash = <CMD>;
$testhash =~ /([a-zA-Z0-9]*)/;
$testhash = $1;
close CMD;
die "Hash of extracted file does not match (found $testhash, expected $hash!\n" if ($testhash ne $hash);
}
sub get_hunk ($$)
{
my ($offset, $length) = @_;
my ($chunklength, $buf, $rcount, $out);
sysseek(INFILE, $offset, SEEK_SET);
while ($length > 0) {
# Calc chunk size
$chunklength = 2048;
$chunklength = $length if ($chunklength > $length);
$rcount = sysread(INFILE, $buf, $chunklength);
die "Ran out of data\n" if ($rcount != $chunklength);
$out .= $buf;
$length -= $rcount;
}
return $out;
}
sub write_le16($)
{
my $val = shift;
my $msb = ($val >> 8) &0xff;
my $lsb = $val & 0xff;
syswrite(OUTFILE, chr($lsb).chr($msb));
}
sub write_le32($)
{
my $val = shift;
my $l3 = ($val >> 24) & 0xff;
my $l2 = ($val >> 16) & 0xff;
my $l1 = ($val >> 8) & 0xff;
my $l0 = $val & 0xff;
syswrite(OUTFILE, chr($l0).chr($l1).chr($l2).chr($l3));
}
sub write_le64($$)
{
my $msb_val = shift;
my $lsb_val = shift;
my $l7 = ($msb_val >> 24) & 0xff;
my $l6 = ($msb_val >> 16) & 0xff;
my $l5 = ($msb_val >> 8) & 0xff;
my $l4 = $msb_val & 0xff;
my $l3 = ($lsb_val >> 24) & 0xff;
my $l2 = ($lsb_val >> 16) & 0xff;
my $l1 = ($lsb_val >> 8) & 0xff;
my $l0 = $lsb_val & 0xff;
syswrite(OUTFILE,
chr($l0).chr($l1).chr($l2).chr($l3).
chr($l4).chr($l5).chr($l6).chr($l7));
}
sub write_hunk($$)
{
my ($offset, $length) = @_;
my $out = get_hunk($offset, $length);
printf "(len %d) ",$length if ($debug);
for (my $i=0;$i<$length;$i++) {
printf "%02x ",ord(substr($out,$i,1)) if ($debug);
}
printf "\n" if ($debug);
syswrite(OUTFILE, $out);
}
sub write_hunk_fix_endian($$)
{
my ($offset, $length) = @_;
my $out = get_hunk($offset, $length);
printf "(len_fix %d) ",$length if ($debug);
for (my $i=0;$i<$length;$i++) {
printf "%02x ",ord(substr($out,$i,1)) if ($debug);
}
printf "\n" if ($debug);
my $i=0;
while ($i<$length) {
my $size = ord(substr($out,$i,1))*256+ord(substr($out,$i+1,1));
syswrite(OUTFILE, substr($out,$i+1,1));
syswrite(OUTFILE, substr($out,$i,1));
$i+=2;
if ($size>0 && $size <0x8000) {
for (my $j=0;$j<$size;$j++) {
syswrite(OUTFILE, substr($out,$j+$i,1));
}
$i+=$size;
}
}
}
sub main_firmware($$$$)
{
my $out;
my $j=0;
my $outfile = shift;
my $name = shift;
my $version = shift;
my $nr_desc = shift;
for ($j = length($name); $j <32; $j++) {
$name = $name.chr(0);
}
open OUTFILE, ">$outfile";
syswrite(OUTFILE, $name);
write_le16($version);
write_le16($nr_desc);
#
# Firmware 0, type: BASE FW F8MHZ (0x00000003), id: (0000000000000000), size: 8718
#
write_le32(0x00000003); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(8718); # Size
write_hunk_fix_endian(813432, 8718);
#
# Firmware 1, type: BASE FW F8MHZ MTS (0x00000007), id: (0000000000000000), size: 8712
#
write_le32(0x00000007); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(8712); # Size
write_hunk_fix_endian(822152, 8712);
#
# Firmware 2, type: BASE FW FM (0x00000401), id: (0000000000000000), size: 8562
#
write_le32(0x00000401); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(8562); # Size
write_hunk_fix_endian(830872, 8562);
#
# Firmware 3, type: BASE FW FM INPUT1 (0x00000c01), id: (0000000000000000), size: 8576
#
write_le32(0x00000c01); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(8576); # Size
write_hunk_fix_endian(839440, 8576);
#
# Firmware 4, type: BASE FW (0x00000001), id: (0000000000000000), size: 8706
#
write_le32(0x00000001); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(8706); # Size
write_hunk_fix_endian(848024, 8706);
#
# Firmware 5, type: BASE FW MTS (0x00000005), id: (0000000000000000), size: 8682
#
write_le32(0x00000005); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(8682); # Size
write_hunk_fix_endian(856736, 8682);
#
# Firmware 6, type: STD FW (0x00000000), id: PAL/BG A2/A (0000000100000007), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000001, 0x00000007); # ID
write_le32(161); # Size
write_hunk_fix_endian(865424, 161);
#
# Firmware 7, type: STD FW MTS (0x00000004), id: PAL/BG A2/A (0000000100000007), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x00000001, 0x00000007); # ID
write_le32(169); # Size
write_hunk_fix_endian(865592, 169);
#
# Firmware 8, type: STD FW (0x00000000), id: PAL/BG A2/B (0000000200000007), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000002, 0x00000007); # ID
write_le32(161); # Size
write_hunk_fix_endian(865424, 161);
#
# Firmware 9, type: STD FW MTS (0x00000004), id: PAL/BG A2/B (0000000200000007), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x00000002, 0x00000007); # ID
write_le32(169); # Size
write_hunk_fix_endian(865592, 169);
#
# Firmware 10, type: STD FW (0x00000000), id: PAL/BG NICAM/A (0000000400000007), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000004, 0x00000007); # ID
write_le32(161); # Size
write_hunk_fix_endian(866112, 161);
#
# Firmware 11, type: STD FW MTS (0x00000004), id: PAL/BG NICAM/A (0000000400000007), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x00000004, 0x00000007); # ID
write_le32(169); # Size
write_hunk_fix_endian(866280, 169);
#
# Firmware 12, type: STD FW (0x00000000), id: PAL/BG NICAM/B (0000000800000007), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000008, 0x00000007); # ID
write_le32(161); # Size
write_hunk_fix_endian(866112, 161);
#
# Firmware 13, type: STD FW MTS (0x00000004), id: PAL/BG NICAM/B (0000000800000007), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x00000008, 0x00000007); # ID
write_le32(169); # Size
write_hunk_fix_endian(866280, 169);
#
# Firmware 14, type: STD FW (0x00000000), id: PAL/DK A2 (00000003000000e0), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000003, 0x000000e0); # ID
write_le32(161); # Size
write_hunk_fix_endian(866800, 161);
#
# Firmware 15, type: STD FW MTS (0x00000004), id: PAL/DK A2 (00000003000000e0), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x00000003, 0x000000e0); # ID
write_le32(169); # Size
write_hunk_fix_endian(866968, 169);
#
# Firmware 16, type: STD FW (0x00000000), id: PAL/DK NICAM (0000000c000000e0), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x0000000c, 0x000000e0); # ID
write_le32(161); # Size
write_hunk_fix_endian(867144, 161);
#
# Firmware 17, type: STD FW MTS (0x00000004), id: PAL/DK NICAM (0000000c000000e0), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x0000000c, 0x000000e0); # ID
write_le32(169); # Size
write_hunk_fix_endian(867312, 169);
#
# Firmware 18, type: STD FW (0x00000000), id: SECAM/K1 (0000000000200000), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000000, 0x00200000); # ID
write_le32(161); # Size
write_hunk_fix_endian(867488, 161);
#
# Firmware 19, type: STD FW MTS (0x00000004), id: SECAM/K1 (0000000000200000), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x00000000, 0x00200000); # ID
write_le32(169); # Size
write_hunk_fix_endian(867656, 169);
#
# Firmware 20, type: STD FW (0x00000000), id: SECAM/K3 (0000000004000000), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000000, 0x04000000); # ID
write_le32(161); # Size
write_hunk_fix_endian(867832, 161);
#
# Firmware 21, type: STD FW MTS (0x00000004), id: SECAM/K3 (0000000004000000), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x00000000, 0x04000000); # ID
write_le32(169); # Size
write_hunk_fix_endian(868000, 169);
#
# Firmware 22, type: STD FW D2633 DTV6 ATSC (0x00010030), id: (0000000000000000), size: 149
#
write_le32(0x00010030); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(149); # Size
write_hunk_fix_endian(868176, 149);
#
# Firmware 23, type: STD FW D2620 DTV6 QAM (0x00000068), id: (0000000000000000), size: 149
#
write_le32(0x00000068); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(149); # Size
write_hunk_fix_endian(868336, 149);
#
# Firmware 24, type: STD FW D2633 DTV6 QAM (0x00000070), id: (0000000000000000), size: 149
#
write_le32(0x00000070); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(149); # Size
write_hunk_fix_endian(868488, 149);
#
# Firmware 25, type: STD FW D2620 DTV7 (0x00000088), id: (0000000000000000), size: 149
#
write_le32(0x00000088); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(149); # Size
write_hunk_fix_endian(868648, 149);
#
# Firmware 26, type: STD FW D2633 DTV7 (0x00000090), id: (0000000000000000), size: 149
#
write_le32(0x00000090); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(149); # Size
write_hunk_fix_endian(868800, 149);
#
# Firmware 27, type: STD FW D2620 DTV78 (0x00000108), id: (0000000000000000), size: 149
#
write_le32(0x00000108); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(149); # Size
write_hunk_fix_endian(868960, 149);
#
# Firmware 28, type: STD FW D2633 DTV78 (0x00000110), id: (0000000000000000), size: 149
#
write_le32(0x00000110); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(149); # Size
write_hunk_fix_endian(869112, 149);
#
# Firmware 29, type: STD FW D2620 DTV8 (0x00000208), id: (0000000000000000), size: 149
#
write_le32(0x00000208); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(149); # Size
write_hunk_fix_endian(868648, 149);
#
# Firmware 30, type: STD FW D2633 DTV8 (0x00000210), id: (0000000000000000), size: 149
#
write_le32(0x00000210); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(149); # Size
write_hunk_fix_endian(868800, 149);
#
# Firmware 31, type: STD FW FM (0x00000400), id: (0000000000000000), size: 135
#
write_le32(0x00000400); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le32(135); # Size
write_hunk_fix_endian(869584, 135);
#
# Firmware 32, type: STD FW (0x00000000), id: PAL/I (0000000000000010), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000000, 0x00000010); # ID
write_le32(161); # Size
write_hunk_fix_endian(869728, 161);
#
# Firmware 33, type: STD FW MTS (0x00000004), id: PAL/I (0000000000000010), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x00000000, 0x00000010); # ID
write_le32(169); # Size
write_hunk_fix_endian(869896, 169);
#
# Firmware 34, type: STD FW (0x00000000), id: SECAM/L AM (0000001000400000), size: 169
#
write_le32(0x00000000); # Type
write_le64(0x00000010, 0x00400000); # ID
write_le32(169); # Size
write_hunk_fix_endian(870072, 169);
#
# Firmware 35, type: STD FW (0x00000000), id: SECAM/L NICAM (0000000c00400000), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x0000000c, 0x00400000); # ID
write_le32(161); # Size
write_hunk_fix_endian(870248, 161);
#
# Firmware 36, type: STD FW (0x00000000), id: SECAM/Lc (0000000000800000), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000000, 0x00800000); # ID
write_le32(161); # Size
write_hunk_fix_endian(870416, 161);
#
# Firmware 37, type: STD FW (0x00000000), id: NTSC/M Kr (0000000000008000), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000000, 0x00008000); # ID
write_le32(161); # Size
write_hunk_fix_endian(870584, 161);
#
# Firmware 38, type: STD FW LCD (0x00001000), id: NTSC/M Kr (0000000000008000), size: 161
#
write_le32(0x00001000); # Type
write_le64(0x00000000, 0x00008000); # ID
write_le32(161); # Size
write_hunk_fix_endian(870752, 161);
#
# Firmware 39, type: STD FW LCD NOGD (0x00003000), id: NTSC/M Kr (0000000000008000), size: 161
#
write_le32(0x00003000); # Type
write_le64(0x00000000, 0x00008000); # ID
write_le32(161); # Size
write_hunk_fix_endian(870920, 161);
#
# Firmware 40, type: STD FW MTS (0x00000004), id: NTSC/M Kr (0000000000008000), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x00000000, 0x00008000); # ID
write_le32(169); # Size
write_hunk_fix_endian(871088, 169);
#
# Firmware 41, type: STD FW (0x00000000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000000, 0x0000b700); # ID
write_le32(161); # Size
write_hunk_fix_endian(871264, 161);
#
# Firmware 42, type: STD FW LCD (0x00001000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161
#
write_le32(0x00001000); # Type
write_le64(0x00000000, 0x0000b700); # ID
write_le32(161); # Size
write_hunk_fix_endian(871432, 161);
#
# Firmware 43, type: STD FW LCD NOGD (0x00003000), id: NTSC PAL/M PAL/N (000000000000b700), size: 161
#
write_le32(0x00003000); # Type
write_le64(0x00000000, 0x0000b700); # ID
write_le32(161); # Size
write_hunk_fix_endian(871600, 161);
#
# Firmware 44, type: STD FW (0x00000000), id: NTSC/M Jp (0000000000002000), size: 161
#
write_le32(0x00000000); # Type
write_le64(0x00000000, 0x00002000); # ID
write_le32(161); # Size
write_hunk_fix_endian(871264, 161);
#
# Firmware 45, type: STD FW MTS (0x00000004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169
#
write_le32(0x00000004); # Type
write_le64(0x00000000, 0x0000b700); # ID
write_le32(169); # Size
write_hunk_fix_endian(871936, 169);
#
# Firmware 46, type: STD FW MTS LCD (0x00001004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169
#
write_le32(0x00001004); # Type
write_le64(0x00000000, 0x0000b700); # ID
write_le32(169); # Size
write_hunk_fix_endian(872112, 169);
#
# Firmware 47, type: STD FW MTS LCD NOGD (0x00003004), id: NTSC PAL/M PAL/N (000000000000b700), size: 169
#
write_le32(0x00003004); # Type
write_le64(0x00000000, 0x0000b700); # ID
write_le32(169); # Size
write_hunk_fix_endian(872288, 169);
#
# Firmware 48, type: SCODE FW HAS IF (0x60000000), IF = 3.28 MHz id: (0000000000000000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(3280); # IF
write_le32(192); # Size
write_hunk(811896, 192);
#
# Firmware 49, type: SCODE FW HAS IF (0x60000000), IF = 3.30 MHz id: (0000000000000000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(3300); # IF
write_le32(192); # Size
write_hunk(813048, 192);
#
# Firmware 50, type: SCODE FW HAS IF (0x60000000), IF = 3.44 MHz id: (0000000000000000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(3440); # IF
write_le32(192); # Size
write_hunk(812280, 192);
#
# Firmware 51, type: SCODE FW HAS IF (0x60000000), IF = 3.46 MHz id: (0000000000000000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(3460); # IF
write_le32(192); # Size
write_hunk(812472, 192);
#
# Firmware 52, type: SCODE FW DTV6 ATSC OREN36 HAS IF (0x60210020), IF = 3.80 MHz id: (0000000000000000), size: 192
#
write_le32(0x60210020); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(3800); # IF
write_le32(192); # Size
write_hunk(809784, 192);
#
# Firmware 53, type: SCODE FW HAS IF (0x60000000), IF = 4.00 MHz id: (0000000000000000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(4000); # IF
write_le32(192); # Size
write_hunk(812088, 192);
#
# Firmware 54, type: SCODE FW DTV6 ATSC TOYOTA388 HAS IF (0x60410020), IF = 4.08 MHz id: (0000000000000000), size: 192
#
write_le32(0x60410020); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(4080); # IF
write_le32(192); # Size
write_hunk(809976, 192);
#
# Firmware 55, type: SCODE FW HAS IF (0x60000000), IF = 4.20 MHz id: (0000000000000000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(4200); # IF
write_le32(192); # Size
write_hunk(811704, 192);
#
# Firmware 56, type: SCODE FW MONO HAS IF (0x60008000), IF = 4.32 MHz id: NTSC/M Kr (0000000000008000), size: 192
#
write_le32(0x60008000); # Type
write_le64(0x00000000, 0x00008000); # ID
write_le16(4320); # IF
write_le32(192); # Size
write_hunk(808056, 192);
#
# Firmware 57, type: SCODE FW HAS IF (0x60000000), IF = 4.45 MHz id: (0000000000000000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(4450); # IF
write_le32(192); # Size
write_hunk(812664, 192);
#
# Firmware 58, type: SCODE FW HAS IF (0x60000000), IF = 4.50 MHz id: NTSC/M Jp (0000000000002000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00002000); # ID
write_le16(4500); # IF
write_le32(192); # Size
write_hunk(807672, 192);
#
# Firmware 59, type: SCODE FW LCD NOGD IF HAS IF (0x60023000), IF = 4.60 MHz id: NTSC/M Kr (0000000000008000), size: 192
#
write_le32(0x60023000); # Type
write_le64(0x00000000, 0x00008000); # ID
write_le16(4600); # IF
write_le32(192); # Size
write_hunk(807864, 192);
#
# Firmware 60, type: SCODE FW DTV78 ZARLINK456 HAS IF (0x62000100), IF = 4.76 MHz id: (0000000000000000), size: 192
#
write_le32(0x62000100); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(4760); # IF
write_le32(192); # Size
write_hunk(807288, 192);
#
# Firmware 61, type: SCODE FW HAS IF (0x60000000), IF = 4.94 MHz id: (0000000000000000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(4940); # IF
write_le32(192); # Size
write_hunk(811512, 192);
#
# Firmware 62, type: SCODE FW DTV7 ZARLINK456 HAS IF (0x62000080), IF = 5.26 MHz id: (0000000000000000), size: 192
#
write_le32(0x62000080); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(5260); # IF
write_le32(192); # Size
write_hunk(810552, 192);
#
# Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
#
write_le32(0x60008000); # Type
write_le64(0x00000008, 0x00000007); # ID
write_le16(5320); # IF
write_le32(192); # Size
write_hunk(810744, 192);
#
# Firmware 64, type: SCODE FW DTV8 CHINA HAS IF (0x64000200), IF = 5.40 MHz id: (0000000000000000), size: 192
#
write_le32(0x64000200); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(5400); # IF
write_le32(192); # Size
write_hunk(807096, 192);
#
# Firmware 65, type: SCODE FW DTV6 ATSC OREN538 HAS IF (0x60110020), IF = 5.58 MHz id: (0000000000000000), size: 192
#
write_le32(0x60110020); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(5580); # IF
write_le32(192); # Size
write_hunk(809592, 192);
#
# Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2/B (0000000200000007), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000002, 0x00000007); # ID
write_le16(5640); # IF
write_le32(192); # Size
write_hunk(808440, 192);
#
# Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000008, 0x00000007); # ID
write_le16(5740); # IF
write_le32(192); # Size
write_hunk(808632, 192);
#
# Firmware 68, type: SCODE FW DTV7 DIBCOM52 HAS IF (0x61000080), IF = 5.90 MHz id: (0000000000000000), size: 192
#
write_le32(0x61000080); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(5900); # IF
write_le32(192); # Size
write_hunk(810360, 192);
#
# Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/I (0000000000000010), size: 192
#
write_le32(0x60008000); # Type
write_le64(0x00000000, 0x00000010); # ID
write_le16(6000); # IF
write_le32(192); # Size
write_hunk(808824, 192);
#
# Firmware 70, type: SCODE FW DTV6 QAM F6MHZ HAS IF (0x68000060), IF = 6.20 MHz id: (0000000000000000), size: 192
#
write_le32(0x68000060); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(6200); # IF
write_le32(192); # Size
write_hunk(809400, 192);
#
# Firmware 71, type: SCODE FW HAS IF (0x60000000), IF = 6.24 MHz id: PAL/I (0000000000000010), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000010); # ID
write_le16(6240); # IF
write_le32(192); # Size
write_hunk(808248, 192);
#
# Firmware 72, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.32 MHz id: SECAM/K1 (0000000000200000), size: 192
#
write_le32(0x60008000); # Type
write_le64(0x00000000, 0x00200000); # ID
write_le16(6320); # IF
write_le32(192); # Size
write_hunk(811320, 192);
#
# Firmware 73, type: SCODE FW HAS IF (0x60000000), IF = 6.34 MHz id: SECAM/K1 (0000000000200000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00200000); # ID
write_le16(6340); # IF
write_le32(192); # Size
write_hunk(809208, 192);
#
# Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: SECAM/K3 (0000000004000000), size: 192
#
write_le32(0x60008000); # Type
write_le64(0x00000000, 0x04000000); # ID
write_le16(6500); # IF
write_le32(192); # Size
write_hunk(811128, 192);
#
# Firmware 75, type: SCODE FW DTV6 ATSC ATI638 HAS IF (0x60090020), IF = 6.58 MHz id: (0000000000000000), size: 192
#
write_le32(0x60090020); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(6580); # IF
write_le32(192); # Size
write_hunk(807480, 192);
#
# Firmware 76, type: SCODE FW HAS IF (0x60000000), IF = 6.60 MHz id: PAL/DK A2 (00000003000000e0), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000003, 0x000000e0); # ID
write_le16(6600); # IF
write_le32(192); # Size
write_hunk(809016, 192);
#
# Firmware 77, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.68 MHz id: PAL/DK A2 (00000003000000e0), size: 192
#
write_le32(0x60008000); # Type
write_le64(0x00000003, 0x000000e0); # ID
write_le16(6680); # IF
write_le32(192); # Size
write_hunk(810936, 192);
#
# Firmware 78, type: SCODE FW DTV6 ATSC TOYOTA794 HAS IF (0x60810020), IF = 8.14 MHz id: (0000000000000000), size: 192
#
write_le32(0x60810020); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(8140); # IF
write_le32(192); # Size
write_hunk(810168, 192);
#
# Firmware 79, type: SCODE FW HAS IF (0x60000000), IF = 8.20 MHz id: (0000000000000000), size: 192
#
write_le32(0x60000000); # Type
write_le64(0x00000000, 0x00000000); # ID
write_le16(8200); # IF
write_le32(192); # Size
write_hunk(812856, 192);
}
sub extract_firmware {
my $sourcefile = "hcw85bda.sys";
my $hash = "0e44dbf63bb0169d57446aec21881ff2";
my $outfile = "xc3028-v27.fw";
my $name = "xc2028 firmware";
my $version = 519;
my $nr_desc = 80;
my $out;
verify($sourcefile, $hash);
open INFILE, "<$sourcefile";
main_firmware($outfile, $name, $version, $nr_desc);
close INFILE;
}
extract_firmware;
printf "Firmwares generated.\n";

View File

@ -568,6 +568,7 @@ the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'.
Many thanks to following persons for their contribute (listed in alphabetical
order):
- David Anderson for the donation of a webcam;
- Luca Capello for the donation of a webcam;
- Philippe Coval for having helped testing the PAS202BCA image sensor;
- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the

View File

@ -2141,6 +2141,15 @@ L: isdn4linux@listserv.isdn4linux.de
W: http://www.melware.de
S: Maintained
IVTV VIDEO4LINUX DRIVER
P: Hans Verkuil
M: hverkuil@xs4all.nl
L: ivtv-devel@ivtvdriver.org
L: ivtv-users@ivtvdriver.org
L: video4linux-list@redhat.com
W: http://www.ivtvdriver.org
S: Maintained
JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
P: David Woodhouse
M: dwmw2@infradead.org

View File

@ -69,11 +69,13 @@ source "drivers/media/common/Kconfig"
config VIDEO_TUNER
tristate
depends on I2C
select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE
select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE
select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE
select TUNER_TEA5761 if !VIDEO_TUNER_CUSTOMIZE
select TUNER_TEA5767 if !VIDEO_TUNER_CUSTOMIZE
select TUNER_SIMPLE if !VIDEO_TUNER_CUSTOMIZE
select TUNER_TDA9887 if !VIDEO_TUNER_CUSTOMIZE
menuconfig VIDEO_TUNER_CUSTOMIZE
bool "Customize analog tuner modules to build"
@ -89,6 +91,13 @@ menuconfig VIDEO_TUNER_CUSTOMIZE
if VIDEO_TUNER_CUSTOMIZE
config TUNER_XC2028
tristate "XCeive xc2028/xc3028 tuners"
depends on I2C
default m if VIDEO_TUNER_CUSTOMIZE
help
Say Y here to include support for the xc2028/xc3028 tuners.
config TUNER_MT20XX
tristate "Microtune 2032 / 2050 tuners"
depends on I2C
@ -97,8 +106,10 @@ config TUNER_MT20XX
Say Y here to include support for the MT2032 / MT2050 tuner.
config TUNER_TDA8290
tristate "TDA 8290+8275(a) tuner combo"
tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
depends on I2C
select DVB_TDA827X
select DVB_TDA18271
default m if VIDEO_TUNER_CUSTOMIZE
help
Say Y here to include support for Philips TDA8290+8275(a) tuner.
@ -120,10 +131,19 @@ config TUNER_TEA5767
config TUNER_SIMPLE
tristate "Simple tuner support"
depends on I2C
select TUNER_TDA9887
default m if VIDEO_TUNER_CUSTOMIZE
help
Say Y here to include support for various simple tuners.
config TUNER_TDA9887
tristate "TDA 9885/6/7 analog IF demodulator"
depends on I2C
default m if VIDEO_TUNER_CUSTOMIZE
help
Say Y here to include support for Philips TDA9885/6/7
analog IF demodulator.
endif # VIDEO_TUNER_CUSTOMIZE
config VIDEOBUF_GEN

View File

@ -1,6 +1,6 @@
config VIDEO_SAA7146
tristate
depends on I2C
depends on I2C && PCI
config VIDEO_SAA7146_VV
tristate

View File

@ -258,7 +258,7 @@ int ir_decode_biphase(u32 *samples, int count, int low, int high)
* saa7134 */
/* decode raw bit pattern to RC5 code */
u32 ir_rc5_decode(unsigned int code)
static u32 ir_rc5_decode(unsigned int code)
{
unsigned int org_code = code;
unsigned int pair;
@ -371,7 +371,6 @@ EXPORT_SYMBOL_GPL(ir_dump_samples);
EXPORT_SYMBOL_GPL(ir_decode_biphase);
EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
EXPORT_SYMBOL_GPL(ir_rc5_decode);
EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);

View File

@ -1331,7 +1331,12 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
[ 0x35 ] = KEY_FASTFORWARD,
[ 0x36 ] = KEY_TV,
[ 0x37 ] = KEY_RADIO, /* FM */
[ 0x38 ] = KEY_DVD
[ 0x38 ] = KEY_DVD,
[ 0x3e ] = KEY_F21, /* MCE +VOL, on Y04G0033 */
[ 0x3a ] = KEY_F22, /* MCE -VOL, on Y04G0033 */
[ 0x3b ] = KEY_F23, /* MCE +CH, on Y04G0033 */
[ 0x3f ] = KEY_F24 /* MCE -CH, on Y04G0033 */
};
EXPORT_SYMBOL_GPL(ir_codes_winfast);
@ -1843,3 +1848,142 @@ IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE] = {
};
EXPORT_SYMBOL_GPL(ir_codes_fusionhdtv_mce);
/* Pinnacle PCTV HD 800i mini remote */
IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE] = {
[0x0f] = KEY_1,
[0x15] = KEY_2,
[0x10] = KEY_3,
[0x18] = KEY_4,
[0x1b] = KEY_5,
[0x1e] = KEY_6,
[0x11] = KEY_7,
[0x21] = KEY_8,
[0x12] = KEY_9,
[0x27] = KEY_0,
[0x24] = KEY_ZOOM,
[0x2a] = KEY_SUBTITLE,
[0x00] = KEY_MUTE,
[0x01] = KEY_ENTER, /* Pinnacle Logo */
[0x39] = KEY_POWER,
[0x03] = KEY_VOLUMEUP,
[0x09] = KEY_VOLUMEDOWN,
[0x06] = KEY_CHANNELUP,
[0x0c] = KEY_CHANNELDOWN,
[0x2d] = KEY_REWIND,
[0x30] = KEY_PLAYPAUSE,
[0x33] = KEY_FASTFORWARD,
[0x3c] = KEY_STOP,
[0x36] = KEY_RECORD,
[0x3f] = KEY_EPG, /* Labeled "?" */
};
EXPORT_SYMBOL_GPL(ir_codes_pinnacle_pctv_hd);
/*
* Igor Kuznetsov <igk72@ya.ru>
* Andrey J. Melnikov <temnota@kmv.ru>
*
* Keytable is used by BeholdTV 60x series, M6 series at
* least, and probably other cards too.
* The "ascii-art picture" below (in comments, first row
* is the keycode in hex, and subsequent row(s) shows
* the button labels (several variants when appropriate)
* helps to descide which keycodes to assign to the buttons.
*/
IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = {
/* 0x1c 0x12 *
* TV/FM POWER *
* */
[ 0x1c ] = KEY_TUNER, /*XXX KEY_TV KEY_RADIO */
[ 0x12 ] = KEY_POWER,
/* 0x01 0x02 0x03 *
* 1 2 3 *
* *
* 0x04 0x05 0x06 *
* 4 5 6 *
* *
* 0x07 0x08 0x09 *
* 7 8 9 *
* */
[ 0x01 ] = KEY_1,
[ 0x02 ] = KEY_2,
[ 0x03 ] = KEY_3,
[ 0x04 ] = KEY_4,
[ 0x05 ] = KEY_5,
[ 0x06 ] = KEY_6,
[ 0x07 ] = KEY_7,
[ 0x08 ] = KEY_8,
[ 0x09 ] = KEY_9,
/* 0x0a 0x00 0x17 *
* RECALL 0 MODE *
* */
[ 0x0a ] = KEY_AGAIN,
[ 0x00 ] = KEY_0,
[ 0x17 ] = KEY_MODE,
/* 0x14 0x10 *
* ASPECT FULLSCREEN *
* */
[ 0x14 ] = KEY_SCREEN,
[ 0x10 ] = KEY_ZOOM,
/* 0x0b *
* Up *
* *
* 0x18 0x16 0x0c *
* Left Ok Right *
* *
* 0x015 *
* Down *
* */
[ 0x0b ] = KEY_CHANNELUP, /*XXX KEY_UP */
[ 0x18 ] = KEY_VOLUMEDOWN, /*XXX KEY_LEFT */
[ 0x16 ] = KEY_OK, /*XXX KEY_ENTER */
[ 0x0c ] = KEY_VOLUMEUP, /*XXX KEY_RIGHT */
[ 0x15 ] = KEY_CHANNELDOWN, /*XXX KEY_DOWN */
/* 0x11 0x0d *
* MUTE INFO *
* */
[ 0x11 ] = KEY_MUTE,
[ 0x0d ] = KEY_INFO,
/* 0x0f 0x1b 0x1a *
* RECORD PLAY/PAUSE STOP *
* *
* 0x0e 0x1f 0x1e *
*TELETEXT AUDIO SOURCE *
* RED YELLOW *
* */
[ 0x0f ] = KEY_RECORD,
[ 0x1b ] = KEY_PLAYPAUSE,
[ 0x1a ] = KEY_STOP,
[ 0x0e ] = KEY_TEXT,
[ 0x1f ] = KEY_RED, /*XXX KEY_AUDIO */
[ 0x1e ] = KEY_YELLOW, /*XXX KEY_SOURCE */
/* 0x1d 0x13 0x19 *
* SLEEP PREVIEW DVB *
* GREEN BLUE *
* */
[ 0x1d ] = KEY_SLEEP,
[ 0x13 ] = KEY_GREEN,
[ 0x19 ] = KEY_BLUE, /*XXX KEY_SAT */
/* 0x58 0x5c *
* FREEZE SNAPSHOT *
* */
[ 0x58 ] = KEY_SLOW,
[ 0x5c ] = KEY_SAVE,
};
EXPORT_SYMBOL_GPL(ir_codes_behold);

View File

@ -61,7 +61,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
videobuf_waiton(&buf->vb,0,0);
videobuf_dma_unmap(q, dma);
videobuf_dma_free(dma);
buf->vb.state = STATE_NEEDS_INIT;
buf->vb.state = VIDEOBUF_NEEDS_INIT;
}
@ -83,7 +83,7 @@ int saa7146_buffer_queue(struct saa7146_dev *dev,
buf->activate(dev,buf,NULL);
} else {
list_add_tail(&buf->vb.queue,&q->queue);
buf->vb.state = STATE_QUEUED;
buf->vb.state = VIDEOBUF_QUEUED;
DEB_D(("adding buffer %p to queue. (active buffer present)\n", buf));
}
return 0;
@ -174,7 +174,7 @@ void saa7146_buffer_timeout(unsigned long data)
spin_lock_irqsave(&dev->slock,flags);
if (q->curr) {
DEB_D(("timeout on %p\n", q->curr));
saa7146_buffer_finish(dev,q,STATE_ERROR);
saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
}
/* we don't restart the transfer here like other drivers do. when
@ -366,7 +366,7 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
}
poll_wait(file, &buf->done, wait);
if (buf->state == STATE_DONE || buf->state == STATE_ERROR) {
if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
DEB_D(("poll succeeded!\n"));
return POLLIN|POLLRDNORM;
}
@ -538,6 +538,7 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
// fixme: -1 should be an insmod parameter *for the extension* (like "video_nr");
if (video_register_device(vfd, type, -1) < 0) {
ERR(("cannot register v4l2 device. skipping.\n"));
video_device_release(vfd);
return -1;
}

View File

@ -205,7 +205,7 @@ static int buffer_activate(struct saa7146_dev *dev,
struct saa7146_buf *next)
{
struct saa7146_vv *vv = dev->vv_data;
buf->vb.state = STATE_ACTIVE;
buf->vb.state = VIDEOBUF_ACTIVE;
DEB_VBI(("dev:%p, buf:%p, next:%p\n",dev,buf,next));
saa7146_set_vbi_capture(dev,buf,next);
@ -238,7 +238,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
if (buf->vb.size != size)
saa7146_dma_free(dev,q,buf);
if (STATE_NEEDS_INIT == buf->vb.state) {
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
buf->vb.width = llength;
@ -257,7 +257,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,e
if (0 != err)
return err;
}
buf->vb.state = STATE_PREPARED;
buf->vb.state = VIDEOBUF_PREPARED;
buf->activate = buffer_activate;
return 0;
@ -335,7 +335,7 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file)
saa7146_write(dev, MC1, MASK_20);
if (vv->vbi_q.curr) {
saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE);
saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
}
videobuf_queue_cancel(&fh->vbi_q);
@ -458,7 +458,7 @@ static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
/* this must be += 2, one count for each field */
vv->vbi_fieldcount+=2;
vv->vbi_q.curr->vb.field_count = vv->vbi_fieldcount;
saa7146_buffer_finish(dev,&vv->vbi_q,STATE_DONE);
saa7146_buffer_finish(dev,&vv->vbi_q,VIDEOBUF_DONE);
} else {
DEB_VBI(("dev:%p\n",dev));
}

View File

@ -1235,7 +1235,7 @@ static int buffer_activate (struct saa7146_dev *dev,
{
struct saa7146_vv *vv = dev->vv_data;
buf->vb.state = STATE_ACTIVE;
buf->vb.state = VIDEOBUF_ACTIVE;
saa7146_set_capture(dev,buf,next);
mod_timer(&vv->video_q.timeout, jiffies+BUFFER_TIMEOUT);
@ -1281,7 +1281,7 @@ static int buffer_prepare(struct videobuf_queue *q,
saa7146_dma_free(dev,q,buf);
}
if (STATE_NEEDS_INIT == buf->vb.state) {
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
struct saa7146_format *sfmt;
buf->vb.bytesperline = fh->video_fmt.bytesperline;
@ -1314,7 +1314,7 @@ static int buffer_prepare(struct videobuf_queue *q,
if (err)
goto oops;
}
buf->vb.state = STATE_PREPARED;
buf->vb.state = VIDEOBUF_PREPARED;
buf->activate = buffer_activate;
return 0;
@ -1453,7 +1453,7 @@ static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
/* only finish the buffer if we have one... */
if( NULL != q->curr ) {
saa7146_buffer_finish(dev,q,STATE_DONE);
saa7146_buffer_finish(dev,q,VIDEOBUF_DONE);
}
saa7146_buffer_next(dev,q,0);

View File

@ -212,7 +212,6 @@ void flexcop_reset_block_300(struct flexcop_device *fc)
fc->write_ibi_reg(fc,ctrl_208,v208_save);
}
EXPORT_SYMBOL(flexcop_reset_block_300);
struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
{

View File

@ -378,23 +378,37 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *
EXPORT_SYMBOL(bt878_device_control);
#define BROOKTREE_878_DEVICE(vend, dev, name) \
{ \
.vendor = PCI_VENDOR_ID_BROOKTREE, \
.device = PCI_DEVICE_ID_BROOKTREE_878, \
.subvendor = (vend), .subdevice = (dev), \
.driver_data = (unsigned long) name \
}
static struct cards card_list[] __devinitdata = {
{ 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
{ 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
{ 0x001c11bd, BTTV_BOARD_PINNACLESAT, "Pinnacle PCTV Sat" },
{ 0x002611bd, BTTV_BOARD_TWINHAN_DST, "Pinnacle PCTV SAT CI" },
{ 0x00011822, BTTV_BOARD_TWINHAN_DST, "Twinhan VisionPlus DVB" },
{ 0xfc00270f, BTTV_BOARD_TWINHAN_DST, "ChainTech digitop DST-1000 DVB-S" },
{ 0x07711461, BTTV_BOARD_AVDVBT_771, "AVermedia AverTV DVB-T 771" },
{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE, "DViCO FusionHDTV DVB-T Lite" },
{ 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE, "Ultraview DVB-T Lite" },
{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" },
{ 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV" },
{ 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini" }
static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
BROOKTREE_878_DEVICE(0x0071, 0x0101, "Nebula Electronics DigiTV"),
BROOKTREE_878_DEVICE(0x1461, 0x0761, "AverMedia AverTV DVB-T 761"),
BROOKTREE_878_DEVICE(0x11bd, 0x001c, "Pinnacle PCTV Sat"),
BROOKTREE_878_DEVICE(0x11bd, 0x0026, "Pinnacle PCTV SAT CI"),
BROOKTREE_878_DEVICE(0x1822, 0x0001, "Twinhan VisionPlus DVB"),
BROOKTREE_878_DEVICE(0x270f, 0xfc00,
"ChainTech digitop DST-1000 DVB-S"),
BROOKTREE_878_DEVICE(0x1461, 0x0771, "AVermedia AverTV DVB-T 771"),
BROOKTREE_878_DEVICE(0x18ac, 0xdb10, "DViCO FusionHDTV DVB-T Lite"),
BROOKTREE_878_DEVICE(0x18ac, 0xdb11, "Ultraview DVB-T Lite"),
BROOKTREE_878_DEVICE(0x18ac, 0xd500, "DViCO FusionHDTV 5 Lite"),
BROOKTREE_878_DEVICE(0x7063, 0x2000, "pcHDTV HD-2000 TV"),
BROOKTREE_878_DEVICE(0x1822, 0x0026, "DNTV Live! Mini"),
{ }
};
MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
static const char * __devinit card_name(const struct pci_device_id *id)
{
return id->driver_data ? (const char *)id->driver_data : "Unknown";
}
/***********************/
/* PCI device handling */
@ -403,15 +417,13 @@ static struct cards card_list[] __devinitdata = {
static int __devinit bt878_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
int result = 0, has_dvb = 0, i;
int result = 0;
unsigned char lat;
struct bt878 *bt;
#if defined(__powerpc__)
unsigned int cmd;
#endif
unsigned int cardid;
unsigned short id;
struct cards *dvb_cards;
printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
bt878_num);
@ -423,25 +435,11 @@ static int __devinit bt878_probe(struct pci_dev *dev,
if (pci_enable_device(dev))
return -EIO;
pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &id);
cardid = id << 16;
pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &id);
cardid |= id;
cardid = dev->subsystem_device << 16;
cardid |= dev->subsystem_vendor;
for (i = 0, dvb_cards = card_list; i < ARRAY_SIZE(card_list); i++, dvb_cards++) {
if (cardid == dvb_cards->pci_id) {
printk("%s: card id=[0x%x],[ %s ] has DVB functions.\n",
__func__, cardid, dvb_cards->name);
has_dvb = 1;
}
}
if (!has_dvb) {
printk("%s: card id=[0x%x], Unknown card.\nExiting..\n", __func__, cardid);
result = -EINVAL;
goto fail0;
}
printk(KERN_INFO "%s: card id=[0x%x],[ %s ] has DVB functions.\n",
__func__, cardid, card_name(pci_id));
bt = &bt878[bt878_num];
bt->dev = dev;
@ -572,14 +570,6 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev)
return;
}
static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
{PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BROOKTREE_878,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
static struct pci_driver bt878_pci_driver = {
.name = "bt878",
.id_table = bt878_pci_tbl,

View File

@ -101,12 +101,6 @@
#define BTTV_BOARD_DVICO_DVBT_LITE 0x80
#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
struct cards {
__u32 pci_id;
__u16 card_id;
char *name;
};
extern int bt878_num;
struct bt878 {

View File

@ -71,6 +71,7 @@ MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
} \
} while(0)
static int dst_command(struct dst_state *state, u8 *data, u8 len);
static void dst_packsize(struct dst_state *state, int psize)
{
@ -80,7 +81,8 @@ static void dst_packsize(struct dst_state *state, int psize)
bt878_device_control(state->bt, DST_IG_TS, &bits);
}
int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb, u32 outhigh, int delay)
static int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb,
u32 outhigh, int delay)
{
union dst_gpio_packet enb;
union dst_gpio_packet bits;
@ -109,9 +111,8 @@ int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb, u32 outhigh, int
return 0;
}
EXPORT_SYMBOL(dst_gpio_outb);
int dst_gpio_inb(struct dst_state *state, u8 *result)
static int dst_gpio_inb(struct dst_state *state, u8 *result)
{
union dst_gpio_packet rd_packet;
int err;
@ -125,7 +126,6 @@ int dst_gpio_inb(struct dst_state *state, u8 *result)
return 0;
}
EXPORT_SYMBOL(dst_gpio_inb);
int rdc_reset_state(struct dst_state *state)
{
@ -145,7 +145,7 @@ int rdc_reset_state(struct dst_state *state)
}
EXPORT_SYMBOL(rdc_reset_state);
int rdc_8820_reset(struct dst_state *state)
static int rdc_8820_reset(struct dst_state *state)
{
dprintk(verbose, DST_DEBUG, 1, "Resetting DST");
if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
@ -160,9 +160,8 @@ int rdc_8820_reset(struct dst_state *state)
return 0;
}
EXPORT_SYMBOL(rdc_8820_reset);
int dst_pio_enable(struct dst_state *state)
static int dst_pio_enable(struct dst_state *state)
{
if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
@ -172,7 +171,6 @@ int dst_pio_enable(struct dst_state *state)
return 0;
}
EXPORT_SYMBOL(dst_pio_enable);
int dst_pio_disable(struct dst_state *state)
{
@ -611,7 +609,7 @@ static int dst_type_print(struct dst_state *state, u8 type)
return 0;
}
struct tuner_types tuner_list[] = {
static struct tuner_types tuner_list[] = {
{
.tuner_type = TUNER_TYPE_L64724,
.tuner_name = "L 64724",
@ -1224,7 +1222,7 @@ static int dst_probe(struct dst_state *state)
return 0;
}
int dst_command(struct dst_state *state, u8 *data, u8 len)
static int dst_command(struct dst_state *state, u8 *data, u8 len)
{
u8 reply;
@ -1287,7 +1285,6 @@ error:
return -EIO;
}
EXPORT_SYMBOL(dst_command);
static int dst_get_signal(struct dst_state *state)
{

View File

@ -165,10 +165,8 @@ struct dst_config
};
int rdc_reset_state(struct dst_state *state);
int rdc_8820_reset(struct dst_state *state);
int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode);
int dst_pio_enable(struct dst_state *state);
int dst_pio_disable(struct dst_state *state);
int dst_error_recovery(struct dst_state* state);
int dst_error_bailout(struct dst_state *state);
@ -179,9 +177,6 @@ int read_dst(struct dst_state *state, u8 * ret, u8 len);
u8 dst_check_sum(u8 * buf, u32 len);
struct dst_state* dst_attach(struct dst_state* state, struct dvb_adapter *dvb_adapter);
struct dvb_device *dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay);
int dst_command(struct dst_state* state, u8 * data, u8 len);
#endif // DST_COMMON_H

View File

@ -1202,6 +1202,10 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
fe->ops.tuner_ops.release(fe);
symbol_put_addr(fe->ops.tuner_ops.release);
}
if (fe->ops.analog_ops.release) {
fe->ops.analog_ops.release(fe);
symbol_put_addr(fe->ops.analog_ops.release);
}
ptr = (void*)fe->ops.release;
if (ptr) {
fe->ops.release(fe);
@ -1215,6 +1219,8 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
fe->ops.release_sec(fe);
if (fe->ops.tuner_ops.release)
fe->ops.tuner_ops.release(fe);
if (fe->ops.analog_ops.release)
fe->ops.analog_ops.release(fe);
if (fe->ops.release)
fe->ops.release(fe);
}

View File

@ -84,6 +84,9 @@ struct dvb_tuner_ops {
/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
/** This is to allow setting tuner-specific configs */
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
@ -98,6 +101,28 @@ struct dvb_tuner_ops {
int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
};
struct analog_demod_info {
char *name;
};
struct analog_demod_ops {
struct analog_demod_info info;
void (*set_params)(struct dvb_frontend *fe,
struct analog_parameters *params);
int (*has_signal)(struct dvb_frontend *fe);
int (*is_stereo)(struct dvb_frontend *fe);
int (*get_afc)(struct dvb_frontend *fe);
void (*tuner_status)(struct dvb_frontend *fe);
void (*standby)(struct dvb_frontend *fe);
void (*release)(struct dvb_frontend *fe);
int (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable);
/** This is to allow setting tuner-specific configuration */
int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
};
struct dvb_frontend_ops {
struct dvb_frontend_info info;
@ -143,6 +168,7 @@ struct dvb_frontend_ops {
int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
struct dvb_tuner_ops tuner_ops;
struct analog_demod_ops analog_ops;
};
#define MAX_EVENT 8
@ -159,18 +185,19 @@ struct dvb_fe_events {
struct dvb_frontend {
struct dvb_frontend_ops ops;
struct dvb_adapter *dvb;
void* demodulator_priv;
void* tuner_priv;
void* frontend_priv;
void* sec_priv;
void *demodulator_priv;
void *tuner_priv;
void *frontend_priv;
void *sec_priv;
void *analog_demod_priv;
};
extern int dvb_register_frontend(struct dvb_adapter* dvb,
struct dvb_frontend* fe);
extern int dvb_register_frontend(struct dvb_adapter *dvb,
struct dvb_frontend *fe);
extern int dvb_unregister_frontend(struct dvb_frontend* fe);
extern int dvb_unregister_frontend(struct dvb_frontend *fe);
extern void dvb_frontend_detach(struct dvb_frontend* fe);
extern void dvb_frontend_detach(struct dvb_frontend *fe);
extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);

View File

@ -261,11 +261,6 @@ EXPORT_SYMBOL(dvb_ringbuffer_init);
EXPORT_SYMBOL(dvb_ringbuffer_empty);
EXPORT_SYMBOL(dvb_ringbuffer_free);
EXPORT_SYMBOL(dvb_ringbuffer_avail);
EXPORT_SYMBOL(dvb_ringbuffer_flush);
EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
EXPORT_SYMBOL(dvb_ringbuffer_read);
EXPORT_SYMBOL(dvb_ringbuffer_write);
EXPORT_SYMBOL(dvb_ringbuffer_pkt_write);
EXPORT_SYMBOL(dvb_ringbuffer_pkt_read);
EXPORT_SYMBOL(dvb_ringbuffer_pkt_dispose);
EXPORT_SYMBOL(dvb_ringbuffer_pkt_next);

View File

@ -1026,6 +1026,7 @@ static int af9005_usb_probe(struct usb_interface *intf,
static struct usb_device_id af9005_usb_table[] = {
{USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9005)},
{USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE)},
{USB_DEVICE(USB_VID_ANSONIC, USB_PID_ANSONIC_DVBT_USB)},
{0},
};
@ -1075,7 +1076,7 @@ static struct dvb_usb_device_properties af9005_properties = {
.rc_key_map_size = 0,
.rc_query = af9005_rc_query,
.num_device_descs = 2,
.num_device_descs = 3,
.devices = {
{.name = "Afatech DVB-T USB1.1 stick",
.cold_ids = {&af9005_usb_table[0], NULL},
@ -1085,6 +1086,10 @@ static struct dvb_usb_device_properties af9005_properties = {
.cold_ids = {&af9005_usb_table[1], NULL},
.warm_ids = {NULL},
},
{.name = "Ansonic DVB-T USB1.1 stick",
.cold_ids = {&af9005_usb_table[2], NULL},
.warm_ids = {NULL},
},
{NULL},
}
};

View File

@ -79,12 +79,12 @@ static int au6610_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
if (num > 2)
return -EINVAL;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
for (i = 0; i < num; i++) {
/* write/read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {

View File

@ -15,7 +15,7 @@
*
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
* Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org)
* Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
* Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au)
*
* 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
@ -30,11 +30,16 @@
#include "mt352.h"
#include "mt352_priv.h"
#include "zl10353.h"
#include "tuner-xc2028.h"
#include "tuner-xc2028-types.h"
/* debug */
int dvb_usb_cxusb_debug;
static int dvb_usb_cxusb_debug;
module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
#define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
dprintk(dvb_usb_cxusb_debug,0x01,args)
static int cxusb_ctrl_msg(struct dvb_usb_device *d,
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
@ -46,11 +51,9 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
sndbuf[0] = cmd;
memcpy(&sndbuf[1], wbuf, wlen);
if (wo)
dvb_usb_generic_write(d, sndbuf, 1+wlen);
return dvb_usb_generic_write(d, sndbuf, 1+wlen);
else
dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
return 0;
return dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
}
/* GPIO */
@ -72,6 +75,34 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
st->gpio_write_state[GPIO_TUNER] = onoff;
}
static int cxusb_bluebird_gpio_rw(struct dvb_usb_device *d, u8 changemask,
u8 newval)
{
u8 o[2], gpio_state;
int rc;
o[0] = 0xff & ~changemask; /* mask of bits to keep */
o[1] = newval & changemask; /* new values for bits */
rc = cxusb_ctrl_msg(d, CMD_BLUEBIRD_GPIO_RW, o, 2, &gpio_state, 1);
if (rc < 0 || (gpio_state & changemask) != (newval & changemask))
deb_info("bluebird_gpio_write failed.\n");
return rc < 0 ? rc : gpio_state;
}
static void cxusb_bluebird_gpio_pulse(struct dvb_usb_device *d, u8 pin, int low)
{
cxusb_bluebird_gpio_rw(d, pin, low ? 0 : pin);
msleep(5);
cxusb_bluebird_gpio_rw(d, pin, low ? pin : 0);
}
static void cxusb_nano2_led(struct dvb_usb_device *d, int onoff)
{
cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40);
}
/* I2C */
static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
@ -82,9 +113,6 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
if (num > 2)
warn("more than two i2c messages at a time is not handled yet. TODO.");
for (i = 0; i < num; i++) {
if (d->udev->descriptor.idVendor == USB_VID_MEDION)
@ -97,8 +125,22 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
break;
}
/* read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
if (msg[i].flags & I2C_M_RD) {
/* read only */
u8 obuf[3], ibuf[1+msg[i].len];
obuf[0] = 0;
obuf[1] = msg[i].len;
obuf[2] = msg[i].addr;
if (cxusb_ctrl_msg(d, CMD_I2C_READ,
obuf, 3,
ibuf, 1+msg[i].len) < 0) {
warn("i2c read failed");
break;
}
memcpy(msg[i].buf, &ibuf[1], msg[i].len);
} else if (i+1 < num && (msg[i+1].flags & I2C_M_RD) &&
msg[i].addr == msg[i+1].addr) {
/* write to then read from same address */
u8 obuf[3+msg[i].len], ibuf[1+msg[i+1].len];
obuf[0] = msg[i].len;
obuf[1] = msg[i+1].len;
@ -116,7 +158,8 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len);
i++;
} else { /* write */
} else {
/* write only */
u8 obuf[2+msg[i].len], ibuf;
obuf[0] = msg[i].addr;
obuf[1] = msg[i].len;
@ -131,7 +174,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
}
mutex_unlock(&d->i2c_mutex);
return i;
return i == num ? num : -EREMOTEIO;
}
static u32 cxusb_i2c_func(struct i2c_adapter *adapter)
@ -162,6 +205,17 @@ static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
return 0;
}
static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff)
{
int rc = 0;
rc = cxusb_power_ctrl(d, onoff);
if (!onoff)
cxusb_nano2_led(d, 0);
return rc;
}
static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{
u8 buf[2] = { 0x03, 0x00 };
@ -197,6 +251,34 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0;
}
static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
int *state)
{
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
u8 ircode[4];
int i;
struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
.buf = ircode, .len = 4 };
*event = 0;
*state = REMOTE_NO_KEY_PRESSED;
if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
return 0;
for (i = 0; i < d->props.rc_key_map_size; i++) {
if (keymap[i].custom == ircode[1] &&
keymap[i].data == ircode[2]) {
*event = keymap[i].event;
*state = REMOTE_KEY_PRESSED;
return 0;
}
}
return 0;
}
static struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
{ 0xfe, 0x02, KEY_TV },
{ 0xfe, 0x0e, KEY_MP3 },
@ -351,6 +433,20 @@ static struct mt352_config cxusb_mt352_config = {
.demod_init = cxusb_mt352_demod_init,
};
static struct zl10353_config cxusb_zl10353_xc3028_config = {
.demod_address = 0x0f,
.if2 = 45600,
.no_tuner = 1,
.parallel_ts = 1,
};
static struct mt352_config cxusb_mt352_xc3028_config = {
.demod_address = 0x0f,
.if2 = 4560,
.no_tuner = 1,
.demod_init = cxusb_mt352_demod_init,
};
/* Callbacks for DVB USB */
static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
{
@ -386,6 +482,51 @@ static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
return 0;
}
static int dvico_bluebird_xc2028_callback(void *ptr, int command, int arg)
{
struct dvb_usb_device *d = ptr;
switch (command) {
case XC2028_TUNER_RESET:
deb_info("%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg);
cxusb_bluebird_gpio_pulse(d, 0x01, 1);
break;
case XC2028_RESET_CLK:
deb_info("%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg);
break;
default:
deb_info("%s: unknown command %d, arg %d\n", __FUNCTION__,
command, arg);
return -EINVAL;
}
return 0;
}
static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dvb_frontend *fe;
struct xc2028_config cfg = {
.i2c_adap = &adap->dev->i2c_adap,
.i2c_addr = 0x61,
.video_dev = adap->dev,
.callback = dvico_bluebird_xc2028_callback,
};
static struct xc2028_ctrl ctl = {
.fname = "xc3028-dvico-au-01.fw",
.max_len = 64,
.scode_table = ZARLINK456,
};
fe = dvb_attach(xc2028_attach, adap->fe, &cfg);
if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
return -EIO;
fe->ops.tuner_ops.set_config(fe, &ctl);
return 0;
}
static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
{
u8 b;
@ -447,27 +588,120 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
return -EIO;
}
static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
{
u8 ircode[4];
int i;
struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
.buf = ircode, .len = 4 };
if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
err("set interface failed");
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
/* reset the tuner and demodulator */
cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
if ((adap->fe = dvb_attach(zl10353_attach,
&cxusb_zl10353_xc3028_config,
&adap->dev->i2c_adap)) == NULL)
return -EIO;
/* try to determine if there is no IR decoder on the I2C bus */
for (i = 0; adap->dev->props.rc_key_map != NULL && i < 5; i++) {
msleep(20);
if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
goto no_IR;
if (ircode[0] == 0 && ircode[1] == 0)
continue;
if (ircode[2] + ircode[3] != 0xff) {
no_IR:
adap->dev->props.rc_key_map = NULL;
info("No IR receiver detected on this device.");
break;
}
}
return 0;
}
static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
{
if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
err("set interface failed");
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
/* reset the tuner and demodulator */
cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
if ((adap->fe = dvb_attach(zl10353_attach,
&cxusb_zl10353_xc3028_config,
&adap->dev->i2c_adap)) != NULL)
return 0;
if ((adap->fe = dvb_attach(mt352_attach,
&cxusb_mt352_xc3028_config,
&adap->dev->i2c_adap)) != NULL)
return 0;
return -EIO;
}
/*
* DViCO has shipped two devices with the same USB ID, but only one of them
* needs a firmware download. Check the device class details to see if they
* have non-default values to decide whether the device is actually cold or
* not, and forget a match if it turns out we selected the wrong device.
*/
static int bluebird_fx2_identify_state(struct usb_device *udev,
struct dvb_usb_device_properties *props,
struct dvb_usb_device_description **desc,
int *cold)
{
int wascold = *cold;
*cold = udev->descriptor.bDeviceClass == 0xff &&
udev->descriptor.bDeviceSubClass == 0xff &&
udev->descriptor.bDeviceProtocol == 0xff;
if (*cold && !wascold)
*desc = NULL;
return 0;
}
/*
* DViCO bluebird firmware needs the "warm" product ID to be patched into the
* firmware file before download.
*/
#define BLUEBIRD_01_ID_OFFSET 6638
static const int dvico_firmware_id_offsets[] = { 6638, 3204 };
static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
const struct firmware *fw)
{
if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
return -EINVAL;
int pos;
if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
for (pos = 0; pos < ARRAY_SIZE(dvico_firmware_id_offsets); pos++) {
int idoff = dvico_firmware_id_offsets[pos];
fw->data[BLUEBIRD_01_ID_OFFSET + 2] =
le16_to_cpu(udev->descriptor.idProduct) + 1;
fw->data[BLUEBIRD_01_ID_OFFSET + 3] =
le16_to_cpu(udev->descriptor.idProduct) >> 8;
if (fw->size < idoff + 4)
continue;
return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
if (fw->data[idoff] == (USB_VID_DVICO & 0xff) &&
fw->data[idoff + 1] == USB_VID_DVICO >> 8) {
fw->data[idoff + 2] =
le16_to_cpu(udev->descriptor.idProduct) + 1;
fw->data[idoff + 3] =
le16_to_cpu(udev->descriptor.idProduct) >> 8;
return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
}
}
return -EINVAL;
@ -479,6 +713,9 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties;
static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@ -487,7 +724,10 @@ static int cxusb_probe(struct usb_interface *intf,
dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_lgz201_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0) {
dvb_usb_device_init(intf,&cxusb_bluebird_dtt7579_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_dualdig4_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_nano2_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_nano2_needsfirmware_properties,THIS_MODULE,NULL) == 0) {
return 0;
}
@ -508,6 +748,9 @@ static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
@ -766,6 +1009,151 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
}
};
static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2,
.size_of_priv = sizeof(struct cxusb_state),
.num_adapters = 1,
.adapter = {
{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_dualdig4_frontend_attach,
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
.count = 5,
.endpoint = 0x02,
.u = {
.bulk = {
.buffersize = 8192,
}
}
},
},
},
.power_ctrl = cxusb_power_ctrl,
.i2c_algo = &cxusb_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x01,
.rc_interval = 100,
.rc_key_map = dvico_mce_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys),
.rc_query = cxusb_bluebird2_rc_query,
.num_device_descs = 1,
.devices = {
{ "DViCO FusionHDTV DVB-T Dual Digital 4",
{ NULL },
{ &cxusb_table[13], NULL },
},
}
};
static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2,
.identify_state = bluebird_fx2_identify_state,
.size_of_priv = sizeof(struct cxusb_state),
.num_adapters = 1,
.adapter = {
{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_nano2_frontend_attach,
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
.count = 5,
.endpoint = 0x02,
.u = {
.bulk = {
.buffersize = 8192,
}
}
},
},
},
.power_ctrl = cxusb_nano2_power_ctrl,
.i2c_algo = &cxusb_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x01,
.rc_interval = 100,
.rc_key_map = dvico_portable_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
.rc_query = cxusb_bluebird2_rc_query,
.num_device_descs = 1,
.devices = {
{ "DViCO FusionHDTV DVB-T NANO2",
{ NULL },
{ &cxusb_table[14], NULL },
},
}
};
static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-bluebird-02.fw",
.download_firmware = bluebird_patch_dvico_firmware_download,
.identify_state = bluebird_fx2_identify_state,
.size_of_priv = sizeof(struct cxusb_state),
.num_adapters = 1,
.adapter = {
{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_nano2_frontend_attach,
.tuner_attach = cxusb_dvico_xc3028_tuner_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
.count = 5,
.endpoint = 0x02,
.u = {
.bulk = {
.buffersize = 8192,
}
}
},
},
},
.power_ctrl = cxusb_nano2_power_ctrl,
.i2c_algo = &cxusb_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x01,
.rc_interval = 100,
.rc_key_map = dvico_portable_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dvico_portable_rc_keys),
.rc_query = cxusb_rc_query,
.num_device_descs = 1,
.devices = {
{ "DViCO FusionHDTV DVB-T NANO2 w/o firmware",
{ &cxusb_table[14], NULL },
{ &cxusb_table[15], NULL },
},
}
};
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,

View File

@ -4,12 +4,9 @@
#define DVB_USB_LOG_PREFIX "cxusb"
#include "dvb-usb.h"
extern int dvb_usb_cxusb_debug;
#define deb_info(args...) dprintk(dvb_usb_cxusb_debug,0x01,args)
#define deb_i2c(args...) if (d->udev->descriptor.idVendor == USB_VID_MEDION) \
dprintk(dvb_usb_cxusb_debug,0x01,args)
/* usb commands - some of it are guesses, don't have a reference yet */
#define CMD_BLUEBIRD_GPIO_RW 0x05
#define CMD_I2C_WRITE 0x08
#define CMD_I2C_READ 0x09

View File

@ -243,7 +243,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
u8 b[4];
b[0] = REQUEST_ENABLE_VIDEO;
b[1] = 0x00;
b[1] = (onoff << 4) | 0x00; /* this bit gives a kind of command, rather than enabling something or not */
b[2] = (0x01 << 4); /* Master mode */
b[3] = 0x00;
@ -256,9 +256,6 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
b[2] |= st->channel_state;
if (st->channel_state) /* if at least one channel is active */
b[1] = (0x01 << 4) | 0x00;
deb_info("data for streaming: %x %x\n",b[1],b[2]);
return dib0700_ctrl_wr(adap->dev, b, 4);

View File

@ -94,12 +94,28 @@ static int bristol_frontend_attach(struct dvb_usb_adapter *adap)
(10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0;
}
static int eeprom_read(struct i2c_adapter *adap,u8 adrs,u8 *pval)
{
struct i2c_msg msg[2] = {
{ .addr = 0x50, .flags = 0, .buf = &adrs, .len = 1 },
{ .addr = 0x50, .flags = I2C_M_RD, .buf = pval, .len = 1 },
};
if (i2c_transfer(adap, msg, 2) != 2) return -EREMOTEIO;
return 0;
}
static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
return dvb_attach(mt2060_attach,adap->fe, tun_i2c, &bristol_mt2060_config[adap->id],
st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0;
s8 a;
int if1=1220;
if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE &&
adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_500_2) {
if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a;
}
return dvb_attach(mt2060_attach,adap->fe, tun_i2c,&bristol_mt2060_config[adap->id],
if1) == NULL ? -ENODEV : 0;
}
/* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */
@ -230,6 +246,27 @@ static struct mt2266_config stk7700d_mt2266_config[2] = {
}
};
static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
{
if (adap->id == 0) {
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10);
dib7000p_i2c_enumeration(&adap->dev->i2c_adap,1,18,stk7700d_dib7000p_mt2266_config);
}
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
&stk7700d_dib7000p_mt2266_config[adap->id]);
return adap->fe == NULL ? -ENODEV : 0;
}
static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
{
if (adap->id == 0) {
@ -415,6 +452,35 @@ static struct dvb_usb_rc_key dib0700_rc_keys[] = {
{ 0x1e, 0x38, KEY_YELLOW },
{ 0x1e, 0x3b, KEY_GOTO },
{ 0x1e, 0x3d, KEY_POWER },
/* Key codes for the Leadtek Winfast DTV Dongle */
{ 0x00, 0x42, KEY_POWER },
{ 0x07, 0x7c, KEY_TUNER },
{ 0x0f, 0x4e, KEY_PRINT }, /* PREVIEW */
{ 0x08, 0x40, KEY_SCREEN }, /* full screen toggle*/
{ 0x0f, 0x71, KEY_DOT }, /* frequency */
{ 0x07, 0x43, KEY_0 },
{ 0x0c, 0x41, KEY_1 },
{ 0x04, 0x43, KEY_2 },
{ 0x0b, 0x7f, KEY_3 },
{ 0x0e, 0x41, KEY_4 },
{ 0x06, 0x43, KEY_5 },
{ 0x09, 0x7f, KEY_6 },
{ 0x0d, 0x7e, KEY_7 },
{ 0x05, 0x7c, KEY_8 },
{ 0x0a, 0x40, KEY_9 },
{ 0x0e, 0x4e, KEY_CLEAR },
{ 0x04, 0x7c, KEY_CHANNEL }, /* show channel number */
{ 0x0f, 0x41, KEY_LAST }, /* recall */
{ 0x03, 0x42, KEY_MUTE },
{ 0x06, 0x4c, KEY_RESERVED }, /* PIP button*/
{ 0x01, 0x72, KEY_SHUFFLE }, /* SNAPSHOT */
{ 0x0c, 0x4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
{ 0x0b, 0x70, KEY_RECORD },
{ 0x03, 0x7d, KEY_VOLUMEUP },
{ 0x01, 0x7d, KEY_VOLUMEDOWN },
{ 0x02, 0x42, KEY_CHANNELUP },
{ 0x00, 0x7d, KEY_CHANNELDOWN },
};
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
@ -578,16 +644,22 @@ static struct mt2060_config stk7700p_mt2060_config = {
static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
struct dib0700_state *st = adap->dev->priv;
struct i2c_adapter *tun_i2c;
s8 a;
int if1=1220;
if (adap->dev->udev->descriptor.idVendor == USB_VID_HAUPPAUGE &&
adap->dev->udev->descriptor.idProduct == USB_PID_HAUPPAUGE_NOVA_T_STICK) {
if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
}
if (st->is_dib7000pc)
tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
else
tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
if1) == NULL ? -ENODEV : 0;
}
/* DIB7070 generic */
@ -709,6 +781,8 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
.agc_config_count = 1,
.agc = &dib7070_agc_config,
.bw = &dib7070_bw_config_12_mhz,
.tuner_is_baseband = 1,
.spur_protect = 1,
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
@ -748,6 +822,8 @@ static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
.agc_config_count = 1,
.agc = &dib7070_agc_config,
.bw = &dib7070_bw_config_12_mhz,
.tuner_is_baseband = 1,
.spur_protect = 1,
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
@ -760,6 +836,8 @@ static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
.agc_config_count = 1,
.agc = &dib7070_agc_config,
.bw = &dib7070_bw_config_12_mhz,
.tuner_is_baseband = 1,
.spur_protect = 1,
.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
@ -821,6 +899,12 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500_PC) },
/* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) },
{ USB_DEVICE(USB_VID_GIGABYTE, USB_PID_GIGABYTE_U7000) },
{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
{ USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3000) },
{ USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100) },
/* 25 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
{ 0 } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@ -862,7 +946,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
.num_device_descs = 7,
.num_device_descs = 8,
.devices = {
{ "DiBcom STK7700P reference design",
{ &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] },
@ -891,6 +975,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "AVerMedia AVerTV DVB-T Express",
{ &dib0700_usb_id_table[20] },
{ NULL },
},
{ "Gigabyte U7000",
{ &dib0700_usb_id_table[21], NULL },
{ NULL },
}
},
@ -961,7 +1049,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "DiBcom STK7700D reference design",
{ &dib0700_usb_id_table[14], NULL },
{ NULL },
},
}
},
.rc_interval = DEFAULT_RC_INTERVAL,
@ -969,6 +1057,25 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
.rc_query = dib0700_rc_query
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 1,
.adapter = {
{
.frontend_attach = stk7700P2_frontend_attach,
.tuner_attach = stk7700d_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
},
},
.num_device_descs = 1,
.devices = {
{ "ASUS My Cinema U3000 Mini DVBT Tuner",
{ &dib0700_usb_id_table[23], NULL },
{ NULL },
},
}
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 1,
@ -983,7 +1090,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
},
},
.num_device_descs = 2,
.num_device_descs = 6,
.devices = {
{ "DiBcom STK7070P reference design",
{ &dib0700_usb_id_table[15], NULL },
@ -993,7 +1100,29 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[16], NULL },
{ NULL },
},
}
{ "Artec T14BR DVB-T",
{ &dib0700_usb_id_table[22], NULL },
{ NULL },
},
{ "ASUS My Cinema U3100 Mini DVBT Tuner",
{ &dib0700_usb_id_table[24], NULL },
{ NULL },
},
{ "Hauppauge Nova-T Stick",
{ &dib0700_usb_id_table[25], NULL },
{ NULL },
},
{ "Hauppauge Nova-T MyTV.t",
{ &dib0700_usb_id_table[26], NULL },
{ NULL },
},
},
.rc_interval = DEFAULT_RC_INTERVAL,
.rc_key_map = dib0700_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
.rc_query = dib0700_rc_query
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 2,
@ -1024,7 +1153,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "Pinnacle PCTV Dual DVB-T Diversity Stick",
{ &dib0700_usb_id_table[18], NULL },
{ NULL },
},
}
}
},
};

View File

@ -17,9 +17,10 @@
#include "nxt6000.h"
/* debug */
int dvb_usb_digitv_debug;
static int dvb_usb_digitv_debug;
module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
#define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
static int digitv_ctrl_msg(struct dvb_usb_device *d,
u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)

View File

@ -8,9 +8,6 @@ struct digitv_state {
int is_nxt6000;
};
extern int dvb_usb_digitv_debug;
#define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
/* protocol (from usblogging and the SDK:
*
* Always 7 bytes bulk message(s) for controlling

View File

@ -15,7 +15,9 @@
#define USB_VID_ALCOR_MICRO 0x058f
#define USB_VID_ALINK 0x05e3
#define USB_VID_ANCHOR 0x0547
#define USB_VID_ANSONIC 0x10b9
#define USB_VID_ANUBIS_ELECTRONIC 0x10fd
#define USB_VID_ASUS 0x0b05
#define USB_VID_AVERMEDIA 0x07ca
#define USB_VID_COMPRO 0x185b
#define USB_VID_COMPRO_UNK 0x145f
@ -44,12 +46,16 @@
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
#define USB_VID_UNIWILL 0x1584
#define USB_VID_WIDEVIEW 0x14aa
/* dom : pour gigabyte u7000 */
#define USB_VID_GIGABYTE 0x1044
/* Product IDs */
#define USB_PID_ADSTECH_USB2_COLD 0xa333
#define USB_PID_ADSTECH_USB2_WARM 0xa334
#define USB_PID_AFATECH_AF9005 0x9020
#define USB_VID_ALINK_DTU 0xf170
#define USB_PID_ANSONIC_DVBT_USB 0x6000
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
@ -69,6 +75,7 @@
#define USB_PID_DIBCOM_STK7700P 0x1e14
#define USB_PID_DIBCOM_STK7700P_PC 0x1e78
#define USB_PID_DIBCOM_STK7700D 0x1ef0
#define USB_PID_DIBCOM_STK7700_U7000 0x7001
#define USB_PID_DIBCOM_STK7070P 0x1ebc
#define USB_PID_DIBCOM_STK7070PD 0x1ebe
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
@ -99,6 +106,7 @@
#define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a
#define USB_PID_ARTEC_T14_COLD 0x810b
#define USB_PID_ARTEC_T14_WARM 0x810c
#define USB_PID_ARTEC_T14BR 0x810f
#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
@ -120,6 +128,8 @@
#define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950
#define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_3 0x7070
#define USB_PID_HAUPPAUGE_MYTV_T 0x7080
#define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580
#define USB_PID_AVERMEDIA_EXPRESS 0xb568
#define USB_PID_AVERMEDIA_VOLAR 0xa807
@ -143,6 +153,9 @@
#define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59
#define USB_PID_DVICO_BLUEBIRD_DUAL_4 0xdb78
#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2 0xdb70
#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM 0xdb71
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55
#define USB_PID_MEDION_MD95700 0x0932
@ -170,6 +183,9 @@
#define USB_PID_OPERA1_WARM 0x3829
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD 0x0514
#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM 0x0513
/* dom pour gigabyte u7000 */
#define USB_PID_GIGABYTE_U7000 0x7001
#define USB_PID_ASUS_U3000 0x171f
#define USB_PID_ASUS_U3100 0x173f
#endif

View File

@ -56,12 +56,12 @@ static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
if (num > 2)
return -EINVAL;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
for (i = 0; i < num; i++) {
/* write/read request */
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {

View File

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

View File

@ -92,6 +92,5 @@ extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
u16 index, u8 *b, int blen);
extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d);
#endif

View File

@ -10,7 +10,9 @@
* see Documentation/dvb/README.dvb-usb for more information
*/
#include "opera1.h"
#define DVB_USB_LOG_PREFIX "opera"
#include "dvb-usb.h"
#include "stv0299.h"
#define OPERA_READ_MSG 0
@ -38,7 +40,7 @@ struct opera_rc_keys {
u32 event;
};
int dvb_usb_opera1_debug;
static int dvb_usb_opera1_debug;
module_param_named(debug, dvb_usb_opera1_debug, int, 0644);
MODULE_PARM_DESC(debug,
"set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."

View File

@ -1,9 +0,0 @@
#ifndef _OPERA1_H_
#define _OPERA1_H_
#define DVB_USB_LOG_PREFIX "opera"
#include "dvb-usb.h"
extern int dvb_usb_opera1_debug;
#define deb_xfer(args...) dprintk(dvb_usb_opera1_debug,0x02,args)
#endif

View File

@ -56,7 +56,7 @@ int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8
return ret;
}
int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
u16 index, u8 *b, int blen)
{
int ret;
@ -204,19 +204,6 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
return 0;
}
int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff)
{
struct vp702x_device_state *st = d->priv;
if (st->power_state == 0 && onoff)
vp702x_usb_out_op(d, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
else if (st->power_state == 1 && onoff == 0)
vp702x_usb_out_op(d, SET_TUNER_POWER_REQ, 0, 7, NULL, 0);
st->power_state = onoff;
return 0;
}
static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
{

View File

@ -102,7 +102,5 @@ extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
extern int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff);
#endif

View File

@ -15,9 +15,12 @@
#include "vp7045.h"
/* debug */
int dvb_usb_vp7045_debug;
static int dvb_usb_vp7045_debug;
module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
#define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args)
int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
{

View File

@ -17,11 +17,6 @@
#define DVB_USB_LOG_PREFIX "vp7045"
#include "dvb-usb.h"
extern int dvb_usb_vp7045_debug;
#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
#define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args)
/* vp7045 commands */
/* Twinhan Vendor requests */

View File

@ -316,6 +316,13 @@ config DVB_TDA827X
help
A DVB-T silicon tuner module. Say Y when you want to support this tuner.
config DVB_TDA18271
tristate "NXP TDA18271 silicon tuner"
depends on I2C
default m if DVB_FE_CUSTOMISE
help
A silicon tuner module. Say Y when you want to support this tuner.
config DVB_TUNER_QT1010
tristate "Quantek QT1010 silicon tuner"
depends on DVB_CORE && I2C
@ -353,6 +360,15 @@ config DVB_TUNER_DIB0070
This device is only used inside a SiP called togther with a
demodulator for now.
config DVB_TUNER_XC5000
tristate "Xceive XC5000 silicon tuner"
depends on I2C
default m if DVB_FE_CUSTOMISE
help
A driver for the silicon tuner XC5000 from Xceive.
This device is only used inside a SiP called togther with a
demodulator for now.
comment "Miscellaneous devices"
depends on DVB_CORE

View File

@ -3,6 +3,9 @@
#
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
EXTRA_CFLAGS += -Idrivers/media/video/
tda18271-objs := tda18271-tables.o tda18271-common.o tda18271-fe.o
obj-$(CONFIG_DVB_PLL) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o
@ -39,6 +42,7 @@ obj-$(CONFIG_DVB_ISL6421) += isl6421.o
obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
obj-$(CONFIG_DVB_TDA827X) += tda827x.o
obj-$(CONFIG_DVB_TDA18271) += tda18271.o
obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o
obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
@ -46,3 +50,4 @@ obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o

View File

@ -434,9 +434,14 @@ static u16 dib0070_p1f_defaults[] =
0,
};
static void dib0070_wbd_calibration(struct dib0070_state *state)
static void dib0070_wbd_calibration(struct dvb_frontend *fe)
{
u16 wbd_offs;
struct dib0070_state *state = fe->tuner_priv;
if (state->cfg->sleep)
state->cfg->sleep(fe, 0);
dib0070_write_reg(state, 0x0f, 0x6d81);
dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
msleep(9);
@ -444,6 +449,10 @@ static void dib0070_wbd_calibration(struct dib0070_state *state)
dib0070_write_reg(state, 0x20, 0);
state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2);
dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset);
if (state->cfg->sleep)
state->cfg->sleep(fe, 1);
}
u16 dib0070_wbd_offset(struct dvb_frontend *fe)
@ -560,7 +569,7 @@ struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
if (dib0070_reset(state) != 0)
goto free_mem;
dib0070_wbd_calibration(state);
dib0070_wbd_calibration(fe);
printk(KERN_INFO "DiB0070: successfully identified\n");
memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));

View File

@ -684,6 +684,9 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct dib3000mc_state *state = fe->demodulator_priv;
int ret;
dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
state->current_bandwidth = fep->u.ofdm.bandwidth;
dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
@ -700,7 +703,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ||
fep->u.ofdm.constellation == QAM_AUTO ||
fep->u.ofdm.code_rate_HP == FEC_AUTO) {
int i = 100, found;
int i = 1000, found;
dib3000mc_autosearch_start(fe, fep);
do {
@ -715,10 +718,11 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
dib3000mc_get_frontend(fe, fep);
}
ret = dib3000mc_tune(fe, fep);
/* make this a config parameter */
dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
return dib3000mc_tune(fe, fep);
return ret;
}
static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)

View File

@ -1171,7 +1171,9 @@ static int dib7000m_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct dib7000m_state *state = fe->demodulator_priv;
int time;
int time, ret;
dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
state->current_bandwidth = fep->u.ofdm.bandwidth;
dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
@ -1206,10 +1208,11 @@ static int dib7000m_set_frontend(struct dvb_frontend* fe,
dib7000m_get_frontend(fe, fep);
}
ret = dib7000m_tune(fe, fep);
/* make this a config parameter */
dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
return dib7000m_tune(fe, fep);
return ret;
}
static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)

View File

@ -35,8 +35,8 @@ struct dib7000p_state {
u16 wbd_ref;
u8 current_band;
fe_bandwidth_t current_bandwidth;
u8 current_band;
u32 current_bandwidth;
struct dibx000_agc_config *current_agc;
u32 timf;
@ -1074,7 +1074,7 @@ static int dib7000p_get_frontend(struct dvb_frontend* fe,
fep->inversion = INVERSION_AUTO;
fep->u.ofdm.bandwidth = state->current_bandwidth;
fep->u.ofdm.bandwidth = BANDWIDTH_TO_INDEX(state->current_bandwidth);
switch ((tps >> 8) & 0x3) {
case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
@ -1128,12 +1128,11 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
struct dib7000p_state *state = fe->demodulator_priv;
int time;
int time, ret;
state->current_bandwidth = fep->u.ofdm.bandwidth;
dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->u.ofdm.bandwidth));
dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
/* maybe the parameter has been changed */
/* maybe the parameter has been changed */
state->sfn_workaround_active = buggy_sfn_workaround;
if (fe->ops.tuner_ops.set_params)
@ -1166,10 +1165,11 @@ static int dib7000p_set_frontend(struct dvb_frontend* fe,
dib7000p_get_frontend(fe, fep);
}
ret = dib7000p_tune(fe, fep);
/* make this a config parameter */
dib7000p_set_output_mode(state, OUTMODE_MPEG2_FIFO);
return dib7000p_tune(fe, fep);
return ret;
}
static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat)

View File

@ -128,6 +128,11 @@ enum dibx000_adc_states {
(v) == BANDWIDTH_7_MHZ ? 7000 : \
(v) == BANDWIDTH_6_MHZ ? 6000 : 8000 )
#define BANDWIDTH_TO_INDEX(v) ( \
(v) == 8000 ? BANDWIDTH_8_MHZ : \
(v) == 7000 ? BANDWIDTH_7_MHZ : \
(v) == 6000 ? BANDWIDTH_6_MHZ : BANDWIDTH_8_MHZ )
/* Chip output mode. */
#define OUTMODE_HIGH_Z 0
#define OUTMODE_MPEG2_PAR_GATED_CLK 1

View File

@ -38,8 +38,12 @@ struct mt2266_priv {
u32 frequency;
u32 bandwidth;
u8 band;
};
#define MT2266_VHF 1
#define MT2266_UHF 0
/* Here, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
static int debug;
@ -90,26 +94,30 @@ static int mt2266_writeregs(struct mt2266_priv *priv,u8 *buf, u8 len)
}
// Initialisation sequences
static u8 mt2266_init1[] = {
REG_TUNE,
0x00, 0x00, 0x28, 0x00, 0x52, 0x99, 0x3f };
static u8 mt2266_init1[] = { REG_TUNE, 0x00, 0x00, 0x28,
0x00, 0x52, 0x99, 0x3f };
static u8 mt2266_init2[] = {
0x17, 0x6d, 0x71, 0x61, 0xc0, 0xbf, 0xff, 0xdc, 0x00, 0x0a,
0xd4, 0x03, 0x64, 0x64, 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x7f, 0x5e, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x77, 0x0f, 0x2d };
0x17, 0x6d, 0x71, 0x61, 0xc0, 0xbf, 0xff, 0xdc, 0x00, 0x0a, 0xd4,
0x03, 0x64, 0x64, 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7f, 0x5e, 0x3f, 0xff, 0xff,
0xff, 0x00, 0x77, 0x0f, 0x2d
};
static u8 mt2266_init_8mhz[] = {
REG_BANDWIDTH,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 };
static u8 mt2266_init_8mhz[] = { REG_BANDWIDTH, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22 };
static u8 mt2266_init_7mhz[] = {
REG_BANDWIDTH,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32 };
static u8 mt2266_init_7mhz[] = { REG_BANDWIDTH, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32 };
static u8 mt2266_init_6mhz[] = {
REG_BANDWIDTH,
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7 };
static u8 mt2266_init_6mhz[] = { REG_BANDWIDTH, 0xa7, 0xa7, 0xa7, 0xa7,
0xa7, 0xa7, 0xa7, 0xa7 };
static u8 mt2266_uhf[] = { 0x1d, 0xdc, 0x00, 0x0a, 0xd4, 0x03, 0x64, 0x64,
0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14 };
static u8 mt2266_vhf[] = { 0x1d, 0xfe, 0x00, 0x00, 0xb4, 0x03, 0xa5, 0xa5,
0xa5, 0xa5, 0x82, 0xaa, 0xf1, 0x17, 0x80, 0x1f };
#define FREF 30000 // Quartz oscillator 30 MHz
@ -122,35 +130,78 @@ static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
u8 lnaband;
u8 b[10];
int i;
u8 band;
priv = fe->tuner_priv;
mt2266_writereg(priv,0x17,0x6d);
mt2266_writereg(priv,0x1c,0xff);
freq = params->frequency / 1000; // Hz -> kHz
if (freq < 470000 && freq > 230000)
return -EINVAL; /* Gap between VHF and UHF bands */
priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
priv->frequency = freq * 1000;
tune=2 * freq * (8192/16) / (FREF/16);
if (freq <= 495000) lnaband = 0xEE; else
if (freq <= 525000) lnaband = 0xDD; else
if (freq <= 550000) lnaband = 0xCC; else
if (freq <= 580000) lnaband = 0xBB; else
if (freq <= 605000) lnaband = 0xAA; else
if (freq <= 630000) lnaband = 0x99; else
if (freq <= 655000) lnaband = 0x88; else
if (freq <= 685000) lnaband = 0x77; else
if (freq <= 710000) lnaband = 0x66; else
if (freq <= 735000) lnaband = 0x55; else
if (freq <= 765000) lnaband = 0x44; else
if (freq <= 802000) lnaband = 0x33; else
if (freq <= 840000) lnaband = 0x22; else lnaband = 0x11;
tune = 2 * freq * (8192/16) / (FREF/16);
band = (freq < 300000) ? MT2266_VHF : MT2266_UHF;
if (band == MT2266_VHF)
tune *= 2;
msleep(100);
mt2266_writeregs(priv,(params->u.ofdm.bandwidth==BANDWIDTH_6_MHZ)?mt2266_init_6mhz:
(params->u.ofdm.bandwidth==BANDWIDTH_7_MHZ)?mt2266_init_7mhz:
mt2266_init_8mhz,sizeof(mt2266_init_8mhz));
switch (params->u.ofdm.bandwidth) {
case BANDWIDTH_6_MHZ:
mt2266_writeregs(priv, mt2266_init_6mhz,
sizeof(mt2266_init_6mhz));
break;
case BANDWIDTH_7_MHZ:
mt2266_writeregs(priv, mt2266_init_7mhz,
sizeof(mt2266_init_7mhz));
break;
case BANDWIDTH_8_MHZ:
default:
mt2266_writeregs(priv, mt2266_init_8mhz,
sizeof(mt2266_init_8mhz));
break;
}
if (band == MT2266_VHF && priv->band == MT2266_UHF) {
dprintk("Switch from UHF to VHF");
mt2266_writereg(priv, 0x05, 0x04);
mt2266_writereg(priv, 0x19, 0x61);
mt2266_writeregs(priv, mt2266_vhf, sizeof(mt2266_vhf));
} else if (band == MT2266_UHF && priv->band == MT2266_VHF) {
dprintk("Switch from VHF to UHF");
mt2266_writereg(priv, 0x05, 0x52);
mt2266_writereg(priv, 0x19, 0x61);
mt2266_writeregs(priv, mt2266_uhf, sizeof(mt2266_uhf));
}
msleep(10);
if (freq <= 495000)
lnaband = 0xEE;
else if (freq <= 525000)
lnaband = 0xDD;
else if (freq <= 550000)
lnaband = 0xCC;
else if (freq <= 580000)
lnaband = 0xBB;
else if (freq <= 605000)
lnaband = 0xAA;
else if (freq <= 630000)
lnaband = 0x99;
else if (freq <= 655000)
lnaband = 0x88;
else if (freq <= 685000)
lnaband = 0x77;
else if (freq <= 710000)
lnaband = 0x66;
else if (freq <= 735000)
lnaband = 0x55;
else if (freq <= 765000)
lnaband = 0x44;
else if (freq <= 802000)
lnaband = 0x33;
else if (freq <= 840000)
lnaband = 0x22;
else
lnaband = 0x11;
b[0] = REG_TUNE;
b[1] = (tune >> 8) & 0x1F;
@ -158,47 +209,54 @@ static int mt2266_set_params(struct dvb_frontend *fe, struct dvb_frontend_parame
b[3] = tune >> 13;
mt2266_writeregs(priv,b,4);
dprintk("set_parms: tune=%d band=%d",(int)tune,(int)lnaband);
dprintk("set_parms: [1..3]: %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3]);
dprintk("set_parms: tune=%d band=%d %s",
(int) tune, (int) lnaband,
(band == MT2266_UHF) ? "UHF" : "VHF");
dprintk("set_parms: [1..3]: %2x %2x %2x",
(int) b[1], (int) b[2], (int)b[3]);
b[0] = 0x05;
b[1] = 0x62;
b[2] = lnaband;
mt2266_writeregs(priv,b,3);
if (band == MT2266_UHF) {
b[0] = 0x05;
b[1] = (priv->band == MT2266_VHF) ? 0x52 : 0x62;
b[2] = lnaband;
mt2266_writeregs(priv, b, 3);
}
//Waits for pll lock or timeout
/* Wait for pll lock or timeout */
i = 0;
do {
mt2266_readreg(priv,REG_LOCK,b);
if ((b[0] & 0x40)==0x40)
if (b[0] & 0x40)
break;
msleep(10);
i++;
} while (i<10);
dprintk("Lock when i=%i",(int)i);
if (band == MT2266_UHF && priv->band == MT2266_VHF)
mt2266_writereg(priv, 0x05, 0x62);
priv->band = band;
return ret;
}
static void mt2266_calibrate(struct mt2266_priv *priv)
{
mt2266_writereg(priv,0x11,0x03);
mt2266_writereg(priv,0x11,0x01);
mt2266_writeregs(priv,mt2266_init1,sizeof(mt2266_init1));
mt2266_writeregs(priv,mt2266_init2,sizeof(mt2266_init2));
mt2266_writereg(priv,0x33,0x5e);
mt2266_writereg(priv,0x10,0x10);
mt2266_writereg(priv,0x10,0x00);
mt2266_writeregs(priv,mt2266_init_8mhz,sizeof(mt2266_init_8mhz));
mt2266_writereg(priv, 0x11, 0x03);
mt2266_writereg(priv, 0x11, 0x01);
mt2266_writeregs(priv, mt2266_init1, sizeof(mt2266_init1));
mt2266_writeregs(priv, mt2266_init2, sizeof(mt2266_init2));
mt2266_writereg(priv, 0x33, 0x5e);
mt2266_writereg(priv, 0x10, 0x10);
mt2266_writereg(priv, 0x10, 0x00);
mt2266_writeregs(priv, mt2266_init_8mhz, sizeof(mt2266_init_8mhz));
msleep(25);
mt2266_writereg(priv,0x17,0x6d);
mt2266_writereg(priv,0x1c,0x00);
mt2266_writereg(priv, 0x17, 0x6d);
mt2266_writereg(priv, 0x1c, 0x00);
msleep(75);
mt2266_writereg(priv,0x17,0x6d);
mt2266_writereg(priv,0x1c,0xff);
mt2266_writereg(priv, 0x17, 0x6d);
mt2266_writereg(priv, 0x1c, 0xff);
}
static int mt2266_get_frequency(struct dvb_frontend *fe, u32 *frequency)
@ -217,17 +275,22 @@ static int mt2266_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
static int mt2266_init(struct dvb_frontend *fe)
{
int ret;
struct mt2266_priv *priv = fe->tuner_priv;
mt2266_writereg(priv,0x17,0x6d);
mt2266_writereg(priv,0x1c,0xff);
ret = mt2266_writereg(priv, 0x17, 0x6d);
if (ret < 0)
return ret;
ret = mt2266_writereg(priv, 0x1c, 0xff);
if (ret < 0)
return ret;
return 0;
}
static int mt2266_sleep(struct dvb_frontend *fe)
{
struct mt2266_priv *priv = fe->tuner_priv;
mt2266_writereg(priv,0x17,0x6d);
mt2266_writereg(priv,0x1c,0x00);
mt2266_writereg(priv, 0x17, 0x6d);
mt2266_writereg(priv, 0x1c, 0x00);
return 0;
}
@ -241,8 +304,8 @@ static int mt2266_release(struct dvb_frontend *fe)
static const struct dvb_tuner_ops mt2266_tuner_ops = {
.info = {
.name = "Microtune MT2266",
.frequency_min = 470000000,
.frequency_max = 860000000,
.frequency_min = 174000000,
.frequency_max = 862000000,
.frequency_step = 50000,
},
.release = mt2266_release,
@ -264,8 +327,9 @@ struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter
priv->cfg = cfg;
priv->i2c = i2c;
priv->band = MT2266_UHF;
if (mt2266_readreg(priv,0,&id) != 0) {
if (mt2266_readreg(priv, 0, &id)) {
kfree(priv);
return NULL;
}

View File

@ -37,9 +37,9 @@
struct mt312_state {
struct i2c_adapter* i2c;
struct i2c_adapter *i2c;
/* configuration settings */
const struct mt312_config* config;
const struct mt312_config *config;
struct dvb_frontend frontend;
u8 id;
@ -49,14 +49,15 @@ struct mt312_state {
static int debug;
#define dprintk(args...) \
do { \
if (debug) printk(KERN_DEBUG "mt312: " args); \
if (debug) \
printk(KERN_DEBUG "mt312: " args); \
} while (0)
#define MT312_SYS_CLK 90000000UL /* 90 MHz */
#define MT312_LPOWER_SYS_CLK 60000000UL /* 60 MHz */
#define MT312_PLL_CLK 10000000UL /* 10 MHz */
static int mt312_read(struct mt312_state* state, const enum mt312_reg_addr reg,
static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
void *buf, const size_t count)
{
int ret;
@ -79,7 +80,7 @@ static int mt312_read(struct mt312_state* state, const enum mt312_reg_addr reg,
return -EREMOTEIO;
}
if(debug) {
if (debug) {
int i;
dprintk("R(%d):", reg & 0x7f);
for (i = 0; i < count; i++)
@ -90,14 +91,14 @@ static int mt312_read(struct mt312_state* state, const enum mt312_reg_addr reg,
return 0;
}
static int mt312_write(struct mt312_state* state, const enum mt312_reg_addr reg,
static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
const void *src, const size_t count)
{
int ret;
u8 buf[count + 1];
struct i2c_msg msg;
if(debug) {
if (debug) {
int i;
dprintk("W(%d):", reg & 0x7f);
for (i = 0; i < count; i++)
@ -123,13 +124,13 @@ static int mt312_write(struct mt312_state* state, const enum mt312_reg_addr reg,
return 0;
}
static inline int mt312_readreg(struct mt312_state* state,
static inline int mt312_readreg(struct mt312_state *state,
const enum mt312_reg_addr reg, u8 *val)
{
return mt312_read(state, reg, val, 1);
}
static inline int mt312_writereg(struct mt312_state* state,
static inline int mt312_writereg(struct mt312_state *state,
const enum mt312_reg_addr reg, const u8 val)
{
return mt312_write(state, reg, &val, 1);
@ -140,18 +141,19 @@ static inline u32 mt312_div(u32 a, u32 b)
return (a + (b / 2)) / b;
}
static int mt312_reset(struct mt312_state* state, const u8 full)
static int mt312_reset(struct mt312_state *state, const u8 full)
{
return mt312_writereg(state, RESET, full ? 0x80 : 0x40);
}
static int mt312_get_inversion(struct mt312_state* state,
static int mt312_get_inversion(struct mt312_state *state,
fe_spectral_inversion_t *i)
{
int ret;
u8 vit_mode;
if ((ret = mt312_readreg(state, VIT_MODE, &vit_mode)) < 0)
ret = mt312_readreg(state, VIT_MODE, &vit_mode);
if (ret < 0)
return ret;
if (vit_mode & 0x80) /* auto inversion was used */
@ -160,7 +162,7 @@ static int mt312_get_inversion(struct mt312_state* state,
return 0;
}
static int mt312_get_symbol_rate(struct mt312_state* state, u32 *sr)
static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
{
int ret;
u8 sym_rate_h;
@ -169,37 +171,44 @@ static int mt312_get_symbol_rate(struct mt312_state* state, u32 *sr)
u16 monitor;
u8 buf[2];
if ((ret = mt312_readreg(state, SYM_RATE_H, &sym_rate_h)) < 0)
ret = mt312_readreg(state, SYM_RATE_H, &sym_rate_h);
if (ret < 0)
return ret;
if (sym_rate_h & 0x80) { /* symbol rate search was used */
if ((ret = mt312_writereg(state, MON_CTRL, 0x03)) < 0)
if (sym_rate_h & 0x80) {
/* symbol rate search was used */
ret = mt312_writereg(state, MON_CTRL, 0x03);
if (ret < 0)
return ret;
if ((ret = mt312_read(state, MONITOR_H, buf, sizeof(buf))) < 0)
ret = mt312_read(state, MONITOR_H, buf, sizeof(buf));
if (ret < 0)
return ret;
monitor = (buf[0] << 8) | buf[1];
dprintk(KERN_DEBUG "sr(auto) = %u\n",
dprintk("sr(auto) = %u\n",
mt312_div(monitor * 15625, 4));
} else {
if ((ret = mt312_writereg(state, MON_CTRL, 0x05)) < 0)
ret = mt312_writereg(state, MON_CTRL, 0x05);
if (ret < 0)
return ret;
if ((ret = mt312_read(state, MONITOR_H, buf, sizeof(buf))) < 0)
ret = mt312_read(state, MONITOR_H, buf, sizeof(buf));
if (ret < 0)
return ret;
dec_ratio = ((buf[0] >> 5) & 0x07) * 32;
if ((ret = mt312_read(state, SYM_RAT_OP_H, buf, sizeof(buf))) < 0)
ret = mt312_read(state, SYM_RAT_OP_H, buf, sizeof(buf));
if (ret < 0)
return ret;
sym_rat_op = (buf[0] << 8) | buf[1];
dprintk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n",
dprintk("sym_rat_op=%d dec_ratio=%d\n",
sym_rat_op, dec_ratio);
dprintk(KERN_DEBUG "*sr(manual) = %lu\n",
dprintk("*sr(manual) = %lu\n",
(((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) *
2) - dec_ratio);
}
@ -207,7 +216,7 @@ static int mt312_get_symbol_rate(struct mt312_state* state, u32 *sr)
return 0;
}
static int mt312_get_code_rate(struct mt312_state* state, fe_code_rate_t *cr)
static int mt312_get_code_rate(struct mt312_state *state, fe_code_rate_t *cr)
{
const fe_code_rate_t fec_tab[8] =
{ FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8,
@ -216,7 +225,8 @@ static int mt312_get_code_rate(struct mt312_state* state, fe_code_rate_t *cr)
int ret;
u8 fec_status;
if ((ret = mt312_readreg(state, FEC_STATUS, &fec_status)) < 0)
ret = mt312_readreg(state, FEC_STATUS, &fec_status);
if (ret < 0)
return ret;
*cr = fec_tab[(fec_status >> 4) & 0x07];
@ -224,61 +234,72 @@ static int mt312_get_code_rate(struct mt312_state* state, fe_code_rate_t *cr)
return 0;
}
static int mt312_initfe(struct dvb_frontend* fe)
static int mt312_initfe(struct dvb_frontend *fe)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[2];
/* wake up */
if ((ret = mt312_writereg(state, CONFIG, (state->frequency == 60 ? 0x88 : 0x8c))) < 0)
ret = mt312_writereg(state, CONFIG,
(state->frequency == 60 ? 0x88 : 0x8c));
if (ret < 0)
return ret;
/* wait at least 150 usec */
udelay(150);
/* full reset */
if ((ret = mt312_reset(state, 1)) < 0)
ret = mt312_reset(state, 1);
if (ret < 0)
return ret;
// Per datasheet, write correct values. 09/28/03 ACCJr.
// If we don't do this, we won't get FE_HAS_VITERBI in the VP310.
/* Per datasheet, write correct values. 09/28/03 ACCJr.
* If we don't do this, we won't get FE_HAS_VITERBI in the VP310. */
{
u8 buf_def[8]={0x14, 0x12, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00};
u8 buf_def[8] = { 0x14, 0x12, 0x03, 0x02,
0x01, 0x00, 0x00, 0x00 };
if ((ret = mt312_write(state, VIT_SETUP, buf_def, sizeof(buf_def))) < 0)
ret = mt312_write(state, VIT_SETUP, buf_def, sizeof(buf_def));
if (ret < 0)
return ret;
}
/* SYS_CLK */
buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK : MT312_SYS_CLK) * 2, 1000000);
buf[0] = mt312_div((state->frequency == 60 ? MT312_LPOWER_SYS_CLK :
MT312_SYS_CLK) * 2, 1000000);
/* DISEQC_RATIO */
buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4);
if ((ret = mt312_write(state, SYS_CLK, buf, sizeof(buf))) < 0)
ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
if (ret < 0)
return ret;
if ((ret = mt312_writereg(state, SNR_THS_HIGH, 0x32)) < 0)
ret = mt312_writereg(state, SNR_THS_HIGH, 0x32);
if (ret < 0)
return ret;
if ((ret = mt312_writereg(state, OP_CTRL, 0x53)) < 0)
ret = mt312_writereg(state, OP_CTRL, 0x53);
if (ret < 0)
return ret;
/* TS_SW_LIM */
buf[0] = 0x8c;
buf[1] = 0x98;
if ((ret = mt312_write(state, TS_SW_LIM_L, buf, sizeof(buf))) < 0)
ret = mt312_write(state, TS_SW_LIM_L, buf, sizeof(buf));
if (ret < 0)
return ret;
if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0)
ret = mt312_writereg(state, CS_SW_LIM, 0x69);
if (ret < 0)
return ret;
return 0;
}
static int mt312_send_master_cmd(struct dvb_frontend* fe,
static int mt312_send_master_cmd(struct dvb_frontend *fe,
struct dvb_diseqc_master_cmd *c)
{
struct mt312_state *state = fe->demodulator_priv;
@ -288,29 +309,31 @@ static int mt312_send_master_cmd(struct dvb_frontend* fe,
if ((c->msg_len == 0) || (c->msg_len > sizeof(c->msg)))
return -EINVAL;
if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0)
ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
if (ret < 0)
return ret;
if ((ret =
mt312_write(state, (0x80 | DISEQC_INSTR), c->msg, c->msg_len)) < 0)
ret = mt312_write(state, (0x80 | DISEQC_INSTR), c->msg, c->msg_len);
if (ret < 0)
return ret;
if ((ret =
mt312_writereg(state, DISEQC_MODE,
(diseqc_mode & 0x40) | ((c->msg_len - 1) << 3)
| 0x04)) < 0)
ret = mt312_writereg(state, DISEQC_MODE,
(diseqc_mode & 0x40) | ((c->msg_len - 1) << 3)
| 0x04);
if (ret < 0)
return ret;
/* set DISEQC_MODE[2:0] to zero if a return message is expected */
if (c->msg[0] & 0x02)
if ((ret =
mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40))) < 0)
if (c->msg[0] & 0x02) {
ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40));
if (ret < 0)
return ret;
}
return 0;
}
static int mt312_send_burst(struct dvb_frontend* fe, const fe_sec_mini_cmd_t c)
static int mt312_send_burst(struct dvb_frontend *fe, const fe_sec_mini_cmd_t c)
{
struct mt312_state *state = fe->demodulator_priv;
const u8 mini_tab[2] = { 0x02, 0x03 };
@ -321,18 +344,19 @@ static int mt312_send_burst(struct dvb_frontend* fe, const fe_sec_mini_cmd_t c)
if (c > SEC_MINI_B)
return -EINVAL;
if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0)
ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
if (ret < 0)
return ret;
if ((ret =
mt312_writereg(state, DISEQC_MODE,
(diseqc_mode & 0x40) | mini_tab[c])) < 0)
ret = mt312_writereg(state, DISEQC_MODE,
(diseqc_mode & 0x40) | mini_tab[c]);
if (ret < 0)
return ret;
return 0;
}
static int mt312_set_tone(struct dvb_frontend* fe, const fe_sec_tone_mode_t t)
static int mt312_set_tone(struct dvb_frontend *fe, const fe_sec_tone_mode_t t)
{
struct mt312_state *state = fe->demodulator_priv;
const u8 tone_tab[2] = { 0x01, 0x00 };
@ -343,18 +367,19 @@ static int mt312_set_tone(struct dvb_frontend* fe, const fe_sec_tone_mode_t t)
if (t > SEC_TONE_OFF)
return -EINVAL;
if ((ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode)) < 0)
ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
if (ret < 0)
return ret;
if ((ret =
mt312_writereg(state, DISEQC_MODE,
(diseqc_mode & 0x40) | tone_tab[t])) < 0)
ret = mt312_writereg(state, DISEQC_MODE,
(diseqc_mode & 0x40) | tone_tab[t]);
if (ret < 0)
return ret;
return 0;
}
static int mt312_set_voltage(struct dvb_frontend* fe, const fe_sec_voltage_t v)
static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
{
struct mt312_state *state = fe->demodulator_priv;
const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
@ -365,7 +390,7 @@ static int mt312_set_voltage(struct dvb_frontend* fe, const fe_sec_voltage_t v)
return mt312_writereg(state, DISEQC_MODE, volt_tab[v]);
}
static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s)
static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
@ -373,10 +398,12 @@ static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s)
*s = 0;
if ((ret = mt312_read(state, QPSK_STAT_H, status, sizeof(status))) < 0)
ret = mt312_read(state, QPSK_STAT_H, status, sizeof(status));
if (ret < 0)
return ret;
dprintk(KERN_DEBUG "QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x, FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]);
dprintk("QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x,"
" FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]);
if (status[0] & 0xc0)
*s |= FE_HAS_SIGNAL; /* signal noise ratio */
@ -392,13 +419,14 @@ static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s)
return 0;
}
static int mt312_read_ber(struct dvb_frontend* fe, u32 *ber)
static int mt312_read_ber(struct dvb_frontend *fe, u32 *ber)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[3];
if ((ret = mt312_read(state, RS_BERCNT_H, buf, 3)) < 0)
ret = mt312_read(state, RS_BERCNT_H, buf, 3);
if (ret < 0)
return ret;
*ber = ((buf[0] << 16) | (buf[1] << 8) | buf[2]) * 64;
@ -406,7 +434,8 @@ static int mt312_read_ber(struct dvb_frontend* fe, u32 *ber)
return 0;
}
static int mt312_read_signal_strength(struct dvb_frontend* fe, u16 *signal_strength)
static int mt312_read_signal_strength(struct dvb_frontend *fe,
u16 *signal_strength)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
@ -414,7 +443,8 @@ static int mt312_read_signal_strength(struct dvb_frontend* fe, u16 *signal_stren
u16 agc;
s16 err_db;
if ((ret = mt312_read(state, AGC_H, buf, sizeof(buf))) < 0)
ret = mt312_read(state, AGC_H, buf, sizeof(buf));
if (ret < 0)
return ret;
agc = (buf[0] << 6) | (buf[1] >> 2);
@ -422,18 +452,19 @@ static int mt312_read_signal_strength(struct dvb_frontend* fe, u16 *signal_stren
*signal_strength = agc;
dprintk(KERN_DEBUG "agc=%08x err_db=%hd\n", agc, err_db);
dprintk("agc=%08x err_db=%hd\n", agc, err_db);
return 0;
}
static int mt312_read_snr(struct dvb_frontend* fe, u16 *snr)
static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[2];
if ((ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf))) < 0)
ret = mt312_read(state, M_SNR_H, &buf, sizeof(buf));
if (ret < 0)
return ret;
*snr = 0xFFFF - ((((buf[0] & 0x7f) << 8) | buf[1]) << 1);
@ -441,13 +472,14 @@ static int mt312_read_snr(struct dvb_frontend* fe, u16 *snr)
return 0;
}
static int mt312_read_ucblocks(struct dvb_frontend* fe, u32 *ubc)
static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[2];
if ((ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf))) < 0)
ret = mt312_read(state, RS_UBC_H, &buf, sizeof(buf));
if (ret < 0)
return ret;
*ubc = (buf[0] << 8) | buf[1];
@ -455,7 +487,7 @@ static int mt312_read_ucblocks(struct dvb_frontend* fe, u32 *ubc)
return 0;
}
static int mt312_set_frontend(struct dvb_frontend* fe,
static int mt312_set_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p)
{
struct mt312_state *state = fe->demodulator_priv;
@ -491,24 +523,28 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
switch (state->id) {
case ID_VP310:
// For now we will do this only for the VP310.
// It should be better for the mt312 as well, but tunning will be slower. ACCJr 09/29/03
/* For now we will do this only for the VP310.
* It should be better for the mt312 as well,
* but tuning will be slower. ACCJr 09/29/03
*/
ret = mt312_readreg(state, CONFIG, &config_val);
if (ret < 0)
return ret;
if (p->u.qpsk.symbol_rate >= 30000000) //Note that 30MS/s should use 90MHz
{
if ((config_val & 0x0c) == 0x08) { //We are running 60MHz
if (p->u.qpsk.symbol_rate >= 30000000) {
/* Note that 30MS/s should use 90MHz */
if ((config_val & 0x0c) == 0x08) {
/* We are running 60MHz */
state->frequency = 90;
if ((ret = mt312_initfe(fe)) < 0)
ret = mt312_initfe(fe);
if (ret < 0)
return ret;
}
}
else
{
if ((config_val & 0x0c) == 0x0C) { //We are running 90MHz
} else {
if ((config_val & 0x0c) == 0x0C) {
/* We are running 90MHz */
state->frequency = 60;
if ((ret = mt312_initfe(fe)) < 0)
ret = mt312_initfe(fe);
if (ret < 0)
return ret;
}
}
@ -523,7 +559,8 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, p);
if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
/* sr = (u16)(sr * 256.0 / 1000000.0) */
@ -545,7 +582,8 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
/* GO */
buf[4] = 0x01;
if ((ret = mt312_write(state, SYM_RATE_H, buf, sizeof(buf))) < 0)
ret = mt312_write(state, SYM_RATE_H, buf, sizeof(buf));
if (ret < 0)
return ret;
mt312_reset(state, 0);
@ -553,27 +591,30 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
return 0;
}
static int mt312_get_frontend(struct dvb_frontend* fe,
static int mt312_get_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
if ((ret = mt312_get_inversion(state, &p->inversion)) < 0)
ret = mt312_get_inversion(state, &p->inversion);
if (ret < 0)
return ret;
if ((ret = mt312_get_symbol_rate(state, &p->u.qpsk.symbol_rate)) < 0)
ret = mt312_get_symbol_rate(state, &p->u.qpsk.symbol_rate);
if (ret < 0)
return ret;
if ((ret = mt312_get_code_rate(state, &p->u.qpsk.fec_inner)) < 0)
ret = mt312_get_code_rate(state, &p->u.qpsk.fec_inner);
if (ret < 0)
return ret;
return 0;
}
static int mt312_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct mt312_state* state = fe->demodulator_priv;
struct mt312_state *state = fe->demodulator_priv;
if (enable) {
return mt312_writereg(state, GPP_CTRL, 0x40);
@ -582,27 +623,31 @@ static int mt312_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
}
}
static int mt312_sleep(struct dvb_frontend* fe)
static int mt312_sleep(struct dvb_frontend *fe)
{
struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 config;
/* reset all registers to defaults */
if ((ret = mt312_reset(state, 1)) < 0)
ret = mt312_reset(state, 1);
if (ret < 0)
return ret;
if ((ret = mt312_readreg(state, CONFIG, &config)) < 0)
ret = mt312_readreg(state, CONFIG, &config);
if (ret < 0)
return ret;
/* enter standby */
if ((ret = mt312_writereg(state, CONFIG, config & 0x7f)) < 0)
ret = mt312_writereg(state, CONFIG, config & 0x7f);
if (ret < 0)
return ret;
return 0;
}
static int mt312_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
static int mt312_get_tune_settings(struct dvb_frontend *fe,
struct dvb_frontend_tune_settings *fesettings)
{
fesettings->min_delay_ms = 50;
fesettings->step_size = 0;
@ -610,9 +655,9 @@ static int mt312_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_
return 0;
}
static void mt312_release(struct dvb_frontend* fe)
static void mt312_release(struct dvb_frontend *fe)
{
struct mt312_state* state = fe->demodulator_priv;
struct mt312_state *state = fe->demodulator_priv;
kfree(state);
}
@ -655,10 +700,10 @@ static struct dvb_frontend_ops vp310_mt312_ops = {
.set_voltage = mt312_set_voltage,
};
struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
struct i2c_adapter* i2c)
struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
struct i2c_adapter *i2c)
{
struct mt312_state* state = NULL;
struct mt312_state *state = NULL;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
@ -674,7 +719,8 @@ struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
goto error;
/* create dvb_frontend */
memcpy(&state->frontend.ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
memcpy(&state->frontend.ops, &vp310_mt312_ops,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
switch (state->id) {
@ -687,7 +733,8 @@ struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
state->frequency = 60;
break;
default:
printk (KERN_WARNING "Only Zarlink VP310/MT312 are supported chips.\n");
printk(KERN_WARNING "Only Zarlink VP310/MT312"
" are supported chips.\n");
goto error;
}
@ -697,6 +744,7 @@ error:
kfree(state);
return NULL;
}
EXPORT_SYMBOL(vp310_mt312_attach);
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
@ -705,4 +753,3 @@ MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver");
MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(vp310_mt312_attach);

View File

@ -28,22 +28,21 @@
#include <linux/dvb/frontend.h>
struct mt312_config
{
struct mt312_config {
/* the demodulator's i2c address */
u8 demod_address;
};
#if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
struct i2c_adapter* i2c);
struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config,
struct i2c_adapter *i2c);
#else
static inline struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
struct i2c_adapter* i2c)
static inline struct dvb_frontend *vp310_mt312_attach(
const struct mt312_config *config, struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}
#endif // CONFIG_DVB_MT312
#endif /* CONFIG_DVB_MT312 */
#endif // MT312_H
#endif /* MT312_H */

View File

@ -152,7 +152,13 @@ static void mt352_calc_input_freq(struct mt352_state* state,
if (state->config.if2)
if2 = state->config.if2;
ife = (2*adc_clock - if2);
if (adc_clock >= if2 * 2)
ife = if2;
else {
ife = adc_clock - (if2 % adc_clock);
if (ife > adc_clock / 2)
ife = adc_clock - ife;
}
value = -16374 * ife / adc_clock;
dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
__FUNCTION__, if2, ife, adc_clock, value, value & 0x3fff);

View File

@ -564,7 +564,7 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
/* Allocate memory for the internal state */
state = kmalloc(sizeof(struct or51132_state), GFP_KERNEL);
if (state == NULL)
goto error;
return NULL;
/* Setup the state */
state->config = config;
@ -576,10 +576,6 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
error:
kfree(state);
return NULL;
}
static struct dvb_frontend_ops or51132_ops = {

View File

@ -529,7 +529,7 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config,
/* Allocate memory for the internal state */
state = kmalloc(sizeof(struct or51211_state), GFP_KERNEL);
if (state == NULL)
goto error;
return NULL;
/* Setup the state */
state->config = config;
@ -541,10 +541,6 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config,
memcpy(&state->frontend.ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
return &state->frontend;
error:
kfree(state);
return NULL;
}
static struct dvb_frontend_ops or51211_ops = {

View File

@ -42,6 +42,7 @@ struct s5h1409_state {
fe_modulation_t current_modulation;
u32 current_frequency;
int if_freq;
u32 is_qam_locked;
u32 qam_state;
@ -97,7 +98,7 @@ static struct init_tab {
{ 0xac, 0x1003, },
{ 0xad, 0x103f, },
{ 0xe2, 0x0100, },
{ 0xe3, 0x0000, },
{ 0xe3, 0x1000, },
{ 0x28, 0x1010, },
{ 0xb1, 0x000e, },
};
@ -348,28 +349,32 @@ static int s5h1409_softreset(struct dvb_frontend* fe)
return 0;
}
#define S5H1409_VSB_IF_FREQ 5380
#define S5H1409_QAM_IF_FREQ state->config->qam_if
static int s5h1409_set_if_freq(struct dvb_frontend* fe, int KHz)
{
struct s5h1409_state* state = fe->demodulator_priv;
int ret = 0;
dprintk("%s(%d KHz)\n", __FUNCTION__, KHz);
if( (KHz == 44000) || (KHz == 5380) ) {
s5h1409_writereg(state, 0x87, 0x01be);
s5h1409_writereg(state, 0x88, 0x0436);
s5h1409_writereg(state, 0x89, 0x054d);
} else
if (KHz == 4000) {
switch (KHz) {
case 4000:
s5h1409_writereg(state, 0x87, 0x014b);
s5h1409_writereg(state, 0x88, 0x0cb5);
s5h1409_writereg(state, 0x89, 0x03e2);
} else {
printk("%s() Invalid arg = %d KHz\n", __FUNCTION__, KHz);
ret = -1;
break;
case 5380:
case 44000:
default:
s5h1409_writereg(state, 0x87, 0x01be);
s5h1409_writereg(state, 0x88, 0x0436);
s5h1409_writereg(state, 0x89, 0x054d);
break;
}
state->if_freq = KHz;
return ret;
return 0;
}
static int s5h1409_set_spectralinversion(struct dvb_frontend* fe, int inverted)
@ -394,11 +399,15 @@ static int s5h1409_enable_modulation(struct dvb_frontend* fe,
switch(m) {
case VSB_8:
dprintk("%s() VSB_8\n", __FUNCTION__);
if (state->if_freq != S5H1409_VSB_IF_FREQ)
s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
s5h1409_writereg(state, 0xf4, 0);
break;
case QAM_64:
case QAM_256:
dprintk("%s() QAM_AUTO (64/256)\n", __FUNCTION__);
if (state->if_freq != S5H1409_QAM_IF_FREQ)
s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
s5h1409_writereg(state, 0xf4, 1);
s5h1409_writereg(state, 0x85, 0x110);
break;
@ -432,9 +441,11 @@ static int s5h1409_set_gpio(struct dvb_frontend* fe, int enable)
dprintk("%s(%d)\n", __FUNCTION__, enable);
if (enable)
return s5h1409_writereg(state, 0xe3, 0x1100);
return s5h1409_writereg(state, 0xe3,
s5h1409_readreg(state, 0xe3) | 0x1100);
else
return s5h1409_writereg(state, 0xe3, 0x1000);
return s5h1409_writereg(state, 0xe3,
s5h1409_readreg(state, 0xe3) & 0xeeff);
}
static int s5h1409_sleep(struct dvb_frontend* fe, int enable)
@ -504,13 +515,15 @@ static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
s5h1409_writereg(state, 0x96, 0x20);
s5h1409_writereg(state, 0xad,
( ((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)) );
s5h1409_writereg(state, 0xab, 0x1100);
s5h1409_writereg(state, 0xab,
s5h1409_readreg(state, 0xab) & 0xeffe);
}
} else {
if (state->qam_state != 1) {
state->qam_state = 1;
s5h1409_writereg(state, 0x96, 0x08);
s5h1409_writereg(state, 0xab, 0x1101);
s5h1409_writereg(state, 0xab,
s5h1409_readreg(state, 0xab) | 0x1001);
}
}
}
@ -547,6 +560,36 @@ static int s5h1409_set_frontend (struct dvb_frontend* fe,
return 0;
}
static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
{
struct s5h1409_state *state = fe->demodulator_priv;
u16 val;
dprintk("%s(%d)\n", __FUNCTION__, mode);
val = s5h1409_readreg(state, 0xac) & 0xcfff;
switch (mode) {
case S5H1409_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
val |= 0x0000;
break;
case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
dprintk("%s(%d) Mode1 or Defaulting\n", __FUNCTION__, mode);
val |= 0x1000;
break;
case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
val |= 0x2000;
break;
case S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
val |= 0x3000;
break;
default:
return -EINVAL;
}
/* Configure MPEG Signal Timing charactistics */
return s5h1409_writereg(state, 0xac, val);
}
/* Reset the demod hardware and reset all of the configuration registers
to a default state. */
static int s5h1409_init (struct dvb_frontend* fe)
@ -566,13 +609,16 @@ static int s5h1409_init (struct dvb_frontend* fe)
state->current_modulation = VSB_8;
if (state->config->output_mode == S5H1409_SERIAL_OUTPUT)
s5h1409_writereg(state, 0xab, 0x100); /* Serial */
s5h1409_writereg(state, 0xab,
s5h1409_readreg(state, 0xab) | 0x100); /* Serial */
else
s5h1409_writereg(state, 0xab, 0x0); /* Parallel */
s5h1409_writereg(state, 0xab,
s5h1409_readreg(state, 0xab) & 0xfeff); /* Parallel */
s5h1409_set_spectralinversion(fe, state->config->inversion);
s5h1409_set_if_freq(fe, state->config->if_freq);
s5h1409_set_if_freq(fe, state->if_freq);
s5h1409_set_gpio(fe, state->config->gpio);
s5h1409_set_mpeg_timing(fe, state->config->mpeg_timing);
s5h1409_softreset(fe);
/* Note: Leaving the I2C gate closed. */
@ -741,6 +787,7 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
struct i2c_adapter* i2c)
{
struct s5h1409_state* state = NULL;
u16 reg;
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
@ -751,9 +798,11 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
state->config = config;
state->i2c = i2c;
state->current_modulation = 0;
state->if_freq = S5H1409_VSB_IF_FREQ;
/* check if the demod exists */
if (s5h1409_readreg(state, 0x04) != 0x0066)
reg = s5h1409_readreg(state, 0x04);
if ((reg != 0x0066) && (reg != 0x007f))
goto error;
/* create dvb_frontend */
@ -761,8 +810,14 @@ struct dvb_frontend* s5h1409_attach(const struct s5h1409_config* config,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
if (s5h1409_init(&state->frontend) != 0) {
printk(KERN_ERR "%s: Failed to initialize correctly\n",
__FUNCTION__);
goto error;
}
/* Note: Leaving the I2C gate open here. */
s5h1409_writereg(state, 0xf3, 1);
s5h1409_i2c_gate_ctrl(&state->frontend, 1);
return &state->frontend;

View File

@ -39,8 +39,8 @@ struct s5h1409_config
#define S5H1409_GPIO_ON 1
u8 gpio;
/* IF Freq in KHz */
u16 if_freq;
/* IF Freq for QAM in KHz, VSB is hardcoded to 5380 */
u16 qam_if;
/* Spectral Inversion */
#define S5H1409_INVERSION_OFF 0
@ -51,6 +51,13 @@ struct s5h1409_config
#define S5H1409_TUNERLOCKING 0
#define S5H1409_DEMODLOCKING 1
u8 status_mode;
/* MPEG signal timing */
#define S5H1409_MPEGTIMING_CONTINOUS_INVERTING_CLOCK 0
#define S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK 1
#define S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK 2
#define S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
u16 mpeg_timing;
};
#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) && defined(MODULE))

View File

@ -0,0 +1,653 @@
/*
tda18271-common.c - driver for the Philips / NXP TDA18271 silicon tuner
Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "tda18271-priv.h"
static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
{
struct tda18271_priv *priv = fe->tuner_priv;
enum tda18271_i2c_gate gate;
int ret = 0;
switch (priv->gate) {
case TDA18271_GATE_DIGITAL:
case TDA18271_GATE_ANALOG:
gate = priv->gate;
break;
case TDA18271_GATE_AUTO:
default:
switch (priv->mode) {
case TDA18271_DIGITAL:
gate = TDA18271_GATE_DIGITAL;
break;
case TDA18271_ANALOG:
default:
gate = TDA18271_GATE_ANALOG;
break;
}
}
switch (gate) {
case TDA18271_GATE_ANALOG:
if (fe->ops.analog_ops.i2c_gate_ctrl)
ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable);
break;
case TDA18271_GATE_DIGITAL:
if (fe->ops.i2c_gate_ctrl)
ret = fe->ops.i2c_gate_ctrl(fe, enable);
break;
default:
ret = -EINVAL;
break;
}
return ret;
};
/*---------------------------------------------------------------------*/
static void tda18271_dump_regs(struct dvb_frontend *fe, int extended)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
tda_reg("=== TDA18271 REG DUMP ===\n");
tda_reg("ID_BYTE = 0x%02x\n", 0xff & regs[R_ID]);
tda_reg("THERMO_BYTE = 0x%02x\n", 0xff & regs[R_TM]);
tda_reg("POWER_LEVEL_BYTE = 0x%02x\n", 0xff & regs[R_PL]);
tda_reg("EASY_PROG_BYTE_1 = 0x%02x\n", 0xff & regs[R_EP1]);
tda_reg("EASY_PROG_BYTE_2 = 0x%02x\n", 0xff & regs[R_EP2]);
tda_reg("EASY_PROG_BYTE_3 = 0x%02x\n", 0xff & regs[R_EP3]);
tda_reg("EASY_PROG_BYTE_4 = 0x%02x\n", 0xff & regs[R_EP4]);
tda_reg("EASY_PROG_BYTE_5 = 0x%02x\n", 0xff & regs[R_EP5]);
tda_reg("CAL_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_CPD]);
tda_reg("CAL_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_CD1]);
tda_reg("CAL_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_CD2]);
tda_reg("CAL_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_CD3]);
tda_reg("MAIN_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_MPD]);
tda_reg("MAIN_DIV_BYTE_1 = 0x%02x\n", 0xff & regs[R_MD1]);
tda_reg("MAIN_DIV_BYTE_2 = 0x%02x\n", 0xff & regs[R_MD2]);
tda_reg("MAIN_DIV_BYTE_3 = 0x%02x\n", 0xff & regs[R_MD3]);
/* only dump extended regs if DBG_ADV is set */
if (!(tda18271_debug & DBG_ADV))
return;
/* W indicates write-only registers.
* Register dump for write-only registers shows last value written. */
tda_reg("EXTENDED_BYTE_1 = 0x%02x\n", 0xff & regs[R_EB1]);
tda_reg("EXTENDED_BYTE_2 = 0x%02x\n", 0xff & regs[R_EB2]);
tda_reg("EXTENDED_BYTE_3 = 0x%02x\n", 0xff & regs[R_EB3]);
tda_reg("EXTENDED_BYTE_4 = 0x%02x\n", 0xff & regs[R_EB4]);
tda_reg("EXTENDED_BYTE_5 = 0x%02x\n", 0xff & regs[R_EB5]);
tda_reg("EXTENDED_BYTE_6 = 0x%02x\n", 0xff & regs[R_EB6]);
tda_reg("EXTENDED_BYTE_7 = 0x%02x\n", 0xff & regs[R_EB7]);
tda_reg("EXTENDED_BYTE_8 = 0x%02x\n", 0xff & regs[R_EB8]);
tda_reg("EXTENDED_BYTE_9 W = 0x%02x\n", 0xff & regs[R_EB9]);
tda_reg("EXTENDED_BYTE_10 = 0x%02x\n", 0xff & regs[R_EB10]);
tda_reg("EXTENDED_BYTE_11 = 0x%02x\n", 0xff & regs[R_EB11]);
tda_reg("EXTENDED_BYTE_12 = 0x%02x\n", 0xff & regs[R_EB12]);
tda_reg("EXTENDED_BYTE_13 = 0x%02x\n", 0xff & regs[R_EB13]);
tda_reg("EXTENDED_BYTE_14 = 0x%02x\n", 0xff & regs[R_EB14]);
tda_reg("EXTENDED_BYTE_15 = 0x%02x\n", 0xff & regs[R_EB15]);
tda_reg("EXTENDED_BYTE_16 W = 0x%02x\n", 0xff & regs[R_EB16]);
tda_reg("EXTENDED_BYTE_17 W = 0x%02x\n", 0xff & regs[R_EB17]);
tda_reg("EXTENDED_BYTE_18 = 0x%02x\n", 0xff & regs[R_EB18]);
tda_reg("EXTENDED_BYTE_19 W = 0x%02x\n", 0xff & regs[R_EB19]);
tda_reg("EXTENDED_BYTE_20 W = 0x%02x\n", 0xff & regs[R_EB20]);
tda_reg("EXTENDED_BYTE_21 = 0x%02x\n", 0xff & regs[R_EB21]);
tda_reg("EXTENDED_BYTE_22 = 0x%02x\n", 0xff & regs[R_EB22]);
tda_reg("EXTENDED_BYTE_23 = 0x%02x\n", 0xff & regs[R_EB23]);
}
int tda18271_read_regs(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
unsigned char buf = 0x00;
int ret;
struct i2c_msg msg[] = {
{ .addr = priv->i2c_addr, .flags = 0,
.buf = &buf, .len = 1 },
{ .addr = priv->i2c_addr, .flags = I2C_M_RD,
.buf = regs, .len = 16 }
};
tda18271_i2c_gate_ctrl(fe, 1);
/* read all registers */
ret = i2c_transfer(priv->i2c_adap, msg, 2);
tda18271_i2c_gate_ctrl(fe, 0);
if (ret != 2)
tda_err("ERROR: i2c_transfer returned: %d\n", ret);
if (tda18271_debug & DBG_REG)
tda18271_dump_regs(fe, 0);
return (ret == 2 ? 0 : ret);
}
int tda18271_read_extended(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
unsigned char regdump[TDA18271_NUM_REGS];
unsigned char buf = 0x00;
int ret, i;
struct i2c_msg msg[] = {
{ .addr = priv->i2c_addr, .flags = 0,
.buf = &buf, .len = 1 },
{ .addr = priv->i2c_addr, .flags = I2C_M_RD,
.buf = regdump, .len = TDA18271_NUM_REGS }
};
tda18271_i2c_gate_ctrl(fe, 1);
/* read all registers */
ret = i2c_transfer(priv->i2c_adap, msg, 2);
tda18271_i2c_gate_ctrl(fe, 0);
if (ret != 2)
tda_err("ERROR: i2c_transfer returned: %d\n", ret);
for (i = 0; i <= TDA18271_NUM_REGS; i++) {
/* don't update write-only registers */
if ((i != R_EB9) &&
(i != R_EB16) &&
(i != R_EB17) &&
(i != R_EB19) &&
(i != R_EB20))
regs[i] = regdump[i];
}
if (tda18271_debug & DBG_REG)
tda18271_dump_regs(fe, 1);
return (ret == 2 ? 0 : ret);
}
int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
unsigned char buf[TDA18271_NUM_REGS + 1];
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
.buf = buf, .len = len + 1 };
int i, ret;
BUG_ON((len == 0) || (idx + len > sizeof(buf)));
buf[0] = idx;
for (i = 1; i <= len; i++)
buf[i] = regs[idx - 1 + i];
tda18271_i2c_gate_ctrl(fe, 1);
/* write registers */
ret = i2c_transfer(priv->i2c_adap, &msg, 1);
tda18271_i2c_gate_ctrl(fe, 0);
if (ret != 1)
tda_err("ERROR: i2c_transfer returned: %d\n", ret);
return (ret == 1 ? 0 : ret);
}
/*---------------------------------------------------------------------*/
int tda18271_init_regs(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
tda_dbg("initializing registers for device @ %d-%04x\n",
i2c_adapter_id(priv->i2c_adap), priv->i2c_addr);
/* initialize registers */
switch (priv->id) {
case TDA18271HDC1:
regs[R_ID] = 0x83;
break;
case TDA18271HDC2:
regs[R_ID] = 0x84;
break;
};
regs[R_TM] = 0x08;
regs[R_PL] = 0x80;
regs[R_EP1] = 0xc6;
regs[R_EP2] = 0xdf;
regs[R_EP3] = 0x16;
regs[R_EP4] = 0x60;
regs[R_EP5] = 0x80;
regs[R_CPD] = 0x80;
regs[R_CD1] = 0x00;
regs[R_CD2] = 0x00;
regs[R_CD3] = 0x00;
regs[R_MPD] = 0x00;
regs[R_MD1] = 0x00;
regs[R_MD2] = 0x00;
regs[R_MD3] = 0x00;
switch (priv->id) {
case TDA18271HDC1:
regs[R_EB1] = 0xff;
break;
case TDA18271HDC2:
regs[R_EB1] = 0xfc;
break;
};
regs[R_EB2] = 0x01;
regs[R_EB3] = 0x84;
regs[R_EB4] = 0x41;
regs[R_EB5] = 0x01;
regs[R_EB6] = 0x84;
regs[R_EB7] = 0x40;
regs[R_EB8] = 0x07;
regs[R_EB9] = 0x00;
regs[R_EB10] = 0x00;
regs[R_EB11] = 0x96;
switch (priv->id) {
case TDA18271HDC1:
regs[R_EB12] = 0x0f;
break;
case TDA18271HDC2:
regs[R_EB12] = 0x33;
break;
};
regs[R_EB13] = 0xc1;
regs[R_EB14] = 0x00;
regs[R_EB15] = 0x8f;
regs[R_EB16] = 0x00;
regs[R_EB17] = 0x00;
switch (priv->id) {
case TDA18271HDC1:
regs[R_EB18] = 0x00;
break;
case TDA18271HDC2:
regs[R_EB18] = 0x8c;
break;
};
regs[R_EB19] = 0x00;
regs[R_EB20] = 0x20;
switch (priv->id) {
case TDA18271HDC1:
regs[R_EB21] = 0x33;
break;
case TDA18271HDC2:
regs[R_EB21] = 0xb3;
break;
};
regs[R_EB22] = 0x48;
regs[R_EB23] = 0xb0;
tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
/* setup agc1 gain */
regs[R_EB17] = 0x00;
tda18271_write_regs(fe, R_EB17, 1);
regs[R_EB17] = 0x03;
tda18271_write_regs(fe, R_EB17, 1);
regs[R_EB17] = 0x43;
tda18271_write_regs(fe, R_EB17, 1);
regs[R_EB17] = 0x4c;
tda18271_write_regs(fe, R_EB17, 1);
/* setup agc2 gain */
if ((priv->id) == TDA18271HDC1) {
regs[R_EB20] = 0xa0;
tda18271_write_regs(fe, R_EB20, 1);
regs[R_EB20] = 0xa7;
tda18271_write_regs(fe, R_EB20, 1);
regs[R_EB20] = 0xe7;
tda18271_write_regs(fe, R_EB20, 1);
regs[R_EB20] = 0xec;
tda18271_write_regs(fe, R_EB20, 1);
}
/* image rejection calibration */
/* low-band */
regs[R_EP3] = 0x1f;
regs[R_EP4] = 0x66;
regs[R_EP5] = 0x81;
regs[R_CPD] = 0xcc;
regs[R_CD1] = 0x6c;
regs[R_CD2] = 0x00;
regs[R_CD3] = 0x00;
regs[R_MPD] = 0xcd;
regs[R_MD1] = 0x77;
regs[R_MD2] = 0x08;
regs[R_MD3] = 0x00;
switch (priv->id) {
case TDA18271HDC1:
tda18271_write_regs(fe, R_EP3, 11);
break;
case TDA18271HDC2:
tda18271_write_regs(fe, R_EP3, 12);
break;
};
if ((priv->id) == TDA18271HDC2) {
/* main pll cp source on */
regs[R_EB4] = 0x61;
tda18271_write_regs(fe, R_EB4, 1);
msleep(1);
/* main pll cp source off */
regs[R_EB4] = 0x41;
tda18271_write_regs(fe, R_EB4, 1);
}
msleep(5); /* pll locking */
/* launch detector */
tda18271_write_regs(fe, R_EP1, 1);
msleep(5); /* wanted low measurement */
regs[R_EP5] = 0x85;
regs[R_CPD] = 0xcb;
regs[R_CD1] = 0x66;
regs[R_CD2] = 0x70;
tda18271_write_regs(fe, R_EP3, 7);
msleep(5); /* pll locking */
/* launch optimization algorithm */
tda18271_write_regs(fe, R_EP2, 1);
msleep(30); /* image low optimization completion */
/* mid-band */
regs[R_EP5] = 0x82;
regs[R_CPD] = 0xa8;
regs[R_CD2] = 0x00;
regs[R_MPD] = 0xa9;
regs[R_MD1] = 0x73;
regs[R_MD2] = 0x1a;
tda18271_write_regs(fe, R_EP3, 11);
msleep(5); /* pll locking */
tda18271_write_regs(fe, R_EP1, 1);
msleep(5); /* wanted mid measurement */
regs[R_EP5] = 0x86;
regs[R_CPD] = 0xa8;
regs[R_CD1] = 0x66;
regs[R_CD2] = 0xa0;
tda18271_write_regs(fe, R_EP3, 7);
msleep(5); /* pll locking */
/* launch optimization algorithm */
tda18271_write_regs(fe, R_EP2, 1);
msleep(30); /* image mid optimization completion */
/* high-band */
regs[R_EP5] = 0x83;
regs[R_CPD] = 0x98;
regs[R_CD1] = 0x65;
regs[R_CD2] = 0x00;
regs[R_MPD] = 0x99;
regs[R_MD1] = 0x71;
regs[R_MD2] = 0xcd;
tda18271_write_regs(fe, R_EP3, 11);
msleep(5); /* pll locking */
/* launch detector */
tda18271_write_regs(fe, R_EP1, 1);
msleep(5); /* wanted high measurement */
regs[R_EP5] = 0x87;
regs[R_CD1] = 0x65;
regs[R_CD2] = 0x50;
tda18271_write_regs(fe, R_EP3, 7);
msleep(5); /* pll locking */
/* launch optimization algorithm */
tda18271_write_regs(fe, R_EP2, 1);
msleep(30); /* image high optimization completion */
/* return to normal mode */
regs[R_EP4] = 0x64;
tda18271_write_regs(fe, R_EP4, 1);
/* synchronize */
tda18271_write_regs(fe, R_EP1, 1);
return 0;
}
/*---------------------------------------------------------------------*/
/*
* Standby modes, EP3 [7:5]
*
* | SM || SM_LT || SM_XT || mode description
* |=====\\=======\\=======\\===================================
* | 0 || 0 || 0 || normal mode
* |-----||-------||-------||-----------------------------------
* | || || || standby mode w/ slave tuner output
* | 1 || 0 || 0 || & loop thru & xtal oscillator on
* |-----||-------||-------||-----------------------------------
* | 1 || 1 || 0 || standby mode w/ xtal oscillator on
* |-----||-------||-------||-----------------------------------
* | 1 || 1 || 1 || power off
*
*/
int tda18271_set_standby_mode(struct dvb_frontend *fe,
int sm, int sm_lt, int sm_xt)
{
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt);
regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */
regs[R_EP3] |= sm ? (1 << 7) : 0 |
sm_lt ? (1 << 6) : 0 |
sm_xt ? (1 << 5) : 0;
tda18271_write_regs(fe, R_EP3, 1);
return 0;
}
/*---------------------------------------------------------------------*/
int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
{
/* sets main post divider & divider bytes, but does not write them */
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
u8 d, pd;
u32 div;
int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d);
if (ret < 0)
goto fail;
regs[R_MPD] = (0x77 & pd);
switch (priv->mode) {
case TDA18271_ANALOG:
regs[R_MPD] &= ~0x08;
break;
case TDA18271_DIGITAL:
regs[R_MPD] |= 0x08;
break;
}
div = ((d * (freq / 1000)) << 7) / 125;
regs[R_MD1] = 0x7f & (div >> 16);
regs[R_MD2] = 0xff & (div >> 8);
regs[R_MD3] = 0xff & div;
fail:
return ret;
}
int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq)
{
/* sets cal post divider & divider bytes, but does not write them */
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
u8 d, pd;
u32 div;
int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d);
if (ret < 0)
goto fail;
regs[R_CPD] = pd;
div = ((d * (freq / 1000)) << 7) / 125;
regs[R_CD1] = 0x7f & (div >> 16);
regs[R_CD2] = 0xff & (div >> 8);
regs[R_CD3] = 0xff & div;
fail:
return ret;
}
/*---------------------------------------------------------------------*/
int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq)
{
/* sets bp filter bits, but does not write them */
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val);
if (ret < 0)
goto fail;
regs[R_EP1] &= ~0x07; /* clear bp filter bits */
regs[R_EP1] |= (0x07 & val);
fail:
return ret;
}
int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq)
{
/* sets K & M bits, but does not write them */
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val);
if (ret < 0)
goto fail;
regs[R_EB13] &= ~0x7c; /* clear k & m bits */
regs[R_EB13] |= (0x7c & val);
fail:
return ret;
}
int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq)
{
/* sets rf band bits, but does not write them */
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val);
if (ret < 0)
goto fail;
regs[R_EP2] &= ~0xe0; /* clear rf band bits */
regs[R_EP2] |= (0xe0 & (val << 5));
fail:
return ret;
}
int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq)
{
/* sets gain taper bits, but does not write them */
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val);
if (ret < 0)
goto fail;
regs[R_EP2] &= ~0x1f; /* clear gain taper bits */
regs[R_EP2] |= (0x1f & val);
fail:
return ret;
}
int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq)
{
/* sets IR Meas bits, but does not write them */
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
u8 val;
int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val);
if (ret < 0)
goto fail;
regs[R_EP5] &= ~0x07;
regs[R_EP5] |= (0x07 & val);
fail:
return ret;
}
int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
{
/* sets rf cal byte (RFC_Cprog), but does not write it */
struct tda18271_priv *priv = fe->tuner_priv;
unsigned char *regs = priv->tda18271_regs;
u8 val;
tda18271_lookup_map(fe, RF_CAL, freq, &val);
regs[R_EB14] = val;
return 0;
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* ---------------------------------------------------------------------------
* Local variables:
* c-basic-offset: 8
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,212 @@
/*
tda18271-priv.h - private header for the NXP TDA18271 silicon tuner
Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __TDA18271_PRIV_H__
#define __TDA18271_PRIV_H__
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mutex.h>
#include "tda18271.h"
#define R_ID 0x00 /* ID byte */
#define R_TM 0x01 /* Thermo byte */
#define R_PL 0x02 /* Power level byte */
#define R_EP1 0x03 /* Easy Prog byte 1 */
#define R_EP2 0x04 /* Easy Prog byte 2 */
#define R_EP3 0x05 /* Easy Prog byte 3 */
#define R_EP4 0x06 /* Easy Prog byte 4 */
#define R_EP5 0x07 /* Easy Prog byte 5 */
#define R_CPD 0x08 /* Cal Post-Divider byte */
#define R_CD1 0x09 /* Cal Divider byte 1 */
#define R_CD2 0x0a /* Cal Divider byte 2 */
#define R_CD3 0x0b /* Cal Divider byte 3 */
#define R_MPD 0x0c /* Main Post-Divider byte */
#define R_MD1 0x0d /* Main Divider byte 1 */
#define R_MD2 0x0e /* Main Divider byte 2 */
#define R_MD3 0x0f /* Main Divider byte 3 */
#define R_EB1 0x10 /* Extended byte 1 */
#define R_EB2 0x11 /* Extended byte 2 */
#define R_EB3 0x12 /* Extended byte 3 */
#define R_EB4 0x13 /* Extended byte 4 */
#define R_EB5 0x14 /* Extended byte 5 */
#define R_EB6 0x15 /* Extended byte 6 */
#define R_EB7 0x16 /* Extended byte 7 */
#define R_EB8 0x17 /* Extended byte 8 */
#define R_EB9 0x18 /* Extended byte 9 */
#define R_EB10 0x19 /* Extended byte 10 */
#define R_EB11 0x1a /* Extended byte 11 */
#define R_EB12 0x1b /* Extended byte 12 */
#define R_EB13 0x1c /* Extended byte 13 */
#define R_EB14 0x1d /* Extended byte 14 */
#define R_EB15 0x1e /* Extended byte 15 */
#define R_EB16 0x1f /* Extended byte 16 */
#define R_EB17 0x20 /* Extended byte 17 */
#define R_EB18 0x21 /* Extended byte 18 */
#define R_EB19 0x22 /* Extended byte 19 */
#define R_EB20 0x23 /* Extended byte 20 */
#define R_EB21 0x24 /* Extended byte 21 */
#define R_EB22 0x25 /* Extended byte 22 */
#define R_EB23 0x26 /* Extended byte 23 */
#define TDA18271_NUM_REGS 39
/*---------------------------------------------------------------------*/
struct tda18271_rf_tracking_filter_cal {
u32 rfmax;
u8 rfband;
u32 rf1_def;
u32 rf2_def;
u32 rf3_def;
u32 rf1;
u32 rf2;
u32 rf3;
int rf_a1;
int rf_b1;
int rf_a2;
int rf_b2;
};
enum tda18271_mode {
TDA18271_ANALOG,
TDA18271_DIGITAL,
};
struct tda18271_map_layout;
enum tda18271_ver {
TDA18271HDC1,
TDA18271HDC2,
};
struct tda18271_priv {
u8 i2c_addr;
struct i2c_adapter *i2c_adap;
unsigned char tda18271_regs[TDA18271_NUM_REGS];
struct list_head tda18271_list;
enum tda18271_mode mode;
enum tda18271_i2c_gate gate;
enum tda18271_ver id;
unsigned int count;
unsigned int tm_rfcal;
unsigned int cal_initialized:1;
struct tda18271_map_layout *maps;
struct tda18271_std_map std;
struct tda18271_rf_tracking_filter_cal rf_cal_state[8];
struct mutex lock;
u32 frequency;
u32 bandwidth;
};
/*---------------------------------------------------------------------*/
extern int tda18271_debug;
#define DBG_INFO 1
#define DBG_MAP 2
#define DBG_REG 4
#define DBG_ADV 8
#define DBG_CAL 16
#define tda_printk(kern, fmt, arg...) \
printk(kern "%s: " fmt, __FUNCTION__, ##arg)
#define dprintk(kern, lvl, fmt, arg...) do {\
if (tda18271_debug & lvl) \
tda_printk(kern, fmt, ##arg); } while (0)
#define tda_info(fmt, arg...) printk(KERN_INFO fmt, ##arg)
#define tda_warn(fmt, arg...) tda_printk(KERN_WARNING, fmt, ##arg)
#define tda_err(fmt, arg...) tda_printk(KERN_ERR, fmt, ##arg)
#define tda_dbg(fmt, arg...) dprintk(KERN_DEBUG, DBG_INFO, fmt, ##arg)
#define tda_map(fmt, arg...) dprintk(KERN_DEBUG, DBG_MAP, fmt, ##arg)
#define tda_reg(fmt, arg...) dprintk(KERN_DEBUG, DBG_REG, fmt, ##arg)
#define tda_cal(fmt, arg...) dprintk(KERN_DEBUG, DBG_CAL, fmt, ##arg)
/*---------------------------------------------------------------------*/
enum tda18271_map_type {
/* tda18271_pll_map */
MAIN_PLL,
CAL_PLL,
/* tda18271_map */
RF_CAL,
RF_CAL_KMCO,
RF_CAL_DC_OVER_DT,
BP_FILTER,
RF_BAND,
GAIN_TAPER,
IR_MEASURE,
};
extern int tda18271_lookup_pll_map(struct dvb_frontend *fe,
enum tda18271_map_type map_type,
u32 *freq, u8 *post_div, u8 *div);
extern int tda18271_lookup_map(struct dvb_frontend *fe,
enum tda18271_map_type map_type,
u32 *freq, u8 *val);
extern int tda18271_lookup_thermometer(struct dvb_frontend *fe);
extern int tda18271_lookup_rf_band(struct dvb_frontend *fe,
u32 *freq, u8 *rf_band);
extern int tda18271_lookup_cid_target(struct dvb_frontend *fe,
u32 *freq, u8 *cid_target,
u16 *count_limit);
extern int tda18271_assign_map_layout(struct dvb_frontend *fe);
/*---------------------------------------------------------------------*/
extern int tda18271_read_regs(struct dvb_frontend *fe);
extern int tda18271_read_extended(struct dvb_frontend *fe);
extern int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len);
extern int tda18271_init_regs(struct dvb_frontend *fe);
extern int tda18271_set_standby_mode(struct dvb_frontend *fe,
int sm, int sm_lt, int sm_xt);
extern int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq);
extern int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq);
extern int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq);
extern int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq);
extern int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq);
extern int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq);
extern int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq);
extern int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq);
#endif /* __TDA18271_PRIV_H__ */
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* ---------------------------------------------------------------------------
* Local variables:
* c-basic-offset: 8
* End:
*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
/*
tda18271.h - header for the Philips / NXP TDA18271 silicon tuner
Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __TDA18271_H__
#define __TDA18271_H__
#include <linux/i2c.h>
#include "dvb_frontend.h"
struct tda18271_std_map_item {
u16 if_freq;
u8 std_bits;
};
struct tda18271_std_map {
struct tda18271_std_map_item fm_radio;
struct tda18271_std_map_item atv_b;
struct tda18271_std_map_item atv_dk;
struct tda18271_std_map_item atv_gh;
struct tda18271_std_map_item atv_i;
struct tda18271_std_map_item atv_l;
struct tda18271_std_map_item atv_lc;
struct tda18271_std_map_item atv_mn;
struct tda18271_std_map_item atsc_6;
struct tda18271_std_map_item dvbt_6;
struct tda18271_std_map_item dvbt_7;
struct tda18271_std_map_item dvbt_8;
struct tda18271_std_map_item qam_6;
struct tda18271_std_map_item qam_8;
};
enum tda18271_i2c_gate {
TDA18271_GATE_AUTO = 0,
TDA18271_GATE_ANALOG,
TDA18271_GATE_DIGITAL,
};
struct tda18271_config {
/* override default if freq / std settings (optional) */
struct tda18271_std_map *std_map;
/* use i2c gate provided by analog or digital demod */
enum tda18271_i2c_gate gate;
};
#if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE))
extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
struct i2c_adapter *i2c,
struct tda18271_config *cfg);
#else
static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
u8 addr,
struct i2c_adapter *i2c,
struct tda18271_config *cfg)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}
#endif
#endif /* __TDA18271_H__ */

View File

@ -19,12 +19,16 @@
*/
#include <linux/module.h>
#include <linux/dvb/frontend.h>
#include <asm/types.h>
#include <linux/dvb/frontend.h>
#include <linux/videodev2.h>
#include "tda827x.h"
static int debug = 0;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
#define dprintk(args...) \
do { \
if (debug) printk(KERN_DEBUG "tda827x: " args); \
@ -34,10 +38,57 @@ struct tda827x_priv {
int i2c_addr;
struct i2c_adapter *i2c_adap;
struct tda827x_config *cfg;
unsigned int sgIF;
unsigned char lpsel;
u32 frequency;
u32 bandwidth;
};
static void tda827x_set_std(struct dvb_frontend *fe,
struct analog_parameters *params)
{
struct tda827x_priv *priv = fe->tuner_priv;
char *mode;
priv->lpsel = 0;
if (params->std & V4L2_STD_MN) {
priv->sgIF = 92;
priv->lpsel = 1;
mode = "MN";
} else if (params->std & V4L2_STD_B) {
priv->sgIF = 108;
mode = "B";
} else if (params->std & V4L2_STD_GH) {
priv->sgIF = 124;
mode = "GH";
} else if (params->std & V4L2_STD_PAL_I) {
priv->sgIF = 124;
mode = "I";
} else if (params->std & V4L2_STD_DK) {
priv->sgIF = 124;
mode = "DK";
} else if (params->std & V4L2_STD_SECAM_L) {
priv->sgIF = 124;
mode = "L";
} else if (params->std & V4L2_STD_SECAM_LC) {
priv->sgIF = 20;
mode = "LC";
} else {
priv->sgIF = 124;
mode = "xx";
}
if (params->mode == V4L2_TUNER_RADIO)
priv->sgIF = 88; /* if frequency is 5.5 MHz */
dprintk("setting tda827x to system %s\n", mode);
}
/* ------------------------------------------------------------------ */
struct tda827x_data {
u32 lomax;
u8 spd;
@ -48,7 +99,7 @@ struct tda827x_data {
u8 div1p5;
};
static const struct tda827x_data tda827x_dvbt[] = {
static const struct tda827x_data tda827x_table[] = {
{ .lomax = 62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
{ .lomax = 66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
{ .lomax = 76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
@ -106,21 +157,22 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
tuner_freq = params->frequency + if_freq;
i = 0;
while (tda827x_dvbt[i].lomax < tuner_freq) {
if(tda827x_dvbt[i + 1].lomax == 0)
while (tda827x_table[i].lomax < tuner_freq) {
if (tda827x_table[i + 1].lomax == 0)
break;
i++;
}
N = ((tuner_freq + 125000) / 250000) << (tda827x_dvbt[i].spd + 2);
N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
buf[0] = 0;
buf[1] = (N>>8) | 0x40;
buf[2] = N & 0xff;
buf[3] = 0;
buf[4] = 0x52;
buf[5] = (tda827x_dvbt[i].spd << 6) + (tda827x_dvbt[i].div1p5 << 5) +
(tda827x_dvbt[i].bs << 3) + tda827x_dvbt[i].bp;
buf[6] = (tda827x_dvbt[i].gc3 << 4) + 0x8f;
buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
(tda827x_table[i].bs << 3) +
tda827x_table[i].bp;
buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
buf[7] = 0xbf;
buf[8] = 0x2a;
buf[9] = 0x05;
@ -140,7 +192,7 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
msleep(500);
/* correct CP value */
buf[0] = 0x30;
buf[1] = 0x50 + tda827x_dvbt[i].cp;
buf[1] = 0x50 + tda827x_table[i].cp;
msg.len = 2;
if (fe->ops.i2c_gate_ctrl)
@ -173,6 +225,102 @@ static int tda827xo_sleep(struct dvb_frontend *fe)
/* ------------------------------------------------------------------ */
static int tda827xo_set_analog_params(struct dvb_frontend *fe,
struct analog_parameters *params)
{
unsigned char tuner_reg[8];
unsigned char reg2[2];
u32 N;
int i;
struct tda827x_priv *priv = fe->tuner_priv;
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
unsigned int freq = params->frequency;
tda827x_set_std(fe, params);
if (params->mode == V4L2_TUNER_RADIO)
freq = freq / 1000;
N = freq + priv->sgIF;
i = 0;
while (tda827x_table[i].lomax < N * 62500) {
if (tda827x_table[i + 1].lomax == 0)
break;
i++;
}
N = N << tda827x_table[i].spd;
tuner_reg[0] = 0;
tuner_reg[1] = (unsigned char)(N>>8);
tuner_reg[2] = (unsigned char) N;
tuner_reg[3] = 0x40;
tuner_reg[4] = 0x52 + (priv->lpsel << 5);
tuner_reg[5] = (tda827x_table[i].spd << 6) +
(tda827x_table[i].div1p5 << 5) +
(tda827x_table[i].bs << 3) + tda827x_table[i].bp;
tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
tuner_reg[7] = 0x8f;
msg.buf = tuner_reg;
msg.len = 8;
i2c_transfer(priv->i2c_adap, &msg, 1);
msg.buf = reg2;
msg.len = 2;
reg2[0] = 0x80;
reg2[1] = 0;
i2c_transfer(priv->i2c_adap, &msg, 1);
reg2[0] = 0x60;
reg2[1] = 0xbf;
i2c_transfer(priv->i2c_adap, &msg, 1);
reg2[0] = 0x30;
reg2[1] = tuner_reg[4] + 0x80;
i2c_transfer(priv->i2c_adap, &msg, 1);
msleep(1);
reg2[0] = 0x30;
reg2[1] = tuner_reg[4] + 4;
i2c_transfer(priv->i2c_adap, &msg, 1);
msleep(1);
reg2[0] = 0x30;
reg2[1] = tuner_reg[4];
i2c_transfer(priv->i2c_adap, &msg, 1);
msleep(550);
reg2[0] = 0x30;
reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
i2c_transfer(priv->i2c_adap, &msg, 1);
reg2[0] = 0x60;
reg2[1] = 0x3f;
i2c_transfer(priv->i2c_adap, &msg, 1);
reg2[0] = 0x80;
reg2[1] = 0x08; /* Vsync en */
i2c_transfer(priv->i2c_adap, &msg, 1);
priv->frequency = freq * 62500;
return 0;
}
static void tda827xo_agcf(struct dvb_frontend *fe)
{
struct tda827x_priv *priv = fe->tuner_priv;
unsigned char data[] = { 0x80, 0x0c };
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
.buf = data, .len = 2};
i2c_transfer(priv->i2c_adap, &msg, 1);
}
/* ------------------------------------------------------------------ */
struct tda827xa_data {
u32 lomax;
u8 svco;
@ -212,6 +360,35 @@ static const struct tda827xa_data tda827xa_dvbt[] = {
{ .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
};
static struct tda827xa_data tda827xa_analog[] = {
{ .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3},
{ .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
{ .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
{ .lomax = 97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
{ .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
{ .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
{ .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
{ .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
{ .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
{ .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
{ .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
{ .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
{ .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
{ .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
{ .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
{ .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
{ .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
{ .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
{ .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
{ .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
{ .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
{ .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
{ .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
{ .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
};
static int tda827xa_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
@ -368,6 +545,163 @@ static int tda827xa_sleep(struct dvb_frontend *fe)
return 0;
}
/* ------------------------------------------------------------------ */
static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
struct analog_parameters *params)
{
struct tda827x_priv *priv = fe->tuner_priv;
unsigned char buf[] = {0x22, 0x01};
int arg;
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
.buf = buf, .len = sizeof(buf) };
if (NULL == priv->cfg) {
dprintk("tda827x_config not defined, cannot set LNA gain!\n");
return;
}
if (priv->cfg->config) {
if (high)
dprintk("setting LNA to high gain\n");
else
dprintk("setting LNA to low gain\n");
}
switch (*priv->cfg->config) {
case 0: /* no LNA */
break;
case 1: /* switch is GPIO 0 of tda8290 */
case 2:
/* turn Vsync on */
if (params->std & V4L2_STD_MN)
arg = 1;
else
arg = 0;
if (priv->cfg->tuner_callback)
priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
1, arg);
buf[1] = high ? 0 : 1;
if (*priv->cfg->config == 2)
buf[1] = high ? 1 : 0;
i2c_transfer(priv->i2c_adap, &msg, 1);
break;
case 3: /* switch with GPIO of saa713x */
if (priv->cfg->tuner_callback)
priv->cfg->tuner_callback(priv->i2c_adap->algo_data,
0, high);
break;
}
}
static int tda827xa_set_analog_params(struct dvb_frontend *fe,
struct analog_parameters *params)
{
unsigned char tuner_reg[11];
u32 N;
int i;
struct tda827x_priv *priv = fe->tuner_priv;
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
.buf = tuner_reg, .len = sizeof(tuner_reg) };
unsigned int freq = params->frequency;
tda827x_set_std(fe, params);
tda827xa_lna_gain(fe, 1, params);
msleep(10);
if (params->mode == V4L2_TUNER_RADIO)
freq = freq / 1000;
N = freq + priv->sgIF;
i = 0;
while (tda827xa_analog[i].lomax < N * 62500) {
if (tda827xa_analog[i + 1].lomax == 0)
break;
i++;
}
N = N << tda827xa_analog[i].spd;
tuner_reg[0] = 0;
tuner_reg[1] = (unsigned char)(N>>8);
tuner_reg[2] = (unsigned char) N;
tuner_reg[3] = 0;
tuner_reg[4] = 0x16;
tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
(tda827xa_analog[i].svco << 3) +
tda827xa_analog[i].sbs;
tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
tuner_reg[7] = 0x1c;
tuner_reg[8] = 4;
tuner_reg[9] = 0x20;
tuner_reg[10] = 0x00;
msg.len = 11;
i2c_transfer(priv->i2c_adap, &msg, 1);
tuner_reg[0] = 0x90;
tuner_reg[1] = 0xff;
tuner_reg[2] = 0xe0;
tuner_reg[3] = 0;
tuner_reg[4] = 0x99 + (priv->lpsel << 1);
msg.len = 5;
i2c_transfer(priv->i2c_adap, &msg, 1);
tuner_reg[0] = 0xa0;
tuner_reg[1] = 0xc0;
msg.len = 2;
i2c_transfer(priv->i2c_adap, &msg, 1);
tuner_reg[0] = 0x30;
tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
i2c_transfer(priv->i2c_adap, &msg, 1);
msg.flags = I2C_M_RD;
i2c_transfer(priv->i2c_adap, &msg, 1);
msg.flags = 0;
tuner_reg[1] >>= 4;
dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
if (tuner_reg[1] < 1)
tda827xa_lna_gain(fe, 0, params);
msleep(100);
tuner_reg[0] = 0x60;
tuner_reg[1] = 0x3c;
i2c_transfer(priv->i2c_adap, &msg, 1);
msleep(163);
tuner_reg[0] = 0x50;
tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
i2c_transfer(priv->i2c_adap, &msg, 1);
tuner_reg[0] = 0x80;
tuner_reg[1] = 0x28;
i2c_transfer(priv->i2c_adap, &msg, 1);
tuner_reg[0] = 0xb0;
tuner_reg[1] = 0x01;
i2c_transfer(priv->i2c_adap, &msg, 1);
tuner_reg[0] = 0xc0;
tuner_reg[1] = 0x19 + (priv->lpsel << 1);
i2c_transfer(priv->i2c_adap, &msg, 1);
priv->frequency = freq * 62500;
return 0;
}
static void tda827xa_agcf(struct dvb_frontend *fe)
{
struct tda827x_priv *priv = fe->tuner_priv;
unsigned char data[] = {0x80, 0x2c};
struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
.buf = data, .len = 2};
i2c_transfer(priv->i2c_adap, &msg, 1);
}
/* ------------------------------------------------------------------ */
static int tda827x_release(struct dvb_frontend *fe)
{
kfree(fe->tuner_priv);
@ -430,6 +764,7 @@ static struct dvb_tuner_ops tda827xo_tuner_ops = {
.init = tda827x_initial_init,
.sleep = tda827x_initial_sleep,
.set_params = tda827xo_set_params,
.set_analog_params = tda827xo_set_analog_params,
.get_frequency = tda827x_get_frequency,
.get_bandwidth = tda827x_get_bandwidth,
};
@ -445,6 +780,7 @@ static struct dvb_tuner_ops tda827xa_tuner_ops = {
.init = tda827x_init,
.sleep = tda827xa_sleep,
.set_params = tda827xa_set_params,
.set_analog_params = tda827xa_set_analog_params,
.get_frequency = tda827x_get_frequency,
.get_bandwidth = tda827x_get_bandwidth,
};
@ -465,9 +801,13 @@ static int tda827x_probe_version(struct dvb_frontend *fe)
dprintk("tda827x tuner found\n");
fe->ops.tuner_ops.init = tda827x_init;
fe->ops.tuner_ops.sleep = tda827xo_sleep;
if (priv->cfg)
priv->cfg->agcf = tda827xo_agcf;
} else {
dprintk("tda827xa tuner found\n");
memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
if (priv->cfg)
priv->cfg->agcf = tda827xa_agcf;
}
return 0;
}
@ -487,16 +827,13 @@ struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
priv->i2c_adap = i2c;
priv->cfg = cfg;
memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
fe->tuner_priv = priv;
dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
return fe;
}
EXPORT_SYMBOL(tda827x_attach);
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
EXPORT_SYMBOL_GPL(tda827x_attach);
MODULE_DESCRIPTION("DVB TDA827x driver");
MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>");

View File

@ -29,9 +29,16 @@
struct tda827x_config
{
/* saa7134 - provided callbacks */
void (*lna_gain) (struct dvb_frontend *fe, int high);
int (*init) (struct dvb_frontend *fe);
int (*sleep) (struct dvb_frontend *fe);
/* interface to tda829x driver */
unsigned int *config;
int (*tuner_callback) (void *dev, int command, int arg);
void (*agcf)(struct dvb_frontend *fe);
};

View File

@ -65,7 +65,7 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1)
printk("ves1820: %s(): writereg error (reg == 0x%02x,"
printk("ves1820: %s(): writereg error (reg == 0x%02x, "
"val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret);
return (ret != 1) ? -EREMOTEIO : 0;
@ -84,7 +84,7 @@ static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2)
printk("ves1820: %s(): readreg error (reg == 0x%02x,"
printk("ves1820: %s(): readreg error (reg == 0x%02x, "
"ret == %i)\n", __FUNCTION__, reg, ret);
return b1[0];

View File

@ -0,0 +1,964 @@
/*
* Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
*
* Copyright (c) 2007 Xceive Corporation
* Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/videodev2.h>
#include <linux/delay.h>
#include <linux/dvb/frontend.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
#include "xc5000.h"
#include "xc5000_priv.h"
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
#define dprintk(level,fmt, arg...) if (debug >= level) \
printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
#define XC5000_DEFAULT_FIRMWARE "dvb-fe-xc5000-1.1.fw"
#define XC5000_DEFAULT_FIRMWARE_SIZE 12332
/* Misc Defines */
#define MAX_TV_STANDARD 23
#define XC_MAX_I2C_WRITE_LENGTH 64
/* 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 0x1388
/* Registers */
#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_IF_OUT 0x05
#define XREG_SEEK_MODE 0x07
#define XREG_POWER_DOWN 0x0A
#define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
#define XREG_SMOOTHEDCVBS 0x0E
#define XREG_XTALFREQ 0x0F
#define XREG_FINERFFREQ 0x10
#define XREG_DDIMODE 0x11
#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
#define XREG_BUSY 0x09
/*
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.
*/
typedef struct {
char *Name;
u16 AudioMode;
u16 VideoMode;
} XC_TV_STANDARD;
/* Tuner standards */
#define MN_NTSC_PAL_BTSC 0
#define MN_NTSC_PAL_A2 1
#define MN_NTSC_PAL_EIAJ 2
#define MN_NTSC_PAL_Mono 3
#define BG_PAL_A2 4
#define BG_PAL_NICAM 5
#define BG_PAL_MONO 6
#define I_PAL_NICAM 7
#define I_PAL_NICAM_MONO 8
#define DK_PAL_A2 9
#define DK_PAL_NICAM 10
#define DK_PAL_MONO 11
#define DK_SECAM_A2DK1 12
#define DK_SECAM_A2LDK3 13
#define DK_SECAM_A2MONO 14
#define L_SECAM_NICAM 15
#define LC_SECAM_NICAM 16
#define DTV6 17
#define DTV8 18
#define DTV7_8 19
#define DTV7 20
#define FM_Radio_INPUT2 21
#define FM_Radio_INPUT1 22
XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
{"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
{"M/N-NTSC/PAL-A2", 0x0600, 0x8020},
{"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
{"M/N-NTSC/PAL-Mono", 0x0478, 0x8020},
{"B/G-PAL-A2", 0x0A00, 0x8049},
{"B/G-PAL-NICAM", 0x0C04, 0x8049},
{"B/G-PAL-MONO", 0x0878, 0x8059},
{"I-PAL-NICAM", 0x1080, 0x8009},
{"I-PAL-NICAM-MONO", 0x0E78, 0x8009},
{"D/K-PAL-A2", 0x1600, 0x8009},
{"D/K-PAL-NICAM", 0x0E80, 0x8009},
{"D/K-PAL-MONO", 0x1478, 0x8009},
{"D/K-SECAM-A2 DK1", 0x1200, 0x8009},
{"D/K-SECAM-A2 L/DK3",0x0E00, 0x8009},
{"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
{"L-SECAM-NICAM", 0x8E82, 0x0009},
{"L'-SECAM-NICAM", 0x8E82, 0x4009},
{"DTV6", 0x00C0, 0x8002},
{"DTV8", 0x00C0, 0x800B},
{"DTV7/8", 0x00C0, 0x801B},
{"DTV7", 0x00C0, 0x8007},
{"FM Radio-INPUT2", 0x9802, 0x9002},
{"FM Radio-INPUT1", 0x0208, 0x9002}
};
static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len);
static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len);
static void xc5000_TunerReset(struct dvb_frontend *fe);
static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
{
return xc5000_writeregs(priv, buf, len)
? XC_RESULT_I2C_WRITE_FAILURE : XC_RESULT_SUCCESS;
}
static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
{
return xc5000_readregs(priv, buf, len)
? XC_RESULT_I2C_READ_FAILURE : XC_RESULT_SUCCESS;
}
static int xc_reset(struct dvb_frontend *fe)
{
xc5000_TunerReset(fe);
return XC_RESULT_SUCCESS;
}
static void xc_wait(int wait_ms)
{
msleep(wait_ms);
}
static void xc5000_TunerReset(struct dvb_frontend *fe)
{
struct xc5000_priv *priv = fe->tuner_priv;
int ret;
dprintk(1, "%s()\n", __FUNCTION__);
if (priv->cfg->tuner_callback) {
ret = priv->cfg->tuner_callback(priv->cfg->priv,
XC5000_TUNER_RESET, 0);
if (ret)
printk(KERN_ERR "xc5000: reset failed\n");
} else
printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n");
}
static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
{
u8 buf[4];
int WatchDogTimer = 5;
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);
if (result == XC_RESULT_SUCCESS) {
/* wait for busy flag to clear */
while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) {
buf[0] = 0;
buf[1] = XREG_BUSY;
result = xc_send_i2c_data(priv, buf, 2);
if (result == XC_RESULT_SUCCESS) {
result = xc_read_i2c_data(priv, buf, 2);
if (result == XC_RESULT_SUCCESS) {
if ((buf[0] == 0) && (buf[1] == 0)) {
/* busy flag cleared */
break;
} else {
xc_wait(100); /* wait 5 ms */
WatchDogTimer--;
}
}
}
}
}
if (WatchDogTimer < 0)
result = XC_RESULT_I2C_WRITE_FAILURE;
return result;
}
static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData)
{
u8 buf[2];
int result;
buf[0] = (regAddr >> 8) & 0xFF;
buf[1] = regAddr & 0xFF;
result = xc_send_i2c_data(priv, buf, 2);
if (result != XC_RESULT_SUCCESS)
return result;
result = xc_read_i2c_data(priv, buf, 2);
if (result != XC_RESULT_SUCCESS)
return result;
*i2cData = buf[0] * 256 + buf[1];
return result;
}
static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
{
struct xc5000_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 */
result = xc_reset(fe);
index += 2;
if (result != XC_RESULT_SUCCESS)
return result;
} 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_initialize(struct xc5000_priv *priv)
{
dprintk(1, "%s()\n", __FUNCTION__);
return xc_write_reg(priv, XREG_INIT, 0);
}
static int xc_SetTVStandard(struct xc5000_priv *priv,
u16 VideoMode, u16 AudioMode)
{
int ret;
dprintk(1, "%s(0x%04x,0x%04x)\n", __FUNCTION__, VideoMode, AudioMode);
dprintk(1, "%s() Standard = %s\n",
__FUNCTION__,
XC5000_Standard[priv->video_standard].Name);
ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
if (ret == XC_RESULT_SUCCESS)
ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode);
return ret;
}
static int xc_shutdown(struct xc5000_priv *priv)
{
return 0;
/* Fixme: cannot bring tuner back alive once shutdown
* without reloading the driver modules.
* return xc_write_reg(priv, XREG_POWER_DOWN, 0);
*/
}
static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
{
dprintk(1, "%s(%d) Source = %s\n", __FUNCTION__, 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",
__FUNCTION__);
}
return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
}
static const struct dvb_tuner_ops xc5000_tuner_ops;
static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
{
u16 freq_code;
dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
(freq_hz < xc5000_tuner_ops.info.frequency_min))
return XC_RESULT_OUT_OF_RANGE;
freq_code = (u16)(freq_hz / 15625);
return xc_write_reg(priv, XREG_RF_FREQ, freq_code);
}
static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
{
u32 freq_code = (freq_khz * 1024)/1000;
dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
__FUNCTION__, freq_khz, freq_code);
return xc_write_reg(priv, XREG_IF_OUT, freq_code);
}
static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope)
{
return xc_read_reg(priv, XREG_ADC_ENV, adc_envelope);
}
static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
{
int result;
u16 regData;
u32 tmp;
result = xc_read_reg(priv, XREG_FREQ_ERROR, &regData);
if (result)
return result;
tmp = (u32)regData;
(*freq_error_hz) = (tmp * 15625) / 1000;
return result;
}
static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
{
return xc_read_reg(priv, XREG_LOCK, lock_status);
}
static int xc_get_version(struct xc5000_priv *priv,
u8 *hw_majorversion, u8 *hw_minorversion,
u8 *fw_majorversion, u8 *fw_minorversion)
{
u16 data;
int result;
result = xc_read_reg(priv, XREG_VERSION, &data);
if (result)
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 xc5000_priv *priv, u32 *hsync_freq_hz)
{
u16 regData;
int result;
result = xc_read_reg(priv, XREG_HSYNC_FREQ, &regData);
if (result)
return result;
(*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
return result;
}
static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
{
return xc_read_reg(priv, XREG_FRAME_LINES, frame_lines);
}
static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
{
return xc_read_reg(priv, XREG_QUALITY, quality);
}
static u16 WaitForLock(struct xc5000_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 xc5000_priv *priv, u32 freq_hz)
{
int found = 0;
dprintk(1, "%s(%u)\n", __FUNCTION__, freq_hz);
if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
return 0;
if (WaitForLock(priv) == 1)
found = 1;
return found;
}
static int xc5000_readreg(struct xc5000_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->cfg->i2c_address,
.flags = 0, .buf = &buf[0], .len = 2 },
{ .addr = priv->cfg->i2c_address,
.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
};
if (i2c_transfer(priv->i2c, msg, 2) != 2) {
printk(KERN_WARNING "xc5000: I2C read failed\n");
return -EREMOTEIO;
}
*val = (bval[0] << 8) | bval[1];
return 0;
}
static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len)
{
struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
.flags = 0, .buf = buf, .len = len };
if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n",
(int)len);
return -EREMOTEIO;
}
return 0;
}
static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len)
{
struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
.flags = I2C_M_RD, .buf = buf, .len = len };
if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n",(int)len);
return -EREMOTEIO;
}
return 0;
}
static int xc5000_fwupload(struct dvb_frontend* fe)
{
struct xc5000_priv *priv = fe->tuner_priv;
const struct firmware *fw;
int ret;
/* request the firmware, this will block and timeout */
printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
XC5000_DEFAULT_FIRMWARE);
ret = request_firmware(&fw, XC5000_DEFAULT_FIRMWARE, &priv->i2c->dev);
if (ret) {
printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
ret = XC_RESULT_RESET_FAILURE;
goto out;
} else {
printk(KERN_INFO "xc5000: firmware read %Zu bytes.\n",
fw->size);
ret = XC_RESULT_SUCCESS;
}
if (fw->size != XC5000_DEFAULT_FIRMWARE_SIZE) {
printk(KERN_ERR "xc5000: firmware incorrect size\n");
ret = XC_RESULT_RESET_FAILURE;
} else {
printk(KERN_INFO "xc5000: firmware upload\n");
ret = xc_load_i2c_sequence(fe, fw->data );
}
out:
release_firmware(fw);
return ret;
}
static void xc_debug_dump(struct xc5000_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;
/* 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);
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);
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 xc5000_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
struct xc5000_priv *priv = fe->tuner_priv;
int ret;
dprintk(1, "%s() frequency=%d (Hz)\n", __FUNCTION__, params->frequency);
switch(params->u.vsb.modulation) {
case VSB_8:
case VSB_16:
dprintk(1, "%s() VSB modulation\n", __FUNCTION__);
priv->rf_mode = XC_RF_MODE_AIR;
priv->freq_hz = params->frequency - 1750000;
priv->bandwidth = BANDWIDTH_6_MHZ;
priv->video_standard = DTV6;
break;
case QAM_64:
case QAM_256:
case QAM_AUTO:
dprintk(1, "%s() QAM modulation\n", __FUNCTION__);
priv->rf_mode = XC_RF_MODE_CABLE;
priv->freq_hz = params->frequency - 1750000;
priv->bandwidth = BANDWIDTH_6_MHZ;
priv->video_standard = DTV6;
break;
default:
return -EINVAL;
}
dprintk(1, "%s() frequency=%d (compensated)\n",
__FUNCTION__, priv->freq_hz);
ret = xc_SetSignalSource(priv, priv->rf_mode);
if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR
"xc5000: xc_SetSignalSource(%d) failed\n",
priv->rf_mode);
return -EREMOTEIO;
}
ret = xc_SetTVStandard(priv,
XC5000_Standard[priv->video_standard].VideoMode,
XC5000_Standard[priv->video_standard].AudioMode);
if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
return -EREMOTEIO;
}
ret = xc_set_IF_frequency(priv, priv->cfg->if_khz);
if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
priv->cfg->if_khz);
return -EIO;
}
xc_tune_channel(priv, priv->freq_hz);
if (debug)
xc_debug_dump(priv);
return 0;
}
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
static int xc5000_set_analog_params(struct dvb_frontend *fe,
struct analog_parameters *params)
{
struct xc5000_priv *priv = fe->tuner_priv;
int ret;
if(priv->fwloaded == 0)
xc_load_fw_and_init_tuner(fe);
dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
__FUNCTION__, params->frequency);
priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */
/* params->frequency is in units of 62.5khz */
priv->freq_hz = params->frequency * 62500;
/* FIX ME: Some video standards may have several possible audio
standards. We simply default to one of them here.
*/
if(params->std & V4L2_STD_MN) {
/* default to BTSC audio standard */
priv->video_standard = MN_NTSC_PAL_BTSC;
goto tune_channel;
}
if(params->std & V4L2_STD_PAL_BG) {
/* default to NICAM audio standard */
priv->video_standard = BG_PAL_NICAM;
goto tune_channel;
}
if(params->std & V4L2_STD_PAL_I) {
/* default to NICAM audio standard */
priv->video_standard = I_PAL_NICAM;
goto tune_channel;
}
if(params->std & V4L2_STD_PAL_DK) {
/* default to NICAM audio standard */
priv->video_standard = DK_PAL_NICAM;
goto tune_channel;
}
if(params->std & V4L2_STD_SECAM_DK) {
/* default to A2 DK1 audio standard */
priv->video_standard = DK_SECAM_A2DK1;
goto tune_channel;
}
if(params->std & V4L2_STD_SECAM_L) {
priv->video_standard = L_SECAM_NICAM;
goto tune_channel;
}
if(params->std & V4L2_STD_SECAM_LC) {
priv->video_standard = LC_SECAM_NICAM;
goto tune_channel;
}
tune_channel:
ret = xc_SetSignalSource(priv, priv->rf_mode);
if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR
"xc5000: xc_SetSignalSource(%d) failed\n",
priv->rf_mode);
return -EREMOTEIO;
}
ret = xc_SetTVStandard(priv,
XC5000_Standard[priv->video_standard].VideoMode,
XC5000_Standard[priv->video_standard].AudioMode);
if (ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
return -EREMOTEIO;
}
xc_tune_channel(priv, priv->freq_hz);
if (debug)
xc_debug_dump(priv);
return 0;
}
static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
{
struct xc5000_priv *priv = fe->tuner_priv;
dprintk(1, "%s()\n", __FUNCTION__);
*freq = priv->freq_hz;
return 0;
}
static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
{
struct xc5000_priv *priv = fe->tuner_priv;
dprintk(1, "%s()\n", __FUNCTION__);
*bw = priv->bandwidth;
return 0;
}
static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
{
struct xc5000_priv *priv = fe->tuner_priv;
u16 lock_status = 0;
xc_get_lock_status(priv, &lock_status);
dprintk(1, "%s() lock_status = 0x%08x\n", __FUNCTION__, lock_status);
*status = lock_status;
return 0;
}
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
{
struct xc5000_priv *priv = fe->tuner_priv;
int ret = 0;
if (priv->fwloaded == 0) {
ret = xc5000_fwupload(fe);
if (ret != XC_RESULT_SUCCESS)
return ret;
priv->fwloaded = 1;
}
/* Start the tuner self-calibration process */
ret |= xc_initialize(priv);
/* Wait for calibration to complete.
* We could continue but XC5000 will clock stretch subsequent
* I2C transactions until calibration is complete. This way we
* don't have to rely on clock stretching working.
*/
xc_wait( 100 );
/* Default to "CABLE" mode */
ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
return ret;
}
static int xc5000_sleep(struct dvb_frontend *fe)
{
struct xc5000_priv *priv = fe->tuner_priv;
int ret;
dprintk(1, "%s()\n", __FUNCTION__);
/* On Pinnacle PCTV HD 800i, the tuner cannot be reinitialized
* once shutdown without reloading the driver. Maybe I am not
* doing something right.
*
*/
ret = xc_shutdown(priv);
if(ret != XC_RESULT_SUCCESS) {
printk(KERN_ERR
"xc5000: %s() unable to shutdown tuner\n",
__FUNCTION__);
return -EREMOTEIO;
}
else {
/* priv->fwloaded = 0; */
return XC_RESULT_SUCCESS;
}
}
static int xc5000_init(struct dvb_frontend *fe)
{
struct xc5000_priv *priv = fe->tuner_priv;
dprintk(1, "%s()\n", __FUNCTION__);
if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
return -EREMOTEIO;
}
if (debug)
xc_debug_dump(priv);
return 0;
}
static int xc5000_release(struct dvb_frontend *fe)
{
dprintk(1, "%s()\n", __FUNCTION__);
kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
return 0;
}
static const struct dvb_tuner_ops xc5000_tuner_ops = {
.info = {
.name = "Xceive XC5000",
.frequency_min = 1000000,
.frequency_max = 1023000000,
.frequency_step = 50000,
},
.release = xc5000_release,
.init = xc5000_init,
.sleep = xc5000_sleep,
.set_params = xc5000_set_params,
.set_analog_params = xc5000_set_analog_params,
.get_frequency = xc5000_get_frequency,
.get_bandwidth = xc5000_get_bandwidth,
.get_status = xc5000_get_status
};
struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct xc5000_config *cfg)
{
struct xc5000_priv *priv = NULL;
u16 id = 0;
dprintk(1, "%s()\n", __FUNCTION__);
priv = kzalloc(sizeof(struct xc5000_priv), GFP_KERNEL);
if (priv == NULL)
return NULL;
priv->cfg = cfg;
priv->bandwidth = BANDWIDTH_6_MHZ;
priv->i2c = i2c;
/* Check if firmware has been loaded. It is possible that another
instance of the driver has loaded the firmware.
*/
if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) {
kfree(priv);
return NULL;
}
switch(id) {
case XC_PRODUCT_ID_FW_LOADED:
printk(KERN_INFO
"xc5000: Successfully identified at address 0x%02x\n",
cfg->i2c_address);
printk(KERN_INFO
"xc5000: Firmware has been loaded previously\n");
priv->fwloaded = 1;
break;
case XC_PRODUCT_ID_FW_NOT_LOADED:
printk(KERN_INFO
"xc5000: Successfully identified at address 0x%02x\n",
cfg->i2c_address);
printk(KERN_INFO
"xc5000: Firmware has not been loaded previously\n");
priv->fwloaded = 0;
break;
default:
printk(KERN_ERR
"xc5000: Device not found at addr 0x%02x (0x%x)\n",
cfg->i2c_address, id);
kfree(priv);
return NULL;
}
memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
sizeof(struct dvb_tuner_ops));
fe->tuner_priv = priv;
return fe;
}
EXPORT_SYMBOL(xc5000_attach);
MODULE_AUTHOR("Steven Toth");
MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,62 @@
/*
* Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
*
* Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __XC5000_H__
#define __XC5000_H__
#include <linux/firmware.h>
struct dvb_frontend;
struct i2c_adapter;
struct xc5000_config {
u8 i2c_address;
u32 if_khz;
/* 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 priv accordingly.
* The xc5000 driver cares not for this value, other than ensuring
* it's passed back to a bridge during tuner_callback().
*/
void *priv;
int (*tuner_callback) (void *priv, int command, int arg);
};
/* xc5000 callback command */
#define XC5000_TUNER_RESET 0
#if defined(CONFIG_DVB_TUNER_XC5000) || defined(CONFIG_DVB_TUNER_XC5000_MODULE)
extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct xc5000_config *cfg);
#else
static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
struct xc5000_config *cfg)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}
#endif // CONFIG_DVB_TUNER_XC5000
#endif // __XC5000_H__

View File

@ -0,0 +1,36 @@
/*
* Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
*
* Copyright (c) 2007 Steven Toth <stoth@hauppauge.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef XC5000_PRIV_H
#define XC5000_PRIV_H
struct xc5000_priv {
struct xc5000_config *cfg;
struct i2c_adapter *i2c;
u32 freq_hz;
u32 bandwidth;
u8 video_standard;
u8 rf_mode;
u8 fwloaded;
};
#endif

View File

@ -1,7 +1,7 @@
/*
* Driver for Zarlink DVB-T ZL10353 demodulator
*
* Copyright (C) 2006 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
* Copyright (C) 2006, 2007 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
*
* 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
@ -16,7 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
@ -25,6 +25,7 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <asm/div64.h>
#include "dvb_frontend.h"
#include "zl10353_priv.h"
@ -35,6 +36,8 @@ struct zl10353_state {
struct dvb_frontend frontend;
struct zl10353_config config;
enum fe_bandwidth bandwidth;
};
static int debug;
@ -122,9 +125,10 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
enum fe_bandwidth bandwidth,
u16 *nominal_rate)
{
u32 adc_clock = 45056; /* 45.056 MHz */
u8 bw;
struct zl10353_state *state = fe->demodulator_priv;
u32 adc_clock = 450560; /* 45.056 MHz */
u64 value;
u8 bw;
if (state->config.adc_clock)
adc_clock = state->config.adc_clock;
@ -142,12 +146,44 @@ static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
break;
}
*nominal_rate = (bw * (1 << 23) / 7 * 125 + adc_clock / 2) / adc_clock;
value = (u64)10 * (1 << 23) / 7 * 125;
value = (bw * value) + adc_clock / 2;
do_div(value, adc_clock);
*nominal_rate = value;
dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
__FUNCTION__, bw, adc_clock, *nominal_rate);
}
static void zl10353_calc_input_freq(struct dvb_frontend *fe,
u16 *input_freq)
{
struct zl10353_state *state = fe->demodulator_priv;
u32 adc_clock = 450560; /* 45.056 MHz */
int if2 = 361667; /* 36.1667 MHz */
int ife;
u64 value;
if (state->config.adc_clock)
adc_clock = state->config.adc_clock;
if (state->config.if2)
if2 = state->config.if2;
if (adc_clock >= if2 * 2)
ife = if2;
else {
ife = adc_clock - (if2 % adc_clock);
if (ife > adc_clock / 2)
ife = adc_clock - ife;
}
value = (u64)65536 * ife + adc_clock / 2;
do_div(value, adc_clock);
*input_freq = -value;
dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
__FUNCTION__, if2, ife, adc_clock, -(int)value, *input_freq);
}
static int zl10353_sleep(struct dvb_frontend *fe)
{
static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 };
@ -160,64 +196,276 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
struct dvb_frontend_parameters *param)
{
struct zl10353_state *state = fe->demodulator_priv;
u16 nominal_rate;
u8 pllbuf[6] = { 0x67 };
u16 nominal_rate, input_freq;
u8 pllbuf[6] = { 0x67 }, acq_ctl = 0;
u16 tps = 0;
struct dvb_ofdm_parameters *op = &param->u.ofdm;
/* These settings set "auto-everything" and start the FSM. */
zl10353_single_write(fe, 0x55, 0x80);
zl10353_single_write(fe, RESET, 0x80);
udelay(200);
zl10353_single_write(fe, 0xEA, 0x01);
udelay(200);
zl10353_single_write(fe, 0xEA, 0x00);
zl10353_single_write(fe, 0x56, 0x28);
zl10353_single_write(fe, 0x89, 0x20);
zl10353_single_write(fe, 0x5E, 0x00);
zl10353_single_write(fe, AGC_TARGET, 0x28);
zl10353_calc_nominal_rate(fe, param->u.ofdm.bandwidth, &nominal_rate);
if (op->transmission_mode != TRANSMISSION_MODE_AUTO)
acq_ctl |= (1 << 0);
if (op->guard_interval != GUARD_INTERVAL_AUTO)
acq_ctl |= (1 << 1);
zl10353_single_write(fe, ACQ_CTL, acq_ctl);
switch (op->bandwidth) {
case BANDWIDTH_6_MHZ:
/* These are extrapolated from the 7 and 8MHz values */
zl10353_single_write(fe, MCLK_RATIO, 0x97);
zl10353_single_write(fe, 0x64, 0x34);
break;
case BANDWIDTH_7_MHZ:
zl10353_single_write(fe, MCLK_RATIO, 0x86);
zl10353_single_write(fe, 0x64, 0x35);
break;
case BANDWIDTH_8_MHZ:
default:
zl10353_single_write(fe, MCLK_RATIO, 0x75);
zl10353_single_write(fe, 0x64, 0x36);
}
zl10353_calc_nominal_rate(fe, op->bandwidth, &nominal_rate);
zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
state->bandwidth = op->bandwidth;
zl10353_calc_input_freq(fe, &input_freq);
zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq));
zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq));
/* Hint at TPS settings */
switch (op->code_rate_HP) {
case FEC_2_3:
tps |= (1 << 7);
break;
case FEC_3_4:
tps |= (2 << 7);
break;
case FEC_5_6:
tps |= (3 << 7);
break;
case FEC_7_8:
tps |= (4 << 7);
break;
case FEC_1_2:
case FEC_AUTO:
break;
default:
return -EINVAL;
}
switch (op->code_rate_LP) {
case FEC_2_3:
tps |= (1 << 4);
break;
case FEC_3_4:
tps |= (2 << 4);
break;
case FEC_5_6:
tps |= (3 << 4);
break;
case FEC_7_8:
tps |= (4 << 4);
break;
case FEC_1_2:
case FEC_AUTO:
break;
case FEC_NONE:
if (op->hierarchy_information == HIERARCHY_AUTO ||
op->hierarchy_information == HIERARCHY_NONE)
break;
default:
return -EINVAL;
}
switch (op->constellation) {
case QPSK:
break;
case QAM_AUTO:
case QAM_16:
tps |= (1 << 13);
break;
case QAM_64:
tps |= (2 << 13);
break;
default:
return -EINVAL;
}
switch (op->transmission_mode) {
case TRANSMISSION_MODE_2K:
case TRANSMISSION_MODE_AUTO:
break;
case TRANSMISSION_MODE_8K:
tps |= (1 << 0);
break;
default:
return -EINVAL;
}
switch (op->guard_interval) {
case GUARD_INTERVAL_1_32:
case GUARD_INTERVAL_AUTO:
break;
case GUARD_INTERVAL_1_16:
tps |= (1 << 2);
break;
case GUARD_INTERVAL_1_8:
tps |= (2 << 2);
break;
case GUARD_INTERVAL_1_4:
tps |= (3 << 2);
break;
default:
return -EINVAL;
}
switch (op->hierarchy_information) {
case HIERARCHY_AUTO:
case HIERARCHY_NONE:
break;
case HIERARCHY_1:
tps |= (1 << 10);
break;
case HIERARCHY_2:
tps |= (2 << 10);
break;
case HIERARCHY_4:
tps |= (3 << 10);
break;
default:
return -EINVAL;
}
zl10353_single_write(fe, TPS_GIVEN_1, msb(tps));
zl10353_single_write(fe, TPS_GIVEN_0, lsb(tps));
zl10353_single_write(fe, 0x6C, 0xCD);
zl10353_single_write(fe, 0x6D, 0x7E);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
// if there is no attached secondary tuner, we call set_params to program
// a potential tuner attached somewhere else
/*
* If there is no tuner attached to the secondary I2C bus, we call
* set_params to program a potential tuner attached somewhere else.
* Otherwise, we update the PLL registers via calc_regs.
*/
if (state->config.no_tuner) {
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, param);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
}
}
// if pllbuf is defined, retrieve the settings
if (fe->ops.tuner_ops.calc_regs) {
fe->ops.tuner_ops.calc_regs(fe, param, pllbuf+1, 5);
} else if (fe->ops.tuner_ops.calc_regs) {
fe->ops.tuner_ops.calc_regs(fe, param, pllbuf + 1, 5);
pllbuf[1] <<= 1;
} else {
// fake pllbuf settings
pllbuf[1] = 0x61 << 1;
pllbuf[2] = 0;
pllbuf[3] = 0;
pllbuf[3] = 0;
pllbuf[4] = 0;
zl10353_write(fe, pllbuf, sizeof(pllbuf));
}
// there is no call to _just_ start decoding, so we send the pllbuf anyway
// even if there isn't a PLL attached to the secondary bus
zl10353_write(fe, pllbuf, sizeof(pllbuf));
zl10353_single_write(fe, 0x5F, 0x13);
zl10353_single_write(fe, 0x70, 0x01);
udelay(250);
zl10353_single_write(fe, 0xE4, 0x00);
zl10353_single_write(fe, 0xE5, 0x2A);
zl10353_single_write(fe, 0xE9, 0x02);
zl10353_single_write(fe, 0xE7, 0x40);
zl10353_single_write(fe, 0xE8, 0x10);
/* If no attached tuner or invalid PLL registers, just start the FSM. */
if (state->config.no_tuner || fe->ops.tuner_ops.calc_regs == NULL)
zl10353_single_write(fe, FSM_GO, 0x01);
else
zl10353_single_write(fe, TUNER_GO, 0x01);
return 0;
}
static int zl10353_get_parameters(struct dvb_frontend *fe,
struct dvb_frontend_parameters *param)
{
struct zl10353_state *state = fe->demodulator_priv;
struct dvb_ofdm_parameters *op = &param->u.ofdm;
int s6, s9;
u16 tps;
static const u8 tps_fec_to_api[8] = {
FEC_1_2,
FEC_2_3,
FEC_3_4,
FEC_5_6,
FEC_7_8,
FEC_AUTO,
FEC_AUTO,
FEC_AUTO
};
s6 = zl10353_read_register(state, STATUS_6);
s9 = zl10353_read_register(state, STATUS_9);
if (s6 < 0 || s9 < 0)
return -EREMOTEIO;
if ((s6 & (1 << 5)) == 0 || (s9 & (1 << 4)) == 0)
return -EINVAL; /* no FE or TPS lock */
tps = zl10353_read_register(state, TPS_RECEIVED_1) << 8 |
zl10353_read_register(state, TPS_RECEIVED_0);
op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
switch ((tps >> 13) & 3) {
case 0:
op->constellation = QPSK;
break;
case 1:
op->constellation = QAM_16;
break;
case 2:
op->constellation = QAM_64;
break;
default:
op->constellation = QAM_AUTO;
break;
}
op->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K :
TRANSMISSION_MODE_2K;
switch ((tps >> 2) & 3) {
case 0:
op->guard_interval = GUARD_INTERVAL_1_32;
break;
case 1:
op->guard_interval = GUARD_INTERVAL_1_16;
break;
case 2:
op->guard_interval = GUARD_INTERVAL_1_8;
break;
case 3:
op->guard_interval = GUARD_INTERVAL_1_4;
break;
default:
op->guard_interval = GUARD_INTERVAL_AUTO;
break;
}
switch ((tps >> 10) & 7) {
case 0:
op->hierarchy_information = HIERARCHY_NONE;
break;
case 1:
op->hierarchy_information = HIERARCHY_1;
break;
case 2:
op->hierarchy_information = HIERARCHY_2;
break;
case 3:
op->hierarchy_information = HIERARCHY_4;
break;
default:
op->hierarchy_information = HIERARCHY_AUTO;
break;
}
param->frequency = 0;
op->bandwidth = state->bandwidth;
param->inversion = INVERSION_AUTO;
return 0;
}
@ -406,6 +654,7 @@ static struct dvb_frontend_ops zl10353_ops = {
.write = zl10353_write,
.set_frontend = zl10353_set_parameters,
.get_frontend = zl10353_get_parameters,
.get_tune_settings = zl10353_get_tune_settings,
.read_status = zl10353_read_status,

View File

@ -1,7 +1,7 @@
/*
* Driver for Zarlink DVB-T ZL10353 demodulator
*
* Copyright (C) 2006 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
* Copyright (C) 2006, 2007 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
*
* 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
@ -29,8 +29,9 @@ struct zl10353_config
/* demodulator's I2C address */
u8 demod_address;
/* frequencies in kHz */
int adc_clock; /* default: 45056 */
/* frequencies in units of 0.1kHz */
int adc_clock; /* default: 450560 (45.056 MHz) */
int if2; /* default: 361667 (36.1667 MHz) */
/* set if no pll is connected to the secondary i2c bus */
int no_tuner;
@ -49,6 +50,6 @@ static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *c
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}
#endif // CONFIG_DVB_ZL10353
#endif /* CONFIG_DVB_ZL10353 */
#endif /* ZL10353_H */

View File

@ -1,7 +1,7 @@
/*
* Driver for Zarlink DVB-T ZL10353 demodulator
*
* Copyright (C) 2006 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
* Copyright (C) 2006, 2007 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
*
* 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
@ -16,7 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ZL10353_PRIV_
@ -46,9 +46,28 @@ enum zl10353_reg_addr {
RS_ERR_CNT_0 = 0x13,
RS_UBC_1 = 0x14,
RS_UBC_0 = 0x15,
TPS_RECEIVED_1 = 0x1D,
TPS_RECEIVED_0 = 0x1E,
TPS_CURRENT_1 = 0x1F,
TPS_CURRENT_0 = 0x20,
RESET = 0x55,
AGC_TARGET = 0x56,
MCLK_RATIO = 0x5C,
ACQ_CTL = 0x5E,
TRL_NOMINAL_RATE_1 = 0x65,
TRL_NOMINAL_RATE_0 = 0x66,
INPUT_FREQ_1 = 0x6C,
INPUT_FREQ_0 = 0x6D,
TPS_GIVEN_1 = 0x6E,
TPS_GIVEN_0 = 0x6F,
TUNER_GO = 0x70,
FSM_GO = 0x71,
CHIP_ID = 0x7F,
CHAN_STEP_1 = 0xE4,
CHAN_STEP_0 = 0xE5,
OFDM_LOCK_TIME = 0xE7,
FEC_LOCK_TIME = 0xE8,
ACQ_DELAY = 0xE9,
};
#endif /* _ZL10353_PRIV_ */

View File

@ -1,8 +1,14 @@
config TTPCI_EEPROM
tristate
default n
config DVB_AV7110
tristate "AV7110 cards"
depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
depends on DVB_CORE && PCI && I2C
select FW_LOADER if !DVB_AV7110_FIRMWARE
select TTPCI_EEPROM
select VIDEO_SAA7146_VV
depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV
select DVB_VES1820 if !DVB_FE_CUSTOMISE
select DVB_VES1X93 if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
@ -57,10 +63,19 @@ config DVB_AV7110_OSD
All other people say N.
config DVB_BUDGET_CORE
tristate "SAA7146 DVB cards (aka Budget, Nova-PCI)"
depends on DVB_CORE && PCI && I2C
select VIDEO_SAA7146
select TTPCI_EEPROM
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
MPEG2 decoder.
config DVB_BUDGET
tristate "Budget cards"
depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
select VIDEO_SAA7146
depends on DVB_BUDGET_CORE && I2C
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_VES1X93 if !DVB_FE_CUSTOMISE
select DVB_VES1820 if !DVB_FE_CUSTOMISE
@ -73,9 +88,9 @@ config DVB_BUDGET
select DVB_TDA826X if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
help
Support for simple SAA7146 based DVB cards
(so called Budget- or Nova-PCI cards) without onboard
MPEG2 decoder.
Support for simple SAA7146 based DVB cards (so called Budget-
or Nova-PCI cards) without onboard MPEG2 decoder, and without
analog inputs or an onboard Common Interface connector.
Say Y if you own such a card and want to use it.
@ -84,8 +99,7 @@ config DVB_BUDGET
config DVB_BUDGET_CI
tristate "Budget cards with onboard CI connector"
depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 && INPUT
select VIDEO_SAA7146
depends on DVB_BUDGET_CORE && I2C
select DVB_STV0297 if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
@ -106,8 +120,9 @@ config DVB_BUDGET_CI
config DVB_BUDGET_AV
tristate "Budget cards with analog video inputs"
depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
depends on DVB_BUDGET_CORE && I2C
select VIDEO_SAA7146_VV
depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV
select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
@ -127,8 +142,8 @@ config DVB_BUDGET_AV
config DVB_BUDGET_PATCH
tristate "AV7110 cards with Budget Patch"
depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1
select DVB_AV7110
depends on DVB_BUDGET_CORE && I2C
depends on DVB_AV7110
select DVB_STV0299 if !DVB_FE_CUSTOMISE
select DVB_VES1X93 if !DVB_FE_CUSTOMISE
select DVB_TDA8083 if !DVB_FE_CUSTOMISE

View File

@ -5,11 +5,13 @@
dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o av7110_ca.o av7110.o av7110_ipack.o av7110_ir.o
obj-$(CONFIG_DVB_BUDGET) += budget-core.o budget.o ttpci-eeprom.o
obj-$(CONFIG_DVB_BUDGET_AV) += budget-core.o budget-av.o ttpci-eeprom.o
obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o budget-ci.o ttpci-eeprom.o
obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o budget-patch.o ttpci-eeprom.o
obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o
obj-$(CONFIG_TTPCI_EEPROM) += ttpci-eeprom.o
obj-$(CONFIG_DVB_BUDGET_CORE) += budget-core.o
obj-$(CONFIG_DVB_BUDGET) += budget.o
obj-$(CONFIG_DVB_BUDGET_AV) += budget-av.o
obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o
obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/

View File

@ -2595,7 +2595,8 @@ static int __devinit av7110_attach(struct saa7146_dev* dev,
mutex_init(&av7110->osd_mutex);
/* TV standard */
av7110->vidmode = tv_standard == 1 ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL;
av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
: AV7110_VIDEO_MODE_PAL;
/* ARM "watchdog" */
init_waitqueue_head(&av7110->arm_wait);

View File

@ -46,6 +46,11 @@ extern int av7110_debug;
enum {AV_PES_STREAM, PS_STREAM, TS_STREAM, PES_STREAM};
enum av7110_video_mode {
AV7110_VIDEO_MODE_PAL = 0,
AV7110_VIDEO_MODE_NTSC = 1
};
struct av7110_p2t {
u8 pes[TS_SIZE];
u8 counter;
@ -170,7 +175,7 @@ struct av7110 {
ca_slot_info_t ci_slot[2];
int vidmode;
enum av7110_video_mode vidmode;
struct dmxdev dmxdev;
struct dvb_demux demux;

View File

@ -329,7 +329,7 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
return 0;
}
int av7110_set_vidmode(struct av7110 *av7110, int mode)
int av7110_set_vidmode(struct av7110 *av7110, enum av7110_video_mode mode)
{
int ret;
dprintk(2, "av7110:%p, \n", av7110);
@ -348,11 +348,15 @@ int av7110_set_vidmode(struct av7110 *av7110, int mode)
}
static int sw2mode[16] = {
VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_NTSC, VIDEO_MODE_PAL,
VIDEO_MODE_NTSC, VIDEO_MODE_NTSC, VIDEO_MODE_PAL, VIDEO_MODE_NTSC,
VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL,
VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL,
static enum av7110_video_mode sw2mode[16] = {
AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_NTSC,
AV7110_VIDEO_MODE_NTSC, AV7110_VIDEO_MODE_PAL,
AV7110_VIDEO_MODE_NTSC, AV7110_VIDEO_MODE_NTSC,
AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_NTSC,
AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
};
static int get_video_format(struct av7110 *av7110, u8 *buf, int count)

View File

@ -3,7 +3,8 @@
struct av7110;
extern int av7110_set_vidmode(struct av7110 *av7110, int mode);
extern int av7110_set_vidmode(struct av7110 *av7110,
enum av7110_video_mode mode);
extern int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len);
extern int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen);

View File

@ -876,11 +876,11 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
if (std->id & V4L2_STD_PAL) {
av7110->vidmode = VIDEO_MODE_PAL;
av7110->vidmode = AV7110_VIDEO_MODE_PAL;
av7110_set_vidmode(av7110, av7110->vidmode);
}
else if (std->id & V4L2_STD_NTSC) {
av7110->vidmode = VIDEO_MODE_NTSC;
av7110->vidmode = AV7110_VIDEO_MODE_NTSC;
av7110_set_vidmode(av7110, av7110->vidmode);
}
else

View File

@ -351,4 +351,14 @@ config USB_DSBR
To compile this driver as a module, choose M here: the
module will be called dsbr100.
config USB_SI470X
tristate "Silicon Labs Si470x FM Radio Receiver support"
depends on USB && VIDEO_V4L2
---help---
Say Y here if you want to connect this type of radio to your
computer's USB port.
To compile this driver as a module, choose M here: the
module will be called radio-silabs.
endif # RADIO_ADAPTERS

View File

@ -21,5 +21,6 @@ obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
obj-$(CONFIG_USB_SI470X) += radio-si470x.o
EXTRA_CFLAGS += -Isound

View File

@ -33,6 +33,9 @@
History:
Version 0.43:
Oliver Neukum: avoided DMA coherency issue
Version 0.42:
Converted dsbr100 to use video_ioctl2
by Douglas Landgraf <dougsland@gmail.com>
@ -135,7 +138,7 @@ module_param(radio_nr, int, 0);
struct dsbr100_device {
struct usb_device *usbdev;
struct video_device *videodev;
unsigned char transfer_buffer[TB_LEN];
u8 *transfer_buffer;
int curfreq;
int stereo;
int users;
@ -237,10 +240,7 @@ static void dsbr100_getstat(struct dsbr100_device *radio)
/* handle unplugging of the device, release data structures
if nothing keeps us from doing it. If something is still
keeping us busy, the release callback of v4l will take care
of releasing it. stv680.c does not relase its private
data, so I don't do this here either. Checking out the
code I'd expect I better did that, but if there's a memory
leak here it's tiny (~50 bytes per disconnect) */
of releasing it. */
static void usb_dsbr100_disconnect(struct usb_interface *intf)
{
struct dsbr100_device *radio = usb_get_intfdata(intf);
@ -250,6 +250,7 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf)
video_unregister_device(radio->videodev);
radio->videodev = NULL;
if (radio->users) {
kfree(radio->transfer_buffer);
kfree(radio);
} else {
radio->removed = 1;
@ -425,6 +426,7 @@ static int usb_dsbr100_close(struct inode *inode, struct file *file)
return -ENODEV;
radio->users = 0;
if (radio->removed) {
kfree(radio->transfer_buffer);
kfree(radio);
}
return 0;
@ -471,7 +473,12 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
return -ENOMEM;
if (!(radio->transfer_buffer = kmalloc(TB_LEN, GFP_KERNEL))) {
kfree(radio);
return -ENOMEM;
}
if (!(radio->videodev = video_device_alloc())) {
kfree(radio->transfer_buffer);
kfree(radio);
return -ENOMEM;
}
@ -485,6 +492,7 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) {
warn("Could not register video device");
video_device_release(radio->videodev);
kfree(radio->transfer_buffer);
kfree(radio);
return -EIO;
}

View File

@ -58,10 +58,10 @@ static int initmute = 1;
static int radio_nr = -1;
module_param(io, int, 0444);
MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic"
MODULE_PARM_DESC(io, "Force I/O port for the GemTek Radio card if automatic "
"probing is disabled or fails. The most common I/O ports are: 0x20c "
"0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to "
" work for the combined sound/radiocard).");
"work for the combined sound/radiocard).");
module_param(probe, bool, 0444);
MODULE_PARM_DESC(probe, "Enable automatic device probing. Note: only the most "
@ -392,7 +392,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
}
};
static struct file_operations gemtek_fops = {
static const struct file_operations gemtek_fops = {
.owner = THIS_MODULE,
.open = video_exclusive_open,
.release = video_exclusive_release,

View File

@ -423,7 +423,7 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
errunr:
video_unregister_device(maestro_radio_inst);
errfr1:
kfree(maestro_radio_inst);
video_device_release(maestro_radio_inst);
errfr:
kfree(radio_unit);
err:

View File

@ -321,7 +321,7 @@ static struct isapnp_device_id id_table[] __devinitdata = {
MODULE_DEVICE_TABLE(isapnp, id_table);
static int isapnp_fmi_probe(void)
static int __init isapnp_fmi_probe(void)
{
int i = 0;

View File

@ -476,8 +476,7 @@ static int __init fmr2_init(void)
return -EBUSY;
}
if(video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr)==-1)
{
if (video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr) < 0) {
release_region(io, 2);
return -EINVAL;
}

File diff suppressed because it is too large Load Diff

View File

@ -45,7 +45,7 @@ comment "Audio decoders"
config VIDEO_TVAUDIO
tristate "Simple audio decoder chips"
depends on VIDEO_V4L1 && I2C
depends on VIDEO_V4L2 && I2C
---help---
Support for several audio decoder chips found on some bt8xx boards:
Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300,
@ -57,7 +57,7 @@ config VIDEO_TVAUDIO
config VIDEO_TDA7432
tristate "Philips TDA7432 audio processor"
depends on VIDEO_V4L1 && I2C
depends on VIDEO_V4L2 && I2C
---help---
Support for tda7432 audio decoder chip found on some bt8xx boards.
@ -75,7 +75,7 @@ config VIDEO_TDA9840
config VIDEO_TDA9875
tristate "Philips TDA9875 audio processor"
depends on VIDEO_V4L1 && I2C
depends on VIDEO_V4L2 && I2C
---help---
Support for tda9875 audio decoder chip found on some bt8xx boards.
@ -109,9 +109,19 @@ config VIDEO_MSP3400
To compile this driver as a module, choose M here: the
module will be called msp3400.
config VIDEO_CS5345
tristate "Cirrus Logic CS5345 audio ADC"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
---help---
Support for the Cirrus Logic CS5345 24-bit, 192 kHz
stereo A/D converter.
To compile this driver as a module, choose M here: the
module will be called cs5345.
config VIDEO_CS53L32A
tristate "Cirrus Logic CS53L32A audio ADC"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
depends on VIDEO_V4L2 && I2C
---help---
Support for the Cirrus Logic CS53L32A low voltage
stereo A/D converter.
@ -119,6 +129,15 @@ config VIDEO_CS53L32A
To compile this driver as a module, choose M here: the
module will be called cs53l32a.
config VIDEO_M52790
tristate "Mitsubishi M52790 A/V switch"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
---help---
Support for the Mitsubishi M52790 A/V switch.
To compile this driver as a module, choose M here: the
module will be called m52790.
config VIDEO_TLV320AIC23B
tristate "Texas Instruments TLV320AIC23B audio codec"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
@ -130,7 +149,7 @@ config VIDEO_TLV320AIC23B
config VIDEO_WM8775
tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
depends on VIDEO_V4L2 && I2C
---help---
Support for the Wolfson Microelectronics WM8775 high
performance stereo A/D Converter with a 4 channel input mixer.
@ -140,7 +159,7 @@ config VIDEO_WM8775
config VIDEO_WM8739
tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
depends on VIDEO_V4L2 && I2C
---help---
Support for the Wolfson Microelectronics WM8739
stereo A/D Converter.
@ -244,7 +263,7 @@ config VIDEO_SAA7114
config VIDEO_SAA711X
tristate "Philips SAA7113/4/5 video decoders"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
depends on VIDEO_V4L2 && I2C
---help---
Support for the Philips SAA7113/4/5 video decoders.
@ -300,7 +319,7 @@ comment "Video encoders"
config VIDEO_SAA7127
tristate "Philips SAA7127/9 digital video encoders"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
depends on VIDEO_V4L2 && I2C
---help---
Support for the Philips SAA7127/9 digital video encoders.
@ -338,7 +357,7 @@ comment "Video improvement chips"
config VIDEO_UPD64031A
tristate "NEC Electronics uPD64031A Ghost Reduction"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
depends on VIDEO_V4L2 && I2C
---help---
Support for the NEC Electronics uPD64031A Ghost Reduction
video chip. It is most often found in NTSC TV cards made for
@ -350,7 +369,7 @@ config VIDEO_UPD64031A
config VIDEO_UPD64083
tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
depends on VIDEO_V4L2 && I2C
---help---
Support for the NEC Electronics uPD64083 3-Dimensional Y/C
separation video chip. It is used to improve the quality of
@ -802,6 +821,19 @@ config USB_ZR364XX
To compile this driver as a module, choose M here: the
module will be called zr364xx.
config USB_STKWEBCAM
tristate "USB Syntek DC1125 Camera support"
depends on VIDEO_V4L2 && EXPERIMENTAL
---help---
Say Y here if you want to use this type of camera.
Supported devices are typically found in some Asus laptops,
with USB id 174f:a311 and 05e1:0501. Other Syntek cameras
may be supported by the stk11xx driver, from which this is
derived, see http://stk11xx.sourceforge.net
To compile this driver as a module, choose M here: the
module will be called stkwebcam.
endif # V4L_USB_DRIVERS
endif # VIDEO_CAPTURE_DRIVERS

View File

@ -4,10 +4,12 @@
zr36067-objs := zoran_procfs.o zoran_device.o \
zoran_driver.o zoran_card.o
tuner-objs := tuner-core.o tuner-types.o tda9887.o
tuner-objs := tuner-core.o tuner-types.o
msp3400-objs := msp3400-driver.o msp3400-kthreads.o
stkwebcam-objs := stk-webcam.o stk-sensor.o
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \
v4l2-int-device.o
@ -66,7 +68,9 @@ obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
obj-$(CONFIG_VIDEO_M52790) += m52790.o
obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
@ -81,11 +85,13 @@ obj-$(CONFIG_TUNER_3036) += tuner-3036.o
obj-$(CONFIG_VIDEO_TUNER) += tuner.o
obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o
obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
obj-$(CONFIG_TUNER_TEA5761) += tea5761.o
obj-$(CONFIG_TUNER_TDA9887) += tda9887.o
obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
@ -112,6 +118,7 @@ obj-$(CONFIG_USB_SE401) += se401.o
obj-$(CONFIG_USB_STV680) += stv680.o
obj-$(CONFIG_USB_W9968CF) += w9968cf.o
obj-$(CONFIG_USB_ZR364XX) += zr364xx.o
obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o
obj-$(CONFIG_USB_SN9C102) += sn9c102/
obj-$(CONFIG_USB_ET61X251) += et61x251/
@ -129,3 +136,4 @@ obj-$(CONFIG_VIDEO_VIVI) += vivi.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885/
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends

View File

@ -1,6 +1,6 @@
config VIDEO_BT848
tristate "BT848 Video For Linux"
depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L1
depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT
select I2C_ALGOBIT
select FW_LOADER
select VIDEO_BTCX

View File

@ -4,7 +4,7 @@
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
bttv-input.o
bttv-input.o bttv-audio-hook.o
obj-$(CONFIG_VIDEO_BT848) += bttv.o

View File

@ -0,0 +1,382 @@
/*
* Handlers for board audio hooks, splitted from bttv-cards
*
* Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
* This code is placed under the terms of the GNU General Public License
*/
#include "bttv-audio-hook.h"
#include <linux/delay.h>
/* ----------------------------------------------------------------------- */
/* winview */
void winview_volume(struct bttv *btv, __u16 volume)
{
/* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
int bits_out, loops, vol, data;
/* 32 levels logarithmic */
vol = 32 - ((volume>>11));
/* units */
bits_out = (PT2254_DBS_IN_2>>(vol%5));
/* tens */
bits_out |= (PT2254_DBS_IN_10>>(vol/5));
bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL;
data = gpio_read();
data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
WINVIEW_PT2254_STROBE);
for (loops = 17; loops >= 0 ; loops--) {
if (bits_out & (1<<loops))
data |= WINVIEW_PT2254_DATA;
else
data &= ~WINVIEW_PT2254_DATA;
gpio_write(data);
udelay(5);
data |= WINVIEW_PT2254_CLK;
gpio_write(data);
udelay(5);
data &= ~WINVIEW_PT2254_CLK;
gpio_write(data);
}
data |= WINVIEW_PT2254_STROBE;
data &= ~WINVIEW_PT2254_DATA;
gpio_write(data);
udelay(10);
data &= ~WINVIEW_PT2254_STROBE;
gpio_write(data);
}
/* ----------------------------------------------------------------------- */
/* mono/stereo control for various cards (which don't use i2c chips but */
/* connect something to the GPIO pins */
void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
unsigned int con = 0;
if (set) {
gpio_inout(0x300, 0x300);
if (t->audmode & V4L2_TUNER_MODE_LANG1)
con = 0x000;
if (t->audmode & V4L2_TUNER_MODE_LANG2)
con = 0x300;
if (t->audmode & V4L2_TUNER_MODE_STEREO)
con = 0x200;
/* if (t->audmode & V4L2_TUNER_MODE_MONO)
* con = 0x100; */
gpio_bits(0x300, con);
} else {
t->audmode = V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
}
}
void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
unsigned int val, con;
if (btv->radio_user)
return;
val = gpio_read();
if (set) {
con = 0x000;
if (t->audmode & V4L2_TUNER_MODE_LANG2) {
if (t->audmode & V4L2_TUNER_MODE_LANG1) {
/* LANG1 + LANG2 */
con = 0x100;
}
else {
/* LANG2 */
con = 0x300;
}
}
if (con != (val & 0x300)) {
gpio_bits(0x300, con);
if (bttv_gpio)
bttv_gpio_tracking(btv,"gvbctv5pci");
}
} else {
switch (val & 0x70) {
case 0x10:
t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
break;
case 0x30:
t->rxsubchans = V4L2_TUNER_SUB_LANG2;
break;
case 0x50:
t->rxsubchans = V4L2_TUNER_SUB_LANG1;
break;
case 0x60:
t->rxsubchans = V4L2_TUNER_SUB_STEREO;
break;
case 0x70:
t->rxsubchans = V4L2_TUNER_SUB_MONO;
break;
default:
t->rxsubchans = V4L2_TUNER_SUB_MONO |
V4L2_TUNER_SUB_STEREO |
V4L2_TUNER_SUB_LANG1 |
V4L2_TUNER_SUB_LANG2;
}
t->audmode = V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
}
}
/*
* Mario Medina Nussbaum <medisoft@alohabbs.org.mx>
* I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
* 0xdde enables mono and 0xccd enables sap
*
* Petr Vandrovec <VANDROVE@vc.cvut.cz>
* P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
* input/output sound connection, so both must be set for output mode.
*
* Looks like it's needed only for the "tvphone", the "tvphone 98"
* handles this with a tda9840
*
*/
void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
int val = 0;
if (set) {
if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
val = 0x02;
if (t->audmode & V4L2_TUNER_MODE_STEREO)
val = 0x01;
if (val) {
gpio_bits(0x03,val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"avermedia");
}
} else {
t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1;
return;
}
}
void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
int val = 0;
if (set) {
if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
val = 0x01;
if (t->audmode & V4L2_TUNER_MODE_STEREO) /* STEREO */
val = 0x02;
btaor(val, ~0x03, BT848_GPIO_DATA);
if (bttv_gpio)
bttv_gpio_tracking(btv,"avermedia");
} else {
t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
return;
}
}
/* Lifetec 9415 handling */
void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
int val = 0;
if (gpio_read() & 0x4000) {
t->audmode = V4L2_TUNER_MODE_MONO;
return;
}
if (set) {
if (t->audmode & V4L2_TUNER_MODE_LANG2) /* A2 SAP */
val = 0x0080;
if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */
val = 0x0880;
if ((t->audmode & V4L2_TUNER_MODE_LANG1) ||
(t->audmode & V4L2_TUNER_MODE_MONO))
val = 0;
gpio_bits(0x0880, val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"lt9415");
} else {
/* autodetect doesn't work with this card :-( */
t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
return;
}
}
/* TDA9821 on TerraTV+ Bt848, Bt878 */
void terratv_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
unsigned int con = 0;
if (set) {
gpio_inout(0x180000,0x180000);
if (t->audmode & V4L2_TUNER_MODE_LANG2)
con = 0x080000;
if (t->audmode & V4L2_TUNER_MODE_STEREO)
con = 0x180000;
gpio_bits(0x180000, con);
if (bttv_gpio)
bttv_gpio_tracking(btv,"terratv");
} else {
t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
}
}
void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
unsigned long val = 0;
if (set) {
/*btor (0xc32000, BT848_GPIO_OUT_EN);*/
if (t->audmode & V4L2_TUNER_MODE_MONO) /* Mono */
val = 0x420000;
if (t->audmode & V4L2_TUNER_MODE_LANG1) /* Mono */
val = 0x420000;
if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
val = 0x410000;
if (t->audmode & V4L2_TUNER_MODE_STEREO) /* Stereo */
val = 0x020000;
if (val) {
gpio_bits(0x430000, val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"winfast2000");
}
} else {
t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
}
}
/*
* Dariusz Kowalewski <darekk@automex.pl>
* sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
* revision 9B has on-board TDA9874A sound decoder).
*
* Note: There are card variants without tda9874a. Forcing the "stereo sound route"
* will mute this cards.
*/
void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
unsigned int val = 0;
if (btv->radio_user)
return;
if (set) {
if (t->audmode & V4L2_TUNER_MODE_MONO) {
val = 0x01;
}
if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
|| (t->audmode & V4L2_TUNER_MODE_STEREO)) {
val = 0x02;
}
if (val) {
gpio_bits(0x03,val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"pvbt878p9b");
}
} else {
t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
}
}
/*
* Dariusz Kowalewski <darekk@automex.pl>
* sound control for FlyVideo 2000S (with tda9874 decoder)
* based on pvbt878p9b_audio() - this is not tested, please fix!!!
*/
void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
unsigned int val = 0xffff;
if (btv->radio_user)
return;
if (set) {
if (t->audmode & V4L2_TUNER_MODE_MONO) {
val = 0x0000;
}
if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
|| (t->audmode & V4L2_TUNER_MODE_STEREO)) {
val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
}
if (val != 0xffff) {
gpio_bits(0x1800, val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"fv2000s");
}
} else {
t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
}
}
/*
* sound control for Canopus WinDVR PCI
* Masaki Suzuki <masaki@btree.org>
*/
void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
unsigned long val = 0;
if (set) {
if (t->audmode & V4L2_TUNER_MODE_MONO)
val = 0x040000;
if (t->audmode & V4L2_TUNER_MODE_LANG1)
val = 0;
if (t->audmode & V4L2_TUNER_MODE_LANG2)
val = 0x100000;
if (t->audmode & V4L2_TUNER_MODE_STEREO)
val = 0;
if (val) {
gpio_bits(0x140000, val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"windvr");
}
} else {
t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
}
}
/*
* sound control for AD-TVK503
* Hiroshi Takekawa <sian@big.or.jp>
*/
void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
unsigned int con = 0xffffff;
/* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
if (set) {
/* btor(***, BT848_GPIO_OUT_EN); */
if (t->audmode & V4L2_TUNER_MODE_LANG1)
con = 0x00000000;
if (t->audmode & V4L2_TUNER_MODE_LANG2)
con = 0x00180000;
if (t->audmode & V4L2_TUNER_MODE_STEREO)
con = 0x00000000;
if (t->audmode & V4L2_TUNER_MODE_MONO)
con = 0x00060000;
if (con != 0xffffff) {
gpio_bits(0x1e0000,con);
if (bttv_gpio)
bttv_gpio_tracking(btv, "adtvk503");
}
} else {
t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
}
}

View File

@ -0,0 +1,23 @@
/*
* Handlers for board audio hooks, splitted from bttv-cards
*
* Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
* This code is placed under the terms of the GNU General Public License
*/
#include "bttvp.h"
void winview_volume (struct bttv *btv, __u16 volume);
void lt9415_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void terratv_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void windvr_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);

View File

@ -39,6 +39,7 @@
#include "bttvp.h"
#include <media/v4l2-common.h>
#include <media/tvaudio.h>
#include "bttv-audio-hook.h"
/* fwd decl */
static void boot_msp34xx(struct bttv *btv, int pin);
@ -50,20 +51,6 @@ static void modtec_eeprom(struct bttv *btv);
static void init_PXC200(struct bttv *btv);
static void init_RTV24(struct bttv *btv);
static void winview_audio(struct bttv *btv, struct video_audio *v, int set);
static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set);
static void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v,
int set);
static void avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v,
int set);
static void terratv_audio(struct bttv *btv, struct video_audio *v, int set);
static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set);
static void gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set);
static void winfast2000_audio(struct bttv *btv, struct video_audio *v, int set);
static void pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set);
static void fv2000s_audio(struct bttv *btv, struct video_audio *v, int set);
static void windvr_audio(struct bttv *btv, struct video_audio *v, int set);
static void adtvk503_audio(struct bttv *btv, struct video_audio *v, int set);
static void rv605_muxsel(struct bttv *btv, unsigned int input);
static void eagle_muxsel(struct bttv *btv, unsigned int input);
static void xguard_muxsel(struct bttv *btv, unsigned int input);
@ -427,7 +414,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = avermedia_tvphone_audio,
.audio_mode_gpio= avermedia_tvphone_audio,
.has_remote = 1,
},
[BTTV_BOARD_MATRIX_VISION] = {
@ -539,7 +526,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = avermedia_tv_stereo_audio,
.audio_mode_gpio= avermedia_tv_stereo_audio,
.no_gpioirq = 1,
},
[BTTV_BOARD_VHX] = {
@ -604,7 +591,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = winview_audio,
.volume_gpio = winview_volume,
.has_radio = 1,
},
[BTTV_BOARD_AVEC_INTERCAP] = {
@ -728,7 +715,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = terratv_audio,
.audio_mode_gpio= terratv_audio,
},
[BTTV_BOARD_HAUPPAUG_WCAM] = {
.name = "Hauppauge WinCam newer (bt878)",
@ -776,7 +763,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = terratv_audio,
.audio_mode_gpio= terratv_audio,
/* GPIO wiring:
External 20 pin connector (for Active Radio Upgrade board)
gpio00: i2c-sda
@ -915,7 +902,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL, /* default for now, gpio reads BFFF06 for Pal bg+dk */
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = winfast2000_audio,
.audio_mode_gpio= winfast2000_audio,
.has_remote = 1,
},
[BTTV_BOARD_CHRONOS_VS2] = {
@ -1035,7 +1022,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.has_radio = 1,
.audio_hook = avermedia_tvphone_audio,
.audio_mode_gpio= avermedia_tvphone_audio,
},
[BTTV_BOARD_PV951] = {
.name = "ProVideo PV951", /* pic16c54 */
@ -1167,7 +1154,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_ALPS_TSHC6_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = gvbctv3pci_audio,
.audio_mode_gpio= gvbctv3pci_audio,
},
[BTTV_BOARD_PXELVWPLTVPAK] = {
.name = "Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP",
@ -1472,7 +1459,7 @@ struct tvcard bttv_tvcards[] = {
/* -dk-???: set mute=0x1800 for tda9874h daughterboard */
.gpiomux = { 0x0000,0x0800,0x1000,0x1000 },
.gpiomute = 0x1800,
.audio_hook = fv2000s_audio,
.audio_mode_gpio= fv2000s_audio,
.no_msp34xx = 1,
.no_tda9875 = 1,
.needs_tvaudio = 1,
@ -1513,7 +1500,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_SHARP_2U5JF5540_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = gvbctv3pci_audio,
.audio_mode_gpio= gvbctv3pci_audio,
},
/* ---- card 0x44 ---------------------------------- */
@ -1632,7 +1619,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_PAL,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = pvbt878p9b_audio, /* Note: not all cards have stereo */
.audio_mode_gpio= pvbt878p9b_audio, /* Note: not all cards have stereo */
.has_radio = 1, /* Note: not all cards have radio */
.has_remote = 1,
/* GPIO wiring:
@ -1710,7 +1697,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = windvr_audio,
.audio_mode_gpio= windvr_audio,
},
[BTTV_BOARD_GRANDTEC_MULTI] = {
.name = "GrandTec Multi Capture Card (Bt878)",
@ -1807,7 +1794,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_NTSC_M,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = gvbctv5pci_audio,
.audio_mode_gpio= gvbctv5pci_audio,
.has_radio = 1,
},
[BTTV_BOARD_OSPREY1x0] = {
@ -2106,7 +2093,7 @@ struct tvcard bttv_tvcards[] = {
.tuner_type = TUNER_PHILIPS_NTSC,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
.audio_hook = adtvk503_audio,
.audio_mode_gpio= adtvk503_audio,
},
/* ---- card 0x64 ---------------------------------- */
@ -3173,8 +3160,8 @@ static void flyvideo_gpio(struct bttv *btv)
/* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
* LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
* Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */
if(has_tda9820_tda9821) btv->audio_hook = lt9415_audio;
/* todo: if(has_tda9874) btv->audio_hook = fv2000s_audio; */
if(has_tda9820_tda9821) btv->audio_mode_gpio = lt9415_audio;
/* todo: if(has_tda9874) btv->audio_mode_gpio = fv2000s_audio; */
}
static int miro_tunermap[] = { 0,6,2,3, 4,5,6,0, 3,0,4,5, 5,2,16,1,
@ -3574,8 +3561,12 @@ void __devinit bttv_init_card2(struct bttv *btv)
}
if (btv->tda9887_conf) {
bttv_call_i2c_clients(btv, TDA9887_SET_CONFIG,
&btv->tda9887_conf);
struct v4l2_priv_tun_config tda9887_cfg;
tda9887_cfg.tuner = TUNER_TDA9887;
tda9887_cfg.priv = &btv->tda9887_conf;
bttv_call_i2c_clients(btv, TUNER_SET_CONFIG, &tda9887_cfg);
}
btv->svhs = bttv_tvcards[btv->c.type].svhs;
@ -3590,8 +3581,10 @@ void __devinit bttv_init_card2(struct bttv *btv)
btv->has_remote=1;
if (!bttv_tvcards[btv->c.type].no_gpioirq)
btv->gpioirq=1;
if (bttv_tvcards[btv->c.type].audio_hook)
btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook;
if (bttv_tvcards[btv->c.type].volume_gpio)
btv->volume_gpio=bttv_tvcards[btv->c.type].volume_gpio;
if (bttv_tvcards[btv->c.type].audio_mode_gpio)
btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio;
if (bttv_tvcards[btv->c.type].digital_mode == DIGITAL_MODE_CAMERA) {
/* detect Bt832 chip for quartzsight digital camera */
@ -3950,7 +3943,7 @@ static void __devinit avermedia_eeprom(struct bttv *btv)
void bttv_tda9880_setnorm(struct bttv *btv, int norm)
{
/* fix up our card entry */
if(norm==VIDEO_MODE_NTSC) {
if(norm==V4L2_STD_NTSC) {
bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].gpiomute=0x957fff;
bttv_tvcards[BTTV_BOARD_VOODOOTV_200].gpiomux[TVAUDIO_INPUT_TUNER]=0x957fff;
@ -4319,387 +4312,6 @@ void tea5757_set_freq(struct bttv *btv, unsigned short freq)
tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
}
/* ----------------------------------------------------------------------- */
/* winview */
static void winview_audio(struct bttv *btv, struct video_audio *v, int set)
{
/* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
int bits_out, loops, vol, data;
if (!set) {
/* Fixed by Leandro Lucarella <luca@linuxmendoza.org.ar (07/31/01) */
v->flags |= VIDEO_AUDIO_VOLUME;
return;
}
/* 32 levels logarithmic */
vol = 32 - ((v->volume>>11));
/* units */
bits_out = (PT2254_DBS_IN_2>>(vol%5));
/* tens */
bits_out |= (PT2254_DBS_IN_10>>(vol/5));
bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL;
data = gpio_read();
data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
WINVIEW_PT2254_STROBE);
for (loops = 17; loops >= 0 ; loops--) {
if (bits_out & (1<<loops))
data |= WINVIEW_PT2254_DATA;
else
data &= ~WINVIEW_PT2254_DATA;
gpio_write(data);
udelay(5);
data |= WINVIEW_PT2254_CLK;
gpio_write(data);
udelay(5);
data &= ~WINVIEW_PT2254_CLK;
gpio_write(data);
}
data |= WINVIEW_PT2254_STROBE;
data &= ~WINVIEW_PT2254_DATA;
gpio_write(data);
udelay(10);
data &= ~WINVIEW_PT2254_STROBE;
gpio_write(data);
}
/* ----------------------------------------------------------------------- */
/* mono/stereo control for various cards (which don't use i2c chips but */
/* connect something to the GPIO pins */
static void
gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int con = 0;
if (set) {
gpio_inout(0x300, 0x300);
if (v->mode & VIDEO_SOUND_LANG1)
con = 0x000;
if (v->mode & VIDEO_SOUND_LANG2)
con = 0x300;
if (v->mode & VIDEO_SOUND_STEREO)
con = 0x200;
/* if (v->mode & VIDEO_SOUND_MONO)
* con = 0x100; */
gpio_bits(0x300, con);
} else {
v->mode = VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
static void
gvbctv5pci_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int val, con;
if (btv->radio_user)
return;
val = gpio_read();
if (set) {
con = 0x000;
if (v->mode & VIDEO_SOUND_LANG2) {
if (v->mode & VIDEO_SOUND_LANG1) {
/* LANG1 + LANG2 */
con = 0x100;
}
else {
/* LANG2 */
con = 0x300;
}
}
if (con != (val & 0x300)) {
gpio_bits(0x300, con);
if (bttv_gpio)
bttv_gpio_tracking(btv,"gvbctv5pci");
}
} else {
switch (val & 0x70) {
case 0x10:
v->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
break;
case 0x30:
v->mode = VIDEO_SOUND_LANG2;
break;
case 0x50:
v->mode = VIDEO_SOUND_LANG1;
break;
case 0x60:
v->mode = VIDEO_SOUND_STEREO;
break;
case 0x70:
v->mode = VIDEO_SOUND_MONO;
break;
default:
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
}
/*
* Mario Medina Nussbaum <medisoft@alohabbs.org.mx>
* I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
* 0xdde enables mono and 0xccd enables sap
*
* Petr Vandrovec <VANDROVE@vc.cvut.cz>
* P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
* input/output sound connection, so both must be set for output mode.
*
* Looks like it's needed only for the "tvphone", the "tvphone 98"
* handles this with a tda9840
*
*/
static void
avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set)
{
int val = 0;
if (set) {
if (v->mode & VIDEO_SOUND_LANG2) /* SAP */
val = 0x02;
if (v->mode & VIDEO_SOUND_STEREO)
val = 0x01;
if (val) {
gpio_bits(0x03,val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"avermedia");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1;
return;
}
}
static void
avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set)
{
int val = 0;
if (set) {
if (v->mode & VIDEO_SOUND_LANG2) /* SAP */
val = 0x01;
if (v->mode & VIDEO_SOUND_STEREO) /* STEREO */
val = 0x02;
btaor(val, ~0x03, BT848_GPIO_DATA);
if (bttv_gpio)
bttv_gpio_tracking(btv,"avermedia");
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
return;
}
}
/* Lifetec 9415 handling */
static void
lt9415_audio(struct bttv *btv, struct video_audio *v, int set)
{
int val = 0;
if (gpio_read() & 0x4000) {
v->mode = VIDEO_SOUND_MONO;
return;
}
if (set) {
if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */
val = 0x0080;
if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */
val = 0x0880;
if ((v->mode & VIDEO_SOUND_LANG1) ||
(v->mode & VIDEO_SOUND_MONO))
val = 0;
gpio_bits(0x0880, val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"lt9415");
} else {
/* autodetect doesn't work with this card :-( */
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
return;
}
}
/* TDA9821 on TerraTV+ Bt848, Bt878 */
static void
terratv_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int con = 0;
if (set) {
gpio_inout(0x180000,0x180000);
if (v->mode & VIDEO_SOUND_LANG2)
con = 0x080000;
if (v->mode & VIDEO_SOUND_STEREO)
con = 0x180000;
gpio_bits(0x180000, con);
if (bttv_gpio)
bttv_gpio_tracking(btv,"terratv");
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
static void
winfast2000_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned long val = 0;
if (set) {
/*btor (0xc32000, BT848_GPIO_OUT_EN);*/
if (v->mode & VIDEO_SOUND_MONO) /* Mono */
val = 0x420000;
if (v->mode & VIDEO_SOUND_LANG1) /* Mono */
val = 0x420000;
if (v->mode & VIDEO_SOUND_LANG2) /* SAP */
val = 0x410000;
if (v->mode & VIDEO_SOUND_STEREO) /* Stereo */
val = 0x020000;
if (val) {
gpio_bits(0x430000, val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"winfast2000");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
/*
* Dariusz Kowalewski <darekk@automex.pl>
* sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
* revision 9B has on-board TDA9874A sound decoder).
*
* Note: There are card variants without tda9874a. Forcing the "stereo sound route"
* will mute this cards.
*/
static void
pvbt878p9b_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int val = 0;
if (btv->radio_user)
return;
if (set) {
if (v->mode & VIDEO_SOUND_MONO) {
val = 0x01;
}
if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
|| (v->mode & VIDEO_SOUND_STEREO)) {
val = 0x02;
}
if (val) {
gpio_bits(0x03,val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"pvbt878p9b");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
/*
* Dariusz Kowalewski <darekk@automex.pl>
* sound control for FlyVideo 2000S (with tda9874 decoder)
* based on pvbt878p9b_audio() - this is not tested, please fix!!!
*/
static void
fv2000s_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int val = 0xffff;
if (btv->radio_user)
return;
if (set) {
if (v->mode & VIDEO_SOUND_MONO) {
val = 0x0000;
}
if ((v->mode & (VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2))
|| (v->mode & VIDEO_SOUND_STEREO)) {
val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
}
if (val != 0xffff) {
gpio_bits(0x1800, val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"fv2000s");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
/*
* sound control for Canopus WinDVR PCI
* Masaki Suzuki <masaki@btree.org>
*/
static void
windvr_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned long val = 0;
if (set) {
if (v->mode & VIDEO_SOUND_MONO)
val = 0x040000;
if (v->mode & VIDEO_SOUND_LANG1)
val = 0;
if (v->mode & VIDEO_SOUND_LANG2)
val = 0x100000;
if (v->mode & VIDEO_SOUND_STEREO)
val = 0;
if (val) {
gpio_bits(0x140000, val);
if (bttv_gpio)
bttv_gpio_tracking(btv,"windvr");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
/*
* sound control for AD-TVK503
* Hiroshi Takekawa <sian@big.or.jp>
*/
static void
adtvk503_audio(struct bttv *btv, struct video_audio *v, int set)
{
unsigned int con = 0xffffff;
/* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
if (set) {
/* btor(***, BT848_GPIO_OUT_EN); */
if (v->mode & VIDEO_SOUND_LANG1)
con = 0x00000000;
if (v->mode & VIDEO_SOUND_LANG2)
con = 0x00180000;
if (v->mode & VIDEO_SOUND_STEREO)
con = 0x00000000;
if (v->mode & VIDEO_SOUND_MONO)
con = 0x00060000;
if (con != 0xffffff) {
gpio_bits(0x1e0000,con);
if (bttv_gpio)
bttv_gpio_tracking(btv, "adtvk503");
}
} else {
v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
}
}
/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
*
* This is needed because rv605 don't use a normal multiplex, but a crosspoint

File diff suppressed because it is too large Load Diff

View File

@ -69,6 +69,11 @@ static void ir_handle_key(struct bttv *btv)
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
ir_input_keydown(ir->dev,&ir->ir,data,data);
} else {
/* HACK: Probably, ir->mask_keydown is missing
for this board */
if (btv->c.type == BTTV_BOARD_WINFAST2000)
ir_input_keydown(ir->dev, &ir->ir, data, data);
ir_input_nokey(ir->dev,&ir->ir);
}

View File

@ -582,7 +582,7 @@ bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf
videobuf_dma_free(dma);
btcx_riscmem_free(btv->c.pci,&buf->bottom);
btcx_riscmem_free(btv->c.pci,&buf->top);
buf->vb.state = STATE_NEEDS_INIT;
buf->vb.state = VIDEOBUF_NEEDS_INIT;
}
int
@ -602,7 +602,7 @@ bttv_buffer_activate_vbi(struct bttv *btv,
if (vbi) {
unsigned int crop, vdelay;
vbi->vb.state = STATE_ACTIVE;
vbi->vb.state = VIDEOBUF_ACTIVE;
list_del(&vbi->vb.queue);
/* VDELAY is start of video, end of VBI capturing. */
@ -644,12 +644,12 @@ bttv_buffer_activate_video(struct bttv *btv,
/* video capture */
if (NULL != set->top && NULL != set->bottom) {
if (set->top == set->bottom) {
set->top->vb.state = STATE_ACTIVE;
set->top->vb.state = VIDEOBUF_ACTIVE;
if (set->top->vb.queue.next)
list_del(&set->top->vb.queue);
} else {
set->top->vb.state = STATE_ACTIVE;
set->bottom->vb.state = STATE_ACTIVE;
set->top->vb.state = VIDEOBUF_ACTIVE;
set->bottom->vb.state = VIDEOBUF_ACTIVE;
if (set->top->vb.queue.next)
list_del(&set->top->vb.queue);
if (set->bottom->vb.queue.next)
@ -666,7 +666,7 @@ bttv_buffer_activate_video(struct bttv *btv,
btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
~0x0f, BT848_COLOR_CTL);
} else if (NULL != set->top) {
set->top->vb.state = STATE_ACTIVE;
set->top->vb.state = VIDEOBUF_ACTIVE;
if (set->top->vb.queue.next)
list_del(&set->top->vb.queue);
bttv_apply_geo(btv, &set->top->geo,1);
@ -677,7 +677,7 @@ bttv_buffer_activate_video(struct bttv *btv,
btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
} else if (NULL != set->bottom) {
set->bottom->vb.state = STATE_ACTIVE;
set->bottom->vb.state = VIDEOBUF_ACTIVE;
if (set->bottom->vb.queue.next)
list_del(&set->bottom->vb.queue);
bttv_apply_geo(btv, &set->bottom->geo,1);

View File

@ -142,7 +142,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
redo_dma_risc = 1;
}
if (STATE_NEEDS_INIT == buf->vb.state) {
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
redo_dma_risc = 1;
if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
goto fail;
@ -189,7 +189,7 @@ static int vbi_buffer_prepare(struct videobuf_queue *q,
/* For bttv_buffer_activate_vbi(). */
buf->geo.vdelay = min_vdelay;
buf->vb.state = STATE_PREPARED;
buf->vb.state = VIDEOBUF_PREPARED;
buf->vb.field = field;
dprintk("buf prepare %p: top=%p bottom=%p field=%s\n",
vb, &buf->top, &buf->bottom,
@ -209,7 +209,7 @@ vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
dprintk("queue %p\n",vb);
buf->vb.state = STATE_QUEUED;
buf->vb.state = VIDEOBUF_QUEUED;
list_add_tail(&buf->vb.queue,&btv->vcapture);
if (NULL == btv->cvbi) {
fh->btv->loop_irq |= 4;
@ -236,10 +236,8 @@ struct videobuf_queue_ops bttv_vbi_qops = {
/* ----------------------------------------------------------------------- */
static int
try_fmt (struct v4l2_vbi_format * f,
const struct bttv_tvnorm * tvnorm,
__s32 crop_start)
static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
__s32 crop_start)
{
__s32 min_start, max_start, max_end, f2_offset;
unsigned int i;
@ -305,10 +303,9 @@ try_fmt (struct v4l2_vbi_format * f,
return 0;
}
int
bttv_vbi_try_fmt (struct bttv_fh * fh,
struct v4l2_vbi_format * f)
int bttv_try_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
const struct bttv_tvnorm *tvnorm;
__s32 crop_start;
@ -320,13 +317,13 @@ bttv_vbi_try_fmt (struct bttv_fh * fh,
mutex_unlock(&btv->lock);
return try_fmt(f, tvnorm, crop_start);
return try_fmt(&frt->fmt.vbi, tvnorm, crop_start);
}
int
bttv_vbi_set_fmt (struct bttv_fh * fh,
struct v4l2_vbi_format * f)
int bttv_s_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
const struct bttv_tvnorm *tvnorm;
__s32 start1, end;
@ -340,11 +337,12 @@ bttv_vbi_set_fmt (struct bttv_fh * fh,
tvnorm = &bttv_tvnorms[btv->tvnorm];
rc = try_fmt(f, tvnorm, btv->crop_start);
rc = try_fmt(&frt->fmt.vbi, tvnorm, btv->crop_start);
if (0 != rc)
goto fail;
start1 = f->start[1] - tvnorm->vbistart[1] + tvnorm->vbistart[0];
start1 = frt->fmt.vbi.start[1] - tvnorm->vbistart[1] +
tvnorm->vbistart[0];
/* First possible line of video capturing. Should be
max(f->start[0] + f->count[0], start1 + f->count[1]) * 2
@ -352,11 +350,11 @@ bttv_vbi_set_fmt (struct bttv_fh * fh,
pretend the VBI and video capture window may overlap,
so end = start + 1, the lowest possible value, times two
because vbi_fmt.end counts field lines times two. */
end = max(f->start[0], start1) * 2 + 2;
end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
mutex_lock(&fh->vbi.lock);
fh->vbi_fmt.fmt = *f;
fh->vbi_fmt.fmt = frt->fmt.vbi;
fh->vbi_fmt.tvnorm = tvnorm;
fh->vbi_fmt.end = end;
@ -370,13 +368,13 @@ bttv_vbi_set_fmt (struct bttv_fh * fh,
return rc;
}
void
bttv_vbi_get_fmt (struct bttv_fh * fh,
struct v4l2_vbi_format * f)
int bttv_g_fmt_vbi(struct file *file, void *f, struct v4l2_format *frt)
{
struct bttv_fh *fh = f;
const struct bttv_tvnorm *tvnorm;
*f = fh->vbi_fmt.fmt;
frt->fmt.vbi = fh->vbi_fmt.fmt;
tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
@ -391,28 +389,28 @@ bttv_vbi_get_fmt (struct bttv_fh * fh,
max_end = (tvnorm->cropcap.bounds.top
+ tvnorm->cropcap.bounds.height) >> 1;
f->sampling_rate = tvnorm->Fsc;
frt->fmt.vbi.sampling_rate = tvnorm->Fsc;
for (i = 0; i < 2; ++i) {
__s32 new_start;
new_start = f->start[i]
new_start = frt->fmt.vbi.start[i]
+ tvnorm->vbistart[i]
- fh->vbi_fmt.tvnorm->vbistart[i];
f->start[i] = min(new_start, max_end - 1);
f->count[i] = min((__s32) f->count[i],
max_end - f->start[i]);
frt->fmt.vbi.start[i] = min(new_start, max_end - 1);
frt->fmt.vbi.count[i] =
min((__s32) frt->fmt.vbi.count[i],
max_end - frt->fmt.vbi.start[i]);
max_end += tvnorm->vbistart[1]
- tvnorm->vbistart[0];
}
}
return 0;
}
void
bttv_vbi_fmt_reset (struct bttv_vbi_fmt * f,
int norm)
void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, int norm)
{
const struct bttv_tvnorm *tvnorm;
unsigned int real_samples_per_line;

Some files were not shown because too many files have changed in this diff Show More