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:
commit
b94d10e7f6
|
@ -25,7 +25,7 @@ use IO::Handle;
|
|||
"tda10046lifeview", "av7110", "dec2000t", "dec2540t",
|
||||
"dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
|
||||
"or51211", "or51132_qam", "or51132_vsb", "bluebird",
|
||||
"opera1");
|
||||
"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2" );
|
||||
|
||||
# Check args
|
||||
syntax() if (scalar(@ARGV) != 1);
|
||||
|
@ -37,8 +37,8 @@ for ($i=0; $i < scalar(@components); $i++) {
|
|||
$outfile = eval($cid);
|
||||
die $@ if $@;
|
||||
print STDERR <<EOF;
|
||||
Firmware $outfile extracted successfully.
|
||||
Now copy it to either /usr/lib/hotplug/firmware or /lib/firmware
|
||||
Firmware(s) $outfile extracted successfully.
|
||||
Now copy it(they) to either /usr/lib/hotplug/firmware or /lib/firmware
|
||||
(depending on configuration of firmware hotplug).
|
||||
EOF
|
||||
exit(0);
|
||||
|
@ -345,6 +345,85 @@ sub or51211 {
|
|||
$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 {
|
||||
my $fwfile = "dvb-fe-or51132-qam.fw";
|
||||
my $url = "http://linuxtv.org/downloads/firmware/$fwfile";
|
||||
|
|
|
@ -64,10 +64,10 @@ Who: Pavel Machek <pavel@suse.cz>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
|
||||
When: December 2008
|
||||
Files: include/linux/video_decoder.h include/linux/videodev.h
|
||||
Check: include/linux/video_decoder.h include/linux/videodev.h
|
||||
What: Video4Linux API 1 ioctls and from Video devices.
|
||||
When: July 2009
|
||||
Files: 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
|
||||
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
|
||||
|
|
|
@ -122,10 +122,8 @@ Code Seq# Include File Comments
|
|||
'c' 00-7F linux/coda.h conflict!
|
||||
'c' 80-9F arch/s390/include/asm/chsc.h
|
||||
'd' 00-FF linux/char/drm/drm/h conflict!
|
||||
'd' 00-DF linux/video_decoder.h conflict!
|
||||
'd' F0-FF linux/digi1.h
|
||||
'e' all linux/digi1.h conflict!
|
||||
'e' 00-1F linux/video_encoder.h conflict!
|
||||
'e' 00-1F net/irda/irtty.h conflict!
|
||||
'f' 00-1F linux/ext2_fs.h
|
||||
'h' 00-7F Charon filesystem
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
134 -> Adlink RTV24
|
||||
135 -> DViCO FusionHDTV 5 Lite [18ac:d500]
|
||||
136 -> Acorp Y878F [9511:1540]
|
||||
137 -> Conceptronic CTVFMi v2
|
||||
137 -> Conceptronic CTVFMi v2 [036e:109e]
|
||||
138 -> Prolink Pixelview PV-BT878P+ (Rev.2E)
|
||||
139 -> Prolink PixelView PlayTV MPEG2 PV-M4900
|
||||
140 -> Osprey 440 [0070:ff07]
|
||||
|
@ -154,3 +154,7 @@
|
|||
153 -> PHYTEC VD-012 (bt878)
|
||||
154 -> PHYTEC VD-012-X1 (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]
|
||||
|
|
|
@ -12,3 +12,7 @@
|
|||
11 -> DViCO FusionHDTV DVB-T Dual Express [18ac:db78]
|
||||
12 -> Leadtek Winfast PxDVR3200 H [107d:6681]
|
||||
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]
|
||||
|
|
|
@ -77,3 +77,4 @@
|
|||
76 -> SATTRADE ST4200 DVB-S/S2 [b200:4200]
|
||||
77 -> TBS 8910 DVB-S [8910:8888]
|
||||
78 -> Prof 6200 DVB-S [b022:3022]
|
||||
79 -> Terratec Cinergy HT PCI MKII [153b:1177]
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
6 -> Terratec Cinergy 200 USB (em2800)
|
||||
7 -> Leadtek Winfast USB II (em2800) [0413:6023]
|
||||
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]
|
||||
11 -> Terratec Hybrid XS (em2880) [0ccd:0042]
|
||||
12 -> Kworld PVR TV 2800 RF (em2820/em2840)
|
||||
13 -> Terratec Prodigy XS (em2880) [0ccd:0047]
|
||||
14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
|
||||
14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
|
||||
15 -> V-Gear PocketTV (em2800)
|
||||
16 -> Hauppauge WinTV HVR 950 (em2883) [2040:6513,2040:6517,2040:651b]
|
||||
17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227]
|
||||
|
@ -30,7 +30,6 @@
|
|||
30 -> Videology 20K14XUSB USB2.0 (em2820/em2840)
|
||||
31 -> Usbgear VD204v9 (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]
|
||||
35 -> Typhoon DVD Maker (em2860)
|
||||
36 -> NetGMBH Cam (em2860)
|
||||
|
@ -58,3 +57,7 @@
|
|||
58 -> Compro VideoMate ForYou/Stereo (em2820/em2840) [185b:2041]
|
||||
60 -> Hauppauge WinTV HVR 850 (em2883) [2040:651f]
|
||||
61 -> Pixelview PlayTV Box 4 USB 2.0 (em2820/em2840)
|
||||
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]
|
||||
|
|
|
@ -153,3 +153,5 @@
|
|||
152 -> Asus Tiger Rev:1.00 [1043:4857]
|
||||
153 -> Kworld Plus TV Analog Lite PCI [17de:7128]
|
||||
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]
|
||||
|
|
|
@ -401,8 +401,7 @@ Additional notes for software developers:
|
|||
first set the correct norm. Well, it seems logically correct: TV
|
||||
standard is "more constant" for current country than geometry
|
||||
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
|
||||
avoid any ambiguity.
|
||||
square pixel format.
|
||||
--
|
||||
Please note that lavplay/lavrec are also included in the MJPEG-tools
|
||||
(http://mjpeg.sf.net/).
|
||||
|
|
|
@ -81,16 +81,6 @@ tuner.o
|
|||
pal=[bdgil] select PAL variant (used for some tuners
|
||||
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
|
||||
new, experimental module which is supported to provide a single
|
||||
driver for all simple i2c audio control chips (tda/tea*).
|
||||
|
|
|
@ -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
|
||||
slogan is "Do it yourself".
|
||||
|
||||
There is a mailing list: video4linux-list@redhat.com.
|
||||
https://listman.redhat.com/mailman/listinfo/video4linux-list
|
||||
There is a mailing list: linux-media@vger.kernel.org
|
||||
http://vger.kernel.org/vger-lists.html#linux-media
|
||||
|
||||
If you have trouble with some specific TV card, try to ask there
|
||||
instead of mailing me directly. The chance that someone with the
|
||||
|
|
|
@ -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
|
||||
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>
|
||||
|
|
|
@ -32,6 +32,7 @@ spca561 041e:403b Creative Webcam Vista (VF0010)
|
|||
zc3xx 041e:4051 Creative Live!Cam Notebook Pro (VF0250)
|
||||
ov519 041e:4052 Creative Live! VISTA 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:4060 Creative Live! VISTA VF0350
|
||||
ov519 041e:4061 Creative Live! VISTA VF0400
|
||||
|
@ -193,6 +194,7 @@ spca500 084d:0003 D-Link DSC-350
|
|||
spca500 08ca:0103 Aiptek PocketDV
|
||||
sunplus 08ca:0104 Aiptek PocketDVII 1.3
|
||||
sunplus 08ca:0106 Aiptek Pocket DV3100+
|
||||
mr97310a 08ca:0111 Aiptek PenCam VGA+
|
||||
sunplus 08ca:2008 Aiptek Mini PenCam 2 M
|
||||
sunplus 08ca:2010 Aiptek PocketCam 3M
|
||||
sunplus 08ca:2016 Aiptek PocketCam 2 Mega
|
||||
|
@ -215,6 +217,7 @@ pac207 093a:2468 PAC207
|
|||
pac207 093a:2470 Genius GF112
|
||||
pac207 093a:2471 Genius VideoCam ge111
|
||||
pac207 093a:2472 Genius VideoCam ge110
|
||||
pac207 093a:2474 Genius iLook 111
|
||||
pac207 093a:2476 Genius e-Messenger 112
|
||||
pac7311 093a:2600 PAC7311 Typhoon
|
||||
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
|
||||
ov534 1415:2000 Sony HD Eye for PS3 (SLEH 00201)
|
||||
pac207 145f:013a Trust WB-1300N
|
||||
vc032x 15b8:6001 HP 2.0 Megapixel
|
||||
vc032x 15b8:6002 HP 2.0 Megapixel rz406aa
|
||||
spca501 1776:501c Arowana 300K CMOS Camera
|
||||
t613 17a1:0128 TASCORP JPEG Webcam, NGS Cyclops
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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
|
||||
|
@ -41,7 +41,7 @@ chips are known to work:
|
|||
- 10c4:818a: Silicon Labs USB FM Radio Reference Design
|
||||
- 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF)
|
||||
- 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
|
||||
|
@ -52,6 +52,7 @@ Testing is usually done with most application under Debian/testing:
|
|||
- gradio - GTK FM radio tuner
|
||||
- kradio - Comfortable Radio Application for KDE
|
||||
- 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
|
||||
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
|
||||
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
|
||||
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):
|
||||
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:
|
||||
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
|
||||
=================
|
||||
|
|
|
@ -47,7 +47,9 @@ All drivers have the following structure:
|
|||
3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX, /dev/radioX and
|
||||
/dev/vtxX) and keeping track of device-node specific data.
|
||||
|
||||
4) Filehandle-specific structs containing per-filehandle data.
|
||||
4) Filehandle-specific structs containing per-filehandle data;
|
||||
|
||||
5) video buffer handling.
|
||||
|
||||
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);
|
||||
|
||||
Registration will initialize the v4l2_device struct and link dev->driver_data
|
||||
to v4l2_dev. Registration will also set v4l2_dev->name to a value derived from
|
||||
dev (driver name followed by the bus_id, to be precise). You may change the
|
||||
name after registration if you want.
|
||||
to v4l2_dev. If v4l2_dev->name is empty then it will be set to a value derived
|
||||
from dev (driver name followed by the bus_id, to be precise). If you set it
|
||||
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,
|
||||
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:
|
||||
|
||||
|
@ -95,6 +105,17 @@ You unregister with:
|
|||
|
||||
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
|
||||
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
|
||||
|
@ -134,7 +155,7 @@ The recommended approach is as follows:
|
|||
|
||||
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)
|
||||
{
|
||||
...
|
||||
|
@ -218,7 +239,7 @@ to add new ops and categories.
|
|||
|
||||
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
|
||||
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
|
||||
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.
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
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
|
||||
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:
|
||||
|
||||
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
|
||||
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
|
||||
errors (except -ENOIOCTLCMD) occured, then 0 is returned.
|
||||
|
||||
The second argument to both calls is a group ID. If 0, then all subdevs are
|
||||
called. If non-zero, then only those whose group ID match that value will
|
||||
be called. Before a bridge driver registers a subdev it can set subdev->grp_id
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
@ -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
|
||||
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:
|
||||
|
||||
|
@ -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.
|
||||
If all goes well, then it registers the subdev with the v4l2_device. It gets
|
||||
the v4l2_device by calling i2c_get_adapdata(adapter), so you should make sure
|
||||
that adapdata is set to v4l2_device when you setup the i2c_adapter in your
|
||||
driver.
|
||||
to call i2c_set_adapdata(adapter, v4l2_device) when you setup the i2c_adapter
|
||||
in your driver.
|
||||
|
||||
You can also use v4l2_i2c_new_probed_subdev() which is very similar to
|
||||
v4l2_i2c_new_subdev(), except that it has an array of possible I2C addresses
|
||||
|
@ -358,6 +390,14 @@ that it should probe. Internally it calls i2c_new_probed_device().
|
|||
|
||||
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
|
||||
-------------------
|
||||
|
@ -396,6 +436,15 @@ You should also set these fields:
|
|||
- ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
|
||||
(highly recommended to use this and it might become compulsory in the
|
||||
future!), then set this to your v4l2_ioctl_ops struct.
|
||||
- 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
|
||||
.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:
|
||||
|
||||
void *video_get_drvdata(struct video_device *dev);
|
||||
void video_set_drvdata(struct video_device *dev, void *data);
|
||||
void *video_get_drvdata(struct video_device *vdev);
|
||||
void video_set_drvdata(struct video_device *vdev, void *data);
|
||||
|
||||
Note that you can safely call video_set_drvdata() before calling
|
||||
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:
|
||||
|
||||
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).
|
||||
|
|
|
@ -105,8 +105,8 @@ int main(int argc, char ** argv)
|
|||
struct video_picture vpic;
|
||||
|
||||
unsigned char *buffer, *src;
|
||||
int bpp = 24, r, g, b;
|
||||
unsigned int i, src_depth;
|
||||
int bpp = 24, r = 0, g = 0, b = 0;
|
||||
unsigned int i, src_depth = 16;
|
||||
|
||||
if (fd < 0) {
|
||||
perror(VIDEO_DEV);
|
||||
|
|
|
@ -65,3 +65,4 @@ Vendor Product Distributor Model
|
|||
0x06d6 0x003b Trust Powerc@m 970Z
|
||||
0x0a17 0x004e Pentax Optio 50
|
||||
0x041e 0x405d Creative DiVi CAM 516
|
||||
0x08ca 0x2102 Aiptek DV T300
|
||||
|
|
|
@ -1063,7 +1063,6 @@ BTTV VIDEO4LINUX DRIVER
|
|||
P: Mauro Carvalho Chehab
|
||||
M: mchehab@infradead.org
|
||||
L: linux-media@vger.kernel.org
|
||||
L: video4linux-list@redhat.com
|
||||
W: http://linuxtv.org
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
|
||||
S: Maintained
|
||||
|
@ -4835,7 +4834,6 @@ VIDEO FOR LINUX (V4L)
|
|||
P: Mauro Carvalho Chehab
|
||||
M: mchehab@infradead.org
|
||||
L: linux-media@vger.kernel.org
|
||||
L: video4linux-list@redhat.com
|
||||
W: http://linuxtv.org
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
|
||||
S: Maintained
|
||||
|
|
|
@ -380,14 +380,49 @@ static struct pca953x_platform_data pca9536_data = {
|
|||
.gpio_base = NR_BUILTIN_GPIO + 1,
|
||||
};
|
||||
|
||||
static struct soc_camera_link iclink[] = {
|
||||
{
|
||||
.bus_id = 0, /* Must match with the camera ID above */
|
||||
.gpio = NR_BUILTIN_GPIO + 1,
|
||||
}, {
|
||||
.bus_id = 0, /* Must match with the camera ID above */
|
||||
.gpio = -ENXIO,
|
||||
static int gpio_bus_switch;
|
||||
|
||||
static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
|
||||
unsigned long flags)
|
||||
{
|
||||
if (gpio_bus_switch <= 0) {
|
||||
if (flags == SOCAM_DATAWIDTH_10)
|
||||
return 0;
|
||||
else
|
||||
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. */
|
||||
|
@ -398,10 +433,10 @@ static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
|
|||
.platform_data = &pca9536_data,
|
||||
}, {
|
||||
I2C_BOARD_INFO("mt9v022", 0x48),
|
||||
.platform_data = &iclink[0], /* With extender */
|
||||
.platform_data = &iclink, /* With extender */
|
||||
}, {
|
||||
I2C_BOARD_INFO("mt9m001", 0x5d),
|
||||
.platform_data = &iclink[0], /* With extender */
|
||||
.platform_data = &iclink, /* With extender */
|
||||
},
|
||||
};
|
||||
#endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
|
||||
|
|
|
@ -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
|
|
@ -310,7 +310,8 @@ static struct platform_device camera_device = {
|
|||
|
||||
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
|
||||
.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[] = {
|
||||
|
|
|
@ -352,8 +352,9 @@ static int tw9910_power(struct device *dev, int mode)
|
|||
}
|
||||
|
||||
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
|
||||
.flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING \
|
||||
| SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH,
|
||||
.flags = SOCAM_MASTER | SOCAM_DATAWIDTH_8 | SOCAM_PCLK_SAMPLE_RISING
|
||||
| SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH
|
||||
| SOCAM_DATA_ACTIVE_HIGH,
|
||||
};
|
||||
|
||||
static struct resource migor_ceu_resources[] = {
|
||||
|
|
|
@ -117,7 +117,7 @@ source "drivers/media/dvb/Kconfig"
|
|||
config DAB
|
||||
boolean "DAB adapters"
|
||||
---help---
|
||||
Allow selecting support for for Digital Audio Broadcasting (DAB)
|
||||
Allow selecting support for Digital Audio Broadcasting (DAB)
|
||||
Receiver adapters.
|
||||
|
||||
if DAB
|
||||
|
|
|
@ -153,6 +153,65 @@ IR_KEYTAB_TYPE ir_codes_avermedia_m135a[IR_KEYTAB_SIZE] = {
|
|||
};
|
||||
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> */
|
||||
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);
|
||||
|
||||
/* 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] = {
|
||||
[0x20] = KEY_LIST,
|
||||
[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);
|
||||
|
||||
/* 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);
|
||||
|
|
|
@ -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));
|
||||
dev->ext = ext;
|
||||
|
||||
pci_set_drvdata(pci, dev);
|
||||
|
||||
mutex_init(&dev->lock);
|
||||
spin_lock_init(&dev->int_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)) {
|
||||
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);
|
||||
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:
|
||||
return err;
|
||||
|
||||
err_unprobe:
|
||||
pci_set_drvdata(pci, NULL);
|
||||
err_free_i2c:
|
||||
pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr,
|
||||
dev->d_i2c.dma_handle);
|
||||
|
@ -514,7 +514,8 @@ err_free:
|
|||
|
||||
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 {
|
||||
void *addr;
|
||||
dma_addr_t dma;
|
||||
|
@ -528,6 +529,8 @@ static void saa7146_remove_one(struct pci_dev *pdev)
|
|||
DEB_EE(("dev:%p\n",dev));
|
||||
|
||||
dev->ext->detach(dev);
|
||||
/* Zero the PCI drvdata after use. */
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
|
||||
/* shut down all video dma transfers */
|
||||
saa7146_write(dev, MC1, 0x00ff0000);
|
||||
|
|
|
@ -308,14 +308,6 @@ static int fops_release(struct file *file)
|
|||
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)
|
||||
{
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
|
@ -425,7 +417,7 @@ static const struct v4l2_file_operations video_fops =
|
|||
.write = fops_write,
|
||||
.poll = fops_poll,
|
||||
.mmap = fops_mmap,
|
||||
.ioctl = fops_ioctl,
|
||||
.ioctl = video_ioctl2,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
struct saa7146_vv *vv = kzalloc (sizeof(struct saa7146_vv),GFP_KERNEL);
|
||||
if( NULL == vv ) {
|
||||
struct saa7146_vv *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"));
|
||||
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));
|
||||
|
||||
|
@ -507,6 +502,7 @@ int saa7146_vv_release(struct saa7146_dev* 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);
|
||||
kfree(vv);
|
||||
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 video_device *vfd;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
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)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(vfd, &device_template, sizeof(struct video_device));
|
||||
strlcpy(vfd->name, name, sizeof(vfd->name));
|
||||
vfd->fops = &video_fops;
|
||||
vfd->ioctl_ops = &dev->ext_vv_data->ops;
|
||||
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);
|
||||
|
||||
// fixme: -1 should be an insmod parameter *for the extension* (like "video_nr");
|
||||
if (video_register_device(vfd, type, -1) < 0) {
|
||||
err = video_register_device(vfd, type, -1);
|
||||
if (err < 0) {
|
||||
ERR(("cannot register v4l2 device. skipping.\n"));
|
||||
video_device_release(vfd);
|
||||
return -1;
|
||||
return err;
|
||||
}
|
||||
|
||||
if( VFL_TYPE_GRABBER == type ) {
|
||||
|
|
|
@ -293,7 +293,6 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
|
|||
int i = 0, count = 0;
|
||||
__le32 *buffer = dev->d_i2c.cpu_addr;
|
||||
int err = 0;
|
||||
int address_err = 0;
|
||||
int short_delay = 0;
|
||||
|
||||
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
|
||||
device is really *not* there. retrying in that case
|
||||
increases the time the device needs to probe greatly, so
|
||||
it should be avoided. because of the fact, that only
|
||||
analog based cards use irq based i2c transactions (for dvb
|
||||
cards, this screwes up other interrupt sources), we bail out
|
||||
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;
|
||||
}
|
||||
address_err++;
|
||||
}
|
||||
it should be avoided. So we bail out in irq mode after an
|
||||
address error and trust the saa7146 address error detection. */
|
||||
if (-EREMOTEIO == err && 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags))
|
||||
goto out;
|
||||
DEB_I2C(("error while sending message(s). starting again.\n"));
|
||||
break;
|
||||
}
|
||||
|
@ -358,10 +350,9 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
|
|||
|
||||
} while (err != num && retries--);
|
||||
|
||||
/* if every retry had an address error, exit right away */
|
||||
if (address_err == retries) {
|
||||
/* quit if any error occurred */
|
||||
if (err != num)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if any things had to be read, get the results */
|
||||
if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
|
||||
|
@ -390,7 +381,8 @@ out:
|
|||
/* utility functions */
|
||||
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 */
|
||||
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;
|
||||
saa7146_i2c_reset(dev);
|
||||
|
||||
if( NULL != i2c_adapter ) {
|
||||
BUG_ON(!i2c_adapter->class);
|
||||
i2c_set_adapdata(i2c_adapter,dev);
|
||||
if (i2c_adapter) {
|
||||
i2c_set_adapdata(i2c_adapter, &dev->v4l2_dev);
|
||||
i2c_adapter->dev.parent = &dev->pci->dev;
|
||||
i2c_adapter->algo = &saa7146_algo;
|
||||
i2c_adapter->algo_data = NULL;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,16 +21,17 @@ config MEDIA_TUNER
|
|||
tristate
|
||||
default VIDEO_MEDIA && I2C
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
|
||||
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"
|
||||
depends on MEDIA_TUNER
|
||||
default n
|
||||
|
@ -43,13 +44,13 @@ menuconfig MEDIA_TUNER_CUSTOMIZE
|
|||
|
||||
If unsure say N.
|
||||
|
||||
if MEDIA_TUNER_CUSTOMIZE
|
||||
if MEDIA_TUNER_CUSTOMISE
|
||||
|
||||
config MEDIA_TUNER_SIMPLE
|
||||
tristate "Simple tuner support"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
select MEDIA_TUNER_TDA9887
|
||||
default m if MEDIA_TUNER_CUSTOMIZE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for various simple tuners.
|
||||
|
||||
|
@ -58,28 +59,28 @@ config MEDIA_TUNER_TDA8290
|
|||
depends on VIDEO_MEDIA && I2C
|
||||
select MEDIA_TUNER_TDA827X
|
||||
select MEDIA_TUNER_TDA18271
|
||||
default m if MEDIA_TUNER_CUSTOMIZE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for Philips TDA8290+8275(a) tuner.
|
||||
|
||||
config MEDIA_TUNER_TDA827X
|
||||
tristate "Philips TDA827X silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A DVB-T silicon tuner module. Say Y when you want to support this tuner.
|
||||
|
||||
config MEDIA_TUNER_TDA18271
|
||||
tristate "NXP TDA18271 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A silicon tuner module. Say Y when you want to support this tuner.
|
||||
|
||||
config MEDIA_TUNER_TDA9887
|
||||
tristate "TDA 9885/6/7 analog IF demodulator"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMIZE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for Philips TDA9885/6/7
|
||||
analog IF demodulator.
|
||||
|
@ -88,63 +89,63 @@ config MEDIA_TUNER_TEA5761
|
|||
tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
depends on EXPERIMENTAL
|
||||
default m if MEDIA_TUNER_CUSTOMIZE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for the Philips TEA5761 radio tuner.
|
||||
|
||||
config MEDIA_TUNER_TEA5767
|
||||
tristate "TEA 5767 radio tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMIZE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for the Philips TEA5767 radio tuner.
|
||||
|
||||
config MEDIA_TUNER_MT20XX
|
||||
tristate "Microtune 2032 / 2050 tuners"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMIZE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for the MT2032 / MT2050 tuner.
|
||||
|
||||
config MEDIA_TUNER_MT2060
|
||||
tristate "Microtune MT2060 silicon IF tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon IF tuner MT2060 from Microtune.
|
||||
|
||||
config MEDIA_TUNER_MT2266
|
||||
tristate "Microtune MT2266 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon baseband tuner MT2266 from Microtune.
|
||||
|
||||
config MEDIA_TUNER_MT2131
|
||||
tristate "Microtune MT2131 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon baseband tuner MT2131 from Microtune.
|
||||
|
||||
config MEDIA_TUNER_QT1010
|
||||
tristate "Quantek QT1010 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon tuner QT1010 from Quantek.
|
||||
|
||||
config MEDIA_TUNER_XC2028
|
||||
tristate "XCeive xc2028/xc3028 tuners"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if MEDIA_TUNER_CUSTOMIZE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to include support for the xc2028/xc3028 tuners.
|
||||
|
||||
config MEDIA_TUNER_XC5000
|
||||
tristate "Xceive XC5000 silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon tuner XC5000 from Xceive.
|
||||
This device is only used inside a SiP called togther with a
|
||||
|
@ -153,15 +154,22 @@ config MEDIA_TUNER_XC5000
|
|||
config MEDIA_TUNER_MXL5005S
|
||||
tristate "MaxLinear MSL5005S silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
A driver for the silicon tuner MXL5005S from MaxLinear.
|
||||
|
||||
config MEDIA_TUNER_MXL5007T
|
||||
tristate "MaxLinear MxL5007T silicon tuner"
|
||||
depends on VIDEO_MEDIA && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
default m if MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
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
|
||||
|
|
|
@ -22,6 +22,7 @@ obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
|
|||
obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
|
||||
obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.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/frontends
|
||||
|
|
|
@ -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, ®);
|
||||
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");
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
||||
msleep(20);
|
||||
|
||||
if (i < 10) {
|
||||
if (i <= 10) {
|
||||
mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :)
|
||||
dprintk("calibration was successful: %d", (int)priv->fmfreq);
|
||||
} else
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/videodev.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include "tuner-i2c.h"
|
||||
#include "mt20xx.h"
|
||||
|
||||
|
|
|
@ -4003,12 +4003,11 @@ static int mxl5005s_set_params(struct dvb_frontend *fe,
|
|||
/* Change tuner for new modulation type if reqd */
|
||||
if (req_mode != state->current_mode) {
|
||||
switch (req_mode) {
|
||||
case VSB_8:
|
||||
case QAM_64:
|
||||
case QAM_256:
|
||||
case QAM_AUTO:
|
||||
case MXL_ATSC:
|
||||
case MXL_QAM:
|
||||
req_bw = MXL5005S_BANDWIDTH_6MHZ;
|
||||
break;
|
||||
case MXL_DVBT:
|
||||
default:
|
||||
/* Assume DVB-T */
|
||||
switch (params->u.ofdm.bandwidth) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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
|
||||
* 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
|
||||
|
||||
enum mxl5007t_mode {
|
||||
MxL_MODE_OTA_DVBT_ATSC = 0,
|
||||
MxL_MODE_OTA_NTSC_PAL_GH = 1,
|
||||
MxL_MODE_OTA_PAL_IB = 2,
|
||||
MxL_MODE_OTA_PAL_D_SECAM_KL = 3,
|
||||
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,
|
||||
MxL_MODE_ISDBT = 0,
|
||||
MxL_MODE_DVBT = 1,
|
||||
MxL_MODE_ATSC = 2,
|
||||
MxL_MODE_CABLE = 0x10,
|
||||
};
|
||||
|
||||
enum mxl5007t_chip_version {
|
||||
MxL_UNKNOWN_ID = 0x00,
|
||||
MxL_5007_V1_F1 = 0x11,
|
||||
MxL_5007_V1_F2 = 0x12,
|
||||
MxL_5007_V4 = 0x14,
|
||||
MxL_5007_V2_100_F1 = 0x21,
|
||||
MxL_5007_V2_100_F2 = 0x22,
|
||||
MxL_5007_V2_200_F1 = 0x23,
|
||||
|
@ -96,67 +91,61 @@ struct reg_pair_t {
|
|||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static struct reg_pair_t init_tab[] = {
|
||||
{ 0x0b, 0x44 }, /* XTAL */
|
||||
{ 0x0c, 0x60 }, /* IF */
|
||||
{ 0x10, 0x00 }, /* MISC */
|
||||
{ 0x12, 0xca }, /* IDAC */
|
||||
{ 0x16, 0x90 }, /* MODE */
|
||||
{ 0x32, 0x38 }, /* MODE Analog/Digital */
|
||||
{ 0xd8, 0x18 }, /* CLK_OUT_ENABLE */
|
||||
{ 0x2c, 0x34 }, /* OVERRIDE */
|
||||
{ 0x4d, 0x40 }, /* OVERRIDE */
|
||||
{ 0x7f, 0x02 }, /* OVERRIDE */
|
||||
{ 0x9a, 0x52 }, /* OVERRIDE */
|
||||
{ 0x48, 0x5a }, /* OVERRIDE */
|
||||
{ 0x76, 0x1a }, /* OVERRIDE */
|
||||
{ 0x6a, 0x48 }, /* OVERRIDE */
|
||||
{ 0x64, 0x28 }, /* OVERRIDE */
|
||||
{ 0x66, 0xe6 }, /* OVERRIDE */
|
||||
{ 0x35, 0x0e }, /* OVERRIDE */
|
||||
{ 0x7e, 0x01 }, /* OVERRIDE */
|
||||
{ 0x83, 0x00 }, /* OVERRIDE */
|
||||
{ 0x04, 0x0b }, /* OVERRIDE */
|
||||
{ 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
|
||||
{ 0x02, 0x06 },
|
||||
{ 0x03, 0x48 },
|
||||
{ 0x05, 0x04 },
|
||||
{ 0x06, 0x10 },
|
||||
{ 0x2e, 0x15 }, /* OVERRIDE */
|
||||
{ 0x30, 0x10 }, /* OVERRIDE */
|
||||
{ 0x45, 0x58 }, /* OVERRIDE */
|
||||
{ 0x48, 0x19 }, /* OVERRIDE */
|
||||
{ 0x52, 0x03 }, /* OVERRIDE */
|
||||
{ 0x53, 0x44 }, /* OVERRIDE */
|
||||
{ 0x6a, 0x4b }, /* OVERRIDE */
|
||||
{ 0x76, 0x00 }, /* OVERRIDE */
|
||||
{ 0x78, 0x18 }, /* OVERRIDE */
|
||||
{ 0x7a, 0x17 }, /* OVERRIDE */
|
||||
{ 0x85, 0x06 }, /* OVERRIDE */
|
||||
{ 0x01, 0x01 }, /* TOP_MASTER_ENABLE */
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static struct reg_pair_t init_tab_cable[] = {
|
||||
{ 0x0b, 0x44 }, /* XTAL */
|
||||
{ 0x0c, 0x60 }, /* IF */
|
||||
{ 0x10, 0x00 }, /* MISC */
|
||||
{ 0x12, 0xca }, /* IDAC */
|
||||
{ 0x16, 0x90 }, /* MODE */
|
||||
{ 0x32, 0x38 }, /* MODE A/D */
|
||||
{ 0x71, 0x3f }, /* TOP1 */
|
||||
{ 0x72, 0x3f }, /* TOP2 */
|
||||
{ 0x74, 0x3f }, /* TOP3 */
|
||||
{ 0xd8, 0x18 }, /* CLK_OUT_ENABLE */
|
||||
{ 0x2c, 0x34 }, /* OVERRIDE */
|
||||
{ 0x4d, 0x40 }, /* OVERRIDE */
|
||||
{ 0x7f, 0x02 }, /* OVERRIDE */
|
||||
{ 0x9a, 0x52 }, /* OVERRIDE */
|
||||
{ 0x48, 0x5a }, /* OVERRIDE */
|
||||
{ 0x76, 0x1a }, /* OVERRIDE */
|
||||
{ 0x6a, 0x48 }, /* OVERRIDE */
|
||||
{ 0x64, 0x28 }, /* OVERRIDE */
|
||||
{ 0x66, 0xe6 }, /* OVERRIDE */
|
||||
{ 0x35, 0x0e }, /* OVERRIDE */
|
||||
{ 0x7e, 0x01 }, /* OVERRIDE */
|
||||
{ 0x04, 0x0b }, /* OVERRIDE */
|
||||
{ 0x68, 0xb4 }, /* OVERRIDE */
|
||||
{ 0x36, 0x00 }, /* OVERRIDE */
|
||||
{ 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
|
||||
{ 0x02, 0x06 },
|
||||
{ 0x03, 0x48 },
|
||||
{ 0x05, 0x04 },
|
||||
{ 0x06, 0x10 },
|
||||
{ 0x09, 0x3f },
|
||||
{ 0x0a, 0x3f },
|
||||
{ 0x0b, 0x3f },
|
||||
{ 0x2e, 0x15 }, /* OVERRIDE */
|
||||
{ 0x30, 0x10 }, /* OVERRIDE */
|
||||
{ 0x45, 0x58 }, /* OVERRIDE */
|
||||
{ 0x48, 0x19 }, /* OVERRIDE */
|
||||
{ 0x52, 0x03 }, /* OVERRIDE */
|
||||
{ 0x53, 0x44 }, /* OVERRIDE */
|
||||
{ 0x6a, 0x4b }, /* OVERRIDE */
|
||||
{ 0x76, 0x00 }, /* OVERRIDE */
|
||||
{ 0x78, 0x18 }, /* OVERRIDE */
|
||||
{ 0x7a, 0x17 }, /* OVERRIDE */
|
||||
{ 0x85, 0x06 }, /* OVERRIDE */
|
||||
{ 0x01, 0x01 }, /* TOP_MASTER_ENABLE */
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static struct reg_pair_t reg_pair_rftune[] = {
|
||||
{ 0x11, 0x00 }, /* abort tune */
|
||||
{ 0x13, 0x15 },
|
||||
{ 0x14, 0x40 },
|
||||
{ 0x15, 0x0e },
|
||||
{ 0x11, 0x02 }, /* start tune */
|
||||
{ 0x0f, 0x00 }, /* abort tune */
|
||||
{ 0x0c, 0x15 },
|
||||
{ 0x0d, 0x40 },
|
||||
{ 0x0e, 0x0e },
|
||||
{ 0x1f, 0x87 }, /* OVERRIDE */
|
||||
{ 0x20, 0x1f }, /* OVERRIDE */
|
||||
{ 0x21, 0x87 }, /* OVERRIDE */
|
||||
{ 0x22, 0x1f }, /* OVERRIDE */
|
||||
{ 0x80, 0x01 }, /* freq dependent */
|
||||
{ 0x0f, 0x01 }, /* start tune */
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -227,63 +216,20 @@ static void mxl5007t_set_mode_bits(struct mxl5007t_state *state,
|
|||
s32 if_diff_out_level)
|
||||
{
|
||||
switch (mode) {
|
||||
case MxL_MODE_OTA_DVBT_ATSC:
|
||||
set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06);
|
||||
set_reg_bits(state->tab_init, 0x35, 0xff, 0x0e);
|
||||
case MxL_MODE_ATSC:
|
||||
set_reg_bits(state->tab_init, 0x06, 0x1f, 0x12);
|
||||
break;
|
||||
case MxL_MODE_OTA_ISDBT:
|
||||
set_reg_bits(state->tab_init, 0x32, 0x0f, 0x06);
|
||||
set_reg_bits(state->tab_init, 0x35, 0xff, 0x12);
|
||||
case MxL_MODE_DVBT:
|
||||
set_reg_bits(state->tab_init, 0x06, 0x1f, 0x11);
|
||||
break;
|
||||
case MxL_MODE_OTA_NTSC_PAL_GH:
|
||||
set_reg_bits(state->tab_init, 0x16, 0x70, 0x00);
|
||||
set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
|
||||
case MxL_MODE_ISDBT:
|
||||
set_reg_bits(state->tab_init, 0x06, 0x1f, 0x10);
|
||||
break;
|
||||
case MxL_MODE_OTA_PAL_IB:
|
||||
set_reg_bits(state->tab_init, 0x16, 0x70, 0x10);
|
||||
set_reg_bits(state->tab_init, 0x32, 0xff, 0x85);
|
||||
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,
|
||||
case MxL_MODE_CABLE:
|
||||
set_reg_bits(state->tab_init_cable, 0x09, 0xff, 0xc1);
|
||||
set_reg_bits(state->tab_init_cable, 0x0a, 0xff,
|
||||
8 - if_diff_out_level);
|
||||
set_reg_bits(state->tab_init_cable, 0x74, 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);
|
||||
set_reg_bits(state->tab_init_cable, 0x0b, 0xff, 0x17);
|
||||
break;
|
||||
default:
|
||||
mxl_fail(-EINVAL);
|
||||
|
@ -302,43 +248,43 @@ static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,
|
|||
val = 0x00;
|
||||
break;
|
||||
case MxL_IF_4_5_MHZ:
|
||||
val = 0x20;
|
||||
val = 0x02;
|
||||
break;
|
||||
case MxL_IF_4_57_MHZ:
|
||||
val = 0x30;
|
||||
val = 0x03;
|
||||
break;
|
||||
case MxL_IF_5_MHZ:
|
||||
val = 0x40;
|
||||
val = 0x04;
|
||||
break;
|
||||
case MxL_IF_5_38_MHZ:
|
||||
val = 0x50;
|
||||
val = 0x05;
|
||||
break;
|
||||
case MxL_IF_6_MHZ:
|
||||
val = 0x60;
|
||||
val = 0x06;
|
||||
break;
|
||||
case MxL_IF_6_28_MHZ:
|
||||
val = 0x70;
|
||||
val = 0x07;
|
||||
break;
|
||||
case MxL_IF_9_1915_MHZ:
|
||||
val = 0x80;
|
||||
val = 0x08;
|
||||
break;
|
||||
case MxL_IF_35_25_MHZ:
|
||||
val = 0x90;
|
||||
val = 0x09;
|
||||
break;
|
||||
case MxL_IF_36_15_MHZ:
|
||||
val = 0xa0;
|
||||
val = 0x0a;
|
||||
break;
|
||||
case MxL_IF_44_MHZ:
|
||||
val = 0xb0;
|
||||
val = 0x0b;
|
||||
break;
|
||||
default:
|
||||
mxl_fail(-EINVAL);
|
||||
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_reg_bits(state->tab_init, 0x0c, 0x08, invert_if ? 0x08 : 0x00);
|
||||
set_reg_bits(state->tab_init, 0x02, 0x10, invert_if ? 0x10 : 0x00);
|
||||
|
||||
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,
|
||||
enum mxl5007t_xtal_freq xtal_freq)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
switch (xtal_freq) {
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
default:
|
||||
mxl_fail(-EINVAL);
|
||||
return;
|
||||
}
|
||||
set_reg_bits(state->tab_init, 0x0b, 0xff, val);
|
||||
|
||||
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_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);
|
||||
|
||||
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) {
|
||||
if (mode >= MxL_MODE_CABLE) {
|
||||
copy_reg_bits(state->tab_init, state->tab_init_cable);
|
||||
return state->tab_init_cable;
|
||||
} else
|
||||
|
@ -447,7 +400,7 @@ static void mxl5007t_set_bw_bits(struct mxl5007t_state *state,
|
|||
* and DIG_MODEINDEX_CSF */
|
||||
break;
|
||||
case MxL_BW_7MHz:
|
||||
val = 0x21;
|
||||
val = 0x2a;
|
||||
break;
|
||||
case MxL_BW_8MHz:
|
||||
val = 0x3f;
|
||||
|
@ -456,7 +409,7 @@ static void mxl5007t_set_bw_bits(struct mxl5007t_state *state,
|
|||
mxl_fail(-EINVAL);
|
||||
return;
|
||||
}
|
||||
set_reg_bits(state->tab_rftune, 0x13, 0x3f, val);
|
||||
set_reg_bits(state->tab_rftune, 0x0c, 0x3f, val);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -493,8 +446,11 @@ reg_pair_t *mxl5007t_calc_rf_tune_regs(struct mxl5007t_state *state,
|
|||
if (temp > 7812)
|
||||
dig_rf_freq++;
|
||||
|
||||
set_reg_bits(state->tab_rftune, 0x14, 0xff, (u8)dig_rf_freq);
|
||||
set_reg_bits(state->tab_rftune, 0x15, 0xff, (u8)(dig_rf_freq >> 8));
|
||||
set_reg_bits(state->tab_rftune, 0x0d, 0xff, (u8) dig_rf_freq);
|
||||
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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
u8 d = 0xff;
|
||||
struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,
|
||||
.buf = &d, .len = 1 };
|
||||
|
||||
struct i2c_msg msg = {
|
||||
.addr = state->i2c_props.addr, .flags = 0,
|
||||
.buf = &d, .len = 1
|
||||
};
|
||||
int ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
|
||||
|
||||
if (ret != 1) {
|
||||
|
@ -580,9 +537,6 @@ static int mxl5007t_tuner_init(struct mxl5007t_state *state,
|
|||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
mdelay(1);
|
||||
|
||||
ret = mxl5007t_write_reg(state, 0x2c, 0x35);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
@ -615,7 +569,7 @@ static int mxl5007t_synth_lock_status(struct mxl5007t_state *state,
|
|||
*rf_locked = 0;
|
||||
*ref_locked = 0;
|
||||
|
||||
ret = mxl5007t_read_reg(state, 0xcf, &d);
|
||||
ret = mxl5007t_read_reg(state, 0xd8, &d);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
|
@ -628,37 +582,14 @@ fail:
|
|||
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)
|
||||
{
|
||||
struct mxl5007t_state *state = fe->tuner_priv;
|
||||
int rf_locked, ref_locked;
|
||||
s32 rf_input_level = 0;
|
||||
int ret;
|
||||
int rf_locked, ref_locked, ret;
|
||||
|
||||
*status = 0;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
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 " : "",
|
||||
ref_locked ? "ref locked" : "");
|
||||
|
||||
ret = mxl5007t_check_rf_input_power(state, &rf_input_level);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
mxl_debug("rf input power: %d", rf_input_level);
|
||||
if ((rf_locked) || (ref_locked))
|
||||
*status |= TUNER_STATUS_LOCKED;
|
||||
fail:
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
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) {
|
||||
case VSB_8:
|
||||
case VSB_16:
|
||||
mode = MxL_MODE_OTA_DVBT_ATSC;
|
||||
mode = MxL_MODE_ATSC;
|
||||
break;
|
||||
case QAM_64:
|
||||
case QAM_256:
|
||||
mode = MxL_MODE_CABLE_DIGITAL;
|
||||
mode = MxL_MODE_CABLE;
|
||||
break;
|
||||
default:
|
||||
mxl_err("modulation not set!");
|
||||
|
@ -721,7 +650,7 @@ static int mxl5007t_set_params(struct dvb_frontend *fe,
|
|||
mxl_err("bandwidth not set!");
|
||||
return -EINVAL;
|
||||
}
|
||||
mode = MxL_MODE_OTA_DVBT_ATSC;
|
||||
mode = MxL_MODE_DVBT;
|
||||
} else {
|
||||
mxl_err("modulation type not supported!");
|
||||
return -EINVAL;
|
||||
|
@ -752,96 +681,20 @@ fail:
|
|||
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)
|
||||
{
|
||||
struct mxl5007t_state *state = fe->tuner_priv;
|
||||
int ret;
|
||||
u8 d;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
ret = mxl5007t_read_reg(state, 0x05, &d);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl5007t_write_reg(state, 0x05, d | 0x01);
|
||||
/* wake from standby */
|
||||
ret = mxl5007t_write_reg(state, 0x01, 0x01);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
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;
|
||||
int ret;
|
||||
u8 d;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
ret = mxl5007t_read_reg(state, 0x05, &d);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = mxl5007t_write_reg(state, 0x05, d & ~0x01);
|
||||
/* enter standby mode */
|
||||
ret = mxl5007t_write_reg(state, 0x01, 0x00);
|
||||
mxl_fail(ret);
|
||||
fail:
|
||||
ret = mxl5007t_write_reg(state, 0x0f, 0x00);
|
||||
mxl_fail(ret);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
|
@ -911,7 +762,6 @@ static struct dvb_tuner_ops mxl5007t_tuner_ops = {
|
|||
.init = mxl5007t_init,
|
||||
.sleep = mxl5007t_sleep,
|
||||
.set_params = mxl5007t_set_params,
|
||||
.set_analog_params = mxl5007t_set_analog_params,
|
||||
.get_status = mxl5007t_get_status,
|
||||
.get_frequency = mxl5007t_get_frequency,
|
||||
.get_bandwidth = mxl5007t_get_bandwidth,
|
||||
|
@ -924,7 +774,7 @@ static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
|
|||
int ret;
|
||||
u8 id;
|
||||
|
||||
ret = mxl5007t_read_reg(state, 0xd3, &id);
|
||||
ret = mxl5007t_read_reg(state, 0xd9, &id);
|
||||
if (mxl_fail(ret))
|
||||
goto fail;
|
||||
|
||||
|
@ -947,8 +797,12 @@ static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
|
|||
case MxL_5007_V2_200_F2:
|
||||
name = "MxL5007.v2.200.f2";
|
||||
break;
|
||||
case MxL_5007_V4:
|
||||
name = "MxL5007T.v4";
|
||||
break;
|
||||
default:
|
||||
name = "MxL5007T";
|
||||
printk(KERN_WARNING "%s: unknown rev (%02x)\n", __func__, id);
|
||||
id = MxL_UNKNOWN_ID;
|
||||
}
|
||||
state->chip_id = id;
|
||||
|
@ -975,7 +829,7 @@ struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
|
|||
mutex_lock(&mxl5007t_list_mutex);
|
||||
instance = hybrid_tuner_request_state(struct mxl5007t_state, state,
|
||||
hybrid_tuner_instance_list,
|
||||
i2c, addr, "mxl5007");
|
||||
i2c, addr, "mxl5007t");
|
||||
switch (instance) {
|
||||
case 0:
|
||||
goto fail;
|
||||
|
@ -1018,7 +872,7 @@ EXPORT_SYMBOL_GPL(mxl5007t_attach);
|
|||
MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver");
|
||||
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("0.1");
|
||||
MODULE_VERSION("0.2");
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
|
|
|
@ -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);
|
||||
|
||||
regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */
|
||||
regs[R_EP3] |= sm ? (1 << 7) : 0 |
|
||||
sm_lt ? (1 << 6) : 0 |
|
||||
sm_xt ? (1 << 5) : 0;
|
||||
regs[R_EP3] |= (sm ? (1 << 7) : 0) |
|
||||
(sm_lt ? (1 << 6) : 0) |
|
||||
(sm_xt ? (1 << 5) : 0);
|
||||
|
||||
return tda18271_write_regs(fe, R_EP3, 1);
|
||||
}
|
||||
|
|
|
@ -818,6 +818,38 @@ fail:
|
|||
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,
|
||||
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",
|
||||
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);
|
||||
if (tda_fail(ret))
|
||||
goto fail;
|
||||
|
@ -1159,6 +1195,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
|
|||
/* new tuner instance */
|
||||
priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
|
||||
priv->role = (cfg) ? cfg->role : TDA18271_MASTER;
|
||||
priv->config = (cfg) ? cfg->config : 0;
|
||||
priv->cal_initialized = false;
|
||||
mutex_init(&priv->lock);
|
||||
|
||||
|
|
|
@ -91,11 +91,6 @@ enum tda18271_pll {
|
|||
TDA18271_CAL_PLL,
|
||||
};
|
||||
|
||||
enum tda18271_mode {
|
||||
TDA18271_ANALOG,
|
||||
TDA18271_DIGITAL,
|
||||
};
|
||||
|
||||
struct tda18271_map_layout;
|
||||
|
||||
enum tda18271_ver {
|
||||
|
@ -114,6 +109,7 @@ struct tda18271_priv {
|
|||
enum tda18271_i2c_gate gate;
|
||||
enum tda18271_ver id;
|
||||
|
||||
unsigned int config; /* interface to saa713x / tda829x */
|
||||
unsigned int tm_rfcal;
|
||||
unsigned int cal_initialized:1;
|
||||
unsigned int small_i2c:1;
|
||||
|
|
|
@ -79,6 +79,16 @@ struct tda18271_config {
|
|||
|
||||
/* some i2c providers cant write all 39 registers at once */
|
||||
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))
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
||||
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,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct tda827x_priv *priv = fe->tuner_priv;
|
||||
u8 buf[14];
|
||||
int rc;
|
||||
|
||||
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
|
||||
.buf = buf, .len = sizeof(buf) };
|
||||
|
@ -183,27 +203,29 @@ static int tda827xo_set_params(struct dvb_frontend *fe,
|
|||
buf[13] = 0x40;
|
||||
|
||||
msg.len = 14;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
|
||||
printk("%s: could not write to tuner at addr: 0x%02x\n",
|
||||
__func__, priv->i2c_addr << 1);
|
||||
return -EIO;
|
||||
}
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
msleep(500);
|
||||
/* correct CP value */
|
||||
buf[0] = 0x30;
|
||||
buf[1] = 0x50 + tda827x_table[i].cp;
|
||||
msg.len = 2;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
priv->frequency = params->frequency;
|
||||
priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 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)
|
||||
|
@ -214,9 +236,7 @@ static int tda827xo_sleep(struct dvb_frontend *fe)
|
|||
.buf = buf, .len = sizeof(buf) };
|
||||
|
||||
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 (priv->cfg && priv->cfg->sleep)
|
||||
priv->cfg->sleep(fe);
|
||||
|
@ -266,44 +286,44 @@ static int tda827xo_set_analog_params(struct dvb_frontend *fe,
|
|||
|
||||
msg.buf = tuner_reg;
|
||||
msg.len = 8;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
msg.buf = reg2;
|
||||
msg.len = 2;
|
||||
reg2[0] = 0x80;
|
||||
reg2[1] = 0;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
reg2[0] = 0x60;
|
||||
reg2[1] = 0xbf;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
reg2[0] = 0x30;
|
||||
reg2[1] = tuner_reg[4] + 0x80;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
msleep(1);
|
||||
reg2[0] = 0x30;
|
||||
reg2[1] = tuner_reg[4] + 4;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
msleep(1);
|
||||
reg2[0] = 0x30;
|
||||
reg2[1] = tuner_reg[4];
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
msleep(550);
|
||||
reg2[0] = 0x30;
|
||||
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[1] = 0x3f;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
reg2[0] = 0x80;
|
||||
reg2[1] = 0x08; /* Vsync en */
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
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,
|
||||
.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;
|
||||
};
|
||||
|
||||
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 = 67250000, .svco = 0, .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}
|
||||
};
|
||||
|
||||
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[] = {
|
||||
{ .lomax = 56875000, .svco = 3, .spd = 4, .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) };
|
||||
|
||||
dprintk("%s:\n", __func__);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
if (priv->cfg && priv->cfg->sleep)
|
||||
priv->cfg->sleep(fe);
|
||||
|
@ -455,7 +500,7 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
|
|||
buf[1] = high ? 0 : 1;
|
||||
if (priv->cfg->config == 2)
|
||||
buf[1] = high ? 1 : 0;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
break;
|
||||
case 3: /* switch with GPIO of saa713x */
|
||||
if (fe->callback)
|
||||
|
@ -469,12 +514,13 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
|
|||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct tda827x_priv *priv = fe->tuner_priv;
|
||||
struct tda827xa_data *frequency_map = tda827xa_dvbt;
|
||||
u8 buf[11];
|
||||
|
||||
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
|
||||
.buf = buf, .len = sizeof(buf) };
|
||||
|
||||
int i, tuner_freq, if_freq;
|
||||
int i, tuner_freq, if_freq, rc;
|
||||
u32 N;
|
||||
|
||||
dprintk("%s:\n", __func__);
|
||||
|
@ -495,56 +541,58 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
|
|||
}
|
||||
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;
|
||||
while (tda827xa_dvbt[i].lomax < tuner_freq) {
|
||||
if(tda827xa_dvbt[i + 1].lomax == 0)
|
||||
while (frequency_map[i].lomax < tuner_freq) {
|
||||
if (frequency_map[i + 1].lomax == 0)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
|
||||
N = ((tuner_freq + 31250) / 62500) << tda827xa_dvbt[i].spd;
|
||||
N = ((tuner_freq + 31250) / 62500) << frequency_map[i].spd;
|
||||
buf[0] = 0; // subaddress
|
||||
buf[1] = N >> 8;
|
||||
buf[2] = N & 0xff;
|
||||
buf[3] = 0;
|
||||
buf[4] = 0x16;
|
||||
buf[5] = (tda827xa_dvbt[i].spd << 5) + (tda827xa_dvbt[i].svco << 3) +
|
||||
tda827xa_dvbt[i].sbs;
|
||||
buf[6] = 0x4b + (tda827xa_dvbt[i].gc3 << 4);
|
||||
buf[5] = (frequency_map[i].spd << 5) + (frequency_map[i].svco << 3) +
|
||||
frequency_map[i].sbs;
|
||||
buf[6] = 0x4b + (frequency_map[i].gc3 << 4);
|
||||
buf[7] = 0x1c;
|
||||
buf[8] = 0x06;
|
||||
buf[9] = 0x24;
|
||||
buf[10] = 0x00;
|
||||
msg.len = 11;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
|
||||
printk("%s: could not write to tuner at addr: 0x%02x\n",
|
||||
__func__, priv->i2c_addr << 1);
|
||||
return -EIO;
|
||||
}
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
buf[0] = 0x90;
|
||||
buf[1] = 0xff;
|
||||
buf[2] = 0x60;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0x59; // lpsel, for 6MHz + 2
|
||||
msg.len = 5;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
buf[0] = 0xa0;
|
||||
buf[1] = 0x40;
|
||||
msg.len = 2;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
msleep(11);
|
||||
msg.flags = I2C_M_RD;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
msg.flags = 0;
|
||||
|
||||
buf[1] >>= 4;
|
||||
|
@ -553,49 +601,55 @@ static int tda827xa_set_params(struct dvb_frontend *fe,
|
|||
tda827xa_lna_gain(fe, 0, NULL);
|
||||
buf[0] = 0x60;
|
||||
buf[1] = 0x0c;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
buf[0] = 0xc0;
|
||||
buf[1] = 0x99; // lpsel, for 6MHz + 2
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
buf[0] = 0x60;
|
||||
buf[1] = 0x3c;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
/* correct CP value */
|
||||
buf[0] = 0x30;
|
||||
buf[1] = 0x10 + tda827xa_dvbt[i].scr;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
buf[1] = 0x10 + frequency_map[i].scr;
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
msleep(163);
|
||||
buf[0] = 0xc0;
|
||||
buf[1] = 0x39; // lpsel, for 6MHz + 2
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
msleep(3);
|
||||
/* freeze AGC1 */
|
||||
buf[0] = 0x50;
|
||||
buf[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
buf[1] = 0x4f + (frequency_map[i].gc3 << 4);
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
if (rc < 0)
|
||||
goto err;
|
||||
|
||||
priv->frequency = params->frequency;
|
||||
priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 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[10] = 0x00;
|
||||
msg.len = 11;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
tuner_reg[0] = 0x90;
|
||||
tuner_reg[1] = 0xff;
|
||||
|
@ -651,19 +705,19 @@ static int tda827xa_set_analog_params(struct dvb_frontend *fe,
|
|||
tuner_reg[3] = 0;
|
||||
tuner_reg[4] = 0x99 + (priv->lpsel << 1);
|
||||
msg.len = 5;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
tuner_reg[0] = 0xa0;
|
||||
tuner_reg[1] = 0xc0;
|
||||
msg.len = 2;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
tuner_reg[0] = 0x30;
|
||||
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;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
msg.flags = 0;
|
||||
tuner_reg[1] >>= 4;
|
||||
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);
|
||||
tuner_reg[0] = 0x60;
|
||||
tuner_reg[1] = 0x3c;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
msleep(163);
|
||||
tuner_reg[0] = 0x50;
|
||||
tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
tuner_reg[0] = 0x80;
|
||||
tuner_reg[1] = 0x28;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
tuner_reg[0] = 0xb0;
|
||||
tuner_reg[1] = 0x01;
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
tuner_reg[0] = 0xc0;
|
||||
tuner_reg[1] = 0x19 + (priv->lpsel << 1);
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
tuner_transfer(fe, &msg, 1);
|
||||
|
||||
priv->frequency = params->frequency;
|
||||
|
||||
|
@ -703,7 +757,7 @@ static void tda827xa_agcf(struct dvb_frontend *fe)
|
|||
unsigned char data[] = {0x80, 0x2c};
|
||||
struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
|
||||
.buf = data, .len = 2};
|
||||
i2c_transfer(priv->i2c_adap, &msg, 1);
|
||||
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)
|
||||
{ u8 data;
|
||||
{
|
||||
u8 data;
|
||||
int rc;
|
||||
struct tda827x_priv *priv = fe->tuner_priv;
|
||||
struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = I2C_M_RD,
|
||||
.buf = &data, .len = 1 };
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer(priv->i2c_adap, &msg, 1) != 1) {
|
||||
|
||||
rc = tuner_transfer(fe, &msg, 1);
|
||||
|
||||
if (rc < 0) {
|
||||
printk("%s: could not read from tuner at addr: 0x%02x\n",
|
||||
__func__, msg.addr << 1);
|
||||
return -EIO;
|
||||
return rc;
|
||||
}
|
||||
if ((data & 0x3c) == 0) {
|
||||
dprintk("tda827x tuner found\n");
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/videodev.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include "tuner-i2c.h"
|
||||
#include "tda8290.h"
|
||||
#include "tda827x.h"
|
||||
|
@ -566,8 +566,11 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
|
|||
u8 data;
|
||||
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;
|
||||
}
|
||||
|
||||
analog_ops->i2c_gate_ctrl(fe, 1);
|
||||
|
||||
|
@ -615,11 +618,13 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
|
|||
|
||||
if (ret != 1) {
|
||||
tuner_warn("tuner access failed!\n");
|
||||
analog_ops->i2c_gate_ctrl(fe, 0);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
if ((data == 0x83) || (data == 0x84)) {
|
||||
priv->ver |= TDA18271;
|
||||
tda829x_tda18271_config.config = priv->cfg.config;
|
||||
dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
|
||||
priv->i2c_props.adap, &tda829x_tda18271_config);
|
||||
} else {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/videodev.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/tuner.h>
|
||||
#include "tuner-i2c.h"
|
||||
#include "tea5761.h"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/videodev.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include "tuner-i2c.h"
|
||||
#include "tea5767.h"
|
||||
|
||||
|
|
|
@ -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",
|
||||
__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 */
|
||||
priv->freq_hz = params->frequency * 62500;
|
||||
|
@ -970,8 +973,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
|
|||
case 1:
|
||||
/* new tuner instance */
|
||||
priv->bandwidth = BANDWIDTH_6_MHZ;
|
||||
priv->if_khz = cfg->if_khz;
|
||||
|
||||
fe->tuner_priv = priv;
|
||||
break;
|
||||
default:
|
||||
|
@ -980,6 +981,13 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
|
|||
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
|
||||
instance of the driver has loaded the firmware.
|
||||
*/
|
||||
|
|
|
@ -13,7 +13,7 @@ config DVB_B2C2_FLEXCOP
|
|||
select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
|
||||
select DVB_ISL6421 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
|
||||
help
|
||||
Support for the digital TV receiver chip made by B2C2 Inc. included in
|
||||
|
|
|
@ -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
|
||||
obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
|
||||
|
||||
|
||||
ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
|
||||
b2c2-flexcop-objs += flexcop-dma.o
|
||||
endif
|
||||
|
|
|
@ -28,11 +28,14 @@
|
|||
|
||||
/* Steal from usb.h */
|
||||
#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
|
||||
#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
|
||||
#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 pci_dev *pdev;
|
||||
|
@ -91,16 +94,14 @@ struct flexcop_device {
|
|||
int fullts_streaming_state;
|
||||
|
||||
/* bus specific callbacks */
|
||||
flexcop_ibi_value (*read_ibi_reg) (struct flexcop_device *, flexcop_ibi_register);
|
||||
int (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value);
|
||||
|
||||
|
||||
int (*i2c_request) (struct flexcop_i2c_adapter*,
|
||||
flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *,
|
||||
flexcop_ibi_register);
|
||||
int (*write_ibi_reg) (struct flexcop_device *,
|
||||
flexcop_ibi_register, flexcop_ibi_value);
|
||||
int (*i2c_request) (struct flexcop_i2c_adapter *,
|
||||
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);
|
||||
|
||||
void *bus_specific;
|
||||
};
|
||||
|
||||
|
@ -111,22 +112,28 @@ void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len);
|
|||
void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no);
|
||||
|
||||
struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len);
|
||||
void flexcop_device_kfree(struct flexcop_device*);
|
||||
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_reset_block_300(struct flexcop_device *fc);
|
||||
|
||||
/* 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);
|
||||
|
||||
int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
|
||||
int flexcop_dma_control_size_irq(struct flexcop_device *fc, 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_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);
|
||||
int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
|
||||
flexcop_dma_index_t no, int onoff);
|
||||
int flexcop_dma_control_size_irq(struct flexcop_device *fc,
|
||||
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_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 */
|
||||
/* 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);
|
||||
|
||||
/* 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_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 */
|
||||
/* 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);
|
||||
|
||||
/* from flexcop-i2c.c */
|
||||
|
@ -159,11 +168,14 @@ int flexcop_sram_init(struct flexcop_device *fc);
|
|||
|
||||
/* from flexcop-misc.c */
|
||||
void flexcop_determine_revision(struct flexcop_device *fc);
|
||||
void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const char *suffix);
|
||||
void flexcop_dump_reg(struct flexcop_device *fc, flexcop_ibi_register reg, int num);
|
||||
void flexcop_device_name(struct flexcop_device *fc,
|
||||
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 */
|
||||
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_smc_ctrl(struct flexcop_device *fc, int onoff);
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
/*
|
||||
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
*
|
||||
* flexcop-dma.c - methods for configuring and controlling the DMA of the FlexCop.
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
* flexcop-dma.c - configuring and controlling the DMA of the FlexCop
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
#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;
|
||||
dma_addr_t tdma = 0;
|
||||
|
@ -32,7 +31,8 @@ EXPORT_SYMBOL(flexcop_dma_allocate);
|
|||
|
||||
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));
|
||||
}
|
||||
EXPORT_SYMBOL(flexcop_dma_free);
|
||||
|
@ -44,8 +44,8 @@ int flexcop_dma_config(struct flexcop_device *fc,
|
|||
flexcop_ibi_value v0x0,v0x4,v0xc;
|
||||
v0x0.raw = v0x4.raw = v0xc.raw = 0;
|
||||
|
||||
v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2;
|
||||
v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2;
|
||||
v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2;
|
||||
v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2;
|
||||
v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
|
||||
|
||||
if ((dma_idx & FC_DMA_1) == dma_idx) {
|
||||
|
@ -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_01c,v0xc);
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
@ -81,7 +82,8 @@ int flexcop_dma_xfer_control(struct flexcop_device *fc,
|
|||
r0x0 = dma2_010;
|
||||
r0xc = dma2_01c;
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
@ -154,8 +156,7 @@ EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
|
|||
|
||||
/* 1 cycles = 1.97 msec */
|
||||
int flexcop_dma_config_timer(struct flexcop_device *fc,
|
||||
flexcop_dma_index_t dma_idx,
|
||||
u8 cycles)
|
||||
flexcop_dma_index_t dma_idx, u8 cycles)
|
||||
{
|
||||
flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
|
||||
flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/*
|
||||
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
*
|
||||
* flexcop-eeprom.c - eeprom access methods (currently only MAC address reading is used)
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
* flexcop-eeprom.c - eeprom access methods (currently only MAC address reading)
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
#include "flexcop.h"
|
||||
|
||||
|
@ -14,17 +12,17 @@ static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 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;
|
||||
|
||||
for (i = 0; i < retries; i++) {
|
||||
if (eeprom_write(adapter, addr, wbuf, len) == len) {
|
||||
if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1)
|
||||
return 1;
|
||||
for (i = 0; i < retries; i++) {
|
||||
if (eeprom_write(adapter, addr, wbuf, len) == len) {
|
||||
if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -39,12 +37,10 @@ static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len)
|
|||
return 0;
|
||||
|
||||
memcpy(wbuf, key, len);
|
||||
|
||||
wbuf[16] = 0;
|
||||
wbuf[17] = 0;
|
||||
wbuf[18] = 0;
|
||||
wbuf[19] = calc_lrc(wbuf, 19);
|
||||
|
||||
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;
|
||||
|
||||
memcpy(key, buf, len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -74,9 +69,7 @@ static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac)
|
|||
tmp[3] = mac[5];
|
||||
tmp[4] = mac[6];
|
||||
tmp[5] = mac[7];
|
||||
|
||||
} else {
|
||||
|
||||
tmp[0] = mac[0];
|
||||
tmp[1] = mac[1];
|
||||
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)
|
||||
return 1;
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -110,7 +103,8 @@ static u8 calc_lrc(u8 *buf, int len)
|
|||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
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 (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;
|
||||
/* 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
|
||||
memcpy(fc->dvb_adapter.proposed_mac,buf,6);
|
||||
}
|
||||
|
|
|
@ -592,14 +592,14 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
fc->fe_sleep = ops->sleep;
|
||||
ops->sleep = flexcop_sleep;
|
||||
|
||||
fc->dev_type = FC_SKY;
|
||||
fc->dev_type = FC_SKY_REV26;
|
||||
goto fe_found;
|
||||
}
|
||||
|
||||
/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
|
||||
fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
|
||||
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;
|
||||
goto fe_found;
|
||||
}
|
||||
|
@ -653,7 +653,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
fc->fe_sleep = ops->sleep;
|
||||
ops->sleep = flexcop_sleep;
|
||||
|
||||
fc->dev_type = FC_SKY_OLD;
|
||||
fc->dev_type = FC_SKY_REV23;
|
||||
goto fe_found;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +1,30 @@
|
|||
/*
|
||||
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
*
|
||||
* flexcop-hw-filter.c - pid and mac address filtering and corresponding control functions.
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
* flexcop-hw-filter.c - pid and mac address filtering and control functions
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
#include "flexcop.h"
|
||||
|
||||
static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff)
|
||||
{
|
||||
flexcop_set_ibi_value(ctrl_208,Rcv_Data_sig,onoff);
|
||||
|
||||
deb_ts("rcv_data is now: '%s'\n",onoff ? "on" : "off");
|
||||
flexcop_set_ibi_value(ctrl_208, Rcv_Data_sig, onoff);
|
||||
deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off");
|
||||
}
|
||||
|
||||
void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff)
|
||||
{
|
||||
flexcop_set_ibi_value(ctrl_208,SMC_Enable_sig,onoff);
|
||||
flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff);
|
||||
}
|
||||
|
||||
static void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff)
|
||||
{
|
||||
flexcop_set_ibi_value(ctrl_208,Null_filter_sig,onoff);
|
||||
flexcop_set_ibi_value(ctrl_208, Null_filter_sig, onoff);
|
||||
}
|
||||
|
||||
void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6])
|
||||
{
|
||||
flexcop_ibi_value v418,v41c;
|
||||
v41c = fc->read_ibi_reg(fc,mac_address_41c);
|
||||
flexcop_ibi_value v418, v41c;
|
||||
v41c = fc->read_ibi_reg(fc, mac_address_41c);
|
||||
|
||||
v418.mac_address_418.MAC1 = mac[0];
|
||||
v418.mac_address_418.MAC2 = mac[1];
|
||||
|
@ -36,27 +33,28 @@ void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6])
|
|||
v41c.mac_address_41c.MAC7 = mac[4];
|
||||
v41c.mac_address_41c.MAC8 = mac[5];
|
||||
|
||||
fc->write_ibi_reg(fc,mac_address_418,v418);
|
||||
fc->write_ibi_reg(fc,mac_address_41c,v41c);
|
||||
fc->write_ibi_reg(fc, mac_address_418, v418);
|
||||
fc->write_ibi_reg(fc, mac_address_41c, v41c);
|
||||
}
|
||||
|
||||
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 */
|
||||
flexcop_ibi_value v30c;
|
||||
v30c.pid_filter_30c_ext_ind_0_7.Group_PID = pid;
|
||||
v30c.pid_filter_30c_ext_ind_0_7.Group_mask = mask;
|
||||
fc->write_ibi_reg(fc,pid_filter_30c,v30c);
|
||||
fc->write_ibi_reg(fc, pid_filter_30c, v30c);
|
||||
}
|
||||
|
||||
static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff)
|
||||
{
|
||||
flexcop_set_ibi_value(ctrl_208,Mask_filter_sig,onoff);
|
||||
flexcop_set_ibi_value(ctrl_208, Mask_filter_sig, onoff);
|
||||
}
|
||||
|
||||
/* this fancy define reduces the code size of the quite similar PID controlling of
|
||||
|
@ -65,91 +63,112 @@ static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff)
|
|||
|
||||
#define pid_ctrl(vregname,field,enablefield,trans_field,transval) \
|
||||
flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \
|
||||
v208 = fc->read_ibi_reg(fc, ctrl_208); \
|
||||
\
|
||||
vpid.vregname.field = onoff ? pid : 0x1fff; \
|
||||
vpid.vregname.trans_field = transval; \
|
||||
v208.ctrl_208.enablefield = onoff; \
|
||||
\
|
||||
fc->write_ibi_reg(fc,vregname,vpid); \
|
||||
fc->write_ibi_reg(fc,ctrl_208,v208);
|
||||
v208 = fc->read_ibi_reg(fc, ctrl_208); \
|
||||
vpid.vregname.field = onoff ? pid : 0x1fff; \
|
||||
vpid.vregname.trans_field = transval; \
|
||||
v208.ctrl_208.enablefield = onoff; \
|
||||
fc->write_ibi_reg(fc, vregname, vpid); \
|
||||
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)
|
||||
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.
|
||||
* I decided against it, but to use the real register names */
|
||||
switch (index) {
|
||||
case 0: flexcop_pid_Stream1_PID_ctrl(fc,pid,onoff); break;
|
||||
case 1: flexcop_pid_Stream2_PID_ctrl(fc,pid,onoff); 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:
|
||||
if (fc->has_32_hw_pid_filter && index < 38) {
|
||||
flexcop_ibi_value vpid,vid;
|
||||
case 0:
|
||||
flexcop_pid_Stream1_PID_ctrl(fc, pid, onoff);
|
||||
break;
|
||||
case 1:
|
||||
flexcop_pid_Stream2_PID_ctrl(fc, pid, onoff);
|
||||
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:
|
||||
if (fc->has_32_hw_pid_filter && index < 38) {
|
||||
flexcop_ibi_value vpid, vid;
|
||||
|
||||
/* set the index */
|
||||
vid = fc->read_ibi_reg(fc,index_reg_310);
|
||||
vid.index_reg_310.index_reg = index - 6;
|
||||
fc->write_ibi_reg(fc,index_reg_310, vid);
|
||||
/* set the index */
|
||||
vid = fc->read_ibi_reg(fc, index_reg_310);
|
||||
vid.index_reg_310.index_reg = index - 6;
|
||||
fc->write_ibi_reg(fc, index_reg_310, vid);
|
||||
|
||||
vpid = fc->read_ibi_reg(fc,pid_n_reg_314);
|
||||
vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff;
|
||||
vpid.pid_n_reg_314.PID_enable_bit = onoff;
|
||||
fc->write_ibi_reg(fc,pid_n_reg_314, vpid);
|
||||
}
|
||||
break;
|
||||
vpid = fc->read_ibi_reg(fc, pid_n_reg_314);
|
||||
vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff;
|
||||
vpid.pid_n_reg_314.PID_enable_bit = onoff;
|
||||
fc->write_ibi_reg(fc, pid_n_reg_314, vpid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc,int onoff)
|
||||
static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc, int onoff)
|
||||
{
|
||||
if (fc->fullts_streaming_state != onoff) {
|
||||
deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling");
|
||||
flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff));
|
||||
flexcop_pid_group_filter_ctrl(fc,onoff);
|
||||
flexcop_pid_group_filter_ctrl(fc, onoff);
|
||||
fc->fullts_streaming_state = onoff;
|
||||
}
|
||||
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;
|
||||
|
||||
|
@ -164,24 +183,25 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d
|
|||
* - or the requested pid is 0x2000 */
|
||||
|
||||
if (!fc->pid_filtering && fc->feedcount == onoff)
|
||||
flexcop_toggle_fullts_streaming(fc,onoff);
|
||||
flexcop_toggle_fullts_streaming(fc, onoff);
|
||||
|
||||
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)
|
||||
flexcop_toggle_fullts_streaming(fc,1);
|
||||
flexcop_toggle_fullts_streaming(fc, 1);
|
||||
else if (dvbdmxfeed->pid == 0x2000)
|
||||
flexcop_toggle_fullts_streaming(fc,onoff);
|
||||
flexcop_toggle_fullts_streaming(fc, onoff);
|
||||
else
|
||||
flexcop_toggle_fullts_streaming(fc,0);
|
||||
flexcop_toggle_fullts_streaming(fc, 0);
|
||||
}
|
||||
|
||||
/* if it was the first or last feed request change the stream-status */
|
||||
if (fc->feedcount == onoff) {
|
||||
flexcop_rcv_data_ctrl(fc,onoff);
|
||||
flexcop_rcv_data_ctrl(fc, onoff);
|
||||
if (fc->stream_control) /* device specific stream control */
|
||||
fc->stream_control(fc,onoff);
|
||||
fc->stream_control(fc, onoff);
|
||||
|
||||
/* feeding stopped -> reset the flexcop filter*/
|
||||
if (onoff == 0) {
|
||||
|
@ -189,7 +209,6 @@ int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *d
|
|||
flexcop_hw_filter_init(fc);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(flexcop_pid_feed_control);
|
||||
|
@ -199,15 +218,15 @@ void flexcop_hw_filter_init(struct flexcop_device *fc)
|
|||
int i;
|
||||
flexcop_ibi_value v;
|
||||
for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++)
|
||||
flexcop_pid_control(fc,i,0x1fff,0);
|
||||
flexcop_pid_control(fc, i, 0x1fff, 0);
|
||||
|
||||
flexcop_pid_group_filter(fc, 0, 0x1fe0);
|
||||
flexcop_pid_group_filter_ctrl(fc,0);
|
||||
flexcop_pid_group_filter_ctrl(fc, 0);
|
||||
|
||||
v = fc->read_ibi_reg(fc,pid_filter_308);
|
||||
v = fc->read_ibi_reg(fc, pid_filter_308);
|
||||
v.pid_filter_308.EMM_filter_4 = 1;
|
||||
v.pid_filter_308.EMM_filter_6 = 0;
|
||||
fc->write_ibi_reg(fc,pid_filter_308,v);
|
||||
fc->write_ibi_reg(fc, pid_filter_308, v);
|
||||
|
||||
flexcop_null_filter_ctrl(fc, 1);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
#include "flexcop.h"
|
||||
|
||||
#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;
|
||||
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);
|
||||
|
||||
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;
|
||||
deb_i2c("i2c success\n");
|
||||
return 0;
|
||||
|
@ -36,17 +33,31 @@ static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r
|
|||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
if (ret != 0) {
|
||||
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 > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
|
||||
}
|
||||
|
||||
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;
|
||||
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 */
|
||||
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.data3_reg = len > 1 ? buf[2] : 0;
|
||||
r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
|
||||
|
@ -94,7 +104,7 @@ static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100,
|
|||
}
|
||||
|
||||
int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
|
||||
flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
|
||||
flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -117,7 +127,6 @@ int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
|
|||
printk("rd(");
|
||||
else
|
||||
printk("wr(");
|
||||
|
||||
printk("%02x): %02x ", chipaddr, addr);
|
||||
#endif
|
||||
|
||||
|
@ -163,7 +172,8 @@ int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
|
|||
EXPORT_SYMBOL(flexcop_i2c_request);
|
||||
|
||||
/* 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);
|
||||
int i, ret = 0;
|
||||
|
@ -182,12 +192,13 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs
|
|||
/* reading */
|
||||
if (i+1 < num && (msgs[i+1].flags == I2C_M_RD)) {
|
||||
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 */
|
||||
} else /* writing */
|
||||
ret = i2c->fc->i2c_request(i2c, FC_WRITE, msgs[i].addr,
|
||||
msgs[i].buf[0], &msgs[i].buf[1],
|
||||
msgs[i].len - 1);
|
||||
msgs[i].buf[0], &msgs[i].buf[1],
|
||||
msgs[i].len - 1);
|
||||
if (ret < 0) {
|
||||
err("i2c master_xfer failed");
|
||||
break;
|
||||
|
@ -214,23 +225,21 @@ static struct i2c_algorithm flexcop_algo = {
|
|||
int flexcop_i2c_init(struct flexcop_device *fc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_init(&fc->i2c_mutex);
|
||||
|
||||
fc->fc_i2c_adap[0].fc = fc;
|
||||
fc->fc_i2c_adap[1].fc = fc;
|
||||
fc->fc_i2c_adap[2].fc = fc;
|
||||
|
||||
fc->fc_i2c_adap[0].port = FC_I2C_PORT_DEMOD;
|
||||
fc->fc_i2c_adap[1].port = FC_I2C_PORT_EEPROM;
|
||||
fc->fc_i2c_adap[2].port = FC_I2C_PORT_TUNER;
|
||||
|
||||
strlcpy(fc->fc_i2c_adap[0].i2c_adap.name, "B2C2 FlexCop I2C to demod",
|
||||
sizeof(fc->fc_i2c_adap[0].i2c_adap.name));
|
||||
sizeof(fc->fc_i2c_adap[0].i2c_adap.name));
|
||||
strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",
|
||||
sizeof(fc->fc_i2c_adap[1].i2c_adap.name));
|
||||
sizeof(fc->fc_i2c_adap[1].i2c_adap.name));
|
||||
strlcpy(fc->fc_i2c_adap[2].i2c_adap.name, "B2C2 FlexCop I2C to tuner",
|
||||
sizeof(fc->fc_i2c_adap[2].i2c_adap.name));
|
||||
sizeof(fc->fc_i2c_adap[2].i2c_adap.name));
|
||||
|
||||
i2c_set_adapdata(&fc->fc_i2c_adap[0].i2c_adap, &fc->fc_i2c_adap[0]);
|
||||
i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
|
||||
|
@ -268,7 +277,6 @@ adap_2_failed:
|
|||
i2c_del_adapter(&fc->fc_i2c_adap[1].i2c_adap);
|
||||
adap_1_failed:
|
||||
i2c_del_adapter(&fc->fc_i2c_adap[0].i2c_adap);
|
||||
|
||||
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[0].i2c_adap);
|
||||
}
|
||||
|
||||
fc->init_state &= ~FC_STATE_I2C_INIT;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/*
|
||||
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
*
|
||||
* flexcop-misc.c - miscellaneous functions.
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
* flexcop-misc.c - miscellaneous functions
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
#include "flexcop.h"
|
||||
|
||||
|
@ -12,39 +10,43 @@ void flexcop_determine_revision(struct flexcop_device *fc)
|
|||
flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204);
|
||||
|
||||
switch (v.misc_204.Rev_N_sig_revision_hi) {
|
||||
case 0x2:
|
||||
deb_info("found a FlexCopII.\n");
|
||||
fc->rev = FLEXCOP_II;
|
||||
break;
|
||||
case 0x3:
|
||||
deb_info("found a FlexCopIIb.\n");
|
||||
fc->rev = FLEXCOP_IIB;
|
||||
break;
|
||||
case 0x0:
|
||||
deb_info("found a FlexCopIII.\n");
|
||||
fc->rev = FLEXCOP_III;
|
||||
break;
|
||||
default:
|
||||
err("unkown FlexCop Revision: %x. Please report the linux-dvb@linuxtv.org.",v.misc_204.Rev_N_sig_revision_hi);
|
||||
break;
|
||||
case 0x2:
|
||||
deb_info("found a FlexCopII.\n");
|
||||
fc->rev = FLEXCOP_II;
|
||||
break;
|
||||
case 0x3:
|
||||
deb_info("found a FlexCopIIb.\n");
|
||||
fc->rev = FLEXCOP_IIB;
|
||||
break;
|
||||
case 0x0:
|
||||
deb_info("found a FlexCopIII.\n");
|
||||
fc->rev = FLEXCOP_III;
|
||||
break;
|
||||
default:
|
||||
err("unknown FlexCop Revision: %x. Please report this to "
|
||||
"linux-dvb@linuxtv.org.",
|
||||
v.misc_204.Rev_N_sig_revision_hi);
|
||||
break;
|
||||
}
|
||||
|
||||
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
|
||||
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. */
|
||||
}
|
||||
|
||||
static const char *flexcop_revision_names[] = {
|
||||
"Unkown chip",
|
||||
"Unknown chip",
|
||||
"FlexCopII",
|
||||
"FlexCopIIb",
|
||||
"FlexCopIII",
|
||||
};
|
||||
|
||||
static const char *flexcop_device_names[] = {
|
||||
"Unkown device",
|
||||
"Unknown device",
|
||||
"Air2PC/AirStar 2 DVB-T",
|
||||
"Air2PC/AirStar 2 ATSC 1st generation",
|
||||
"Air2PC/AirStar 2 ATSC 2nd generation",
|
||||
|
@ -61,21 +63,23 @@ static const char *flexcop_bus_names[] = {
|
|||
"PCI",
|
||||
};
|
||||
|
||||
void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const
|
||||
char *suffix)
|
||||
void flexcop_device_name(struct flexcop_device *fc,
|
||||
const char *prefix, const char *suffix)
|
||||
{
|
||||
info("%s '%s' at the '%s' bus controlled by a '%s' %s",prefix,
|
||||
flexcop_device_names[fc->dev_type],flexcop_bus_names[fc->bus_type],
|
||||
flexcop_revision_names[fc->rev],suffix);
|
||||
info("%s '%s' at the '%s' bus controlled by a '%s' %s",
|
||||
prefix, flexcop_device_names[fc->dev_type],
|
||||
flexcop_bus_names[fc->bus_type],
|
||||
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;
|
||||
int i;
|
||||
for (i = 0; i < num; i++) {
|
||||
v = fc->read_ibi_reg(fc,reg+4*i);
|
||||
deb_rdump("0x%03x: %08x, ",reg+4*i, v.raw);
|
||||
v = fc->read_ibi_reg(fc, reg+4*i);
|
||||
deb_rdump("0x%03x: %08x, ", reg+4*i, v.raw);
|
||||
}
|
||||
deb_rdump("\n");
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/*
|
||||
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
*
|
||||
* flexcop-pci.c - covers the PCI part including DMA transfers.
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* Linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
* flexcop-pci.c - covers the PCI part including DMA transfers
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
|
||||
#define FC_LOG_PREFIX "flexcop-pci"
|
||||
|
@ -11,7 +9,8 @@
|
|||
|
||||
static int enable_pid_filtering = 1;
|
||||
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;
|
||||
module_param(irq_chk_intv, int, 0644);
|
||||
|
@ -26,17 +25,17 @@ MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog.");
|
|||
#define DEBSTATUS " (debugging is not enabled)"
|
||||
#endif
|
||||
|
||||
#define deb_info(args...) dprintk(0x01,args)
|
||||
#define deb_reg(args...) dprintk(0x02,args)
|
||||
#define deb_ts(args...) dprintk(0x04,args)
|
||||
#define deb_irq(args...) dprintk(0x08,args)
|
||||
#define deb_chk(args...) dprintk(0x10,args)
|
||||
#define deb_info(args...) dprintk(0x01, args)
|
||||
#define deb_reg(args...) dprintk(0x02, args)
|
||||
#define deb_ts(args...) dprintk(0x04, args)
|
||||
#define deb_irq(args...) dprintk(0x08, args)
|
||||
#define deb_chk(args...) dprintk(0x10, args)
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug,
|
||||
"set debug level (1=info,2=regs,4=TS,8=irqdma,16=check (|-able))."
|
||||
DEBSTATUS);
|
||||
DEBSTATUS);
|
||||
|
||||
#define DRIVER_VERSION "0.1"
|
||||
#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
|
||||
|
@ -51,30 +50,30 @@ struct flexcop_pci {
|
|||
|
||||
void __iomem *io_mem;
|
||||
u32 irq;
|
||||
/* buffersize (at least for DMA1, need to be % 188 == 0,
|
||||
* this logic is required */
|
||||
/* buffersize (at least for DMA1, need to be % 188 == 0,
|
||||
* this logic is required */
|
||||
#define FC_DEFAULT_DMA1_BUFSIZE (1280 * 188)
|
||||
#define FC_DEFAULT_DMA2_BUFSIZE (10 * 188)
|
||||
struct flexcop_dma dma[2];
|
||||
|
||||
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_prev;
|
||||
int stream_problem;
|
||||
|
||||
spinlock_t irq_lock;
|
||||
|
||||
unsigned long last_irq;
|
||||
|
||||
struct delayed_work irq_check_work;
|
||||
|
||||
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;
|
||||
flexcop_ibi_value v;
|
||||
|
@ -82,19 +81,20 @@ static flexcop_ibi_value flexcop_pci_read_ibi_reg (struct flexcop_device *fc, fl
|
|||
|
||||
if (lastrreg != r || lastrval != v.raw) {
|
||||
lastrreg = r; lastrval = v.raw;
|
||||
deb_reg("new rd: %3x: %08x\n",r,v.raw);
|
||||
deb_reg("new rd: %3x: %08x\n", r, v.raw);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (lastwreg != r || lastwval != v.raw) {
|
||||
lastwreg = r; lastwval = v.raw;
|
||||
deb_reg("new wr: %3x: %08x\n",r,v.raw);
|
||||
deb_reg("new wr: %3x: %08x\n", r, v.raw);
|
||||
}
|
||||
|
||||
writel(v.raw, fc_pci->io_mem + r);
|
||||
|
@ -113,15 +113,16 @@ static void flexcop_pci_irq_check_work(struct work_struct *work)
|
|||
deb_chk("no IRQ since the last check\n");
|
||||
if (fc_pci->stream_problem++ == 3) {
|
||||
struct dvb_demux_feed *feed;
|
||||
deb_info("flexcop-pci: stream problem, resetting pid filter\n");
|
||||
|
||||
spin_lock_irq(&fc->demux.lock);
|
||||
list_for_each_entry(feed, &fc->demux.feed_list,
|
||||
list_head) {
|
||||
list_head) {
|
||||
flexcop_pid_feed_control(fc, feed, 0);
|
||||
}
|
||||
|
||||
list_for_each_entry(feed, &fc->demux.feed_list,
|
||||
list_head) {
|
||||
list_head) {
|
||||
flexcop_pid_feed_control(fc, feed, 1);
|
||||
}
|
||||
spin_unlock_irq(&fc->demux.lock);
|
||||
|
@ -149,11 +150,10 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
|
|||
flexcop_ibi_value v;
|
||||
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 */
|
||||
if (v.irq_20c.Data_receiver_error)
|
||||
deb_chk("data receiver error\n");
|
||||
if (v.irq_20c.Continuity_error_flag)
|
||||
|
@ -164,24 +164,29 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
|
|||
deb_chk("Transport error\n");
|
||||
|
||||
if ((fc_pci->count % 1000) == 0)
|
||||
deb_chk("%d valid irq took place so far\n",fc_pci->count);
|
||||
deb_chk("%d valid irq took place so far\n", fc_pci->count);
|
||||
|
||||
if (v.irq_20c.DMA1_IRQ_Status == 1) {
|
||||
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
|
||||
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);
|
||||
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
|
||||
* complete TS packets when reading from the DMA memory */
|
||||
} else if (v.irq_20c.DMA1_Timer_Status == 1) {
|
||||
dma_addr_t cur_addr =
|
||||
fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
|
||||
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),
|
||||
v.raw, (unsigned long long)cur_addr, cur_pos,
|
||||
fc_pci->last_dma1_cur_pos);
|
||||
|
@ -191,30 +196,36 @@ 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
|
||||
*/
|
||||
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,
|
||||
fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos,
|
||||
(fc_pci->dma[0].size*2) - fc_pci->last_dma1_cur_pos);
|
||||
fc_pci->dma[0].cpu_addr0 +
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos,
|
||||
cur_pos - 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);
|
||||
}
|
||||
deb_irq("\n");
|
||||
|
||||
fc_pci->last_dma1_cur_pos = cur_pos;
|
||||
fc_pci->count++;
|
||||
} 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;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&fc_pci->irq_lock,flags);
|
||||
|
||||
spin_unlock_irqrestore(&fc_pci->irq_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -222,52 +233,48 @@ static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff)
|
|||
{
|
||||
struct flexcop_pci *fc_pci = fc->bus_specific;
|
||||
if (onoff) {
|
||||
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_timer(fc,FC_DMA_1,0);
|
||||
|
||||
flexcop_dma_xfer_control(fc,FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1,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_timer(fc, FC_DMA_1, 0);
|
||||
flexcop_dma_xfer_control(fc, FC_DMA_1,
|
||||
FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1, 1);
|
||||
deb_irq("DMA xfer enabled\n");
|
||||
|
||||
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");
|
||||
|
||||
fc_pci->count_prev = fc_pci->count;
|
||||
|
||||
// fc_pci->active_dma1_addr = 0;
|
||||
// flexcop_dma_control_size_irq(fc,FC_DMA_1,1);
|
||||
|
||||
} 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");
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci)
|
||||
{
|
||||
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;
|
||||
|
||||
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]);
|
||||
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_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
|
||||
|
||||
flexcop_sram_set_dest(fc_pci->fc_dev, FC_SRAM_DEST_MEDIA |
|
||||
FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
|
||||
flexcop_sram_set_dest(fc_pci->fc_dev, FC_SRAM_DEST_CAO |
|
||||
FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
|
||||
fc_pci->init_state |= FC_PCI_DMA_INIT;
|
||||
|
||||
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)
|
||||
return ret;
|
||||
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
static int flexcop_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct flexcop_device *fc;
|
||||
struct flexcop_pci *fc_pci;
|
||||
|
@ -350,7 +353,7 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* general flexcop init */
|
||||
/* general flexcop init */
|
||||
fc_pci = fc->bus_specific;
|
||||
fc_pci->fc_dev = fc;
|
||||
|
||||
|
@ -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->i2c_request = flexcop_i2c_request;
|
||||
fc->get_mac_addr = flexcop_eeprom_check_mac_addr;
|
||||
|
||||
fc->stream_control = flexcop_pci_stream_control;
|
||||
|
||||
if (enable_pid_filtering)
|
||||
|
@ -368,29 +370,29 @@ static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
|
||||
fc->pid_filtering = enable_pid_filtering;
|
||||
fc->bus_type = FC_PCI;
|
||||
|
||||
fc->dev = &pdev->dev;
|
||||
fc->owner = THIS_MODULE;
|
||||
|
||||
/* bus specific part */
|
||||
/* bus specific part */
|
||||
fc_pci->pdev = pdev;
|
||||
if ((ret = flexcop_pci_init(fc_pci)) != 0)
|
||||
goto err_kfree;
|
||||
|
||||
/* init flexcop */
|
||||
/* init flexcop */
|
||||
if ((ret = flexcop_device_initialize(fc)) != 0)
|
||||
goto err_pci_exit;
|
||||
|
||||
/* init dma */
|
||||
/* init dma */
|
||||
if ((ret = flexcop_pci_dma_init(fc_pci)) != 0)
|
||||
goto err_fc_exit;
|
||||
|
||||
INIT_DELAYED_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work);
|
||||
|
||||
if (irq_chk_intv > 0)
|
||||
schedule_delayed_work(&fc_pci->irq_check_work,
|
||||
msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
|
||||
|
||||
if (irq_chk_intv > 0)
|
||||
schedule_delayed_work(&fc_pci->irq_check_work,
|
||||
msecs_to_jiffies(irq_chk_intv < 100 ?
|
||||
100 :
|
||||
irq_chk_intv));
|
||||
return ret;
|
||||
|
||||
err_fc_exit:
|
||||
|
@ -420,7 +422,6 @@ static void flexcop_pci_remove(struct pci_dev *pdev)
|
|||
|
||||
static struct pci_device_id flexcop_pci_tbl[] = {
|
||||
{ PCI_DEVICE(0x13d0, 0x2103) },
|
||||
/* { PCI_DEVICE(0x13d0, 0x2200) }, ? */
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
#ifndef __FLEXCOP_REG_H__
|
||||
#define __FLEXCOP_REG_H__
|
||||
|
||||
|
||||
typedef enum {
|
||||
FLEXCOP_UNK = 0,
|
||||
FLEXCOP_II,
|
||||
|
@ -18,13 +15,13 @@ typedef enum {
|
|||
|
||||
typedef enum {
|
||||
FC_UNK = 0,
|
||||
FC_AIR_DVB,
|
||||
FC_CABLE,
|
||||
FC_AIR_DVBT,
|
||||
FC_AIR_ATSC1,
|
||||
FC_AIR_ATSC2,
|
||||
FC_SKY,
|
||||
FC_SKY_OLD,
|
||||
FC_CABLE,
|
||||
FC_AIR_ATSC3,
|
||||
FC_SKY_REV23,
|
||||
FC_SKY_REV26,
|
||||
FC_SKY_REV27,
|
||||
FC_SKY_REV28,
|
||||
} flexcop_device_type_t;
|
||||
|
@ -36,12 +33,12 @@ typedef enum {
|
|||
|
||||
/* FlexCop IBI Registers */
|
||||
#if defined(__LITTLE_ENDIAN)
|
||||
#include "flexcop_ibi_value_le.h"
|
||||
#include "flexcop_ibi_value_le.h"
|
||||
#else
|
||||
#if defined(__BIG_ENDIAN)
|
||||
#include "flexcop_ibi_value_be.h"
|
||||
#include "flexcop_ibi_value_be.h"
|
||||
#else
|
||||
#error no endian defined
|
||||
#error no endian defined
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,45 +1,43 @@
|
|||
/*
|
||||
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
*
|
||||
* flexcop-sram.c - functions for controlling the SRAM.
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
* flexcop-sram.c - functions for controlling the SRAM
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
#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);
|
||||
}
|
||||
|
||||
int flexcop_sram_init(struct flexcop_device *fc)
|
||||
{
|
||||
switch (fc->rev) {
|
||||
case FLEXCOP_II:
|
||||
case FLEXCOP_IIB:
|
||||
flexcop_sram_set_chip(fc,FC_SRAM_1_32KB);
|
||||
break;
|
||||
case FLEXCOP_III:
|
||||
flexcop_sram_set_chip(fc,FC_SRAM_1_48KB);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
case FLEXCOP_II:
|
||||
case FLEXCOP_IIB:
|
||||
flexcop_sram_set_chip(fc, FC_SRAM_1_32KB);
|
||||
break;
|
||||
case FLEXCOP_III:
|
||||
flexcop_sram_set_chip(fc, FC_SRAM_1_48KB);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
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;
|
||||
|
||||
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) {
|
||||
err("SRAM destination target to available on FlexCopII(b)\n");
|
||||
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)
|
||||
v.sram_dest_reg_714.NET_Dest = target;
|
||||
|
@ -154,14 +152,12 @@ static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len
|
|||
else
|
||||
bank = 0x10000000;
|
||||
}
|
||||
|
||||
flex_sram_write(adapter, bank, addr & 0x7fff, buf, len);
|
||||
}
|
||||
|
||||
static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
|
||||
{
|
||||
u32 bank;
|
||||
|
||||
bank = 0;
|
||||
|
||||
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
|
||||
bank = 0x10000000;
|
||||
}
|
||||
|
||||
flex_sram_read(adapter, bank, addr & 0x7fff, buf, len);
|
||||
}
|
||||
|
||||
static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
|
||||
{
|
||||
u32 length;
|
||||
|
||||
while (len != 0) {
|
||||
length = len;
|
||||
|
||||
// check if the address range belongs to the same
|
||||
// 32K memory chip. If not, the data is read from
|
||||
// one chip at a time.
|
||||
/* check if the address range belongs to the same
|
||||
* 32K memory chip. If not, the data is read
|
||||
* from one chip at a time */
|
||||
if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
|
||||
length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
|
||||
}
|
||||
|
||||
sram_read_chunk(adapter, addr, buf, length);
|
||||
|
||||
addr = addr + length;
|
||||
buf = buf + 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)
|
||||
{
|
||||
u32 length;
|
||||
|
||||
while (len != 0) {
|
||||
length = len;
|
||||
|
||||
// check if the address range belongs to the same
|
||||
// 32K memory chip. If not, the data is written to
|
||||
// one chip at a time.
|
||||
/* check if the address range belongs to the same
|
||||
* 32K memory chip. If not, the data is
|
||||
* written to one chip at a time */
|
||||
if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
|
||||
length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
|
||||
}
|
||||
|
||||
sram_write_chunk(adapter, addr, buf, length);
|
||||
|
||||
addr = addr + length;
|
||||
buf = buf + 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
tmp = read_reg_dw(adapter, 0x71c);
|
||||
|
||||
write_reg_dw(adapter, 0x71c, 1);
|
||||
|
||||
if (read_reg_dw(adapter, 0x71c) != 0) {
|
||||
write_reg_dw(adapter, 0x71c, tmp);
|
||||
|
||||
adapter->dw_sram_type = tmp & 0x30000;
|
||||
|
||||
ddprintk("%s: dw_sram_type = %x\n", __func__, adapter->dw_sram_type);
|
||||
|
||||
} else {
|
||||
|
||||
adapter->dw_sram_type = 0x10000;
|
||||
|
||||
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)
|
||||
{
|
||||
u8 tmp1, tmp2;
|
||||
|
||||
dprintk("%s: mask = %x, addr = %x\n", __func__, mask, addr);
|
||||
|
||||
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);
|
||||
|
||||
tmp2 = 0;
|
||||
|
||||
mdelay(20);
|
||||
|
||||
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);
|
||||
|
||||
tmp2 = 0;
|
||||
|
||||
mdelay(20);
|
||||
|
||||
sram_read(adapter, addr, &tmp2, 1);
|
||||
|
@ -297,26 +275,24 @@ static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
|
|||
|
||||
if (tmp2 != 0x5a)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 sram_length(struct adapter *adapter)
|
||||
{
|
||||
if (adapter->dw_sram_type == 0x10000)
|
||||
return 32768; // 32K
|
||||
return 32768; /* 32K */
|
||||
if (adapter->dw_sram_type == 0x00000)
|
||||
return 65536; // 64K
|
||||
return 65536; /* 64K */
|
||||
if (adapter->dw_sram_type == 0x20000)
|
||||
return 131072; // 128K
|
||||
|
||||
return 32768; // 32K
|
||||
return 131072; /* 128K */
|
||||
return 32768; /* 32K */
|
||||
}
|
||||
|
||||
/* FlexcopII can work with 32K, 64K or 128K of external SRAM memory.
|
||||
- for 128K there are 4x32K chips at bank 0,1,2,3.
|
||||
- for 64K there are 2x32K chips at bank 1,2.
|
||||
- for 32K there is one 32K chip at bank 0.
|
||||
- for 128K there are 4x32K chips at bank 0,1,2,3.
|
||||
- for 64K there are 2x32K chips at bank 1,2.
|
||||
- for 32K there is one 32K chip at bank 0.
|
||||
|
||||
FlexCop works only with one bank at a time. The bank is selected
|
||||
by bits 28-29 of the 0x700 register.
|
||||
|
@ -324,24 +300,18 @@ static u32 sram_length(struct adapter *adapter)
|
|||
bank 0 covers addresses 0x00000-0x07fff
|
||||
bank 1 covers addresses 0x08000-0x0ffff
|
||||
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)
|
||||
{
|
||||
flexcop_ibi_value r208,r71c_0,vr71c_1;
|
||||
|
||||
flexcop_ibi_value r208, r71c_0, vr71c_1;
|
||||
r208 = fc->read_ibi_reg(fc, ctrl_208);
|
||||
fc->write_ibi_reg(fc, ctrl_208, ibi_zero);
|
||||
|
||||
r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c);
|
||||
|
||||
write_reg_dw(adapter, 0x71c, 1);
|
||||
|
||||
tmp3 = read_reg_dw(adapter, 0x71c);
|
||||
|
||||
dprintk("%s: tmp3 = %x\n", __func__, tmp3);
|
||||
|
||||
write_reg_dw(adapter, 0x71c, tmp2);
|
||||
|
||||
// check for internal SRAM ???
|
||||
|
@ -350,9 +320,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
|
|||
sram_set_size(adapter, 0x10000);
|
||||
sram_init(adapter);
|
||||
write_reg_dw(adapter, 0x208, tmp);
|
||||
|
||||
dprintk("%s: sram size = 32K\n", __func__);
|
||||
|
||||
return 32;
|
||||
}
|
||||
|
||||
|
@ -360,9 +328,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
|
|||
sram_set_size(adapter, 0x20000);
|
||||
sram_init(adapter);
|
||||
write_reg_dw(adapter, 0x208, tmp);
|
||||
|
||||
dprintk("%s: sram size = 128K\n", __func__);
|
||||
|
||||
return 128;
|
||||
}
|
||||
|
||||
|
@ -370,9 +336,7 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
|
|||
sram_set_size(adapter, 0x00000);
|
||||
sram_init(adapter);
|
||||
write_reg_dw(adapter, 0x208, tmp);
|
||||
|
||||
dprintk("%s: sram size = 64K\n", __func__);
|
||||
|
||||
return 64;
|
||||
}
|
||||
|
||||
|
@ -380,18 +344,14 @@ static int flexcop_sram_detect(struct flexcop_device *fc)
|
|||
sram_set_size(adapter, 0x10000);
|
||||
sram_init(adapter);
|
||||
write_reg_dw(adapter, 0x208, tmp);
|
||||
|
||||
dprintk("%s: sram size = 32K\n", __func__);
|
||||
|
||||
return 32;
|
||||
}
|
||||
|
||||
sram_set_size(adapter, 0x10000);
|
||||
sram_init(adapter);
|
||||
write_reg_dw(adapter, 0x208, tmp);
|
||||
|
||||
dprintk("%s: SRAM detection failed. Set to 32K \n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
/*
|
||||
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
*
|
||||
* flexcop-usb.c - covers the USB part.
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
* flexcop-usb.c - covers the USB part
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
|
||||
#define FC_LOG_PREFIX "flexcop_usb"
|
||||
#include "flexcop-usb.h"
|
||||
#include "flexcop-common.h"
|
||||
|
@ -18,42 +15,47 @@
|
|||
/* debug */
|
||||
#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
|
||||
#define dprintk(level,args...) \
|
||||
do { if ((debug & level)) { printk(args); } } while (0)
|
||||
#define debug_dump(b,l,method) {\
|
||||
do { if ((debug & level)) printk(args); } while (0)
|
||||
|
||||
#define debug_dump(b, l, method) do {\
|
||||
int i; \
|
||||
for (i = 0; i < l; i++) method("%02x ", b[i]); \
|
||||
method("\n");\
|
||||
}
|
||||
for (i = 0; i < l; i++) \
|
||||
method("%02x ", b[i]); \
|
||||
method("\n"); \
|
||||
} while (0)
|
||||
|
||||
#define DEBSTATUS ""
|
||||
#else
|
||||
#define dprintk(level,args...)
|
||||
#define debug_dump(b,l,method)
|
||||
#define dprintk(level, args...)
|
||||
#define debug_dump(b, l, method)
|
||||
#define DEBSTATUS " (debugging is not enabled)"
|
||||
#endif
|
||||
|
||||
static int debug;
|
||||
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
|
||||
|
||||
#define deb_info(args...) dprintk(0x01,args)
|
||||
#define deb_ts(args...) dprintk(0x02,args)
|
||||
#define deb_ctrl(args...) dprintk(0x04,args)
|
||||
#define deb_i2c(args...) dprintk(0x08,args)
|
||||
#define deb_v8(args...) dprintk(0x10,args)
|
||||
#define deb_info(args...) dprintk(0x01, args)
|
||||
#define deb_ts(args...) dprintk(0x02, args)
|
||||
#define deb_ctrl(args...) dprintk(0x04, args)
|
||||
#define deb_i2c(args...) dprintk(0x08, args)
|
||||
#define deb_v8(args...) dprintk(0x10, args)
|
||||
|
||||
/* 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.
|
||||
* 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
|
||||
* IBI ADDRESS FORMAT: RHHH BLLL
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70))
|
||||
#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
|
||||
#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) \
|
||||
(((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70))
|
||||
#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) \
|
||||
(((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
|
||||
|
||||
/*
|
||||
* DKT 020228
|
||||
|
@ -69,12 +71,13 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI,
|
|||
struct flexcop_usb *fc_usb = fc->bus_specific;
|
||||
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 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,
|
||||
read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
|
||||
request,
|
||||
request_type, /* 0xc0 read or 0x40 write*/
|
||||
request_type, /* 0xc0 read or 0x40 write */
|
||||
wAddress,
|
||||
0,
|
||||
val,
|
||||
|
@ -82,55 +85,49 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI,
|
|||
B2C2_WAIT_FOR_OPERATION_RDW * HZ);
|
||||
|
||||
if (len != sizeof(u32)) {
|
||||
err("error while %s dword from %d (%d).",read ? "reading" : "writing",
|
||||
wAddress,wRegOffsPCI);
|
||||
err("error while %s dword from %d (%d).", read ? "reading" :
|
||||
"writing", wAddress, wRegOffsPCI);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* DKT 010817 - add support for V8 memory read/write and flash update
|
||||
*/
|
||||
static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
|
||||
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;
|
||||
u16 wIndex;
|
||||
int nWaitTime,pipe,len;
|
||||
|
||||
int nWaitTime, pipe, len;
|
||||
wIndex = page << 8;
|
||||
|
||||
switch (req) {
|
||||
case B2C2_USB_READ_V8_MEM:
|
||||
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
|
||||
request_type |= USB_DIR_IN;
|
||||
// dwRequestType = (u8) RTYPE_READ_V8_MEMORY;
|
||||
pipe = B2C2_USB_CTRL_PIPE_IN;
|
||||
case B2C2_USB_READ_V8_MEM:
|
||||
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
|
||||
request_type |= USB_DIR_IN;
|
||||
pipe = B2C2_USB_CTRL_PIPE_IN;
|
||||
break;
|
||||
case B2C2_USB_WRITE_V8_MEM:
|
||||
wIndex |= pbBuffer[0];
|
||||
request_type |= USB_DIR_OUT;
|
||||
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
|
||||
// dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY;
|
||||
pipe = B2C2_USB_CTRL_PIPE_OUT;
|
||||
case B2C2_USB_WRITE_V8_MEM:
|
||||
wIndex |= pbBuffer[0];
|
||||
request_type |= USB_DIR_OUT;
|
||||
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
|
||||
pipe = B2C2_USB_CTRL_PIPE_OUT;
|
||||
break;
|
||||
case B2C2_USB_FLASH_BLOCK:
|
||||
request_type |= USB_DIR_OUT;
|
||||
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
|
||||
// dwRequestType = (u8) RTYPE_WRITE_V8_FLASH;
|
||||
pipe = B2C2_USB_CTRL_PIPE_OUT;
|
||||
case B2C2_USB_FLASH_BLOCK:
|
||||
request_type |= USB_DIR_OUT;
|
||||
nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
|
||||
pipe = B2C2_USB_CTRL_PIPE_OUT;
|
||||
break;
|
||||
default:
|
||||
deb_info("unsupported request for v8_mem_req %x.\n",req);
|
||||
default:
|
||||
deb_info("unsupported request for v8_mem_req %x.\n", req);
|
||||
return -EINVAL;
|
||||
}
|
||||
deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n",request_type,req,
|
||||
wAddress,wIndex,buflen);
|
||||
deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,
|
||||
wAddress, wIndex, buflen);
|
||||
|
||||
len = usb_control_msg(fc_usb->udev,pipe,
|
||||
len = usb_control_msg(fc_usb->udev, pipe,
|
||||
req,
|
||||
request_type,
|
||||
wAddress,
|
||||
|
@ -139,39 +136,53 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
|
|||
buflen,
|
||||
nWaitTime * HZ);
|
||||
|
||||
debug_dump(pbBuffer,len,deb_v8);
|
||||
|
||||
debug_dump(pbBuffer, len, deb_v8);
|
||||
return len == buflen ? 0 : -EIO;
|
||||
}
|
||||
|
||||
#define bytes_left_to_read_on_page(paddr,buflen) \
|
||||
((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \
|
||||
? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)))
|
||||
((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \
|
||||
? 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,
|
||||
flexcop_usb_mem_page_t page_start, u32 addr, int extended, u8 *buf, u32 len)
|
||||
static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,
|
||||
flexcop_usb_request_t req, flexcop_usb_mem_page_t page_start,
|
||||
u32 addr, int extended, u8 *buf, u32 len)
|
||||
{
|
||||
int i,ret = 0;
|
||||
u16 wMax;
|
||||
u32 pagechunk = 0;
|
||||
|
||||
switch(req) {
|
||||
case B2C2_USB_READ_V8_MEM: wMax = USB_MEM_READ_MAX; break;
|
||||
case B2C2_USB_WRITE_V8_MEM: wMax = USB_MEM_WRITE_MAX; break;
|
||||
case B2C2_USB_FLASH_BLOCK: wMax = USB_FLASH_MAX; break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
case B2C2_USB_READ_V8_MEM:
|
||||
wMax = USB_MEM_READ_MAX;
|
||||
break;
|
||||
case B2C2_USB_WRITE_V8_MEM:
|
||||
wMax = USB_MEM_WRITE_MAX;
|
||||
break;
|
||||
case B2C2_USB_FLASH_BLOCK:
|
||||
wMax = USB_FLASH_MAX;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < len;) {
|
||||
pagechunk = wMax < bytes_left_to_read_on_page(addr,len) ? wMax : bytes_left_to_read_on_page(addr,len);
|
||||
deb_info("%x\n",(addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended));
|
||||
if ((ret = flexcop_usb_v8_memory_req(fc_usb,req,
|
||||
page_start + (addr / V8_MEMORY_PAGE_SIZE), /* actual page */
|
||||
(addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended),
|
||||
&buf[i],pagechunk)) < 0)
|
||||
return ret;
|
||||
pagechunk =
|
||||
wMax < bytes_left_to_read_on_page(addr, len) ?
|
||||
wMax :
|
||||
bytes_left_to_read_on_page(addr, len);
|
||||
deb_info("%x\n",
|
||||
(addr & V8_MEMORY_PAGE_MASK) |
|
||||
(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;
|
||||
len -= pagechunk;
|
||||
}
|
||||
|
@ -180,8 +191,9 @@ 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)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -191,11 +203,8 @@ static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
|
|||
{
|
||||
u16 wValue;
|
||||
u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
|
||||
// u8 dwRequestType = (u8) RTYPE_GENERIC,
|
||||
int nWaitTime = 2,
|
||||
pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN,
|
||||
len;
|
||||
|
||||
pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len;
|
||||
wValue = (func << 8) | extra;
|
||||
|
||||
len = usb_control_msg(fc_usb->udev,pipe,
|
||||
|
@ -218,36 +227,35 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
|
|||
struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
|
||||
u16 wValue, wIndex;
|
||||
int nWaitTime,pipe,len;
|
||||
// u8 dwRequestType;
|
||||
u8 request_type = USB_TYPE_VENDOR;
|
||||
|
||||
switch (func) {
|
||||
case USB_FUNC_I2C_WRITE:
|
||||
case USB_FUNC_I2C_MULTIWRITE:
|
||||
case USB_FUNC_I2C_REPEATWRITE:
|
||||
case USB_FUNC_I2C_WRITE:
|
||||
case USB_FUNC_I2C_MULTIWRITE:
|
||||
case USB_FUNC_I2C_REPEATWRITE:
|
||||
/* DKT 020208 - add this to support special case of DiSEqC */
|
||||
case USB_FUNC_I2C_CHECKWRITE:
|
||||
pipe = B2C2_USB_CTRL_PIPE_OUT;
|
||||
nWaitTime = 2;
|
||||
// dwRequestType = (u8) RTYPE_GENERIC;
|
||||
request_type |= USB_DIR_OUT;
|
||||
case USB_FUNC_I2C_CHECKWRITE:
|
||||
pipe = B2C2_USB_CTRL_PIPE_OUT;
|
||||
nWaitTime = 2;
|
||||
request_type |= USB_DIR_OUT;
|
||||
break;
|
||||
case USB_FUNC_I2C_READ:
|
||||
case USB_FUNC_I2C_REPEATREAD:
|
||||
pipe = B2C2_USB_CTRL_PIPE_IN;
|
||||
nWaitTime = 2;
|
||||
// dwRequestType = (u8) RTYPE_GENERIC;
|
||||
request_type |= USB_DIR_IN;
|
||||
case USB_FUNC_I2C_READ:
|
||||
case USB_FUNC_I2C_REPEATREAD:
|
||||
pipe = B2C2_USB_CTRL_PIPE_IN;
|
||||
nWaitTime = 2;
|
||||
request_type |= USB_DIR_IN;
|
||||
break;
|
||||
default:
|
||||
deb_info("unsupported function for i2c_req %x\n",func);
|
||||
return -EINVAL;
|
||||
default:
|
||||
deb_info("unsupported function for i2c_req %x\n", func);
|
||||
return -EINVAL;
|
||||
}
|
||||
wValue = (func << 8) | (i2c->port << 4);
|
||||
wIndex = (chipaddr << 8 ) | addr;
|
||||
|
||||
deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req,
|
||||
wValue & 0xff, wValue >> 8, wIndex & 0xff, wIndex >> 8);
|
||||
deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",
|
||||
func, request_type, req,
|
||||
wValue & 0xff, wValue >> 8,
|
||||
wIndex & 0xff, wIndex >> 8);
|
||||
|
||||
len = usb_control_msg(fc_usb->udev,pipe,
|
||||
req,
|
||||
|
@ -257,44 +265,49 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
|
|||
buf,
|
||||
buflen,
|
||||
nWaitTime * HZ);
|
||||
|
||||
return len == buflen ? 0 : -EREMOTEIO;
|
||||
}
|
||||
|
||||
/* actual bus specific access functions, 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)
|
||||
/* actual bus specific access functions,
|
||||
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;
|
||||
val.raw = 0;
|
||||
flexcop_usb_readwrite_dw(fc,reg, &val.raw, 1);
|
||||
flexcop_usb_readwrite_dw(fc, reg, &val.raw, 1);
|
||||
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);
|
||||
}
|
||||
|
||||
static int flexcop_usb_i2c_request(struct flexcop_i2c_adapter *i2c,
|
||||
flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
|
||||
flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
|
||||
{
|
||||
if (op == FC_READ)
|
||||
return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
|
||||
USB_FUNC_I2C_READ, chipaddr, addr, buf, len);
|
||||
USB_FUNC_I2C_READ, chipaddr, addr, buf, len);
|
||||
else
|
||||
return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
|
||||
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;
|
||||
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) {
|
||||
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;
|
||||
b = fc_usb->tmp_buffer;
|
||||
l = fc_usb->tmp_buffer_length;
|
||||
|
@ -304,23 +317,26 @@ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, in
|
|||
}
|
||||
|
||||
while (l >= 190) {
|
||||
if (*b == 0xff)
|
||||
if (*b == 0xff) {
|
||||
switch (*(b+1) & 0x03) {
|
||||
case 0x01: /* media packet */
|
||||
if ( *(b+2) == 0x47 )
|
||||
flexcop_pass_dmx_packets(fc_usb->fc_dev, b+2, 1);
|
||||
else
|
||||
deb_ts("not ts packet %02x %02x %02x %02x \n", *(b+2), *(b+3), *(b+4), *(b+5) );
|
||||
|
||||
b += 190;
|
||||
l -= 190;
|
||||
case 0x01: /* media packet */
|
||||
if (*(b+2) == 0x47)
|
||||
flexcop_pass_dmx_packets(
|
||||
fc_usb->fc_dev, b+2, 1);
|
||||
else
|
||||
deb_ts(
|
||||
"not ts packet %02x %02x %02x %02x \n",
|
||||
*(b+2), *(b+3),
|
||||
*(b+4), *(b+5));
|
||||
b += 190;
|
||||
l -= 190;
|
||||
break;
|
||||
default:
|
||||
deb_ts("wrong packet type\n");
|
||||
l = 0;
|
||||
default:
|
||||
deb_ts("wrong packet type\n");
|
||||
l = 0;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
deb_ts("wrong header\n");
|
||||
l = 0;
|
||||
}
|
||||
|
@ -337,23 +353,26 @@ static void flexcop_usb_urb_complete(struct urb *urb)
|
|||
int i;
|
||||
|
||||
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++) {
|
||||
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
|
||||
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,
|
||||
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].status = 0;
|
||||
urb->iso_frame_desc[i].actual_length = 0;
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
u16 frame_size = le16_to_cpu(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;
|
||||
u16 frame_size = le16_to_cpu(
|
||||
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;
|
||||
|
||||
deb_ts("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n",
|
||||
B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size,bufsize);
|
||||
deb_ts("creating %d iso-urbs with %d frames "
|
||||
"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)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(fc_usb->iso_buffer, 0, bufsize);
|
||||
fc_usb->buffer_size = bufsize;
|
||||
|
||||
/* creating iso urbs */
|
||||
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))) {
|
||||
for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
|
||||
fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,
|
||||
GFP_ATOMIC);
|
||||
if (fc_usb->iso_urb[i] == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto urb_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialising and submitting iso urbs */
|
||||
for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
|
||||
int frame_offset = 0;
|
||||
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->context = fc_usb;
|
||||
|
@ -416,26 +447,26 @@ static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
|
|||
|
||||
buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO;
|
||||
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].length = frame_size;
|
||||
frame_offset += frame_size;
|
||||
}
|
||||
|
||||
if ((ret = usb_submit_urb(fc_usb->iso_urb[i],GFP_ATOMIC))) {
|
||||
err("submitting urb %d failed with %d.",i,ret);
|
||||
err("submitting urb %d failed with %d.", i, ret);
|
||||
goto urb_error;
|
||||
}
|
||||
deb_ts("submitted urb no. %d.\n",i);
|
||||
}
|
||||
|
||||
/* SRAM */
|
||||
|
||||
flexcop_sram_set_dest(fc_usb->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET |
|
||||
FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_WAN_USB);
|
||||
flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS);
|
||||
flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1);
|
||||
|
||||
/* SRAM */
|
||||
flexcop_sram_set_dest(fc_usb->fc_dev, FC_SRAM_DEST_MEDIA |
|
||||
FC_SRAM_DEST_NET | FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI,
|
||||
FC_SRAM_DEST_TARGET_WAN_USB);
|
||||
flexcop_wan_set_speed(fc_usb->fc_dev, FC_WAN_SPEED_8MBITS);
|
||||
flexcop_sram_ctrl(fc_usb->fc_dev, 1, 1, 1);
|
||||
return 0;
|
||||
|
||||
urb_error:
|
||||
|
@ -448,20 +479,20 @@ static int flexcop_usb_init(struct flexcop_usb *fc_usb)
|
|||
/* use the alternate setting with the larges buffer */
|
||||
usb_set_interface(fc_usb->udev,0,1);
|
||||
switch (fc_usb->udev->speed) {
|
||||
case USB_SPEED_LOW:
|
||||
err("cannot handle USB speed because it is to sLOW.");
|
||||
return -ENODEV;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
info("running at FULL speed.");
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
info("running at HIGH speed.");
|
||||
break;
|
||||
case USB_SPEED_UNKNOWN: /* fall through */
|
||||
default:
|
||||
err("cannot handle USB speed because it is unkown.");
|
||||
return -ENODEV;
|
||||
case USB_SPEED_LOW:
|
||||
err("cannot handle USB speed because it is too slow.");
|
||||
return -ENODEV;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
info("running at FULL speed.");
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
info("running at HIGH speed.");
|
||||
break;
|
||||
case USB_SPEED_UNKNOWN: /* fall through */
|
||||
default:
|
||||
err("cannot handle USB speed because it is unknown.");
|
||||
return -ENODEV;
|
||||
}
|
||||
usb_set_intfdata(fc_usb->uintf, fc_usb);
|
||||
return 0;
|
||||
|
@ -485,7 +516,7 @@ static int flexcop_usb_probe(struct usb_interface *intf,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* general flexcop init */
|
||||
/* general flexcop init */
|
||||
fc_usb = fc->bus_specific;
|
||||
fc_usb->fc_dev = fc;
|
||||
|
||||
|
@ -502,21 +533,21 @@ static int flexcop_usb_probe(struct usb_interface *intf,
|
|||
fc->dev = &udev->dev;
|
||||
fc->owner = THIS_MODULE;
|
||||
|
||||
/* bus specific part */
|
||||
/* bus specific part */
|
||||
fc_usb->udev = udev;
|
||||
fc_usb->uintf = intf;
|
||||
if ((ret = flexcop_usb_init(fc_usb)) != 0)
|
||||
goto err_kfree;
|
||||
|
||||
/* init flexcop */
|
||||
/* init flexcop */
|
||||
if ((ret = flexcop_device_initialize(fc)) != 0)
|
||||
goto err_usb_exit;
|
||||
|
||||
/* xfer init */
|
||||
/* xfer init */
|
||||
if ((ret = flexcop_usb_transfer_init(fc_usb)) != 0)
|
||||
goto err_fc_exit;
|
||||
|
||||
info("%s successfully initialized and connected.",DRIVER_NAME);
|
||||
info("%s successfully initialized and connected.", DRIVER_NAME);
|
||||
return 0;
|
||||
|
||||
err_fc_exit:
|
||||
|
@ -535,12 +566,12 @@ static void flexcop_usb_disconnect(struct usb_interface *intf)
|
|||
flexcop_device_exit(fc_usb->fc_dev);
|
||||
flexcop_usb_exit(fc_usb);
|
||||
flexcop_device_kfree(fc_usb->fc_dev);
|
||||
info("%s successfully deinitialized and disconnected.",DRIVER_NAME);
|
||||
info("%s successfully deinitialized and disconnected.", DRIVER_NAME);
|
||||
}
|
||||
|
||||
static struct usb_device_id flexcop_usb_table [] = {
|
||||
{ USB_DEVICE(0x0af7, 0x0101) },
|
||||
{ }
|
||||
{ USB_DEVICE(0x0af7, 0x0101) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE (usb, flexcop_usb_table);
|
||||
|
||||
|
@ -557,10 +588,9 @@ static int __init flexcop_usb_module_init(void)
|
|||
{
|
||||
int result;
|
||||
if ((result = usb_register(&flexcop_usb_driver))) {
|
||||
err("usb_register failed. (%d)",result);
|
||||
err("usb_register failed. (%d)", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
/*
|
||||
* 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__
|
||||
#define __FLEXCOP_USB_H_INCLUDED__
|
||||
|
||||
#include <linux/usb.h>
|
||||
|
||||
/* transfer parameters */
|
||||
#define B2C2_USB_FRAMES_PER_ISO 4
|
||||
#define B2C2_USB_NUM_ISO_URB 4
|
||||
#define B2C2_USB_FRAMES_PER_ISO 4
|
||||
#define B2C2_USB_NUM_ISO_URB 4
|
||||
|
||||
#define B2C2_USB_CTRL_PIPE_IN usb_rcvctrlpipe(fc_usb->udev,0)
|
||||
#define B2C2_USB_CTRL_PIPE_OUT usb_sndctrlpipe(fc_usb->udev,0)
|
||||
#define B2C2_USB_DATA_PIPE usb_rcvisocpipe(fc_usb->udev,0x81)
|
||||
#define B2C2_USB_CTRL_PIPE_IN usb_rcvctrlpipe(fc_usb->udev, 0)
|
||||
#define B2C2_USB_CTRL_PIPE_OUT usb_sndctrlpipe(fc_usb->udev, 0)
|
||||
#define B2C2_USB_DATA_PIPE usb_rcvisocpipe(fc_usb->udev, 0x81)
|
||||
|
||||
struct flexcop_usb {
|
||||
struct usb_device *udev;
|
||||
|
@ -18,8 +23,8 @@ struct flexcop_usb {
|
|||
u8 *iso_buffer;
|
||||
int buffer_size;
|
||||
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;
|
||||
|
||||
u8 tmp_buffer[1023+190];
|
||||
|
@ -30,14 +35,6 @@ struct flexcop_usb {
|
|||
/* request types TODO What is its use?*/
|
||||
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;
|
||||
#endif
|
||||
|
||||
|
@ -47,7 +44,6 @@ typedef enum {
|
|||
B2C2_USB_READ_V8_MEM = 0x05,
|
||||
B2C2_USB_READ_REG = 0x08,
|
||||
B2C2_USB_WRITE_REG = 0x0A,
|
||||
/* B2C2_USB_WRITEREGLO = 0x0A, */
|
||||
B2C2_USB_WRITEREGHI = 0x0B,
|
||||
B2C2_USB_FLASH_BLOCK = 0x10,
|
||||
B2C2_USB_I2C_REQUEST = 0x11,
|
||||
|
@ -62,15 +58,13 @@ typedef enum {
|
|||
USB_FUNC_I2C_REPEATWRITE = 0x04,
|
||||
USB_FUNC_GET_DESCRIPTOR = 0x05,
|
||||
USB_FUNC_I2C_REPEATREAD = 0x06,
|
||||
/* DKT 020208 - add this to support special case of DiSEqC */
|
||||
/* DKT 020208 - add this to support special case of DiSEqC */
|
||||
USB_FUNC_I2C_CHECKWRITE = 0x07,
|
||||
USB_FUNC_I2C_CHECKRESULT = 0x08,
|
||||
} flexcop_usb_i2c_function_t;
|
||||
|
||||
/*
|
||||
* function definition for UTILITY request 0x12
|
||||
* DKT 020304 - new utility function
|
||||
*/
|
||||
/* function definition for UTILITY request 0x12
|
||||
* DKT 020304 - new utility function */
|
||||
typedef enum {
|
||||
UTILITY_SET_FILTER = 0x01,
|
||||
UTILITY_DATA_ENABLE = 0x02,
|
||||
|
@ -84,7 +78,7 @@ typedef enum {
|
|||
UTILITY_DATA_RESET = 0x0A,
|
||||
UTILITY_GET_DATA_STATUS = 0x10,
|
||||
UTILITY_GET_V8_REG = 0x11,
|
||||
/* DKT 020326 - add function for v1.14 */
|
||||
/* DKT 020326 - add function for v1.14 */
|
||||
UTILITY_SRAM_WRITE = 0x12,
|
||||
UTILITY_SRAM_READ = 0x13,
|
||||
UTILITY_SRAM_TESTFILL = 0x14,
|
||||
|
@ -92,13 +86,13 @@ typedef enum {
|
|||
UTILITY_SRAM_TESTVERIFY = 0x16,
|
||||
} flexcop_usb_utility_function_t;
|
||||
|
||||
#define B2C2_WAIT_FOR_OPERATION_RW 1*HZ /* 1 s */
|
||||
#define B2C2_WAIT_FOR_OPERATION_RDW 3*HZ /* 3 s */
|
||||
#define B2C2_WAIT_FOR_OPERATION_WDW 1*HZ /* 1 s */
|
||||
#define B2C2_WAIT_FOR_OPERATION_RW (1*HZ)
|
||||
#define B2C2_WAIT_FOR_OPERATION_RDW (3*HZ)
|
||||
#define B2C2_WAIT_FOR_OPERATION_WDW (1*HZ)
|
||||
|
||||
#define B2C2_WAIT_FOR_OPERATION_V8READ 3*HZ /* 3 s */
|
||||
#define B2C2_WAIT_FOR_OPERATION_V8WRITE 3*HZ /* 3 s */
|
||||
#define B2C2_WAIT_FOR_OPERATION_V8FLASH 3*HZ /* 3 s */
|
||||
#define B2C2_WAIT_FOR_OPERATION_V8READ (3*HZ)
|
||||
#define B2C2_WAIT_FOR_OPERATION_V8WRITE (3*HZ)
|
||||
#define B2C2_WAIT_FOR_OPERATION_V8FLASH (3*HZ)
|
||||
|
||||
typedef enum {
|
||||
V8_MEMORY_PAGE_DVB_CI = 0x20,
|
||||
|
@ -107,13 +101,11 @@ typedef enum {
|
|||
V8_MEMORY_PAGE_FLASH = 0x80
|
||||
} flexcop_usb_mem_page_t;
|
||||
|
||||
#define V8_MEMORY_EXTENDED (1 << 15)
|
||||
|
||||
#define USB_MEM_READ_MAX 32
|
||||
#define USB_MEM_WRITE_MAX 1
|
||||
#define USB_FLASH_MAX 8
|
||||
|
||||
#define V8_MEMORY_PAGE_SIZE 0x8000 // 32K
|
||||
#define V8_MEMORY_PAGE_MASK 0x7FFF
|
||||
#define V8_MEMORY_EXTENDED (1 << 15)
|
||||
#define USB_MEM_READ_MAX 32
|
||||
#define USB_MEM_WRITE_MAX 1
|
||||
#define USB_FLASH_MAX 8
|
||||
#define V8_MEMORY_PAGE_SIZE 0x8000 /* 32K */
|
||||
#define V8_MEMORY_PAGE_MASK 0x7FFF
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
/*
|
||||
* flexcop.c - driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
*
|
||||
* Copyright (C) 2004-5 Patrick Boettcher <patrick.boettcher@desy.de>
|
||||
*
|
||||
* based on the skystar2-driver
|
||||
* Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
|
||||
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
* flexcop.c - main module part
|
||||
* Copyright (C) 2004-9 Patrick Boettcher <patrick.boettcher@desy.de>
|
||||
* based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
|
||||
*
|
||||
* Acknowledgements:
|
||||
* John Jurrius from BBTI, Inc. for extensive support with
|
||||
* code examples and data books
|
||||
*
|
||||
* Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting)
|
||||
* John Jurrius from BBTI, Inc. for extensive support
|
||||
* with code examples and data books
|
||||
* Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting)
|
||||
*
|
||||
* Contributions to the skystar2-driver have been done by
|
||||
* Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes)
|
||||
* Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code)
|
||||
* Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac filtering)
|
||||
*
|
||||
* Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes)
|
||||
* Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code)
|
||||
* 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
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
|
@ -46,7 +44,10 @@
|
|||
|
||||
int b2c2_flexcop_debug;
|
||||
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
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
@ -57,37 +58,36 @@ flexcop_ibi_value ibi_zero;
|
|||
static int flexcop_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
|
||||
{
|
||||
struct flexcop_device *fc = dvbdmxfeed->demux->priv;
|
||||
return flexcop_pid_feed_control(fc,dvbdmxfeed,1);
|
||||
return flexcop_pid_feed_control(fc, dvbdmxfeed, 1);
|
||||
}
|
||||
|
||||
static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
|
||||
{
|
||||
struct flexcop_device *fc = dvbdmxfeed->demux->priv;
|
||||
return flexcop_pid_feed_control(fc,dvbdmxfeed,0);
|
||||
return flexcop_pid_feed_control(fc, dvbdmxfeed, 0);
|
||||
}
|
||||
|
||||
static int flexcop_dvb_init(struct flexcop_device *fc)
|
||||
{
|
||||
int ret = dvb_register_adapter(&fc->dvb_adapter,
|
||||
"FlexCop Digital TV device", fc->owner,
|
||||
fc->dev, adapter_nr);
|
||||
"FlexCop Digital TV device", fc->owner,
|
||||
fc->dev, adapter_nr);
|
||||
if (ret < 0) {
|
||||
err("error registering DVB adapter");
|
||||
return ret;
|
||||
}
|
||||
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.filternum = fc->demux.feednum = FC_MAX_FEED;
|
||||
|
||||
fc->demux.start_feed = flexcop_dvb_start_feed;
|
||||
fc->demux.stop_feed = flexcop_dvb_stop_feed;
|
||||
fc->demux.write_to_decoder = NULL;
|
||||
|
||||
if ((ret = dvb_dmx_init(&fc->demux)) < 0) {
|
||||
err("dvb_dmx failed: error %d",ret);
|
||||
err("dvb_dmx failed: error %d", ret);
|
||||
goto err_dmx;
|
||||
}
|
||||
|
||||
|
@ -97,23 +97,23 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
|
|||
fc->dmxdev.demux = &fc->demux.dmx;
|
||||
fc->dmxdev.capabilities = 0;
|
||||
if ((ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter)) < 0) {
|
||||
err("dvb_dmxdev_init failed: error %d",ret);
|
||||
err("dvb_dmxdev_init failed: error %d", ret);
|
||||
goto err_dmx_dev;
|
||||
}
|
||||
|
||||
if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) {
|
||||
err("adding hw_frontend to dmx failed: error %d",ret);
|
||||
err("adding hw_frontend to dmx failed: error %d", ret);
|
||||
goto err_dmx_add_hw_frontend;
|
||||
}
|
||||
|
||||
fc->mem_frontend.source = DMX_MEMORY_FE;
|
||||
if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend)) < 0) {
|
||||
err("adding mem_frontend to dmx failed: error %d",ret);
|
||||
err("adding mem_frontend to dmx failed: error %d", ret);
|
||||
goto err_dmx_add_mem_frontend;
|
||||
}
|
||||
|
||||
if ((ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) {
|
||||
err("connect frontend failed: error %d",ret);
|
||||
err("connect frontend failed: error %d", ret);
|
||||
goto err_connect_frontend;
|
||||
}
|
||||
|
||||
|
@ -123,9 +123,9 @@ static int flexcop_dvb_init(struct flexcop_device *fc)
|
|||
return 0;
|
||||
|
||||
err_connect_frontend:
|
||||
fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
|
||||
fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->mem_frontend);
|
||||
err_dmx_add_mem_frontend:
|
||||
fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend);
|
||||
fc->demux.dmx.remove_frontend(&fc->demux.dmx, &fc->hw_frontend);
|
||||
err_dmx_add_hw_frontend:
|
||||
dvb_dmxdev_release(&fc->dmxdev);
|
||||
err_dmx_dev:
|
||||
|
@ -141,12 +141,13 @@ static void flexcop_dvb_exit(struct flexcop_device *fc)
|
|||
dvb_net_release(&fc->dvbnet);
|
||||
|
||||
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->hw_frontend);
|
||||
fc->demux.dmx.remove_frontend(&fc->demux.dmx,
|
||||
&fc->mem_frontend);
|
||||
fc->demux.dmx.remove_frontend(&fc->demux.dmx,
|
||||
&fc->hw_frontend);
|
||||
dvb_dmxdev_release(&fc->dmxdev);
|
||||
dvb_dmx_release(&fc->demux);
|
||||
dvb_unregister_adapter(&fc->dvb_adapter);
|
||||
|
||||
deb_info("deinitialized dvb stuff\n");
|
||||
}
|
||||
fc->init_state &= ~FC_STATE_DVB_INIT;
|
||||
|
@ -168,9 +169,9 @@ EXPORT_SYMBOL(flexcop_pass_dmx_packets);
|
|||
|
||||
static void flexcop_reset(struct flexcop_device *fc)
|
||||
{
|
||||
flexcop_ibi_value v210,v204;
|
||||
flexcop_ibi_value v210, v204;
|
||||
|
||||
/* reset the flexcop itself */
|
||||
/* reset the flexcop itself */
|
||||
fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
|
||||
|
||||
v210.raw = 0;
|
||||
|
@ -183,13 +184,11 @@ static void flexcop_reset(struct flexcop_device *fc)
|
|||
v210.sw_reset_210.reset_block_600 = 1;
|
||||
v210.sw_reset_210.reset_block_700 = 1;
|
||||
v210.sw_reset_210.Block_reset_enable = 0xb2;
|
||||
|
||||
v210.sw_reset_210.Special_controls = 0xc259;
|
||||
|
||||
fc->write_ibi_reg(fc,sw_reset_210,v210);
|
||||
msleep(1);
|
||||
|
||||
/* reset the periphical devices */
|
||||
/* reset the periphical devices */
|
||||
|
||||
v204 = fc->read_ibi_reg(fc,misc_204);
|
||||
v204.misc_204.Per_reset_sig = 0;
|
||||
|
@ -201,25 +200,24 @@ static void flexcop_reset(struct flexcop_device *fc)
|
|||
|
||||
void flexcop_reset_block_300(struct flexcop_device *fc)
|
||||
{
|
||||
flexcop_ibi_value v208_save = fc->read_ibi_reg(fc,ctrl_208),
|
||||
v210 = fc->read_ibi_reg(fc,sw_reset_210);
|
||||
|
||||
deb_rdump("208: %08x, 210: %08x\n",v208_save.raw,v210.raw);
|
||||
flexcop_ibi_value v208_save = fc->read_ibi_reg(fc, ctrl_208),
|
||||
v210 = fc->read_ibi_reg(fc, sw_reset_210);
|
||||
|
||||
deb_rdump("208: %08x, 210: %08x\n", v208_save.raw, v210.raw);
|
||||
fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
|
||||
|
||||
v210.sw_reset_210.reset_block_300 = 1;
|
||||
v210.sw_reset_210.Block_reset_enable = 0xb2;
|
||||
|
||||
fc->write_ibi_reg(fc,sw_reset_210,v210);
|
||||
udelay(1000);
|
||||
fc->write_ibi_reg(fc,ctrl_208,v208_save);
|
||||
}
|
||||
|
||||
struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
|
||||
{
|
||||
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) {
|
||||
err("no memory");
|
||||
return NULL;
|
||||
|
@ -254,7 +252,6 @@ int flexcop_device_initialize(struct flexcop_device *fc)
|
|||
flexcop_determine_revision(fc);
|
||||
flexcop_sram_init(fc);
|
||||
flexcop_hw_filter_init(fc);
|
||||
|
||||
flexcop_smc_ctrl(fc, 0);
|
||||
|
||||
if ((ret = flexcop_dvb_init(fc)))
|
||||
|
@ -279,7 +276,6 @@ int flexcop_device_initialize(struct flexcop_device *fc)
|
|||
goto error;
|
||||
|
||||
flexcop_device_name(fc,"initialization of","complete");
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/*
|
||||
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
*
|
||||
* flexcop.h - private header file for all flexcop-chip-source files.
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
|
||||
* flexcop.h - private header file for all flexcop-chip-source files
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
#ifndef __FLEXCOP_H__
|
||||
#define __FLEXCOP_H___
|
||||
|
@ -21,11 +19,11 @@ extern int b2c2_flexcop_debug;
|
|||
#define dprintk(level,args...)
|
||||
#endif
|
||||
|
||||
#define deb_info(args...) dprintk(0x01,args)
|
||||
#define deb_tuner(args...) dprintk(0x02,args)
|
||||
#define deb_i2c(args...) dprintk(0x04,args)
|
||||
#define deb_ts(args...) dprintk(0x08,args)
|
||||
#define deb_sram(args...) dprintk(0x10,args)
|
||||
#define deb_rdump(args...) dprintk(0x20,args)
|
||||
#define deb_info(args...) dprintk(0x01, args)
|
||||
#define deb_tuner(args...) dprintk(0x02, args)
|
||||
#define deb_i2c(args...) dprintk(0x04, args)
|
||||
#define deb_ts(args...) dprintk(0x08, args)
|
||||
#define deb_sram(args...) dprintk(0x10, args)
|
||||
#define deb_rdump(args...) dprintk(0x20, args)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
|
||||
/* This file is automatically generated, do not edit things here. */
|
||||
#ifndef __FLEXCOP_IBI_VALUE_INCLUDED__
|
||||
#define __FLEXCOP_IBI_VALUE_INCLUDED__
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* see flexcop.c for copyright information.
|
||||
* see flexcop.c for copyright information
|
||||
*/
|
||||
|
||||
/* This file is automatically generated, do not edit things here. */
|
||||
#ifndef __FLEXCOP_IBI_VALUE_INCLUDED__
|
||||
#define __FLEXCOP_IBI_VALUE_INCLUDED__
|
||||
|
|
|
@ -8,7 +8,7 @@ config DVB_BT8XX
|
|||
select DVB_OR51211 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LGDT330X 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
|
||||
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
|
||||
the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
|
||||
|
|
|
@ -552,16 +552,19 @@ free_mem_and_exit:
|
|||
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 dst_state* state = (struct dst_state*) dvbdev->priv;
|
||||
struct dvb_device *dvbdev;
|
||||
struct dst_state *state;
|
||||
struct ca_slot_info *p_ca_slot_info;
|
||||
struct ca_caps *p_ca_caps;
|
||||
struct ca_msg *p_ca_message;
|
||||
void __user *arg = (void __user *)ioctl_arg;
|
||||
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_slot_info = kmalloc(sizeof (struct ca_slot_info), 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_caps);
|
||||
|
||||
unlock_kernel();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -682,9 +686,9 @@ static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations dst_ca_fops = {
|
||||
static const struct file_operations dst_ca_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = dst_ca_ioctl,
|
||||
.unlocked_ioctl = dst_ca_ioctl,
|
||||
.open = dst_ca_open,
|
||||
.release = dst_ca_release,
|
||||
.read = dst_ca_read,
|
||||
|
|
|
@ -814,7 +814,7 @@ static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
|
|||
|
||||
mutex_init(&card->lock);
|
||||
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;
|
||||
|
||||
switch(sub->core->type) {
|
||||
|
|
|
@ -8,6 +8,7 @@ config DVB_DM1105
|
|||
select DVB_STB6000 if !DVB_FE_CUSTOMISE
|
||||
select DVB_CX24116 if !DVB_FE_CUSTOMISE
|
||||
select DVB_SI21XX if !DVB_FE_CUSTOMISE
|
||||
select VIDEO_IR
|
||||
help
|
||||
Support for cards based on the SDMC DM1105 PCI chip like
|
||||
DvbWorld 2002
|
||||
|
|
|
@ -156,46 +156,12 @@ MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
|
|||
|
||||
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 */
|
||||
struct infrared {
|
||||
u16 key_map[128];
|
||||
struct input_dev *input_dev;
|
||||
struct ir_input_state ir;
|
||||
char input_phys[32];
|
||||
struct tasklet_struct ir_tasklet;
|
||||
struct work_struct work;
|
||||
u32 ir_command;
|
||||
};
|
||||
|
||||
|
@ -220,10 +186,14 @@ struct dm1105dvb {
|
|||
/* i2c */
|
||||
struct i2c_adapter i2c_adap;
|
||||
|
||||
/* irq */
|
||||
struct work_struct work;
|
||||
|
||||
/* dma */
|
||||
dma_addr_t dma_addr;
|
||||
unsigned char *ts_buf;
|
||||
u32 wrp;
|
||||
u32 nextwrp;
|
||||
u32 buffer_size;
|
||||
unsigned int PacketErrorCount;
|
||||
unsigned int dmarst;
|
||||
|
@ -233,8 +203,6 @@ struct dm1105dvb {
|
|||
|
||||
#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,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
|
@ -407,38 +375,61 @@ static int dm1105dvb_stop_feed(struct dvb_demux_feed *f)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* ir tasklet */
|
||||
static void dm1105_emit_key(unsigned long parm)
|
||||
/* ir work handler */
|
||||
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;
|
||||
u8 data;
|
||||
u16 keycode;
|
||||
|
||||
if (ir_debug)
|
||||
printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom);
|
||||
|
||||
data = (ircom >> 8) & 0x7f;
|
||||
|
||||
input_event(ir->input_dev, EV_MSC, MSC_RAW, (0x0000f8 << 16) | data);
|
||||
input_event(ir->input_dev, EV_MSC, MSC_SCAN, data);
|
||||
keycode = ir->key_map[data];
|
||||
ir_input_keydown(ir->input_dev, &ir->ir, data, data);
|
||||
ir_input_nokey(ir->input_dev, &ir->ir);
|
||||
}
|
||||
|
||||
if (!keycode)
|
||||
return;
|
||||
/* work handler */
|
||||
static void dm1105_dmx_buffer(struct work_struct *work)
|
||||
{
|
||||
struct dm1105dvb *dm1105dvb =
|
||||
container_of(work, struct dm1105dvb, work);
|
||||
unsigned int nbpackets;
|
||||
u32 oldwrp = dm1105dvb->wrp;
|
||||
u32 nextwrp = dm1105dvb->nextwrp;
|
||||
|
||||
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);
|
||||
if (!((dm1105dvb->ts_buf[oldwrp] == 0x47) &&
|
||||
(dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
|
||||
(dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
|
||||
dm1105dvb->PacketErrorCount++;
|
||||
/* bad packet found */
|
||||
if ((dm1105dvb->PacketErrorCount >= 2) &&
|
||||
(dm1105dvb->dmarst == 0)) {
|
||||
outb(1, dm_io_mem(DM1105_RST));
|
||||
dm1105dvb->wrp = 0;
|
||||
dm1105dvb->PacketErrorCount = 0;
|
||||
dm1105dvb->dmarst = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (nextwrp < oldwrp) {
|
||||
memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size,
|
||||
dm1105dvb->ts_buf, nextwrp);
|
||||
nbpackets = ((dm1105dvb->buffer_size - oldwrp) + nextwrp) / 188;
|
||||
} else
|
||||
nbpackets = (nextwrp - oldwrp) / 188;
|
||||
|
||||
dm1105dvb->wrp = nextwrp;
|
||||
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;
|
||||
unsigned int piece;
|
||||
unsigned int nbpackets;
|
||||
u32 command;
|
||||
u32 nextwrp;
|
||||
u32 oldwrp;
|
||||
|
||||
/* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
|
||||
unsigned int intsts = inb(dm_io_mem(DM1105_INTSTS));
|
||||
|
@ -447,71 +438,25 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id)
|
|||
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) &&
|
||||
(dm1105dvb->ts_buf[oldwrp + 188] == 0x47) &&
|
||||
(dm1105dvb->ts_buf[oldwrp + 188 * 2] == 0x47))) {
|
||||
dm1105dvb->PacketErrorCount++;
|
||||
/* bad packet found */
|
||||
if ((dm1105dvb->PacketErrorCount >= 2) &&
|
||||
(dm1105dvb->dmarst == 0)) {
|
||||
outb(1, dm_io_mem(DM1105_RST));
|
||||
dm1105dvb->wrp = 0;
|
||||
dm1105dvb->PacketErrorCount = 0;
|
||||
dm1105dvb->dmarst = 0;
|
||||
spin_unlock(&dm1105dvb->lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
if (nextwrp < oldwrp) {
|
||||
piece = dm1105dvb->buffer_size - oldwrp;
|
||||
memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp);
|
||||
nbpackets = (piece + nextwrp)/188;
|
||||
} else {
|
||||
nbpackets = (nextwrp - oldwrp)/188;
|
||||
}
|
||||
dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], nbpackets);
|
||||
dm1105dvb->wrp = nextwrp;
|
||||
spin_unlock(&dm1105dvb->lock);
|
||||
dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) -
|
||||
inl(dm_io_mem(DM1105_STADR));
|
||||
schedule_work(&dm1105dvb->work);
|
||||
break;
|
||||
case INTSTS_IR:
|
||||
command = inl(dm_io_mem(DM1105_IRCODE));
|
||||
if (ir_debug)
|
||||
printk("dm1105: received byte 0x%04x\n", command);
|
||||
|
||||
dm1105dvb->ir.ir_command = command;
|
||||
tasklet_schedule(&dm1105dvb->ir.ir_tasklet);
|
||||
dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE));
|
||||
schedule_work(&dm1105dvb->ir.work);
|
||||
break;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int err;
|
||||
|
||||
dm1105dvb_local = dm1105;
|
||||
IR_KEYTAB_TYPE *ir_codes = ir_codes_dm1105_nec;
|
||||
int ir_type = IR_TYPE_OTHER;
|
||||
int err = -ENOMEM;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
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),
|
||||
"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->phys = dm1105->ir.input_phys;
|
||||
input_dev->id.bustype = BUS_PCI;
|
||||
input_dev->id.version = 2;
|
||||
input_dev->id.version = 1;
|
||||
if (dm1105->pdev->subsystem_vendor) {
|
||||
input_dev->id.vendor = dm1105->pdev->subsystem_vendor;
|
||||
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.product = dm1105->pdev->device;
|
||||
}
|
||||
|
||||
input_dev->dev.parent = &dm1105->pdev->dev;
|
||||
/* initial keymap */
|
||||
memcpy(dm1105->ir.key_map, ir_codes_dm1105_nec, sizeof dm1105->ir.key_map);
|
||||
input_register_keys(&dm1105->ir);
|
||||
|
||||
INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err) {
|
||||
input_free_device(input_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
tasklet_init(&dm1105->ir.ir_tasklet, dm1105_emit_key, (unsigned long) &dm1105->ir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105)
|
||||
{
|
||||
tasklet_kill(&dm1105->ir.ir_tasklet);
|
||||
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);
|
||||
if (!dm1105dvb)
|
||||
goto out;
|
||||
return -ENOMEM;
|
||||
|
||||
dm1105dvb->pdev = pdev;
|
||||
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);
|
||||
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);
|
||||
if (ret < 0)
|
||||
goto err_free_irq;
|
||||
goto err_pci_iounmap;
|
||||
|
||||
/* i2c */
|
||||
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);
|
||||
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:
|
||||
dmx->disconnect_frontend(dmx);
|
||||
|
@ -843,7 +787,7 @@ err_pci_disable_device:
|
|||
err_kfree:
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
kfree(dm1105dvb);
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit dm1105_remove(struct pci_dev *pdev)
|
||||
|
|
|
@ -1024,7 +1024,7 @@ static int dvb_demux_release(struct inode *inode, struct file *file)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct file_operations dvb_demux_fops = {
|
||||
static const struct file_operations dvb_demux_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = dvb_demux_read,
|
||||
.ioctl = dvb_demux_ioctl,
|
||||
|
|
|
@ -1607,7 +1607,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
|
|||
EXPORT_SYMBOL(dvb_ca_en50221_init);
|
||||
|
||||
|
||||
static struct file_operations dvb_ca_fops = {
|
||||
static const struct file_operations dvb_ca_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = dvb_ca_en50221_io_read,
|
||||
.write = dvb_ca_en50221_io_write,
|
||||
|
|
|
@ -1875,7 +1875,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct file_operations dvb_frontend_fops = {
|
||||
static const struct file_operations dvb_frontend_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = dvb_generic_ioctl,
|
||||
.poll = dvb_frontend_poll,
|
||||
|
|
|
@ -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,
|
||||
.ioctl = dvb_net_ioctl,
|
||||
.open = dvb_generic_open,
|
||||
|
|
|
@ -228,8 +228,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
|
|||
dvbdev->fops = dvbdevfops;
|
||||
init_waitqueue_head (&dvbdev->wait_queue);
|
||||
|
||||
memcpy(dvbdev->fops, template->fops, sizeof(struct file_operations));
|
||||
dvbdev->fops->owner = adap->module;
|
||||
memcpy(dvbdevfops, template->fops, sizeof(struct file_operations));
|
||||
dvbdevfops->owner = adap->module;
|
||||
|
||||
list_add_tail (&dvbdev->list_head, &adap->device_list);
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ struct dvb_adapter {
|
|||
|
||||
struct dvb_device {
|
||||
struct list_head list_head;
|
||||
struct file_operations *fops;
|
||||
const struct file_operations *fops;
|
||||
struct dvb_adapter *adapter;
|
||||
int type;
|
||||
int minor;
|
||||
|
|
|
@ -25,7 +25,7 @@ config DVB_USB_A800
|
|||
depends on DVB_USB
|
||||
select DVB_DIB3000MC
|
||||
select DVB_PLL if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
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
|
||||
select DVB_PLL if !DVB_FE_CUSTOMISE
|
||||
select DVB_DIB3000MB
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
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.
|
||||
|
@ -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)"
|
||||
depends on DVB_USB
|
||||
select DVB_DIB3000MC
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
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.
|
||||
|
@ -69,15 +69,17 @@ config DVB_USB_DIBUSB_MC
|
|||
config DVB_USB_DIB0700
|
||||
tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
|
||||
depends on DVB_USB
|
||||
select DVB_DIB7000P
|
||||
select DVB_DIB7000M
|
||||
select DVB_DIB3000MC
|
||||
select DVB_DIB7000P if !DVB_FE_CUSTOMISE
|
||||
select DVB_DIB7000M if !DVB_FE_CUSTOMISE
|
||||
select DVB_DIB3000MC if !DVB_FE_CUSTOMISE
|
||||
select DVB_S5H1411 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TUNER_DIB0070
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE
|
||||
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
|
||||
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
|
||||
|
@ -95,7 +97,8 @@ config DVB_USB_UMT_010
|
|||
depends on DVB_USB
|
||||
select DVB_PLL if !DVB_FE_CUSTOMISE
|
||||
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
|
||||
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_ZL10353 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 MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Conexant USB2.0 hybrid reference design.
|
||||
Currently, only DVB and ATSC modes are supported, analog mode
|
||||
|
@ -125,8 +129,8 @@ config DVB_USB_M920X
|
|||
depends on DVB_USB
|
||||
select DVB_MT352 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
|
||||
Currently, only devices with a product id of
|
||||
|
@ -137,7 +141,7 @@ config DVB_USB_GL861
|
|||
tristate "Genesys Logic GL861 USB2.0 support"
|
||||
depends on DVB_USB
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
|
||||
receiver with USB ID 0db0:5581.
|
||||
|
@ -146,7 +150,7 @@ config DVB_USB_AU6610
|
|||
tristate "Alcor Micro AU6610 USB2.0 support"
|
||||
depends on DVB_USB
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
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
|
||||
select DVB_DIB3000MC
|
||||
select DVB_PLL if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
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
|
||||
tristate "Afatech AF9005 DVB-T USB1.1 support"
|
||||
depends on DVB_USB && EXPERIMENTAL
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
|
||||
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"
|
||||
depends on DVB_USB
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
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
|
||||
select DVB_AF9013
|
||||
select DVB_PLL if !DVB_FE_CUSTOMISE
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE
|
||||
select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
|
||||
select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
|
||||
help
|
||||
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
|
||||
|
|
|
@ -76,6 +76,8 @@ obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o
|
|||
dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.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/
|
||||
# due to tuner-xc3028
|
||||
|
|
|
@ -27,9 +27,7 @@
|
|||
#include "qt1010.h"
|
||||
#include "tda18271.h"
|
||||
#include "mxl5005s.h"
|
||||
#if 0
|
||||
#include "mc44s80x.h"
|
||||
#endif
|
||||
#include "mc44s803.h"
|
||||
|
||||
static int dvb_usb_af9015_debug;
|
||||
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;
|
||||
module_param_named(remote, dvb_usb_af9015_remote, int, 0644);
|
||||
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);
|
||||
|
||||
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];
|
||||
ret = af9015_ctrl_msg(d, &req);
|
||||
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 {
|
||||
if (msg[i].addr ==
|
||||
af9015_af9013_config[0].demod_address)
|
||||
|
@ -748,6 +758,16 @@ static int af9015_read_config(struct usb_device *udev)
|
|||
af9015_config.ir_table_size =
|
||||
ARRAY_SIZE(af9015_ir_table_digittrade);
|
||||
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 {
|
||||
switch (le16_to_cpu(udev->descriptor.idVendor)) {
|
||||
|
@ -836,9 +856,6 @@ static int af9015_read_config(struct usb_device *udev)
|
|||
goto error;
|
||||
af9015_config.dual_mode = val;
|
||||
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
|
||||
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) {
|
||||
case AF9013_TUNER_ENV77H11D5:
|
||||
case AF9013_TUNER_MT2060:
|
||||
case AF9013_TUNER_MC44S803:
|
||||
case AF9013_TUNER_QT1010:
|
||||
case AF9013_TUNER_UNKNOWN:
|
||||
case AF9013_TUNER_MT2060_2:
|
||||
|
@ -948,6 +964,10 @@ static int af9015_read_config(struct usb_device *udev)
|
|||
case AF9013_TUNER_MXL5005R:
|
||||
af9015_af9013_config[i].rf_spec_inv = 0;
|
||||
break;
|
||||
case AF9013_TUNER_MC44S803:
|
||||
af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO;
|
||||
af9015_af9013_config[i].rf_spec_inv = 1;
|
||||
break;
|
||||
default:
|
||||
warn("tuner id:%d not supported, please report!", val);
|
||||
return -ENODEV;
|
||||
|
@ -1135,6 +1155,11 @@ static struct mxl5005s_config af9015_mxl5005_config = {
|
|||
.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)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
case AF9013_TUNER_MC44S803:
|
||||
#if 0
|
||||
ret = dvb_attach(mc44s80x_attach, adap->fe, i2c_adap)
|
||||
== 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
|
||||
ret = dvb_attach(mc44s803_attach, adap->fe, i2c_adap,
|
||||
&af9015_mc44s803_config) == NULL ? -ENODEV : 0;
|
||||
break;
|
||||
case AF9013_TUNER_UNKNOWN:
|
||||
default:
|
||||
|
@ -1218,6 +1236,7 @@ static struct usb_device_id af9015_usb_table[] = {
|
|||
{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
|
||||
/* 15 */{USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
|
||||
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)},
|
||||
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
|
||||
{0},
|
||||
};
|
||||
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 " \
|
||||
"(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},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ enum af9015_remote {
|
|||
AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
|
||||
AF9015_REMOTE_MYGICTV_U718,
|
||||
AF9015_REMOTE_DIGITTRADE_DVB_T,
|
||||
AF9015_REMOTE_AVERMEDIA_KS,
|
||||
};
|
||||
|
||||
/* Leadtek WinFast DTV Dongle Gold */
|
||||
|
@ -597,6 +598,36 @@ static u8 af9015_ir_table_avermedia[] = {
|
|||
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 */
|
||||
static struct dvb_usb_rc_key af9015_rc_keys_digittrade[] = {
|
||||
{ 0x01, 0x0f, KEY_LAST }, /* RETURN */
|
||||
|
|
|
@ -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");
|
|
@ -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
|
|
@ -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);
|
||||
break;
|
||||
}
|
||||
|
||||
deb_data("<<< ");
|
||||
debug_dump(msg[i].buf, msg[i].len, deb_data);
|
||||
|
||||
} else {
|
||||
/* Write request */
|
||||
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 */
|
||||
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,
|
||||
usb_sndctrlpipe(d->udev, 0),
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include "xc5000.h"
|
||||
#include "s5h1411.h"
|
||||
#include "dib0070.h"
|
||||
#include "lgdt3305.h"
|
||||
#include "mxl5007t.h"
|
||||
|
||||
static int force_lna_activation;
|
||||
module_param(force_lna_activation, int, 0644);
|
||||
|
@ -262,7 +264,12 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
|
||||
msleep(10);
|
||||
dib7000p_i2c_enumeration(&adap->dev->i2c_adap,1,18,stk7700d_dib7000p_mt2266_config);
|
||||
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),
|
||||
|
@ -284,7 +291,12 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
|
||||
msleep(10);
|
||||
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),
|
||||
|
@ -421,8 +433,12 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
|
||||
msleep(10);
|
||||
|
||||
dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
|
||||
&stk7700ph_dib7700_xc3028_config);
|
||||
if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
|
||||
&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,
|
||||
&stk7700ph_dib7700_xc3028_config);
|
||||
|
@ -1187,8 +1203,12 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
|
||||
|
||||
dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
|
||||
&dib7070p_dib7000p_config);
|
||||
if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
|
||||
&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,
|
||||
&dib7070p_dib7000p_config);
|
||||
|
@ -1244,7 +1264,12 @@ static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
|
|||
msleep(10);
|
||||
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]);
|
||||
return adap->fe == NULL ? -ENODEV : 0;
|
||||
|
@ -1347,6 +1372,72 @@ static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
== 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 */
|
||||
struct usb_device_id dib0700_usb_id_table[] = {
|
||||
/* 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_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 */
|
||||
};
|
||||
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 = {
|
||||
{ "DiBcom STK7070P reference design",
|
||||
{ &dib0700_usb_id_table[15], NULL },
|
||||
|
@ -1633,6 +1730,14 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ &dib0700_usb_id_table[33], 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,
|
||||
|
@ -1661,7 +1766,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 5,
|
||||
.num_device_descs = 6,
|
||||
.devices = {
|
||||
{ "DiBcom STK7070PD reference design",
|
||||
{ &dib0700_usb_id_table[17], NULL },
|
||||
|
@ -1682,8 +1787,16 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ "Terratec Cinergy DT USB XS Diversity",
|
||||
{ &dib0700_usb_id_table[43], 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,
|
||||
|
||||
.num_adapters = 1,
|
||||
|
@ -1699,7 +1812,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.num_device_descs = 5,
|
||||
.num_device_descs = 7,
|
||||
.devices = {
|
||||
{ "Terratec Cinergy HT USB XE",
|
||||
{ &dib0700_usb_id_table[27], NULL },
|
||||
|
@ -1725,6 +1838,10 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ &dib0700_usb_id_table[39], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "YUAN High-Tech MC770",
|
||||
{ &dib0700_usb_id_table[48], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
},
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.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_size = ARRAY_SIZE(dib0700_rc_keys),
|
||||
.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 },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -27,12 +27,14 @@
|
|||
#define USB_VID_DIBCOM 0x10b8
|
||||
#define USB_VID_DPOSH 0x1498
|
||||
#define USB_VID_DVICO 0x0fe9
|
||||
#define USB_VID_ELGATO 0x0fd9
|
||||
#define USB_VID_EMPIA 0xeb1a
|
||||
#define USB_VID_GENPIX 0x09c0
|
||||
#define USB_VID_GRANDTEC 0x5032
|
||||
#define USB_VID_HANFTEK 0x15f4
|
||||
#define USB_VID_HAUPPAUGE 0x2040
|
||||
#define USB_VID_HYPER_PALTEK 0x1025
|
||||
#define USB_VID_INTEL 0x8086
|
||||
#define USB_VID_KWORLD 0xeb2a
|
||||
#define USB_VID_KWORLD_2 0x1b80
|
||||
#define USB_VID_KYE 0x0458
|
||||
|
@ -48,6 +50,7 @@
|
|||
#define USB_VID_TERRATEC 0x0ccd
|
||||
#define USB_VID_TELESTAR 0x10b9
|
||||
#define USB_VID_VISIONPLUS 0x13d3
|
||||
#define USB_VID_SONY 0x1415
|
||||
#define USB_VID_TWINHAN 0x1822
|
||||
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
|
||||
#define USB_VID_UNIWILL 0x1584
|
||||
|
@ -95,8 +98,10 @@
|
|||
#define USB_PID_UNIWILL_STK7700P 0x6003
|
||||
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
|
||||
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
|
||||
#define USB_PID_INTEL_CE9500 0x9500
|
||||
#define USB_PID_KWORLD_399U 0xe399
|
||||
#define USB_PID_KWORLD_395U 0xe396
|
||||
#define USB_PID_KWORLD_395U_2 0xe39b
|
||||
#define USB_PID_KWORLD_PC160_2T 0xc160
|
||||
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
|
||||
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
|
||||
|
@ -149,6 +154,8 @@
|
|||
#define USB_PID_HAUPPAUGE_MYTV_T 0x7080
|
||||
#define USB_PID_HAUPPAUGE_NOVA_TD_STICK 0x9580
|
||||
#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_VOLAR 0xa807
|
||||
#define USB_PID_AVERMEDIA_VOLAR_2 0xb808
|
||||
|
@ -232,9 +239,13 @@
|
|||
#define USB_PID_ASUS_U3100 0x173f
|
||||
#define USB_PID_YUAN_EC372S 0x1edc
|
||||
#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_XTENSIONS_XD_380 0x0381
|
||||
#define USB_PID_TELESTAR_STARSTICK_2 0x8000
|
||||
#define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807
|
||||
#define USB_PID_SONY_PLAYTV 0x0003
|
||||
#define USB_PID_ELGATO_EYETV_DTT 0x0021
|
||||
|
||||
#endif
|
||||
|
|
|
@ -223,7 +223,7 @@ struct dvb_usb_device_properties {
|
|||
int generic_bulk_ctrl_endpoint;
|
||||
|
||||
int num_device_descs;
|
||||
struct dvb_usb_device_description devices[9];
|
||||
struct dvb_usb_device_description devices[11];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -151,7 +151,7 @@ static void debug_fcp(const u8 *data, int length)
|
|||
subunit_type = data[1] >> 3;
|
||||
subunit_id = data[1] & 7;
|
||||
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,
|
||||
debug_fcp_ctype(data[0]),
|
||||
debug_fcp_opcode(op, data, length));
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
menu "Customise DVB Frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_FE_CUSTOMISE
|
||||
bool "Customise the frontend modules to build"
|
||||
depends on DVB_CORE
|
||||
default N
|
||||
help
|
||||
This allows the user to deselect frontend drivers unnecessary
|
||||
for their hardware from the build. 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.
|
||||
This allows the user to select/deselect frontend drivers for their
|
||||
hardware from the build.
|
||||
|
||||
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 DVB_FE_CUSTOMISE
|
||||
|
||||
menu "Customise DVB Frontends"
|
||||
|
||||
comment "Multistandard (satellite) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
@ -55,6 +59,13 @@ config DVB_MT312
|
|||
help
|
||||
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
|
||||
tristate "Samsung S5H1420 based"
|
||||
depends on DVB_CORE && I2C
|
||||
|
@ -83,6 +94,20 @@ config DVB_STV0299
|
|||
help
|
||||
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
|
||||
tristate "Philips TDA8083 based"
|
||||
depends on DVB_CORE && I2C
|
||||
|
@ -288,6 +313,13 @@ config DVB_TDA10048
|
|||
help
|
||||
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"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
@ -387,6 +419,14 @@ config DVB_LGDT3304
|
|||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
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
|
||||
tristate "Samsung S5H1409 based"
|
||||
depends on DVB_CORE && I2C
|
||||
|
@ -397,7 +437,7 @@ config DVB_S5H1409
|
|||
|
||||
config DVB_AU8522
|
||||
tristate "Auvitek AU8522 based"
|
||||
depends on DVB_CORE && I2C
|
||||
depends on DVB_CORE && I2C && VIDEO_V4L2
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
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
|
||||
|
||||
config DVB_LNBP21
|
||||
tristate "LNBP21 SEC controller"
|
||||
tristate "LNBP21/LNBH24 SEC controllers"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
An SEC control chip.
|
||||
An SEC control chips.
|
||||
|
||||
config DVB_ISL6405
|
||||
tristate "ISL6405 SEC controller"
|
||||
|
@ -478,11 +518,6 @@ comment "Tools to develop new frontends"
|
|||
config DVB_DUMMY_FE
|
||||
tristate "Dummy frontend driver"
|
||||
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
|
||||
|
||||
endif
|
||||
|
|
|
@ -7,6 +7,8 @@ EXTRA_CFLAGS += -Idrivers/media/common/tuners/
|
|||
|
||||
s921-objs := s921_module.o s921_core.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_STV0299) += stv0299.o
|
||||
|
@ -28,6 +30,7 @@ obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o
|
|||
obj-$(CONFIG_DVB_SP887X) += sp887x.o
|
||||
obj-$(CONFIG_DVB_NXT6000) += nxt6000.o
|
||||
obj-$(CONFIG_DVB_MT352) += mt352.o
|
||||
obj-$(CONFIG_DVB_ZL10036) += zl10036.o
|
||||
obj-$(CONFIG_DVB_ZL10353) += zl10353.o
|
||||
obj-$(CONFIG_DVB_CX22702) += cx22702.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_LGDT330X) += lgdt330x.o
|
||||
obj-$(CONFIG_DVB_LGDT3304) += lgdt3304.o
|
||||
obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
|
||||
obj-$(CONFIG_DVB_CX24123) += cx24123.o
|
||||
obj-$(CONFIG_DVB_LNBP21) += lnbp21.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_STB6000) += stb6000.o
|
||||
obj-$(CONFIG_DVB_S921) += s921.o
|
||||
obj-$(CONFIG_DVB_STV6110) += stv6110.o
|
||||
obj-$(CONFIG_DVB_STV0900) += stv0900.o
|
||||
|
||||
|
|
|
@ -74,6 +74,22 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config,
|
|||
}
|
||||
#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__ */
|
||||
|
||||
/*
|
||||
|
|
|
@ -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, ®->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, ®->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,
|
||||
};
|
|
@ -27,35 +27,25 @@
|
|||
#include <linux/delay.h>
|
||||
#include "dvb_frontend.h"
|
||||
#include "au8522.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;
|
||||
};
|
||||
#include "au8522_priv.h"
|
||||
|
||||
static int debug;
|
||||
|
||||
#define dprintk(arg...) do { \
|
||||
if (debug) \
|
||||
printk(arg); \
|
||||
/* Despite the name "hybrid_tuner", the framework works just as well for
|
||||
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);\
|
||||
} while (0)
|
||||
|
||||
/* 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;
|
||||
u8 buf [] = { reg >> 8, reg & 0xff, data };
|
||||
u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
|
||||
|
||||
struct i2c_msg msg = { .addr = state->config->demod_address,
|
||||
.flags = 0, .buf = buf, .len = 3 };
|
||||
|
@ -69,13 +59,13 @@ static int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
|
|||
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;
|
||||
u8 b0 [] = { reg >> 8, reg & 0xff };
|
||||
u8 b1 [] = { 0 };
|
||||
u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
|
||||
u8 b1[] = { 0 };
|
||||
|
||||
struct i2c_msg msg [] = {
|
||||
struct i2c_msg msg[] = {
|
||||
{ .addr = state->config->demod_address, .flags = 0,
|
||||
.buf = b0, .len = 2 },
|
||||
{ .addr = state->config->demod_address, .flags = I2C_M_RD,
|
||||
|
@ -528,7 +518,7 @@ static int au8522_set_frontend(struct dvb_frontend *fe,
|
|||
|
||||
/* Reset the demod hardware and reset all of the configuration registers
|
||||
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;
|
||||
dprintk("%s()\n", __func__);
|
||||
|
@ -624,7 +614,7 @@ static int au8522_led_ctrl(struct au8522_state *state, int led)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int au8522_sleep(struct dvb_frontend *fe)
|
||||
int au8522_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct au8522_state *state = fe->demodulator_priv;
|
||||
dprintk("%s()\n", __func__);
|
||||
|
@ -632,6 +622,9 @@ static int au8522_sleep(struct dvb_frontend *fe)
|
|||
/* turn off led */
|
||||
au8522_led_ctrl(state, 0);
|
||||
|
||||
/* Power down the chip */
|
||||
au8522_writereg(state, 0xa4, 1 << 5);
|
||||
|
||||
state->current_frequency = 0;
|
||||
|
||||
return 0;
|
||||
|
@ -798,23 +791,58 @@ static int au8522_get_tune_settings(struct dvb_frontend *fe,
|
|||
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)
|
||||
{
|
||||
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 i2c_adapter *i2c)
|
||||
{
|
||||
struct au8522_state *state = NULL;
|
||||
int instance;
|
||||
|
||||
/* allocate memory for the internal state */
|
||||
state = kmalloc(sizeof(struct au8522_state), GFP_KERNEL);
|
||||
if (state == NULL)
|
||||
goto error;
|
||||
instance = au8522_get_state(&state, i2c, config->demod_address);
|
||||
switch (instance) {
|
||||
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 */
|
||||
state->config = config;
|
||||
|
@ -836,7 +864,7 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config,
|
|||
return &state->frontend;
|
||||
|
||||
error:
|
||||
kfree(state);
|
||||
au8522_release_state(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(au8522_attach);
|
|
@ -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
|
|
@ -559,7 +559,7 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
|
|||
kzalloc(sizeof(struct cx24113_state), GFP_KERNEL);
|
||||
int rc;
|
||||
if (state == NULL) {
|
||||
err("Unable to kmalloc\n");
|
||||
err("Unable to kzalloc\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
September, 9th 2008
|
||||
Fixed locking on high symbol rates (>30000).
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -146,7 +149,7 @@ enum cmds {
|
|||
CMD_GETAGC = 0x19,
|
||||
CMD_LNBCONFIG = 0x20,
|
||||
CMD_LNBSEND = 0x21, /* Formerly CMD_SEND_DISEQC */
|
||||
CMD_SET_TONEPRE = 0x22,
|
||||
CMD_LNBDCLEVEL = 0x22,
|
||||
CMD_SET_TONE = 0x23,
|
||||
CMD_UPDFWVERS = 0x35,
|
||||
CMD_TUNERSLEEP = 0x36,
|
||||
|
@ -667,16 +670,6 @@ static int cx24116_load_firmware(struct dvb_frontend *fe,
|
|||
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)
|
||||
{
|
||||
struct cx24116_state *state = fe->demodulator_priv;
|
||||
|
@ -837,6 +830,34 @@ static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
|
|||
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,
|
||||
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 */
|
||||
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 */
|
||||
cmd.args[0x00] = CMD_SET_TONE;
|
||||
cmd.args[0x01] = 0x00;
|
||||
|
@ -1099,13 +1112,10 @@ struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
|
|||
dprintk("%s\n", __func__);
|
||||
|
||||
/* 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)
|
||||
goto error1;
|
||||
|
||||
/* setup the state */
|
||||
memset(state, 0, sizeof(struct cx24116_state));
|
||||
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
|
||||
|
@ -1154,7 +1164,12 @@ static int cx24116_initfe(struct dvb_frontend *fe)
|
|||
if (ret != 0)
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1069,13 +1069,13 @@ static struct dvb_frontend_ops cx24123_ops;
|
|||
struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
/* allocate memory for the internal state */
|
||||
struct cx24123_state *state =
|
||||
kzalloc(sizeof(struct cx24123_state), GFP_KERNEL);
|
||||
|
||||
dprintk("\n");
|
||||
/* allocate memory for the internal state */
|
||||
if (state == NULL) {
|
||||
err("Unable to kmalloc\n");
|
||||
err("Unable to kzalloc\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,4 @@ static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe)
|
|||
}
|
||||
#endif
|
||||
|
||||
extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, uint8_t open);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -39,20 +39,44 @@ struct dib3000mc_config {
|
|||
#define DEFAULT_DIB3000MC_I2C_ADDRESS 16
|
||||
#define DEFAULT_DIB3000P_I2C_ADDRESS 24
|
||||
|
||||
#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg);
|
||||
#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && \
|
||||
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
|
||||
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__);
|
||||
return NULL;
|
||||
}
|
||||
#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_parse(struct dvb_frontend *fe, int onoff);
|
||||
|
||||
|
|
|
@ -38,8 +38,32 @@ struct dib7000m_config {
|
|||
|
||||
#define DEFAULT_DIB7000M_I2C_ADDRESS 18
|
||||
|
||||
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);
|
||||
#if defined(CONFIG_DVB_DIB7000M) || (defined(CONFIG_DVB_DIB7000M_MODULE) && \
|
||||
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
|
||||
extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
|
||||
|
|
|
@ -37,7 +37,8 @@ struct dib7000p_config {
|
|||
|
||||
#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,
|
||||
u8 i2c_addr,
|
||||
struct dib7000p_config *cfg);
|
||||
|
@ -49,10 +50,11 @@ extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
|
|||
struct dib7000p_config cfg[]);
|
||||
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 dib7000pc_detection(struct i2c_adapter *i2c_adap);
|
||||
#else
|
||||
static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
|
||||
u8 i2c_addr,
|
||||
struct dib7000p_config *cfg)
|
||||
static inline
|
||||
struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
|
||||
struct dib7000p_config *cfg)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return NULL;
|
||||
|
@ -60,36 +62,39 @@ static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
|
|||
|
||||
static inline
|
||||
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__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline
|
||||
int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
|
||||
int no_of_demods, u8 default_addr,
|
||||
struct dib7000p_config cfg[])
|
||||
static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
|
||||
int no_of_demods, u8 default_addr,
|
||||
struct dib7000p_config cfg[])
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline
|
||||
int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
|
||||
static inline int dib7000p_set_gpio(struct dvb_frontend *fe,
|
||||
u8 num, u8 dir, u8 val)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline
|
||||
int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
|
||||
static inline int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,8 +25,27 @@
|
|||
#include <linux/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_qpsk_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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue