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

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (707 commits)
  V4L/DVB (11316): saa7191: tuner ops wasn't set.
  V4L/DVB (11315): cx25840: fix 'unused variable' warning.
  V4L/DVB (11314): au8522: remove unused I2C_DRIVERID
  V4L/DVB (11313): v4l2-subdev: add enum_framesizes and enum_frameintervals.
  V4L/DVB (11312): tuner: remove V4L1 code from this driver.
  V4L/DVB (11311): v4l: replace 'ioctl' references in v4l i2c drivers
  V4L/DVB (11310): cx18: remove intermediate 'ioctl' step
  V4L/DVB (11309): cx25840: cleanup: remove intermediate 'ioctl' step
  V4L/DVB (11308): msp3400: use the V4L2 header since no V4L1 code is there
  V4L/DVB (11305): cx88: prevent probing rtc and ir devices
  V4L/DVB (11304): v4l2: remove v4l2_subdev_command calls where they are no longer needed.
  V4L/DVB (11303): tda7432: remove legacy code for old-style i2c API
  V4L/DVB (11302): tda9875: remove legacy code for old-style i2c API
  V4L/DVB (11301): wm8775: remove legacy code for old-style i2c API
  V4L/DVB (11300): cx88: convert to v4l2_subdev.
  V4L/DVB (11298): cx25840: remove legacy code for old-style i2c API
  V4L/DVB (11297): cx23885: convert to v4l2_subdev.
  V4L/DVB (11296): cx23885: bugfix error message if firmware is not found
  V4L/DVB (11295): cx23885: convert to v4l2_device.
  V4L/DVB (11293): uvcvideo: Add zero fill for VIDIOC_ENUM_FMT
  ...
This commit is contained in:
Linus Torvalds
2009-03-30 10:09:14 -07:00
489 changed files with 48991 additions and 27835 deletions

View File

@@ -25,7 +25,7 @@ use IO::Handle;
"tda10046lifeview", "av7110", "dec2000t", "dec2540t", "tda10046lifeview", "av7110", "dec2000t", "dec2540t",
"dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
"or51211", "or51132_qam", "or51132_vsb", "bluebird", "or51211", "or51132_qam", "or51132_vsb", "bluebird",
"opera1"); "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2" );
# Check args # Check args
syntax() if (scalar(@ARGV) != 1); syntax() if (scalar(@ARGV) != 1);
@@ -37,8 +37,8 @@ for ($i=0; $i < scalar(@components); $i++) {
$outfile = eval($cid); $outfile = eval($cid);
die $@ if $@; die $@ if $@;
print STDERR <<EOF; print STDERR <<EOF;
Firmware $outfile extracted successfully. Firmware(s) $outfile extracted successfully.
Now copy it to either /usr/lib/hotplug/firmware or /lib/firmware Now copy it(they) to either /usr/lib/hotplug/firmware or /lib/firmware
(depending on configuration of firmware hotplug). (depending on configuration of firmware hotplug).
EOF EOF
exit(0); exit(0);
@@ -345,6 +345,85 @@ sub or51211 {
$fwfile; $fwfile;
} }
sub cx231xx {
my $fwfile = "v4l-cx231xx-avcore-01.fw";
my $url = "http://linuxtv.org/downloads/firmware/$fwfile";
my $hash = "7d3bb956dc9df0eafded2b56ba57cc42";
checkstandard();
wgetfile($fwfile, $url);
verify($fwfile, $hash);
$fwfile;
}
sub cx18 {
my $url = "http://linuxtv.org/downloads/firmware/";
my %files = (
'v4l-cx23418-apu.fw' => '588f081b562f5c653a3db1ad8f65939a',
'v4l-cx23418-cpu.fw' => 'b6c7ed64bc44b1a6e0840adaeac39d79',
'v4l-cx23418-dig.fw' => '95bc688d3e7599fd5800161e9971cc55',
);
checkstandard();
my $allfiles;
foreach my $fwfile (keys %files) {
wgetfile($fwfile, "$url/$fwfile");
verify($fwfile, $files{$fwfile});
$allfiles .= " $fwfile";
}
$allfiles =~ s/^\s//;
$allfiles;
}
sub cx23885 {
my $url = "http://linuxtv.org/downloads/firmware/";
my %files = (
'v4l-cx23885-avcore-01.fw' => 'a9f8f5d901a7fb42f552e1ee6384f3bb',
'v4l-cx23885-enc.fw' => 'a9f8f5d901a7fb42f552e1ee6384f3bb',
);
checkstandard();
my $allfiles;
foreach my $fwfile (keys %files) {
wgetfile($fwfile, "$url/$fwfile");
verify($fwfile, $files{$fwfile});
$allfiles .= " $fwfile";
}
$allfiles =~ s/^\s//;
$allfiles;
}
sub pvrusb2 {
my $url = "http://linuxtv.org/downloads/firmware/";
my %files = (
'v4l-cx25840.fw' => 'dadb79e9904fc8af96e8111d9cb59320',
);
checkstandard();
my $allfiles;
foreach my $fwfile (keys %files) {
wgetfile($fwfile, "$url/$fwfile");
verify($fwfile, $files{$fwfile});
$allfiles .= " $fwfile";
}
$allfiles =~ s/^\s//;
$allfiles;
}
sub or51132_qam { sub or51132_qam {
my $fwfile = "dvb-fe-or51132-qam.fw"; my $fwfile = "dvb-fe-or51132-qam.fw";
my $url = "http://linuxtv.org/downloads/firmware/$fwfile"; my $url = "http://linuxtv.org/downloads/firmware/$fwfile";

View File

@@ -64,10 +64,10 @@ Who: Pavel Machek <pavel@suse.cz>
--------------------------- ---------------------------
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices. What: Video4Linux API 1 ioctls and from Video devices.
When: December 2008 When: July 2009
Files: include/linux/video_decoder.h include/linux/videodev.h Files: include/linux/videodev.h
Check: include/linux/video_decoder.h include/linux/videodev.h Check: include/linux/videodev.h
Why: V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6 Why: V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6
series. The old API have lots of drawbacks and don't provide enough series. The old API have lots of drawbacks and don't provide enough
means to work with all video and audio standards. The newer API is means to work with all video and audio standards. The newer API is

View File

@@ -122,10 +122,8 @@ Code Seq# Include File Comments
'c' 00-7F linux/coda.h conflict! 'c' 00-7F linux/coda.h conflict!
'c' 80-9F arch/s390/include/asm/chsc.h 'c' 80-9F arch/s390/include/asm/chsc.h
'd' 00-FF linux/char/drm/drm/h conflict! 'd' 00-FF linux/char/drm/drm/h conflict!
'd' 00-DF linux/video_decoder.h conflict!
'd' F0-FF linux/digi1.h 'd' F0-FF linux/digi1.h
'e' all linux/digi1.h conflict! 'e' all linux/digi1.h conflict!
'e' 00-1F linux/video_encoder.h conflict!
'e' 00-1F net/irda/irtty.h conflict! 'e' 00-1F net/irda/irtty.h conflict!
'f' 00-1F linux/ext2_fs.h 'f' 00-1F linux/ext2_fs.h
'h' 00-7F Charon filesystem 'h' 00-7F Charon filesystem

View File

@@ -135,7 +135,7 @@
134 -> Adlink RTV24 134 -> Adlink RTV24
135 -> DViCO FusionHDTV 5 Lite [18ac:d500] 135 -> DViCO FusionHDTV 5 Lite [18ac:d500]
136 -> Acorp Y878F [9511:1540] 136 -> Acorp Y878F [9511:1540]
137 -> Conceptronic CTVFMi v2 137 -> Conceptronic CTVFMi v2 [036e:109e]
138 -> Prolink Pixelview PV-BT878P+ (Rev.2E) 138 -> Prolink Pixelview PV-BT878P+ (Rev.2E)
139 -> Prolink PixelView PlayTV MPEG2 PV-M4900 139 -> Prolink PixelView PlayTV MPEG2 PV-M4900
140 -> Osprey 440 [0070:ff07] 140 -> Osprey 440 [0070:ff07]
@@ -154,3 +154,7 @@
153 -> PHYTEC VD-012 (bt878) 153 -> PHYTEC VD-012 (bt878)
154 -> PHYTEC VD-012-X1 (bt878) 154 -> PHYTEC VD-012-X1 (bt878)
155 -> PHYTEC VD-012-X2 (bt878) 155 -> PHYTEC VD-012-X2 (bt878)
156 -> IVCE-8784 [0000:f050,0001:f050,0002:f050,0003:f050]
157 -> Geovision GV-800(S) (master) [800a:763d]
158 -> Geovision GV-800(S) (slave) [800b:763d,800c:763d,800d:763d]
159 -> ProVideo PV183 [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540]

View File

@@ -12,3 +12,7 @@
11 -> DViCO FusionHDTV DVB-T Dual Express [18ac:db78] 11 -> DViCO FusionHDTV DVB-T Dual Express [18ac:db78]
12 -> Leadtek Winfast PxDVR3200 H [107d:6681] 12 -> Leadtek Winfast PxDVR3200 H [107d:6681]
13 -> Compro VideoMate E650F [185b:e800] 13 -> Compro VideoMate E650F [185b:e800]
14 -> TurboSight TBS 6920 [6920:8888]
15 -> TeVii S470 [d470:9022]
16 -> DVBWorld DVB-S2 2005 [0001:2005]
17 -> NetUP Dual DVB-S2 CI [1b55:2a2c]

View File

@@ -77,3 +77,4 @@
76 -> SATTRADE ST4200 DVB-S/S2 [b200:4200] 76 -> SATTRADE ST4200 DVB-S/S2 [b200:4200]
77 -> TBS 8910 DVB-S [8910:8888] 77 -> TBS 8910 DVB-S [8910:8888]
78 -> Prof 6200 DVB-S [b022:3022] 78 -> Prof 6200 DVB-S [b022:3022]
79 -> Terratec Cinergy HT PCI MKII [153b:1177]

View File

@@ -7,12 +7,12 @@
6 -> Terratec Cinergy 200 USB (em2800) 6 -> Terratec Cinergy 200 USB (em2800)
7 -> Leadtek Winfast USB II (em2800) [0413:6023] 7 -> Leadtek Winfast USB II (em2800) [0413:6023]
8 -> Kworld USB2800 (em2800) 8 -> Kworld USB2800 (em2800)
9 -> Pinnacle Dazzle DVC 90/DVC 100 (em2820/em2840) [2304:0207,2304:021a] 9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker (em2820/em2840) [1b80:e302,2304:0207,2304:021a]
10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500] 10 -> Hauppauge WinTV HVR 900 (em2880) [2040:6500]
11 -> Terratec Hybrid XS (em2880) [0ccd:0042] 11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
12 -> Kworld PVR TV 2800 RF (em2820/em2840) 12 -> Kworld PVR TV 2800 RF (em2820/em2840)
13 -> Terratec Prodigy XS (em2880) [0ccd:0047] 13 -> Terratec Prodigy XS (em2880) [0ccd:0047]
14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) 14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
15 -> V-Gear PocketTV (em2800) 15 -> V-Gear PocketTV (em2800)
16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b] 16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b]
17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227] 17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227]
@@ -30,7 +30,6 @@
30 -> Videology 20K14XUSB USB2.0 (em2820/em2840) 30 -> Videology 20K14XUSB USB2.0 (em2820/em2840)
31 -> Usbgear VD204v9 (em2821) 31 -> Usbgear VD204v9 (em2821)
32 -> Supercomp USB 2.0 TV (em2821) 32 -> Supercomp USB 2.0 TV (em2821)
33 -> SIIG AVTuner-PVR/Prolink PlayTV USB 2.0 (em2821)
34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f] 34 -> Terratec Cinergy A Hybrid XS (em2860) [0ccd:004f]
35 -> Typhoon DVD Maker (em2860) 35 -> Typhoon DVD Maker (em2860)
36 -> NetGMBH Cam (em2860) 36 -> NetGMBH Cam (em2860)
@@ -58,3 +57,7 @@
58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041] 58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041]
60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f] 60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f]
61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840) 61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840)
62 -> Gadmei TVR200 (em2820/em2840)
63 -> Kaiomy TVnPC U2 (em2860) [eb1a:e303]
64 -> Easy Cap Capture DC-60 (em2860)
65 -> IO-DATA GV-MVP/SZ (em2820/em2840) [04bb:0515]

View File

@@ -153,3 +153,5 @@
152 -> Asus Tiger Rev:1.00 [1043:4857] 152 -> Asus Tiger Rev:1.00 [1043:4857]
153 -> Kworld Plus TV Analog Lite PCI [17de:7128] 153 -> Kworld Plus TV Analog Lite PCI [17de:7128]
154 -> Avermedia AVerTV GO 007 FM Plus [1461:f31d] 154 -> Avermedia AVerTV GO 007 FM Plus [1461:f31d]
155 -> Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid [0070:6706,0070:6708]
156 -> Hauppauge WinTV-HVR1110r3 [0070:6707,0070:6709,0070:670a]

View File

@@ -401,8 +401,7 @@ Additional notes for software developers:
first set the correct norm. Well, it seems logically correct: TV first set the correct norm. Well, it seems logically correct: TV
standard is "more constant" for current country than geometry standard is "more constant" for current country than geometry
settings of a variety of TV capture cards which may work in ITU or settings of a variety of TV capture cards which may work in ITU or
square pixel format. Remember that users now can lock the norm to square pixel format.
avoid any ambiguity.
-- --
Please note that lavplay/lavrec are also included in the MJPEG-tools Please note that lavplay/lavrec are also included in the MJPEG-tools
(http://mjpeg.sf.net/). (http://mjpeg.sf.net/).

View File

@@ -81,16 +81,6 @@ tuner.o
pal=[bdgil] select PAL variant (used for some tuners pal=[bdgil] select PAL variant (used for some tuners
only, important for the audio carrier). only, important for the audio carrier).
tvmixer.o
registers a mixer device for the TV card's volume/bass/treble
controls (requires a i2c audio control chip like the msp3400).
insmod args:
debug=1 print some debug info to the syslog.
devnr=n allocate device #n (0 == /dev/mixer,
1 = /dev/mixer1, ...), default is to
use the first free one.
tvaudio.o tvaudio.o
new, experimental module which is supported to provide a single new, experimental module which is supported to provide a single
driver for all simple i2c audio control chips (tda/tea*). driver for all simple i2c audio control chips (tda/tea*).

View File

@@ -63,8 +63,8 @@ If you have some knowledge and spare time, please try to fix this
yourself (patches very welcome of course...) You know: The linux yourself (patches very welcome of course...) You know: The linux
slogan is "Do it yourself". slogan is "Do it yourself".
There is a mailing list: video4linux-list@redhat.com. There is a mailing list: linux-media@vger.kernel.org
https://listman.redhat.com/mailman/listinfo/video4linux-list http://vger.kernel.org/vger-lists.html#linux-media
If you have trouble with some specific TV card, try to ask there If you have trouble with some specific TV card, try to ask there
instead of mailing me directly. The chance that someone with the instead of mailing me directly. The chance that someone with the

View File

@@ -32,6 +32,10 @@ Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels.
The width of a frame is always 720 pixels, regardless of the actual specified The width of a frame is always 720 pixels, regardless of the actual specified
width. width.
If the height is not a multiple of 32 lines, then the captured video is
missing macroblocks at the end and is unusable. So the height must be a
multiple of 32.
-------------------------------------------------------------------------- --------------------------------------------------------------------------
#include <stdio.h> #include <stdio.h>

View File

@@ -32,6 +32,7 @@ spca561 041e:403b Creative Webcam Vista (VF0010)
zc3xx 041e:4051 Creative Live!Cam Notebook Pro (VF0250) zc3xx 041e:4051 Creative Live!Cam Notebook Pro (VF0250)
ov519 041e:4052 Creative Live! VISTA IM ov519 041e:4052 Creative Live! VISTA IM
zc3xx 041e:4053 Creative Live!Cam Video IM zc3xx 041e:4053 Creative Live!Cam Video IM
vc032x 041e:405b Creative Live! Cam Notebook Ultra (VC0130)
ov519 041e:405f Creative Live! VISTA VF0330 ov519 041e:405f Creative Live! VISTA VF0330
ov519 041e:4060 Creative Live! VISTA VF0350 ov519 041e:4060 Creative Live! VISTA VF0350
ov519 041e:4061 Creative Live! VISTA VF0400 ov519 041e:4061 Creative Live! VISTA VF0400
@@ -193,6 +194,7 @@ spca500 084d:0003 D-Link DSC-350
spca500 08ca:0103 Aiptek PocketDV spca500 08ca:0103 Aiptek PocketDV
sunplus 08ca:0104 Aiptek PocketDVII 1.3 sunplus 08ca:0104 Aiptek PocketDVII 1.3
sunplus 08ca:0106 Aiptek Pocket DV3100+ sunplus 08ca:0106 Aiptek Pocket DV3100+
mr97310a 08ca:0111 Aiptek PenCam VGA+
sunplus 08ca:2008 Aiptek Mini PenCam 2 M sunplus 08ca:2008 Aiptek Mini PenCam 2 M
sunplus 08ca:2010 Aiptek PocketCam 3M sunplus 08ca:2010 Aiptek PocketCam 3M
sunplus 08ca:2016 Aiptek PocketCam 2 Mega sunplus 08ca:2016 Aiptek PocketCam 2 Mega
@@ -215,6 +217,7 @@ pac207 093a:2468 PAC207
pac207 093a:2470 Genius GF112 pac207 093a:2470 Genius GF112
pac207 093a:2471 Genius VideoCam ge111 pac207 093a:2471 Genius VideoCam ge111
pac207 093a:2472 Genius VideoCam ge110 pac207 093a:2472 Genius VideoCam ge110
pac207 093a:2474 Genius iLook 111
pac207 093a:2476 Genius e-Messenger 112 pac207 093a:2476 Genius e-Messenger 112
pac7311 093a:2600 PAC7311 Typhoon pac7311 093a:2600 PAC7311 Typhoon
pac7311 093a:2601 Philips SPC 610 NC pac7311 093a:2601 Philips SPC 610 NC
@@ -279,6 +282,7 @@ spca561 10fd:7e50 FlyCam Usb 100
zc3xx 10fd:8050 Typhoon Webshot II USB 300k zc3xx 10fd:8050 Typhoon Webshot II USB 300k
ov534 1415:2000 Sony HD Eye for PS3 (SLEH 00201) ov534 1415:2000 Sony HD Eye for PS3 (SLEH 00201)
pac207 145f:013a Trust WB-1300N pac207 145f:013a Trust WB-1300N
vc032x 15b8:6001 HP 2.0 Megapixel
vc032x 15b8:6002 HP 2.0 Megapixel rz406aa vc032x 15b8:6002 HP 2.0 Megapixel rz406aa
spca501 1776:501c Arowana 300K CMOS Camera spca501 1776:501c Arowana 300K CMOS Camera
t613 17a1:0128 TASCORP JPEG Webcam, NGS Cyclops t613 17a1:0128 TASCORP JPEG Webcam, NGS Cyclops

View File

@@ -1,6 +1,6 @@
Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers
Copyright (c) 2008 Tobias Lorenz <tobias.lorenz@gmx.net> Copyright (c) 2009 Tobias Lorenz <tobias.lorenz@gmx.net>
Information from Silicon Labs Information from Silicon Labs
@@ -41,7 +41,7 @@ chips are known to work:
- 10c4:818a: Silicon Labs USB FM Radio Reference Design - 10c4:818a: Silicon Labs USB FM Radio Reference Design
- 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF)
- 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700) - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700)
- 10c5:819a: DealExtreme USB Radio - 10c5:819a: Sanei Electric, Inc. FM USB Radio (sold as DealExtreme.com PCear)
Software Software
@@ -52,6 +52,7 @@ Testing is usually done with most application under Debian/testing:
- gradio - GTK FM radio tuner - gradio - GTK FM radio tuner
- kradio - Comfortable Radio Application for KDE - kradio - Comfortable Radio Application for KDE
- radio - ncurses-based radio application - radio - ncurses-based radio application
- mplayer - The Ultimate Movie Player For Linux
There is also a library libv4l, which can be used. It's going to have a function There is also a library libv4l, which can be used. It's going to have a function
for frequency seeking, either by using hardware functionality as in radio-si470x for frequency seeking, either by using hardware functionality as in radio-si470x
@@ -69,7 +70,7 @@ Audio Listing
USB Audio is provided by the ALSA snd_usb_audio module. It is recommended to USB Audio is provided by the ALSA snd_usb_audio module. It is recommended to
also select SND_USB_AUDIO, as this is required to get sound from the radio. For also select SND_USB_AUDIO, as this is required to get sound from the radio. For
listing you have to redirect the sound, for example using one of the following listing you have to redirect the sound, for example using one of the following
commands. commands. Please adjust the audio devices to your needs (/dev/dsp* and hw:x,x).
If you just want to test audio (very poor quality): If you just want to test audio (very poor quality):
cat /dev/dsp1 > /dev/dsp cat /dev/dsp1 > /dev/dsp
@@ -80,6 +81,10 @@ sox -2 --endian little -r 96000 -t oss /dev/dsp1 -t oss /dev/dsp
If you use arts try: If you use arts try:
arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B - arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B -
If you use mplayer try:
mplayer -radio adevice=hw=1.0:arate=96000 \
-rawaudio rate=96000 \
radio://<frequency>/capture
Module Parameters Module Parameters
================= =================

View File

@@ -47,7 +47,9 @@ All drivers have the following structure:
3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX, /dev/radioX and 3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX, /dev/radioX and
/dev/vtxX) and keeping track of device-node specific data. /dev/vtxX) and keeping track of device-node specific data.
4) Filehandle-specific structs containing per-filehandle data. 4) Filehandle-specific structs containing per-filehandle data;
5) video buffer handling.
This is a rough schematic of how it all relates: This is a rough schematic of how it all relates:
@@ -82,12 +84,20 @@ You must register the device instance:
v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
Registration will initialize the v4l2_device struct and link dev->driver_data Registration will initialize the v4l2_device struct and link dev->driver_data
to v4l2_dev. Registration will also set v4l2_dev->name to a value derived from to v4l2_dev. If v4l2_dev->name is empty then it will be set to a value derived
dev (driver name followed by the bus_id, to be precise). You may change the from dev (driver name followed by the bus_id, to be precise). If you set it
name after registration if you want. up before calling v4l2_device_register then it will be untouched. If dev is
NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register.
The first 'dev' argument is normally the struct device pointer of a pci_dev, The first 'dev' argument is normally the struct device pointer of a pci_dev,
usb_device or platform_device. usb_device or platform_device. It is rare for dev to be NULL, but it happens
with ISA devices or when one device creates multiple PCI devices, thus making
it impossible to associate v4l2_dev with a particular parent.
You can also supply a notify() callback that can be called by sub-devices to
notify you of events. Whether you need to set this depends on the sub-device.
Any notifications a sub-device supports must be defined in a header in
include/media/<subdevice>.h.
You unregister with: You unregister with:
@@ -95,6 +105,17 @@ You unregister with:
Unregistering will also automatically unregister all subdevs from the device. Unregistering will also automatically unregister all subdevs from the device.
If you have a hotpluggable device (e.g. a USB device), then when a disconnect
happens the parent device becomes invalid. Since v4l2_device has a pointer to
that parent device it has to be cleared as well to mark that the parent is
gone. To do this call:
v4l2_device_disconnect(struct v4l2_device *v4l2_dev);
This does *not* unregister the subdevs, so you still need to call the
v4l2_device_unregister() function for that. If your driver is not hotpluggable,
then there is no need to call v4l2_device_disconnect().
Sometimes you need to iterate over all devices registered by a specific Sometimes you need to iterate over all devices registered by a specific
driver. This is usually the case if multiple device drivers use the same driver. This is usually the case if multiple device drivers use the same
hardware. E.g. the ivtvfb driver is a framebuffer driver that uses the ivtv hardware. E.g. the ivtvfb driver is a framebuffer driver that uses the ivtv
@@ -134,7 +155,7 @@ The recommended approach is as follows:
static atomic_t drv_instance = ATOMIC_INIT(0); static atomic_t drv_instance = ATOMIC_INIT(0);
static int __devinit drv_probe(struct pci_dev *dev, static int __devinit drv_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_id) const struct pci_device_id *pci_id)
{ {
... ...
@@ -218,7 +239,7 @@ to add new ops and categories.
A sub-device driver initializes the v4l2_subdev struct using: A sub-device driver initializes the v4l2_subdev struct using:
v4l2_subdev_init(subdev, &ops); v4l2_subdev_init(sd, &ops);
Afterwards you need to initialize subdev->name with a unique name and set the Afterwards you need to initialize subdev->name with a unique name and set the
module owner. This is done for you if you use the i2c helper functions. module owner. This is done for you if you use the i2c helper functions.
@@ -226,7 +247,7 @@ module owner. This is done for you if you use the i2c helper functions.
A device (bridge) driver needs to register the v4l2_subdev with the A device (bridge) driver needs to register the v4l2_subdev with the
v4l2_device: v4l2_device:
int err = v4l2_device_register_subdev(device, subdev); int err = v4l2_device_register_subdev(v4l2_dev, sd);
This can fail if the subdev module disappeared before it could be registered. This can fail if the subdev module disappeared before it could be registered.
After this function was called successfully the subdev->dev field points to After this function was called successfully the subdev->dev field points to
@@ -234,17 +255,17 @@ the v4l2_device.
You can unregister a sub-device using: You can unregister a sub-device using:
v4l2_device_unregister_subdev(subdev); v4l2_device_unregister_subdev(sd);
Afterwards the subdev module can be unloaded and subdev->dev == NULL. Afterwards the subdev module can be unloaded and sd->dev == NULL.
You can call an ops function either directly: You can call an ops function either directly:
err = subdev->ops->core->g_chip_ident(subdev, &chip); err = sd->ops->core->g_chip_ident(sd, &chip);
but it is better and easier to use this macro: but it is better and easier to use this macro:
err = v4l2_subdev_call(subdev, core, g_chip_ident, &chip); err = v4l2_subdev_call(sd, core, g_chip_ident, &chip);
The macro will to the right NULL pointer checks and returns -ENODEV if subdev The macro will to the right NULL pointer checks and returns -ENODEV if subdev
is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_chip_ident is is NULL, -ENOIOCTLCMD if either subdev->core or subdev->core->g_chip_ident is
@@ -252,19 +273,19 @@ NULL, or the actual result of the subdev->ops->core->g_chip_ident ops.
It is also possible to call all or a subset of the sub-devices: It is also possible to call all or a subset of the sub-devices:
v4l2_device_call_all(dev, 0, core, g_chip_ident, &chip); v4l2_device_call_all(v4l2_dev, 0, core, g_chip_ident, &chip);
Any subdev that does not support this ops is skipped and error results are Any subdev that does not support this ops is skipped and error results are
ignored. If you want to check for errors use this: ignored. If you want to check for errors use this:
err = v4l2_device_call_until_err(dev, 0, core, g_chip_ident, &chip); err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip);
Any error except -ENOIOCTLCMD will exit the loop with that error. If no Any error except -ENOIOCTLCMD will exit the loop with that error. If no
errors (except -ENOIOCTLCMD) occured, then 0 is returned. errors (except -ENOIOCTLCMD) occured, then 0 is returned.
The second argument to both calls is a group ID. If 0, then all subdevs are The second argument to both calls is a group ID. If 0, then all subdevs are
called. If non-zero, then only those whose group ID match that value will called. If non-zero, then only those whose group ID match that value will
be called. Before a bridge driver registers a subdev it can set subdev->grp_id be called. Before a bridge driver registers a subdev it can set sd->grp_id
to whatever value it wants (it's 0 by default). This value is owned by the to whatever value it wants (it's 0 by default). This value is owned by the
bridge driver and the sub-device driver will never modify or use it. bridge driver and the sub-device driver will never modify or use it.
@@ -276,6 +297,11 @@ e.g. AUDIO_CONTROLLER and specify that as the group ID value when calling
v4l2_device_call_all(). That ensures that it will only go to the subdev v4l2_device_call_all(). That ensures that it will only go to the subdev
that needs it. that needs it.
If the sub-device needs to notify its v4l2_device parent of an event, then
it can call v4l2_subdev_notify(sd, notification, arg). This macro checks
whether there is a notify() callback defined and returns -ENODEV if not.
Otherwise the result of the notify() call is returned.
The advantage of using v4l2_subdev is that it is a generic struct and does The advantage of using v4l2_subdev is that it is a generic struct and does
not contain any knowledge about the underlying hardware. So a driver might not contain any knowledge about the underlying hardware. So a driver might
contain several subdevs that use an I2C bus, but also a subdev that is contain several subdevs that use an I2C bus, but also a subdev that is
@@ -340,6 +366,12 @@ Make sure to call v4l2_device_unregister_subdev(sd) when the remove() callback
is called. This will unregister the sub-device from the bridge driver. It is is called. This will unregister the sub-device from the bridge driver. It is
safe to call this even if the sub-device was never registered. safe to call this even if the sub-device was never registered.
You need to do this because when the bridge driver destroys the i2c adapter
the remove() callbacks are called of the i2c devices on that adapter.
After that the corresponding v4l2_subdev structures are invalid, so they
have to be unregistered first. Calling v4l2_device_unregister_subdev(sd)
from the remove() callback ensures that this is always done correctly.
The bridge driver also has some helper functions it can use: The bridge driver also has some helper functions it can use:
@@ -349,8 +381,8 @@ This loads the given module (can be NULL if no module needs to be loaded) and
calls i2c_new_device() with the given i2c_adapter and chip/address arguments. calls i2c_new_device() with the given i2c_adapter and chip/address arguments.
If all goes well, then it registers the subdev with the v4l2_device. It gets If all goes well, then it registers the subdev with the v4l2_device. It gets
the v4l2_device by calling i2c_get_adapdata(adapter), so you should make sure the v4l2_device by calling i2c_get_adapdata(adapter), so you should make sure
that adapdata is set to v4l2_device when you setup the i2c_adapter in your to call i2c_set_adapdata(adapter, v4l2_device) when you setup the i2c_adapter
driver. in your driver.
You can also use v4l2_i2c_new_probed_subdev() which is very similar to You can also use v4l2_i2c_new_probed_subdev() which is very similar to
v4l2_i2c_new_subdev(), except that it has an array of possible I2C addresses v4l2_i2c_new_subdev(), except that it has an array of possible I2C addresses
@@ -358,6 +390,14 @@ that it should probe. Internally it calls i2c_new_probed_device().
Both functions return NULL if something went wrong. Both functions return NULL if something went wrong.
Note that the chipid you pass to v4l2_i2c_new_(probed_)subdev() is usually
the same as the module name. It allows you to specify a chip variant, e.g.
"saa7114" or "saa7115". In general though the i2c driver autodetects this.
The use of chipid is something that needs to be looked at more closely at a
later date. It differs between i2c drivers and as such can be confusing.
To see which chip variants are supported you can look in the i2c driver code
for the i2c_device_id table. This lists all the possibilities.
struct video_device struct video_device
------------------- -------------------
@@ -396,6 +436,15 @@ You should also set these fields:
- ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance - ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
(highly recommended to use this and it might become compulsory in the (highly recommended to use this and it might become compulsory in the
future!), then set this to your v4l2_ioctl_ops struct. future!), then set this to your v4l2_ioctl_ops struct.
- parent: you only set this if v4l2_device was registered with NULL as
the parent device struct. This only happens in cases where one hardware
device has multiple PCI devices that all share the same v4l2_device core.
The cx88 driver is an example of this: one core v4l2_device struct, but
it is used by both an raw video PCI device (cx8800) and a MPEG PCI device
(cx8802). Since the v4l2_device cannot be associated with a particular
PCI device it is setup without a parent device. But when the struct
video_device is setup you do know which parent PCI device to use.
If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or
.ioctl to video_ioctl2 in your v4l2_file_operations struct. .ioctl to video_ioctl2 in your v4l2_file_operations struct.
@@ -499,8 +548,8 @@ There are a few useful helper functions:
You can set/get driver private data in the video_device struct using: You can set/get driver private data in the video_device struct using:
void *video_get_drvdata(struct video_device *dev); void *video_get_drvdata(struct video_device *vdev);
void video_set_drvdata(struct video_device *dev, void *data); void video_set_drvdata(struct video_device *vdev, void *data);
Note that you can safely call video_set_drvdata() before calling Note that you can safely call video_set_drvdata() before calling
video_register_device(). video_register_device().
@@ -519,3 +568,103 @@ void *video_drvdata(struct file *file);
You can go from a video_device struct to the v4l2_device struct using: You can go from a video_device struct to the v4l2_device struct using:
struct v4l2_device *v4l2_dev = vdev->v4l2_dev; struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
video buffer helper functions
-----------------------------
The v4l2 core API provides a standard method for dealing with video
buffers. Those methods allow a driver to implement read(), mmap() and
overlay() on a consistent way.
There are currently methods for using video buffers on devices that
supports DMA with scatter/gather method (videobuf-dma-sg), DMA with
linear access (videobuf-dma-contig), and vmalloced buffers, mostly
used on USB drivers (videobuf-vmalloc).
Any driver using videobuf should provide operations (callbacks) for
four handlers:
ops->buf_setup - calculates the size of the video buffers and avoid they
to waste more than some maximum limit of RAM;
ops->buf_prepare - fills the video buffer structs and calls
videobuf_iolock() to alloc and prepare mmaped memory;
ops->buf_queue - advices the driver that another buffer were
requested (by read() or by QBUF);
ops->buf_release - frees any buffer that were allocated.
In order to use it, the driver need to have a code (generally called at
interrupt context) that will properly handle the buffer request lists,
announcing that a new buffer were filled.
The irq handling code should handle the videobuf task lists, in order
to advice videobuf that a new frame were filled, in order to honor to a
request. The code is generally like this one:
if (list_empty(&dma_q->active))
return;
buf = list_entry(dma_q->active.next, struct vbuffer, vb.queue);
if (!waitqueue_active(&buf->vb.done))
return;
/* Some logic to handle the buf may be needed here */
list_del(&buf->vb.queue);
do_gettimeofday(&buf->vb.ts);
wake_up(&buf->vb.done);
Those are the videobuffer functions used on drivers, implemented on
videobuf-core:
- Videobuf init functions
videobuf_queue_sg_init()
Initializes the videobuf infrastructure. This function should be
called before any other videobuf function on drivers that uses DMA
Scatter/Gather buffers.
videobuf_queue_dma_contig_init
Initializes the videobuf infrastructure. This function should be
called before any other videobuf function on drivers that need DMA
contiguous buffers.
videobuf_queue_vmalloc_init()
Initializes the videobuf infrastructure. This function should be
called before any other videobuf function on USB (and other drivers)
that need a vmalloced type of videobuf.
- videobuf_iolock()
Prepares the videobuf memory for the proper method (read, mmap, overlay).
- videobuf_queue_is_busy()
Checks if a videobuf is streaming.
- videobuf_queue_cancel()
Stops video handling.
- videobuf_mmap_free()
frees mmap buffers.
- videobuf_stop()
Stops video handling, ends mmap and frees mmap and other buffers.
- V4L2 api functions. Those functions correspond to VIDIOC_foo ioctls:
videobuf_reqbufs(), videobuf_querybuf(), videobuf_qbuf(),
videobuf_dqbuf(), videobuf_streamon(), videobuf_streamoff().
- V4L1 api function (corresponds to VIDIOCMBUF ioctl):
videobuf_cgmbuf()
This function is used to provide backward compatibility with V4L1
API.
- Some help functions for read()/poll() operations:
videobuf_read_stream()
For continuous stream read()
videobuf_read_one()
For snapshot read()
videobuf_poll_stream()
polling help function
The better way to understand it is to take a look at vivi driver. One
of the main reasons for vivi is to be a videobuf usage example. the
vivi_thread_tick() does the task that the IRQ callback would do on PCI
drivers (or the irq callback on USB).

View File

@@ -105,8 +105,8 @@ int main(int argc, char ** argv)
struct video_picture vpic; struct video_picture vpic;
unsigned char *buffer, *src; unsigned char *buffer, *src;
int bpp = 24, r, g, b; int bpp = 24, r = 0, g = 0, b = 0;
unsigned int i, src_depth; unsigned int i, src_depth = 16;
if (fd < 0) { if (fd < 0) {
perror(VIDEO_DEV); perror(VIDEO_DEV);

View File

@@ -65,3 +65,4 @@ Vendor Product Distributor Model
0x06d6 0x003b Trust Powerc@m 970Z 0x06d6 0x003b Trust Powerc@m 970Z
0x0a17 0x004e Pentax Optio 50 0x0a17 0x004e Pentax Optio 50
0x041e 0x405d Creative DiVi CAM 516 0x041e 0x405d Creative DiVi CAM 516
0x08ca 0x2102 Aiptek DV T300

View File

@@ -1063,7 +1063,6 @@ BTTV VIDEO4LINUX DRIVER
P: Mauro Carvalho Chehab P: Mauro Carvalho Chehab
M: mchehab@infradead.org M: mchehab@infradead.org
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
L: video4linux-list@redhat.com
W: http://linuxtv.org W: http://linuxtv.org
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained S: Maintained
@@ -4835,7 +4834,6 @@ VIDEO FOR LINUX (V4L)
P: Mauro Carvalho Chehab P: Mauro Carvalho Chehab
M: mchehab@infradead.org M: mchehab@infradead.org
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
L: video4linux-list@redhat.com
W: http://linuxtv.org W: http://linuxtv.org
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained S: Maintained

View File

@@ -380,14 +380,49 @@ static struct pca953x_platform_data pca9536_data = {
.gpio_base = NR_BUILTIN_GPIO + 1, .gpio_base = NR_BUILTIN_GPIO + 1,
}; };
static struct soc_camera_link iclink[] = { static int gpio_bus_switch;
static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
unsigned long flags)
{ {
.bus_id = 0, /* Must match with the camera ID above */ if (gpio_bus_switch <= 0) {
.gpio = NR_BUILTIN_GPIO + 1, if (flags == SOCAM_DATAWIDTH_10)
}, { return 0;
.bus_id = 0, /* Must match with the camera ID above */ else
.gpio = -ENXIO, return -EINVAL;
} }
if (flags & SOCAM_DATAWIDTH_8)
gpio_set_value(gpio_bus_switch, 1);
else
gpio_set_value(gpio_bus_switch, 0);
return 0;
}
static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
{
int ret;
if (!gpio_bus_switch) {
ret = gpio_request(NR_BUILTIN_GPIO + 1, "camera");
if (!ret) {
gpio_bus_switch = NR_BUILTIN_GPIO + 1;
gpio_direction_output(gpio_bus_switch, 0);
} else
gpio_bus_switch = -EINVAL;
}
if (gpio_bus_switch > 0)
return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
else
return SOCAM_DATAWIDTH_10;
}
static struct soc_camera_link iclink = {
.bus_id = 0, /* Must match with the camera ID above */
.query_bus_param = pcm990_camera_query_bus_param,
.set_bus_param = pcm990_camera_set_bus_param,
}; };
/* Board I2C devices. */ /* Board I2C devices. */
@@ -398,10 +433,10 @@ static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
.platform_data = &pca9536_data, .platform_data = &pca9536_data,
}, { }, {
I2C_BOARD_INFO("mt9v022", 0x48), I2C_BOARD_INFO("mt9v022", 0x48),
.platform_data = &iclink[0], /* With extender */ .platform_data = &iclink, /* With extender */
}, { }, {
I2C_BOARD_INFO("mt9m001", 0x5d), I2C_BOARD_INFO("mt9m001", 0x5d),
.platform_data = &iclink[0], /* With extender */ .platform_data = &iclink, /* With extender */
}, },
}; };
#endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */ #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */

View File

@@ -0,0 +1,52 @@
/*
* mx3_camera.h - i.MX3x camera driver header file
*
* Copyright (C) 2008, Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _MX3_CAMERA_H_
#define _MX3_CAMERA_H_
#include <linux/device.h>
#define MX3_CAMERA_CLK_SRC 1
#define MX3_CAMERA_EXT_VSYNC 2
#define MX3_CAMERA_DP 4
#define MX3_CAMERA_PCP 8
#define MX3_CAMERA_HSP 0x10
#define MX3_CAMERA_VSP 0x20
#define MX3_CAMERA_DATAWIDTH_4 0x40
#define MX3_CAMERA_DATAWIDTH_8 0x80
#define MX3_CAMERA_DATAWIDTH_10 0x100
#define MX3_CAMERA_DATAWIDTH_15 0x200
#define MX3_CAMERA_DATAWIDTH_MASK (MX3_CAMERA_DATAWIDTH_4 | MX3_CAMERA_DATAWIDTH_8 | \
MX3_CAMERA_DATAWIDTH_10 | MX3_CAMERA_DATAWIDTH_15)
/**
* struct mx3_camera_pdata - i.MX3x camera platform data
* @flags: MX3_CAMERA_* flags
* @mclk_10khz: master clock frequency in 10kHz units
* @dma_dev: IPU DMA device to match against in channel allocation
*/
struct mx3_camera_pdata {
unsigned long flags;
unsigned long mclk_10khz;
struct device *dma_dev;
};
#endif

View File

@@ -310,7 +310,8 @@ static struct platform_device camera_device = {
static struct sh_mobile_ceu_info sh_mobile_ceu_info = { static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
.flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH | .flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8, SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER |
SOCAM_DATAWIDTH_8,
}; };
static struct resource ceu_resources[] = { static struct resource ceu_resources[] = {

View File

@@ -352,8 +352,9 @@ static int tw9910_power(struct device *dev, int mode)
} }
static struct sh_mobile_ceu_info sh_mobile_ceu_info = { static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
.flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING \ .flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING
| SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH, | SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH
| SOCAM_DATA_ACTIVE_HIGH,
}; };
static struct resource migor_ceu_resources[] = { static struct resource migor_ceu_resources[] = {

View File

@@ -117,7 +117,7 @@ source "drivers/media/dvb/Kconfig"
config DAB config DAB
boolean "DAB adapters" boolean "DAB adapters"
---help--- ---help---
Allow selecting support for for Digital Audio Broadcasting (DAB) Allow selecting support for Digital Audio Broadcasting (DAB)
Receiver adapters. Receiver adapters.
if DAB if DAB

View File

@@ -153,6 +153,65 @@ IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = {
}; };
EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a); EXPORT_SYMBOL_GPL(ir_codes_avermedia_m135a);
/* Oldrich Jedlicka <oldium.pro@seznam.cz> */
IR_KEYTAB_TYPE ir_codes_avermedia_cardbus[IR_KEYTAB_SIZE] = {
[0x00] = KEY_POWER,
[0x01] = KEY_TUNER, /* TV/FM */
[0x03] = KEY_TEXT, /* Teletext */
[0x04] = KEY_EPG,
[0x05] = KEY_1,
[0x06] = KEY_2,
[0x07] = KEY_3,
[0x08] = KEY_AUDIO,
[0x09] = KEY_4,
[0x0a] = KEY_5,
[0x0b] = KEY_6,
[0x0c] = KEY_ZOOM, /* Full screen */
[0x0d] = KEY_7,
[0x0e] = KEY_8,
[0x0f] = KEY_9,
[0x10] = KEY_PAGEUP, /* 16-CH PREV */
[0x11] = KEY_0,
[0x12] = KEY_INFO,
[0x13] = KEY_AGAIN, /* CH RTN - channel return */
[0x14] = KEY_MUTE,
[0x15] = KEY_EDIT, /* Autoscan */
[0x17] = KEY_SAVE, /* Screenshot */
[0x18] = KEY_PLAYPAUSE,
[0x19] = KEY_RECORD,
[0x1a] = KEY_PLAY,
[0x1b] = KEY_STOP,
[0x1c] = KEY_FASTFORWARD,
[0x1d] = KEY_REWIND,
[0x1e] = KEY_VOLUMEDOWN,
[0x1f] = KEY_VOLUMEUP,
[0x22] = KEY_SLEEP, /* Sleep */
[0x23] = KEY_ZOOM, /* Aspect */
[0x26] = KEY_SCREEN, /* Pos */
[0x27] = KEY_ANGLE, /* Size */
[0x28] = KEY_SELECT, /* Select */
[0x29] = KEY_BLUE, /* Blue/Picture */
[0x2a] = KEY_BACKSPACE, /* Back */
[0x2b] = KEY_MEDIA, /* PIP (Picture-in-picture) */
[0x2c] = KEY_DOWN,
[0x2e] = KEY_DOT,
[0x2f] = KEY_TV, /* Live TV */
[0x32] = KEY_LEFT,
[0x33] = KEY_CLEAR, /* Clear */
[0x35] = KEY_RED, /* Red/TV */
[0x36] = KEY_UP,
[0x37] = KEY_HOME, /* Home */
[0x39] = KEY_GREEN, /* Green/Video */
[0x3d] = KEY_YELLOW, /* Yellow/Music */
[0x3e] = KEY_OK, /* Ok */
[0x3f] = KEY_RIGHT,
[0x40] = KEY_NEXT, /* Next */
[0x41] = KEY_PREVIOUS, /* Previous */
[0x42] = KEY_CHANNELDOWN, /* Channel down */
[0x43] = KEY_CHANNELUP /* Channel up */
};
EXPORT_SYMBOL_GPL(ir_codes_avermedia_cardbus);
/* Attila Kondoros <attila.kondoros@chello.hu> */ /* Attila Kondoros <attila.kondoros@chello.hu> */
IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = { IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
@@ -2452,6 +2511,55 @@ IR_KEYTAB_TYPE ir_codes_kworld_plus_tv_analog[IR_KEYTAB_SIZE] = {
}; };
EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog); EXPORT_SYMBOL_GPL(ir_codes_kworld_plus_tv_analog);
/* Kaiomy TVnPC U2
Mauro Carvalho Chehab <mchehab@infradead.org>
*/
IR_KEYTAB_TYPE ir_codes_kaiomy[IR_KEYTAB_SIZE] = {
[0x43] = KEY_POWER2,
[0x01] = KEY_LIST,
[0x0b] = KEY_ZOOM,
[0x03] = KEY_POWER,
[0x04] = KEY_1,
[0x08] = KEY_2,
[0x02] = KEY_3,
[0x0f] = KEY_4,
[0x05] = KEY_5,
[0x06] = KEY_6,
[0x0c] = KEY_7,
[0x0d] = KEY_8,
[0x0a] = KEY_9,
[0x11] = KEY_0,
[0x09] = KEY_CHANNELUP,
[0x07] = KEY_CHANNELDOWN,
[0x0e] = KEY_VOLUMEUP,
[0x13] = KEY_VOLUMEDOWN,
[0x10] = KEY_HOME,
[0x12] = KEY_ENTER,
[0x14] = KEY_RECORD,
[0x15] = KEY_STOP,
[0x16] = KEY_PLAY,
[0x17] = KEY_MUTE,
[0x18] = KEY_UP,
[0x19] = KEY_DOWN,
[0x1a] = KEY_LEFT,
[0x1b] = KEY_RIGHT,
[0x1c] = KEY_RED,
[0x1d] = KEY_GREEN,
[0x1e] = KEY_YELLOW,
[0x1f] = KEY_BLUE,
};
EXPORT_SYMBOL_GPL(ir_codes_kaiomy);
IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = { IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = {
[0x20] = KEY_LIST, [0x20] = KEY_LIST,
[0x00] = KEY_POWER, [0x00] = KEY_POWER,
@@ -2604,3 +2712,41 @@ IR_KEYTAB_TYPE ir_codes_ati_tv_wonder_hd_600[IR_KEYTAB_SIZE] = {
}; };
EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600); EXPORT_SYMBOL_GPL(ir_codes_ati_tv_wonder_hd_600);
/* DVBWorld remotes
Igor M. Liplianin <liplianin@me.by>
*/
IR_KEYTAB_TYPE ir_codes_dm1105_nec[IR_KEYTAB_SIZE] = {
[0x0a] = KEY_Q, /*power*/
[0x0c] = KEY_M, /*mute*/
[0x11] = KEY_1,
[0x12] = KEY_2,
[0x13] = KEY_3,
[0x14] = KEY_4,
[0x15] = KEY_5,
[0x16] = KEY_6,
[0x17] = KEY_7,
[0x18] = KEY_8,
[0x19] = KEY_9,
[0x10] = KEY_0,
[0x1c] = KEY_PAGEUP, /*ch+*/
[0x0f] = KEY_PAGEDOWN, /*ch-*/
[0x1a] = KEY_O, /*vol+*/
[0x0e] = KEY_Z, /*vol-*/
[0x04] = KEY_R, /*rec*/
[0x09] = KEY_D, /*fav*/
[0x08] = KEY_BACKSPACE, /*rewind*/
[0x07] = KEY_A, /*fast*/
[0x0b] = KEY_P, /*pause*/
[0x02] = KEY_ESC, /*cancel*/
[0x03] = KEY_G, /*tab*/
[0x00] = KEY_UP, /*up*/
[0x1f] = KEY_ENTER, /*ok*/
[0x01] = KEY_DOWN, /*down*/
[0x05] = KEY_C, /*cap*/
[0x06] = KEY_S, /*stop*/
[0x40] = KEY_F, /*full*/
[0x1e] = KEY_W, /*tvmode*/
[0x1b] = KEY_B, /*recall*/
};
EXPORT_SYMBOL_GPL(ir_codes_dm1105_nec);

View File

@@ -452,8 +452,6 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device)); INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
dev->ext = ext; dev->ext = ext;
pci_set_drvdata(pci, dev);
mutex_init(&dev->lock); mutex_init(&dev->lock);
spin_lock_init(&dev->int_slock); spin_lock_init(&dev->int_slock);
spin_lock_init(&dev->slock); spin_lock_init(&dev->slock);
@@ -477,8 +475,12 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
if (ext->attach(dev, pci_ext)) { if (ext->attach(dev, pci_ext)) {
DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); DEB_D(("ext->attach() failed for %p. skipping device.\n",dev));
goto err_unprobe; goto err_free_i2c;
} }
/* V4L extensions will set the pci drvdata to the v4l2_device in the
attach() above. So for those cards that do not use V4L we have to
set it explicitly. */
pci_set_drvdata(pci, &dev->v4l2_dev);
INIT_LIST_HEAD(&dev->item); INIT_LIST_HEAD(&dev->item);
list_add_tail(&dev->item,&saa7146_devices); list_add_tail(&dev->item,&saa7146_devices);
@@ -488,8 +490,6 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
out: out:
return err; return err;
err_unprobe:
pci_set_drvdata(pci, NULL);
err_free_i2c: err_free_i2c:
pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr,
dev->d_i2c.dma_handle); dev->d_i2c.dma_handle);
@@ -514,7 +514,8 @@ err_free:
static void saa7146_remove_one(struct pci_dev *pdev) static void saa7146_remove_one(struct pci_dev *pdev)
{ {
struct saa7146_dev* dev = pci_get_drvdata(pdev); struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
struct saa7146_dev *dev = to_saa7146_dev(v4l2_dev);
struct { struct {
void *addr; void *addr;
dma_addr_t dma; dma_addr_t dma;
@@ -528,6 +529,8 @@ static void saa7146_remove_one(struct pci_dev *pdev)
DEB_EE(("dev:%p\n",dev)); DEB_EE(("dev:%p\n",dev));
dev->ext->detach(dev); dev->ext->detach(dev);
/* Zero the PCI drvdata after use. */
pci_set_drvdata(pdev, NULL);
/* shut down all video dma transfers */ /* shut down all video dma transfers */
saa7146_write(dev, MC1, 0x00ff0000); saa7146_write(dev, MC1, 0x00ff0000);

View File

@@ -308,14 +308,6 @@ static int fops_release(struct file *file)
return 0; return 0;
} }
static long fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
/*
DEB_EE(("file:%p, cmd:%d, arg:%li\n", file, cmd, arg));
*/
return video_usercopy(file, cmd, arg, saa7146_video_do_ioctl);
}
static int fops_mmap(struct file *file, struct vm_area_struct * vma) static int fops_mmap(struct file *file, struct vm_area_struct * vma)
{ {
struct saa7146_fh *fh = file->private_data; struct saa7146_fh *fh = file->private_data;
@@ -425,7 +417,7 @@ static const struct v4l2_file_operations video_fops =
.write = fops_write, .write = fops_write,
.poll = fops_poll, .poll = fops_poll,
.mmap = fops_mmap, .mmap = fops_mmap,
.ioctl = fops_ioctl, .ioctl = video_ioctl2,
}; };
static void vv_callback(struct saa7146_dev *dev, unsigned long status) static void vv_callback(struct saa7146_dev *dev, unsigned long status)
@@ -452,19 +444,22 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
} }
} }
static struct video_device device_template =
{
.fops = &video_fops,
.minor = -1,
};
int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
{ {
struct saa7146_vv *vv = kzalloc (sizeof(struct saa7146_vv),GFP_KERNEL); struct saa7146_vv *vv;
if( NULL == vv ) { int err;
err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev);
if (err)
return err;
vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
if (vv == NULL) {
ERR(("out of memory. aborting.\n")); ERR(("out of memory. aborting.\n"));
return -1; return -ENOMEM;
} }
ext_vv->ops = saa7146_video_ioctl_ops;
ext_vv->core_ops = &saa7146_video_ioctl_ops;
DEB_EE(("dev:%p\n",dev)); DEB_EE(("dev:%p\n",dev));
@@ -507,6 +502,7 @@ int saa7146_vv_release(struct saa7146_dev* dev)
DEB_EE(("dev:%p\n",dev)); DEB_EE(("dev:%p\n",dev));
v4l2_device_unregister(&dev->v4l2_dev);
pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
kfree(vv); kfree(vv);
dev->vv_data = NULL; dev->vv_data = NULL;
@@ -521,6 +517,8 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
{ {
struct saa7146_vv *vv = dev->vv_data; struct saa7146_vv *vv = dev->vv_data;
struct video_device *vfd; struct video_device *vfd;
int err;
int i;
DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type)); DEB_EE(("dev:%p, name:'%s', type:%d\n",dev,name,type));
@@ -529,16 +527,20 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
if (vfd == NULL) if (vfd == NULL)
return -ENOMEM; return -ENOMEM;
memcpy(vfd, &device_template, sizeof(struct video_device)); vfd->fops = &video_fops;
strlcpy(vfd->name, name, sizeof(vfd->name)); vfd->ioctl_ops = &dev->ext_vv_data->ops;
vfd->release = video_device_release; vfd->release = video_device_release;
vfd->tvnorms = 0;
for (i = 0; i < dev->ext_vv_data->num_stds; i++)
vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
strlcpy(vfd->name, name, sizeof(vfd->name));
video_set_drvdata(vfd, dev); video_set_drvdata(vfd, dev);
// fixme: -1 should be an insmod parameter *for the extension* (like "video_nr"); err = video_register_device(vfd, type, -1);
if (video_register_device(vfd, type, -1) < 0) { if (err < 0) {
ERR(("cannot register v4l2 device. skipping.\n")); ERR(("cannot register v4l2 device. skipping.\n"));
video_device_release(vfd); video_device_release(vfd);
return -1; return err;
} }
if( VFL_TYPE_GRABBER == type ) { if( VFL_TYPE_GRABBER == type ) {

View File

@@ -293,7 +293,6 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
int i = 0, count = 0; int i = 0, count = 0;
__le32 *buffer = dev->d_i2c.cpu_addr; __le32 *buffer = dev->d_i2c.cpu_addr;
int err = 0; int err = 0;
int address_err = 0;
int short_delay = 0; int short_delay = 0;
if (mutex_lock_interruptible(&dev->i2c_lock)) if (mutex_lock_interruptible(&dev->i2c_lock))
@@ -333,17 +332,10 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
i2c address probing, however, and address errors indicate that a i2c address probing, however, and address errors indicate that a
device is really *not* there. retrying in that case device is really *not* there. retrying in that case
increases the time the device needs to probe greatly, so increases the time the device needs to probe greatly, so
it should be avoided. because of the fact, that only it should be avoided. So we bail out in irq mode after an
analog based cards use irq based i2c transactions (for dvb address error and trust the saa7146 address error detection. */
cards, this screwes up other interrupt sources), we bail out if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags))
completely for analog cards after an address error and trust
the saa7146 address error detection. */
if ( -EREMOTEIO == err ) {
if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
goto out; goto out;
}
address_err++;
}
DEB_I2C(("error while sending message(s). starting again.\n")); DEB_I2C(("error while sending message(s). starting again.\n"));
break; break;
} }
@@ -358,10 +350,9 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
} while (err != num && retries--); } while (err != num && retries--);
/* if every retry had an address error, exit right away */ /* quit if any error occurred */
if (address_err == retries) { if (err != num)
goto out; goto out;
}
/* if any things had to be read, get the results */ /* if any things had to be read, get the results */
if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) { if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
@@ -390,7 +381,8 @@ out:
/* utility functions */ /* utility functions */
static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num) static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
{ {
struct saa7146_dev* dev = i2c_get_adapdata(adapter); struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter);
struct saa7146_dev *dev = to_saa7146_dev(v4l2_dev);
/* use helper function to transfer data */ /* use helper function to transfer data */
return saa7146_i2c_transfer(dev, msg, num, adapter->retries); return saa7146_i2c_transfer(dev, msg, num, adapter->retries);
@@ -417,9 +409,8 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c
dev->i2c_bitrate = bitrate; dev->i2c_bitrate = bitrate;
saa7146_i2c_reset(dev); saa7146_i2c_reset(dev);
if( NULL != i2c_adapter ) { if (i2c_adapter) {
BUG_ON(!i2c_adapter->class); i2c_set_adapdata(i2c_adapter, &dev->v4l2_dev);
i2c_set_adapdata(i2c_adapter,dev);
i2c_adapter->dev.parent = &dev->pci->dev; i2c_adapter->dev.parent = &dev->pci->dev;
i2c_adapter->algo = &saa7146_algo; i2c_adapter->algo = &saa7146_algo;
i2c_adapter->algo_data = NULL; i2c_adapter->algo_data = NULL;

File diff suppressed because it is too large Load Diff

View File

@@ -21,16 +21,17 @@ config MEDIA_TUNER
tristate tristate
default VIDEO_MEDIA && I2C default VIDEO_MEDIA && I2C
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
menuconfig MEDIA_TUNER_CUSTOMIZE menuconfig MEDIA_TUNER_CUSTOMISE
bool "Customize analog and hybrid tuner modules to build" bool "Customize analog and hybrid tuner modules to build"
depends on MEDIA_TUNER depends on MEDIA_TUNER
default n default n
@@ -43,13 +44,13 @@ menuconfig MEDIA_TUNER_CUSTOMIZE
If unsure say N. If unsure say N.
if MEDIA_TUNER_CUSTOMIZE if MEDIA_TUNER_CUSTOMISE
config MEDIA_TUNER_SIMPLE config MEDIA_TUNER_SIMPLE
tristate "Simple tuner support" tristate "Simple tuner support"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
select MEDIA_TUNER_TDA9887 select MEDIA_TUNER_TDA9887
default m if MEDIA_TUNER_CUSTOMIZE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for various simple tuners. Say Y here to include support for various simple tuners.
@@ -58,28 +59,28 @@ config MEDIA_TUNER_TDA8290
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
select MEDIA_TUNER_TDA827X select MEDIA_TUNER_TDA827X
select MEDIA_TUNER_TDA18271 select MEDIA_TUNER_TDA18271
default m if MEDIA_TUNER_CUSTOMIZE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for Philips TDA8290+8275(a) tuner. Say Y here to include support for Philips TDA8290+8275(a) tuner.
config MEDIA_TUNER_TDA827X config MEDIA_TUNER_TDA827X
tristate "Philips TDA827X silicon tuner" tristate "Philips TDA827X silicon tuner"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if DVB_FE_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A DVB-T silicon tuner module. Say Y when you want to support this tuner. A DVB-T silicon tuner module. Say Y when you want to support this tuner.
config MEDIA_TUNER_TDA18271 config MEDIA_TUNER_TDA18271
tristate "NXP TDA18271 silicon tuner" tristate "NXP TDA18271 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if DVB_FE_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A silicon tuner module. Say Y when you want to support this tuner. A silicon tuner module. Say Y when you want to support this tuner.
config MEDIA_TUNER_TDA9887 config MEDIA_TUNER_TDA9887
tristate "TDA 9885/6/7 analog IF demodulator" tristate "TDA 9885/6/7 analog IF demodulator"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if MEDIA_TUNER_CUSTOMIZE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for Philips TDA9885/6/7 Say Y here to include support for Philips TDA9885/6/7
analog IF demodulator. analog IF demodulator.
@@ -88,63 +89,63 @@ config MEDIA_TUNER_TEA5761
tristate "TEA 5761 radio tuner (EXPERIMENTAL)" tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
depends on EXPERIMENTAL depends on EXPERIMENTAL
default m if MEDIA_TUNER_CUSTOMIZE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for the Philips TEA5761 radio tuner. Say Y here to include support for the Philips TEA5761 radio tuner.
config MEDIA_TUNER_TEA5767 config MEDIA_TUNER_TEA5767
tristate "TEA 5767 radio tuner" tristate "TEA 5767 radio tuner"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if MEDIA_TUNER_CUSTOMIZE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for the Philips TEA5767 radio tuner. Say Y here to include support for the Philips TEA5767 radio tuner.
config MEDIA_TUNER_MT20XX config MEDIA_TUNER_MT20XX
tristate "Microtune 2032 / 2050 tuners" tristate "Microtune 2032 / 2050 tuners"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if MEDIA_TUNER_CUSTOMIZE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for the MT2032 / MT2050 tuner. Say Y here to include support for the MT2032 / MT2050 tuner.
config MEDIA_TUNER_MT2060 config MEDIA_TUNER_MT2060
tristate "Microtune MT2060 silicon IF tuner" tristate "Microtune MT2060 silicon IF tuner"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if DVB_FE_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon IF tuner MT2060 from Microtune. A driver for the silicon IF tuner MT2060 from Microtune.
config MEDIA_TUNER_MT2266 config MEDIA_TUNER_MT2266
tristate "Microtune MT2266 silicon tuner" tristate "Microtune MT2266 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if DVB_FE_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon baseband tuner MT2266 from Microtune. A driver for the silicon baseband tuner MT2266 from Microtune.
config MEDIA_TUNER_MT2131 config MEDIA_TUNER_MT2131
tristate "Microtune MT2131 silicon tuner" tristate "Microtune MT2131 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if DVB_FE_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon baseband tuner MT2131 from Microtune. A driver for the silicon baseband tuner MT2131 from Microtune.
config MEDIA_TUNER_QT1010 config MEDIA_TUNER_QT1010
tristate "Quantek QT1010 silicon tuner" tristate "Quantek QT1010 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if DVB_FE_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon tuner QT1010 from Quantek. A driver for the silicon tuner QT1010 from Quantek.
config MEDIA_TUNER_XC2028 config MEDIA_TUNER_XC2028
tristate "XCeive xc2028/xc3028 tuners" tristate "XCeive xc2028/xc3028 tuners"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if MEDIA_TUNER_CUSTOMIZE default m if MEDIA_TUNER_CUSTOMISE
help help
Say Y here to include support for the xc2028/xc3028 tuners. Say Y here to include support for the xc2028/xc3028 tuners.
config MEDIA_TUNER_XC5000 config MEDIA_TUNER_XC5000
tristate "Xceive XC5000 silicon tuner" tristate "Xceive XC5000 silicon tuner"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if DVB_FE_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon tuner XC5000 from Xceive. A driver for the silicon tuner XC5000 from Xceive.
This device is only used inside a SiP called togther with a This device is only used inside a SiP called togther with a
@@ -153,15 +154,22 @@ config MEDIA_TUNER_XC5000
config MEDIA_TUNER_MXL5005S config MEDIA_TUNER_MXL5005S
tristate "MaxLinear MSL5005S silicon tuner" tristate "MaxLinear MSL5005S silicon tuner"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if DVB_FE_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon tuner MXL5005S from MaxLinear. A driver for the silicon tuner MXL5005S from MaxLinear.
config MEDIA_TUNER_MXL5007T config MEDIA_TUNER_MXL5007T
tristate "MaxLinear MxL5007T silicon tuner" tristate "MaxLinear MxL5007T silicon tuner"
depends on VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C
default m if DVB_FE_CUSTOMISE default m if MEDIA_TUNER_CUSTOMISE
help help
A driver for the silicon tuner MxL5007T from MaxLinear. A driver for the silicon tuner MxL5007T from MaxLinear.
endif # MEDIA_TUNER_CUSTOMIZE config MEDIA_TUNER_MC44S803
tristate "Freescale MC44S803 Low Power CMOS Broadband tuners"
depends on VIDEO_MEDIA && I2C
default m if MEDIA_TUNER_CUSTOMISE
help
Say Y here to support the Freescale MC44S803 based tuners
endif # MEDIA_TUNER_CUSTOMISE

View File

@@ -22,6 +22,7 @@ obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o
obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends EXTRA_CFLAGS += -Idrivers/media/dvb/frontends

View File

@@ -0,0 +1,371 @@
/*
* Driver for Freescale MC44S803 Low Power CMOS Broadband Tuner
*
* Copyright (c) 2009 Jochen Friedrich <jochen@scram.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/dvb/frontend.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
#include "mc44s803.h"
#include "mc44s803_priv.h"
#define mc_printk(level, format, arg...) \
printk(level "mc44s803: " format , ## arg)
/* Writes a single register */
static int mc44s803_writereg(struct mc44s803_priv *priv, u32 val)
{
u8 buf[3];
struct i2c_msg msg = {
.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 3
};
buf[0] = (val & 0xff0000) >> 16;
buf[1] = (val & 0xff00) >> 8;
buf[2] = (val & 0xff);
if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
mc_printk(KERN_WARNING, "I2C write failed\n");
return -EREMOTEIO;
}
return 0;
}
/* Reads a single register */
static int mc44s803_readreg(struct mc44s803_priv *priv, u8 reg, u32 *val)
{
u32 wval;
u8 buf[3];
int ret;
struct i2c_msg msg[] = {
{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
.buf = buf, .len = 3 },
};
wval = MC44S803_REG_SM(MC44S803_REG_DATAREG, MC44S803_ADDR) |
MC44S803_REG_SM(reg, MC44S803_D);
ret = mc44s803_writereg(priv, wval);
if (ret)
return ret;
if (i2c_transfer(priv->i2c, msg, 1) != 1) {
mc_printk(KERN_WARNING, "I2C read failed\n");
return -EREMOTEIO;
}
*val = (buf[0] << 16) | (buf[1] << 8) | buf[2];
return 0;
}
static int mc44s803_release(struct dvb_frontend *fe)
{
struct mc44s803_priv *priv = fe->tuner_priv;
fe->tuner_priv = NULL;
kfree(priv);
return 0;
}
static int mc44s803_init(struct dvb_frontend *fe)
{
struct mc44s803_priv *priv = fe->tuner_priv;
u32 val;
int err;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
/* Reset chip */
val = MC44S803_REG_SM(MC44S803_REG_RESET, MC44S803_ADDR) |
MC44S803_REG_SM(1, MC44S803_RS);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
val = MC44S803_REG_SM(MC44S803_REG_RESET, MC44S803_ADDR);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
/* Power Up and Start Osc */
val = MC44S803_REG_SM(MC44S803_REG_REFOSC, MC44S803_ADDR) |
MC44S803_REG_SM(0xC0, MC44S803_REFOSC) |
MC44S803_REG_SM(1, MC44S803_OSCSEL);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
val = MC44S803_REG_SM(MC44S803_REG_POWER, MC44S803_ADDR) |
MC44S803_REG_SM(0x200, MC44S803_POWER);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
msleep(10);
val = MC44S803_REG_SM(MC44S803_REG_REFOSC, MC44S803_ADDR) |
MC44S803_REG_SM(0x40, MC44S803_REFOSC) |
MC44S803_REG_SM(1, MC44S803_OSCSEL);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
msleep(20);
/* Setup Mixer */
val = MC44S803_REG_SM(MC44S803_REG_MIXER, MC44S803_ADDR) |
MC44S803_REG_SM(1, MC44S803_TRI_STATE) |
MC44S803_REG_SM(0x7F, MC44S803_MIXER_RES);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
/* Setup Cirquit Adjust */
val = MC44S803_REG_SM(MC44S803_REG_CIRCADJ, MC44S803_ADDR) |
MC44S803_REG_SM(1, MC44S803_G1) |
MC44S803_REG_SM(1, MC44S803_G3) |
MC44S803_REG_SM(0x3, MC44S803_CIRCADJ_RES) |
MC44S803_REG_SM(1, MC44S803_G6) |
MC44S803_REG_SM(priv->cfg->dig_out, MC44S803_S1) |
MC44S803_REG_SM(0x3, MC44S803_LP) |
MC44S803_REG_SM(1, MC44S803_CLRF) |
MC44S803_REG_SM(1, MC44S803_CLIF);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
val = MC44S803_REG_SM(MC44S803_REG_CIRCADJ, MC44S803_ADDR) |
MC44S803_REG_SM(1, MC44S803_G1) |
MC44S803_REG_SM(1, MC44S803_G3) |
MC44S803_REG_SM(0x3, MC44S803_CIRCADJ_RES) |
MC44S803_REG_SM(1, MC44S803_G6) |
MC44S803_REG_SM(priv->cfg->dig_out, MC44S803_S1) |
MC44S803_REG_SM(0x3, MC44S803_LP);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
/* Setup Digtune */
val = MC44S803_REG_SM(MC44S803_REG_DIGTUNE, MC44S803_ADDR) |
MC44S803_REG_SM(3, MC44S803_XOD);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
/* Setup AGC */
val = MC44S803_REG_SM(MC44S803_REG_LNAAGC, MC44S803_ADDR) |
MC44S803_REG_SM(1, MC44S803_AT1) |
MC44S803_REG_SM(1, MC44S803_AT2) |
MC44S803_REG_SM(1, MC44S803_AGC_AN_DIG) |
MC44S803_REG_SM(1, MC44S803_AGC_READ_EN) |
MC44S803_REG_SM(1, MC44S803_LNA0);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
return 0;
exit:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
mc_printk(KERN_WARNING, "I/O Error\n");
return err;
}
static int mc44s803_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params)
{
struct mc44s803_priv *priv = fe->tuner_priv;
u32 r1, r2, n1, n2, lo1, lo2, freq, val;
int err;
priv->frequency = params->frequency;
r1 = MC44S803_OSC / 1000000;
r2 = MC44S803_OSC / 100000;
n1 = (params->frequency + MC44S803_IF1 + 500000) / 1000000;
freq = MC44S803_OSC / r1 * n1;
lo1 = ((60 * n1) + (r1 / 2)) / r1;
freq = freq - params->frequency;
n2 = (freq - MC44S803_IF2 + 50000) / 100000;
lo2 = ((60 * n2) + (r2 / 2)) / r2;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
val = MC44S803_REG_SM(MC44S803_REG_REFDIV, MC44S803_ADDR) |
MC44S803_REG_SM(r1-1, MC44S803_R1) |
MC44S803_REG_SM(r2-1, MC44S803_R2) |
MC44S803_REG_SM(1, MC44S803_REFBUF_EN);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
val = MC44S803_REG_SM(MC44S803_REG_LO1, MC44S803_ADDR) |
MC44S803_REG_SM(n1-2, MC44S803_LO1);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
val = MC44S803_REG_SM(MC44S803_REG_LO2, MC44S803_ADDR) |
MC44S803_REG_SM(n2-2, MC44S803_LO2);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
val = MC44S803_REG_SM(MC44S803_REG_DIGTUNE, MC44S803_ADDR) |
MC44S803_REG_SM(1, MC44S803_DA) |
MC44S803_REG_SM(lo1, MC44S803_LO_REF) |
MC44S803_REG_SM(1, MC44S803_AT);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
val = MC44S803_REG_SM(MC44S803_REG_DIGTUNE, MC44S803_ADDR) |
MC44S803_REG_SM(2, MC44S803_DA) |
MC44S803_REG_SM(lo2, MC44S803_LO_REF) |
MC44S803_REG_SM(1, MC44S803_AT);
err = mc44s803_writereg(priv, val);
if (err)
goto exit;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
return 0;
exit:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
mc_printk(KERN_WARNING, "I/O Error\n");
return err;
}
static int mc44s803_get_frequency(struct dvb_frontend *fe, u32 *frequency)
{
struct mc44s803_priv *priv = fe->tuner_priv;
*frequency = priv->frequency;
return 0;
}
static const struct dvb_tuner_ops mc44s803_tuner_ops = {
.info = {
.name = "Freescale MC44S803",
.frequency_min = 48000000,
.frequency_max = 1000000000,
.frequency_step = 100000,
},
.release = mc44s803_release,
.init = mc44s803_init,
.set_params = mc44s803_set_params,
.get_frequency = mc44s803_get_frequency
};
/* This functions tries to identify a MC44S803 tuner by reading the ID
register. This is hasty. */
struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, struct mc44s803_config *cfg)
{
struct mc44s803_priv *priv;
u32 reg;
u8 id;
int ret;
reg = 0;
priv = kzalloc(sizeof(struct mc44s803_priv), GFP_KERNEL);
if (priv == NULL)
return NULL;
priv->cfg = cfg;
priv->i2c = i2c;
priv->fe = fe;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
ret = mc44s803_readreg(priv, MC44S803_REG_ID, &reg);
if (ret)
goto error;
id = MC44S803_REG_MS(reg, MC44S803_ID);
if (id != 0x14) {
mc_printk(KERN_ERR, "unsupported ID "
"(%x should be 0x14)\n", id);
goto error;
}
mc_printk(KERN_INFO, "successfully identified (ID = %x)\n", id);
memcpy(&fe->ops.tuner_ops, &mc44s803_tuner_ops,
sizeof(struct dvb_tuner_ops));
fe->tuner_priv = priv;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
return fe;
error:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
kfree(priv);
return NULL;
}
EXPORT_SYMBOL(mc44s803_attach);
MODULE_AUTHOR("Jochen Friedrich");
MODULE_DESCRIPTION("Freescale MC44S803 silicon tuner driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,46 @@
/*
* Driver for Freescale MC44S803 Low Power CMOS Broadband Tuner
*
* Copyright (c) 2009 Jochen Friedrich <jochen@scram.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
*/
#ifndef MC44S803_H
#define MC44S803_H
struct dvb_frontend;
struct i2c_adapter;
struct mc44s803_config {
u8 i2c_address;
u8 dig_out;
};
#if defined(CONFIG_MEDIA_TUNER_MC44S803) || \
(defined(CONFIG_MEDIA_TUNER_MC44S803_MODULE) && defined(MODULE))
extern struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, struct mc44s803_config *cfg);
#else
static inline struct dvb_frontend *mc44s803_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, struct mc44s803_config *cfg)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_MEDIA_TUNER_MC44S803 */
#endif

View File

@@ -0,0 +1,208 @@
/*
* Driver for Freescale MC44S803 Low Power CMOS Broadband Tuner
*
* Copyright (c) 2009 Jochen Friedrich <jochen@scram.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
*/
#ifndef MC44S803_PRIV_H
#define MC44S803_PRIV_H
/* This driver is based on the information available in the datasheet
http://www.freescale.com/files/rf_if/doc/data_sheet/MC44S803.pdf
SPI or I2C Address : 0xc0-0xc6
Reg.No | Function
-------------------------------------------
00 | Power Down
01 | Reference Oszillator
02 | Reference Dividers
03 | Mixer and Reference Buffer
04 | Reset/Serial Out
05 | LO 1
06 | LO 2
07 | Circuit Adjust
08 | Test
09 | Digital Tune
0A | LNA AGC
0B | Data Register Address
0C | Regulator Test
0D | VCO Test
0E | LNA Gain/Input Power
0F | ID Bits
*/
#define MC44S803_OSC 26000000 /* 26 MHz */
#define MC44S803_IF1 1086000000 /* 1086 MHz */
#define MC44S803_IF2 36125000 /* 36.125 MHz */
#define MC44S803_REG_POWER 0
#define MC44S803_REG_REFOSC 1
#define MC44S803_REG_REFDIV 2
#define MC44S803_REG_MIXER 3
#define MC44S803_REG_RESET 4
#define MC44S803_REG_LO1 5
#define MC44S803_REG_LO2 6
#define MC44S803_REG_CIRCADJ 7
#define MC44S803_REG_TEST 8
#define MC44S803_REG_DIGTUNE 9
#define MC44S803_REG_LNAAGC 0x0A
#define MC44S803_REG_DATAREG 0x0B
#define MC44S803_REG_REGTEST 0x0C
#define MC44S803_REG_VCOTEST 0x0D
#define MC44S803_REG_LNAGAIN 0x0E
#define MC44S803_REG_ID 0x0F
/* Register definitions */
#define MC44S803_ADDR 0x0F
#define MC44S803_ADDR_S 0
/* REG_POWER */
#define MC44S803_POWER 0xFFFFF0
#define MC44S803_POWER_S 4
/* REG_REFOSC */
#define MC44S803_REFOSC 0x1FF0
#define MC44S803_REFOSC_S 4
#define MC44S803_OSCSEL 0x2000
#define MC44S803_OSCSEL_S 13
/* REG_REFDIV */
#define MC44S803_R2 0x1FF0
#define MC44S803_R2_S 4
#define MC44S803_REFBUF_EN 0x2000
#define MC44S803_REFBUF_EN_S 13
#define MC44S803_R1 0x7C000
#define MC44S803_R1_S 14
/* REG_MIXER */
#define MC44S803_R3 0x70
#define MC44S803_R3_S 4
#define MC44S803_MUX3 0x80
#define MC44S803_MUX3_S 7
#define MC44S803_MUX4 0x100
#define MC44S803_MUX4_S 8
#define MC44S803_OSC_SCR 0x200
#define MC44S803_OSC_SCR_S 9
#define MC44S803_TRI_STATE 0x400
#define MC44S803_TRI_STATE_S 10
#define MC44S803_BUF_GAIN 0x800
#define MC44S803_BUF_GAIN_S 11
#define MC44S803_BUF_IO 0x1000
#define MC44S803_BUF_IO_S 12
#define MC44S803_MIXER_RES 0xFE000
#define MC44S803_MIXER_RES_S 13
/* REG_RESET */
#define MC44S803_RS 0x10
#define MC44S803_RS_S 4
#define MC44S803_SO 0x20
#define MC44S803_SO_S 5
/* REG_LO1 */
#define MC44S803_LO1 0xFFF0
#define MC44S803_LO1_S 4
/* REG_LO2 */
#define MC44S803_LO2 0x7FFF0
#define MC44S803_LO2_S 4
/* REG_CIRCADJ */
#define MC44S803_G1 0x20
#define MC44S803_G1_S 5
#define MC44S803_G3 0x80
#define MC44S803_G3_S 7
#define MC44S803_CIRCADJ_RES 0x300
#define MC44S803_CIRCADJ_RES_S 8
#define MC44S803_G6 0x400
#define MC44S803_G6_S 10
#define MC44S803_G7 0x800
#define MC44S803_G7_S 11
#define MC44S803_S1 0x1000
#define MC44S803_S1_S 12
#define MC44S803_LP 0x7E000
#define MC44S803_LP_S 13
#define MC44S803_CLRF 0x80000
#define MC44S803_CLRF_S 19
#define MC44S803_CLIF 0x100000
#define MC44S803_CLIF_S 20
/* REG_TEST */
/* REG_DIGTUNE */
#define MC44S803_DA 0xF0
#define MC44S803_DA_S 4
#define MC44S803_XOD 0x300
#define MC44S803_XOD_S 8
#define MC44S803_RST 0x10000
#define MC44S803_RST_S 16
#define MC44S803_LO_REF 0x1FFF00
#define MC44S803_LO_REF_S 8
#define MC44S803_AT 0x200000
#define MC44S803_AT_S 21
#define MC44S803_MT 0x400000
#define MC44S803_MT_S 22
/* REG_LNAAGC */
#define MC44S803_G 0x3F0
#define MC44S803_G_S 4
#define MC44S803_AT1 0x400
#define MC44S803_AT1_S 10
#define MC44S803_AT2 0x800
#define MC44S803_AT2_S 11
#define MC44S803_HL_GR_EN 0x8000
#define MC44S803_HL_GR_EN_S 15
#define MC44S803_AGC_AN_DIG 0x10000
#define MC44S803_AGC_AN_DIG_S 16
#define MC44S803_ATTEN_EN 0x20000
#define MC44S803_ATTEN_EN_S 17
#define MC44S803_AGC_READ_EN 0x40000
#define MC44S803_AGC_READ_EN_S 18
#define MC44S803_LNA0 0x80000
#define MC44S803_LNA0_S 19
#define MC44S803_AGC_SEL 0x100000
#define MC44S803_AGC_SEL_S 20
#define MC44S803_AT0 0x200000
#define MC44S803_AT0_S 21
#define MC44S803_B 0xC00000
#define MC44S803_B_S 22
/* REG_DATAREG */
#define MC44S803_D 0xF0
#define MC44S803_D_S 4
/* REG_REGTEST */
/* REG_VCOTEST */
/* REG_LNAGAIN */
#define MC44S803_IF_PWR 0x700
#define MC44S803_IF_PWR_S 8
#define MC44S803_RF_PWR 0x3800
#define MC44S803_RF_PWR_S 11
#define MC44S803_LNA_GAIN 0xFC000
#define MC44S803_LNA_GAIN_S 14
/* REG_ID */
#define MC44S803_ID 0x3E00
#define MC44S803_ID_S 9
/* Some macros to read/write fields */
/* First shift, then mask */
#define MC44S803_REG_SM(_val, _reg) \
(((_val) << _reg##_S) & (_reg))
/* First mask, then shift */
#define MC44S803_REG_MS(_val, _reg) \
(((_val) & (_reg)) >> _reg##_S)
struct mc44s803_priv {
struct mc44s803_config *cfg;
struct i2c_adapter *i2c;
struct dvb_frontend *fe;
u32 frequency;
};
#endif

View File

@@ -278,7 +278,7 @@ static void mt2060_calibrate(struct mt2060_priv *priv)
while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0) while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
msleep(20); msleep(20);
if (i < 10) { if (i <= 10) {
mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :) mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :)
dprintk("calibration was successful: %d", (int)priv->fmfreq); dprintk("calibration was successful: %d", (int)priv->fmfreq);
} else } else

View File

@@ -6,7 +6,7 @@
*/ */
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev.h> #include <linux/videodev2.h>
#include "tuner-i2c.h" #include "tuner-i2c.h"
#include "mt20xx.h" #include "mt20xx.h"

View File

@@ -4003,12 +4003,11 @@ static int mxl5005s_set_params(struct dvb_frontend *fe,
/* Change tuner for new modulation type if reqd */ /* Change tuner for new modulation type if reqd */
if (req_mode != state->current_mode) { if (req_mode != state->current_mode) {
switch (req_mode) { switch (req_mode) {
case VSB_8: case MXL_ATSC:
case QAM_64: case MXL_QAM:
case QAM_256:
case QAM_AUTO:
req_bw = MXL5005S_BANDWIDTH_6MHZ; req_bw = MXL5005S_BANDWIDTH_6MHZ;
break; break;
case MXL_DVBT:
default: default:
/* Assume DVB-T */ /* Assume DVB-T */
switch (params->u.ofdm.bandwidth) { switch (params->u.ofdm.bandwidth) {

View File

@@ -1,7 +1,7 @@
/* /*
* mxl5007t.c - driver for the MaxLinear MxL5007T silicon tuner * mxl5007t.c - driver for the MaxLinear MxL5007T silicon tuner
* *
* Copyright (C) 2008 Michael Krufky <mkrufky@linuxtv.org> * Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -66,22 +66,17 @@ MODULE_PARM_DESC(debug, "set debug level");
#define MHz 1000000 #define MHz 1000000
enum mxl5007t_mode { enum mxl5007t_mode {
MxL_MODE_OTA_DVBT_ATSC = 0, MxL_MODE_ISDBT = 0,
MxL_MODE_OTA_NTSC_PAL_GH = 1, MxL_MODE_DVBT = 1,
MxL_MODE_OTA_PAL_IB = 2, MxL_MODE_ATSC = 2,
MxL_MODE_OTA_PAL_D_SECAM_KL = 3, MxL_MODE_CABLE = 0x10,
MxL_MODE_OTA_ISDBT = 4,
MxL_MODE_CABLE_DIGITAL = 0x10,
MxL_MODE_CABLE_NTSC_PAL_GH = 0x11,
MxL_MODE_CABLE_PAL_IB = 0x12,
MxL_MODE_CABLE_PAL_D_SECAM_KL = 0x13,
MxL_MODE_CABLE_SCTE40 = 0x14,
}; };
enum mxl5007t_chip_version { enum mxl5007t_chip_version {
MxL_UNKNOWN_ID = 0x00, MxL_UNKNOWN_ID = 0x00,
MxL_5007_V1_F1 = 0x11, MxL_5007_V1_F1 = 0x11,
MxL_5007_V1_F2 = 0x12, MxL_5007_V1_F2 = 0x12,
MxL_5007_V4 = 0x14,
MxL_5007_V2_100_F1 = 0x21, MxL_5007_V2_100_F1 = 0x21,
MxL_5007_V2_100_F2 = 0x22, MxL_5007_V2_100_F2 = 0x22,
MxL_5007_V2_200_F1 = 0x23, MxL_5007_V2_200_F1 = 0x23,
@@ -96,67 +91,61 @@ struct reg_pair_t {
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static struct reg_pair_t init_tab[] = { static struct reg_pair_t init_tab[] = {
{ 0x0b, 0x44 }, /* XTAL */ { 0x02, 0x06 },
{ 0x0c, 0x60 }, /* IF */ { 0x03, 0x48 },
{ 0x10, 0x00 }, /* MISC */ { 0x05, 0x04 },
{ 0x12, 0xca }, /* IDAC */ { 0x06, 0x10 },
{ 0x16, 0x90 }, /* MODE */ { 0x2e, 0x15 }, /* OVERRIDE */
{ 0x32, 0x38 }, /* MODE Analog/Digital */ { 0x30, 0x10 }, /* OVERRIDE */
{ 0xd8, 0x18 }, /* CLK_OUT_ENABLE */ { 0x45, 0x58 }, /* OVERRIDE */
{ 0x2c, 0x34 }, /* OVERRIDE */ { 0x48, 0x19 }, /* OVERRIDE */
{ 0x4d, 0x40 }, /* OVERRIDE */ { 0x52, 0x03 }, /* OVERRIDE */
{ 0x7f, 0x02 }, /* OVERRIDE */ { 0x53, 0x44 }, /* OVERRIDE */
{ 0x9a, 0x52 }, /* OVERRIDE */ { 0x6a, 0x4b }, /* OVERRIDE */
{ 0x48, 0x5a }, /* OVERRIDE */ { 0x76, 0x00 }, /* OVERRIDE */
{ 0x76, 0x1a }, /* OVERRIDE */ { 0x78, 0x18 }, /* OVERRIDE */
{ 0x6a, 0x48 }, /* OVERRIDE */ { 0x7a, 0x17 }, /* OVERRIDE */
{ 0x64, 0x28 }, /* OVERRIDE */ { 0x85, 0x06 }, /* OVERRIDE */
{ 0x66, 0xe6 }, /* OVERRIDE */ { 0x01, 0x01 }, /* TOP_MASTER_ENABLE */
{ 0x35, 0x0e }, /* OVERRIDE */
{ 0x7e, 0x01 }, /* OVERRIDE */
{ 0x83, 0x00 }, /* OVERRIDE */
{ 0x04, 0x0b }, /* OVERRIDE */
{ 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
{ 0, 0 } { 0, 0 }
}; };
static struct reg_pair_t init_tab_cable[] = { static struct reg_pair_t init_tab_cable[] = {
{ 0x0b, 0x44 }, /* XTAL */ { 0x02, 0x06 },
{ 0x0c, 0x60 }, /* IF */ { 0x03, 0x48 },
{ 0x10, 0x00 }, /* MISC */ { 0x05, 0x04 },
{ 0x12, 0xca }, /* IDAC */ { 0x06, 0x10 },
{ 0x16, 0x90 }, /* MODE */ { 0x09, 0x3f },
{ 0x32, 0x38 }, /* MODE A/D */ { 0x0a, 0x3f },
{ 0x71, 0x3f }, /* TOP1 */ { 0x0b, 0x3f },
{ 0x72, 0x3f }, /* TOP2 */ { 0x2e, 0x15 }, /* OVERRIDE */
{ 0x74, 0x3f }, /* TOP3 */ { 0x30, 0x10 }, /* OVERRIDE */
{ 0xd8, 0x18 }, /* CLK_OUT_ENABLE */ { 0x45, 0x58 }, /* OVERRIDE */
{ 0x2c, 0x34 }, /* OVERRIDE */ { 0x48, 0x19 }, /* OVERRIDE */
{ 0x4d, 0x40 }, /* OVERRIDE */ { 0x52, 0x03 }, /* OVERRIDE */
{ 0x7f, 0x02 }, /* OVERRIDE */ { 0x53, 0x44 }, /* OVERRIDE */
{ 0x9a, 0x52 }, /* OVERRIDE */ { 0x6a, 0x4b }, /* OVERRIDE */
{ 0x48, 0x5a }, /* OVERRIDE */ { 0x76, 0x00 }, /* OVERRIDE */
{ 0x76, 0x1a }, /* OVERRIDE */ { 0x78, 0x18 }, /* OVERRIDE */
{ 0x6a, 0x48 }, /* OVERRIDE */ { 0x7a, 0x17 }, /* OVERRIDE */
{ 0x64, 0x28 }, /* OVERRIDE */ { 0x85, 0x06 }, /* OVERRIDE */
{ 0x66, 0xe6 }, /* OVERRIDE */ { 0x01, 0x01 }, /* TOP_MASTER_ENABLE */
{ 0x35, 0x0e }, /* OVERRIDE */
{ 0x7e, 0x01 }, /* OVERRIDE */
{ 0x04, 0x0b }, /* OVERRIDE */
{ 0x68, 0xb4 }, /* OVERRIDE */
{ 0x36, 0x00 }, /* OVERRIDE */
{ 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
{ 0, 0 } { 0, 0 }
}; };
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static struct reg_pair_t reg_pair_rftune[] = { static struct reg_pair_t reg_pair_rftune[] = {
{ 0x11, 0x00 }, /* abort tune */ { 0x0f, 0x00 }, /* abort tune */
{ 0x13, 0x15 }, { 0x0c, 0x15 },
{ 0x14, 0x40 }, { 0x0d, 0x40 },
{ 0x15, 0x0e }, { 0x0e, 0x0e },
{ 0x11, 0x02 }, /* start tune */ { 0x1f, 0x87 }, /* OVERRIDE */
{ 0x20, 0x1f }, /* OVERRIDE */
{ 0x21, 0x87 }, /* OVERRIDE */
{ 0x22, 0x1f }, /* OVERRIDE */
{ 0x80, 0x01 }, /* freq dependent */
{ 0x0f, 0x01 }, /* start tune */
{ 0, 0 } { 0, 0 }
}; };
@@ -227,63 +216,20 @@ static void mxl5007t_set_mode_bits(struct mxl5007t_state *state,
s32 if_diff_out_level) s32 if_diff_out_level)
{ {
switch (mode) { switch (mode) {
case MxL_MODE_OTA_DVBT_ATSC: case MxL_MODE_ATSC:
set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06); set_reg_bits(state->tab_init, 0x06, 0x1f, 0x12);
set_reg_bits(state->tab_init, 0x35, 0xff, 0x0e);
break; break;
case MxL_MODE_OTA_ISDBT: case MxL_MODE_DVBT:
set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06); set_reg_bits(state->tab_init, 0x06, 0x1f, 0x11);
set_reg_bits(state->tab_init, 0x35, 0xff, 0x12);
break; break;
case MxL_MODE_OTA_NTSC_PAL_GH: case MxL_MODE_ISDBT:
set_reg_bits(state->tab_init, 0x16, 0x70, 0x00); set_reg_bits(state->tab_init, 0x06, 0x1f, 0x10);
set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
break; break;
case MxL_MODE_OTA_PAL_IB: case MxL_MODE_CABLE:
set_reg_bits(state->tab_init, 0x16, 0x70, 0x10); set_reg_bits(state->tab_init_cable, 0x09, 0xff, 0xc1);
set_reg_bits(state->tab_init, 0x32, 0xff, 0x85); set_reg_bits(state->tab_init_cable, 0x0a, 0xff,
break;
case MxL_MODE_OTA_PAL_D_SECAM_KL:
set_reg_bits(state->tab_init, 0x16, 0x70, 0x20);
set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
break;
case MxL_MODE_CABLE_DIGITAL:
set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
set_reg_bits(state->tab_init_cable, 0x72, 0xff,
8 - if_diff_out_level); 8 - if_diff_out_level);
set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17); set_reg_bits(state->tab_init_cable, 0x0b, 0xff, 0x17);
break;
case MxL_MODE_CABLE_NTSC_PAL_GH:
set_reg_bits(state->tab_init, 0x16, 0x70, 0x00);
set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
set_reg_bits(state->tab_init_cable, 0x72, 0xff,
8 - if_diff_out_level);
set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
break;
case MxL_MODE_CABLE_PAL_IB:
set_reg_bits(state->tab_init, 0x16, 0x70, 0x10);
set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
set_reg_bits(state->tab_init_cable, 0x72, 0xff,
8 - if_diff_out_level);
set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
break;
case MxL_MODE_CABLE_PAL_D_SECAM_KL:
set_reg_bits(state->tab_init, 0x16, 0x70, 0x20);
set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
set_reg_bits(state->tab_init_cable, 0x72, 0xff,
8 - if_diff_out_level);
set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
break;
case MxL_MODE_CABLE_SCTE40:
set_reg_bits(state->tab_init_cable, 0x36, 0xff, 0x08);
set_reg_bits(state->tab_init_cable, 0x68, 0xff, 0xbc);
set_reg_bits(state->tab_init_cable, 0x71, 0xff, 0x01);
set_reg_bits(state->tab_init_cable, 0x72, 0xff,
8 - if_diff_out_level);
set_reg_bits(state->tab_init_cable, 0x74, 0xff, 0x17);
break; break;
default: default:
mxl_fail(-EINVAL); mxl_fail(-EINVAL);
@@ -302,43 +248,43 @@ static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,
val = 0x00; val = 0x00;
break; break;
case MxL_IF_4_5_MHZ: case MxL_IF_4_5_MHZ:
val = 0x20; val = 0x02;
break; break;
case MxL_IF_4_57_MHZ: case MxL_IF_4_57_MHZ:
val = 0x30; val = 0x03;
break; break;
case MxL_IF_5_MHZ: case MxL_IF_5_MHZ:
val = 0x40; val = 0x04;
break; break;
case MxL_IF_5_38_MHZ: case MxL_IF_5_38_MHZ:
val = 0x50; val = 0x05;
break; break;
case MxL_IF_6_MHZ: case MxL_IF_6_MHZ:
val = 0x60; val = 0x06;
break; break;
case MxL_IF_6_28_MHZ: case MxL_IF_6_28_MHZ:
val = 0x70; val = 0x07;
break; break;
case MxL_IF_9_1915_MHZ: case MxL_IF_9_1915_MHZ:
val = 0x80; val = 0x08;
break; break;
case MxL_IF_35_25_MHZ: case MxL_IF_35_25_MHZ:
val = 0x90; val = 0x09;
break; break;
case MxL_IF_36_15_MHZ: case MxL_IF_36_15_MHZ:
val = 0xa0; val = 0x0a;
break; break;
case MxL_IF_44_MHZ: case MxL_IF_44_MHZ:
val = 0xb0; val = 0x0b;
break; break;
default: default:
mxl_fail(-EINVAL); mxl_fail(-EINVAL);
return; return;
} }
set_reg_bits(state->tab_init, 0x0c, 0xf0, val); set_reg_bits(state->tab_init, 0x02, 0x0f, val);
/* set inverted IF or normal IF */ /* set inverted IF or normal IF */
set_reg_bits(state->tab_init, 0x0c, 0x08, invert_if ? 0x08 : 0x00); set_reg_bits(state->tab_init, 0x02, 0x10, invert_if ? 0x10 : 0x00);
return; return;
} }
@@ -346,56 +292,68 @@ static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,
static void mxl5007t_set_xtal_freq_bits(struct mxl5007t_state *state, static void mxl5007t_set_xtal_freq_bits(struct mxl5007t_state *state,
enum mxl5007t_xtal_freq xtal_freq) enum mxl5007t_xtal_freq xtal_freq)
{ {
u8 val;
switch (xtal_freq) { switch (xtal_freq) {
case MxL_XTAL_16_MHZ: case MxL_XTAL_16_MHZ:
val = 0x00; /* select xtal freq & Ref Freq */ /* select xtal freq & ref freq */
set_reg_bits(state->tab_init, 0x03, 0xf0, 0x00);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x00);
break; break;
case MxL_XTAL_20_MHZ: case MxL_XTAL_20_MHZ:
val = 0x11; set_reg_bits(state->tab_init, 0x03, 0xf0, 0x10);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x01);
break; break;
case MxL_XTAL_20_25_MHZ: case MxL_XTAL_20_25_MHZ:
val = 0x22; set_reg_bits(state->tab_init, 0x03, 0xf0, 0x20);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x02);
break; break;
case MxL_XTAL_20_48_MHZ: case MxL_XTAL_20_48_MHZ:
val = 0x33; set_reg_bits(state->tab_init, 0x03, 0xf0, 0x30);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x03);
break; break;
case MxL_XTAL_24_MHZ: case MxL_XTAL_24_MHZ:
val = 0x44; set_reg_bits(state->tab_init, 0x03, 0xf0, 0x40);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x04);
break; break;
case MxL_XTAL_25_MHZ: case MxL_XTAL_25_MHZ:
val = 0x55; set_reg_bits(state->tab_init, 0x03, 0xf0, 0x50);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x05);
break; break;
case MxL_XTAL_25_14_MHZ: case MxL_XTAL_25_14_MHZ:
val = 0x66; set_reg_bits(state->tab_init, 0x03, 0xf0, 0x60);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x06);
break; break;
case MxL_XTAL_27_MHZ: case MxL_XTAL_27_MHZ:
val = 0x77; set_reg_bits(state->tab_init, 0x03, 0xf0, 0x70);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x07);
break; break;
case MxL_XTAL_28_8_MHZ: case MxL_XTAL_28_8_MHZ:
val = 0x88; set_reg_bits(state->tab_init, 0x03, 0xf0, 0x80);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x08);
break; break;
case MxL_XTAL_32_MHZ: case MxL_XTAL_32_MHZ:
val = 0x99; set_reg_bits(state->tab_init, 0x03, 0xf0, 0x90);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x09);
break; break;
case MxL_XTAL_40_MHZ: case MxL_XTAL_40_MHZ:
val = 0xaa; set_reg_bits(state->tab_init, 0x03, 0xf0, 0xa0);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0a);
break; break;
case MxL_XTAL_44_MHZ: case MxL_XTAL_44_MHZ:
val = 0xbb; set_reg_bits(state->tab_init, 0x03, 0xf0, 0xb0);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0b);
break; break;
case MxL_XTAL_48_MHZ: case MxL_XTAL_48_MHZ:
val = 0xcc; set_reg_bits(state->tab_init, 0x03, 0xf0, 0xc0);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0c);
break; break;
case MxL_XTAL_49_3811_MHZ: case MxL_XTAL_49_3811_MHZ:
val = 0xdd; set_reg_bits(state->tab_init, 0x03, 0xf0, 0xd0);
set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0d);
break; break;
default: default:
mxl_fail(-EINVAL); mxl_fail(-EINVAL);
return; return;
} }
set_reg_bits(state->tab_init, 0x0b, 0xff, val);
return; return;
} }
@@ -412,16 +370,11 @@ static struct reg_pair_t *mxl5007t_calc_init_regs(struct mxl5007t_state *state,
mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if); mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if);
mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz); mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz);
set_reg_bits(state->tab_init, 0x10, 0x40, cfg->loop_thru_enable << 6); set_reg_bits(state->tab_init, 0x04, 0x01, cfg->loop_thru_enable);
set_reg_bits(state->tab_init, 0x03, 0x08, cfg->clk_out_enable << 3);
set_reg_bits(state->tab_init, 0x03, 0x07, cfg->clk_out_amp);
set_reg_bits(state->tab_init, 0xd8, 0x08, cfg->clk_out_enable << 3); if (mode >= MxL_MODE_CABLE) {
set_reg_bits(state->tab_init, 0x10, 0x07, cfg->clk_out_amp);
/* set IDAC to automatic mode control by AGC */
set_reg_bits(state->tab_init, 0x12, 0x80, 0x00);
if (mode >= MxL_MODE_CABLE_DIGITAL) {
copy_reg_bits(state->tab_init, state->tab_init_cable); copy_reg_bits(state->tab_init, state->tab_init_cable);
return state->tab_init_cable; return state->tab_init_cable;
} else } else
@@ -447,7 +400,7 @@ static void mxl5007t_set_bw_bits(struct mxl5007t_state *state,
* and DIG_MODEINDEX_CSF */ * and DIG_MODEINDEX_CSF */
break; break;
case MxL_BW_7MHz: case MxL_BW_7MHz:
val = 0x21; val = 0x2a;
break; break;
case MxL_BW_8MHz: case MxL_BW_8MHz:
val = 0x3f; val = 0x3f;
@@ -456,7 +409,7 @@ static void mxl5007t_set_bw_bits(struct mxl5007t_state *state,
mxl_fail(-EINVAL); mxl_fail(-EINVAL);
return; return;
} }
set_reg_bits(state->tab_rftune, 0x13, 0x3f, val); set_reg_bits(state->tab_rftune, 0x0c, 0x3f, val);
return; return;
} }
@@ -493,8 +446,11 @@ reg_pair_t *mxl5007t_calc_rf_tune_regs(struct mxl5007t_state *state,
if (temp > 7812) if (temp > 7812)
dig_rf_freq++; dig_rf_freq++;
set_reg_bits(state->tab_rftune, 0x14, 0xff, (u8)dig_rf_freq); set_reg_bits(state->tab_rftune, 0x0d, 0xff, (u8) dig_rf_freq);
set_reg_bits(state->tab_rftune, 0x15, 0xff, (u8)(dig_rf_freq >> 8)); set_reg_bits(state->tab_rftune, 0x0e, 0xff, (u8) (dig_rf_freq >> 8));
if (rf_freq >= 333000000)
set_reg_bits(state->tab_rftune, 0x80, 0x40, 0x40);
return state->tab_rftune; return state->tab_rftune;
} }
@@ -551,9 +507,10 @@ static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val)
static int mxl5007t_soft_reset(struct mxl5007t_state *state) static int mxl5007t_soft_reset(struct mxl5007t_state *state)
{ {
u8 d = 0xff; u8 d = 0xff;
struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0, struct i2c_msg msg = {
.buf = &d, .len = 1 }; .addr = state->i2c_props.addr, .flags = 0,
.buf = &d, .len = 1
};
int ret = i2c_transfer(state->i2c_props.adap, &msg, 1); int ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
if (ret != 1) { if (ret != 1) {
@@ -580,9 +537,6 @@ static int mxl5007t_tuner_init(struct mxl5007t_state *state,
if (mxl_fail(ret)) if (mxl_fail(ret))
goto fail; goto fail;
mdelay(1); mdelay(1);
ret = mxl5007t_write_reg(state, 0x2c, 0x35);
mxl_fail(ret);
fail: fail:
return ret; return ret;
} }
@@ -615,7 +569,7 @@ static int mxl5007t_synth_lock_status(struct mxl5007t_state *state,
*rf_locked = 0; *rf_locked = 0;
*ref_locked = 0; *ref_locked = 0;
ret = mxl5007t_read_reg(state, 0xcf, &d); ret = mxl5007t_read_reg(state, 0xd8, &d);
if (mxl_fail(ret)) if (mxl_fail(ret))
goto fail; goto fail;
@@ -628,37 +582,14 @@ fail:
return ret; return ret;
} }
static int mxl5007t_check_rf_input_power(struct mxl5007t_state *state,
s32 *rf_input_level)
{
u8 d1, d2;
int ret;
ret = mxl5007t_read_reg(state, 0xb7, &d1);
if (mxl_fail(ret))
goto fail;
ret = mxl5007t_read_reg(state, 0xbf, &d2);
if (mxl_fail(ret))
goto fail;
d2 = d2 >> 4;
if (d2 > 7)
d2 += 0xf0;
*rf_input_level = (s32)(d1 + d2 - 113);
fail:
return ret;
}
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status) static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status)
{ {
struct mxl5007t_state *state = fe->tuner_priv; struct mxl5007t_state *state = fe->tuner_priv;
int rf_locked, ref_locked; int rf_locked, ref_locked, ret;
s32 rf_input_level = 0;
int ret; *status = 0;
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.i2c_gate_ctrl(fe, 1);
@@ -669,10 +600,8 @@ static int mxl5007t_get_status(struct dvb_frontend *fe, u32 *status)
mxl_debug("%s%s", rf_locked ? "rf locked " : "", mxl_debug("%s%s", rf_locked ? "rf locked " : "",
ref_locked ? "ref locked" : ""); ref_locked ? "ref locked" : "");
ret = mxl5007t_check_rf_input_power(state, &rf_input_level); if ((rf_locked) || (ref_locked))
if (mxl_fail(ret)) *status |= TUNER_STATUS_LOCKED;
goto fail;
mxl_debug("rf input power: %d", rf_input_level);
fail: fail:
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); fe->ops.i2c_gate_ctrl(fe, 0);
@@ -695,11 +624,11 @@ static int mxl5007t_set_params(struct dvb_frontend *fe,
switch (params->u.vsb.modulation) { switch (params->u.vsb.modulation) {
case VSB_8: case VSB_8:
case VSB_16: case VSB_16:
mode = MxL_MODE_OTA_DVBT_ATSC; mode = MxL_MODE_ATSC;
break; break;
case QAM_64: case QAM_64:
case QAM_256: case QAM_256:
mode = MxL_MODE_CABLE_DIGITAL; mode = MxL_MODE_CABLE;
break; break;
default: default:
mxl_err("modulation not set!"); mxl_err("modulation not set!");
@@ -721,7 +650,7 @@ static int mxl5007t_set_params(struct dvb_frontend *fe,
mxl_err("bandwidth not set!"); mxl_err("bandwidth not set!");
return -EINVAL; return -EINVAL;
} }
mode = MxL_MODE_OTA_DVBT_ATSC; mode = MxL_MODE_DVBT;
} else { } else {
mxl_err("modulation type not supported!"); mxl_err("modulation type not supported!");
return -EINVAL; return -EINVAL;
@@ -752,96 +681,20 @@ fail:
return ret; return ret;
} }
static int mxl5007t_set_analog_params(struct dvb_frontend *fe,
struct analog_parameters *params)
{
struct mxl5007t_state *state = fe->tuner_priv;
enum mxl5007t_bw_mhz bw = 0; /* FIXME */
enum mxl5007t_mode cbl_mode;
enum mxl5007t_mode ota_mode;
char *mode_name;
int ret;
u32 freq = params->frequency * 62500;
#define cable 1
if (params->std & V4L2_STD_MN) {
cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
mode_name = "MN";
} else if (params->std & V4L2_STD_B) {
cbl_mode = MxL_MODE_CABLE_PAL_IB;
ota_mode = MxL_MODE_OTA_PAL_IB;
mode_name = "B";
} else if (params->std & V4L2_STD_GH) {
cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
mode_name = "GH";
} else if (params->std & V4L2_STD_PAL_I) {
cbl_mode = MxL_MODE_CABLE_PAL_IB;
ota_mode = MxL_MODE_OTA_PAL_IB;
mode_name = "I";
} else if (params->std & V4L2_STD_DK) {
cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
mode_name = "DK";
} else if (params->std & V4L2_STD_SECAM_L) {
cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
mode_name = "L";
} else if (params->std & V4L2_STD_SECAM_LC) {
cbl_mode = MxL_MODE_CABLE_PAL_D_SECAM_KL;
ota_mode = MxL_MODE_OTA_PAL_D_SECAM_KL;
mode_name = "L'";
} else {
mode_name = "xx";
/* FIXME */
cbl_mode = MxL_MODE_CABLE_NTSC_PAL_GH;
ota_mode = MxL_MODE_OTA_NTSC_PAL_GH;
}
mxl_debug("setting mxl5007 to system %s", mode_name);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
mutex_lock(&state->lock);
ret = mxl5007t_tuner_init(state, cable ? cbl_mode : ota_mode);
if (mxl_fail(ret))
goto fail;
ret = mxl5007t_tuner_rf_tune(state, freq, bw);
if (mxl_fail(ret))
goto fail;
state->frequency = freq;
state->bandwidth = 0;
fail:
mutex_unlock(&state->lock);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
return ret;
}
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static int mxl5007t_init(struct dvb_frontend *fe) static int mxl5007t_init(struct dvb_frontend *fe)
{ {
struct mxl5007t_state *state = fe->tuner_priv; struct mxl5007t_state *state = fe->tuner_priv;
int ret; int ret;
u8 d;
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.i2c_gate_ctrl(fe, 1);
ret = mxl5007t_read_reg(state, 0x05, &d); /* wake from standby */
if (mxl_fail(ret)) ret = mxl5007t_write_reg(state, 0x01, 0x01);
goto fail;
ret = mxl5007t_write_reg(state, 0x05, d | 0x01);
mxl_fail(ret); mxl_fail(ret);
fail:
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); fe->ops.i2c_gate_ctrl(fe, 0);
@@ -852,18 +705,16 @@ static int mxl5007t_sleep(struct dvb_frontend *fe)
{ {
struct mxl5007t_state *state = fe->tuner_priv; struct mxl5007t_state *state = fe->tuner_priv;
int ret; int ret;
u8 d;
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.i2c_gate_ctrl(fe, 1);
ret = mxl5007t_read_reg(state, 0x05, &d); /* enter standby mode */
if (mxl_fail(ret)) ret = mxl5007t_write_reg(state, 0x01, 0x00);
goto fail;
ret = mxl5007t_write_reg(state, 0x05, d & ~0x01);
mxl_fail(ret); mxl_fail(ret);
fail: ret = mxl5007t_write_reg(state, 0x0f, 0x00);
mxl_fail(ret);
if (fe->ops.i2c_gate_ctrl) if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0); fe->ops.i2c_gate_ctrl(fe, 0);
@@ -911,7 +762,6 @@ static struct dvb_tuner_ops mxl5007t_tuner_ops = {
.init = mxl5007t_init, .init = mxl5007t_init,
.sleep = mxl5007t_sleep, .sleep = mxl5007t_sleep,
.set_params = mxl5007t_set_params, .set_params = mxl5007t_set_params,
.set_analog_params = mxl5007t_set_analog_params,
.get_status = mxl5007t_get_status, .get_status = mxl5007t_get_status,
.get_frequency = mxl5007t_get_frequency, .get_frequency = mxl5007t_get_frequency,
.get_bandwidth = mxl5007t_get_bandwidth, .get_bandwidth = mxl5007t_get_bandwidth,
@@ -924,7 +774,7 @@ static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
int ret; int ret;
u8 id; u8 id;
ret = mxl5007t_read_reg(state, 0xd3, &id); ret = mxl5007t_read_reg(state, 0xd9, &id);
if (mxl_fail(ret)) if (mxl_fail(ret))
goto fail; goto fail;
@@ -947,8 +797,12 @@ static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
case MxL_5007_V2_200_F2: case MxL_5007_V2_200_F2:
name = "MxL5007.v2.200.f2"; name = "MxL5007.v2.200.f2";
break; break;
case MxL_5007_V4:
name = "MxL5007T.v4";
break;
default: default:
name = "MxL5007T"; name = "MxL5007T";
printk(KERN_WARNING "%s: unknown rev (%02x)\n", __func__, id);
id = MxL_UNKNOWN_ID; id = MxL_UNKNOWN_ID;
} }
state->chip_id = id; state->chip_id = id;
@@ -975,7 +829,7 @@ struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
mutex_lock(&mxl5007t_list_mutex); mutex_lock(&mxl5007t_list_mutex);
instance = hybrid_tuner_request_state(struct mxl5007t_state, state, instance = hybrid_tuner_request_state(struct mxl5007t_state, state,
hybrid_tuner_instance_list, hybrid_tuner_instance_list,
i2c, addr, "mxl5007"); i2c, addr, "mxl5007t");
switch (instance) { switch (instance) {
case 0: case 0:
goto fail; goto fail;
@@ -1018,7 +872,7 @@ EXPORT_SYMBOL_GPL(mxl5007t_attach);
MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver"); MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver");
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>"); MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION("0.1"); MODULE_VERSION("0.2");
/* /*
* Overrides for Emacs so that we follow Linus's tabbing style. * Overrides for Emacs so that we follow Linus's tabbing style.

View File

@@ -490,9 +490,9 @@ int tda18271_set_standby_mode(struct dvb_frontend *fe,
tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt); 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] &= ~0xe0; /* clear sm, sm_lt, sm_xt */
regs[R_EP3] |= sm ? (1 << 7) : 0 | regs[R_EP3] |= (sm ? (1 << 7) : 0) |
sm_lt ? (1 << 6) : 0 | (sm_lt ? (1 << 6) : 0) |
sm_xt ? (1 << 5) : 0; (sm_xt ? (1 << 5) : 0);
return tda18271_write_regs(fe, R_EP3, 1); return tda18271_write_regs(fe, R_EP3, 1);
} }

View File

@@ -818,6 +818,38 @@ fail:
return ret; return ret;
} }
/* ------------------------------------------------------------------ */
static int tda18271_agc(struct dvb_frontend *fe)
{
struct tda18271_priv *priv = fe->tuner_priv;
int ret = 0;
switch (priv->config) {
case 0:
/* no LNA */
tda_dbg("no agc configuration provided\n");
break;
case 3:
/* switch with GPIO of saa713x */
tda_dbg("invoking callback\n");
if (fe->callback)
ret = fe->callback(priv->i2c_props.adap->algo_data,
DVB_FRONTEND_COMPONENT_TUNER,
TDA18271_CALLBACK_CMD_AGC_ENABLE,
priv->mode);
break;
case 1:
case 2:
default:
/* n/a - currently not supported */
tda_err("unsupported configuration: %d\n", priv->config);
ret = -EINVAL;
break;
}
return ret;
}
static int tda18271_tune(struct dvb_frontend *fe, static int tda18271_tune(struct dvb_frontend *fe,
struct tda18271_std_map_item *map, u32 freq, u32 bw) struct tda18271_std_map_item *map, u32 freq, u32 bw)
{ {
@@ -827,6 +859,10 @@ static int tda18271_tune(struct dvb_frontend *fe,
tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n", tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n",
freq, map->if_freq, bw, map->agc_mode, map->std); freq, map->if_freq, bw, map->agc_mode, map->std);
ret = tda18271_agc(fe);
if (tda_fail(ret))
tda_warn("failed to configure agc\n");
ret = tda18271_init(fe); ret = tda18271_init(fe);
if (tda_fail(ret)) if (tda_fail(ret))
goto fail; goto fail;
@@ -1159,6 +1195,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
/* new tuner instance */ /* new tuner instance */
priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
priv->role = (cfg) ? cfg->role : TDA18271_MASTER; priv->role = (cfg) ? cfg->role : TDA18271_MASTER;
priv->config = (cfg) ? cfg->config : 0;
priv->cal_initialized = false; priv->cal_initialized = false;
mutex_init(&priv->lock); mutex_init(&priv->lock);

View File

@@ -91,11 +91,6 @@ enum tda18271_pll {
TDA18271_CAL_PLL, TDA18271_CAL_PLL,
}; };
enum tda18271_mode {
TDA18271_ANALOG,
TDA18271_DIGITAL,
};
struct tda18271_map_layout; struct tda18271_map_layout;
enum tda18271_ver { enum tda18271_ver {
@@ -114,6 +109,7 @@ struct tda18271_priv {
enum tda18271_i2c_gate gate; enum tda18271_i2c_gate gate;
enum tda18271_ver id; enum tda18271_ver id;
unsigned int config; /* interface to saa713x / tda829x */
unsigned int tm_rfcal; unsigned int tm_rfcal;
unsigned int cal_initialized:1; unsigned int cal_initialized:1;
unsigned int small_i2c:1; unsigned int small_i2c:1;

View File

@@ -79,6 +79,16 @@ struct tda18271_config {
/* some i2c providers cant write all 39 registers at once */ /* some i2c providers cant write all 39 registers at once */
unsigned int small_i2c:1; unsigned int small_i2c:1;
/* interface to saa713x / tda829x */
unsigned int config;
};
#define TDA18271_CALLBACK_CMD_AGC_ENABLE 0
enum tda18271_mode {
TDA18271_ANALOG = 0,
TDA18271_DIGITAL,
}; };
#if defined(CONFIG_MEDIA_TUNER_TDA18271) || (defined(CONFIG_MEDIA_TUNER_TDA18271_MODULE) && defined(MODULE)) #if defined(CONFIG_MEDIA_TUNER_TDA18271) || (defined(CONFIG_MEDIA_TUNER_TDA18271_MODULE) && defined(MODULE))

View File

@@ -132,11 +132,31 @@ static const struct tda827x_data tda827x_table[] = {
{ .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0} { .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
}; };
static int tuner_transfer(struct dvb_frontend *fe,
struct i2c_msg *msg,
const int size)
{
int rc;
struct tda827x_priv *priv = fe->tuner_priv;
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
rc = i2c_transfer(priv->i2c_adap, msg, size);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
if (rc >= 0 && rc != size)
return -EIO;
return rc;
}
static int tda827xo_set_params(struct dvb_frontend *fe, static int tda827xo_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params) struct dvb_frontend_parameters *params)
{ {
struct tda827x_priv *priv = fe->tuner_priv; struct tda827x_priv *priv = fe->tuner_priv;
u8 buf[14]; u8 buf[14];
int rc;
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
.buf = buf, .len = sizeof(buf) }; .buf = buf, .len = sizeof(buf) };
@@ -183,27 +203,29 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
buf[13] = 0x40; buf[13] = 0x40;
msg.len = 14; msg.len = 14;
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { goto err;
printk("%s: could not write to tuner at addr: 0x%02x\n",
__func__, priv->i2c_addr << 1);
return -EIO;
}
msleep(500); msleep(500);
/* correct CP value */ /* correct CP value */
buf[0] = 0x30; buf[0] = 0x30;
buf[1] = 0x50 + tda827x_table[i].cp; buf[1] = 0x50 + tda827x_table[i].cp;
msg.len = 2; msg.len = 2;
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
i2c_transfer(priv->i2c_adap, &msg, 1); goto err;
priv->frequency = params->frequency; priv->frequency = params->frequency;
priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
return 0; return 0;
err:
printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
__func__, priv->i2c_addr << 1);
return rc;
} }
static int tda827xo_sleep(struct dvb_frontend *fe) static int tda827xo_sleep(struct dvb_frontend *fe)
@@ -214,9 +236,7 @@ static int tda827xo_sleep(struct dvb_frontend *fe)
.buf = buf, .len = sizeof(buf) }; .buf = buf, .len = sizeof(buf) };
dprintk("%s:\n", __func__); dprintk("%s:\n", __func__);
if (fe->ops.i2c_gate_ctrl) tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1);
i2c_transfer(priv->i2c_adap, &msg, 1);
if (priv->cfg && priv->cfg->sleep) if (priv->cfg && priv->cfg->sleep)
priv->cfg->sleep(fe); priv->cfg->sleep(fe);
@@ -266,44 +286,44 @@ static int tda827xo_set_analog_params(struct dvb_frontend *fe,
msg.buf = tuner_reg; msg.buf = tuner_reg;
msg.len = 8; msg.len = 8;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
msg.buf = reg2; msg.buf = reg2;
msg.len = 2; msg.len = 2;
reg2[0] = 0x80; reg2[0] = 0x80;
reg2[1] = 0; reg2[1] = 0;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
reg2[0] = 0x60; reg2[0] = 0x60;
reg2[1] = 0xbf; reg2[1] = 0xbf;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
reg2[0] = 0x30; reg2[0] = 0x30;
reg2[1] = tuner_reg[4] + 0x80; reg2[1] = tuner_reg[4] + 0x80;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
msleep(1); msleep(1);
reg2[0] = 0x30; reg2[0] = 0x30;
reg2[1] = tuner_reg[4] + 4; reg2[1] = tuner_reg[4] + 4;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
msleep(1); msleep(1);
reg2[0] = 0x30; reg2[0] = 0x30;
reg2[1] = tuner_reg[4]; reg2[1] = tuner_reg[4];
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
msleep(550); msleep(550);
reg2[0] = 0x30; reg2[0] = 0x30;
reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp; reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
reg2[0] = 0x60; reg2[0] = 0x60;
reg2[1] = 0x3f; reg2[1] = 0x3f;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
reg2[0] = 0x80; reg2[0] = 0x80;
reg2[1] = 0x08; /* Vsync en */ reg2[1] = 0x08; /* Vsync en */
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
priv->frequency = params->frequency; priv->frequency = params->frequency;
@@ -317,7 +337,7 @@ static void tda827xo_agcf(struct dvb_frontend *fe)
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
.buf = data, .len = 2}; .buf = data, .len = 2};
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
} }
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -331,7 +351,7 @@ struct tda827xa_data {
u8 gc3; u8 gc3;
}; };
static const struct tda827xa_data tda827xa_dvbt[] = { static struct tda827xa_data tda827xa_dvbt[] = {
{ .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1}, { .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 1},
{ .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, { .lomax = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
{ .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1}, { .lomax = 81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
@@ -361,6 +381,36 @@ static const struct tda827xa_data tda827xa_dvbt[] = {
{ .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0} { .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
}; };
static struct tda827xa_data tda827xa_dvbc[] = {
{ .lomax = 50125000, .svco = 2, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
{ .lomax = 58500000, .svco = 3, .spd = 4, .scr = 2, .sbs = 0, .gc3 = 3},
{ .lomax = 69250000, .svco = 0, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
{ .lomax = 83625000, .svco = 1, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
{ .lomax = 97500000, .svco = 2, .spd = 3, .scr = 2, .sbs = 0, .gc3 = 3},
{ .lomax = 100250000, .svco = 2, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
{ .lomax = 117000000, .svco = 3, .spd = 3, .scr = 2, .sbs = 1, .gc3 = 1},
{ .lomax = 138500000, .svco = 0, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
{ .lomax = 167250000, .svco = 1, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
{ .lomax = 187000000, .svco = 2, .spd = 2, .scr = 2, .sbs = 1, .gc3 = 1},
{ .lomax = 200500000, .svco = 2, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 1},
{ .lomax = 234000000, .svco = 3, .spd = 2, .scr = 2, .sbs = 2, .gc3 = 3},
{ .lomax = 277000000, .svco = 0, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 3},
{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 2, .sbs = 2, .gc3 = 1},
{ .lomax = 334500000, .svco = 1, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
{ .lomax = 401000000, .svco = 2, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 3},
{ .lomax = 468000000, .svco = 3, .spd = 1, .scr = 2, .sbs = 3, .gc3 = 1},
{ .lomax = 535000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
{ .lomax = 554000000, .svco = 0, .spd = 0, .scr = 2, .sbs = 3, .gc3 = 1},
{ .lomax = 638000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
{ .lomax = 669000000, .svco = 1, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
{ .lomax = 720000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
{ .lomax = 802000000, .svco = 2, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
{ .lomax = 835000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
{ .lomax = 885000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 1},
{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 1},
{ .lomax = 0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
};
static struct tda827xa_data tda827xa_analog[] = { static struct tda827xa_data tda827xa_analog[] = {
{ .lomax = 56875000, .svco = 3, .spd = 4, .scr = 0, .sbs = 0, .gc3 = 3}, { .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 = 67250000, .svco = 0, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
@@ -398,13 +448,8 @@ static int tda827xa_sleep(struct dvb_frontend *fe)
.buf = buf, .len = sizeof(buf) }; .buf = buf, .len = sizeof(buf) };
dprintk("%s:\n", __func__); dprintk("%s:\n", __func__);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
if (priv->cfg && priv->cfg->sleep) if (priv->cfg && priv->cfg->sleep)
priv->cfg->sleep(fe); priv->cfg->sleep(fe);
@@ -455,7 +500,7 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
buf[1] = high ? 0 : 1; buf[1] = high ? 0 : 1;
if (priv->cfg->config == 2) if (priv->cfg->config == 2)
buf[1] = high ? 1 : 0; buf[1] = high ? 1 : 0;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
break; break;
case 3: /* switch with GPIO of saa713x */ case 3: /* switch with GPIO of saa713x */
if (fe->callback) if (fe->callback)
@@ -469,12 +514,13 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *params) struct dvb_frontend_parameters *params)
{ {
struct tda827x_priv *priv = fe->tuner_priv; struct tda827x_priv *priv = fe->tuner_priv;
struct tda827xa_data *frequency_map = tda827xa_dvbt;
u8 buf[11]; u8 buf[11];
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0, struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
.buf = buf, .len = sizeof(buf) }; .buf = buf, .len = sizeof(buf) };
int i, tuner_freq, if_freq; int i, tuner_freq, if_freq, rc;
u32 N; u32 N;
dprintk("%s:\n", __func__); dprintk("%s:\n", __func__);
@@ -495,56 +541,58 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
} }
tuner_freq = params->frequency + if_freq; tuner_freq = params->frequency + if_freq;
if (fe->ops.info.type == FE_QAM) {
dprintk("%s select tda827xa_dvbc\n", __func__);
frequency_map = tda827xa_dvbc;
}
i = 0; i = 0;
while (tda827xa_dvbt[i].lomax < tuner_freq) { while (frequency_map[i].lomax < tuner_freq) {
if(tda827xa_dvbt[i + 1].lomax == 0) if (frequency_map[i + 1].lomax == 0)
break; break;
i++; i++;
} }
N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd; N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
buf[0] = 0; // subaddress buf[0] = 0; // subaddress
buf[1] = N >> 8; buf[1] = N >> 8;
buf[2] = N & 0xff; buf[2] = N & 0xff;
buf[3] = 0; buf[3] = 0;
buf[4] = 0x16; buf[4] = 0x16;
buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) + buf[5] = (frequency_map[i].spd << 5) + (frequency_map[i].svco << 3) +
tda827xa_dvbt[i].sbs; frequency_map[i].sbs;
buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4); buf[6] = 0x4b + (frequency_map[i].gc3 << 4);
buf[7] = 0x1c; buf[7] = 0x1c;
buf[8] = 0x06; buf[8] = 0x06;
buf[9] = 0x24; buf[9] = 0x24;
buf[10] = 0x00; buf[10] = 0x00;
msg.len = 11; msg.len = 11;
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) { goto err;
printk("%s: could not write to tuner at addr: 0x%02x\n",
__func__, priv->i2c_addr << 1);
return -EIO;
}
buf[0] = 0x90; buf[0] = 0x90;
buf[1] = 0xff; buf[1] = 0xff;
buf[2] = 0x60; buf[2] = 0x60;
buf[3] = 0x00; buf[3] = 0x00;
buf[4] = 0x59; // lpsel, for 6MHz + 2 buf[4] = 0x59; // lpsel, for 6MHz + 2
msg.len = 5; msg.len = 5;
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
i2c_transfer(priv->i2c_adap, &msg, 1); goto err;
buf[0] = 0xa0; buf[0] = 0xa0;
buf[1] = 0x40; buf[1] = 0x40;
msg.len = 2; msg.len = 2;
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
i2c_transfer(priv->i2c_adap, &msg, 1); goto err;
msleep(11); msleep(11);
msg.flags = I2C_M_RD; msg.flags = I2C_M_RD;
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
i2c_transfer(priv->i2c_adap, &msg, 1); goto err;
msg.flags = 0; msg.flags = 0;
buf[1] >>= 4; buf[1] >>= 4;
@@ -553,49 +601,55 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
tda827xa_lna_gain(fe, 0, NULL); tda827xa_lna_gain(fe, 0, NULL);
buf[0] = 0x60; buf[0] = 0x60;
buf[1] = 0x0c; buf[1] = 0x0c;
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
i2c_transfer(priv->i2c_adap, &msg, 1); goto err;
} }
buf[0] = 0xc0; buf[0] = 0xc0;
buf[1] = 0x99; // lpsel, for 6MHz + 2 buf[1] = 0x99; // lpsel, for 6MHz + 2
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
i2c_transfer(priv->i2c_adap, &msg, 1); goto err;
buf[0] = 0x60; buf[0] = 0x60;
buf[1] = 0x3c; buf[1] = 0x3c;
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
i2c_transfer(priv->i2c_adap, &msg, 1); goto err;
/* correct CP value */ /* correct CP value */
buf[0] = 0x30; buf[0] = 0x30;
buf[1] = 0x10 + tda827xa_dvbt[i].scr; buf[1] = 0x10 + frequency_map[i].scr;
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
i2c_transfer(priv->i2c_adap, &msg, 1); goto err;
msleep(163); msleep(163);
buf[0] = 0xc0; buf[0] = 0xc0;
buf[1] = 0x39; // lpsel, for 6MHz + 2 buf[1] = 0x39; // lpsel, for 6MHz + 2
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
i2c_transfer(priv->i2c_adap, &msg, 1); goto err;
msleep(3); msleep(3);
/* freeze AGC1 */ /* freeze AGC1 */
buf[0] = 0x50; buf[0] = 0x50;
buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4); buf[1] = 0x4f + (frequency_map[i].gc3 << 4);
if (fe->ops.i2c_gate_ctrl) rc = tuner_transfer(fe, &msg, 1);
fe->ops.i2c_gate_ctrl(fe, 1); if (rc < 0)
i2c_transfer(priv->i2c_adap, &msg, 1); goto err;
priv->frequency = params->frequency; priv->frequency = params->frequency;
priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
return 0; return 0;
err:
printk(KERN_ERR "%s: could not write to tuner at addr: 0x%02x\n",
__func__, priv->i2c_addr << 1);
return rc;
} }
@@ -643,7 +697,7 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe,
tuner_reg[9] = 0x20; tuner_reg[9] = 0x20;
tuner_reg[10] = 0x00; tuner_reg[10] = 0x00;
msg.len = 11; msg.len = 11;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
tuner_reg[0] = 0x90; tuner_reg[0] = 0x90;
tuner_reg[1] = 0xff; tuner_reg[1] = 0xff;
@@ -651,19 +705,19 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe,
tuner_reg[3] = 0; tuner_reg[3] = 0;
tuner_reg[4] = 0x99 + (priv->lpsel << 1); tuner_reg[4] = 0x99 + (priv->lpsel << 1);
msg.len = 5; msg.len = 5;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
tuner_reg[0] = 0xa0; tuner_reg[0] = 0xa0;
tuner_reg[1] = 0xc0; tuner_reg[1] = 0xc0;
msg.len = 2; msg.len = 2;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
tuner_reg[0] = 0x30; tuner_reg[0] = 0x30;
tuner_reg[1] = 0x10 + tda827xa_analog[i].scr; tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
msg.flags = I2C_M_RD; msg.flags = I2C_M_RD;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
msg.flags = 0; msg.flags = 0;
tuner_reg[1] >>= 4; tuner_reg[1] >>= 4;
dprintk("AGC2 gain is: %d\n", tuner_reg[1]); dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
@@ -673,24 +727,24 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe,
msleep(100); msleep(100);
tuner_reg[0] = 0x60; tuner_reg[0] = 0x60;
tuner_reg[1] = 0x3c; tuner_reg[1] = 0x3c;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
msleep(163); msleep(163);
tuner_reg[0] = 0x50; tuner_reg[0] = 0x50;
tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4); tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
tuner_reg[0] = 0x80; tuner_reg[0] = 0x80;
tuner_reg[1] = 0x28; tuner_reg[1] = 0x28;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
tuner_reg[0] = 0xb0; tuner_reg[0] = 0xb0;
tuner_reg[1] = 0x01; tuner_reg[1] = 0x01;
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
tuner_reg[0] = 0xc0; tuner_reg[0] = 0xc0;
tuner_reg[1] = 0x19 + (priv->lpsel << 1); tuner_reg[1] = 0x19 + (priv->lpsel << 1);
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
priv->frequency = params->frequency; priv->frequency = params->frequency;
@@ -703,7 +757,7 @@ static void tda827xa_agcf(struct dvb_frontend *fe)
unsigned char data[] = {0x80, 0x2c}; unsigned char data[] = {0x80, 0x2c};
struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0, struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
.buf = data, .len = 2}; .buf = data, .len = 2};
i2c_transfer(priv->i2c_adap, &msg, 1); tuner_transfer(fe, &msg, 1);
} }
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
@@ -792,16 +846,19 @@ static struct dvb_tuner_ops tda827xa_tuner_ops = {
}; };
static int tda827x_probe_version(struct dvb_frontend *fe) static int tda827x_probe_version(struct dvb_frontend *fe)
{ u8 data; {
u8 data;
int rc;
struct tda827x_priv *priv = fe->tuner_priv; struct tda827x_priv *priv = fe->tuner_priv;
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD, struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD,
.buf = &data, .len = 1 }; .buf = &data, .len = 1 };
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1); rc = tuner_transfer(fe, &msg, 1);
if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
if (rc < 0) {
printk("%s: could not read from tuner at addr: 0x%02x\n", printk("%s: could not read from tuner at addr: 0x%02x\n",
__func__, msg.addr << 1); __func__, msg.addr << 1);
return -EIO; return rc;
} }
if ((data & 0x3c) == 0) { if ((data & 0x3c) == 0) {
dprintk("tda827x tuner found\n"); dprintk("tda827x tuner found\n");

View File

@@ -22,7 +22,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/videodev.h> #include <linux/videodev2.h>
#include "tuner-i2c.h" #include "tuner-i2c.h"
#include "tda8290.h" #include "tda8290.h"
#include "tda827x.h" #include "tda827x.h"
@@ -566,8 +566,11 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
u8 data; u8 data;
struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 }; struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
if (NULL == analog_ops->i2c_gate_ctrl) if (!analog_ops->i2c_gate_ctrl) {
printk(KERN_ERR "tda8290: no gate control were provided!\n");
return -EINVAL; return -EINVAL;
}
analog_ops->i2c_gate_ctrl(fe, 1); analog_ops->i2c_gate_ctrl(fe, 1);
@@ -615,11 +618,13 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
if (ret != 1) { if (ret != 1) {
tuner_warn("tuner access failed!\n"); tuner_warn("tuner access failed!\n");
analog_ops->i2c_gate_ctrl(fe, 0);
return -EREMOTEIO; return -EREMOTEIO;
} }
if ((data == 0x83) || (data == 0x84)) { if ((data == 0x83) || (data == 0x84)) {
priv->ver |= TDA18271; priv->ver |= TDA18271;
tda829x_tda18271_config.config = priv->cfg.config;
dvb_attach(tda18271_attach, fe, priv->tda827x_addr, dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
priv->i2c_props.adap, &tda829x_tda18271_config); priv->i2c_props.adap, &tda829x_tda18271_config);
} else { } else {

View File

@@ -9,7 +9,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/videodev.h> #include <linux/videodev2.h>
#include <media/tuner.h> #include <media/tuner.h>
#include "tuner-i2c.h" #include "tuner-i2c.h"
#include "tea5761.h" #include "tea5761.h"

View File

@@ -12,7 +12,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/videodev.h> #include <linux/videodev2.h>
#include "tuner-i2c.h" #include "tuner-i2c.h"
#include "tea5767.h" #include "tea5767.h"

View File

@@ -739,7 +739,10 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
__func__, params->frequency); __func__, params->frequency);
priv->rf_mode = XC_RF_MODE_CABLE; /* Fix me: it could be air. */ /* Fix me: it could be air. */
priv->rf_mode = params->mode;
if (params->mode > XC_RF_MODE_CABLE)
priv->rf_mode = XC_RF_MODE_CABLE;
/* params->frequency is in units of 62.5khz */ /* params->frequency is in units of 62.5khz */
priv->freq_hz = params->frequency * 62500; priv->freq_hz = params->frequency * 62500;
@@ -970,8 +973,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
case 1: case 1:
/* new tuner instance */ /* new tuner instance */
priv->bandwidth = BANDWIDTH_6_MHZ; priv->bandwidth = BANDWIDTH_6_MHZ;
priv->if_khz = cfg->if_khz;
fe->tuner_priv = priv; fe->tuner_priv = priv;
break; break;
default: default:
@@ -980,6 +981,13 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
break; break;
} }
if (priv->if_khz == 0) {
/* If the IF hasn't been set yet, use the value provided by
the caller (occurs in hybrid devices where the analog
call to xc5000_attach occurs before the digital side) */
priv->if_khz = cfg->if_khz;
}
/* Check if firmware has been loaded. It is possible that another /* Check if firmware has been loaded. It is possible that another
instance of the driver has loaded the firmware. instance of the driver has loaded the firmware.
*/ */

View File

@@ -13,7 +13,7 @@ config DVB_B2C2_FLEXCOP
select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
select DVB_ISL6421 if !DVB_FE_CUSTOMISE select DVB_ISL6421 if !DVB_FE_CUSTOMISE
select DVB_CX24123 if !DVB_FE_CUSTOMISE select DVB_CX24123 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE
help help
Support for the digital TV receiver chip made by B2C2 Inc. included in Support for the digital TV receiver chip made by B2C2 Inc. included in

View File

@@ -2,7 +2,6 @@ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),) ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
b2c2-flexcop-objs += flexcop-dma.o b2c2-flexcop-objs += flexcop-dma.o
endif endif

View File

@@ -28,11 +28,14 @@
/* Steal from usb.h */ /* Steal from usb.h */
#undef err #undef err
#define err(format, arg...) printk(KERN_ERR FC_LOG_PREFIX ": " format "\n" , ## arg) #define err(format, arg...) \
printk(KERN_ERR FC_LOG_PREFIX ": " format "\n" , ## arg)
#undef info #undef info
#define info(format, arg...) printk(KERN_INFO FC_LOG_PREFIX ": " format "\n" , ## arg) #define info(format, arg...) \
printk(KERN_INFO FC_LOG_PREFIX ": " format "\n" , ## arg)
#undef warn #undef warn
#define warn(format, arg...) printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg) #define warn(format, arg...) \
printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg)
struct flexcop_dma { struct flexcop_dma {
struct pci_dev *pdev; struct pci_dev *pdev;
@@ -91,16 +94,14 @@ struct flexcop_device {
int fullts_streaming_state; int fullts_streaming_state;
/* bus specific callbacks */ /* bus specific callbacks */
flexcop_ibi_value (*read_ibi_reg) (struct flexcop_device *, flexcop_ibi_register); flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *,
int (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value); flexcop_ibi_register);
int (*write_ibi_reg) (struct flexcop_device *,
flexcop_ibi_register, flexcop_ibi_value);
int (*i2c_request) (struct flexcop_i2c_adapter *, int (*i2c_request) (struct flexcop_i2c_adapter *,
flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len); flexcop_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
int (*stream_control) (struct flexcop_device *, int); int (*stream_control) (struct flexcop_device *, int);
int (*get_mac_addr) (struct flexcop_device *fc, int extended); int (*get_mac_addr) (struct flexcop_device *fc, int extended);
void *bus_specific; void *bus_specific;
}; };
@@ -115,18 +116,24 @@ void flexcop_device_kfree(struct flexcop_device*);
int flexcop_device_initialize(struct flexcop_device *); int flexcop_device_initialize(struct flexcop_device *);
void flexcop_device_exit(struct flexcop_device *fc); void flexcop_device_exit(struct flexcop_device *fc);
void flexcop_reset_block_300(struct flexcop_device *fc); void flexcop_reset_block_300(struct flexcop_device *fc);
/* from flexcop-dma.c */ /* from flexcop-dma.c */
int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size); int flexcop_dma_allocate(struct pci_dev *pdev,
struct flexcop_dma *dma, u32 size);
void flexcop_dma_free(struct flexcop_dma *dma); void flexcop_dma_free(struct flexcop_dma *dma);
int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff); flexcop_dma_index_t no, int onoff);
int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx); int flexcop_dma_control_size_irq(struct flexcop_device *fc,
int flexcop_dma_xfer_control(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index, int onoff); flexcop_dma_index_t no, int onoff);
int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles); int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma,
flexcop_dma_index_t dma_idx);
int flexcop_dma_xfer_control(struct flexcop_device *fc,
flexcop_dma_index_t dma_idx, flexcop_dma_addr_index_t index,
int onoff);
int flexcop_dma_config_timer(struct flexcop_device *fc,
flexcop_dma_index_t dma_idx, u8 cycles);
/* from flexcop-eeprom.c */ /* from flexcop-eeprom.c */
/* the PCI part uses this call to get the MAC address, the USB part has its own */ /* the PCI part uses this call to get the MAC address, the USB part has its own */
@@ -141,13 +148,15 @@ int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t,
u8 chipaddr, u8 addr, u8 *buf, u16 len); u8 chipaddr, u8 addr, u8 *buf, u16 len);
/* from flexcop-sram.c */ /* from flexcop-sram.c */
int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target); int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest,
flexcop_sram_dest_target_t target);
void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s); void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s);
void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill); void flexcop_sram_ctrl(struct flexcop_device *fc,
int usb_wan, int sramdma, int maximumfill);
/* global prototypes for the flexcop-chip */ /* global prototypes for the flexcop-chip */
/* from flexcop-fe-tuner.c */ /* from flexcop-fe-tuner.c */
int flexcop_frontend_init(struct flexcop_device *card); int flexcop_frontend_init(struct flexcop_device *fc);
void flexcop_frontend_exit(struct flexcop_device *fc); void flexcop_frontend_exit(struct flexcop_device *fc);
/* from flexcop-i2c.c */ /* from flexcop-i2c.c */
@@ -159,11 +168,14 @@ int flexcop_sram_init(struct flexcop_device *fc);
/* from flexcop-misc.c */ /* from flexcop-misc.c */
void flexcop_determine_revision(struct flexcop_device *fc); void flexcop_determine_revision(struct flexcop_device *fc);
void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const char *suffix); void flexcop_device_name(struct flexcop_device *fc,
void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num); const char *prefix, const char *suffix);
void flexcop_dump_reg(struct flexcop_device *fc,
flexcop_ibi_register reg, int num);
/* from flexcop-hw-filter.c */ /* from flexcop-hw-filter.c */
int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff); int flexcop_pid_feed_control(struct flexcop_device *fc,
struct dvb_demux_feed *dvbdmxfeed, int onoff);
void flexcop_hw_filter_init(struct flexcop_device *fc); void flexcop_hw_filter_init(struct flexcop_device *fc);
void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff); void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff);

View File

@@ -1,13 +1,12 @@
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* * flexcop-dma.c - configuring and controlling the DMA of the FlexCop
* flexcop-dma.c - methods for configuring and controlling the DMA of the FlexCop. * see flexcop.c for copyright information
*
* see flexcop.c for copyright information.
*/ */
#include "flexcop.h" #include "flexcop.h"
int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size) int flexcop_dma_allocate(struct pci_dev *pdev,
struct flexcop_dma *dma, u32 size)
{ {
u8 *tcpu; u8 *tcpu;
dma_addr_t tdma = 0; dma_addr_t tdma = 0;
@@ -32,7 +31,8 @@ EXPORT_SYMBOL(flexcop_dma_allocate);
void flexcop_dma_free(struct flexcop_dma *dma) void flexcop_dma_free(struct flexcop_dma *dma)
{ {
pci_free_consistent(dma->pdev, dma->size*2,dma->cpu_addr0, dma->dma_addr0); pci_free_consistent(dma->pdev, dma->size*2,
dma->cpu_addr0, dma->dma_addr0);
memset(dma,0,sizeof(struct flexcop_dma)); memset(dma,0,sizeof(struct flexcop_dma));
} }
EXPORT_SYMBOL(flexcop_dma_free); EXPORT_SYMBOL(flexcop_dma_free);
@@ -57,7 +57,8 @@ int flexcop_dma_config(struct flexcop_device *fc,
fc->write_ibi_reg(fc,dma2_014,v0x4); fc->write_ibi_reg(fc,dma2_014,v0x4);
fc->write_ibi_reg(fc,dma2_01c,v0xc); fc->write_ibi_reg(fc,dma2_01c,v0xc);
} else { } else {
err("either DMA1 or DMA2 can be configured at the within one flexcop_dma_config call."); err("either DMA1 or DMA2 can be configured within one "
"flexcop_dma_config call.");
return -EINVAL; return -EINVAL;
} }
@@ -81,7 +82,8 @@ int flexcop_dma_xfer_control(struct flexcop_device *fc,
r0x0 = dma2_010; r0x0 = dma2_010;
r0xc = dma2_01c; r0xc = dma2_01c;
} else { } else {
err("either transfer DMA1 or DMA2 can be started within one flexcop_dma_xfer_control call."); err("either transfer DMA1 or DMA2 can be started within one "
"flexcop_dma_xfer_control call.");
return -EINVAL; return -EINVAL;
} }
@@ -154,8 +156,7 @@ EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
/* 1 cycles = 1.97 msec */ /* 1 cycles = 1.97 msec */
int flexcop_dma_config_timer(struct flexcop_device *fc, int flexcop_dma_config_timer(struct flexcop_device *fc,
flexcop_dma_index_t dma_idx, flexcop_dma_index_t dma_idx, u8 cycles)
u8 cycles)
{ {
flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014; flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
flexcop_ibi_value v = fc->read_ibi_reg(fc,r); flexcop_ibi_value v = fc->read_ibi_reg(fc,r);

View File

@@ -1,9 +1,7 @@
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading)
* flexcop-eeprom.c - eeprom access methods (currently only MAC address reading is used) * see flexcop.c for copyright information
*
* see flexcop.c for copyright information.
*/ */
#include "flexcop.h" #include "flexcop.h"
@@ -14,7 +12,8 @@ static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len)
return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len); return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len);
} }
static int eeprom_lrc_write(struct adapter *adapter, u32 addr, u32 len, u8 *wbuf, u8 *rbuf, int retries) static int eeprom_lrc_write(struct adapter *adapter, u32 addr,
u32 len, u8 *wbuf, u8 *rbuf, int retries)
{ {
int i; int i;
@@ -24,7 +23,6 @@ static int eeprom_lrc_write(struct adapter *adapter, u32 addr, u32 len, u8 *wbuf
return 1; return 1;
} }
} }
return 0; return 0;
} }
@@ -39,12 +37,10 @@ static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len)
return 0; return 0;
memcpy(wbuf, key, len); memcpy(wbuf, key, len);
wbuf[16] = 0; wbuf[16] = 0;
wbuf[17] = 0; wbuf[17] = 0;
wbuf[18] = 0; wbuf[18] = 0;
wbuf[19] = calc_lrc(wbuf, 19); wbuf[19] = calc_lrc(wbuf, 19);
return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4); return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4);
} }
@@ -59,7 +55,6 @@ static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len)
return 0; return 0;
memcpy(key, buf, len); memcpy(key, buf, len);
return 1; return 1;
} }
@@ -74,9 +69,7 @@ static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac)
tmp[3] = mac[5]; tmp[3] = mac[5];
tmp[4] = mac[6]; tmp[4] = mac[6];
tmp[5] = mac[7]; tmp[5] = mac[7];
} else { } else {
tmp[0] = mac[0]; tmp[0] = mac[0];
tmp[1] = mac[1]; tmp[1] = mac[1];
tmp[2] = mac[2]; tmp[2] = mac[2];
@@ -90,11 +83,11 @@ static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac)
if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8) if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8)
return 1; return 1;
return 0; return 0;
} }
static int flexcop_eeprom_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len) static int flexcop_eeprom_read(struct flexcop_device *fc,
u16 addr, u8 *buf, u16 len)
{ {
return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len); return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len);
} }
@@ -110,7 +103,8 @@ static u8 calc_lrc(u8 *buf, int len)
return sum; return sum;
} }
static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries) static int flexcop_eeprom_request(struct flexcop_device *fc,
flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries)
{ {
int i,ret = 0; int i,ret = 0;
u8 chipaddr = 0x50 | ((addr >> 8) & 3); u8 chipaddr = 0x50 | ((addr >> 8) & 3);
@@ -123,7 +117,8 @@ static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t
return ret; return ret;
} }
static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries) static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr,
u8 *buf, u16 len, int retries)
{ {
int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries); int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries);
if (ret == 0) if (ret == 0)
@@ -133,8 +128,7 @@ static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf,
} }
/* JJ's comment about extended == 1: it is not presently used anywhere but was /* JJ's comment about extended == 1: it is not presently used anywhere but was
* added to the low-level functions for possible support of EUI64 * added to the low-level functions for possible support of EUI64 */
*/
int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended) int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended)
{ {
u8 buf[8]; u8 buf[8];
@@ -142,12 +136,9 @@ int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended)
if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) { if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) {
if (extended != 0) { if (extended != 0) {
err("TODO: extended (EUI64) MAC addresses aren't completely supported yet"); err("TODO: extended (EUI64) MAC addresses aren't "
"completely supported yet");
ret = -EINVAL; ret = -EINVAL;
/* memcpy(fc->dvb_adapter.proposed_mac,buf,3);
mac[3] = 0xfe;
mac[4] = 0xff;
memcpy(&fc->dvb_adapter.proposed_mac[3],&buf[5],3); */
} else } else
memcpy(fc->dvb_adapter.proposed_mac,buf,6); memcpy(fc->dvb_adapter.proposed_mac,buf,6);
} }

View File

@@ -592,14 +592,14 @@ int flexcop_frontend_init(struct flexcop_device *fc)
fc->fe_sleep = ops->sleep; fc->fe_sleep = ops->sleep;
ops->sleep = flexcop_sleep; ops->sleep = flexcop_sleep;
fc->dev_type = FC_SKY; fc->dev_type = FC_SKY_REV26;
goto fe_found; goto fe_found;
} }
/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */ /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c); fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
if (fc->fe != NULL) { if (fc->fe != NULL) {
fc->dev_type = FC_AIR_DVB; fc->dev_type = FC_AIR_DVBT;
fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
goto fe_found; goto fe_found;
} }
@@ -653,7 +653,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
fc->fe_sleep = ops->sleep; fc->fe_sleep = ops->sleep;
ops->sleep = flexcop_sleep; ops->sleep = flexcop_sleep;
fc->dev_type = FC_SKY_OLD; fc->dev_type = FC_SKY_REV23;
goto fe_found; goto fe_found;
} }

View File

@@ -1,16 +1,13 @@
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* * flexcop-hw-filter.c - pid and mac address filtering and control functions
* flexcop-hw-filter.c - pid and mac address filtering and corresponding control functions. * see flexcop.c for copyright information
*
* see flexcop.c for copyright information.
*/ */
#include "flexcop.h" #include "flexcop.h"
static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff) static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff)
{ {
flexcop_set_ibi_value(ctrl_208, Rcv_Data_sig, onoff); flexcop_set_ibi_value(ctrl_208, Rcv_Data_sig, onoff);
deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off"); deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off");
} }
@@ -45,7 +42,8 @@ void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff)
flexcop_set_ibi_value(ctrl_208, MAC_filter_Mode_sig, onoff); flexcop_set_ibi_value(ctrl_208, MAC_filter_Mode_sig, onoff);
} }
static void flexcop_pid_group_filter(struct flexcop_device *fc, u16 pid, u16 mask) static void flexcop_pid_group_filter(struct flexcop_device *fc,
u16 pid, u16 mask)
{ {
/* index_reg_310.extra_index_reg need to 0 or 7 to work */ /* index_reg_310.extra_index_reg need to 0 or 7 to work */
flexcop_ibi_value v30c; flexcop_ibi_value v30c;
@@ -66,60 +64,80 @@ static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff)
#define pid_ctrl(vregname,field,enablefield,trans_field,transval) \ #define pid_ctrl(vregname,field,enablefield,trans_field,transval) \
flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \ flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \
v208 = fc->read_ibi_reg(fc, ctrl_208); \ v208 = fc->read_ibi_reg(fc, ctrl_208); \
\
vpid.vregname.field = onoff ? pid : 0x1fff; \ vpid.vregname.field = onoff ? pid : 0x1fff; \
vpid.vregname.trans_field = transval; \ vpid.vregname.trans_field = transval; \
v208.ctrl_208.enablefield = onoff; \ v208.ctrl_208.enablefield = onoff; \
\
fc->write_ibi_reg(fc, vregname, vpid); \ fc->write_ibi_reg(fc, vregname, vpid); \
fc->write_ibi_reg(fc, ctrl_208, v208); fc->write_ibi_reg(fc, ctrl_208, v208);
static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc,
u16 pid, int onoff)
{ {
pid_ctrl(pid_filter_300,Stream1_PID,Stream1_filter_sig,Stream1_trans,0); pid_ctrl(pid_filter_300, Stream1_PID, Stream1_filter_sig,
Stream1_trans, 0);
} }
static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc,
u16 pid, int onoff)
{ {
pid_ctrl(pid_filter_300,Stream2_PID,Stream2_filter_sig,Stream2_trans,0); pid_ctrl(pid_filter_300, Stream2_PID, Stream2_filter_sig,
Stream2_trans, 0);
} }
static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc,
u16 pid, int onoff)
{ {
pid_ctrl(pid_filter_304, PCR_PID, PCR_filter_sig, PCR_trans, 0); pid_ctrl(pid_filter_304, PCR_PID, PCR_filter_sig, PCR_trans, 0);
} }
static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc,
u16 pid, int onoff)
{ {
pid_ctrl(pid_filter_304, PMT_PID, PMT_filter_sig, PMT_trans, 0); pid_ctrl(pid_filter_304, PMT_PID, PMT_filter_sig, PMT_trans, 0);
} }
static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc,
u16 pid, int onoff)
{ {
pid_ctrl(pid_filter_308, EMM_PID, EMM_filter_sig, EMM_trans, 0); pid_ctrl(pid_filter_308, EMM_PID, EMM_filter_sig, EMM_trans, 0);
} }
static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff) static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc,
u16 pid, int onoff)
{ {
pid_ctrl(pid_filter_308, ECM_PID, ECM_filter_sig, ECM_trans, 0); pid_ctrl(pid_filter_308, ECM_PID, ECM_filter_sig, ECM_trans, 0);
} }
static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid,int onoff) static void flexcop_pid_control(struct flexcop_device *fc,
int index, u16 pid, int onoff)
{ {
if (pid == 0x2000) if (pid == 0x2000)
return; return;
deb_ts("setting pid: %5d %04x at index %d '%s'\n",pid,pid,index,onoff ? "on" : "off"); deb_ts("setting pid: %5d %04x at index %d '%s'\n",
pid, pid, index, onoff ? "on" : "off");
/* We could use bit magic here to reduce source code size. /* We could use bit magic here to reduce source code size.
* I decided against it, but to use the real register names */ * I decided against it, but to use the real register names */
switch (index) { switch (index) {
case 0: flexcop_pid_Stream1_PID_ctrl(fc,pid,onoff); break; case 0:
case 1: flexcop_pid_Stream2_PID_ctrl(fc,pid,onoff); break; flexcop_pid_Stream1_PID_ctrl(fc, pid, onoff);
case 2: flexcop_pid_PCR_PID_ctrl(fc,pid,onoff); break; break;
case 3: flexcop_pid_PMT_PID_ctrl(fc,pid,onoff); break; case 1:
case 4: flexcop_pid_EMM_PID_ctrl(fc,pid,onoff); break; flexcop_pid_Stream2_PID_ctrl(fc, pid, onoff);
case 5: flexcop_pid_ECM_PID_ctrl(fc,pid,onoff); break; break;
case 2:
flexcop_pid_PCR_PID_ctrl(fc, pid, onoff);
break;
case 3:
flexcop_pid_PMT_PID_ctrl(fc, pid, onoff);
break;
case 4:
flexcop_pid_EMM_PID_ctrl(fc, pid, onoff);
break;
case 5:
flexcop_pid_ECM_PID_ctrl(fc, pid, onoff);
break;
default: default:
if (fc->has_32_hw_pid_filter && index < 38) { if (fc->has_32_hw_pid_filter && index < 38) {
flexcop_ibi_value vpid, vid; flexcop_ibi_value vpid, vid;
@@ -149,7 +167,8 @@ static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc,int onoff)
return 0; return 0;
} }
int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff) int flexcop_pid_feed_control(struct flexcop_device *fc,
struct dvb_demux_feed *dvbdmxfeed, int onoff)
{ {
int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32; int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32;
@@ -167,7 +186,8 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d
flexcop_toggle_fullts_streaming(fc, onoff); flexcop_toggle_fullts_streaming(fc, onoff);
if (fc->pid_filtering) { if (fc->pid_filtering) {
flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff); flexcop_pid_control \
(fc, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
if (fc->extra_feedcount > 0) if (fc->extra_feedcount > 0)
flexcop_toggle_fullts_streaming(fc, 1); flexcop_toggle_fullts_streaming(fc, 1);
@@ -189,7 +209,6 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d
flexcop_hw_filter_init(fc); flexcop_hw_filter_init(fc);
} }
} }
return 0; return 0;
} }
EXPORT_SYMBOL(flexcop_pid_feed_control); EXPORT_SYMBOL(flexcop_pid_feed_control);

View File

@@ -1,17 +1,14 @@
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
*
* flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization
* * see flexcop.c for copyright information
* see flexcop.c for copyright information.
*/ */
#include "flexcop.h" #include "flexcop.h"
#define FC_MAX_I2C_RETRIES 100000 #define FC_MAX_I2C_RETRIES 100000
/* #define DUMP_I2C_MESSAGES */ static int flexcop_i2c_operation(struct flexcop_device *fc,
flexcop_ibi_value *r100)
static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
{ {
int i; int i;
flexcop_ibi_value r; flexcop_ibi_value r;
@@ -26,7 +23,7 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r
r = fc->read_ibi_reg(fc, tw_sm_c_100); r = fc->read_ibi_reg(fc, tw_sm_c_100);
if (!r.tw_sm_c_100.no_base_addr_ack_error) { if (!r.tw_sm_c_100.no_base_addr_ack_error) {
if (r.tw_sm_c_100.st_done) { /* && !r.tw_sm_c_100.working_start */ if (r.tw_sm_c_100.st_done) {
*r100 = r; *r100 = r;
deb_i2c("i2c success\n"); deb_i2c("i2c success\n");
return 0; return 0;
@@ -36,7 +33,8 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r
return -EREMOTEIO; return -EREMOTEIO;
} }
} }
deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i); deb_i2c("tried %d times i2c operation, "
"never finished or too many ack errors.\n", i);
return -EREMOTEIO; return -EREMOTEIO;
} }
@@ -44,9 +42,22 @@ static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
flexcop_ibi_value r100, u8 *buf) flexcop_ibi_value r100, u8 *buf)
{ {
flexcop_ibi_value r104; flexcop_ibi_value r104;
int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ int len = r100.tw_sm_c_100.total_bytes,
/* remember total_bytes is buflen-1 */
ret; ret;
/* work-around to have CableStar2 and SkyStar2 rev 2.7 work
* correctly:
*
* the ITD1000 is behind an i2c-gate which closes automatically
* after an i2c-transaction the STV0297 needs 2 consecutive reads
* one with no_base_addr = 0 and one with 1
*
* those two work-arounds are conflictin: we check for the card
* type, it is set when probing the ITD1000 */
if (i2c->fc->dev_type == FC_SKY_REV27)
r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr;
ret = flexcop_i2c_operation(i2c->fc, &r100); ret = flexcop_i2c_operation(i2c->fc, &r100);
if (ret != 0) { if (ret != 0) {
deb_i2c("Retrying operation\n"); deb_i2c("Retrying operation\n");
@@ -69,11 +80,11 @@ static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c,
if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg; if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;
if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg; if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
} }
return 0; return 0;
} }
static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf) static int flexcop_i2c_write4(struct flexcop_device *fc,
flexcop_ibi_value r100, u8 *buf)
{ {
flexcop_ibi_value r104; flexcop_ibi_value r104;
int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */ int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */
@@ -81,7 +92,6 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100,
/* there is at least one byte, otherwise we wouldn't be here */ /* there is at least one byte, otherwise we wouldn't be here */
r100.tw_sm_c_100.data1_reg = buf[0]; r100.tw_sm_c_100.data1_reg = buf[0];
r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0; r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0;
r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0; r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0; r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
@@ -117,7 +127,6 @@ int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
printk("rd("); printk("rd(");
else else
printk("wr("); printk("wr(");
printk("%02x): %02x ", chipaddr, addr); printk("%02x): %02x ", chipaddr, addr);
#endif #endif
@@ -163,7 +172,8 @@ int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
EXPORT_SYMBOL(flexcop_i2c_request); EXPORT_SYMBOL(flexcop_i2c_request);
/* master xfer callback for demodulator */ /* master xfer callback for demodulator */
static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) static int flexcop_master_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg msgs[], int num)
{ {
struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap); struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
int i, ret = 0; int i, ret = 0;
@@ -182,7 +192,8 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs
/* reading */ /* reading */
if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) { if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) {
ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr, ret = i2c->fc->i2c_request(i2c, FC_READ, msgs[i].addr,
msgs[i].buf[0], msgs[i+1].buf, msgs[i+1].len); msgs[i].buf[0], msgs[i+1].buf,
msgs[i+1].len);
i++; /* skip the following message */ i++; /* skip the following message */
} else /* writing */ } else /* writing */
ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr, ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
@@ -214,13 +225,11 @@ static struct i2c_algorithm flexcop_algo = {
int flexcop_i2c_init(struct flexcop_device *fc) int flexcop_i2c_init(struct flexcop_device *fc)
{ {
int ret; int ret;
mutex_init(&fc->i2c_mutex); mutex_init(&fc->i2c_mutex);
fc->fc_i2c_adap[0].fc = fc; fc->fc_i2c_adap[0].fc = fc;
fc->fc_i2c_adap[1].fc = fc; fc->fc_i2c_adap[1].fc = fc;
fc->fc_i2c_adap[2].fc = fc; fc->fc_i2c_adap[2].fc = fc;
fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD; fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD;
fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM; fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER; fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
@@ -268,7 +277,6 @@ adap_2_failed:
i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap); i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
adap_1_failed: adap_1_failed:
i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap); i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
return ret; return ret;
} }
@@ -279,6 +287,5 @@ void flexcop_i2c_exit(struct flexcop_device *fc)
i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap); i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap); i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
} }
fc->init_state &= ~FC_STATE_I2C_INIT; fc->init_state &= ~FC_STATE_I2C_INIT;
} }

View File

@@ -1,9 +1,7 @@
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* * flexcop-misc.c - miscellaneous functions
* flexcop-misc.c - miscellaneous functions. * see flexcop.c for copyright information
*
* see flexcop.c for copyright information.
*/ */
#include "flexcop.h" #include "flexcop.h"
@@ -25,26 +23,30 @@ void flexcop_determine_revision(struct flexcop_device *fc)
fc->rev = FLEXCOP_III; fc->rev = FLEXCOP_III;
break; break;
default: default:
err("unkown FlexCop Revision: %x. Please report the linux-dvb@linuxtv.org.",v.misc_204.Rev_N_sig_revision_hi); err("unknown FlexCop Revision: %x. Please report this to "
"linux-dvb@linuxtv.org.",
v.misc_204.Rev_N_sig_revision_hi);
break; break;
} }
if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps)) if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps))
deb_info("this FlexCop has the additional 32 hardware pid filter.\n"); deb_info("this FlexCop has "
"the additional 32 hardware pid filter.\n");
else else
deb_info("this FlexCop has only the 6 basic main hardware pid filter.\n"); deb_info("this FlexCop has "
"the 6 basic main hardware pid filter.\n");
/* bus parts have to decide if hw pid filtering is used or not. */ /* bus parts have to decide if hw pid filtering is used or not. */
} }
static const char *flexcop_revision_names[] = { static const char *flexcop_revision_names[] = {
"Unkown chip", "Unknown chip",
"FlexCopII", "FlexCopII",
"FlexCopIIb", "FlexCopIIb",
"FlexCopIII", "FlexCopIII",
}; };
static const char *flexcop_device_names[] = { static const char *flexcop_device_names[] = {
"Unkown device", "Unknown device",
"Air2PC/AirStar 2 DVB-T", "Air2PC/AirStar 2 DVB-T",
"Air2PC/AirStar 2 ATSC 1st generation", "Air2PC/AirStar 2 ATSC 1st generation",
"Air2PC/AirStar 2 ATSC 2nd generation", "Air2PC/AirStar 2 ATSC 2nd generation",
@@ -61,15 +63,17 @@ static const char *flexcop_bus_names[] = {
"PCI", "PCI",
}; };
void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const void flexcop_device_name(struct flexcop_device *fc,
char *suffix) const char *prefix, const char *suffix)
{ {
info("%s '%s' at the '%s' bus controlled by a '%s' %s",prefix, info("%s '%s' at the '%s' bus controlled by a '%s' %s",
flexcop_device_names[fc->dev_type],flexcop_bus_names[fc->bus_type], prefix, flexcop_device_names[fc->dev_type],
flexcop_bus_names[fc->bus_type],
flexcop_revision_names[fc->rev], suffix); flexcop_revision_names[fc->rev], suffix);
} }
void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num) void flexcop_dump_reg(struct flexcop_device *fc,
flexcop_ibi_register reg, int num)
{ {
flexcop_ibi_value v; flexcop_ibi_value v;
int i; int i;

View File

@@ -1,9 +1,7 @@
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
* * flexcop-pci.c - covers the PCI part including DMA transfers
* flexcop-pci.c - covers the PCI part including DMA transfers. * see flexcop.c for copyright information
*
* see flexcop.c for copyright information.
*/ */
#define FC_LOG_PREFIX "flexcop-pci" #define FC_LOG_PREFIX "flexcop-pci"
@@ -11,7 +9,8 @@
static int enable_pid_filtering = 1; static int enable_pid_filtering = 1;
module_param(enable_pid_filtering, int, 0444); module_param(enable_pid_filtering, int, 0444);
MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1"); MODULE_PARM_DESC(enable_pid_filtering,
"enable hardware pid filtering: supported values: 0 (fullts), 1");
static int irq_chk_intv = 100; static int irq_chk_intv = 100;
module_param(irq_chk_intv, int, 0644); module_param(irq_chk_intv, int, 0644);
@@ -58,23 +57,23 @@ struct flexcop_pci {
struct flexcop_dma dma[2]; struct flexcop_dma dma[2];
int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */ int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */
u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */ u32 last_dma1_cur_pos;
/* position of the pointer last time the timer/packet irq occured */
int count; int count;
int count_prev; int count_prev;
int stream_problem; int stream_problem;
spinlock_t irq_lock; spinlock_t irq_lock;
unsigned long last_irq; unsigned long last_irq;
struct delayed_work irq_check_work; struct delayed_work irq_check_work;
struct flexcop_device *fc_dev; struct flexcop_device *fc_dev;
}; };
static int lastwreg, lastwval, lastrreg, lastrval; static int lastwreg, lastwval, lastrreg, lastrval;
static flexcop_ibi_value flexcop_pci_read_ibi_reg (struct flexcop_device *fc, flexcop_ibi_register r) static flexcop_ibi_value flexcop_pci_read_ibi_reg(struct flexcop_device *fc,
flexcop_ibi_register r)
{ {
struct flexcop_pci *fc_pci = fc->bus_specific; struct flexcop_pci *fc_pci = fc->bus_specific;
flexcop_ibi_value v; flexcop_ibi_value v;
@@ -88,7 +87,8 @@ static flexcop_ibi_value flexcop_pci_read_ibi_reg (struct flexcop_device *fc, fl
return v; return v;
} }
static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register r, flexcop_ibi_value v) static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc,
flexcop_ibi_register r, flexcop_ibi_value v)
{ {
struct flexcop_pci *fc_pci = fc->bus_specific; struct flexcop_pci *fc_pci = fc->bus_specific;
@@ -113,6 +113,7 @@ static void flexcop_pci_irq_check_work(struct work_struct *work)
deb_chk("no IRQ since the last check\n"); deb_chk("no IRQ since the last check\n");
if (fc_pci->stream_problem++ == 3) { if (fc_pci->stream_problem++ == 3) {
struct dvb_demux_feed *feed; struct dvb_demux_feed *feed;
deb_info("flexcop-pci: stream problem, resetting pid filter\n");
spin_lock_irq(&fc->demux.lock); spin_lock_irq(&fc->demux.lock);
list_for_each_entry(feed, &fc->demux.feed_list, list_for_each_entry(feed, &fc->demux.feed_list,
@@ -150,7 +151,6 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
irqreturn_t ret = IRQ_HANDLED; irqreturn_t ret = IRQ_HANDLED;
spin_lock_irqsave(&fc_pci->irq_lock, flags); spin_lock_irqsave(&fc_pci->irq_lock, flags);
v = fc->read_ibi_reg(fc, irq_20c); v = fc->read_ibi_reg(fc, irq_20c);
/* errors */ /* errors */
@@ -168,20 +168,25 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
if (v.irq_20c.DMA1_IRQ_Status == 1) { if (v.irq_20c.DMA1_IRQ_Status == 1) {
if (fc_pci->active_dma1_addr == 0) if (fc_pci->active_dma1_addr == 0)
flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr0,fc_pci->dma[0].size / 188); flexcop_pass_dmx_packets(fc_pci->fc_dev,
fc_pci->dma[0].cpu_addr0,
fc_pci->dma[0].size / 188);
else else
flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr1,fc_pci->dma[0].size / 188); flexcop_pass_dmx_packets(fc_pci->fc_dev,
fc_pci->dma[0].cpu_addr1,
fc_pci->dma[0].size / 188);
deb_irq("page change to page: %d\n",!fc_pci->active_dma1_addr); deb_irq("page change to page: %d\n",!fc_pci->active_dma1_addr);
fc_pci->active_dma1_addr = !fc_pci->active_dma1_addr; fc_pci->active_dma1_addr = !fc_pci->active_dma1_addr;
} else if (v.irq_20c.DMA1_Timer_Status == 1) {
/* for the timer IRQ we only can use buffer dmx feeding, because we don't have /* for the timer IRQ we only can use buffer dmx feeding, because we don't have
* complete TS packets when reading from the DMA memory */ * complete TS packets when reading from the DMA memory */
} else if (v.irq_20c.DMA1_Timer_Status == 1) {
dma_addr_t cur_addr = dma_addr_t cur_addr =
fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ", deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, "
"last_cur_pos: %08x ",
jiffies_to_usecs(jiffies - fc_pci->last_irq), jiffies_to_usecs(jiffies - fc_pci->last_irq),
v.raw, (unsigned long long)cur_addr, cur_pos, v.raw, (unsigned long long)cur_addr, cur_pos,
fc_pci->last_dma1_cur_pos); fc_pci->last_dma1_cur_pos);
@@ -191,17 +196,23 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
* pass the data from last_cur_pos to the buffer end to the demux * pass the data from last_cur_pos to the buffer end to the demux
*/ */
if (cur_pos < fc_pci->last_dma1_cur_pos) { if (cur_pos < fc_pci->last_dma1_cur_pos) {
deb_irq(" end was reached: passing %d bytes ",(fc_pci->dma[0].size*2 - 1) - fc_pci->last_dma1_cur_pos); deb_irq(" end was reached: passing %d bytes ",
(fc_pci->dma[0].size*2 - 1) -
fc_pci->last_dma1_cur_pos);
flexcop_pass_dmx_data(fc_pci->fc_dev, flexcop_pass_dmx_data(fc_pci->fc_dev,
fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, fc_pci->dma[0].cpu_addr0 +
(fc_pci->dma[0].size*2) - fc_pci->last_dma1_cur_pos); fc_pci->last_dma1_cur_pos,
(fc_pci->dma[0].size*2) -
fc_pci->last_dma1_cur_pos);
fc_pci->last_dma1_cur_pos = 0; fc_pci->last_dma1_cur_pos = 0;
} }
if (cur_pos > fc_pci->last_dma1_cur_pos) { if (cur_pos > fc_pci->last_dma1_cur_pos) {
deb_irq(" passing %d bytes ",cur_pos - fc_pci->last_dma1_cur_pos); deb_irq(" passing %d bytes ",
cur_pos - fc_pci->last_dma1_cur_pos);
flexcop_pass_dmx_data(fc_pci->fc_dev, flexcop_pass_dmx_data(fc_pci->fc_dev,
fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, fc_pci->dma[0].cpu_addr0 +
fc_pci->last_dma1_cur_pos,
cur_pos - fc_pci->last_dma1_cur_pos); cur_pos - fc_pci->last_dma1_cur_pos);
} }
deb_irq("\n"); deb_irq("\n");
@@ -209,12 +220,12 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
fc_pci->last_dma1_cur_pos = cur_pos; fc_pci->last_dma1_cur_pos = cur_pos;
fc_pci->count++; fc_pci->count++;
} else { } else {
deb_irq("isr for flexcop called, apparently without reason (%08x)\n",v.raw); deb_irq("isr for flexcop called, "
"apparently without reason (%08x)\n", v.raw);
ret = IRQ_NONE; ret = IRQ_NONE;
} }
spin_unlock_irqrestore(&fc_pci->irq_lock, flags); spin_unlock_irqrestore(&fc_pci->irq_lock, flags);
return ret; return ret;
} }
@@ -224,50 +235,46 @@ static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff)
if (onoff) { if (onoff) {
flexcop_dma_config(fc, &fc_pci->dma[0], FC_DMA_1); flexcop_dma_config(fc, &fc_pci->dma[0], FC_DMA_1);
flexcop_dma_config(fc, &fc_pci->dma[1], FC_DMA_2); flexcop_dma_config(fc, &fc_pci->dma[1], FC_DMA_2);
flexcop_dma_config_timer(fc, FC_DMA_1, 0); flexcop_dma_config_timer(fc, FC_DMA_1, 0);
flexcop_dma_xfer_control(fc, FC_DMA_1,
flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,1); FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1, 1);
deb_irq("DMA xfer enabled\n"); deb_irq("DMA xfer enabled\n");
fc_pci->last_dma1_cur_pos = 0; fc_pci->last_dma1_cur_pos = 0;
flexcop_dma_control_timer_irq(fc, FC_DMA_1, 1); flexcop_dma_control_timer_irq(fc, FC_DMA_1, 1);
deb_irq("IRQ enabled\n"); deb_irq("IRQ enabled\n");
fc_pci->count_prev = fc_pci->count; fc_pci->count_prev = fc_pci->count;
// fc_pci->active_dma1_addr = 0;
// flexcop_dma_control_size_irq(fc,FC_DMA_1,1);
} else { } else {
flexcop_dma_control_timer_irq(fc, FC_DMA_1, 0); flexcop_dma_control_timer_irq(fc, FC_DMA_1, 0);
deb_irq("IRQ disabled\n"); deb_irq("IRQ disabled\n");
// flexcop_dma_control_size_irq(fc,FC_DMA_1,0); flexcop_dma_xfer_control(fc, FC_DMA_1,
FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1, 0);
flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,0);
deb_irq("DMA xfer disabled\n"); deb_irq("DMA xfer disabled\n");
} }
return 0; return 0;
} }
static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci) static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci)
{ {
int ret; int ret;
if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0) ret = flexcop_dma_allocate(fc_pci->pdev, &fc_pci->dma[0],
FC_DEFAULT_DMA1_BUFSIZE);
if (ret != 0)
return ret; return ret;
if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) { ret = flexcop_dma_allocate(fc_pci->pdev, &fc_pci->dma[1],
FC_DEFAULT_DMA2_BUFSIZE);
if (ret != 0) {
flexcop_dma_free(&fc_pci->dma[0]); flexcop_dma_free(&fc_pci->dma[0]);
return ret; return ret;
} }
flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1); flexcop_sram_set_dest(fc_pci->fc_dev, FC_SRAM_DEST_MEDIA |
flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2); FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
flexcop_sram_set_dest(fc_pci->fc_dev, FC_SRAM_DEST_CAO |
FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
fc_pci->init_state |= FC_PCI_DMA_INIT; fc_pci->init_state |= FC_PCI_DMA_INIT;
return ret; return ret;
} }
@@ -290,12 +297,8 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
if ((ret = pci_enable_device(fc_pci->pdev)) != 0) if ((ret = pci_enable_device(fc_pci->pdev)) != 0)
return ret; return ret;
pci_set_master(fc_pci->pdev); pci_set_master(fc_pci->pdev);
/* enable interrupts */
// pci_write_config_dword(pdev, 0x6c, 0x8000);
if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0) if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0)
goto err_pci_disable_device; goto err_pci_disable_device;
@@ -338,8 +341,8 @@ static void flexcop_pci_exit(struct flexcop_pci *fc_pci)
fc_pci->init_state &= ~FC_PCI_INIT; fc_pci->init_state &= ~FC_PCI_INIT;
} }
static int flexcop_pci_probe(struct pci_dev *pdev,
static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct flexcop_device *fc; struct flexcop_device *fc;
struct flexcop_pci *fc_pci; struct flexcop_pci *fc_pci;
@@ -358,7 +361,6 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
fc->write_ibi_reg = flexcop_pci_write_ibi_reg; fc->write_ibi_reg = flexcop_pci_write_ibi_reg;
fc->i2c_request = flexcop_i2c_request; fc->i2c_request = flexcop_i2c_request;
fc->get_mac_addr = flexcop_eeprom_check_mac_addr; fc->get_mac_addr = flexcop_eeprom_check_mac_addr;
fc->stream_control = flexcop_pci_stream_control; fc->stream_control = flexcop_pci_stream_control;
if (enable_pid_filtering) if (enable_pid_filtering)
@@ -368,7 +370,6 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
fc->pid_filtering = enable_pid_filtering; fc->pid_filtering = enable_pid_filtering;
fc->bus_type = FC_PCI; fc->bus_type = FC_PCI;
fc->dev = &pdev->dev; fc->dev = &pdev->dev;
fc->owner = THIS_MODULE; fc->owner = THIS_MODULE;
@@ -389,8 +390,9 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
if (irq_chk_intv > 0) if (irq_chk_intv > 0)
schedule_delayed_work(&fc_pci->irq_check_work, schedule_delayed_work(&fc_pci->irq_check_work,
msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv)); msecs_to_jiffies(irq_chk_intv < 100 ?
100 :
irq_chk_intv));
return ret; return ret;
err_fc_exit: err_fc_exit:
@@ -420,7 +422,6 @@ static void flexcop_pci_remove(struct pci_dev *pdev)
static struct pci_device_id flexcop_pci_tbl[] = { static struct pci_device_id flexcop_pci_tbl[] = {
{ PCI_DEVICE(0x13d0, 0x2103) }, { PCI_DEVICE(0x13d0, 0x2103) },
/* { PCI_DEVICE(0x13d0, 0x2200) }, ? */
{ }, { },
}; };

View File

@@ -1,14 +1,11 @@
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
*
* flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII * flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII
* * see flexcop.c for copyright information
* see flexcop.c for copyright information.
*/ */
#ifndef __FLEXCOP_REG_H__ #ifndef __FLEXCOP_REG_H__
#define __FLEXCOP_REG_H__ #define __FLEXCOP_REG_H__
typedef enum { typedef enum {
FLEXCOP_UNK = 0, FLEXCOP_UNK = 0,
FLEXCOP_II, FLEXCOP_II,
@@ -18,13 +15,13 @@ typedef enum {
typedef enum { typedef enum {
FC_UNK = 0, FC_UNK = 0,
FC_AIR_DVB, FC_CABLE,
FC_AIR_DVBT,
FC_AIR_ATSC1, FC_AIR_ATSC1,
FC_AIR_ATSC2, FC_AIR_ATSC2,
FC_SKY,
FC_SKY_OLD,
FC_CABLE,
FC_AIR_ATSC3, FC_AIR_ATSC3,
FC_SKY_REV23,
FC_SKY_REV26,
FC_SKY_REV27, FC_SKY_REV27,
FC_SKY_REV28, FC_SKY_REV28,
} flexcop_device_type_t; } flexcop_device_type_t;

View File

@@ -1,13 +1,12 @@
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* * flexcop-sram.c - functions for controlling the SRAM
* flexcop-sram.c - functions for controlling the SRAM. * see flexcop.c for copyright information
*
* see flexcop.c for copyright information.
*/ */
#include "flexcop.h" #include "flexcop.h"
static void flexcop_sram_set_chip (struct flexcop_device *fc, flexcop_sram_type_t type) static void flexcop_sram_set_chip(struct flexcop_device *fc,
flexcop_sram_type_t type)
{ {
flexcop_set_ibi_value(wan_ctrl_reg_71c, sram_chip, type); flexcop_set_ibi_value(wan_ctrl_reg_71c, sram_chip, type);
} }
@@ -28,17 +27,16 @@ int flexcop_sram_init(struct flexcop_device *fc)
return 0; return 0;
} }
int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target) int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest,
flexcop_sram_dest_target_t target)
{ {
flexcop_ibi_value v; flexcop_ibi_value v;
v = fc->read_ibi_reg(fc, sram_dest_reg_714); v = fc->read_ibi_reg(fc, sram_dest_reg_714);
if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) { if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) {
err("SRAM destination target to available on FlexCopII(b)\n"); err("SRAM destination target to available on FlexCopII(b)\n");
return -EINVAL; return -EINVAL;
} }
deb_sram("sram dest: %x target: %x\n", dest, target); deb_sram("sram dest: %x target: %x\n", dest, target);
if (dest & FC_SRAM_DEST_NET) if (dest & FC_SRAM_DEST_NET)
@@ -154,14 +152,12 @@ static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len
else else
bank = 0x10000000; bank = 0x10000000;
} }
flex_sram_write(adapter, bank, addr & 0x7fff, buf, len); flex_sram_write(adapter, bank, addr & 0x7fff, buf, len);
} }
static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
{ {
u32 bank; u32 bank;
bank = 0; bank = 0;
if (adapter->dw_sram_type == 0x20000) { if (adapter->dw_sram_type == 0x20000) {
@@ -174,26 +170,22 @@ static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
else else
bank = 0x10000000; bank = 0x10000000;
} }
flex_sram_read(adapter, bank, addr & 0x7fff, buf, len); flex_sram_read(adapter, bank, addr & 0x7fff, buf, len);
} }
static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len) static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
{ {
u32 length; u32 length;
while (len != 0) { while (len != 0) {
length = len; length = len;
/* check if the address range belongs to the same
// check if the address range belongs to the same * 32K memory chip. If not, the data is read
// 32K memory chip. If not, the data is read from * from one chip at a time */
// one chip at a time.
if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) { if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
length = (((addr >> 0x0f) + 1) << 0x0f) - addr; length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
} }
sram_read_chunk(adapter, addr, buf, length); sram_read_chunk(adapter, addr, buf, length);
addr = addr + length; addr = addr + length;
buf = buf + length; buf = buf + length;
len = len - length; len = len - length;
@@ -203,19 +195,17 @@ static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len) static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
{ {
u32 length; u32 length;
while (len != 0) { while (len != 0) {
length = len; length = len;
// check if the address range belongs to the same /* check if the address range belongs to the same
// 32K memory chip. If not, the data is written to * 32K memory chip. If not, the data is
// one chip at a time. * written to one chip at a time */
if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) { if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
length = (((addr >> 0x0f) + 1) << 0x0f) - addr; length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
} }
sram_write_chunk(adapter, addr, buf, length); sram_write_chunk(adapter, addr, buf, length);
addr = addr + length; addr = addr + length;
buf = buf + length; buf = buf + length;
len = len - length; len = len - length;
@@ -224,39 +214,29 @@ static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
static void sram_set_size(struct adapter *adapter, u32 mask) static void sram_set_size(struct adapter *adapter, u32 mask)
{ {
write_reg_dw(adapter, 0x71c, (mask | (~0x30000 & read_reg_dw(adapter, 0x71c)))); write_reg_dw(adapter, 0x71c,
(mask | (~0x30000 & read_reg_dw(adapter, 0x71c))));
} }
static void sram_init(struct adapter *adapter) static void sram_init(struct adapter *adapter)
{ {
u32 tmp; u32 tmp;
tmp = read_reg_dw(adapter, 0x71c); tmp = read_reg_dw(adapter, 0x71c);
write_reg_dw(adapter, 0x71c, 1); write_reg_dw(adapter, 0x71c, 1);
if (read_reg_dw(adapter, 0x71c) != 0) { if (read_reg_dw(adapter, 0x71c) != 0) {
write_reg_dw(adapter, 0x71c, tmp); write_reg_dw(adapter, 0x71c, tmp);
adapter->dw_sram_type = tmp & 0x30000; adapter->dw_sram_type = tmp & 0x30000;
ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type); ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
} else { } else {
adapter->dw_sram_type = 0x10000; adapter->dw_sram_type = 0x10000;
ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type); ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
} }
/* return value is never used? */
/* return adapter->dw_sram_type; */
} }
static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr) static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
{ {
u8 tmp1, tmp2; u8 tmp1, tmp2;
dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr); dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr);
sram_set_size(adapter, mask); sram_set_size(adapter, mask);
@@ -269,7 +249,6 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
sram_write(adapter, addr + 4, &tmp1, 1); sram_write(adapter, addr + 4, &tmp1, 1);
tmp2 = 0; tmp2 = 0;
mdelay(20); mdelay(20);
sram_read(adapter, addr, &tmp2, 1); sram_read(adapter, addr, &tmp2, 1);
@@ -287,7 +266,6 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
sram_write(adapter, addr + 4, &tmp1, 1); sram_write(adapter, addr + 4, &tmp1, 1);
tmp2 = 0; tmp2 = 0;
mdelay(20); mdelay(20);
sram_read(adapter, addr, &tmp2, 1); sram_read(adapter, addr, &tmp2, 1);
@@ -297,20 +275,18 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
if (tmp2 != 0x5a) if (tmp2 != 0x5a)
return 0; return 0;
return 1; return 1;
} }
static u32 sram_length(struct adapter *adapter) static u32 sram_length(struct adapter *adapter)
{ {
if (adapter->dw_sram_type == 0x10000) if (adapter->dw_sram_type == 0x10000)
return 32768; // 32K return 32768; /* 32K */
if (adapter->dw_sram_type == 0x00000) if (adapter->dw_sram_type == 0x00000)
return 65536; // 64K return 65536; /* 64K */
if (adapter->dw_sram_type == 0x20000) if (adapter->dw_sram_type == 0x20000)
return 131072; // 128K return 131072; /* 128K */
return 32768; /* 32K */
return 32768; // 32K
} }
/* FlexcopII can work with 32K, 64K or 128K of external SRAM memory. /* FlexcopII can work with 32K, 64K or 128K of external SRAM memory.
@@ -324,24 +300,18 @@ static u32 sram_length(struct adapter *adapter)
bank 0 covers addresses 0x00000-0x07fff bank 0 covers addresses 0x00000-0x07fff
bank 1 covers addresses 0x08000-0x0ffff bank 1 covers addresses 0x08000-0x0ffff
bank 2 covers addresses 0x10000-0x17fff bank 2 covers addresses 0x10000-0x17fff
bank 3 covers addresses 0x18000-0x1ffff bank 3 covers addresses 0x18000-0x1ffff */
*/
static int flexcop_sram_detect(struct flexcop_device *fc) static int flexcop_sram_detect(struct flexcop_device *fc)
{ {
flexcop_ibi_value r208, r71c_0, vr71c_1; flexcop_ibi_value r208, r71c_0, vr71c_1;
r208 = fc->read_ibi_reg(fc, ctrl_208); r208 = fc->read_ibi_reg(fc, ctrl_208);
fc->write_ibi_reg(fc, ctrl_208, ibi_zero); fc->write_ibi_reg(fc, ctrl_208, ibi_zero);
r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c); r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c);
write_reg_dw(adapter, 0x71c, 1); write_reg_dw(adapter, 0x71c, 1);
tmp3 = read_reg_dw(adapter, 0x71c); tmp3 = read_reg_dw(adapter, 0x71c);
dprintk("%s: tmp3 = %x\n", __func__, tmp3); dprintk("%s: tmp3 = %x\n", __func__, tmp3);
write_reg_dw(adapter, 0x71c, tmp2); write_reg_dw(adapter, 0x71c, tmp2);
// check for internal SRAM ??? // check for internal SRAM ???
@@ -350,9 +320,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
sram_set_size(adapter, 0x10000); sram_set_size(adapter, 0x10000);
sram_init(adapter); sram_init(adapter);
write_reg_dw(adapter, 0x208, tmp); write_reg_dw(adapter, 0x208, tmp);
dprintk("%s: sram size = 32K\n", __func__); dprintk("%s: sram size = 32K\n", __func__);
return 32; return 32;
} }
@@ -360,9 +328,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
sram_set_size(adapter, 0x20000); sram_set_size(adapter, 0x20000);
sram_init(adapter); sram_init(adapter);
write_reg_dw(adapter, 0x208, tmp); write_reg_dw(adapter, 0x208, tmp);
dprintk("%s: sram size = 128K\n", __func__); dprintk("%s: sram size = 128K\n", __func__);
return 128; return 128;
} }
@@ -370,9 +336,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
sram_set_size(adapter, 0x00000); sram_set_size(adapter, 0x00000);
sram_init(adapter); sram_init(adapter);
write_reg_dw(adapter, 0x208, tmp); write_reg_dw(adapter, 0x208, tmp);
dprintk("%s: sram size = 64K\n", __func__); dprintk("%s: sram size = 64K\n", __func__);
return 64; return 64;
} }
@@ -380,18 +344,14 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
sram_set_size(adapter, 0x10000); sram_set_size(adapter, 0x10000);
sram_init(adapter); sram_init(adapter);
write_reg_dw(adapter, 0x208, tmp); write_reg_dw(adapter, 0x208, tmp);
dprintk("%s: sram size = 32K\n", __func__); dprintk("%s: sram size = 32K\n", __func__);
return 32; return 32;
} }
sram_set_size(adapter, 0x10000); sram_set_size(adapter, 0x10000);
sram_init(adapter); sram_init(adapter);
write_reg_dw(adapter, 0x208, tmp); write_reg_dw(adapter, 0x208, tmp);
dprintk("%s: SRAM detection failed. Set to 32K \n", __func__); dprintk("%s: SRAM detection failed. Set to 32K \n", __func__);
return 0; return 0;
} }

View File

@@ -1,11 +1,8 @@
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* * flexcop-usb.c - covers the USB part
* flexcop-usb.c - covers the USB part. * see flexcop.c for copyright information
*
* see flexcop.c for copyright information.
*/ */
#define FC_LOG_PREFIX "flexcop_usb" #define FC_LOG_PREFIX "flexcop_usb"
#include "flexcop-usb.h" #include "flexcop-usb.h"
#include "flexcop-common.h" #include "flexcop-common.h"
@@ -18,12 +15,14 @@
/* debug */ /* debug */
#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
#define dprintk(level,args...) \ #define dprintk(level,args...) \
do { if ((debug & level)) { printk(args); } } while (0) do { if ((debug & level)) printk(args); } while (0)
#define debug_dump(b,l,method) {\
#define debug_dump(b, l, method) do {\
int i; \ int i; \
for (i = 0; i < l; i++) method("%02x ", b[i]); \ for (i = 0; i < l; i++) \
method("%02x ", b[i]); \
method("\n"); \ method("\n"); \
} } while (0)
#define DEBSTATUS "" #define DEBSTATUS ""
#else #else
@@ -34,7 +33,8 @@
static int debug; static int debug;
module_param(debug, int, 0644); module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS); MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,"
"ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS);
#undef DEBSTATUS #undef DEBSTATUS
#define deb_info(args...) dprintk(0x01, args) #define deb_info(args...) dprintk(0x01, args)
@@ -45,15 +45,17 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4,i2c=8,v8mem=16
/* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits /* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits
* in the IBI address, to make the V8 code simpler. * in the IBI address, to make the V8 code simpler.
* PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (these are the six bits used) * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (the six bits used)
* in general: 0000 0HHH 000L LL00 * in general: 0000 0HHH 000L LL00
* IBI ADDRESS FORMAT: RHHH BLLL * IBI ADDRESS FORMAT: RHHH BLLL
* *
* where R is the read(1)/write(0) bit, B is the busy bit * where R is the read(1)/write(0) bit, B is the busy bit
* and HHH and LLL are the two sets of three bits from the PCI address. * and HHH and LLL are the two sets of three bits from the PCI address.
*/ */
#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70)) #define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) \
#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4)) (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70))
#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) \
(((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
/* /*
* DKT 020228 * DKT 020228
@@ -69,7 +71,8 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI,
struct flexcop_usb *fc_usb = fc->bus_specific; struct flexcop_usb *fc_usb = fc->bus_specific;
u8 request = read ? B2C2_USB_READ_REG : B2C2_USB_WRITE_REG; u8 request = read ? B2C2_USB_READ_REG : B2C2_USB_WRITE_REG;
u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR; u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | (read ? 0x80 : 0); u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
(read ? 0x80 : 0);
int len = usb_control_msg(fc_usb->udev, int len = usb_control_msg(fc_usb->udev,
read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT, read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
@@ -82,13 +85,12 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI,
B2C2_WAIT_FOR_OPERATION_RDW * HZ); B2C2_WAIT_FOR_OPERATION_RDW * HZ);
if (len != sizeof(u32)) { if (len != sizeof(u32)) {
err("error while %s dword from %d (%d).",read ? "reading" : "writing", err("error while %s dword from %d (%d).", read ? "reading" :
wAddress,wRegOffsPCI); "writing", wAddress, wRegOffsPCI);
return -EIO; return -EIO;
} }
return 0; return 0;
} }
/* /*
* DKT 010817 - add support for V8 memory read/write and flash update * DKT 010817 - add support for V8 memory read/write and flash update
*/ */
@@ -96,31 +98,26 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
flexcop_usb_request_t req, u8 page, u16 wAddress, flexcop_usb_request_t req, u8 page, u16 wAddress,
u8 *pbBuffer, u32 buflen) u8 *pbBuffer, u32 buflen)
{ {
// u8 dwRequestType;
u8 request_type = USB_TYPE_VENDOR; u8 request_type = USB_TYPE_VENDOR;
u16 wIndex; u16 wIndex;
int nWaitTime, pipe, len; int nWaitTime, pipe, len;
wIndex = page << 8; wIndex = page << 8;
switch (req) { switch (req) {
case B2C2_USB_READ_V8_MEM: case B2C2_USB_READ_V8_MEM:
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
request_type |= USB_DIR_IN; request_type |= USB_DIR_IN;
// dwRequestType = (u8) RTYPE_READ_V8_MEMORY;
pipe = B2C2_USB_CTRL_PIPE_IN; pipe = B2C2_USB_CTRL_PIPE_IN;
break; break;
case B2C2_USB_WRITE_V8_MEM: case B2C2_USB_WRITE_V8_MEM:
wIndex |= pbBuffer[0]; wIndex |= pbBuffer[0];
request_type |= USB_DIR_OUT; request_type |= USB_DIR_OUT;
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE; nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
// dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY;
pipe = B2C2_USB_CTRL_PIPE_OUT; pipe = B2C2_USB_CTRL_PIPE_OUT;
break; break;
case B2C2_USB_FLASH_BLOCK: case B2C2_USB_FLASH_BLOCK:
request_type |= USB_DIR_OUT; request_type |= USB_DIR_OUT;
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH; nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
// dwRequestType = (u8) RTYPE_WRITE_V8_FLASH;
pipe = B2C2_USB_CTRL_PIPE_OUT; pipe = B2C2_USB_CTRL_PIPE_OUT;
break; break;
default: default:
@@ -140,7 +137,6 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
nWaitTime * HZ); nWaitTime * HZ);
debug_dump(pbBuffer, len, deb_v8); debug_dump(pbBuffer, len, deb_v8);
return len == buflen ? 0 : -EIO; return len == buflen ? 0 : -EIO;
} }
@@ -148,30 +144,45 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \ ((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \
? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK))) ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)))
static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,flexcop_usb_request_t req, static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,
flexcop_usb_mem_page_t page_start, u32 addr, int extended, u8 *buf, u32 len) flexcop_usb_request_t req, flexcop_usb_mem_page_t page_start,
u32 addr, int extended, u8 *buf, u32 len)
{ {
int i,ret = 0; int i,ret = 0;
u16 wMax; u16 wMax;
u32 pagechunk = 0; u32 pagechunk = 0;
switch(req) { switch(req) {
case B2C2_USB_READ_V8_MEM: wMax = USB_MEM_READ_MAX; break; case B2C2_USB_READ_V8_MEM:
case B2C2_USB_WRITE_V8_MEM: wMax = USB_MEM_WRITE_MAX; break; wMax = USB_MEM_READ_MAX;
case B2C2_USB_FLASH_BLOCK: wMax = USB_FLASH_MAX; break; break;
case B2C2_USB_WRITE_V8_MEM:
wMax = USB_MEM_WRITE_MAX;
break;
case B2C2_USB_FLASH_BLOCK:
wMax = USB_FLASH_MAX;
break;
default: default:
return -EINVAL; return -EINVAL;
break; break;
} }
for (i = 0; i < len;) { for (i = 0; i < len;) {
pagechunk = wMax < bytes_left_to_read_on_page(addr,len) ? wMax : bytes_left_to_read_on_page(addr,len); pagechunk =
deb_info("%x\n",(addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended)); wMax < bytes_left_to_read_on_page(addr, len) ?
if ((ret = flexcop_usb_v8_memory_req(fc_usb,req, wMax :
page_start + (addr / V8_MEMORY_PAGE_SIZE), /* actual page */ bytes_left_to_read_on_page(addr, len);
(addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended), deb_info("%x\n",
&buf[i],pagechunk)) < 0) (addr & V8_MEMORY_PAGE_MASK) |
return ret; (V8_MEMORY_EXTENDED*extended));
ret = flexcop_usb_v8_memory_req(fc_usb, req,
page_start + (addr / V8_MEMORY_PAGE_SIZE),
(addr & V8_MEMORY_PAGE_MASK) |
(V8_MEMORY_EXTENDED*extended),
&buf[i], pagechunk);
if (ret < 0)
return ret;
addr += pagechunk; addr += pagechunk;
len -= pagechunk; len -= pagechunk;
} }
@@ -181,7 +192,8 @@ static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,flexcop_usb_request
static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended) static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
{ {
return flexcop_usb_memory_req(fc->bus_specific, B2C2_USB_READ_V8_MEM, return flexcop_usb_memory_req(fc->bus_specific, B2C2_USB_READ_V8_MEM,
V8_MEMORY_PAGE_FLASH,0x1f010,1,fc->dvb_adapter.proposed_mac,6); V8_MEMORY_PAGE_FLASH, 0x1f010, 1,
fc->dvb_adapter.proposed_mac, 6);
} }
#if 0 #if 0
@@ -191,11 +203,8 @@ static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
{ {
u16 wValue; u16 wValue;
u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR; u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
// u8 dwRequestType = (u8) RTYPE_GENERIC,
int nWaitTime = 2, int nWaitTime = 2,
pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len;
len;
wValue = (func << 8) | extra; wValue = (func << 8) | extra;
len = usb_control_msg(fc_usb->udev,pipe, len = usb_control_msg(fc_usb->udev,pipe,
@@ -218,7 +227,6 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
struct flexcop_usb *fc_usb = i2c->fc->bus_specific; struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
u16 wValue, wIndex; u16 wValue, wIndex;
int nWaitTime,pipe,len; int nWaitTime,pipe,len;
// u8 dwRequestType;
u8 request_type = USB_TYPE_VENDOR; u8 request_type = USB_TYPE_VENDOR;
switch (func) { switch (func) {
@@ -229,14 +237,12 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
case USB_FUNC_I2C_CHECKWRITE: case USB_FUNC_I2C_CHECKWRITE:
pipe = B2C2_USB_CTRL_PIPE_OUT; pipe = B2C2_USB_CTRL_PIPE_OUT;
nWaitTime = 2; nWaitTime = 2;
// dwRequestType = (u8) RTYPE_GENERIC;
request_type |= USB_DIR_OUT; request_type |= USB_DIR_OUT;
break; break;
case USB_FUNC_I2C_READ: case USB_FUNC_I2C_READ:
case USB_FUNC_I2C_REPEATREAD: case USB_FUNC_I2C_REPEATREAD:
pipe = B2C2_USB_CTRL_PIPE_IN; pipe = B2C2_USB_CTRL_PIPE_IN;
nWaitTime = 2; nWaitTime = 2;
// dwRequestType = (u8) RTYPE_GENERIC;
request_type |= USB_DIR_IN; request_type |= USB_DIR_IN;
break; break;
default: default:
@@ -246,8 +252,10 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
wValue = (func << 8) | (i2c->port << 4); wValue = (func << 8) | (i2c->port << 4);
wIndex = (chipaddr << 8 ) | addr; wIndex = (chipaddr << 8 ) | addr;
deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req, deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",
wValue & 0xff, wValue >> 8, wIndex & 0xff, wIndex >> 8); func, request_type, req,
wValue & 0xff, wValue >> 8,
wIndex & 0xff, wIndex >> 8);
len = usb_control_msg(fc_usb->udev,pipe, len = usb_control_msg(fc_usb->udev,pipe,
req, req,
@@ -257,12 +265,13 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
buf, buf,
buflen, buflen,
nWaitTime * HZ); nWaitTime * HZ);
return len == buflen ? 0 : -EREMOTEIO; return len == buflen ? 0 : -EREMOTEIO;
} }
/* actual bus specific access functions, make sure prototype are/will be equal to pci */ /* actual bus specific access functions,
static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg) make sure prototype are/will be equal to pci */
static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc,
flexcop_ibi_register reg)
{ {
flexcop_ibi_value val; flexcop_ibi_value val;
val.raw = 0; val.raw = 0;
@@ -270,7 +279,8 @@ static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc, fle
return val; return val;
} }
static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg, flexcop_ibi_value val) static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc,
flexcop_ibi_register reg, flexcop_ibi_value val)
{ {
return flexcop_usb_readwrite_dw(fc, reg, &val.raw, 0); return flexcop_usb_readwrite_dw(fc, reg, &val.raw, 0);
} }
@@ -286,15 +296,18 @@ static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c,
USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len); USB_FUNC_I2C_WRITE, chipaddr, addr, buf, len);
} }
static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length) static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb,
u8 *buffer, int buffer_length)
{ {
u8 *b; u8 *b;
int l; int l;
deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", fc_usb->tmp_buffer_length, buffer_length); deb_ts("tmp_buffer_length=%d, buffer_length=%d\n",
fc_usb->tmp_buffer_length, buffer_length);
if (fc_usb->tmp_buffer_length > 0) { if (fc_usb->tmp_buffer_length > 0) {
memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, buffer_length); memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer,
buffer_length);
fc_usb->tmp_buffer_length += buffer_length; fc_usb->tmp_buffer_length += buffer_length;
b = fc_usb->tmp_buffer; b = fc_usb->tmp_buffer;
l = fc_usb->tmp_buffer_length; l = fc_usb->tmp_buffer_length;
@@ -304,14 +317,17 @@ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, in
} }
while (l >= 190) { while (l >= 190) {
if (*b == 0xff) if (*b == 0xff) {
switch (*(b+1) & 0x03) { switch (*(b+1) & 0x03) {
case 0x01: /* media packet */ case 0x01: /* media packet */
if (*(b+2) == 0x47) if (*(b+2) == 0x47)
flexcop_pass_dmx_packets(fc_usb->fc_dev, b+2, 1); flexcop_pass_dmx_packets(
fc_usb->fc_dev, b+2, 1);
else else
deb_ts("not ts packet %02x %02x %02x %02x \n", *(b+2), *(b+3), *(b+4), *(b+5) ); deb_ts(
"not ts packet %02x %02x %02x %02x \n",
*(b+2), *(b+3),
*(b+4), *(b+5));
b += 190; b += 190;
l -= 190; l -= 190;
break; break;
@@ -320,7 +336,7 @@ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, in
l = 0; l = 0;
break; break;
} }
else { } else {
deb_ts("wrong header\n"); deb_ts("wrong header\n");
l = 0; l = 0;
} }
@@ -337,23 +353,26 @@ static void flexcop_usb_urb_complete(struct urb *urb)
int i; int i;
if (urb->actual_length > 0) if (urb->actual_length > 0)
deb_ts("urb completed, bufsize: %d actlen; %d\n",urb->transfer_buffer_length, urb->actual_length); deb_ts("urb completed, bufsize: %d actlen; %d\n",
urb->transfer_buffer_length, urb->actual_length);
for (i = 0; i < urb->number_of_packets; i++) { for (i = 0; i < urb->number_of_packets; i++) {
if (urb->iso_frame_desc[i].status < 0) { if (urb->iso_frame_desc[i].status < 0) {
err("iso frame descriptor %d has an error: %d\n",i,urb->iso_frame_desc[i].status); err("iso frame descriptor %d has an error: %d\n", i,
urb->iso_frame_desc[i].status);
} else } else
if (urb->iso_frame_desc[i].actual_length > 0) { if (urb->iso_frame_desc[i].actual_length > 0) {
deb_ts("passed %d bytes to the demux\n",urb->iso_frame_desc[i].actual_length); deb_ts("passed %d bytes to the demux\n",
urb->iso_frame_desc[i].actual_length);
flexcop_usb_process_frame(fc_usb, flexcop_usb_process_frame(fc_usb,
urb->transfer_buffer + urb->iso_frame_desc[i].offset, urb->transfer_buffer +
urb->iso_frame_desc[i].offset,
urb->iso_frame_desc[i].actual_length); urb->iso_frame_desc[i].actual_length);
} }
urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].status = 0;
urb->iso_frame_desc[i].actual_length = 0; urb->iso_frame_desc[i].actual_length = 0;
} }
usb_submit_urb(urb,GFP_ATOMIC); usb_submit_urb(urb,GFP_ATOMIC);
} }
@@ -374,35 +393,47 @@ static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb)
} }
if (fc_usb->iso_buffer != NULL) if (fc_usb->iso_buffer != NULL)
pci_free_consistent(NULL,fc_usb->buffer_size, fc_usb->iso_buffer, fc_usb->dma_addr); pci_free_consistent(NULL,
fc_usb->buffer_size, fc_usb->iso_buffer,
fc_usb->dma_addr);
} }
static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb) static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
{ {
u16 frame_size = le16_to_cpu(fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize); u16 frame_size = le16_to_cpu(
int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret; fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO *
frame_size, i, j, ret;
int buffer_offset = 0; int buffer_offset = 0;
deb_ts("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n", deb_ts("creating %d iso-urbs with %d frames "
B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size,bufsize); "each of %d bytes size = %d.\n", B2C2_USB_NUM_ISO_URB,
B2C2_USB_FRAMES_PER_ISO, frame_size, bufsize);
fc_usb->iso_buffer = pci_alloc_consistent(NULL,bufsize,&fc_usb->dma_addr); fc_usb->iso_buffer = pci_alloc_consistent(NULL,
bufsize, &fc_usb->dma_addr);
if (fc_usb->iso_buffer == NULL) if (fc_usb->iso_buffer == NULL)
return -ENOMEM; return -ENOMEM;
memset(fc_usb->iso_buffer, 0, bufsize); memset(fc_usb->iso_buffer, 0, bufsize);
fc_usb->buffer_size = bufsize; fc_usb->buffer_size = bufsize;
/* creating iso urbs */ /* creating iso urbs */
for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
if (!(fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) { fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,
GFP_ATOMIC);
if (fc_usb->iso_urb[i] == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto urb_error; goto urb_error;
} }
}
/* initialising and submitting iso urbs */ /* initialising and submitting iso urbs */
for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) { for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
int frame_offset = 0; int frame_offset = 0;
struct urb *urb = fc_usb->iso_urb[i]; struct urb *urb = fc_usb->iso_urb[i];
deb_ts("initializing and submitting urb no. %d (buf_offset: %d).\n",i,buffer_offset); deb_ts("initializing and submitting urb no. %d "
"(buf_offset: %d).\n", i, buffer_offset);
urb->dev = fc_usb->udev; urb->dev = fc_usb->udev;
urb->context = fc_usb; urb->context = fc_usb;
@@ -416,7 +447,8 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO; buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO;
for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) { for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) {
deb_ts("urb no: %d, frame: %d, frame_offset: %d\n",i,j,frame_offset); deb_ts("urb no: %d, frame: %d, frame_offset: %d\n",
i, j, frame_offset);
urb->iso_frame_desc[j].offset = frame_offset; urb->iso_frame_desc[j].offset = frame_offset;
urb->iso_frame_desc[j].length = frame_size; urb->iso_frame_desc[j].length = frame_size;
frame_offset += frame_size; frame_offset += frame_size;
@@ -430,12 +462,11 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
} }
/* SRAM */ /* SRAM */
flexcop_sram_set_dest(fc_usb->fc_dev, FC_SRAM_DEST_MEDIA |
flexcop_sram_set_dest(fc_usb->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET | FC_SRAM_DEST_NET | FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI,
FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_WAN_USB); FC_SRAM_DEST_TARGET_WAN_USB);
flexcop_wan_set_speed(fc_usb->fc_dev, FC_WAN_SPEED_8MBITS); flexcop_wan_set_speed(fc_usb->fc_dev, FC_WAN_SPEED_8MBITS);
flexcop_sram_ctrl(fc_usb->fc_dev, 1, 1, 1); flexcop_sram_ctrl(fc_usb->fc_dev, 1, 1, 1);
return 0; return 0;
urb_error: urb_error:
@@ -449,7 +480,7 @@ static int flexcop_usb_init(struct flexcop_usb *fc_usb)
usb_set_interface(fc_usb->udev,0,1); usb_set_interface(fc_usb->udev,0,1);
switch (fc_usb->udev->speed) { switch (fc_usb->udev->speed) {
case USB_SPEED_LOW: case USB_SPEED_LOW:
err("cannot handle USB speed because it is to sLOW."); err("cannot handle USB speed because it is too slow.");
return -ENODEV; return -ENODEV;
break; break;
case USB_SPEED_FULL: case USB_SPEED_FULL:
@@ -460,7 +491,7 @@ static int flexcop_usb_init(struct flexcop_usb *fc_usb)
break; break;
case USB_SPEED_UNKNOWN: /* fall through */ case USB_SPEED_UNKNOWN: /* fall through */
default: default:
err("cannot handle USB speed because it is unkown."); err("cannot handle USB speed because it is unknown.");
return -ENODEV; return -ENODEV;
} }
usb_set_intfdata(fc_usb->uintf, fc_usb); usb_set_intfdata(fc_usb->uintf, fc_usb);
@@ -560,7 +591,6 @@ static int __init flexcop_usb_module_init(void)
err("usb_register failed. (%d)", result); err("usb_register failed. (%d)", result);
return result; return result;
} }
return 0; return 0;
} }

View File

@@ -1,3 +1,8 @@
/*
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* flexcop-usb.h - header file for the USB part
* see flexcop.c for copyright information
*/
#ifndef __FLEXCOP_USB_H_INCLUDED__ #ifndef __FLEXCOP_USB_H_INCLUDED__
#define __FLEXCOP_USB_H_INCLUDED__ #define __FLEXCOP_USB_H_INCLUDED__
@@ -18,8 +23,8 @@ struct flexcop_usb {
u8 *iso_buffer; u8 *iso_buffer;
int buffer_size; int buffer_size;
dma_addr_t dma_addr; dma_addr_t dma_addr;
struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
struct flexcop_device *fc_dev; struct flexcop_device *fc_dev;
u8 tmp_buffer[1023+190]; u8 tmp_buffer[1023+190];
@@ -30,14 +35,6 @@ struct flexcop_usb {
/* request types TODO What is its use?*/ /* request types TODO What is its use?*/
typedef enum { typedef enum {
/* something is wrong with this part
RTYPE_READ_DW = (1 << 6),
RTYPE_WRITE_DW_1 = (3 << 6),
RTYPE_READ_V8_MEMORY = (6 << 6),
RTYPE_WRITE_V8_MEMORY = (7 << 6),
RTYPE_WRITE_V8_FLASH = (8 << 6),
RTYPE_GENERIC = (9 << 6),
*/
} flexcop_usb_request_type_t; } flexcop_usb_request_type_t;
#endif #endif
@@ -47,7 +44,6 @@ typedef enum {
B2C2_USB_READ_V8_MEM = 0x05, B2C2_USB_READ_V8_MEM = 0x05,
B2C2_USB_READ_REG = 0x08, B2C2_USB_READ_REG = 0x08,
B2C2_USB_WRITE_REG = 0x0A, B2C2_USB_WRITE_REG = 0x0A,
/* B2C2_USB_WRITEREGLO = 0x0A, */
B2C2_USB_WRITEREGHI = 0x0B, B2C2_USB_WRITEREGHI = 0x0B,
B2C2_USB_FLASH_BLOCK = 0x10, B2C2_USB_FLASH_BLOCK = 0x10,
B2C2_USB_I2C_REQUEST = 0x11, B2C2_USB_I2C_REQUEST = 0x11,
@@ -67,10 +63,8 @@ typedef enum {
USB_FUNC_I2C_CHECKRESULT = 0x08, USB_FUNC_I2C_CHECKRESULT = 0x08,
} flexcop_usb_i2c_function_t; } flexcop_usb_i2c_function_t;
/* /* function definition for UTILITY request 0x12
* function definition for UTILITY request 0x12 * DKT 020304 - new utility function */
* DKT 020304 - new utility function
*/
typedef enum { typedef enum {
UTILITY_SET_FILTER = 0x01, UTILITY_SET_FILTER = 0x01,
UTILITY_DATA_ENABLE = 0x02, UTILITY_DATA_ENABLE = 0x02,
@@ -92,13 +86,13 @@ typedef enum {
UTILITY_SRAM_TESTVERIFY = 0x16, UTILITY_SRAM_TESTVERIFY = 0x16,
} flexcop_usb_utility_function_t; } flexcop_usb_utility_function_t;
#define B2C2_WAIT_FOR_OPERATION_RW 1*HZ /* 1 s */ #define B2C2_WAIT_FOR_OPERATION_RW (1*HZ)
#define B2C2_WAIT_FOR_OPERATION_RDW 3*HZ /* 3 s */ #define B2C2_WAIT_FOR_OPERATION_RDW (3*HZ)
#define B2C2_WAIT_FOR_OPERATION_WDW 1*HZ /* 1 s */ #define B2C2_WAIT_FOR_OPERATION_WDW (1*HZ)
#define B2C2_WAIT_FOR_OPERATION_V8READ 3*HZ /* 3 s */ #define B2C2_WAIT_FOR_OPERATION_V8READ (3*HZ)
#define B2C2_WAIT_FOR_OPERATION_V8WRITE 3*HZ /* 3 s */ #define B2C2_WAIT_FOR_OPERATION_V8WRITE (3*HZ)
#define B2C2_WAIT_FOR_OPERATION_V8FLASH 3*HZ /* 3 s */ #define B2C2_WAIT_FOR_OPERATION_V8FLASH (3*HZ)
typedef enum { typedef enum {
V8_MEMORY_PAGE_DVB_CI = 0x20, V8_MEMORY_PAGE_DVB_CI = 0x20,
@@ -108,12 +102,10 @@ typedef enum {
} flexcop_usb_mem_page_t; } flexcop_usb_mem_page_t;
#define V8_MEMORY_EXTENDED (1 << 15) #define V8_MEMORY_EXTENDED (1 << 15)
#define USB_MEM_READ_MAX 32 #define USB_MEM_READ_MAX 32
#define USB_MEM_WRITE_MAX 1 #define USB_MEM_WRITE_MAX 1
#define USB_FLASH_MAX 8 #define USB_FLASH_MAX 8
#define V8_MEMORY_PAGE_SIZE 0x8000 /* 32K */
#define V8_MEMORY_PAGE_SIZE 0x8000 // 32K
#define V8_MEMORY_PAGE_MASK 0x7FFF #define V8_MEMORY_PAGE_MASK 0x7FFF
#endif #endif

View File

@@ -1,22 +1,20 @@
/* /*
* flexcop.c - driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* * flexcop.c - main module part
* Copyright (C) 2004-5 Patrick Boettcher <patrick.boettcher@desy.de> * Copyright (C) 2004-9 Patrick Boettcher <patrick.boettcher@desy.de>
* * based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
* based on the skystar2-driver
* Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
* *
* Acknowledgements: * Acknowledgements:
* John Jurrius from BBTI, Inc. for extensive support with * John Jurrius from BBTI, Inc. for extensive support
* code examples and data books * with code examples and data books
*
* Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting) * Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting)
* *
* Contributions to the skystar2-driver have been done by * Contributions to the skystar2-driver have been done by
* Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes) * Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes)
* Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code) * Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code)
* Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac filtering) * Uwe Bugla, uwe.bugla at gmx.de (doing tests, restyling code, writing docu)
* * Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac
* filtering)
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
@@ -46,7 +44,10 @@
int b2c2_flexcop_debug; int b2c2_flexcop_debug;
module_param_named(debug, b2c2_flexcop_debug, int, 0644); module_param_named(debug, b2c2_flexcop_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))." DEBSTATUS); MODULE_PARM_DESC(debug,
"set debug level (1=info,2=tuner,4=i2c,8=ts,"
"16=sram,32=reg (|-able))."
DEBSTATUS);
#undef DEBSTATUS #undef DEBSTATUS
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
@@ -77,11 +78,10 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
} }
fc->dvb_adapter.priv = fc; fc->dvb_adapter.priv = fc;
fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING
| DMX_MEMORY_BASED_FILTERING);
fc->demux.priv = fc; fc->demux.priv = fc;
fc->demux.filternum = fc->demux.feednum = FC_MAX_FEED; fc->demux.filternum = fc->demux.feednum = FC_MAX_FEED;
fc->demux.start_feed = flexcop_dvb_start_feed; fc->demux.start_feed = flexcop_dvb_start_feed;
fc->demux.stop_feed = flexcop_dvb_stop_feed; fc->demux.stop_feed = flexcop_dvb_stop_feed;
fc->demux.write_to_decoder = NULL; fc->demux.write_to_decoder = NULL;
@@ -141,12 +141,13 @@ static void flexcop_dvb_exit(struct flexcop_device *fc)
dvb_net_release(&fc->dvbnet); dvb_net_release(&fc->dvbnet);
fc->demux.dmx.close(&fc->demux.dmx); fc->demux.dmx.close(&fc->demux.dmx);
fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend); fc->demux.dmx.remove_frontend(&fc->demux.dmx,
fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend); &fc->mem_frontend);
fc->demux.dmx.remove_frontend(&fc->demux.dmx,
&fc->hw_frontend);
dvb_dmxdev_release(&fc->dmxdev); dvb_dmxdev_release(&fc->dmxdev);
dvb_dmx_release(&fc->demux); dvb_dmx_release(&fc->demux);
dvb_unregister_adapter(&fc->dvb_adapter); dvb_unregister_adapter(&fc->dvb_adapter);
deb_info("deinitialized dvb stuff\n"); deb_info("deinitialized dvb stuff\n");
} }
fc->init_state &= ~FC_STATE_DVB_INIT; fc->init_state &= ~FC_STATE_DVB_INIT;
@@ -183,9 +184,7 @@ static void flexcop_reset(struct flexcop_device *fc)
v210.sw_reset_210.reset_block_600 = 1; v210.sw_reset_210.reset_block_600 = 1;
v210.sw_reset_210.reset_block_700 = 1; v210.sw_reset_210.reset_block_700 = 1;
v210.sw_reset_210.Block_reset_enable = 0xb2; v210.sw_reset_210.Block_reset_enable = 0xb2;
v210.sw_reset_210.Special_controls = 0xc259; v210.sw_reset_210.Special_controls = 0xc259;
fc->write_ibi_reg(fc,sw_reset_210,v210); fc->write_ibi_reg(fc,sw_reset_210,v210);
msleep(1); msleep(1);
@@ -205,21 +204,20 @@ void flexcop_reset_block_300(struct flexcop_device *fc)
v210 = fc->read_ibi_reg(fc, sw_reset_210); v210 = fc->read_ibi_reg(fc, sw_reset_210);
deb_rdump("208: %08x, 210: %08x\n", v208_save.raw, v210.raw); deb_rdump("208: %08x, 210: %08x\n", v208_save.raw, v210.raw);
fc->write_ibi_reg(fc,ctrl_208,ibi_zero); fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
v210.sw_reset_210.reset_block_300 = 1; v210.sw_reset_210.reset_block_300 = 1;
v210.sw_reset_210.Block_reset_enable = 0xb2; v210.sw_reset_210.Block_reset_enable = 0xb2;
fc->write_ibi_reg(fc,sw_reset_210,v210); fc->write_ibi_reg(fc,sw_reset_210,v210);
udelay(1000);
fc->write_ibi_reg(fc,ctrl_208,v208_save); fc->write_ibi_reg(fc,ctrl_208,v208_save);
} }
struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len) struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
{ {
void *bus; void *bus;
struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device), GFP_KERNEL); struct flexcop_device *fc = kzalloc(sizeof(struct flexcop_device),
GFP_KERNEL);
if (!fc) { if (!fc) {
err("no memory"); err("no memory");
return NULL; return NULL;
@@ -254,7 +252,6 @@ int flexcop_device_initialize(struct flexcop_device *fc)
flexcop_determine_revision(fc); flexcop_determine_revision(fc);
flexcop_sram_init(fc); flexcop_sram_init(fc);
flexcop_hw_filter_init(fc); flexcop_hw_filter_init(fc);
flexcop_smc_ctrl(fc, 0); flexcop_smc_ctrl(fc, 0);
if ((ret = flexcop_dvb_init(fc))) if ((ret = flexcop_dvb_init(fc)))
@@ -279,7 +276,6 @@ int flexcop_device_initialize(struct flexcop_device *fc)
goto error; goto error;
flexcop_device_name(fc,"initialization of","complete"); flexcop_device_name(fc,"initialization of","complete");
return 0; return 0;
error: error:

View File

@@ -1,9 +1,7 @@
/* /*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* * flexcop.h - private header file for all flexcop-chip-source files
* flexcop.h - private header file for all flexcop-chip-source files. * see flexcop.c for copyright information
*
* see flexcop.c for copyright information.
*/ */
#ifndef __FLEXCOP_H__ #ifndef __FLEXCOP_H__
#define __FLEXCOP_H___ #define __FLEXCOP_H___

View File

@@ -1,10 +1,7 @@
/* This file is part of linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III /* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
*
* register descriptions * register descriptions
* * see flexcop.c for copyright information
* see flexcop.c for copyright information.
*/ */
/* This file is automatically generated, do not edit things here. */ /* This file is automatically generated, do not edit things here. */
#ifndef __FLEXCOP_IBI_VALUE_INCLUDED__ #ifndef __FLEXCOP_IBI_VALUE_INCLUDED__
#define __FLEXCOP_IBI_VALUE_INCLUDED__ #define __FLEXCOP_IBI_VALUE_INCLUDED__

View File

@@ -1,10 +1,7 @@
/* This file is part of linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III /* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
*
* register descriptions * register descriptions
* * see flexcop.c for copyright information
* see flexcop.c for copyright information.
*/ */
/* This file is automatically generated, do not edit things here. */ /* This file is automatically generated, do not edit things here. */
#ifndef __FLEXCOP_IBI_VALUE_INCLUDED__ #ifndef __FLEXCOP_IBI_VALUE_INCLUDED__
#define __FLEXCOP_IBI_VALUE_INCLUDED__ #define __FLEXCOP_IBI_VALUE_INCLUDED__

View File

@@ -8,7 +8,7 @@ config DVB_BT8XX
select DVB_OR51211 if !DVB_FE_CUSTOMISE select DVB_OR51211 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
help help
Support for PCI cards based on the Bt8xx PCI bridge. Examples are Support for PCI cards based on the Bt8xx PCI bridge. Examples are
the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,

View File

@@ -552,16 +552,19 @@ free_mem_and_exit:
return result; return result;
} }
static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long ioctl_arg) static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioctl_arg)
{ {
struct dvb_device* dvbdev = (struct dvb_device*) file->private_data; struct dvb_device *dvbdev;
struct dst_state* state = (struct dst_state*) dvbdev->priv; struct dst_state *state;
struct ca_slot_info *p_ca_slot_info; struct ca_slot_info *p_ca_slot_info;
struct ca_caps *p_ca_caps; struct ca_caps *p_ca_caps;
struct ca_msg *p_ca_message; struct ca_msg *p_ca_message;
void __user *arg = (void __user *)ioctl_arg; void __user *arg = (void __user *)ioctl_arg;
int result = 0; int result = 0;
lock_kernel();
dvbdev = (struct dvb_device *)file->private_data;
state = (struct dst_state *)dvbdev->priv;
p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL); p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL); p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL); p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL);
@@ -647,6 +650,7 @@ static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd
kfree (p_ca_slot_info); kfree (p_ca_slot_info);
kfree (p_ca_caps); kfree (p_ca_caps);
unlock_kernel();
return result; return result;
} }
@@ -682,9 +686,9 @@ static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t
return 0; return 0;
} }
static struct file_operations dst_ca_fops = { static const struct file_operations dst_ca_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.ioctl = dst_ca_ioctl, .unlocked_ioctl = dst_ca_ioctl,
.open = dst_ca_open, .open = dst_ca_open,
.release = dst_ca_release, .release = dst_ca_release,
.read = dst_ca_read, .read = dst_ca_read,

View File

@@ -814,7 +814,7 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
mutex_init(&card->lock); mutex_init(&card->lock);
card->bttv_nr = sub->core->nr; card->bttv_nr = sub->core->nr;
strncpy(card->card_name, sub->core->name, sizeof(sub->core->name)); strlcpy(card->card_name, sub->core->v4l2_dev.name, sizeof(card->card_name));
card->i2c_adapter = &sub->core->i2c_adap; card->i2c_adapter = &sub->core->i2c_adap;
switch(sub->core->type) { switch(sub->core->type) {

View File

@@ -8,6 +8,7 @@ config DVB_DM1105
select DVB_STB6000 if !DVB_FE_CUSTOMISE select DVB_STB6000 if !DVB_FE_CUSTOMISE
select DVB_CX24116 if !DVB_FE_CUSTOMISE select DVB_CX24116 if !DVB_FE_CUSTOMISE
select DVB_SI21XX if !DVB_FE_CUSTOMISE select DVB_SI21XX if !DVB_FE_CUSTOMISE
select VIDEO_IR
help help
Support for cards based on the SDMC DM1105 PCI chip like Support for cards based on the SDMC DM1105 PCI chip like
DvbWorld 2002 DvbWorld 2002

View File

@@ -156,46 +156,12 @@ MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static u16 ir_codes_dm1105_nec[128] = {
[0x0a] = KEY_Q, /*power*/
[0x0c] = KEY_M, /*mute*/
[0x11] = KEY_1,
[0x12] = KEY_2,
[0x13] = KEY_3,
[0x14] = KEY_4,
[0x15] = KEY_5,
[0x16] = KEY_6,
[0x17] = KEY_7,
[0x18] = KEY_8,
[0x19] = KEY_9,
[0x10] = KEY_0,
[0x1c] = KEY_PAGEUP, /*ch+*/
[0x0f] = KEY_PAGEDOWN, /*ch-*/
[0x1a] = KEY_O, /*vol+*/
[0x0e] = KEY_Z, /*vol-*/
[0x04] = KEY_R, /*rec*/
[0x09] = KEY_D, /*fav*/
[0x08] = KEY_BACKSPACE, /*rewind*/
[0x07] = KEY_A, /*fast*/
[0x0b] = KEY_P, /*pause*/
[0x02] = KEY_ESC, /*cancel*/
[0x03] = KEY_G, /*tab*/
[0x00] = KEY_UP, /*up*/
[0x1f] = KEY_ENTER, /*ok*/
[0x01] = KEY_DOWN, /*down*/
[0x05] = KEY_C, /*cap*/
[0x06] = KEY_S, /*stop*/
[0x40] = KEY_F, /*full*/
[0x1e] = KEY_W, /*tvmode*/
[0x1b] = KEY_B, /*recall*/
};
/* infrared remote control */ /* infrared remote control */
struct infrared { struct infrared {
u16 key_map[128];
struct input_dev *input_dev; struct input_dev *input_dev;
struct ir_input_state ir;
char input_phys[32]; char input_phys[32];
struct tasklet_struct ir_tasklet; struct work_struct work;
u32 ir_command; u32 ir_command;
}; };
@@ -220,10 +186,14 @@ struct dm1105dvb {
/* i2c */ /* i2c */
struct i2c_adapter i2c_adap; struct i2c_adapter i2c_adap;
/* irq */
struct work_struct work;
/* dma */ /* dma */
dma_addr_t dma_addr; dma_addr_t dma_addr;
unsigned char *ts_buf; unsigned char *ts_buf;
u32 wrp; u32 wrp;
u32 nextwrp;
u32 buffer_size; u32 buffer_size;
unsigned int PacketErrorCount; unsigned int PacketErrorCount;
unsigned int dmarst; unsigned int dmarst;
@@ -233,8 +203,6 @@ struct dm1105dvb {
#define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg])) #define dm_io_mem(reg) ((unsigned long)(&dm1105dvb->io_mem[reg]))
static struct dm1105dvb *dm1105dvb_local;
static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap, static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msgs, int num) struct i2c_msg *msgs, int num)
{ {
@@ -407,50 +375,31 @@ static int dm1105dvb_stop_feed(struct dvb_demux_feed *f)
return 0; return 0;
} }
/* ir tasklet */ /* ir work handler */
static void dm1105_emit_key(unsigned long parm) static void dm1105_emit_key(struct work_struct *work)
{ {
struct infrared *ir = (struct infrared *) parm; struct infrared *ir = container_of(work, struct infrared, work);
u32 ircom = ir->ir_command; u32 ircom = ir->ir_command;
u8 data; u8 data;
u16 keycode;
if (ir_debug)
printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom);
data = (ircom >> 8) & 0x7f; data = (ircom >> 8) & 0x7f;
input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data); ir_input_keydown(ir->input_dev, &ir->ir, data, data);
input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); ir_input_nokey(ir->input_dev, &ir->ir);
keycode = ir->key_map[data];
if (!keycode)
return;
input_event(ir->input_dev, EV_KEY, keycode, 1);
input_sync(ir->input_dev);
input_event(ir->input_dev, EV_KEY, keycode, 0);
input_sync(ir->input_dev);
} }
static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) /* work handler */
static void dm1105_dmx_buffer(struct work_struct *work)
{ {
struct dm1105dvb *dm1105dvb = dev_id; struct dm1105dvb *dm1105dvb =
unsigned int piece; container_of(work, struct dm1105dvb, work);
unsigned int nbpackets; unsigned int nbpackets;
u32 command; u32 oldwrp = dm1105dvb->wrp;
u32 nextwrp; u32 nextwrp = dm1105dvb->nextwrp;
u32 oldwrp;
/* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
outb(intsts, dm_io_mem(DM1105_INTSTS));
switch (intsts) {
case INTSTS_TSIRQ:
case (INTSTS_TSIRQ | INTSTS_IR):
nextwrp = inl(dm_io_mem(DM1105_WRP)) -
inl(dm_io_mem(DM1105_STADR)) ;
oldwrp = dm1105dvb->wrp;
spin_lock(&dm1105dvb->lock);
if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) && if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
(dm1105dvb->ts_buf[oldwrp + 188] == 0x47) && (dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
(dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) { (dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
@@ -462,56 +411,52 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
dm1105dvb->wrp = 0; dm1105dvb->wrp = 0;
dm1105dvb->PacketErrorCount = 0; dm1105dvb->PacketErrorCount = 0;
dm1105dvb->dmarst = 0; dm1105dvb->dmarst = 0;
spin_unlock(&dm1105dvb->lock); return;
return IRQ_HANDLED;
} }
} }
if (nextwrp < oldwrp) { if (nextwrp < oldwrp) {
piece = dm1105dvb->buffer_size - oldwrp; memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size,
memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp); dm1105dvb->ts_buf, nextwrp);
nbpackets = (piece + nextwrp)/188; nbpackets = ((dm1105dvb->buffer_size - oldwrp) + nextwrp) / 188;
} else { } else
nbpackets = (nextwrp - oldwrp) / 188; nbpackets = (nextwrp - oldwrp) / 188;
}
dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], nbpackets);
dm1105dvb->wrp = nextwrp; dm1105dvb->wrp = nextwrp;
spin_unlock(&dm1105dvb->lock); dvb_dmx_swfilter_packets(&dm1105dvb->demux,
&dm1105dvb->ts_buf[oldwrp], nbpackets);
}
static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
{
struct dm1105dvb *dm1105dvb = dev_id;
/* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
outb(intsts, dm_io_mem(DM1105_INTSTS));
switch (intsts) {
case INTSTS_TSIRQ:
case (INTSTS_TSIRQ | INTSTS_IR):
dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
inl(dm_io_mem(DM1105_STADR));
schedule_work(&dm1105dvb->work);
break; break;
case INTSTS_IR: case INTSTS_IR:
command = inl(dm_io_mem(DM1105_IRCODE)); dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
if (ir_debug) schedule_work(&dm1105dvb->ir.work);
printk("dm1105: received byte 0x%04x\n", command);
dm1105dvb->ir.ir_command = command;
tasklet_schedule(&dm1105dvb->ir.ir_tasklet);
break; break;
} }
return IRQ_HANDLED; return IRQ_HANDLED;
}
/* register with input layer */
static void input_register_keys(struct infrared *ir)
{
int i;
memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit));
for (i = 0; i < ARRAY_SIZE(ir->key_map); i++)
set_bit(ir->key_map[i], ir->input_dev->keybit);
ir->input_dev->keycode = ir->key_map;
ir->input_dev->keycodesize = sizeof(ir->key_map[0]);
ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map);
} }
int __devinit dm1105_ir_init(struct dm1105dvb *dm1105) int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
{ {
struct input_dev *input_dev; struct input_dev *input_dev;
int err; IR_KEYTAB_TYPE *ir_codes = ir_codes_dm1105_nec;
int ir_type = IR_TYPE_OTHER;
dm1105dvb_local = dm1105; int err = -ENOMEM;
input_dev = input_allocate_device(); input_dev = input_allocate_device();
if (!input_dev) if (!input_dev)
@@ -521,12 +466,11 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
"pci-%s/ir0", pci_name(dm1105->pdev)); "pci-%s/ir0", pci_name(dm1105->pdev));
input_dev->evbit[0] = BIT(EV_KEY); ir_input_init(input_dev, &dm1105->ir.ir, ir_type, ir_codes);
input_dev->name = "DVB on-card IR receiver"; input_dev->name = "DVB on-card IR receiver";
input_dev->phys = dm1105->ir.input_phys; input_dev->phys = dm1105->ir.input_phys;
input_dev->id.bustype = BUS_PCI; input_dev->id.bustype = BUS_PCI;
input_dev->id.version = 2; input_dev->id.version = 1;
if (dm1105->pdev->subsystem_vendor) { if (dm1105->pdev->subsystem_vendor) {
input_dev->id.vendor = dm1105->pdev->subsystem_vendor; input_dev->id.vendor = dm1105->pdev->subsystem_vendor;
input_dev->id.product = dm1105->pdev->subsystem_device; input_dev->id.product = dm1105->pdev->subsystem_device;
@@ -534,25 +478,22 @@ int __devinit dm1105_ir_init(struct dm1105dvb *dm1105)
input_dev->id.vendor = dm1105->pdev->vendor; input_dev->id.vendor = dm1105->pdev->vendor;
input_dev->id.product = dm1105->pdev->device; input_dev->id.product = dm1105->pdev->device;
} }
input_dev->dev.parent = &dm1105->pdev->dev; input_dev->dev.parent = &dm1105->pdev->dev;
/* initial keymap */
memcpy(dm1105->ir.key_map, ir_codes_dm1105_nec, sizeof dm1105->ir.key_map); INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
input_register_keys(&dm1105->ir);
err = input_register_device(input_dev); err = input_register_device(input_dev);
if (err) { if (err) {
input_free_device(input_dev); input_free_device(input_dev);
return err; return err;
} }
tasklet_init(&dm1105->ir.ir_tasklet, dm1105_emit_key, (unsigned long) &dm1105->ir);
return 0; return 0;
} }
void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105) void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105)
{ {
tasklet_kill(&dm1105->ir.ir_tasklet);
input_unregister_device(dm1105->ir.input_dev); input_unregister_device(dm1105->ir.input_dev);
} }
@@ -710,7 +651,7 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL); dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL);
if (!dm1105dvb) if (!dm1105dvb)
goto out; return -ENOMEM;
dm1105dvb->pdev = pdev; dm1105dvb->pdev = pdev;
dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES; dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES;
@@ -740,13 +681,9 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
spin_lock_init(&dm1105dvb->lock); spin_lock_init(&dm1105dvb->lock);
pci_set_drvdata(pdev, dm1105dvb); pci_set_drvdata(pdev, dm1105dvb);
ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb);
if (ret < 0)
goto err_pci_iounmap;
ret = dm1105dvb_hw_init(dm1105dvb); ret = dm1105dvb_hw_init(dm1105dvb);
if (ret < 0) if (ret < 0)
goto err_free_irq; goto err_pci_iounmap;
/* i2c */ /* i2c */
i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb); i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb);
@@ -813,8 +750,15 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx); dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx);
dm1105_ir_init(dm1105dvb); dm1105_ir_init(dm1105dvb);
out:
return ret; INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer);
ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED,
DRIVER_NAME, dm1105dvb);
if (ret < 0)
goto err_free_irq;
return 0;
err_disconnect_frontend: err_disconnect_frontend:
dmx->disconnect_frontend(dmx); dmx->disconnect_frontend(dmx);
@@ -843,7 +787,7 @@ err_pci_disable_device:
err_kfree: err_kfree:
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
kfree(dm1105dvb); kfree(dm1105dvb);
goto out; return ret;
} }
static void __devexit dm1105_remove(struct pci_dev *pdev) static void __devexit dm1105_remove(struct pci_dev *pdev)

View File

@@ -1024,7 +1024,7 @@ static int dvb_demux_release(struct inode *inode, struct file *file)
return ret; return ret;
} }
static struct file_operations dvb_demux_fops = { static const struct file_operations dvb_demux_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.read = dvb_demux_read, .read = dvb_demux_read,
.ioctl = dvb_demux_ioctl, .ioctl = dvb_demux_ioctl,

View File

@@ -1607,7 +1607,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
EXPORT_SYMBOL(dvb_ca_en50221_init); EXPORT_SYMBOL(dvb_ca_en50221_init);
static struct file_operations dvb_ca_fops = { static const struct file_operations dvb_ca_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.read = dvb_ca_en50221_io_read, .read = dvb_ca_en50221_io_read,
.write = dvb_ca_en50221_io_write, .write = dvb_ca_en50221_io_write,

View File

@@ -1875,7 +1875,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
return ret; return ret;
} }
static struct file_operations dvb_frontend_fops = { static const struct file_operations dvb_frontend_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.ioctl = dvb_generic_ioctl, .ioctl = dvb_generic_ioctl,
.poll = dvb_frontend_poll, .poll = dvb_frontend_poll,

View File

@@ -1459,7 +1459,7 @@ static int dvb_net_close(struct inode *inode, struct file *file)
} }
static struct file_operations dvb_net_fops = { static const struct file_operations dvb_net_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.ioctl = dvb_net_ioctl, .ioctl = dvb_net_ioctl,
.open = dvb_generic_open, .open = dvb_generic_open,

View File

@@ -228,8 +228,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
dvbdev->fops = dvbdevfops; dvbdev->fops = dvbdevfops;
init_waitqueue_head (&dvbdev->wait_queue); init_waitqueue_head (&dvbdev->wait_queue);
memcpy(dvbdev->fops, template->fops, sizeof(struct file_operations)); memcpy(dvbdevfops, template->fops, sizeof(struct file_operations));
dvbdev->fops->owner = adap->module; dvbdevfops->owner = adap->module;
list_add_tail (&dvbdev->list_head, &adap->device_list); list_add_tail (&dvbdev->list_head, &adap->device_list);

View File

@@ -71,7 +71,7 @@ struct dvb_adapter {
struct dvb_device { struct dvb_device {
struct list_head list_head; struct list_head list_head;
struct file_operations *fops; const struct file_operations *fops;
struct dvb_adapter *adapter; struct dvb_adapter *adapter;
int type; int type;
int minor; int minor;

View File

@@ -25,7 +25,7 @@ config DVB_USB_A800
depends on DVB_USB depends on DVB_USB
select DVB_DIB3000MC select DVB_DIB3000MC
select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
@@ -34,7 +34,7 @@ config DVB_USB_DIBUSB_MB
depends on DVB_USB depends on DVB_USB
select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_DIB3000MB select DVB_DIB3000MB
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
help help
Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
@@ -55,7 +55,7 @@ config DVB_USB_DIBUSB_MC
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
depends on DVB_USB depends on DVB_USB
select DVB_DIB3000MC select DVB_DIB3000MC
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
help help
Support for USB2.0 DVB-T receivers based on reference designs made by Support for USB2.0 DVB-T receivers based on reference designs made by
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
@@ -69,15 +69,17 @@ config DVB_USB_DIBUSB_MC
config DVB_USB_DIB0700 config DVB_USB_DIB0700
tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
depends on DVB_USB depends on DVB_USB
select DVB_DIB7000P select DVB_DIB7000P if !DVB_FE_CUSTOMISE
select DVB_DIB7000M select DVB_DIB7000M if !DVB_FE_CUSTOMISE
select DVB_DIB3000MC select DVB_DIB3000MC if !DVB_FE_CUSTOMISE
select DVB_S5H1411 if !DVB_FE_CUSTOMISE select DVB_S5H1411 if !DVB_FE_CUSTOMISE
select DVB_TUNER_DIB0070 select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
help help
Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
USB bridge is also present in devices having the DiB7700 DVB-T-USB USB bridge is also present in devices having the DiB7700 DVB-T-USB
@@ -95,7 +97,8 @@ config DVB_USB_UMT_010
depends on DVB_USB depends on DVB_USB
select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE
select DVB_DIB3000MC select DVB_DIB3000MC
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
select DVB_MT352 if !DVB_FE_CUSTOMISE
help help
Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
@@ -108,10 +111,11 @@ config DVB_USB_CXUSB
select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select DVB_DIB7000P if !DVB_FE_CUSTOMISE select DVB_DIB7000P if !DVB_FE_CUSTOMISE
select DVB_LGS8GL5 if !DVB_FE_CUSTOMISE
select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the Conexant USB2.0 hybrid reference design. Say Y here to support the Conexant USB2.0 hybrid reference design.
Currently, only DVB and ATSC modes are supported, analog mode Currently, only DVB and ATSC modes are supported, analog mode
@@ -125,8 +129,8 @@ config DVB_USB_M920X
depends on DVB_USB depends on DVB_USB
select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_TDA1004X if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
Currently, only devices with a product id of Currently, only devices with a product id of
@@ -137,7 +141,7 @@ config DVB_USB_GL861
tristate "Genesys Logic GL861 USB2.0 support" tristate "Genesys Logic GL861 USB2.0 support"
depends on DVB_USB depends on DVB_USB
select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
receiver with USB ID 0db0:5581. receiver with USB ID 0db0:5581.
@@ -146,7 +150,7 @@ config DVB_USB_AU6610
tristate "Alcor Micro AU6610 USB2.0 support" tristate "Alcor Micro AU6610 USB2.0 support"
depends on DVB_USB depends on DVB_USB
select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
@@ -199,7 +203,7 @@ config DVB_USB_NOVA_T_USB2
depends on DVB_USB depends on DVB_USB
select DVB_DIB3000MC select DVB_DIB3000MC
select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
@@ -235,8 +239,8 @@ config DVB_USB_OPERA1
config DVB_USB_AF9005 config DVB_USB_AF9005
tristate "Afatech AF9005 DVB-T USB1.1 support" tristate "Afatech AF9005 DVB-T USB1.1 support"
depends on DVB_USB && EXPERIMENTAL depends on DVB_USB && EXPERIMENTAL
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
and the TerraTec Cinergy T USB XE (Rev.1) and the TerraTec Cinergy T USB XE (Rev.1)
@@ -284,7 +288,7 @@ config DVB_USB_DTV5100
tristate "AME DTV-5100 USB2.0 DVB-T support" tristate "AME DTV-5100 USB2.0 DVB-T support"
depends on DVB_USB depends on DVB_USB
select DVB_ZL10353 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
@@ -293,9 +297,18 @@ config DVB_USB_AF9015
depends on DVB_USB && EXPERIMENTAL depends on DVB_USB && EXPERIMENTAL
select DVB_AF9013 select DVB_AF9013
select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_PLL if !DVB_FE_CUSTOMISE
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
help help
Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
config DVB_USB_CE6230
tristate "Intel CE6230 DVB-T USB2.0 support"
depends on DVB_USB && EXPERIMENTAL
select DVB_ZL10353
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
help
Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver

View File

@@ -76,6 +76,8 @@ obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o
dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o
obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o
dvb-usb-ce6230-objs = ce6230.o
obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
# due to tuner-xc3028 # due to tuner-xc3028

View File

@@ -27,9 +27,7 @@
#include "qt1010.h" #include "qt1010.h"
#include "tda18271.h" #include "tda18271.h"
#include "mxl5005s.h" #include "mxl5005s.h"
#if 0 #include "mc44s803.h"
#include "mc44s80x.h"
#endif
static int dvb_usb_af9015_debug; static int dvb_usb_af9015_debug;
module_param_named(debug, dvb_usb_af9015_debug, int, 0644); module_param_named(debug, dvb_usb_af9015_debug, int, 0644);
@@ -37,9 +35,6 @@ MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
static int dvb_usb_af9015_remote; static int dvb_usb_af9015_remote;
module_param_named(remote, dvb_usb_af9015_remote, int, 0644); module_param_named(remote, dvb_usb_af9015_remote, int, 0644);
MODULE_PARM_DESC(remote, "select remote"); MODULE_PARM_DESC(remote, "select remote");
static int dvb_usb_af9015_dual_mode;
module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644);
MODULE_PARM_DESC(dual_mode, "enable dual mode");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static DEFINE_MUTEX(af9015_usb_mutex); static DEFINE_MUTEX(af9015_usb_mutex);
@@ -283,6 +278,21 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
req.data = &msg[i+1].buf[0]; req.data = &msg[i+1].buf[0];
ret = af9015_ctrl_msg(d, &req); ret = af9015_ctrl_msg(d, &req);
i += 2; i += 2;
} else if (msg[i].flags & I2C_M_RD) {
ret = -EINVAL;
if (msg[i].addr ==
af9015_af9013_config[0].demod_address)
goto error;
else
req.cmd = READ_I2C;
req.i2c_addr = msg[i].addr;
req.addr = addr;
req.mbox = mbox;
req.addr_len = addr_len;
req.data_len = msg[i].len;
req.data = &msg[i].buf[0];
ret = af9015_ctrl_msg(d, &req);
i += 1;
} else { } else {
if (msg[i].addr == if (msg[i].addr ==
af9015_af9013_config[0].demod_address) af9015_af9013_config[0].demod_address)
@@ -748,6 +758,16 @@ static int af9015_read_config(struct usb_device *udev)
af9015_config.ir_table_size = af9015_config.ir_table_size =
ARRAY_SIZE(af9015_ir_table_digittrade); ARRAY_SIZE(af9015_ir_table_digittrade);
break; break;
case AF9015_REMOTE_AVERMEDIA_KS:
af9015_properties[i].rc_key_map =
af9015_rc_keys_avermedia;
af9015_properties[i].rc_key_map_size =
ARRAY_SIZE(af9015_rc_keys_avermedia);
af9015_config.ir_table =
af9015_ir_table_avermedia_ks;
af9015_config.ir_table_size =
ARRAY_SIZE(af9015_ir_table_avermedia_ks);
break;
} }
} else { } else {
switch (le16_to_cpu(udev->descriptor.idVendor)) { switch (le16_to_cpu(udev->descriptor.idVendor)) {
@@ -836,9 +856,6 @@ static int af9015_read_config(struct usb_device *udev)
goto error; goto error;
af9015_config.dual_mode = val; af9015_config.dual_mode = val;
deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode); deb_info("%s: TS mode:%d\n", __func__, af9015_config.dual_mode);
/* disable dual mode by default because it is buggy */
if (!dvb_usb_af9015_dual_mode)
af9015_config.dual_mode = 0;
/* Set adapter0 buffer size according to USB port speed, adapter1 buffer /* Set adapter0 buffer size according to USB port speed, adapter1 buffer
size can be static because it is enabled only USB2.0 */ size can be static because it is enabled only USB2.0 */
@@ -935,7 +952,6 @@ static int af9015_read_config(struct usb_device *udev)
switch (val) { switch (val) {
case AF9013_TUNER_ENV77H11D5: case AF9013_TUNER_ENV77H11D5:
case AF9013_TUNER_MT2060: case AF9013_TUNER_MT2060:
case AF9013_TUNER_MC44S803:
case AF9013_TUNER_QT1010: case AF9013_TUNER_QT1010:
case AF9013_TUNER_UNKNOWN: case AF9013_TUNER_UNKNOWN:
case AF9013_TUNER_MT2060_2: case AF9013_TUNER_MT2060_2:
@@ -948,6 +964,10 @@ static int af9015_read_config(struct usb_device *udev)
case AF9013_TUNER_MXL5005R: case AF9013_TUNER_MXL5005R:
af9015_af9013_config[i].rf_spec_inv = 0; af9015_af9013_config[i].rf_spec_inv = 0;
break; break;
case AF9013_TUNER_MC44S803:
af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO;
af9015_af9013_config[i].rf_spec_inv = 1;
break;
default: default:
warn("tuner id:%d not supported, please report!", val); warn("tuner id:%d not supported, please report!", val);
return -ENODEV; return -ENODEV;
@@ -1135,6 +1155,11 @@ static struct mxl5005s_config af9015_mxl5005_config = {
.AgcMasterByte = 0x00, .AgcMasterByte = 0x00,
}; };
static struct mc44s803_config af9015_mc44s803_config = {
.i2c_address = 0xc0,
.dig_out = 1,
};
static int af9015_tuner_attach(struct dvb_usb_adapter *adap) static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
{ {
struct af9015_state *state = adap->dev->priv; struct af9015_state *state = adap->dev->priv;
@@ -1179,15 +1204,8 @@ static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
DVB_PLL_TDA665X) == NULL ? -ENODEV : 0; DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
break; break;
case AF9013_TUNER_MC44S803: case AF9013_TUNER_MC44S803:
#if 0 ret = dvb_attach(mc44s803_attach, adap->fe, i2c_adap,
ret = dvb_attach(mc44s80x_attach, adap->fe, i2c_adap) &af9015_mc44s803_config) == NULL ? -ENODEV : 0;
== NULL ? -ENODEV : 0;
#else
ret = -ENODEV;
info("Freescale MC44S803 tuner found but no driver for that" \
"tuner. Look at the Linuxtv.org for tuner driver" \
"status.");
#endif
break; break;
case AF9013_TUNER_UNKNOWN: case AF9013_TUNER_UNKNOWN:
default: default:
@@ -1218,6 +1236,7 @@ static struct usb_device_id af9015_usb_table[] = {
{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)}, {USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
/* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)}, /* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)}, {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)},
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
{0}, {0},
}; };
MODULE_DEVICE_TABLE(usb, af9015_usb_table); MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1417,7 +1436,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
{ {
.name = "KWorld USB DVB-T TV Stick II " \ .name = "KWorld USB DVB-T TV Stick II " \
"(VS-DVB-T 395U)", "(VS-DVB-T 395U)",
.cold_ids = {&af9015_usb_table[16], NULL}, .cold_ids = {&af9015_usb_table[16],
&af9015_usb_table[17], NULL},
.warm_ids = {NULL}, .warm_ids = {NULL},
}, },
} }

View File

@@ -124,6 +124,7 @@ enum af9015_remote {
AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
AF9015_REMOTE_MYGICTV_U718, AF9015_REMOTE_MYGICTV_U718,
AF9015_REMOTE_DIGITTRADE_DVB_T, AF9015_REMOTE_DIGITTRADE_DVB_T,
AF9015_REMOTE_AVERMEDIA_KS,
}; };
/* Leadtek WinFast DTV Dongle Gold */ /* Leadtek WinFast DTV Dongle Gold */
@@ -597,6 +598,36 @@ static u8 af9015_ir_table_avermedia[] = {
0x03, 0xfc, 0x03, 0xfc, 0x0e, 0x05, 0x00, 0x03, 0xfc, 0x03, 0xfc, 0x0e, 0x05, 0x00,
}; };
static u8 af9015_ir_table_avermedia_ks[] = {
0x05, 0xfa, 0x01, 0xfe, 0x12, 0x05, 0x00,
0x05, 0xfa, 0x02, 0xfd, 0x0e, 0x05, 0x00,
0x05, 0xfa, 0x03, 0xfc, 0x0d, 0x05, 0x00,
0x05, 0xfa, 0x04, 0xfb, 0x2e, 0x05, 0x00,
0x05, 0xfa, 0x05, 0xfa, 0x2d, 0x05, 0x00,
0x05, 0xfa, 0x06, 0xf9, 0x10, 0x05, 0x00,
0x05, 0xfa, 0x07, 0xf8, 0x0f, 0x05, 0x00,
0x05, 0xfa, 0x08, 0xf7, 0x3d, 0x05, 0x00,
0x05, 0xfa, 0x09, 0xf6, 0x1e, 0x05, 0x00,
0x05, 0xfa, 0x0a, 0xf5, 0x1f, 0x05, 0x00,
0x05, 0xfa, 0x0b, 0xf4, 0x20, 0x05, 0x00,
0x05, 0xfa, 0x0c, 0xf3, 0x21, 0x05, 0x00,
0x05, 0xfa, 0x0d, 0xf2, 0x22, 0x05, 0x00,
0x05, 0xfa, 0x0e, 0xf1, 0x23, 0x05, 0x00,
0x05, 0xfa, 0x0f, 0xf0, 0x24, 0x05, 0x00,
0x05, 0xfa, 0x10, 0xef, 0x25, 0x05, 0x00,
0x05, 0xfa, 0x11, 0xee, 0x26, 0x05, 0x00,
0x05, 0xfa, 0x12, 0xed, 0x27, 0x05, 0x00,
0x05, 0xfa, 0x13, 0xec, 0x04, 0x05, 0x00,
0x05, 0xfa, 0x15, 0xea, 0x0a, 0x05, 0x00,
0x05, 0xfa, 0x16, 0xe9, 0x11, 0x05, 0x00,
0x05, 0xfa, 0x17, 0xe8, 0x15, 0x05, 0x00,
0x05, 0xfa, 0x18, 0xe7, 0x16, 0x05, 0x00,
0x05, 0xfa, 0x1c, 0xe3, 0x05, 0x05, 0x00,
0x05, 0xfa, 0x1d, 0xe2, 0x09, 0x05, 0x00,
0x05, 0xfa, 0x4d, 0xb2, 0x3f, 0x05, 0x00,
0x05, 0xfa, 0x56, 0xa9, 0x3e, 0x05, 0x00
};
/* Digittrade DVB-T USB Stick */ /* Digittrade DVB-T USB Stick */
static struct dvb_usb_rc_key af9015_rc_keys_digittrade[] = { static struct dvb_usb_rc_key af9015_rc_keys_digittrade[] = {
{ 0x01, 0x0f, KEY_LAST }, /* RETURN */ { 0x01, 0x0f, KEY_LAST }, /* RETURN */

View File

@@ -0,0 +1,328 @@
/*
* DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver
*
* Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
*
* 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 "ce6230.h"
#include "zl10353.h"
#include "mxl5005s.h"
/* debug */
static int dvb_usb_ce6230_debug;
module_param_named(debug, dvb_usb_ce6230_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static struct zl10353_config ce6230_zl10353_config;
static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
{
int ret;
unsigned int pipe;
u8 request;
u8 requesttype;
u16 value;
u16 index;
u8 buf[req->data_len];
request = req->cmd;
value = req->value;
index = req->index;
switch (req->cmd) {
case I2C_READ:
case DEMOD_READ:
case REG_READ:
requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
break;
case I2C_WRITE:
case DEMOD_WRITE:
case REG_WRITE:
requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
break;
default:
err("unknown command:%02x", req->cmd);
ret = -EPERM;
goto error;
}
if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
/* write */
memcpy(buf, req->data, req->data_len);
pipe = usb_sndctrlpipe(udev, 0);
} else {
/* read */
pipe = usb_rcvctrlpipe(udev, 0);
}
msleep(1); /* avoid I2C errors */
ret = usb_control_msg(udev, pipe, request, requesttype, value, index,
buf, sizeof(buf), CE6230_USB_TIMEOUT);
ce6230_debug_dump(request, requesttype, value, index, buf,
req->data_len, deb_xfer);
if (ret < 0)
deb_info("%s: usb_control_msg failed:%d\n", __func__, ret);
else
ret = 0;
/* read request, copy returned data to return buf */
if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
memcpy(req->data, buf, req->data_len);
error:
return ret;
}
static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
{
return ce6230_rw_udev(d->udev, req);
}
/* I2C */
static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0;
struct req_t req;
int ret = 0;
memset(&req, 0, sizeof(&req));
if (num > 2)
return -EINVAL;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
while (i < num) {
if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
if (msg[i].addr ==
ce6230_zl10353_config.demod_address) {
req.cmd = DEMOD_READ;
req.value = msg[i].addr >> 1;
req.index = msg[i].buf[0];
req.data_len = msg[i+1].len;
req.data = &msg[i+1].buf[0];
ret = ce6230_ctrl_msg(d, &req);
} else {
err("i2c read not implemented");
ret = -EPERM;
}
i += 2;
} else {
if (msg[i].addr ==
ce6230_zl10353_config.demod_address) {
req.cmd = DEMOD_WRITE;
req.value = msg[i].addr >> 1;
req.index = msg[i].buf[0];
req.data_len = msg[i].len-1;
req.data = &msg[i].buf[1];
ret = ce6230_ctrl_msg(d, &req);
} else {
req.cmd = I2C_WRITE;
req.value = 0x2000 + (msg[i].addr >> 1);
req.index = 0x0000;
req.data_len = msg[i].len;
req.data = &msg[i].buf[0];
ret = ce6230_ctrl_msg(d, &req);
}
i += 1;
}
if (ret)
break;
}
mutex_unlock(&d->i2c_mutex);
return ret ? ret : i;
}
static u32 ce6230_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}
static struct i2c_algorithm ce6230_i2c_algo = {
.master_xfer = ce6230_i2c_xfer,
.functionality = ce6230_i2c_func,
};
/* Callbacks for DVB USB */
static struct zl10353_config ce6230_zl10353_config = {
.demod_address = 0x1e,
.adc_clock = 450000,
.if2 = 45700,
.no_tuner = 1,
.parallel_ts = 1,
.clock_ctl_1 = 0x34,
.pll_0 = 0x0e,
};
static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
{
deb_info("%s:\n", __func__);
adap->fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
&adap->dev->i2c_adap);
if (adap->fe == NULL)
return -ENODEV;
return 0;
}
static struct mxl5005s_config ce6230_mxl5003s_config = {
.i2c_address = 0xc6,
.if_freq = IF_FREQ_4570000HZ,
.xtal_freq = CRYSTAL_FREQ_16000000HZ,
.agc_mode = MXL_SINGLE_AGC,
.tracking_filter = MXL_TF_DEFAULT,
.rssi_enable = MXL_RSSI_ENABLE,
.cap_select = MXL_CAP_SEL_ENABLE,
.div_out = MXL_DIV_OUT_4,
.clock_out = MXL_CLOCK_OUT_DISABLE,
.output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
.top = MXL5005S_TOP_25P2,
.mod_mode = MXL_DIGITAL_MODE,
.if_mode = MXL_ZERO_IF,
.AgcMasterByte = 0x00,
};
static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
{
int ret;
deb_info("%s:\n", __func__);
ret = dvb_attach(mxl5005s_attach, adap->fe, &adap->dev->i2c_adap,
&ce6230_mxl5003s_config) == NULL ? -ENODEV : 0;
return ret;
}
static int ce6230_power_ctrl(struct dvb_usb_device *d, int onoff)
{
int ret;
deb_info("%s: onoff:%d\n", __func__, onoff);
/* InterfaceNumber 1 / AlternateSetting 0 idle
InterfaceNumber 1 / AlternateSetting 1 streaming */
ret = usb_set_interface(d->udev, 1, onoff);
if (ret)
err("usb_set_interface failed with error:%d", ret);
return ret;
}
/* DVB USB Driver stuff */
static struct dvb_usb_device_properties ce6230_properties;
static int ce6230_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
int ret = 0;
struct dvb_usb_device *d = NULL;
deb_info("%s: interface:%d\n", __func__,
intf->cur_altsetting->desc.bInterfaceNumber);
if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
ret = dvb_usb_device_init(intf, &ce6230_properties, THIS_MODULE,
&d, adapter_nr);
if (ret)
err("init failed with error:%d\n", ret);
}
return ret;
}
static struct usb_device_id ce6230_table[] = {
{ USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, ce6230_table);
static struct dvb_usb_device_properties ce6230_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.no_reconnect = 1,
.size_of_priv = 0,
.num_adapters = 1,
.adapter = {
{
.frontend_attach = ce6230_zl10353_frontend_attach,
.tuner_attach = ce6230_mxl5003s_tuner_attach,
.stream = {
.type = USB_BULK,
.count = 6,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 512,
}
}
},
}
},
.power_ctrl = ce6230_power_ctrl,
.i2c_algo = &ce6230_i2c_algo,
.num_device_descs = 1,
.devices = {
{
.name = "Intel CE9500 reference design",
.cold_ids = {NULL},
.warm_ids = {&ce6230_table[0], NULL},
},
}
};
static struct usb_driver ce6230_driver = {
.name = "dvb_usb_ce6230",
.probe = ce6230_probe,
.disconnect = dvb_usb_device_exit,
.id_table = ce6230_table,
};
/* module stuff */
static int __init ce6230_module_init(void)
{
int ret;
deb_info("%s:\n", __func__);
ret = usb_register(&ce6230_driver);
if (ret)
err("usb_register failed with error:%d", ret);
return ret;
}
static void __exit ce6230_module_exit(void)
{
deb_info("%s:\n", __func__);
/* deregister this driver from the USB subsystem */
usb_deregister(&ce6230_driver);
}
module_init(ce6230_module_init);
module_exit(ce6230_module_exit);
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_DESCRIPTION("Driver for Intel CE6230 DVB-T USB2.0");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,69 @@
/*
* DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver
*
* Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
*
* 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 _DVB_USB_CE6230_H_
#define _DVB_USB_CE6230_H_
#define DVB_USB_LOG_PREFIX "ce6230"
#include "dvb-usb.h"
#define deb_info(args...) dprintk(dvb_usb_ce6230_debug, 0x01, args)
#define deb_rc(args...) dprintk(dvb_usb_ce6230_debug, 0x02, args)
#define deb_xfer(args...) dprintk(dvb_usb_ce6230_debug, 0x04, args)
#define deb_reg(args...) dprintk(dvb_usb_ce6230_debug, 0x08, args)
#define deb_i2c(args...) dprintk(dvb_usb_ce6230_debug, 0x10, args)
#define deb_fw(args...) dprintk(dvb_usb_ce6230_debug, 0x20, args)
#define ce6230_debug_dump(r, t, v, i, b, l, func) { \
int loop_; \
func("%02x %02x %02x %02x %02x %02x %02x %02x", \
t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \
if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \
func(" >>> "); \
else \
func(" <<< "); \
for (loop_ = 0; loop_ < l; loop_++) \
func("%02x ", b[loop_]); \
func("\n");\
}
#define CE6230_USB_TIMEOUT 1000
struct req_t {
u8 cmd; /* [1] */
u16 value; /* [2|3] */
u16 index; /* [4|5] */
u16 data_len; /* [6|7] */
u8 *data;
};
enum ce6230_cmd {
CONFIG_READ = 0xd0, /* rd 0 (unclear) */
UNKNOWN_WRITE = 0xc7, /* wr 7 (unclear) */
I2C_READ = 0xd9, /* rd 9 (unclear) */
I2C_WRITE = 0xca, /* wr a */
DEMOD_READ = 0xdb, /* rd b */
DEMOD_WRITE = 0xcc, /* wr c */
REG_READ = 0xde, /* rd e */
REG_WRITE = 0xcf, /* wr f */
};
#endif

View File

@@ -158,6 +158,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
err("i2c read error (status = %d)\n", result); err("i2c read error (status = %d)\n", result);
break; break;
} }
deb_data("<<< ");
debug_dump(msg[i].buf, msg[i].len, deb_data);
} else { } else {
/* Write request */ /* Write request */
buf[0] = REQUEST_NEW_I2C_WRITE; buf[0] = REQUEST_NEW_I2C_WRITE;
@@ -169,6 +173,9 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
/* The Actual i2c payload */ /* The Actual i2c payload */
memcpy(&buf[4], msg[i].buf, msg[i].len); memcpy(&buf[4], msg[i].buf, msg[i].len);
deb_data(">>> ");
debug_dump(buf, msg[i].len + 4, deb_data);
result = usb_control_msg(d->udev, result = usb_control_msg(d->udev,
usb_sndctrlpipe(d->udev, 0), usb_sndctrlpipe(d->udev, 0),
REQUEST_NEW_I2C_WRITE, REQUEST_NEW_I2C_WRITE,
@@ -211,7 +218,8 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
/* special thing in the current firmware: when length is zero the read-failed */ /* special thing in the current firmware: when length is zero the read-failed */
if ((len = dib0700_ctrl_rd(d, buf, msg[i].len + 2, msg[i+1].buf, msg[i+1].len)) <= 0) { if ((len = dib0700_ctrl_rd(d, buf, msg[i].len + 2, msg[i+1].buf, msg[i+1].len)) <= 0) {
deb_info("I2C read failed on address %x\n", msg[i].addr); deb_info("I2C read failed on address 0x%02x\n",
msg[i].addr);
break; break;
} }

View File

@@ -17,6 +17,8 @@
#include "xc5000.h" #include "xc5000.h"
#include "s5h1411.h" #include "s5h1411.h"
#include "dib0070.h" #include "dib0070.h"
#include "lgdt3305.h"
#include "mxl5007t.h"
static int force_lna_activation; static int force_lna_activation;
module_param(force_lna_activation, int, 0644); module_param(force_lna_activation, int, 0644);
@@ -262,7 +264,12 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10); msleep(10);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10); msleep(10);
dib7000p_i2c_enumeration(&adap->dev->i2c_adap,1,18,stk7700d_dib7000p_mt2266_config); if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
stk7700d_dib7000p_mt2266_config)
!= 0) {
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
return -ENODEV;
}
} }
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1), adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
@@ -284,7 +291,12 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10); msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
dib7000p_i2c_enumeration(&adap->dev->i2c_adap,2,18,stk7700d_dib7000p_mt2266_config); if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
stk7700d_dib7000p_mt2266_config)
!= 0) {
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
return -ENODEV;
}
} }
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1), adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,0x80+(adap->id << 1),
@@ -421,8 +433,12 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
msleep(10); msleep(10);
dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
&stk7700ph_dib7700_xc3028_config); &stk7700ph_dib7700_xc3028_config) != 0) {
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
__func__);
return -ENODEV;
}
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&stk7700ph_dib7700_xc3028_config); &stk7700ph_dib7700_xc3028_config);
@@ -1187,8 +1203,12 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10); msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
&dib7070p_dib7000p_config); &dib7070p_dib7000p_config) != 0) {
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
__func__);
return -ENODEV;
}
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
&dib7070p_dib7000p_config); &dib7070p_dib7000p_config);
@@ -1244,7 +1264,12 @@ static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
msleep(10); msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, stk7070pd_dib7000p_config); if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
stk7070pd_dib7000p_config) != 0) {
err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
__func__);
return -ENODEV;
}
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]); adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
return adap->fe == NULL ? -ENODEV : 0; return adap->fe == NULL ? -ENODEV : 0;
@@ -1347,6 +1372,72 @@ static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
== NULL ? -ENODEV : 0; == NULL ? -ENODEV : 0;
} }
static struct lgdt3305_config hcw_lgdt3305_config = {
.i2c_addr = 0x0e,
.mpeg_mode = LGDT3305_MPEG_PARALLEL,
.tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE,
.tpvalid_polarity = LGDT3305_TP_VALID_LOW,
.deny_i2c_rptr = 0,
.spectral_inversion = 1,
.qam_if_khz = 6000,
.vsb_if_khz = 6000,
.usref_8vsb = 0x0500,
};
static struct mxl5007t_config hcw_mxl5007t_config = {
.xtal_freq_hz = MxL_XTAL_25_MHZ,
.if_freq_hz = MxL_IF_6_MHZ,
.invert_if = 1,
};
/* TIGER-ATSC map:
GPIO0 - LNA_CTR (H: LNA power enabled, L: LNA power disabled)
GPIO1 - ANT_SEL (H: VPA, L: MCX)
GPIO4 - SCL2
GPIO6 - EN_TUNER
GPIO7 - SDA2
GPIO10 - DEM_RST
MXL is behind LG's i2c repeater. LG is on SCL2/SDA2 gpios on the DIB
*/
static int lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
/* Make use of the new i2c functions from FW 1.20 */
st->fw_use_new_i2c_api = 1;
st->disable_streaming_master_mode = 1;
/* fe power enable */
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
msleep(30);
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(30);
/* demod reset */
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(30);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
msleep(30);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(30);
adap->fe = dvb_attach(lgdt3305_attach,
&hcw_lgdt3305_config,
&adap->dev->i2c_adap);
return adap->fe == NULL ? -ENODEV : 0;
}
static int mxl5007t_tuner_attach(struct dvb_usb_adapter *adap)
{
return dvb_attach(mxl5007t_attach, adap->fe,
&adap->dev->i2c_adap, 0x60,
&hcw_mxl5007t_config) == NULL ? -ENODEV : 0;
}
/* DVB-USB and USB stuff follows */ /* DVB-USB and USB stuff follows */
struct usb_device_id dib0700_usb_id_table[] = { struct usb_device_id dib0700_usb_id_table[] = {
/* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) }, /* 0 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
@@ -1396,6 +1487,12 @@ struct usb_device_id dib0700_usb_id_table[] = {
{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_EXPRESS) }, { USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_EXPRESS) },
{ USB_DEVICE(USB_VID_TERRATEC, { USB_DEVICE(USB_VID_TERRATEC,
USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) }, USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2) },
{ USB_DEVICE(USB_VID_SONY, USB_PID_SONY_PLAYTV) },
/* 45 */{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_PD378S) },
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC) },
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_TIGER_ATSC_B210) },
{ USB_DEVICE(USB_VID_YUAN, USB_PID_YUAN_MC770) },
{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT) },
{ 0 } /* Terminating entry */ { 0 } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -1595,7 +1692,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}, },
}, },
.num_device_descs = 9, .num_device_descs = 11,
.devices = { .devices = {
{ "DiBcom STK7070P reference design", { "DiBcom STK7070P reference design",
{ &dib0700_usb_id_table[15], NULL }, { &dib0700_usb_id_table[15], NULL },
@@ -1633,6 +1730,14 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[33], NULL }, { &dib0700_usb_id_table[33], NULL },
{ NULL }, { NULL },
}, },
{ "Elgato EyeTV DTT",
{ &dib0700_usb_id_table[49], NULL },
{ NULL },
},
{ "Yuan PD378S",
{ &dib0700_usb_id_table[45], NULL },
{ NULL },
},
}, },
.rc_interval = DEFAULT_RC_INTERVAL, .rc_interval = DEFAULT_RC_INTERVAL,
@@ -1661,7 +1766,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
} }
}, },
.num_device_descs = 5, .num_device_descs = 6,
.devices = { .devices = {
{ "DiBcom STK7070PD reference design", { "DiBcom STK7070PD reference design",
{ &dib0700_usb_id_table[17], NULL }, { &dib0700_usb_id_table[17], NULL },
@@ -1682,8 +1787,16 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ "Terratec Cinergy DT USB XS Diversity", { "Terratec Cinergy DT USB XS Diversity",
{ &dib0700_usb_id_table[43], NULL }, { &dib0700_usb_id_table[43], NULL },
{ NULL }, { NULL },
},
{ "Sony PlayTV",
{ &dib0700_usb_id_table[44], 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, }, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 1, .num_adapters = 1,
@@ -1699,7 +1812,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
}, },
}, },
.num_device_descs = 5, .num_device_descs = 7,
.devices = { .devices = {
{ "Terratec Cinergy HT USB XE", { "Terratec Cinergy HT USB XE",
{ &dib0700_usb_id_table[27], NULL }, { &dib0700_usb_id_table[27], NULL },
@@ -1725,6 +1838,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
{ &dib0700_usb_id_table[39], NULL }, { &dib0700_usb_id_table[39], NULL },
{ NULL }, { NULL },
}, },
{ "YUAN High-Tech MC770",
{ &dib0700_usb_id_table[48], NULL },
{ NULL },
},
}, },
.rc_interval = DEFAULT_RC_INTERVAL, .rc_interval = DEFAULT_RC_INTERVAL,
.rc_key_map = dib0700_rc_keys, .rc_key_map = dib0700_rc_keys,
@@ -1759,6 +1876,31 @@ struct dvb_usb_device_properties dib0700_devices[] = {
.rc_key_map = dib0700_rc_keys, .rc_key_map = dib0700_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys), .rc_key_map_size = ARRAY_SIZE(dib0700_rc_keys),
.rc_query = dib0700_rc_query .rc_query = dib0700_rc_query
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
.num_adapters = 1,
.adapter = {
{
.frontend_attach = lgdt3305_frontend_attach,
.tuner_attach = mxl5007t_tuner_attach,
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
.size_of_priv = sizeof(struct
dib0700_adapter_state),
},
},
.num_device_descs = 2,
.devices = {
{ "Hauppauge ATSC MiniCard (B200)",
{ &dib0700_usb_id_table[46], NULL },
{ NULL },
},
{ "Hauppauge ATSC MiniCard (B210)",
{ &dib0700_usb_id_table[47], NULL },
{ NULL },
},
},
}, },
}; };

View File

@@ -27,12 +27,14 @@
#define USB_VID_DIBCOM 0x10b8 #define USB_VID_DIBCOM 0x10b8
#define USB_VID_DPOSH 0x1498 #define USB_VID_DPOSH 0x1498
#define USB_VID_DVICO 0x0fe9 #define USB_VID_DVICO 0x0fe9
#define USB_VID_ELGATO 0x0fd9
#define USB_VID_EMPIA 0xeb1a #define USB_VID_EMPIA 0xeb1a
#define USB_VID_GENPIX 0x09c0 #define USB_VID_GENPIX 0x09c0
#define USB_VID_GRANDTEC 0x5032 #define USB_VID_GRANDTEC 0x5032
#define USB_VID_HANFTEK 0x15f4 #define USB_VID_HANFTEK 0x15f4
#define USB_VID_HAUPPAUGE 0x2040 #define USB_VID_HAUPPAUGE 0x2040
#define USB_VID_HYPER_PALTEK 0x1025 #define USB_VID_HYPER_PALTEK 0x1025
#define USB_VID_INTEL 0x8086
#define USB_VID_KWORLD 0xeb2a #define USB_VID_KWORLD 0xeb2a
#define USB_VID_KWORLD_2 0x1b80 #define USB_VID_KWORLD_2 0x1b80
#define USB_VID_KYE 0x0458 #define USB_VID_KYE 0x0458
@@ -48,6 +50,7 @@
#define USB_VID_TERRATEC 0x0ccd #define USB_VID_TERRATEC 0x0ccd
#define USB_VID_TELESTAR 0x10b9 #define USB_VID_TELESTAR 0x10b9
#define USB_VID_VISIONPLUS 0x13d3 #define USB_VID_VISIONPLUS 0x13d3
#define USB_VID_SONY 0x1415
#define USB_VID_TWINHAN 0x1822 #define USB_VID_TWINHAN 0x1822
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8 #define USB_VID_ULTIMA_ELECTRONIC 0x05d8
#define USB_VID_UNIWILL 0x1584 #define USB_VID_UNIWILL 0x1584
@@ -95,8 +98,10 @@
#define USB_PID_UNIWILL_STK7700P 0x6003 #define USB_PID_UNIWILL_STK7700P 0x6003
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
#define USB_PID_INTEL_CE9500 0x9500
#define USB_PID_KWORLD_399U 0xe399 #define USB_PID_KWORLD_399U 0xe399
#define USB_PID_KWORLD_395U 0xe396 #define USB_PID_KWORLD_395U 0xe396
#define USB_PID_KWORLD_395U_2 0xe39b
#define USB_PID_KWORLD_PC160_2T 0xc160 #define USB_PID_KWORLD_PC160_2T 0xc160
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de #define USB_PID_KWORLD_VSTREAM_COLD 0x17de
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df #define USB_PID_KWORLD_VSTREAM_WARM 0x17df
@@ -149,6 +154,8 @@
#define USB_PID_HAUPPAUGE_MYTV_T 0x7080 #define USB_PID_HAUPPAUGE_MYTV_T 0x7080
#define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580 #define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580
#define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009 0x5200 #define USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009 0x5200
#define USB_PID_HAUPPAUGE_TIGER_ATSC 0xb200
#define USB_PID_HAUPPAUGE_TIGER_ATSC_B210 0xb210
#define USB_PID_AVERMEDIA_EXPRESS 0xb568 #define USB_PID_AVERMEDIA_EXPRESS 0xb568
#define USB_PID_AVERMEDIA_VOLAR 0xa807 #define USB_PID_AVERMEDIA_VOLAR 0xa807
#define USB_PID_AVERMEDIA_VOLAR_2 0xb808 #define USB_PID_AVERMEDIA_VOLAR_2 0xb808
@@ -232,9 +239,13 @@
#define USB_PID_ASUS_U3100 0x173f #define USB_PID_ASUS_U3100 0x173f
#define USB_PID_YUAN_EC372S 0x1edc #define USB_PID_YUAN_EC372S 0x1edc
#define USB_PID_YUAN_STK7700PH 0x1f08 #define USB_PID_YUAN_STK7700PH 0x1f08
#define USB_PID_YUAN_PD378S 0x2edc
#define USB_PID_YUAN_MC770 0x0871
#define USB_PID_DW2102 0x2102 #define USB_PID_DW2102 0x2102
#define USB_PID_XTENSIONS_XD_380 0x0381 #define USB_PID_XTENSIONS_XD_380 0x0381
#define USB_PID_TELESTAR_STARSTICK_2 0x8000 #define USB_PID_TELESTAR_STARSTICK_2 0x8000
#define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807 #define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807
#define USB_PID_SONY_PLAYTV 0x0003
#define USB_PID_ELGATO_EYETV_DTT 0x0021
#endif #endif

View File

@@ -223,7 +223,7 @@ struct dvb_usb_device_properties {
int generic_bulk_ctrl_endpoint; int generic_bulk_ctrl_endpoint;
int num_device_descs; int num_device_descs;
struct dvb_usb_device_description devices[9]; struct dvb_usb_device_description devices[11];
}; };
/** /**

View File

@@ -151,7 +151,7 @@ static void debug_fcp(const u8 *data, int length)
subunit_type = data[1] >> 3; subunit_type = data[1] >> 3;
subunit_id = data[1] & 7; subunit_id = data[1] & 7;
op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2]; op = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n", printk(KERN_INFO "%ssu=%x.%x l=%zu: %-8s - %s\n",
prefix, subunit_type, subunit_id, length, prefix, subunit_type, subunit_id, length,
debug_fcp_ctype(data[0]), debug_fcp_ctype(data[0]),
debug_fcp_opcode(op, data, length)); debug_fcp_opcode(op, data, length));

View File

@@ -1,17 +1,21 @@
menu "Customise DVB Frontends"
depends on DVB_CORE
config DVB_FE_CUSTOMISE config DVB_FE_CUSTOMISE
bool "Customise the frontend modules to build" bool "Customise the frontend modules to build"
depends on DVB_CORE
default N default N
help help
This allows the user to deselect frontend drivers unnecessary This allows the user to select/deselect frontend drivers for their
for their hardware from the build. Use this option with care hardware from the build.
as deselecting frontends which are in fact necessary will result
in DVB devices which cannot be tuned due to lack of driver support. Use this option with care as deselecting frontends which are in fact
necessary will result in DVB devices which cannot be tuned due to lack
of driver support.
If unsure say N. If unsure say N.
if DVB_FE_CUSTOMISE
menu "Customise DVB Frontends"
comment "Multistandard (satellite) frontends" comment "Multistandard (satellite) frontends"
depends on DVB_CORE depends on DVB_CORE
@@ -55,6 +59,13 @@ config DVB_MT312
help help
A DVB-S tuner module. Say Y when you want to support this frontend. A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_ZL10036
tristate "Zarlink ZL10036 silicon tuner"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_S5H1420 config DVB_S5H1420
tristate "Samsung S5H1420 based" tristate "Samsung S5H1420 based"
depends on DVB_CORE && I2C depends on DVB_CORE && I2C
@@ -83,6 +94,20 @@ config DVB_STV0299
help help
A DVB-S tuner module. Say Y when you want to support this frontend. A DVB-S tuner module. Say Y when you want to support this frontend.
config DVB_STV6110
tristate "ST STV6110 silicon tuner"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A DVB-S silicon tuner module. Say Y when you want to support this tuner.
config DVB_STV0900
tristate "ST STV0900 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A DVB-S/S2 demodulator. Say Y when you want to support this frontend.
config DVB_TDA8083 config DVB_TDA8083
tristate "Philips TDA8083 based" tristate "Philips TDA8083 based"
depends on DVB_CORE && I2C depends on DVB_CORE && I2C
@@ -288,6 +313,13 @@ config DVB_TDA10048
help help
A DVB-T tuner module. Say Y when you want to support this frontend. A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_AF9013
tristate "Afatech AF9013 demodulator"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
Say Y when you want to support this frontend.
comment "DVB-C (cable) frontends" comment "DVB-C (cable) frontends"
depends on DVB_CORE depends on DVB_CORE
@@ -387,6 +419,14 @@ config DVB_LGDT3304
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend. to support this frontend.
config DVB_LGDT3305
tristate "LG Electronics LGDT3305 based"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
config DVB_S5H1409 config DVB_S5H1409
tristate "Samsung S5H1409 based" tristate "Samsung S5H1409 based"
depends on DVB_CORE && I2C depends on DVB_CORE && I2C
@@ -397,7 +437,7 @@ config DVB_S5H1409
config DVB_AU8522 config DVB_AU8522
tristate "Auvitek AU8522 based" tristate "Auvitek AU8522 based"
depends on DVB_CORE && I2C depends on DVB_CORE && I2C && VIDEO_V4L2
default m if DVB_FE_CUSTOMISE default m if DVB_FE_CUSTOMISE
help help
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
@@ -446,11 +486,11 @@ comment "SEC control devices for DVB-S"
depends on DVB_CORE depends on DVB_CORE
config DVB_LNBP21 config DVB_LNBP21
tristate "LNBP21 SEC controller" tristate "LNBP21/LNBH24 SEC controllers"
depends on DVB_CORE && I2C depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE default m if DVB_FE_CUSTOMISE
help help
An SEC control chip. An SEC control chips.
config DVB_ISL6405 config DVB_ISL6405
tristate "ISL6405 SEC controller" tristate "ISL6405 SEC controller"
@@ -478,11 +518,6 @@ comment "Tools to develop new frontends"
config DVB_DUMMY_FE config DVB_DUMMY_FE
tristate "Dummy frontend driver" tristate "Dummy frontend driver"
default n default n
config DVB_AF9013
tristate "Afatech AF9013 demodulator"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
Say Y when you want to support this frontend.
endmenu endmenu
endif

View File

@@ -7,6 +7,8 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/
s921-objs := s921_module.o s921_core.o s921-objs := s921_module.o s921_core.o
stb0899-objs = stb0899_drv.o stb0899_algo.o stb0899-objs = stb0899_drv.o stb0899_algo.o
stv0900-objs = stv0900_core.o stv0900_sw.o
au8522-objs = au8522_dig.o au8522_decoder.o
obj-$(CONFIG_DVB_PLL) += dvb-pll.o obj-$(CONFIG_DVB_PLL) += dvb-pll.o
obj-$(CONFIG_DVB_STV0299) += stv0299.o obj-$(CONFIG_DVB_STV0299) += stv0299.o
@@ -28,6 +30,7 @@ obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o
obj-$(CONFIG_DVB_SP887X) += sp887x.o obj-$(CONFIG_DVB_SP887X) += sp887x.o
obj-$(CONFIG_DVB_NXT6000) += nxt6000.o obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
obj-$(CONFIG_DVB_MT352) += mt352.o obj-$(CONFIG_DVB_MT352) += mt352.o
obj-$(CONFIG_DVB_ZL10036) += zl10036.o
obj-$(CONFIG_DVB_ZL10353) += zl10353.o obj-$(CONFIG_DVB_ZL10353) += zl10353.o
obj-$(CONFIG_DVB_CX22702) += cx22702.o obj-$(CONFIG_DVB_CX22702) += cx22702.o
obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o obj-$(CONFIG_DVB_DRX397XD) += drx397xD.o
@@ -41,6 +44,7 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
obj-$(CONFIG_DVB_LGDT3304) += lgdt3304.o obj-$(CONFIG_DVB_LGDT3304) += lgdt3304.o
obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o obj-$(CONFIG_DVB_CX24123) += cx24123.o
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
obj-$(CONFIG_DVB_ISL6405) += isl6405.o obj-$(CONFIG_DVB_ISL6405) += isl6405.o
@@ -64,4 +68,6 @@ obj-$(CONFIG_DVB_SI21XX) += si21xx.o
obj-$(CONFIG_DVB_STV0288) += stv0288.o obj-$(CONFIG_DVB_STV0288) += stv0288.o
obj-$(CONFIG_DVB_STB6000) += stb6000.o obj-$(CONFIG_DVB_STB6000) += stb6000.o
obj-$(CONFIG_DVB_S921) += s921.o obj-$(CONFIG_DVB_S921) += s921.o
obj-$(CONFIG_DVB_STV6110) += stv6110.o
obj-$(CONFIG_DVB_STV0900) += stv0900.o

View File

@@ -74,6 +74,22 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config,
} }
#endif /* CONFIG_DVB_AU8522 */ #endif /* CONFIG_DVB_AU8522 */
/* Other modes may need to be added later */
enum au8522_video_input {
AU8522_COMPOSITE_CH1 = 1,
AU8522_COMPOSITE_CH2,
AU8522_COMPOSITE_CH3,
AU8522_COMPOSITE_CH4,
AU8522_COMPOSITE_CH4_SIF,
AU8522_SVIDEO_CH13,
AU8522_SVIDEO_CH24,
};
enum au8522_audio_input {
AU8522_AUDIO_NONE,
AU8522_AUDIO_SIF,
};
#endif /* __AU8522_H__ */ #endif /* __AU8522_H__ */
/* /*

View File

@@ -0,0 +1,835 @@
/*
* Auvitek AU8522 QAM/8VSB demodulator driver and video decoder
*
* Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org>
* Copyright (C) 2005-2008 Auvitek International, Ltd.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
/* Developer notes:
*
* VBI support is not yet working
* Saturation and hue setting are not yet working
* Enough is implemented here for CVBS and S-Video inputs, but the actual
* analog demodulator code isn't implemented (not needed for xc5000 since it
* has its own demodulator and outputs CVBS)
*
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <media/v4l2-common.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-i2c-drv.h>
#include <media/v4l2-device.h>
#include "au8522.h"
#include "au8522_priv.h"
MODULE_AUTHOR("Devin Heitmueller");
MODULE_LICENSE("GPL");
static int au8522_analog_debug;
module_param_named(analog_debug, au8522_analog_debug, int, 0644);
MODULE_PARM_DESC(analog_debug,
"Analog debugging messages [0=Off (default) 1=On]");
struct au8522_register_config {
u16 reg_name;
u8 reg_val[8];
};
/* Video Decoder Filter Coefficients
The values are as follows from left to right
0="ATV RF" 1="ATV RF13" 2="CVBS" 3="S-Video" 4="PAL" 5=CVBS13" 6="SVideo13"
*/
struct au8522_register_config filter_coef[] = {
{AU8522_FILTER_COEF_R410, {0x25, 0x00, 0x25, 0x25, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R411, {0x20, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R412, {0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R413, {0xe6, 0x00, 0xe6, 0xe6, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R414, {0x40, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R415, {0x1b, 0x00, 0x1b, 0x1b, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R416, {0xc0, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R417, {0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R418, {0x8c, 0x00, 0x8c, 0x8c, 0x00, 0x00, 0x00} },
{AU8522_FILTER_COEF_R419, {0xa0, 0x40, 0xa0, 0xa0, 0x40, 0x40, 0x40} },
{AU8522_FILTER_COEF_R41A, {0x21, 0x09, 0x21, 0x21, 0x09, 0x09, 0x09} },
{AU8522_FILTER_COEF_R41B, {0x6c, 0x38, 0x6c, 0x6c, 0x38, 0x38, 0x38} },
{AU8522_FILTER_COEF_R41C, {0x03, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff} },
{AU8522_FILTER_COEF_R41D, {0xbf, 0xc7, 0xbf, 0xbf, 0xc7, 0xc7, 0xc7} },
{AU8522_FILTER_COEF_R41E, {0xa0, 0xdf, 0xa0, 0xa0, 0xdf, 0xdf, 0xdf} },
{AU8522_FILTER_COEF_R41F, {0x10, 0x06, 0x10, 0x10, 0x06, 0x06, 0x06} },
{AU8522_FILTER_COEF_R420, {0xae, 0x30, 0xae, 0xae, 0x30, 0x30, 0x30} },
{AU8522_FILTER_COEF_R421, {0xc4, 0x01, 0xc4, 0xc4, 0x01, 0x01, 0x01} },
{AU8522_FILTER_COEF_R422, {0x54, 0xdd, 0x54, 0x54, 0xdd, 0xdd, 0xdd} },
{AU8522_FILTER_COEF_R423, {0xd0, 0xaf, 0xd0, 0xd0, 0xaf, 0xaf, 0xaf} },
{AU8522_FILTER_COEF_R424, {0x1c, 0xf7, 0x1c, 0x1c, 0xf7, 0xf7, 0xf7} },
{AU8522_FILTER_COEF_R425, {0x76, 0xdb, 0x76, 0x76, 0xdb, 0xdb, 0xdb} },
{AU8522_FILTER_COEF_R426, {0x61, 0xc0, 0x61, 0x61, 0xc0, 0xc0, 0xc0} },
{AU8522_FILTER_COEF_R427, {0xd1, 0x2f, 0xd1, 0xd1, 0x2f, 0x2f, 0x2f} },
{AU8522_FILTER_COEF_R428, {0x84, 0xd8, 0x84, 0x84, 0xd8, 0xd8, 0xd8} },
{AU8522_FILTER_COEF_R429, {0x06, 0xfb, 0x06, 0x06, 0xfb, 0xfb, 0xfb} },
{AU8522_FILTER_COEF_R42A, {0x21, 0xd5, 0x21, 0x21, 0xd5, 0xd5, 0xd5} },
{AU8522_FILTER_COEF_R42B, {0x0a, 0x3e, 0x0a, 0x0a, 0x3e, 0x3e, 0x3e} },
{AU8522_FILTER_COEF_R42C, {0xe6, 0x15, 0xe6, 0xe6, 0x15, 0x15, 0x15} },
{AU8522_FILTER_COEF_R42D, {0x01, 0x34, 0x01, 0x01, 0x34, 0x34, 0x34} },
};
#define NUM_FILTER_COEF (sizeof(filter_coef)\
/ sizeof(struct au8522_register_config))
/* Registers 0x060b through 0x0652 are the LP Filter coefficients
The values are as follows from left to right
0="SIF" 1="ATVRF/ATVRF13"
Note: the "ATVRF/ATVRF13" mode has never been tested
*/
struct au8522_register_config lpfilter_coef[] = {
{0x060b, {0x21, 0x0b} },
{0x060c, {0xad, 0xad} },
{0x060d, {0x70, 0xf0} },
{0x060e, {0xea, 0xe9} },
{0x060f, {0xdd, 0xdd} },
{0x0610, {0x08, 0x64} },
{0x0611, {0x60, 0x60} },
{0x0612, {0xf8, 0xb2} },
{0x0613, {0x01, 0x02} },
{0x0614, {0xe4, 0xb4} },
{0x0615, {0x19, 0x02} },
{0x0616, {0xae, 0x2e} },
{0x0617, {0xee, 0xc5} },
{0x0618, {0x56, 0x56} },
{0x0619, {0x30, 0x58} },
{0x061a, {0xf9, 0xf8} },
{0x061b, {0x24, 0x64} },
{0x061c, {0x07, 0x07} },
{0x061d, {0x30, 0x30} },
{0x061e, {0xa9, 0xed} },
{0x061f, {0x09, 0x0b} },
{0x0620, {0x42, 0xc2} },
{0x0621, {0x1d, 0x2a} },
{0x0622, {0xd6, 0x56} },
{0x0623, {0x95, 0x8b} },
{0x0624, {0x2b, 0x2b} },
{0x0625, {0x30, 0x24} },
{0x0626, {0x3e, 0x3e} },
{0x0627, {0x62, 0xe2} },
{0x0628, {0xe9, 0xf5} },
{0x0629, {0x99, 0x19} },
{0x062a, {0xd4, 0x11} },
{0x062b, {0x03, 0x04} },
{0x062c, {0xb5, 0x85} },
{0x062d, {0x1e, 0x20} },
{0x062e, {0x2a, 0xea} },
{0x062f, {0xd7, 0xd2} },
{0x0630, {0x15, 0x15} },
{0x0631, {0xa3, 0xa9} },
{0x0632, {0x1f, 0x1f} },
{0x0633, {0xf9, 0xd1} },
{0x0634, {0xc0, 0xc3} },
{0x0635, {0x4d, 0x8d} },
{0x0636, {0x21, 0x31} },
{0x0637, {0x83, 0x83} },
{0x0638, {0x08, 0x8c} },
{0x0639, {0x19, 0x19} },
{0x063a, {0x45, 0xa5} },
{0x063b, {0xef, 0xec} },
{0x063c, {0x8a, 0x8a} },
{0x063d, {0xf4, 0xf6} },
{0x063e, {0x8f, 0x8f} },
{0x063f, {0x44, 0x0c} },
{0x0640, {0xef, 0xf0} },
{0x0641, {0x66, 0x66} },
{0x0642, {0xcc, 0xd2} },
{0x0643, {0x41, 0x41} },
{0x0644, {0x63, 0x93} },
{0x0645, {0x8e, 0x8e} },
{0x0646, {0xa2, 0x42} },
{0x0647, {0x7b, 0x7b} },
{0x0648, {0x04, 0x04} },
{0x0649, {0x00, 0x00} },
{0x064a, {0x40, 0x40} },
{0x064b, {0x8c, 0x98} },
{0x064c, {0x00, 0x00} },
{0x064d, {0x63, 0xc3} },
{0x064e, {0x04, 0x04} },
{0x064f, {0x20, 0x20} },
{0x0650, {0x00, 0x00} },
{0x0651, {0x40, 0x40} },
{0x0652, {0x01, 0x01} },
};
#define NUM_LPFILTER_COEF (sizeof(lpfilter_coef)\
/ sizeof(struct au8522_register_config))
static inline struct au8522_state *to_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct au8522_state, sd);
}
static void setup_vbi(struct au8522_state *state, int aud_input)
{
int i;
/* These are set to zero regardless of what mode we're in */
au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H, 0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_L_REG018H, 0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H, 0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH, 0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH, 0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_USER_THRESH1_REG01CH, 0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH, 0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH, 0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H, 0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H,
0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H,
0x00);
au8522_writereg(state, AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H,
0x00);
/* Setup the VBI registers */
for (i = 0x30; i < 0x60; i++)
au8522_writereg(state, i, 0x40);
/* For some reason, every register is 0x40 except register 0x44
(confirmed via the HVR-950q USB capture) */
au8522_writereg(state, 0x44, 0x60);
/* Enable VBI (we always do this regardless of whether the user is
viewing closed caption info) */
au8522_writereg(state, AU8522_TVDEC_VBI_CTRL_H_REG017H,
AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON);
}
static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
{
int i;
int filter_coef_type;
/* Provide reasonable defaults for picture tuning values */
au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07);
au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed);
state->brightness = 0xed - 128;
au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79);
state->contrast = 0x79;
au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80);
au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80);
au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
/* Other decoder registers */
au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
if (input_mode == 0x23) {
/* S-Video input mapping */
au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
} else {
/* All other modes (CVBS/ATVRF etc.) */
au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
}
au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
AU8522_TVDEC_PGA_REG012H_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_MODE_REG015H,
AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
AU8522_TVDED_DBG_MODE_REG060H_CVBS);
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13);
au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13);
au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR1_REG065H,
AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR2_REG066H,
AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_VDIF_THR3_REG067H,
AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_NOTCH_THR_REG068H,
AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR1_REG069H,
AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR2_REG06AH,
AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH,
AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS);
au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH,
AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H,
AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS);
au8522_writereg(state, AU8522_REG071H, AU8522_REG071H_CVBS);
au8522_writereg(state, AU8522_REG072H, AU8522_REG072H_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H,
AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS);
au8522_writereg(state, AU8522_REG074H, AU8522_REG074H_CVBS);
au8522_writereg(state, AU8522_REG075H, AU8522_REG075H_CVBS);
au8522_writereg(state, AU8522_TVDEC_DCAGC_CTRL_REG077H,
AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS);
au8522_writereg(state, AU8522_TVDEC_PIC_START_ADJ_REG078H,
AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS);
au8522_writereg(state, AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H,
AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS);
au8522_writereg(state, AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH,
AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS);
au8522_writereg(state, AU8522_TVDEC_INTRP_CTRL_REG07BH,
AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS);
au8522_writereg(state, AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H,
AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS);
au8522_writereg(state, AU8522_TOREGAAGC_REG0E5H,
AU8522_TOREGAAGC_REG0E5H_CVBS);
au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
setup_vbi(state, 0);
if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
/* Despite what the table says, for the HVR-950q we still need
to be in CVBS mode for the S-Video input (reason uknown). */
/* filter_coef_type = 3; */
filter_coef_type = 5;
} else {
filter_coef_type = 5;
}
/* Load the Video Decoder Filter Coefficients */
for (i = 0; i < NUM_FILTER_COEF; i++) {
au8522_writereg(state, filter_coef[i].reg_name,
filter_coef[i].reg_val[filter_coef_type]);
}
/* It's not clear what these registers are for, but they are always
set to the same value regardless of what mode we're in */
au8522_writereg(state, AU8522_REG42EH, 0x87);
au8522_writereg(state, AU8522_REG42FH, 0xa2);
au8522_writereg(state, AU8522_REG430H, 0xbf);
au8522_writereg(state, AU8522_REG431H, 0xcb);
au8522_writereg(state, AU8522_REG432H, 0xa1);
au8522_writereg(state, AU8522_REG433H, 0x41);
au8522_writereg(state, AU8522_REG434H, 0x88);
au8522_writereg(state, AU8522_REG435H, 0xc2);
au8522_writereg(state, AU8522_REG436H, 0x3c);
}
static void au8522_setup_cvbs_mode(struct au8522_state *state)
{
/* here we're going to try the pre-programmed route */
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
}
static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
{
/* here we're going to try the pre-programmed route */
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS);
/* It's not clear why they turn off the PGA before enabling the clamp
control, but the Windows trace does it so we will too... */
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
/* Enable clamping control */
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
/* Turn on the PGA */
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
/* Set input mode to CVBS on channel 4 with SIF audio input enabled */
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
setup_decoder_defaults(state,
AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
}
static void au8522_setup_svideo_mode(struct au8522_state *state)
{
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
/* Set input to Y on Channe1, C on Channel 3 */
au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
/* Disable clamping control (required for S-video) */
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
setup_decoder_defaults(state,
AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
}
/* ----------------------------------------------------------------------- */
static void disable_audio_input(struct au8522_state *state)
{
/* This can probably be optimized */
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00);
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40);
au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11);
msleep(5);
au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
}
/* 0=disable, 1=SIF */
static void set_audio_input(struct au8522_state *state, int aud_input)
{
int i;
/* Note that this function needs to be used in conjunction with setting
the input routing via register 0x81 */
if (aud_input == AU8522_AUDIO_NONE) {
disable_audio_input(state);
return;
}
if (aud_input != AU8522_AUDIO_SIF) {
/* The caller asked for a mode we don't currently support */
printk(KERN_ERR "Unsupported audio mode requested! mode=%d\n",
aud_input);
return;
}
/* Load the Audio Decoder Filter Coefficients */
for (i = 0; i < NUM_LPFILTER_COEF; i++) {
au8522_writereg(state, lpfilter_coef[i].reg_name,
lpfilter_coef[i].reg_val[0]);
}
/* Setup audio */
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00);
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00);
au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00);
au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80);
au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
msleep(150);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
msleep(1);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
msleep(50);
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0xff);
msleep(80);
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO);
au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x82);
msleep(70);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x09);
au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03);
au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0xc2);
}
/* ----------------------------------------------------------------------- */
static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
struct au8522_state *state = to_state(sd);
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
state->brightness = ctrl->value;
au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
ctrl->value - 128);
break;
case V4L2_CID_CONTRAST:
state->contrast = ctrl->value;
au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
ctrl->value);
break;
case V4L2_CID_SATURATION:
case V4L2_CID_HUE:
case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_MUTE:
/* Not yet implemented */
default:
return -EINVAL;
}
return 0;
}
static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
struct au8522_state *state = to_state(sd);
/* Note that we are using values cached in the state structure instead
of reading the registers due to issues with i2c reads not working
properly/consistently yet on the HVR-950q */
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
ctrl->value = state->brightness;
break;
case V4L2_CID_CONTRAST:
ctrl->value = state->contrast;
break;
case V4L2_CID_SATURATION:
case V4L2_CID_HUE:
case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_MUTE:
/* Not yet supported */
default:
return -EINVAL;
}
return 0;
}
/* ----------------------------------------------------------------------- */
static int au8522_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
{
switch (fmt->type) {
default:
return -EINVAL;
}
return 0;
}
static int au8522_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
{
switch (fmt->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
/* Not yet implemented */
break;
default:
return -EINVAL;
}
return 0;
}
/* ----------------------------------------------------------------------- */
#ifdef CONFIG_VIDEO_ADV_DEBUG
static int au8522_g_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct au8522_state *state = to_state(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
reg->val = au8522_readreg(state, reg->reg & 0xffff);
return 0;
}
static int au8522_s_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct au8522_state *state = to_state(sd);
if (!v4l2_chip_match_i2c_client(client, &reg->match))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
au8522_writereg(state, reg->reg, reg->val & 0xff);
return 0;
}
#endif
static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
{
struct au8522_state *state = to_state(sd);
if (enable) {
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
0x01);
msleep(1);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
} else {
/* This does not completely power down the device
(it only reduces it from around 140ma to 80ma) */
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
1 << 5);
}
return 0;
}
static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
{
switch (qc->id) {
case V4L2_CID_CONTRAST:
return v4l2_ctrl_query_fill(qc, 0, 255, 1,
AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
case V4L2_CID_BRIGHTNESS:
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
case V4L2_CID_SATURATION:
case V4L2_CID_HUE:
/* Not yet implemented */
default:
break;
}
qc->type = 0;
return -EINVAL;
}
static int au8522_reset(struct v4l2_subdev *sd, u32 val)
{
struct au8522_state *state = to_state(sd);
au8522_writereg(state, 0xa4, 1 << 5);
return 0;
}
static int au8522_s_video_routing(struct v4l2_subdev *sd,
const struct v4l2_routing *route)
{
struct au8522_state *state = to_state(sd);
au8522_reset(sd, 0);
/* Jam open the i2c gate to the tuner. We do this here to handle the
case where the user went into digital mode (causing the gate to be
closed), and then came back to analog mode */
au8522_writereg(state, 0x106, 1);
if (route->input == AU8522_COMPOSITE_CH1) {
au8522_setup_cvbs_mode(state);
} else if (route->input == AU8522_SVIDEO_CH13) {
au8522_setup_svideo_mode(state);
} else if (route->input == AU8522_COMPOSITE_CH4_SIF) {
au8522_setup_cvbs_tuner_mode(state);
} else {
printk(KERN_ERR "au8522 mode not currently supported\n");
return -EINVAL;
}
return 0;
}
static int au8522_s_audio_routing(struct v4l2_subdev *sd,
const struct v4l2_routing *route)
{
struct au8522_state *state = to_state(sd);
set_audio_input(state, route->input);
return 0;
}
static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
{
int val = 0;
struct au8522_state *state = to_state(sd);
u8 lock_status;
/* Interrogate the decoder to see if we are getting a real signal */
lock_status = au8522_readreg(state, 0x00);
if (lock_status == 0xa2)
vt->signal = 0x01;
else
vt->signal = 0x00;
vt->capability |=
V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
val = V4L2_TUNER_SUB_MONO;
vt->rxsubchans = val;
vt->audmode = V4L2_TUNER_MODE_STEREO;
return 0;
}
static int au8522_g_chip_ident(struct v4l2_subdev *sd,
struct v4l2_dbg_chip_ident *chip)
{
struct au8522_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
}
static int au8522_log_status(struct v4l2_subdev *sd)
{
/* FIXME: Add some status info here */
return 0;
}
/* ----------------------------------------------------------------------- */
static const struct v4l2_subdev_core_ops au8522_core_ops = {
.log_status = au8522_log_status,
.g_chip_ident = au8522_g_chip_ident,
.g_ctrl = au8522_g_ctrl,
.s_ctrl = au8522_s_ctrl,
.queryctrl = au8522_queryctrl,
.reset = au8522_reset,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = au8522_g_register,
.s_register = au8522_s_register,
#endif
};
static const struct v4l2_subdev_tuner_ops au8522_tuner_ops = {
.g_tuner = au8522_g_tuner,
};
static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
.s_routing = au8522_s_audio_routing,
};
static const struct v4l2_subdev_video_ops au8522_video_ops = {
.s_routing = au8522_s_video_routing,
.g_fmt = au8522_g_fmt,
.s_fmt = au8522_s_fmt,
.s_stream = au8522_s_stream,
};
static const struct v4l2_subdev_ops au8522_ops = {
.core = &au8522_core_ops,
.tuner = &au8522_tuner_ops,
.audio = &au8522_audio_ops,
.video = &au8522_video_ops,
};
/* ----------------------------------------------------------------------- */
static int au8522_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct au8522_state *state;
struct v4l2_subdev *sd;
int instance;
struct au8522_config *demod_config;
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA)) {
return -EIO;
}
/* allocate memory for the internal state */
instance = au8522_get_state(&state, client->adapter, client->addr);
switch (instance) {
case 0:
printk(KERN_ERR "au8522_decoder allocation failed\n");
return -EIO;
case 1:
/* new demod instance */
printk(KERN_INFO "au8522_decoder creating new instance...\n");
break;
default:
/* existing demod instance */
printk(KERN_INFO "au8522_decoder attach existing instance.\n");
break;
}
demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL);
demod_config->demod_address = 0x8e >> 1;
state->config = demod_config;
state->i2c = client->adapter;
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &au8522_ops);
state->c = client;
state->vid_input = AU8522_COMPOSITE_CH1;
state->aud_input = AU8522_AUDIO_NONE;
state->id = 8522;
state->rev = 0;
/* Jam open the i2c gate to the tuner */
au8522_writereg(state, 0x106, 1);
return 0;
}
static int au8522_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd);
au8522_release_state(to_state(sd));
return 0;
}
static const struct i2c_device_id au8522_id[] = {
{"au8522", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, au8522_id);
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "au8522",
.probe = au8522_probe,
.remove = au8522_remove,
.id_table = au8522_id,
};

View File

@@ -27,35 +27,25 @@
#include <linux/delay.h> #include <linux/delay.h>
#include "dvb_frontend.h" #include "dvb_frontend.h"
#include "au8522.h" #include "au8522.h"
#include "au8522_priv.h"
struct au8522_state {
struct i2c_adapter *i2c;
/* configuration settings */
const struct au8522_config *config;
struct dvb_frontend frontend;
u32 current_frequency;
fe_modulation_t current_modulation;
u32 fe_status;
unsigned int led_state;
};
static int debug; static int debug;
#define dprintk(arg...) do { \ /* Despite the name "hybrid_tuner", the framework works just as well for
if (debug) \ hybrid demodulators as well... */
static LIST_HEAD(hybrid_tuner_instance_list);
static DEFINE_MUTEX(au8522_list_mutex);
#define dprintk(arg...)\
do { if (debug)\
printk(arg);\ printk(arg);\
} while (0) } while (0)
/* 16 bit registers, 8 bit values */ /* 16 bit registers, 8 bit values */
static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data) int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
{ {
int ret; int ret;
u8 buf [] = { reg >> 8, reg & 0xff, data }; u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
struct i2c_msg msg = { .addr = state->config->demod_address, struct i2c_msg msg = { .addr = state->config->demod_address,
.flags = 0, .buf = buf, .len = 3 }; .flags = 0, .buf = buf, .len = 3 };
@@ -69,10 +59,10 @@ static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
return (ret != 1) ? -1 : 0; return (ret != 1) ? -1 : 0;
} }
static u8 au8522_readreg(struct au8522_state *state, u16 reg) u8 au8522_readreg(struct au8522_state *state, u16 reg)
{ {
int ret; int ret;
u8 b0 [] = { reg >> 8, reg & 0xff }; u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
u8 b1[] = { 0 }; u8 b1[] = { 0 };
struct i2c_msg msg[] = { struct i2c_msg msg[] = {
@@ -528,7 +518,7 @@ static int au8522_set_frontend(struct dvb_frontend *fe,
/* Reset the demod hardware and reset all of the configuration registers /* Reset the demod hardware and reset all of the configuration registers
to a default state. */ to a default state. */
static int au8522_init(struct dvb_frontend *fe) int au8522_init(struct dvb_frontend *fe)
{ {
struct au8522_state *state = fe->demodulator_priv; struct au8522_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__); dprintk("%s()\n", __func__);
@@ -624,7 +614,7 @@ static int au8522_led_ctrl(struct au8522_state *state, int led)
return 0; return 0;
} }
static int au8522_sleep(struct dvb_frontend *fe) int au8522_sleep(struct dvb_frontend *fe)
{ {
struct au8522_state *state = fe->demodulator_priv; struct au8522_state *state = fe->demodulator_priv;
dprintk("%s()\n", __func__); dprintk("%s()\n", __func__);
@@ -632,6 +622,9 @@ static int au8522_sleep(struct dvb_frontend *fe)
/* turn off led */ /* turn off led */
au8522_led_ctrl(state, 0); au8522_led_ctrl(state, 0);
/* Power down the chip */
au8522_writereg(state, 0xa4, 1 << 5);
state->current_frequency = 0; state->current_frequency = 0;
return 0; return 0;
@@ -798,23 +791,58 @@ static int au8522_get_tune_settings(struct dvb_frontend *fe,
return 0; return 0;
} }
static struct dvb_frontend_ops au8522_ops;
int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
u8 client_address)
{
int ret;
mutex_lock(&au8522_list_mutex);
ret = hybrid_tuner_request_state(struct au8522_state, (*state),
hybrid_tuner_instance_list,
i2c, client_address, "au8522");
mutex_unlock(&au8522_list_mutex);
return ret;
}
void au8522_release_state(struct au8522_state *state)
{
mutex_lock(&au8522_list_mutex);
if (state != NULL)
hybrid_tuner_release_state(state);
mutex_unlock(&au8522_list_mutex);
}
static void au8522_release(struct dvb_frontend *fe) static void au8522_release(struct dvb_frontend *fe)
{ {
struct au8522_state *state = fe->demodulator_priv; struct au8522_state *state = fe->demodulator_priv;
kfree(state); au8522_release_state(state);
} }
static struct dvb_frontend_ops au8522_ops;
struct dvb_frontend *au8522_attach(const struct au8522_config *config, struct dvb_frontend *au8522_attach(const struct au8522_config *config,
struct i2c_adapter *i2c) struct i2c_adapter *i2c)
{ {
struct au8522_state *state = NULL; struct au8522_state *state = NULL;
int instance;
/* allocate memory for the internal state */ /* allocate memory for the internal state */
state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL); instance = au8522_get_state(&state, i2c, config->demod_address);
if (state == NULL) switch (instance) {
goto error; case 0:
dprintk("%s state allocation failed\n", __func__);
break;
case 1:
/* new demod instance */
dprintk("%s using new instance\n", __func__);
break;
default:
/* existing demod instance */
dprintk("%s using existing instance\n", __func__);
break;
}
/* setup the state */ /* setup the state */
state->config = config; state->config = config;
@@ -836,7 +864,7 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config,
return &state->frontend; return &state->frontend;
error: error:
kfree(state); au8522_release_state(state);
return NULL; return NULL;
} }
EXPORT_SYMBOL(au8522_attach); EXPORT_SYMBOL(au8522_attach);

View File

@@ -0,0 +1,412 @@
/*
Auvitek AU8522 QAM/8VSB demodulator driver
Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
Copyright (C) 2008 Devin Heitmueller <dheitmueller@linuxtv.org>
Copyright (C) 2005-2008 Auvitek International, Ltd.
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/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/videodev2.h>
#include <media/v4l2-device.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
#include "au8522.h"
#include "tuner-i2c.h"
struct au8522_state {
struct i2c_client *c;
struct i2c_adapter *i2c;
/* Used for sharing of the state between analog and digital mode */
struct tuner_i2c_props i2c_props;
struct list_head hybrid_tuner_instance_list;
/* configuration settings */
const struct au8522_config *config;
struct dvb_frontend frontend;
u32 current_frequency;
fe_modulation_t current_modulation;
u32 fe_status;
unsigned int led_state;
/* Analog settings */
struct v4l2_subdev sd;
v4l2_std_id std;
int vid_input;
int aud_input;
u32 id;
u32 rev;
u8 brightness;
u8 contrast;
};
/* These are routines shared by both the VSB/QAM demodulator and the analog
decoder */
int au8522_writereg(struct au8522_state *state, u16 reg, u8 data);
u8 au8522_readreg(struct au8522_state *state, u16 reg);
int au8522_init(struct dvb_frontend *fe);
int au8522_sleep(struct dvb_frontend *fe);
int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
u8 client_address);
void au8522_release_state(struct au8522_state *state);
/* REGISTERS */
#define AU8522_INPUT_CONTROL_REG081H 0x081
#define AU8522_PGA_CONTROL_REG082H 0x082
#define AU8522_CLAMPING_CONTROL_REG083H 0x083
#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H 0x0A3
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H 0x0A4
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H 0x0A5
#define AU8522_AGC_CONTROL_RANGE_REG0A6H 0x0A6
#define AU8522_SYSTEM_GAIN_CONTROL_REG0A7H 0x0A7
#define AU8522_TUNER_AGC_RF_STOP_REG0A8H 0x0A8
#define AU8522_TUNER_AGC_RF_START_REG0A9H 0x0A9
#define AU8522_TUNER_RF_AGC_DEFAULT_REG0AAH 0x0AA
#define AU8522_TUNER_AGC_IF_STOP_REG0ABH 0x0AB
#define AU8522_TUNER_AGC_IF_START_REG0ACH 0x0AC
#define AU8522_TUNER_AGC_IF_DEFAULT_REG0ADH 0x0AD
#define AU8522_TUNER_AGC_STEP_REG0AEH 0x0AE
#define AU8522_TUNER_GAIN_STEP_REG0AFH 0x0AF
/* Receiver registers */
#define AU8522_FRMREGTHRD1_REG0B0H 0x0B0
#define AU8522_FRMREGAGC1H_REG0B1H 0x0B1
#define AU8522_FRMREGSHIFT1_REG0B2H 0x0B2
#define AU8522_TOREGAGC1_REG0B3H 0x0B3
#define AU8522_TOREGASHIFT1_REG0B4H 0x0B4
#define AU8522_FRMREGBBH_REG0B5H 0x0B5
#define AU8522_FRMREGBBM_REG0B6H 0x0B6
#define AU8522_FRMREGBBL_REG0B7H 0x0B7
/* 0xB8 TO 0xD7 are the filter coefficients */
#define AU8522_FRMREGTHRD2_REG0D8H 0x0D8
#define AU8522_FRMREGAGC2H_REG0D9H 0x0D9
#define AU8522_TOREGAGC2_REG0DAH 0x0DA
#define AU8522_TOREGSHIFT2_REG0DBH 0x0DB
#define AU8522_FRMREGPILOTH_REG0DCH 0x0DC
#define AU8522_FRMREGPILOTM_REG0DDH 0x0DD
#define AU8522_FRMREGPILOTL_REG0DEH 0x0DE
#define AU8522_TOREGFREQ_REG0DFH 0x0DF
#define AU8522_RX_PGA_RFOUT_REG0EBH 0x0EB
#define AU8522_RX_PGA_IFOUT_REG0ECH 0x0EC
#define AU8522_RX_PGA_PGAOUT_REG0EDH 0x0ED
#define AU8522_CHIP_MODE_REG0FEH 0x0FE
/* I2C bus control registers */
#define AU8522_I2C_CONTROL_REG0_REG090H 0x090
#define AU8522_I2C_CONTROL_REG1_REG091H 0x091
#define AU8522_I2C_STATUS_REG092H 0x092
#define AU8522_I2C_WR_DATA0_REG093H 0x093
#define AU8522_I2C_WR_DATA1_REG094H 0x094
#define AU8522_I2C_WR_DATA2_REG095H 0x095
#define AU8522_I2C_WR_DATA3_REG096H 0x096
#define AU8522_I2C_WR_DATA4_REG097H 0x097
#define AU8522_I2C_WR_DATA5_REG098H 0x098
#define AU8522_I2C_WR_DATA6_REG099H 0x099
#define AU8522_I2C_WR_DATA7_REG09AH 0x09A
#define AU8522_I2C_RD_DATA0_REG09BH 0x09B
#define AU8522_I2C_RD_DATA1_REG09CH 0x09C
#define AU8522_I2C_RD_DATA2_REG09DH 0x09D
#define AU8522_I2C_RD_DATA3_REG09EH 0x09E
#define AU8522_I2C_RD_DATA4_REG09FH 0x09F
#define AU8522_I2C_RD_DATA5_REG0A0H 0x0A0
#define AU8522_I2C_RD_DATA6_REG0A1H 0x0A1
#define AU8522_I2C_RD_DATA7_REG0A2H 0x0A2
#define AU8522_ENA_USB_REG101H 0x101
#define AU8522_I2S_CTRL_0_REG110H 0x110
#define AU8522_I2S_CTRL_1_REG111H 0x111
#define AU8522_I2S_CTRL_2_REG112H 0x112
#define AU8522_FRMREGFFECONTROL_REG121H 0x121
#define AU8522_FRMREGDFECONTROL_REG122H 0x122
#define AU8522_CARRFREQOFFSET0_REG201H 0x201
#define AU8522_CARRFREQOFFSET1_REG202H 0x202
#define AU8522_DECIMATION_GAIN_REG21AH 0x21A
#define AU8522_FRMREGIFSLP_REG21BH 0x21B
#define AU8522_FRMREGTHRDL2_REG21CH 0x21C
#define AU8522_FRMREGSTEP3DB_REG21DH 0x21D
#define AU8522_DAGC_GAIN_ADJUSTMENT_REG21EH 0x21E
#define AU8522_FRMREGPLLMODE_REG21FH 0x21F
#define AU8522_FRMREGCSTHRD_REG220H 0x220
#define AU8522_FRMREGCRLOCKDMAX_REG221H 0x221
#define AU8522_FRMREGCRPERIODMASK_REG222H 0x222
#define AU8522_FRMREGCRLOCK0THH_REG223H 0x223
#define AU8522_FRMREGCRLOCK1THH_REG224H 0x224
#define AU8522_FRMREGCRLOCK0THL_REG225H 0x225
#define AU8522_FRMREGCRLOCK1THL_REG226H 0x226
#define AU_FRMREGPLLACQPHASESCL_REG227H 0x227
#define AU8522_FRMREGFREQFBCTRL_REG228H 0x228
/* Analog TV Decoder */
#define AU8522_TVDEC_STATUS_REG000H 0x000
#define AU8522_TVDEC_INT_STATUS_REG001H 0x001
#define AU8522_TVDEC_MACROVISION_STATUS_REG002H 0x002
#define AU8522_TVDEC_SHARPNESSREG009H 0x009
#define AU8522_TVDEC_BRIGHTNESS_REG00AH 0x00A
#define AU8522_TVDEC_CONTRAST_REG00BH 0x00B
#define AU8522_TVDEC_SATURATION_CB_REG00CH 0x00C
#define AU8522_TVDEC_SATURATION_CR_REG00DH 0x00D
#define AU8522_TVDEC_HUE_H_REG00EH 0x00E
#define AU8522_TVDEC_HUE_L_REG00FH 0x00F
#define AU8522_TVDEC_INT_MASK_REG010H 0x010
#define AU8522_VIDEO_MODE_REG011H 0x011
#define AU8522_TVDEC_PGA_REG012H 0x012
#define AU8522_TVDEC_COMB_MODE_REG015H 0x015
#define AU8522_REG016H 0x016
#define AU8522_TVDED_DBG_MODE_REG060H 0x060
#define AU8522_TVDEC_FORMAT_CTRL1_REG061H 0x061
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H 0x062
#define AU8522_TVDEC_VCR_DET_LLIM_REG063H 0x063
#define AU8522_TVDEC_VCR_DET_HLIM_REG064H 0x064
#define AU8522_TVDEC_COMB_VDIF_THR1_REG065H 0x065
#define AU8522_TVDEC_COMB_VDIF_THR2_REG066H 0x066
#define AU8522_TVDEC_COMB_VDIF_THR3_REG067H 0x067
#define AU8522_TVDEC_COMB_NOTCH_THR_REG068H 0x068
#define AU8522_TVDEC_COMB_HDIF_THR1_REG069H 0x069
#define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH 0x06A
#define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH 0x06B
#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH 0x06C
#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH 0x06D
#define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH 0x06E
#define AU8522_TVDEC_UV_SEP_THR_REG06FH 0x06F
#define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H 0x070
#define AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H 0x073
#define AU8522_TVDEC_DCAGC_CTRL_REG077H 0x077
#define AU8522_TVDEC_PIC_START_ADJ_REG078H 0x078
#define AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H 0x079
#define AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH 0x07A
#define AU8522_TVDEC_INTRP_CTRL_REG07BH 0x07B
#define AU8522_TVDEC_PLL_STATUS_REG07EH 0x07E
#define AU8522_TVDEC_FSC_FREQ_REG07FH 0x07F
#define AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H 0x0E4
#define AU8522_TOREGAAGC_REG0E5H 0x0E5
#define AU8522_TVDEC_CHROMA_AGC_REG401H 0x401
#define AU8522_TVDEC_CHROMA_SFT_REG402H 0x402
#define AU8522_FILTER_COEF_R410 0x410
#define AU8522_FILTER_COEF_R411 0x411
#define AU8522_FILTER_COEF_R412 0x412
#define AU8522_FILTER_COEF_R413 0x413
#define AU8522_FILTER_COEF_R414 0x414
#define AU8522_FILTER_COEF_R415 0x415
#define AU8522_FILTER_COEF_R416 0x416
#define AU8522_FILTER_COEF_R417 0x417
#define AU8522_FILTER_COEF_R418 0x418
#define AU8522_FILTER_COEF_R419 0x419
#define AU8522_FILTER_COEF_R41A 0x41A
#define AU8522_FILTER_COEF_R41B 0x41B
#define AU8522_FILTER_COEF_R41C 0x41C
#define AU8522_FILTER_COEF_R41D 0x41D
#define AU8522_FILTER_COEF_R41E 0x41E
#define AU8522_FILTER_COEF_R41F 0x41F
#define AU8522_FILTER_COEF_R420 0x420
#define AU8522_FILTER_COEF_R421 0x421
#define AU8522_FILTER_COEF_R422 0x422
#define AU8522_FILTER_COEF_R423 0x423
#define AU8522_FILTER_COEF_R424 0x424
#define AU8522_FILTER_COEF_R425 0x425
#define AU8522_FILTER_COEF_R426 0x426
#define AU8522_FILTER_COEF_R427 0x427
#define AU8522_FILTER_COEF_R428 0x428
#define AU8522_FILTER_COEF_R429 0x429
#define AU8522_FILTER_COEF_R42A 0x42A
#define AU8522_FILTER_COEF_R42B 0x42B
#define AU8522_FILTER_COEF_R42C 0x42C
#define AU8522_FILTER_COEF_R42D 0x42D
/* VBI Control Registers */
#define AU8522_TVDEC_VBI_RX_FIFO_CONTAIN_REG004H 0x004
#define AU8522_TVDEC_VBI_TX_FIFO_CONTAIN_REG005H 0x005
#define AU8522_TVDEC_VBI_RX_FIFO_READ_REG006H 0x006
#define AU8522_TVDEC_VBI_FIFO_STATUS_REG007H 0x007
#define AU8522_TVDEC_VBI_CTRL_H_REG017H 0x017
#define AU8522_TVDEC_VBI_CTRL_L_REG018H 0x018
#define AU8522_TVDEC_VBI_USER_TOTAL_BITS_REG019H 0x019
#define AU8522_TVDEC_VBI_USER_TUNIT_H_REG01AH 0x01A
#define AU8522_TVDEC_VBI_USER_TUNIT_L_REG01BH 0x01B
#define AU8522_TVDEC_VBI_USER_THRESH1_REG01CH 0x01C
#define AU8522_TVDEC_VBI_USER_FRAME_PAT2_REG01EH 0x01E
#define AU8522_TVDEC_VBI_USER_FRAME_PAT1_REG01FH 0x01F
#define AU8522_TVDEC_VBI_USER_FRAME_PAT0_REG020H 0x020
#define AU8522_TVDEC_VBI_USER_FRAME_MASK2_REG021H 0x021
#define AU8522_TVDEC_VBI_USER_FRAME_MASK1_REG022H 0x022
#define AU8522_TVDEC_VBI_USER_FRAME_MASK0_REG023H 0x023
#define AU8522_REG071H 0x071
#define AU8522_REG072H 0x072
#define AU8522_REG074H 0x074
#define AU8522_REG075H 0x075
/* Digital Demodulator Registers */
#define AU8522_FRAME_COUNT0_REG084H 0x084
#define AU8522_RS_STATUS_G0_REG085H 0x085
#define AU8522_RS_STATUS_B0_REG086H 0x086
#define AU8522_RS_STATUS_E_REG087H 0x087
#define AU8522_DEMODULATION_STATUS_REG088H 0x088
#define AU8522_TOREGTRESTATUS_REG0E6H 0x0E6
#define AU8522_TSPORT_CONTROL_REG10BH 0x10B
#define AU8522_TSTHES_REG10CH 0x10C
#define AU8522_FRMREGDFEKEEP_REG301H 0x301
#define AU8522_DFE_AVERAGE_REG302H 0x302
#define AU8522_FRMREGEQLERRWIN_REG303H 0x303
#define AU8522_FRMREGFFEKEEP_REG304H 0x304
#define AU8522_FRMREGDFECONTROL1_REG305H 0x305
#define AU8522_FRMREGEQLERRLOW_REG306H 0x306
#define AU8522_REG42EH 0x42E
#define AU8522_REG42FH 0x42F
#define AU8522_REG430H 0x430
#define AU8522_REG431H 0x431
#define AU8522_REG432H 0x432
#define AU8522_REG433H 0x433
#define AU8522_REG434H 0x434
#define AU8522_REG435H 0x435
#define AU8522_REG436H 0x436
/* GPIO Registers */
#define AU8522_GPIO_CONTROL_REG0E0H 0x0E0
#define AU8522_GPIO_STATUS_REG0E1H 0x0E1
#define AU8522_GPIO_DATA_REG0E2H 0x0E2
/* Audio Control Registers */
#define AU8522_AUDIOAGC_REG0EEH 0x0EE
#define AU8522_AUDIO_STATUS_REG0F0H 0x0F0
#define AU8522_AUDIO_MODE_REG0F1H 0x0F1
#define AU8522_AUDIO_VOLUME_L_REG0F2H 0x0F2
#define AU8522_AUDIO_VOLUME_R_REG0F3H 0x0F3
#define AU8522_AUDIO_VOLUME_REG0F4H 0x0F4
#define AU8522_FRMREGAUPHASE_REG0F7H 0x0F7
#define AU8522_REG0F9H 0x0F9
#define AU8522_AUDIOAGC2_REG605H 0x605
#define AU8522_AUDIOFREQ_REG606H 0x606
/**************************************************************/
#define AU8522_INPUT_CONTROL_REG081H_ATSC 0xC4
#define AU8522_INPUT_CONTROL_REG081H_ATVRF 0xC4
#define AU8522_INPUT_CONTROL_REG081H_ATVRF13 0xC4
#define AU8522_INPUT_CONTROL_REG081H_J83B64 0xC4
#define AU8522_INPUT_CONTROL_REG081H_J83B256 0xC4
#define AU8522_INPUT_CONTROL_REG081H_CVBS 0x20
#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH1 0xA2
#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH2 0xA0
#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH3 0x69
#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH4 0x68
#define AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF 0x28
/* CH1 AS Y,CH3 AS C */
#define AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 0x23
/* CH2 AS Y,CH4 AS C */
#define AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24 0x20
#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATSC 0x0C
#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_J83B64 0x09
#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_J83B256 0x09
#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS 0x12
#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATVRF 0x1A
#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_ATVRF13 0x1A
#define AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO 0x02
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CLEAR 0x00
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO 0x9C
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS 0x9D
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATSC 0xE8
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_J83B256 0xCA
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_J83B64 0xCA
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATVRF 0xDD
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_ATVRF13 0xDD
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_PAL 0xDD
#define AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_FM 0xDD
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATSC 0x80
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_J83B256 0x80
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_J83B64 0x80
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_ATSC 0x40
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_J83B256 0x40
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_J83B64 0x40
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_DONGLE_CLEAR 0x00
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATVRF 0x01
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_ATVRF13 0x01
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_SVIDEO 0x04
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_CVBS 0x01
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_PWM 0x03
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_IIS 0x09
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_PAL 0x01
#define AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H_FM 0x01
/* STILL NEED TO BE REFACTORED @@@@@@@@@@@@@@ */
#define AU8522_TVDEC_CONTRAST_REG00BH_CVBS 0x79
#define AU8522_TVDEC_SATURATION_CB_REG00CH_CVBS 0x80
#define AU8522_TVDEC_SATURATION_CR_REG00DH_CVBS 0x80
#define AU8522_TVDEC_HUE_H_REG00EH_CVBS 0x00
#define AU8522_TVDEC_HUE_L_REG00FH_CVBS 0x00
#define AU8522_TVDEC_PGA_REG012H_CVBS 0x0F
#define AU8522_TVDEC_COMB_MODE_REG015H_CVBS 0x00
#define AU8522_REG016H_CVBS 0x00
#define AU8522_TVDED_DBG_MODE_REG060H_CVBS 0x00
#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS 0x0B
#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13 0x03
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13 0x00
#define AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS 0x19
#define AU8522_REG0F9H_AUDIO 0x20
#define AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS 0xA7
#define AU8522_TVDEC_COMB_VDIF_THR1_REG065H_CVBS 0x0A
#define AU8522_TVDEC_COMB_VDIF_THR2_REG066H_CVBS 0x32
#define AU8522_TVDEC_COMB_VDIF_THR3_REG067H_CVBS 0x19
#define AU8522_TVDEC_COMB_NOTCH_THR_REG068H_CVBS 0x23
#define AU8522_TVDEC_COMB_HDIF_THR1_REG069H_CVBS 0x41
#define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS 0x0A
#define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS 0x32
#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS 0x34
#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS 0x05
#define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS 0x6E
#define AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS 0x0F
#define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS 0x80
#define AU8522_REG071H_CVBS 0x18
#define AU8522_REG072H_CVBS 0x30
#define AU8522_TVDEC_COMB_DC_THR2_NTSC_REG073H_CVBS 0xF0
#define AU8522_REG074H_CVBS 0x80
#define AU8522_REG075H_CVBS 0xF0
#define AU8522_TVDEC_DCAGC_CTRL_REG077H_CVBS 0xFB
#define AU8522_TVDEC_PIC_START_ADJ_REG078H_CVBS 0x04
#define AU8522_TVDEC_AGC_HIGH_LIMIT_REG079H_CVBS 0x00
#define AU8522_TVDEC_MACROVISION_SYNC_THR_REG07AH_CVBS 0x00
#define AU8522_TVDEC_INTRP_CTRL_REG07BH_CVBS 0xEE
#define AU8522_TVDEC_AGC_LOW_LIMIT_REG0E4H_CVBS 0xFE
#define AU8522_TOREGAAGC_REG0E5H_CVBS 0x00
#define AU8522_TVDEC_VBI6A_REG035H_CVBS 0x40
/* Enables Closed captioning */
#define AU8522_TVDEC_VBI_CTRL_H_REG017H_CCON 0x21

View File

@@ -559,7 +559,7 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
kzalloc(sizeof(struct cx24113_state), GFP_KERNEL); kzalloc(sizeof(struct cx24113_state), GFP_KERNEL);
int rc; int rc;
if (state == NULL) { if (state == NULL) {
err("Unable to kmalloc\n"); err("Unable to kzalloc\n");
goto error; goto error;
} }

View File

@@ -15,6 +15,9 @@
September, 9th 2008 September, 9th 2008
Fixed locking on high symbol rates (>30000). Fixed locking on high symbol rates (>30000).
Implement MPEG initialization parameter. Implement MPEG initialization parameter.
January, 17th 2009
Fill set_voltage with actually control voltage code.
Correct set tone to not affect voltage.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@@ -146,7 +149,7 @@ enum cmds {
CMD_GETAGC = 0x19, CMD_GETAGC = 0x19,
CMD_LNBCONFIG = 0x20, CMD_LNBCONFIG = 0x20,
CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */ CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */
CMD_SET_TONEPRE = 0x22, CMD_LNBDCLEVEL = 0x22,
CMD_SET_TONE = 0x23, CMD_SET_TONE = 0x23,
CMD_UPDFWVERS = 0x35, CMD_UPDFWVERS = 0x35,
CMD_TUNERSLEEP = 0x36, CMD_TUNERSLEEP = 0x36,
@@ -667,16 +670,6 @@ static int cx24116_load_firmware(struct dvb_frontend *fe,
return 0; return 0;
} }
static int cx24116_set_voltage(struct dvb_frontend *fe,
fe_sec_voltage_t voltage)
{
/* The isl6421 module will override this function in the fops. */
dprintk("%s() This should never appear if the isl6421 module "
"is loaded correctly\n", __func__);
return -EOPNOTSUPP;
}
static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status) static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
{ {
struct cx24116_state *state = fe->demodulator_priv; struct cx24116_state *state = fe->demodulator_priv;
@@ -837,6 +830,34 @@ static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
return -ETIMEDOUT; /* -EBUSY ? */ return -ETIMEDOUT; /* -EBUSY ? */
} }
static int cx24116_set_voltage(struct dvb_frontend *fe,
fe_sec_voltage_t voltage)
{
struct cx24116_cmd cmd;
int ret;
dprintk("%s: %s\n", __func__,
voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
/* Wait for LNB ready */
ret = cx24116_wait_for_lnb(fe);
if (ret != 0)
return ret;
/* Wait for voltage/min repeat delay */
msleep(100);
cmd.args[0x00] = CMD_LNBDCLEVEL;
cmd.args[0x01] = (voltage == SEC_VOLTAGE_18 ? 0x01 : 0x00);
cmd.len = 0x02;
/* Min delay time before DiSEqC send */
msleep(15);
return cx24116_cmd_execute(fe, &cmd);
}
static int cx24116_set_tone(struct dvb_frontend *fe, static int cx24116_set_tone(struct dvb_frontend *fe,
fe_sec_tone_mode_t tone) fe_sec_tone_mode_t tone)
{ {
@@ -857,14 +878,6 @@ static int cx24116_set_tone(struct dvb_frontend *fe,
/* Min delay time after DiSEqC send */ /* Min delay time after DiSEqC send */
msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */ msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
/* This is always done before the tone is set */
cmd.args[0x00] = CMD_SET_TONEPRE;
cmd.args[0x01] = 0x00;
cmd.len = 0x02;
ret = cx24116_cmd_execute(fe, &cmd);
if (ret != 0)
return ret;
/* Now we set the tone */ /* Now we set the tone */
cmd.args[0x00] = CMD_SET_TONE; cmd.args[0x00] = CMD_SET_TONE;
cmd.args[0x01] = 0x00; cmd.args[0x01] = 0x00;
@@ -1099,13 +1112,10 @@ struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
/* allocate memory for the internal state */ /* allocate memory for the internal state */
state = kmalloc(sizeof(struct cx24116_state), GFP_KERNEL); state = kzalloc(sizeof(struct cx24116_state), GFP_KERNEL);
if (state == NULL) if (state == NULL)
goto error1; goto error1;
/* setup the state */
memset(state, 0, sizeof(struct cx24116_state));
state->config = config; state->config = config;
state->i2c = i2c; state->i2c = i2c;
@@ -1154,7 +1164,12 @@ static int cx24116_initfe(struct dvb_frontend *fe)
if (ret != 0) if (ret != 0)
return ret; return ret;
return cx24116_diseqc_init(fe); ret = cx24116_diseqc_init(fe);
if (ret != 0)
return ret;
/* HVR-4000 needs this */
return cx24116_set_voltage(fe, SEC_VOLTAGE_13);
} }
/* /*

View File

@@ -1069,13 +1069,13 @@ static struct dvb_frontend_ops cx24123_ops;
struct dvb_frontend *cx24123_attach(const struct cx24123_config *config, struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
struct i2c_adapter *i2c) struct i2c_adapter *i2c)
{ {
/* allocate memory for the internal state */
struct cx24123_state *state = struct cx24123_state *state =
kzalloc(sizeof(struct cx24123_state), GFP_KERNEL); kzalloc(sizeof(struct cx24123_state), GFP_KERNEL);
dprintk("\n"); dprintk("\n");
/* allocate memory for the internal state */
if (state == NULL) { if (state == NULL) {
err("Unable to kmalloc\n"); err("Unable to kzalloc\n");
goto error; goto error;
} }

View File

@@ -58,6 +58,4 @@ static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe)
} }
#endif #endif
extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
#endif #endif

View File

@@ -39,20 +39,44 @@ struct dib3000mc_config {
#define DEFAULT_DIB3000MC_I2C_ADDRESS 16 #define DEFAULT_DIB3000MC_I2C_ADDRESS 16
#define DEFAULT_DIB3000P_I2C_ADDRESS 24 #define DEFAULT_DIB3000P_I2C_ADDRESS 24
#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE)) #if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && \
extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg); defined(MODULE))
extern struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap,
u8 i2c_addr,
struct dib3000mc_config *cfg);
extern int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c,
int no_of_demods, u8 default_addr,
struct dib3000mc_config cfg[]);
extern
struct i2c_adapter *dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod,
int gating);
#else #else
static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg) static inline
struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
struct dib3000mc_config *cfg)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline
int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c,
int no_of_demods, u8 default_addr,
struct dib3000mc_config cfg[])
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline
struct i2c_adapter *dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod,
int gating)
{ {
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL; return NULL;
} }
#endif // CONFIG_DVB_DIB3000MC #endif // CONFIG_DVB_DIB3000MC
extern int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[]);
extern struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating);
extern int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff); extern int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff);
extern int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff); extern int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff);

View File

@@ -38,8 +38,32 @@ struct dib7000m_config {
#define DEFAULT_DIB7000M_I2C_ADDRESS 18 #define DEFAULT_DIB7000M_I2C_ADDRESS 18
extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg); #if defined(CONFIG_DVB_DIB7000M) || (defined(CONFIG_DVB_DIB7000M_MODULE) && \
extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); defined(MODULE))
extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap,
u8 i2c_addr,
struct dib7000m_config *cfg);
extern struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *,
enum dibx000_i2c_interface,
int);
#else
static inline
struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap,
u8 i2c_addr, struct dib7000m_config *cfg)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline
struct i2c_adapter *dib7000m_get_i2c_master(struct dvb_frontend *demod,
enum dibx000_i2c_interface intf,
int gating)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
/* TODO /* TODO
extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val); extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);

View File

@@ -37,7 +37,8 @@ struct dib7000p_config {
#define DEFAULT_DIB7000P_I2C_ADDRESS 18 #define DEFAULT_DIB7000P_I2C_ADDRESS 18
#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && defined(MODULE)) #if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && \
defined(MODULE))
extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
u8 i2c_addr, u8 i2c_addr,
struct dib7000p_config *cfg); struct dib7000p_config *cfg);
@@ -49,9 +50,10 @@ extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
struct dib7000p_config cfg[]); struct dib7000p_config cfg[]);
extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value); extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
#else #else
static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, static inline
u8 i2c_addr, struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
struct dib7000p_config *cfg) struct dib7000p_config *cfg)
{ {
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
@@ -60,14 +62,14 @@ static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
static inline static inline
struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe,
enum dibx000_i2c_interface i, int x) enum dibx000_i2c_interface i,
int x)
{ {
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL; return NULL;
} }
static inline static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
int no_of_demods, u8 default_addr, int no_of_demods, u8 default_addr,
struct dib7000p_config cfg[]) struct dib7000p_config cfg[])
{ {
@@ -75,21 +77,24 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
return -ENODEV; return -ENODEV;
} }
static inline static inline int dib7000p_set_gpio(struct dvb_frontend *fe,
int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) u8 num, u8 dir, u8 val)
{ {
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV; return -ENODEV;
} }
static inline static inline int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value) {
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap)
{ {
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV; return -ENODEV;
} }
#endif #endif
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
#endif #endif

View File

@@ -25,8 +25,27 @@
#include <linux/dvb/frontend.h> #include <linux/dvb/frontend.h>
#include "dvb_frontend.h" #include "dvb_frontend.h"
#if defined(CONFIG_DVB_DUMMY_FE) || (defined(CONFIG_DVB_DUMMY_FE_MODULE) && \
defined(MODULE))
extern struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void); extern struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void);
extern struct dvb_frontend* dvb_dummy_fe_qpsk_attach(void); extern struct dvb_frontend* dvb_dummy_fe_qpsk_attach(void);
extern struct dvb_frontend* dvb_dummy_fe_qam_attach(void); extern struct dvb_frontend* dvb_dummy_fe_qam_attach(void);
#else
static inline struct dvb_frontend *dvb_dummy_fe_ofdm_attach(void)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
static inline struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_DUMMY_FE */
#endif // DVB_DUMMY_FE_H #endif // DVB_DUMMY_FE_H

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