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

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

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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/).

View File

@ -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*).

View File

@ -63,8 +63,8 @@ If you have some knowledge and spare time, please try to fix this
yourself (patches very welcome of course...) You know: The linux
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

View File

@ -32,6 +32,10 @@ Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels.
The width of a frame is always 720 pixels, regardless of the actual specified
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>

View File

@ -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

View File

@ -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
=================

View File

@ -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).

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

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

View File

@ -310,7 +310,8 @@ static struct platform_device camera_device = {
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
.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[] = {

View File

@ -352,8 +352,9 @@ static int tw9910_power(struct device *dev, int mode)
}
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
.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[] = {

View File

@ -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

View File

@ -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);

View File

@ -452,8 +452,6 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision, pci->irq, pci->subsystem_vendor, pci->subsystem_device));
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);

View File

@ -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 ) {

View File

@ -293,7 +293,6 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
int i = 0, count = 0;
__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

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

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

View File

@ -278,7 +278,7 @@ static void mt2060_calibrate(struct mt2060_priv *priv)
while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
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

View File

@ -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"

View File

@ -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) {

View File

@ -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.

View File

@ -490,9 +490,9 @@ int tda18271_set_standby_mode(struct dvb_frontend *fe,
tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt);
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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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))

View File

@ -132,11 +132,31 @@ static const struct tda827x_data tda827x_table[] = {
{ .lomax = 0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
};
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");

View File

@ -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 {

View File

@ -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"

View File

@ -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"

View File

@ -739,7 +739,10 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
__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.
*/

View File

@ -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

View File

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

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -1,17 +1,14 @@
/*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
*
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization
*
* 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;
}

View File

@ -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");
}

View File

@ -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) }, ? */
{ },
};

View File

@ -1,14 +1,11 @@
/*
* This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
*
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII
*
* 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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -1,10 +1,7 @@
/* This file is part of linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
*
/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* register descriptions
*
* 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__

View File

@ -1,10 +1,7 @@
/* This file is part of linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
*
/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* register descriptions
*
* 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__

View File

@ -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,

View File

@ -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,

View File

@ -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) {

View File

@ -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

View File

@ -156,46 +156,12 @@ MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
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)

View File

@ -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,

View File

@ -1607,7 +1607,7 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
EXPORT_SYMBOL(dvb_ca_en50221_init);
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,

View File

@ -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,

View File

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

View File

@ -228,8 +228,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
dvbdev->fops = dvbdevfops;
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);

View File

@ -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;

View File

@ -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

View File

@ -76,6 +76,8 @@ obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o
dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o
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

View File

@ -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},
},
}

View File

@ -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 */

View File

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

View File

@ -0,0 +1,69 @@
/*
* DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver
*
* Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef _DVB_USB_CE6230_H_
#define _DVB_USB_CE6230_H_
#define DVB_USB_LOG_PREFIX "ce6230"
#include "dvb-usb.h"
#define deb_info(args...) dprintk(dvb_usb_ce6230_debug, 0x01, args)
#define deb_rc(args...) dprintk(dvb_usb_ce6230_debug, 0x02, args)
#define deb_xfer(args...) dprintk(dvb_usb_ce6230_debug, 0x04, args)
#define deb_reg(args...) dprintk(dvb_usb_ce6230_debug, 0x08, args)
#define deb_i2c(args...) dprintk(dvb_usb_ce6230_debug, 0x10, args)
#define deb_fw(args...) dprintk(dvb_usb_ce6230_debug, 0x20, args)
#define ce6230_debug_dump(r, t, v, i, b, l, func) { \
int loop_; \
func("%02x %02x %02x %02x %02x %02x %02x %02x", \
t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \
if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \
func(" >>> "); \
else \
func(" <<< "); \
for (loop_ = 0; loop_ < l; loop_++) \
func("%02x ", b[loop_]); \
func("\n");\
}
#define CE6230_USB_TIMEOUT 1000
struct req_t {
u8 cmd; /* [1] */
u16 value; /* [2|3] */
u16 index; /* [4|5] */
u16 data_len; /* [6|7] */
u8 *data;
};
enum ce6230_cmd {
CONFIG_READ = 0xd0, /* rd 0 (unclear) */
UNKNOWN_WRITE = 0xc7, /* wr 7 (unclear) */
I2C_READ = 0xd9, /* rd 9 (unclear) */
I2C_WRITE = 0xca, /* wr a */
DEMOD_READ = 0xdb, /* rd b */
DEMOD_WRITE = 0xcc, /* wr c */
REG_READ = 0xde, /* rd e */
REG_WRITE = 0xcf, /* wr f */
};
#endif

View File

@ -158,6 +158,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
err("i2c read error (status = %d)\n", result);
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;
}

View File

@ -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 },
},
},
},
};

View File

@ -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

View File

@ -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];
};
/**

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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__ */
/*

View File

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

View File

@ -27,35 +27,25 @@
#include <linux/delay.h>
#include "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);

View File

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

View File

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

View File

@ -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);
}
/*

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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