Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (132 commits) V4L/DVB 4949b: Fix container_of pointer retreival V4L/DVB (4949a): Fix INIT_WORK V4L/DVB (4949): Cxusb: codingstyle cleanups V4L/DVB (4948): Cxusb: Convert tuner functions to use dvb_pll_attach V4L/DVB (4947): Cx88: trivial cleanups V4L/DVB (4946): Cx88: Move cx88_dvb_bus_ctrl out of the card-specific area V4L/DVB (4945): Cx88: consolidate cx22702_config structs V4L/DVB (4944): Cx88: Convert DViCO FusionHDTV Hybrid to use dvb_pll_attach V4L/DVB (4943): Cx88: cleanup dvb_pll_attach for lgdt3302 tuners V4L/DVB (4953): Usbvision minor fixes V4L/DVB (4951): Add version.h, since it is required for VIDIOC_QUERYCAP V4L/DVB (4940): Or51211: Changed SNR and signal strength calculations V4L/DVB (4939): Or51132: Changed SNR and signal strength reporting V4L/DVB (4938): Cx88: Convert lgdt3302 tuning function to use dvb_pll_attach V4L/DVB (4941): Remove LINUX_VERSION_CODE and fix identations V4L/DVB (4942): Whitespace cleanups V4L/DVB (4937): Usbvision cleanup and code reorganization V4L/DVB (4936): Make MT4049FM5 tuner to set FM Gain to Normal V4L/DVB (4935): Added the capability of selecting fm gain by tuner V4L/DVB (4934): Usbvision radio requires GainNormal at e register ...
This commit is contained in:
commit
bb7320d1d9
124 changed files with 15660 additions and 4354 deletions
|
@ -22,10 +22,10 @@ o Frontends drivers:
|
|||
- ves1x93 : Alps BSRV2 (ves1893 demodulator) and dbox2 (ves1993)
|
||||
- cx24110 : Conexant HM1221/HM1811 (cx24110 or cx24106 demod, cx24108 PLL)
|
||||
- grundig_29504-491 : Grundig 29504-491 (Philips TDA8083 demodulator), tsa5522 PLL
|
||||
- mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLL
|
||||
- mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLLi, Technisat Sky2Pc with bios Rev. 2.3
|
||||
- stv0299 : Alps BSRU6 (tsa5059 PLL), LG TDQB-S00x (tsa5059 PLL),
|
||||
LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL),
|
||||
Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB
|
||||
Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB, Technisat Sky2Pc with bios Rev. 2.6
|
||||
DVB-C:
|
||||
- ves1820 : various (ves1820 demodulator, sp5659c or spXXXX PLL)
|
||||
- at76c651 : Atmel AT76c651(B) with DAT7021 PLL
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025,1822:0019]
|
||||
43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1,12ab:2300]
|
||||
44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54]
|
||||
45 -> KWorld HardwareMpegTV XPert [17de:0840]
|
||||
45 -> KWorld HardwareMpegTV XPert [17de:0840,1421:0305]
|
||||
46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44]
|
||||
47 -> pcHDTV HD5500 HDTV [7063:5500]
|
||||
48 -> Kworld MCE 200 Deluxe [17de:0841]
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
75 -> AVerMedia AVerTVHD MCE A180 [1461:1044]
|
||||
76 -> SKNet MonsterTV Mobile [1131:4ee9]
|
||||
77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e]
|
||||
78 -> ASUSTeK P7131 Dual [1043:4862]
|
||||
78 -> ASUSTeK P7131 Dual [1043:4862,1043:4876]
|
||||
79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)
|
||||
80 -> ASUS Digimatrix TV [1043:0210]
|
||||
81 -> Philips Tiger reference design [1131:2018]
|
||||
|
@ -99,3 +99,8 @@
|
|||
98 -> Proteus Pro 2309 [0919:2003]
|
||||
99 -> AVerMedia TV Hybrid A16AR [1461:2c00]
|
||||
100 -> Asus Europa2 OEM [1043:4860]
|
||||
101 -> Pinnacle PCTV 310i [11bd:002f]
|
||||
102 -> Avermedia AVerTV Studio 507 [1461:9715]
|
||||
103 -> Compro Videomate DVB-T200A
|
||||
104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid [0070:6701]
|
||||
105 -> Terratec Cinergy HT PCMCIA [153b:1172]
|
||||
|
|
54
Documentation/video4linux/cafe_ccic
Normal file
54
Documentation/video4linux/cafe_ccic
Normal file
|
@ -0,0 +1,54 @@
|
|||
"cafe_ccic" is a driver for the Marvell 88ALP01 "cafe" CMOS camera
|
||||
controller. This is the controller found in first-generation OLPC systems,
|
||||
and this driver was written with support from the OLPC project.
|
||||
|
||||
Current status: the core driver works. It can generate data in YUV422,
|
||||
RGB565, and RGB444 formats. (Anybody looking at the code will see RGB32 as
|
||||
well, but that is a debugging aid which will be removed shortly). VGA and
|
||||
QVGA modes work; CIF is there but the colors remain funky. Only the OV7670
|
||||
sensor is known to work with this controller at this time.
|
||||
|
||||
To try it out: either of these commands will work:
|
||||
|
||||
mplayer tv:// -tv driver=v4l2:width=640:height=480 -nosound
|
||||
mplayer tv:// -tv driver=v4l2:width=640:height=480:outfmt=bgr16 -nosound
|
||||
|
||||
The "xawtv" utility also works; gqcam does not, for unknown reasons.
|
||||
|
||||
There are a few load-time options, most of which can be changed after
|
||||
loading via sysfs as well:
|
||||
|
||||
- alloc_bufs_at_load: Normally, the driver will not allocate any DMA
|
||||
buffers until the time comes to transfer data. If this option is set,
|
||||
then worst-case-sized buffers will be allocated at module load time.
|
||||
This option nails down the memory for the life of the module, but
|
||||
perhaps decreases the chances of an allocation failure later on.
|
||||
|
||||
- dma_buf_size: The size of DMA buffers to allocate. Note that this
|
||||
option is only consulted for load-time allocation; when buffers are
|
||||
allocated at run time, they will be sized appropriately for the current
|
||||
camera settings.
|
||||
|
||||
- n_dma_bufs: The controller can cycle through either two or three DMA
|
||||
buffers. Normally, the driver tries to use three buffers; on faster
|
||||
systems, however, it will work well with only two.
|
||||
|
||||
- min_buffers: The minimum number of streaming I/O buffers that the driver
|
||||
will consent to work with. Default is one, but, on slower systems,
|
||||
better behavior with mplayer can be achieved by setting to a higher
|
||||
value (like six).
|
||||
|
||||
- max_buffers: The maximum number of streaming I/O buffers; default is
|
||||
ten. That number was carefully picked out of a hat and should not be
|
||||
assumed to actually mean much of anything.
|
||||
|
||||
- flip: If this boolean parameter is set, the sensor will be instructed to
|
||||
invert the video image. Whether it makes sense is determined by how
|
||||
your particular camera is mounted.
|
||||
|
||||
Work is ongoing with this driver, stay tuned.
|
||||
|
||||
jon
|
||||
|
||||
Jonathan Corbet
|
||||
corbet@lwn.net
|
|
@ -1,162 +0,0 @@
|
|||
Driver for Trust Computer Products Framegrabber, version 0.6.1
|
||||
------ --- ----- -------- -------- ------------ ------- - - -
|
||||
|
||||
- ZORAN ------------------------------------------------------
|
||||
Author: Pauline Middelink <middelin@polyware.nl>
|
||||
Date: 18 September 1999
|
||||
Version: 0.6.1
|
||||
|
||||
- Description ------------------------------------------------
|
||||
|
||||
Video4Linux compatible driver for an unknown brand framegrabber
|
||||
(Sold in the Netherlands by TRUST Computer Products) and various
|
||||
other zoran zr36120 based framegrabbers.
|
||||
|
||||
The card contains a ZR36120 Multimedia PCI Interface and a Philips
|
||||
SAA7110 Onechip Frontend videodecoder. There is also an DSP of
|
||||
which I have forgotten the number, since i will never get that thing
|
||||
to work without specs from the vendor itself.
|
||||
|
||||
The SAA711x are capable of processing 6 different video inputs,
|
||||
CVBS1..6 and Y1+C1, Y2+C2, Y3+C3. All in 50/60Hz, NTSC, PAL or
|
||||
SECAM and delivering a YUV datastream. On my card the input
|
||||
'CVBS-0' corresponds to channel CVBS2 and 'S-Video' to Y2+C2.
|
||||
|
||||
I have some reports of other cards working with the mentioned
|
||||
chip sets. For a list of other working cards please have a look
|
||||
at the cards named in the tvcards struct in the beginning of
|
||||
zr36120.c
|
||||
|
||||
After some testing, I discovered that the carddesigner messed up
|
||||
on the I2C interface. The Zoran chip includes 2 lines SDA and SCL
|
||||
which (s)he connected reversely. So we have to clock on the SDA
|
||||
and r/w data on the SCL pin. Life is fun... Each cardtype now has
|
||||
a bit which signifies if you have a card with the same deficiency.
|
||||
|
||||
Oh, for the completeness of this story I must mention that my
|
||||
card delivers the VSYNC pulse of the SAA chip to GIRQ1, not
|
||||
GIRQ0 as some other cards have. This is also incorporated in
|
||||
the driver be clearing/setting the 'useirq1' bit in the tvcard
|
||||
description.
|
||||
|
||||
Another problems of continuous capturing data with a Zoran chip
|
||||
is something nasty inside the chip. It effectively halves the
|
||||
fps we ought to get... Here is the scenario: capturing frames
|
||||
to memory is done in the so-called snapshot mode. In this mode
|
||||
the Zoran stops after capturing a frame worth of data and wait
|
||||
till the application set GRAB bit to indicate readiness for the
|
||||
next frame. After detecting a set bit, the chip neatly waits
|
||||
till the start of a frame, captures it and it goes back to off.
|
||||
Smart ppl will notice the problem here. Its the waiting on the
|
||||
_next_ frame each time we set the GRAB bit... Oh well, 12,5 fps
|
||||
is still plenty fast for me.
|
||||
-- update 28/7/1999 --
|
||||
Don't believe a word I just said... Proof is the output
|
||||
of `streamer -t 300 -r 25 -f avi15 -o /dev/null`
|
||||
++--+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
|
||||
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+-
|
||||
syncer: done
|
||||
writer: done
|
||||
(note the /dev/null is prudent here, my system is not able to
|
||||
grab /and/ write 25 fps to a file... gifts welcome :) )
|
||||
The technical reasoning follows: The zoran completed the last
|
||||
frame, the VSYNC goes low, and GRAB is cleared. The interrupt
|
||||
routine starts to work since its VSYNC driven, and again
|
||||
activates the GRAB bit. A few ms later the VSYNC (re-)rises and
|
||||
the zoran starts to work on a new and freshly broadcasted frame....
|
||||
|
||||
For pointers I used the specs of both chips. Below are the URLs:
|
||||
http://www.zoran.com/ftp/download/devices/pci/ZR36120/36120data.pdf
|
||||
http://www-us.semiconductor.philips.com/acrobat/datasheets/SAA_7110_A_1.pdf
|
||||
Some alternatives for the Philips SAA 7110 datasheet are:
|
||||
http://www.datasheetcatalog.com/datasheets_pdf/S/A/A/7/SAA7110.shtml
|
||||
http://www.datasheetarchive.com/search.php?search=SAA7110&sType=part
|
||||
|
||||
The documentation has very little on absolute numbers or timings
|
||||
needed for the various modes/resolutions, but there are other
|
||||
programs you can borrow those from.
|
||||
|
||||
------ Install --------------------------------------------
|
||||
Read the file called TODO. Note its long list of limitations.
|
||||
|
||||
Build a kernel with VIDEO4LINUX enabled. Activate the
|
||||
BT848 driver; we need this because we have need for the
|
||||
other modules (i2c and videodev) it enables.
|
||||
|
||||
To install this software, extract it into a suitable directory.
|
||||
Examine the makefile and change anything you don't like. Type "make".
|
||||
|
||||
After making the modules check if you have the much needed
|
||||
/dev/video devices. If not, execute the following 4 lines:
|
||||
mknod /dev/video c 81 0
|
||||
mknod /dev/video1 c 81 1
|
||||
mknod /dev/video2 c 81 2
|
||||
mknod /dev/video3 c 81 3
|
||||
mknod /dev/video4 c 81 4
|
||||
|
||||
After making/checking the devices do:
|
||||
modprobe i2c
|
||||
modprobe videodev
|
||||
modprobe saa7110 (optional)
|
||||
modprobe saa7111 (optional)
|
||||
modprobe tuner (optional)
|
||||
insmod zoran cardtype=<n>
|
||||
|
||||
<n> is the cardtype of the card you have. The cardnumber can
|
||||
be found in the source of zr36120. Look for tvcards. If your
|
||||
card is not there, please try if any other card gives some
|
||||
response, and mail me if you got a working tvcard addition.
|
||||
|
||||
PS. <TVCard editors behold!)
|
||||
Don't forget to set video_input to the number of inputs
|
||||
you defined in the video_mux part of the tvcard definition.
|
||||
It's a common error to add a channel but not incrementing
|
||||
video_input and getting angry with me/v4l/linux/linus :(
|
||||
|
||||
You are now ready to test the framegrabber with your favorite
|
||||
video4linux compatible tool
|
||||
|
||||
------ Application ----------------------------------------
|
||||
|
||||
This device works with all Video4Linux compatible applications,
|
||||
given the limitations in the TODO file.
|
||||
|
||||
------ API ------------------------------------------------
|
||||
|
||||
This uses the V4L interface as of kernel release 2.1.116, and in
|
||||
fact has not been tested on any lower version. There are a couple
|
||||
of minor differences due to the fact that the amount of data returned
|
||||
with each frame varies, and no doubt there are discrepancies due to my
|
||||
misunderstanding of the API. I intend to convert this driver to the
|
||||
new V4L2 API when it has stabilized more.
|
||||
|
||||
------ Current state --------------------------------------
|
||||
|
||||
The driver is capable of overlaying a video image in screen, and
|
||||
even capable of grabbing frames. It uses the BIGPHYSAREA patch
|
||||
to allocate lots of large memory blocks when tis patch is
|
||||
found in the kernel, but it doesn't need it.
|
||||
The consequence is that, when loading the driver as a module,
|
||||
the module may tell you it's out of memory, but 'free' says
|
||||
otherwise. The reason is simple; the modules wants its memory
|
||||
contiguous, not fragmented, and after a long uptime there
|
||||
probably isn't a fragment of memory large enough...
|
||||
|
||||
The driver uses a double buffering scheme, which should really
|
||||
be an n-way buffer, depending on the size of allocated framebuffer
|
||||
and the requested grab-size/format.
|
||||
This current version also fixes a dead-lock situation during irq
|
||||
time, which really, really froze my system... :)
|
||||
|
||||
Good luck.
|
||||
Pauline
|
|
@ -67,6 +67,7 @@ source "drivers/media/common/Kconfig"
|
|||
|
||||
config VIDEO_TUNER
|
||||
tristate
|
||||
depends on I2C
|
||||
|
||||
config VIDEO_BUF
|
||||
tristate
|
||||
|
@ -82,6 +83,7 @@ config VIDEO_IR
|
|||
|
||||
config VIDEO_TVEEPROM
|
||||
tristate
|
||||
depends on I2C
|
||||
|
||||
config USB_DABUSB
|
||||
tristate "DABUSB driver"
|
||||
|
|
|
@ -1552,3 +1552,58 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = {
|
|||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(ir_codes_norwood);
|
||||
|
||||
/* From reading the following remotes:
|
||||
* Zenith Universal 7 / TV Mode 807 / VCR Mode 837
|
||||
* Hauppauge (from NOVA-CI-s box product)
|
||||
* This is a "middle of the road" approach, differences are noted
|
||||
*/
|
||||
IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = {
|
||||
[ 0x00 ] = KEY_0,
|
||||
[ 0x01 ] = KEY_1,
|
||||
[ 0x02 ] = KEY_2,
|
||||
[ 0x03 ] = KEY_3,
|
||||
[ 0x04 ] = KEY_4,
|
||||
[ 0x05 ] = KEY_5,
|
||||
[ 0x06 ] = KEY_6,
|
||||
[ 0x07 ] = KEY_7,
|
||||
[ 0x08 ] = KEY_8,
|
||||
[ 0x09 ] = KEY_9,
|
||||
[ 0x0a ] = KEY_ENTER,
|
||||
[ 0x0b ] = KEY_RED,
|
||||
[ 0x0c ] = KEY_POWER, /* RADIO on Hauppauge */
|
||||
[ 0x0d ] = KEY_MUTE,
|
||||
[ 0x0f ] = KEY_A, /* TV on Hauppauge */
|
||||
[ 0x10 ] = KEY_VOLUMEUP,
|
||||
[ 0x11 ] = KEY_VOLUMEDOWN,
|
||||
[ 0x14 ] = KEY_B,
|
||||
[ 0x1c ] = KEY_UP,
|
||||
[ 0x1d ] = KEY_DOWN,
|
||||
[ 0x1e ] = KEY_OPTION, /* RESERVED on Hauppauge */
|
||||
[ 0x1f ] = KEY_BREAK,
|
||||
[ 0x20 ] = KEY_CHANNELUP,
|
||||
[ 0x21 ] = KEY_CHANNELDOWN,
|
||||
[ 0x22 ] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */
|
||||
[ 0x24 ] = KEY_RESTART,
|
||||
[ 0x25 ] = KEY_OK,
|
||||
[ 0x26 ] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */
|
||||
[ 0x28 ] = KEY_ENTER, /* VCR mode on Zenith */
|
||||
[ 0x29 ] = KEY_PAUSE,
|
||||
[ 0x2b ] = KEY_RIGHT,
|
||||
[ 0x2c ] = KEY_LEFT,
|
||||
[ 0x2e ] = KEY_MENU, /* FULL SCREEN on Hauppauge */
|
||||
[ 0x30 ] = KEY_SLOW,
|
||||
[ 0x31 ] = KEY_PREVIOUS, /* VCR mode on Zenith */
|
||||
[ 0x32 ] = KEY_REWIND,
|
||||
[ 0x34 ] = KEY_FASTFORWARD,
|
||||
[ 0x35 ] = KEY_PLAY,
|
||||
[ 0x36 ] = KEY_STOP,
|
||||
[ 0x37 ] = KEY_RECORD,
|
||||
[ 0x38 ] = KEY_TUNER, /* TV/VCR on Zenith */
|
||||
[ 0x3a ] = KEY_C,
|
||||
[ 0x3c ] = KEY_EXIT,
|
||||
[ 0x3d ] = KEY_POWER2,
|
||||
[ 0x3e ] = KEY_TUNER,
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old);
|
||||
|
|
|
@ -189,13 +189,21 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
|
|||
saa7146_write(dev, I2C_TRANSFER, *dword);
|
||||
|
||||
dev->i2c_op = 1;
|
||||
SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
|
||||
SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
|
||||
saa7146_write(dev, MC2, (MASK_00 | MASK_16));
|
||||
|
||||
wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0);
|
||||
if (signal_pending (current)) {
|
||||
/* a signal arrived */
|
||||
return -ERESTARTSYS;
|
||||
timeout = HZ/100 + 1; /* 10ms */
|
||||
timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout);
|
||||
if (timeout == -ERESTARTSYS || dev->i2c_op) {
|
||||
SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
|
||||
SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
|
||||
if (timeout == -ERESTARTSYS)
|
||||
/* a signal arrived */
|
||||
return -ERESTARTSYS;
|
||||
|
||||
printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n");
|
||||
return -EIO;
|
||||
}
|
||||
status = saa7146_read(dev, I2C_STATUS);
|
||||
} else {
|
||||
|
|
|
@ -9,6 +9,7 @@ config DVB_B2C2_FLEXCOP
|
|||
select DVB_STV0297 if !DVB_FE_CUSTOMISE
|
||||
select DVB_BCM3510 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
|
||||
select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Support for the digital TV receiver chip made by B2C2 Inc. included in
|
||||
Technisats PCI cards and USB boxes.
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "stv0297.h"
|
||||
#include "mt312.h"
|
||||
#include "lgdt330x.h"
|
||||
#include "lg_h06xf.h"
|
||||
#include "lgh06xf.h"
|
||||
#include "dvb-pll.h"
|
||||
|
||||
/* lnb control */
|
||||
|
@ -303,12 +303,6 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
|
|||
return request_firmware(fw, name, fc->dev);
|
||||
}
|
||||
|
||||
static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct flexcop_device *fc = fe->dvb->priv;
|
||||
return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
|
||||
}
|
||||
|
||||
static struct lgdt330x_config air2pc_atsc_hd5000_config = {
|
||||
.demod_address = 0x59,
|
||||
.demod_chip = LGDT3303,
|
||||
|
@ -533,7 +527,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
/* try the air atsc 3nd generation (lgdt3303) */
|
||||
if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
|
||||
fc->dev_type = FC_AIR_ATSC3;
|
||||
fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
|
||||
dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap);
|
||||
info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
|
||||
} else
|
||||
/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
config DVB_BT8XX
|
||||
tristate "BT8xx based PCI cards"
|
||||
depends on DVB_CORE && PCI && I2C && VIDEO_BT848
|
||||
select DVB_PLL
|
||||
select DVB_MT352 if !DVB_FE_CUSTOMISE
|
||||
select DVB_SP887X if !DVB_FE_CUSTOMISE
|
||||
select DVB_NXT6000 if !DVB_FE_CUSTOMISE
|
||||
select DVB_CX24110 if !DVB_FE_CUSTOMISE
|
||||
select DVB_OR51211 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
|
||||
select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
select FW_LOADER
|
||||
help
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "dvb_frontend.h"
|
||||
#include "dvb-bt8xx.h"
|
||||
#include "bt878.h"
|
||||
#include "dvb-pll.h"
|
||||
|
||||
static int debug;
|
||||
|
||||
|
@ -568,12 +567,6 @@ static struct mt352_config digitv_alps_tded4_config = {
|
|||
.demod_init = digitv_alps_tded4_demod_init,
|
||||
};
|
||||
|
||||
static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
|
||||
{
|
||||
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
|
||||
return lg_h06xf_pll_set(fe, card->i2c_adapter, params);
|
||||
}
|
||||
|
||||
static struct lgdt330x_config tdvs_tua6034_config = {
|
||||
.demod_address = 0x0e,
|
||||
.demod_chip = LGDT3303,
|
||||
|
@ -616,7 +609,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
lgdt330x_reset(card);
|
||||
card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
|
||||
if (card->fe != NULL) {
|
||||
card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
|
||||
dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter);
|
||||
dprintk ("dvb_bt8xx: lgdt330x detected\n");
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "cx24110.h"
|
||||
#include "or51211.h"
|
||||
#include "lgdt330x.h"
|
||||
#include "lg_h06xf.h"
|
||||
#include "lgh06xf.h"
|
||||
#include "zl10353.h"
|
||||
|
||||
struct dvb_bt8xx_card {
|
||||
|
|
|
@ -746,6 +746,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
|
|||
dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
|
||||
input_report_key(cinergyt2->rc_input_dev,
|
||||
cinergyt2->rc_input_event, 0);
|
||||
input_sync(cinergyt2->rc_input_dev);
|
||||
cinergyt2->rc_input_event = KEY_MAX;
|
||||
}
|
||||
cinergyt2->rc_last_code = ~0;
|
||||
|
@ -783,6 +784,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
|
|||
dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
|
||||
input_report_key(cinergyt2->rc_input_dev,
|
||||
cinergyt2->rc_input_event, 1);
|
||||
input_sync(cinergyt2->rc_input_dev);
|
||||
cinergyt2->rc_last_code = rc_events[n].value;
|
||||
}
|
||||
}
|
||||
|
@ -798,8 +800,9 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
|
|||
{
|
||||
struct input_dev *input_dev;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
cinergyt2->rc_input_dev = input_dev = input_allocate_device();
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -817,7 +820,13 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
|
|||
input_dev->keycodesize = 0;
|
||||
input_dev->keycodemax = 0;
|
||||
|
||||
input_register_device(cinergyt2->rc_input_dev);
|
||||
err = input_register_device(input_dev);
|
||||
if (err) {
|
||||
input_free_device(input_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
cinergyt2->rc_input_dev = input_dev;
|
||||
schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -69,6 +69,8 @@ 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_TUNER_MT2060 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
|
@ -96,6 +98,7 @@ config DVB_USB_CXUSB
|
|||
depends on DVB_USB
|
||||
select DVB_CX22702 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
|
||||
select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
|
||||
select DVB_MT352 if !DVB_FE_CUSTOMISE
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
|
@ -157,6 +160,17 @@ config DVB_USB_NOVA_T_USB2
|
|||
help
|
||||
Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
|
||||
|
||||
config DVB_USB_TTUSB2
|
||||
tristate "Pinnacle 400e DVB-S USB2.0 support"
|
||||
depends on DVB_USB
|
||||
select DVB_TDA10086 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA826X if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The
|
||||
firmware protocol used by this module is similar to the one used by the
|
||||
old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko.
|
||||
|
||||
config DVB_USB_DTT200U
|
||||
tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
|
||||
depends on DVB_USB
|
||||
|
|
|
@ -36,6 +36,9 @@ obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
|
|||
dvb-usb-cxusb-objs = cxusb.o
|
||||
obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o
|
||||
|
||||
dvb-usb-ttusb2-objs = ttusb2.o
|
||||
obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o
|
||||
|
||||
dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o
|
||||
obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o
|
||||
|
||||
|
|
|
@ -116,24 +116,24 @@ static struct dvb_usb_device_properties a800_properties = {
|
|||
{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 32,
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
|
||||
.frontend_attach = dibusb_dib3000mc_frontend_attach,
|
||||
.tuner_attach = dibusb_dib3000mc_tuner_attach,
|
||||
.frontend_attach = dibusb_dib3000mc_frontend_attach,
|
||||
.tuner_attach = dibusb_dib3000mc_tuner_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
},
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
* TODO: Use the cx25840-driver for the analogue part
|
||||
*
|
||||
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||
* Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net)
|
||||
* Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org)
|
||||
* Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, version 2.
|
||||
* 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, version 2.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
|
@ -27,29 +27,29 @@
|
|||
|
||||
#include "cx22702.h"
|
||||
#include "lgdt330x.h"
|
||||
#include "lg_h06xf.h"
|
||||
#include "lgh06xf.h"
|
||||
#include "mt352.h"
|
||||
#include "mt352_priv.h"
|
||||
#include "zl10353.h"
|
||||
|
||||
/* debug */
|
||||
int dvb_usb_cxusb_debug;
|
||||
module_param_named(debug,dvb_usb_cxusb_debug, int, 0644);
|
||||
module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
|
||||
|
||||
static int cxusb_ctrl_msg(struct dvb_usb_device *d,
|
||||
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
|
||||
u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
|
||||
{
|
||||
int wo = (rbuf == NULL || rlen == 0); /* write-only */
|
||||
u8 sndbuf[1+wlen];
|
||||
memset(sndbuf,0,1+wlen);
|
||||
memset(sndbuf, 0, 1+wlen);
|
||||
|
||||
sndbuf[0] = cmd;
|
||||
memcpy(&sndbuf[1],wbuf,wlen);
|
||||
memcpy(&sndbuf[1], wbuf, wlen);
|
||||
if (wo)
|
||||
dvb_usb_generic_write(d,sndbuf,1+wlen);
|
||||
dvb_usb_generic_write(d, sndbuf, 1+wlen);
|
||||
else
|
||||
dvb_usb_generic_rw(d,sndbuf,1+wlen,rbuf,rlen,0);
|
||||
dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -58,14 +58,14 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
|
|||
static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
|
||||
{
|
||||
struct cxusb_state *st = d->priv;
|
||||
u8 o[2],i;
|
||||
u8 o[2], i;
|
||||
|
||||
if (st->gpio_write_state[GPIO_TUNER] == onoff)
|
||||
return;
|
||||
|
||||
o[0] = GPIO_TUNER;
|
||||
o[1] = onoff;
|
||||
cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1);
|
||||
cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
|
||||
|
||||
if (i != 0x01)
|
||||
deb_info("gpio_write failed.\n");
|
||||
|
@ -74,7 +74,8 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
|
|||
}
|
||||
|
||||
/* I2C */
|
||||
static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
|
||||
static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i;
|
||||
|
@ -89,12 +90,12 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
|
|||
|
||||
if (d->udev->descriptor.idVendor == USB_VID_MEDION)
|
||||
switch (msg[i].addr) {
|
||||
case 0x63:
|
||||
cxusb_gpio_tuner(d,0);
|
||||
break;
|
||||
default:
|
||||
cxusb_gpio_tuner(d,1);
|
||||
break;
|
||||
case 0x63:
|
||||
cxusb_gpio_tuner(d, 0);
|
||||
break;
|
||||
default:
|
||||
cxusb_gpio_tuner(d, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* read request */
|
||||
|
@ -103,26 +104,27 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
|
|||
obuf[0] = msg[i].len;
|
||||
obuf[1] = msg[i+1].len;
|
||||
obuf[2] = msg[i].addr;
|
||||
memcpy(&obuf[3],msg[i].buf,msg[i].len);
|
||||
memcpy(&obuf[3], msg[i].buf, msg[i].len);
|
||||
|
||||
if (cxusb_ctrl_msg(d, CMD_I2C_READ,
|
||||
obuf, 3+msg[i].len,
|
||||
ibuf, 1+msg[i+1].len) < 0)
|
||||
obuf, 3+msg[i].len,
|
||||
ibuf, 1+msg[i+1].len) < 0)
|
||||
break;
|
||||
|
||||
if (ibuf[0] != 0x08)
|
||||
deb_i2c("i2c read may have failed\n");
|
||||
|
||||
memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len);
|
||||
memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len);
|
||||
|
||||
i++;
|
||||
} else { /* write */
|
||||
u8 obuf[2+msg[i].len], ibuf;
|
||||
obuf[0] = msg[i].addr;
|
||||
obuf[1] = msg[i].len;
|
||||
memcpy(&obuf[2],msg[i].buf,msg[i].len);
|
||||
memcpy(&obuf[2], msg[i].buf, msg[i].len);
|
||||
|
||||
if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0)
|
||||
if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf,
|
||||
2+msg[i].len, &ibuf,1) < 0)
|
||||
break;
|
||||
if (ibuf != 0x08)
|
||||
deb_i2c("i2c write may have failed\n");
|
||||
|
@ -324,16 +326,8 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *fep)
|
||||
{
|
||||
struct dvb_usb_adapter *adap = fe->dvb->priv;
|
||||
return lg_h06xf_pll_set(fe, &adap->dev->i2c_adap, fep);
|
||||
}
|
||||
|
||||
static struct cx22702_config cxusb_cx22702_config = {
|
||||
.demod_address = 0x63,
|
||||
|
||||
.output_mode = CX22702_PARALLEL_OUTPUT,
|
||||
};
|
||||
|
||||
|
@ -374,31 +368,27 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
|
||||
static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->pll_addr = 0x61;
|
||||
adap->pll_desc = &dvb_pll_thomson_dtt7579;
|
||||
adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x61,
|
||||
NULL, &dvb_pll_thomson_dtt7579);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->pll_addr = 0x61;
|
||||
adap->pll_desc = &dvb_pll_lg_z201;
|
||||
adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, &dvb_pll_lg_z201);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->pll_addr = 0x60;
|
||||
adap->pll_desc = &dvb_pll_thomson_dtt7579;
|
||||
adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
|
||||
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
|
||||
NULL, &dvb_pll_thomson_dtt7579);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
|
||||
dvb_attach(lgh06xf_attach, adap->fe, &adap->dev->i2c_adap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -410,7 +400,8 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
|
||||
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
|
||||
|
||||
if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &adap->dev->i2c_adap)) != NULL)
|
||||
if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
|
||||
&adap->dev->i2c_adap)) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
|
@ -423,7 +414,8 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
|
||||
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
|
||||
|
||||
if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &adap->dev->i2c_adap)) != NULL)
|
||||
if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config,
|
||||
&adap->dev->i2c_adap)) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
|
@ -437,7 +429,8 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
|
||||
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
|
||||
|
||||
if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &adap->dev->i2c_adap)) != NULL)
|
||||
if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
|
||||
&adap->dev->i2c_adap)) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
|
@ -450,8 +443,11 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
|
||||
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
|
||||
|
||||
if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &adap->dev->i2c_adap)) != NULL) ||
|
||||
((adap->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &adap->dev->i2c_adap)) != NULL))
|
||||
if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
|
||||
&adap->dev->i2c_adap)) != NULL) ||
|
||||
((adap->fe = dvb_attach(zl10353_attach,
|
||||
&cxusb_zl10353_dee1601_config,
|
||||
&adap->dev->i2c_adap)) != NULL))
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
|
@ -463,7 +459,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
*/
|
||||
|
||||
#define BLUEBIRD_01_ID_OFFSET 6638
|
||||
static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw)
|
||||
static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
|
||||
const struct firmware *fw)
|
||||
{
|
||||
if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
|
||||
return -EINVAL;
|
||||
|
@ -471,10 +468,12 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const
|
|||
if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
|
||||
fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
|
||||
|
||||
fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
|
||||
fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;
|
||||
fw->data[BLUEBIRD_01_ID_OFFSET + 2] =
|
||||
udev->descriptor.idProduct + 1;
|
||||
fw->data[BLUEBIRD_01_ID_OFFSET + 3] =
|
||||
udev->descriptor.idProduct >> 8;
|
||||
|
||||
return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2);
|
||||
return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
@ -488,7 +487,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
|
|||
static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
|
||||
|
||||
static int cxusb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
|
||||
dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
|
||||
|
@ -502,20 +501,20 @@ static int cxusb_probe(struct usb_interface *intf,
|
|||
}
|
||||
|
||||
static struct usb_device_id cxusb_table [] = {
|
||||
{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
|
||||
{} /* Terminating entry */
|
||||
{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
|
||||
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE (usb, cxusb_table);
|
||||
|
||||
|
@ -529,20 +528,20 @@ static struct dvb_usb_device_properties cxusb_medion_properties = {
|
|||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_cx22702_frontend_attach,
|
||||
.tuner_attach = cxusb_fmd1216me_tuner_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 5,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_cx22702_frontend_attach,
|
||||
.tuner_attach = cxusb_fmd1216me_tuner_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 5,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
},
|
||||
|
@ -575,21 +574,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
|
|||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_lgdt3303_frontend_attach,
|
||||
.tuner_attach = cxusb_lgdt3303_tuner_attach,
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_lgdt3303_frontend_attach,
|
||||
.tuner_attach = cxusb_lgh064f_tuner_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 5,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 5,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -627,20 +626,20 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
|
|||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_dee1601_frontend_attach,
|
||||
.tuner_attach = cxusb_dee1601_tuner_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_dee1601_frontend_attach,
|
||||
.tuner_attach = cxusb_dee1601_tuner_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 5,
|
||||
.endpoint = 0x04,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 5,
|
||||
.endpoint = 0x04,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
|
@ -686,21 +685,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
|
|||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_mt352_frontend_attach,
|
||||
.tuner_attach = cxusb_lgz201_tuner_attach,
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_mt352_frontend_attach,
|
||||
.tuner_attach = cxusb_lgz201_tuner_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 5,
|
||||
.endpoint = 0x04,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 5,
|
||||
.endpoint = 0x04,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
.power_ctrl = cxusb_bluebird_power_ctrl,
|
||||
|
@ -736,21 +735,21 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
|
|||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_mt352_frontend_attach,
|
||||
.tuner_attach = cxusb_dtt7579_tuner_attach,
|
||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||
.frontend_attach = cxusb_mt352_frontend_attach,
|
||||
.tuner_attach = cxusb_dtt7579_tuner_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 5,
|
||||
.endpoint = 0x04,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 5,
|
||||
.endpoint = 0x04,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
.power_ctrl = cxusb_bluebird_power_ctrl,
|
||||
|
@ -776,7 +775,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
|
|||
static struct usb_driver cxusb_driver = {
|
||||
.name = "dvb_usb_cxusb",
|
||||
.probe = cxusb_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = cxusb_table,
|
||||
};
|
||||
|
||||
|
@ -802,7 +801,7 @@ module_init (cxusb_module_init);
|
|||
module_exit (cxusb_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||
MODULE_AUTHOR("Michael Krufky <mkrufky@m1k.net>");
|
||||
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
|
||||
MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
|
||||
MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design");
|
||||
MODULE_VERSION("1.0-alpha");
|
||||
|
|
|
@ -24,18 +24,23 @@ extern int dvb_usb_dib0700_debug;
|
|||
#define REQUEST_I2C_WRITE 0x3
|
||||
#define REQUEST_POLL_RC 0x4
|
||||
#define REQUEST_JUMPRAM 0x8
|
||||
#define REQUEST_SET_CLOCK 0xB
|
||||
#define REQUEST_SET_GPIO 0xC
|
||||
#define REQUEST_ENABLE_VIDEO 0xF
|
||||
// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
|
||||
// 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
|
||||
// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " )
|
||||
#define REQUEST_GET_VERSION 0x15
|
||||
|
||||
struct dib0700_state {
|
||||
u8 channel_state;
|
||||
u16 mt2060_if1[2];
|
||||
|
||||
u8 is_dib7000pc;
|
||||
};
|
||||
|
||||
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
|
||||
extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
|
||||
extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
|
||||
extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
|
||||
extern struct i2c_algorithm dib0700_i2c_algo;
|
||||
|
|
|
@ -135,14 +135,46 @@ struct i2c_algorithm dib0700_i2c_algo = {
|
|||
int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
|
||||
struct dvb_usb_device_description **desc, int *cold)
|
||||
{
|
||||
u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C
|
||||
*cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
|
||||
buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3;
|
||||
u8 b[16];
|
||||
s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0),
|
||||
REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT);
|
||||
|
||||
deb_info("FW GET_VERSION length: %d\n",ret);
|
||||
|
||||
*cold = ret <= 0;
|
||||
|
||||
deb_info("cold: %d\n", *cold);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
|
||||
u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv,
|
||||
u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
|
||||
{
|
||||
u8 b[10];
|
||||
b[0] = REQUEST_SET_CLOCK;
|
||||
b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4);
|
||||
b[2] = (pll_prediv >> 8) & 0xff; // MSB
|
||||
b[3] = pll_prediv & 0xff; // LSB
|
||||
b[4] = (pll_loopdiv >> 8) & 0xff; // MSB
|
||||
b[5] = pll_loopdiv & 0xff; // LSB
|
||||
b[6] = (free_div >> 8) & 0xff; // MSB
|
||||
b[7] = free_div & 0xff; // LSB
|
||||
b[8] = (dsuScaler >> 8) & 0xff; // MSB
|
||||
b[9] = dsuScaler & 0xff; // LSB
|
||||
|
||||
return dib0700_ctrl_wr(d, b, 10);
|
||||
}
|
||||
|
||||
int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
|
||||
{
|
||||
switch (clk_MHz) {
|
||||
case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break;
|
||||
default: return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib0700_jumpram(struct usb_device *udev, u32 address)
|
||||
{
|
||||
int ret, actlen;
|
||||
|
@ -197,7 +229,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
|
|||
/* start the firmware */
|
||||
if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) {
|
||||
info("firmware started successfully.");
|
||||
msleep(100);
|
||||
msleep(500);
|
||||
}
|
||||
} else
|
||||
ret = -EIO;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include "dib0700.h"
|
||||
|
||||
#include "dib3000mc.h"
|
||||
#include "dib7000m.h"
|
||||
#include "dib7000p.h"
|
||||
#include "mt2060.h"
|
||||
|
||||
static int force_lna_activation;
|
||||
|
@ -95,37 +97,189 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
}
|
||||
|
||||
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
|
||||
/*
|
||||
static struct mt2060_config stk7000p_mt2060_config = {
|
||||
0x60
|
||||
static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
|
||||
BAND_UHF | BAND_VHF, // band_caps
|
||||
|
||||
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
|
||||
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
|
||||
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
|
||||
|
||||
712, // inv_gain
|
||||
41, // time_stabiliz
|
||||
|
||||
0, // alpha_level
|
||||
118, // thlock
|
||||
|
||||
0, // wbd_inv
|
||||
4095, // wbd_ref
|
||||
0, // wbd_sel
|
||||
0, // wbd_alpha
|
||||
|
||||
42598, // agc1_max
|
||||
17694, // agc1_min
|
||||
45875, // agc2_max
|
||||
2621, // agc2_min
|
||||
0, // agc1_pt1
|
||||
76, // agc1_pt2
|
||||
139, // agc1_pt3
|
||||
52, // agc1_slope1
|
||||
59, // agc1_slope2
|
||||
107, // agc2_pt1
|
||||
172, // agc2_pt2
|
||||
57, // agc2_slope1
|
||||
70, // agc2_slope2
|
||||
|
||||
21, // alpha_mant
|
||||
25, // alpha_exp
|
||||
28, // beta_mant
|
||||
48, // beta_exp
|
||||
|
||||
1, // perform_agc_softsplit
|
||||
{ 0, // split_min
|
||||
107, // split_max
|
||||
51800, // global_split_min
|
||||
24700 // global_split_max
|
||||
},
|
||||
};
|
||||
|
||||
static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = {
|
||||
BAND_UHF | BAND_VHF,
|
||||
|
||||
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
|
||||
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
|
||||
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
|
||||
|
||||
712, // inv_gain
|
||||
41, // time_stabiliz
|
||||
|
||||
0, // alpha_level
|
||||
118, // thlock
|
||||
|
||||
0, // wbd_inv
|
||||
4095, // wbd_ref
|
||||
0, // wbd_sel
|
||||
0, // wbd_alpha
|
||||
|
||||
42598, // agc1_max
|
||||
16384, // agc1_min
|
||||
42598, // agc2_max
|
||||
0, // agc2_min
|
||||
|
||||
0, // agc1_pt1
|
||||
137, // agc1_pt2
|
||||
255, // agc1_pt3
|
||||
|
||||
0, // agc1_slope1
|
||||
255, // agc1_slope2
|
||||
|
||||
0, // agc2_pt1
|
||||
0, // agc2_pt2
|
||||
|
||||
0, // agc2_slope1
|
||||
41, // agc2_slope2
|
||||
|
||||
15, // alpha_mant
|
||||
25, // alpha_exp
|
||||
|
||||
28, // beta_mant
|
||||
48, // beta_exp
|
||||
|
||||
0, // perform_agc_softsplit
|
||||
};
|
||||
|
||||
static struct dibx000_bandwidth_config stk7700p_pll_config = {
|
||||
60000, 30000, // internal, sampling
|
||||
1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
|
||||
0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
|
||||
(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
|
||||
60258167, // ifreq
|
||||
20452225, // timf
|
||||
};
|
||||
|
||||
static struct dib7000m_config stk7700p_dib7000m_config = {
|
||||
.dvbt_mode = 1,
|
||||
.output_mpeg2_in_188_bytes = 1,
|
||||
.quartz_direct = 1,
|
||||
|
||||
.agc_config_count = 1,
|
||||
.agc = &stk7700p_7000m_mt2060_agc_config,
|
||||
.bw = &stk7700p_pll_config,
|
||||
|
||||
.gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
|
||||
.gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
|
||||
.gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
|
||||
};
|
||||
|
||||
static struct dib7000p_config stk7700p_dib7000p_config = {
|
||||
.output_mpeg2_in_188_bytes = 1,
|
||||
|
||||
.agc = &stk7700p_7000p_mt2060_agc_config,
|
||||
.bw = &stk7700p_pll_config,
|
||||
|
||||
.gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
|
||||
.gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
|
||||
.gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
|
||||
};
|
||||
*/
|
||||
|
||||
static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dib0700_state *st = adap->dev->priv;
|
||||
/* unless there is no real power management in DVB - we leave the device on GPIO6 */
|
||||
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
|
||||
|
||||
// adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18);
|
||||
return 0;
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
|
||||
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(50);
|
||||
|
||||
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10);
|
||||
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
|
||||
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
|
||||
dib0700_ctrl_clock(adap->dev, 72, 1);
|
||||
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100);
|
||||
|
||||
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
|
||||
|
||||
st->mt2060_if1[0] = 1220;
|
||||
|
||||
if (dib7000pc_detection(&adap->dev->i2c_adap)) {
|
||||
adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
|
||||
st->is_dib7000pc = 1;
|
||||
} else
|
||||
adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
|
||||
|
||||
return adap->fe == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static struct mt2060_config stk7700p_mt2060_config = {
|
||||
0x60
|
||||
};
|
||||
|
||||
static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
// tun_i2c = dib7000m_get_tuner_i2c_master(adap->fe, 1);
|
||||
// return mt2060_attach(adap->fe, tun_i2c, &stk3000p_mt2060_config, if1);
|
||||
return 0;
|
||||
struct dib0700_state *st = adap->dev->priv;
|
||||
struct i2c_adapter *tun_i2c;
|
||||
|
||||
if (st->is_dib7000pc)
|
||||
tun_i2c = dib7000p_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
|
||||
else
|
||||
tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
|
||||
|
||||
return dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk7700p_mt2060_config,
|
||||
st->mt2060_if1[0]) == NULL ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
struct usb_device_id dib0700_usb_id_table[] = {
|
||||
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P) },
|
||||
{ USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) },
|
||||
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
|
||||
{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
|
||||
{ USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_VIDEOMATE_U500) },
|
||||
{ USB_DEVICE(USB_VID_UNIWILL, USB_PID_UNIWILL_STK7700P) },
|
||||
{ USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
|
||||
{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
|
||||
{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
|
||||
|
@ -167,20 +321,32 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.num_device_descs = 3,
|
||||
.num_device_descs = 6,
|
||||
.devices = {
|
||||
{ "DiBcom STK7700P reference design",
|
||||
{ &dib0700_usb_id_table[0], NULL },
|
||||
{ &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Hauppauge Nova-T Stick",
|
||||
{ &dib0700_usb_id_table[3], NULL },
|
||||
{ &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "AVerMedia AVerTV DVB-T Volar",
|
||||
{ &dib0700_usb_id_table[4], NULL },
|
||||
{ &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Compro Videomate U500",
|
||||
{ &dib0700_usb_id_table[6], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Uniwill STK7700P based (Hama and others)",
|
||||
{ &dib0700_usb_id_table[7], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
{ "Leadtek Winfast DTV Dongle (STK7700P based)",
|
||||
{ &dib0700_usb_id_table[8], NULL },
|
||||
{ NULL },
|
||||
}
|
||||
}
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
|
@ -202,7 +368,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ "Hauppauge Nova-T 500 Dual DVB-T",
|
||||
{ &dib0700_usb_id_table[1], &dib0700_usb_id_table[2], NULL },
|
||||
{ &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
}
|
||||
|
|
|
@ -163,23 +163,23 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
|
|||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 16,
|
||||
|
||||
.streaming_ctrl = dibusb_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||
.tuner_attach = dibusb_tuner_probe_and_attach,
|
||||
.streaming_ctrl = dibusb_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||
.tuner_attach = dibusb_tuner_probe_and_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 7,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
},
|
||||
|
@ -248,23 +248,23 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
|
|||
.caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
|
||||
.pid_filter_count = 16,
|
||||
|
||||
.streaming_ctrl = dibusb_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||
.tuner_attach = dibusb_tuner_probe_and_attach,
|
||||
.streaming_ctrl = dibusb_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||
.tuner_attach = dibusb_tuner_probe_and_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 7,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
},
|
||||
},
|
||||
|
@ -312,22 +312,23 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
|
|||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 16,
|
||||
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||
.tuner_attach = dibusb_thomson_tuner_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||
.tuner_attach = dibusb_thomson_tuner_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 7,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
},
|
||||
|
@ -369,22 +370,22 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
|
|||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 16,
|
||||
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||
.tuner_attach = dibusb_tuner_probe_and_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mb_frontend_attach,
|
||||
.tuner_attach = dibusb_tuner_probe_and_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 7,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
},
|
||||
|
|
|
@ -54,23 +54,23 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
|
|||
{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 32,
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mc_frontend_attach,
|
||||
.tuner_attach = dibusb_dib3000mc_tuner_attach,
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mc_frontend_attach,
|
||||
.tuner_attach = dibusb_dib3000mc_tuner_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 7,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
},
|
||||
|
|
|
@ -274,20 +274,20 @@ static struct dvb_usb_device_properties digitv_properties = {
|
|||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.frontend_attach = digitv_frontend_attach,
|
||||
.tuner_attach = digitv_tuner_attach,
|
||||
.frontend_attach = digitv_frontend_attach,
|
||||
.tuner_attach = digitv_tuner_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 7,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
.identify_state = digitv_identify_state,
|
||||
|
|
|
@ -268,20 +268,20 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
|
|||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
|
||||
.pid_filter_count = 15,
|
||||
|
||||
.streaming_ctrl = dtt200u_streaming_ctrl,
|
||||
.pid_filter = dtt200u_pid_filter,
|
||||
.frontend_attach = dtt200u_frontend_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.streaming_ctrl = dtt200u_streaming_ctrl,
|
||||
.pid_filter = dtt200u_pid_filter,
|
||||
.frontend_attach = dtt200u_frontend_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 7,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#define USB_VID_VISIONPLUS 0x13d3
|
||||
#define USB_VID_TWINHAN 0x1822
|
||||
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
|
||||
#define USB_VID_UNIWILL 0x1584
|
||||
#define USB_VID_WIDEVIEW 0x14aa
|
||||
|
||||
/* Product IDs */
|
||||
|
@ -46,6 +47,7 @@
|
|||
#define USB_PID_COMPRO_DVBU2000_WARM 0xd001
|
||||
#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
|
||||
#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
|
||||
#define USB_PID_COMPRO_VIDEOMATE_U500 0x1e78
|
||||
#define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064
|
||||
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
|
||||
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
|
||||
|
@ -53,7 +55,9 @@
|
|||
#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6
|
||||
#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
|
||||
#define USB_PID_DIBCOM_STK7700P 0x1e14
|
||||
#define USB_PID_DIBCOM_STK7700P_PC 0x1e78
|
||||
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
|
||||
#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_KWORLD_VSTREAM_COLD 0x17de
|
||||
|
@ -97,7 +101,9 @@
|
|||
#define USB_PID_HAUPPAUGE_NOVA_T_500 0x9941
|
||||
#define USB_PID_HAUPPAUGE_NOVA_T_500_2 0x9950
|
||||
#define USB_PID_HAUPPAUGE_NOVA_T_STICK 0x7050
|
||||
#define USB_PID_AVERMEDIA_VOLAR 0x1234
|
||||
#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2 0x7060
|
||||
#define USB_PID_AVERMEDIA_VOLAR 0xa807
|
||||
#define USB_PID_AVERMEDIA_VOLAR_2 0xb808
|
||||
#define USB_PID_NEBULA_DIGITV 0x0201
|
||||
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
|
||||
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
|
||||
|
@ -110,8 +116,8 @@
|
|||
#define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM 0xdb51
|
||||
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD 0xdb58
|
||||
#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM 0xdb59
|
||||
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
|
||||
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55
|
||||
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD 0xdb54
|
||||
#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM 0xdb55
|
||||
#define USB_PID_MEDION_MD95700 0x0932
|
||||
#define USB_PID_KYE_DVB_T_COLD 0x701e
|
||||
#define USB_PID_KYE_DVB_T_WARM 0x701f
|
||||
|
@ -125,7 +131,9 @@
|
|||
#define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7
|
||||
#define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025
|
||||
#define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026
|
||||
#define USB_PID_WINFAST_DTV_DONGLE_STK7700P 0x6f00
|
||||
#define USB_PID_GENPIX_8PSK_COLD 0x0200
|
||||
#define USB_PID_GENPIX_8PSK_WARM 0x0201
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -90,7 +90,9 @@ static void dvb_usb_read_remote_control(struct work_struct *work)
|
|||
|
||||
int dvb_usb_remote_init(struct dvb_usb_device *d)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
if (d->props.rc_key_map == NULL ||
|
||||
d->props.rc_query == NULL ||
|
||||
|
@ -100,23 +102,24 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
|
|||
usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
|
||||
strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
|
||||
|
||||
d->rc_input_dev = input_allocate_device();
|
||||
if (!d->rc_input_dev)
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
d->rc_input_dev->evbit[0] = BIT(EV_KEY);
|
||||
d->rc_input_dev->keycodesize = sizeof(unsigned char);
|
||||
d->rc_input_dev->keycodemax = KEY_MAX;
|
||||
d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver";
|
||||
d->rc_input_dev->phys = d->rc_phys;
|
||||
usb_to_input_id(d->udev, &d->rc_input_dev->id);
|
||||
d->rc_input_dev->cdev.dev = &d->udev->dev;
|
||||
input_dev->evbit[0] = BIT(EV_KEY);
|
||||
input_dev->keycodesize = sizeof(unsigned char);
|
||||
input_dev->keycodemax = KEY_MAX;
|
||||
input_dev->name = "IR-receiver inside an USB DVB receiver";
|
||||
input_dev->phys = d->rc_phys;
|
||||
usb_to_input_id(d->udev, &input_dev->id);
|
||||
input_dev->cdev.dev = &d->udev->dev;
|
||||
|
||||
/* set the bits for the keys */
|
||||
deb_rc("key map size: %d\n", d->props.rc_key_map_size);
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
|
||||
set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit);
|
||||
deb_rc("setting bit for event %d item %d\n",
|
||||
d->props.rc_key_map[i].event, i);
|
||||
set_bit(d->props.rc_key_map[i].event, input_dev->keybit);
|
||||
}
|
||||
|
||||
/* Start the remote-control polling. */
|
||||
|
@ -124,10 +127,16 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
|
|||
d->props.rc_interval = 100; /* default */
|
||||
|
||||
/* setting these two values to non-zero, we have to manage key repeats */
|
||||
d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval;
|
||||
d->rc_input_dev->rep[REP_DELAY] = d->props.rc_interval + 150;
|
||||
input_dev->rep[REP_PERIOD] = d->props.rc_interval;
|
||||
input_dev->rep[REP_DELAY] = d->props.rc_interval + 150;
|
||||
|
||||
input_register_device(d->rc_input_dev);
|
||||
err = input_register_device(input_dev);
|
||||
if (err) {
|
||||
input_free_device(input_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
d->rc_input_dev = input_dev;
|
||||
|
||||
INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
|
||||
|
||||
|
|
|
@ -194,19 +194,19 @@ static struct dvb_usb_device_properties gp8psk_properties = {
|
|||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.streaming_ctrl = gp8psk_streaming_ctrl,
|
||||
.frontend_attach = gp8psk_frontend_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.streaming_ctrl = gp8psk_streaming_ctrl,
|
||||
.frontend_attach = gp8psk_frontend_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 7,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 8192,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
.power_ctrl = gp8psk_power_ctrl,
|
||||
|
|
|
@ -163,23 +163,23 @@ static struct dvb_usb_device_properties nova_t_properties = {
|
|||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 32,
|
||||
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mc_frontend_attach,
|
||||
.tuner_attach = dibusb_dib3000mc_tuner_attach,
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.pid_filter = dibusb_pid_filter,
|
||||
.pid_filter_ctrl = dibusb_pid_filter_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mc_frontend_attach,
|
||||
.tuner_attach = dibusb_dib3000mc_tuner_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
|
|
270
drivers/media/dvb/dvb-usb/ttusb2.c
Normal file
270
drivers/media/dvb/dvb-usb/ttusb2.c
Normal file
|
@ -0,0 +1,270 @@
|
|||
/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
|
||||
* (e.g. Pinnacle 400e DVB-S USB2.0).
|
||||
*
|
||||
* The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes.
|
||||
*
|
||||
* TDA8263 + TDA10086
|
||||
*
|
||||
* I2C addresses:
|
||||
* 0x08 - LNBP21PD - LNB power supply
|
||||
* 0x0e - TDA10086 - Demodulator
|
||||
* 0x50 - FX2 eeprom
|
||||
* 0x60 - TDA8263 - Tuner
|
||||
* 0x78 ???
|
||||
*
|
||||
* Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
|
||||
* Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
|
||||
* Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, version 2.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
#define DVB_USB_LOG_PREFIX "ttusb2"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#include "ttusb2.h"
|
||||
|
||||
#include "tda826x.h"
|
||||
#include "tda10086.h"
|
||||
#include "lnbp21.h"
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_ttusb2_debug;
|
||||
#define deb_info(args...) dprintk(dvb_usb_ttusb2_debug,0x01,args)
|
||||
module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
|
||||
|
||||
struct ttusb2_state {
|
||||
u8 id;
|
||||
};
|
||||
|
||||
static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
|
||||
u8 *wbuf, int wlen, u8 *rbuf, int rlen)
|
||||
{
|
||||
struct ttusb2_state *st = d->priv;
|
||||
u8 s[wlen+4],r[64] = { 0 };
|
||||
int ret = 0;
|
||||
|
||||
memset(s,0,wlen+4);
|
||||
|
||||
s[0] = 0xaa;
|
||||
s[1] = ++st->id;
|
||||
s[2] = cmd;
|
||||
s[3] = wlen;
|
||||
memcpy(&s[4],wbuf,wlen);
|
||||
|
||||
ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0);
|
||||
|
||||
if (ret != 0 ||
|
||||
r[0] != 0x55 ||
|
||||
r[1] != s[1] ||
|
||||
r[2] != cmd ||
|
||||
(rlen > 0 && r[3] != rlen)) {
|
||||
warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (rlen > 0)
|
||||
memcpy(rbuf, &r[4], rlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
static u8 obuf[60], ibuf[60];
|
||||
int i,read;
|
||||
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
if (num > 2)
|
||||
warn("more than 2 i2c messages at a time is not handled yet. TODO.");
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
|
||||
|
||||
obuf[0] = (msg[i].addr << 1) | read;
|
||||
obuf[1] = msg[i].len;
|
||||
|
||||
/* read request */
|
||||
if (read)
|
||||
obuf[2] = msg[i+1].len;
|
||||
else
|
||||
obuf[2] = 0;
|
||||
|
||||
memcpy(&obuf[3],msg[i].buf,msg[i].len);
|
||||
|
||||
if (ttusb2_msg(d, CMD_I2C_XFER, obuf, msg[i].len+3, ibuf, obuf[2] + 3) < 0) {
|
||||
err("i2c transfer failed.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (read) {
|
||||
memcpy(msg[i+1].buf,&ibuf[3],msg[i+1].len);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return i;
|
||||
}
|
||||
|
||||
static u32 ttusb2_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm ttusb2_i2c_algo = {
|
||||
.master_xfer = ttusb2_i2c_xfer,
|
||||
.functionality = ttusb2_i2c_func,
|
||||
};
|
||||
|
||||
/* Callbacks for DVB USB */
|
||||
static int ttusb2_identify_state (struct usb_device *udev, struct
|
||||
dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
|
||||
int *cold)
|
||||
{
|
||||
*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff)
|
||||
{
|
||||
u8 b = onoff;
|
||||
ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0);
|
||||
return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
static struct tda10086_config tda10086_config = {
|
||||
.demod_address = 0x0e,
|
||||
.invert = 0,
|
||||
};
|
||||
|
||||
static int ttusb2_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (usb_set_interface(adap->dev->udev,0,3) < 0)
|
||||
err("set interface to alts=3 failed");
|
||||
|
||||
if ((adap->fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
|
||||
deb_info("TDA10086 attach failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ttusb2_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
if (dvb_attach(tda826x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
|
||||
deb_info("TDA8263 attach failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (dvb_attach(lnbp21_attach, adap->fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
|
||||
deb_info("LNBP21 attach failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DVB USB Driver stuff */
|
||||
static struct dvb_usb_device_properties ttusb2_properties;
|
||||
|
||||
static int ttusb2_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return dvb_usb_device_init(intf,&ttusb2_properties,THIS_MODULE,NULL);
|
||||
}
|
||||
|
||||
static struct usb_device_id ttusb2_table [] = {
|
||||
{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE (usb, ttusb2_table);
|
||||
|
||||
static struct dvb_usb_device_properties ttusb2_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
|
||||
.usb_ctrl = CYPRESS_FX2,
|
||||
.firmware = "dvb-usb-pctv-400e-01.fw",
|
||||
|
||||
.size_of_priv = sizeof(struct ttusb2_state),
|
||||
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.streaming_ctrl = NULL, // ttusb2_streaming_ctrl,
|
||||
|
||||
.frontend_attach = ttusb2_frontend_attach,
|
||||
.tuner_attach = ttusb2_tuner_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_ISOC,
|
||||
.count = 5,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.isoc = {
|
||||
.framesperurb = 4,
|
||||
.framesize = 940,
|
||||
.interval = 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
.power_ctrl = ttusb2_power_ctrl,
|
||||
.identify_state = ttusb2_identify_state,
|
||||
|
||||
.i2c_algo = &ttusb2_i2c_algo,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ "Pinnacle 400e DVB-S USB2.0",
|
||||
{ &ttusb2_table[0], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static struct usb_driver ttusb2_driver = {
|
||||
.name = "dvb_usb_ttusb2",
|
||||
.probe = ttusb2_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = ttusb2_table,
|
||||
};
|
||||
|
||||
/* module stuff */
|
||||
static int __init ttusb2_module_init(void)
|
||||
{
|
||||
int result;
|
||||
if ((result = usb_register(&ttusb2_driver))) {
|
||||
err("usb_register failed. Error number %d",result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ttusb2_module_exit(void)
|
||||
{
|
||||
/* deregister this driver from the USB subsystem */
|
||||
usb_deregister(&ttusb2_driver);
|
||||
}
|
||||
|
||||
module_init (ttusb2_module_init);
|
||||
module_exit (ttusb2_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||
MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
70
drivers/media/dvb/dvb-usb/ttusb2.h
Normal file
70
drivers/media/dvb/dvb-usb/ttusb2.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
|
||||
* (e.g. Pinnacle 400e DVB-S USB2.0).
|
||||
*
|
||||
* Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
|
||||
* Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
|
||||
* Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.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, version 2.
|
||||
*
|
||||
* see Documentation/dvb/README.dvb-usb for more information
|
||||
*/
|
||||
#ifndef _DVB_USB_TTUSB2_H_
|
||||
#define _DVB_USB_TTUSB2_H_
|
||||
|
||||
/* TTUSB protocol
|
||||
*
|
||||
* always to messages (out/in)
|
||||
* out message:
|
||||
* 0xaa <id> <cmdbyte> <datalen> <data...>
|
||||
*
|
||||
* in message (complete block is always 0x40 bytes long)
|
||||
* 0x55 <id> <cmdbyte> <datalen> <data...>
|
||||
*
|
||||
* id is incremented for each transaction
|
||||
*/
|
||||
|
||||
#define CMD_DSP_DOWNLOAD 0x13
|
||||
/* out data: <byte>[28]
|
||||
* last block must be empty */
|
||||
|
||||
#define CMD_DSP_BOOT 0x14
|
||||
/* out data: nothing */
|
||||
|
||||
#define CMD_POWER 0x15
|
||||
/* out data: <on=1/off=0> */
|
||||
|
||||
#define CMD_LNB 0x16
|
||||
/* out data: <power=1> <18V=0,13V=1> <tone> <??=1> <??=1> */
|
||||
|
||||
#define CMD_GET_VERSION 0x17
|
||||
/* in data: <version_byte>[5] */
|
||||
|
||||
#define CMD_DISEQC 0x18
|
||||
/* out data: <master=0xff/burst=??> <cmdlen> <cmdbytes>[cmdlen] */
|
||||
|
||||
#define CMD_PID_ENABLE 0x22
|
||||
/* out data: <index> <type: ts=1/sec=2> <pid msb> <pid lsb> */
|
||||
|
||||
#define CMD_PID_DISABLE 0x23
|
||||
/* out data: <index> */
|
||||
|
||||
#define CMD_FILTER_ENABLE 0x24
|
||||
/* out data: <index> <pid_idx> <filter>[12] <mask>[12] */
|
||||
|
||||
#define CMD_FILTER_DISABLE 0x25
|
||||
/* out data: <index> */
|
||||
|
||||
#define CMD_GET_DSP_VERSION 0x26
|
||||
/* in data: <version_byte>[28] */
|
||||
|
||||
#define CMD_I2C_XFER 0x31
|
||||
/* out data: <addr << 1> <sndlen> <rcvlen> <data>[sndlen]
|
||||
* in data: <addr << 1> <sndlen> <rcvlen> <data>[rcvlen] */
|
||||
|
||||
#define CMD_I2C_BITRATE 0x32
|
||||
/* out data: <default=0> */
|
||||
|
||||
#endif
|
|
@ -99,21 +99,21 @@ static struct dvb_usb_device_properties umt_properties = {
|
|||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.frontend_attach = umt_mt352_frontend_attach,
|
||||
.tuner_attach = umt_tuner_attach,
|
||||
.streaming_ctrl = dibusb2_0_streaming_ctrl,
|
||||
.frontend_attach = umt_mt352_frontend_attach,
|
||||
.tuner_attach = umt_tuner_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 20,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 512,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 20,
|
||||
.endpoint = 0x06,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 512,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
}
|
||||
|
|
|
@ -275,22 +275,22 @@ static struct dvb_usb_device_properties vp702x_properties = {
|
|||
.caps = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
|
||||
|
||||
.streaming_ctrl = vp702x_streaming_ctrl,
|
||||
.frontend_attach = vp702x_frontend_attach,
|
||||
.frontend_attach = vp702x_frontend_attach,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 10,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.size_of_priv = sizeof(struct vp702x_state),
|
||||
}
|
||||
},
|
||||
},
|
||||
.read_mac_address = vp702x_read_mac_addr,
|
||||
|
||||
.rc_key_map = vp702x_rc_keys,
|
||||
|
|
|
@ -125,7 +125,25 @@ static struct dvb_usb_rc_key vp7045_rc_keys[] = {
|
|||
{ 0x00, 0x00, KEY_TAB }, /* Tab */
|
||||
{ 0x00, 0x48, KEY_INFO }, /* Preview */
|
||||
{ 0x00, 0x04, KEY_LIST }, /* RecordList */
|
||||
{ 0x00, 0x0f, KEY_TEXT } /* Teletext */
|
||||
{ 0x00, 0x0f, KEY_TEXT }, /* Teletext */
|
||||
{ 0x00, 0x41, KEY_PREVIOUSSONG },
|
||||
{ 0x00, 0x42, KEY_NEXTSONG },
|
||||
{ 0x00, 0x4b, KEY_UP },
|
||||
{ 0x00, 0x51, KEY_DOWN },
|
||||
{ 0x00, 0x4e, KEY_LEFT },
|
||||
{ 0x00, 0x52, KEY_RIGHT },
|
||||
{ 0x00, 0x4f, KEY_ENTER },
|
||||
{ 0x00, 0x13, KEY_CANCEL },
|
||||
{ 0x00, 0x4a, KEY_CLEAR },
|
||||
{ 0x00, 0x54, KEY_PRINT }, /* Capture */
|
||||
{ 0x00, 0x43, KEY_SUBTITLE }, /* Subtitle/CC */
|
||||
{ 0x00, 0x08, KEY_VIDEO }, /* A/V */
|
||||
{ 0x00, 0x07, KEY_SLEEP }, /* Hibernate */
|
||||
{ 0x00, 0x45, KEY_ZOOM }, /* Zoom+ */
|
||||
{ 0x00, 0x18, KEY_RED},
|
||||
{ 0x00, 0x53, KEY_GREEN},
|
||||
{ 0x00, 0x5e, KEY_YELLOW},
|
||||
{ 0x00, 0x5f, KEY_BLUE}
|
||||
};
|
||||
|
||||
static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
|
@ -217,18 +235,18 @@ static struct dvb_usb_device_properties vp7045_properties = {
|
|||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
{
|
||||
.frontend_attach = vp7045_frontend_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.frontend_attach = vp7045_frontend_attach,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
.count = 7,
|
||||
.endpoint = 0x02,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
.power_ctrl = vp7045_power_ctrl,
|
||||
|
|
|
@ -172,6 +172,22 @@ config DVB_DIB3000MC
|
|||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_DIB7000M
|
||||
tristate "DiBcom 7000MA/MB/PA/PB/MC"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_DIB7000P
|
||||
tristate "DiBcom 7000PC"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
comment "DVB-C (cable) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
@ -281,6 +297,14 @@ config DVB_TUNER_MT2060
|
|||
help
|
||||
A driver for the silicon IF tuner MT2060 from Microtune.
|
||||
|
||||
config DVB_TUNER_LGH06XF
|
||||
tristate "LG TDVS-H06xF ATSC tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
select DVB_PLL
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A driver for the LG TDVS-H06xF ATSC tuner family.
|
||||
|
||||
comment "Miscellaneous devices"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ obj-$(CONFIG_DVB_TDA8083) += tda8083.o
|
|||
obj-$(CONFIG_DVB_L64781) += l64781.o
|
||||
obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
|
||||
obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_MT312) += mt312.o
|
||||
obj-$(CONFIG_DVB_VES1820) += ves1820.o
|
||||
obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
|
||||
|
@ -37,3 +39,4 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
|
|||
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
|
||||
obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
|
||||
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
|
||||
obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o
|
||||
|
|
|
@ -511,16 +511,11 @@ static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000
|
|||
|
||||
|
||||
/* a channel for autosearch */
|
||||
reg = 0;
|
||||
if (chan->nfft == -1 && chan->guard == -1) reg = 7;
|
||||
if (chan->nfft == -1 && chan->guard != -1) reg = 2;
|
||||
if (chan->nfft != -1 && chan->guard == -1) reg = 3;
|
||||
|
||||
fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2;
|
||||
fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2;
|
||||
fchan.vit_hrch = 0; fchan.vit_select_hp = 1;
|
||||
|
||||
dib3000mc_set_channel_cfg(state, &fchan, reg);
|
||||
dib3000mc_set_channel_cfg(state, &fchan, 7);
|
||||
|
||||
reg = dib3000mc_read_word(state, 0);
|
||||
dib3000mc_write_word(state, 0, reg | (1 << 8));
|
||||
|
|
1191
drivers/media/dvb/frontends/dib7000m.c
Normal file
1191
drivers/media/dvb/frontends/dib7000m.c
Normal file
File diff suppressed because it is too large
Load diff
51
drivers/media/dvb/frontends/dib7000m.h
Normal file
51
drivers/media/dvb/frontends/dib7000m.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#ifndef DIB7000M_H
|
||||
#define DIB7000M_H
|
||||
|
||||
#include "dibx000_common.h"
|
||||
|
||||
struct dib7000m_config {
|
||||
u8 dvbt_mode;
|
||||
u8 output_mpeg2_in_188_bytes;
|
||||
u8 hostbus_diversity;
|
||||
u8 tuner_is_baseband;
|
||||
u8 mobile_mode;
|
||||
int (*update_lna) (struct dvb_frontend *, u16 agc_global);
|
||||
|
||||
u8 agc_config_count;
|
||||
struct dibx000_agc_config *agc;
|
||||
|
||||
struct dibx000_bandwidth_config *bw;
|
||||
|
||||
#define DIB7000M_GPIO_DEFAULT_DIRECTIONS 0xffff
|
||||
u16 gpio_dir;
|
||||
#define DIB7000M_GPIO_DEFAULT_VALUES 0x0000
|
||||
u16 gpio_val;
|
||||
#define DIB7000M_GPIO_PWM_POS0(v) ((v & 0xf) << 12)
|
||||
#define DIB7000M_GPIO_PWM_POS1(v) ((v & 0xf) << 8 )
|
||||
#define DIB7000M_GPIO_PWM_POS2(v) ((v & 0xf) << 4 )
|
||||
#define DIB7000M_GPIO_PWM_POS3(v) (v & 0xf)
|
||||
#define DIB7000M_GPIO_DEFAULT_PWM_POS 0xffff
|
||||
u16 gpio_pwm_pos;
|
||||
|
||||
u16 pwm_freq_div;
|
||||
|
||||
u8 quartz_direct;
|
||||
|
||||
u8 input_clk_is_div_2;
|
||||
|
||||
int (*agc_control) (struct dvb_frontend *, u8 before);
|
||||
};
|
||||
|
||||
#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);
|
||||
|
||||
/* TODO
|
||||
extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
|
||||
extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod);
|
||||
extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
|
||||
extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod);
|
||||
*/
|
||||
|
||||
#endif
|
1019
drivers/media/dvb/frontends/dib7000p.c
Normal file
1019
drivers/media/dvb/frontends/dib7000p.c
Normal file
File diff suppressed because it is too large
Load diff
46
drivers/media/dvb/frontends/dib7000p.h
Normal file
46
drivers/media/dvb/frontends/dib7000p.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef DIB7000P_H
|
||||
#define DIB7000P_H
|
||||
|
||||
#include "dibx000_common.h"
|
||||
|
||||
struct dib7000p_config {
|
||||
u8 output_mpeg2_in_188_bytes;
|
||||
u8 hostbus_diversity;
|
||||
u8 tuner_is_baseband;
|
||||
int (*update_lna) (struct dvb_frontend *, u16 agc_global);
|
||||
|
||||
struct dibx000_agc_config *agc;
|
||||
struct dibx000_bandwidth_config *bw;
|
||||
|
||||
#define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff
|
||||
u16 gpio_dir;
|
||||
#define DIB7000P_GPIO_DEFAULT_VALUES 0x0000
|
||||
u16 gpio_val;
|
||||
#define DIB7000P_GPIO_PWM_POS0(v) ((v & 0xf) << 12)
|
||||
#define DIB7000P_GPIO_PWM_POS1(v) ((v & 0xf) << 8 )
|
||||
#define DIB7000P_GPIO_PWM_POS2(v) ((v & 0xf) << 4 )
|
||||
#define DIB7000P_GPIO_PWM_POS3(v) (v & 0xf)
|
||||
#define DIB7000P_GPIO_DEFAULT_PWM_POS 0xffff
|
||||
u16 gpio_pwm_pos;
|
||||
|
||||
u16 pwm_freq_div;
|
||||
|
||||
u8 quartz_direct;
|
||||
|
||||
int (*agc_control) (struct dvb_frontend *, u8 before);
|
||||
};
|
||||
|
||||
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
|
||||
|
||||
extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
|
||||
extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
|
||||
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
|
||||
|
||||
/* TODO
|
||||
extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
|
||||
extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod);
|
||||
extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
|
||||
extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod);
|
||||
*/
|
||||
|
||||
#endif
|
|
@ -32,6 +32,13 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
|
|||
#define BAND_LBAND 0x01
|
||||
#define BAND_UHF 0x02
|
||||
#define BAND_VHF 0x04
|
||||
#define BAND_SBAND 0x08
|
||||
#define BAND_FM 0x10
|
||||
|
||||
#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \
|
||||
(freq_kHz) <= 250000 ? BAND_VHF : \
|
||||
(freq_kHz) <= 863000 ? BAND_UHF : \
|
||||
(freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND )
|
||||
|
||||
struct dibx000_agc_config {
|
||||
/* defines the capabilities of this AGC-setting - using the BAND_-defines*/
|
||||
|
@ -129,6 +136,7 @@ enum dibx000_adc_states {
|
|||
|
||||
/* I hope I can get rid of the following kludge in the near future */
|
||||
struct dibx000_ofdm_channel {
|
||||
u32 RF_kHz;
|
||||
u8 Bw;
|
||||
s16 nfft;
|
||||
s16 guard;
|
||||
|
@ -138,9 +146,11 @@ struct dibx000_ofdm_channel {
|
|||
s16 vit_alpha;
|
||||
s16 vit_code_rate_hp;
|
||||
s16 vit_code_rate_lp;
|
||||
u8 intlv_native;
|
||||
};
|
||||
|
||||
#define FEP2DIB(fep,ch) \
|
||||
(ch)->RF_kHz = (fep)->frequency / 1000; \
|
||||
(ch)->Bw = (fep)->u.ofdm.bandwidth; \
|
||||
(ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \
|
||||
(ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \
|
||||
|
@ -149,7 +159,8 @@ struct dibx000_ofdm_channel {
|
|||
(ch)->vit_select_hp = 1; \
|
||||
(ch)->vit_alpha = 1; \
|
||||
(ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \
|
||||
(ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP;
|
||||
(ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \
|
||||
(ch)->intlv_native = 1;
|
||||
|
||||
#define INIT_OFDM_CHANNEL(ch) do {\
|
||||
(ch)->Bw = 0; \
|
||||
|
|
|
@ -472,14 +472,14 @@ int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
|||
printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
|
||||
desc->name, div, buf[0], buf[1], buf[2], buf[3]);
|
||||
|
||||
return 0;
|
||||
// calculate the frequency we set it to
|
||||
return (div * desc->entries[i].stepsize) - desc->entries[i].offset;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_pll_configure);
|
||||
|
||||
static int dvb_pll_release(struct dvb_frontend *fe)
|
||||
{
|
||||
if (fe->tuner_priv)
|
||||
kfree(fe->tuner_priv);
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -489,7 +489,8 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
|
|||
struct dvb_pll_priv *priv = fe->tuner_priv;
|
||||
u8 buf[4];
|
||||
struct i2c_msg msg =
|
||||
{ .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
|
||||
{ .addr = priv->pll_i2c_address, .flags = 0,
|
||||
.buf = buf, .len = sizeof(buf) };
|
||||
int i;
|
||||
int result;
|
||||
|
||||
|
@ -517,16 +518,16 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
|
||||
static int dvb_pll_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct dvb_pll_priv *priv = fe->tuner_priv;
|
||||
u8 buf[4];
|
||||
struct i2c_msg msg =
|
||||
{ .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
|
||||
{ .addr = priv->pll_i2c_address, .flags = 0,
|
||||
.buf = buf, .len = sizeof(buf) };
|
||||
int result;
|
||||
u32 div;
|
||||
int i;
|
||||
u32 bandwidth = 0;
|
||||
u32 bandwidth = 0, frequency = 0;
|
||||
|
||||
if (priv->i2c == NULL)
|
||||
return -EINVAL;
|
||||
|
@ -536,8 +537,11 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
|
|||
bandwidth = params->u.ofdm.bandwidth;
|
||||
}
|
||||
|
||||
if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0)
|
||||
if ((result = dvb_pll_configure(priv->pll_desc, buf,
|
||||
params->frequency, bandwidth)) < 0)
|
||||
return result;
|
||||
else
|
||||
frequency = result;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
|
@ -545,26 +549,19 @@ static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
|
|||
return result;
|
||||
}
|
||||
|
||||
// calculate the frequency we set it to
|
||||
for (i = 0; i < priv->pll_desc->count; i++) {
|
||||
if (params->frequency > priv->pll_desc->entries[i].limit)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
|
||||
priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
|
||||
priv->frequency = frequency;
|
||||
priv->bandwidth = bandwidth;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len)
|
||||
static int dvb_pll_calc_regs(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params,
|
||||
u8 *buf, int buf_len)
|
||||
{
|
||||
struct dvb_pll_priv *priv = fe->tuner_priv;
|
||||
int result;
|
||||
u32 div;
|
||||
int i;
|
||||
u32 bandwidth = 0;
|
||||
u32 bandwidth = 0, frequency = 0;
|
||||
|
||||
if (buf_len < 5)
|
||||
return -EINVAL;
|
||||
|
@ -574,18 +571,15 @@ static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parame
|
|||
bandwidth = params->u.ofdm.bandwidth;
|
||||
}
|
||||
|
||||
if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0)
|
||||
if ((result = dvb_pll_configure(priv->pll_desc, buf+1,
|
||||
params->frequency, bandwidth)) < 0)
|
||||
return result;
|
||||
else
|
||||
frequency = result;
|
||||
|
||||
buf[0] = priv->pll_i2c_address;
|
||||
|
||||
// calculate the frequency we set it to
|
||||
for (i = 0; i < priv->pll_desc->count; i++) {
|
||||
if (params->frequency > priv->pll_desc->entries[i].limit)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
|
||||
priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
|
||||
priv->frequency = frequency;
|
||||
priv->bandwidth = bandwidth;
|
||||
|
||||
return 5;
|
||||
|
@ -614,10 +608,13 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = {
|
|||
.get_bandwidth = dvb_pll_get_bandwidth,
|
||||
};
|
||||
|
||||
struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
|
||||
struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
|
||||
struct i2c_adapter *i2c,
|
||||
struct dvb_pll_desc *desc)
|
||||
{
|
||||
u8 b1 [] = { 0 };
|
||||
struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 };
|
||||
struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD,
|
||||
.buf = b1, .len = 1 };
|
||||
struct dvb_pll_priv *priv = NULL;
|
||||
int ret;
|
||||
|
||||
|
@ -640,7 +637,9 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struc
|
|||
priv->i2c = i2c;
|
||||
priv->pll_desc = desc;
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops));
|
||||
memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
|
||||
sizeof(struct dvb_tuner_ops));
|
||||
|
||||
strncpy(fe->ops.tuner_ops.info.name, desc->name, 128);
|
||||
fe->ops.tuner_ops.info.frequency_min = desc->min;
|
||||
fe->ops.tuner_ops.info.frequency_min = desc->max;
|
||||
|
|
|
@ -48,7 +48,7 @@ extern struct dvb_pll_desc dvb_pll_philips_td1316;
|
|||
extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
|
||||
|
||||
extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
||||
u32 freq, int bandwidth);
|
||||
u32 freq, int bandwidth);
|
||||
|
||||
/**
|
||||
* Attach a dvb-pll to the supplied frontend structure.
|
||||
|
@ -59,6 +59,9 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
|||
* @param desc dvb_pll_desc to use.
|
||||
* @return Frontend pointer on success, NULL on failure
|
||||
*/
|
||||
extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
|
||||
extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
|
||||
int pll_addr,
|
||||
struct i2c_adapter *i2c,
|
||||
struct dvb_pll_desc *desc);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF
|
||||
*
|
||||
* 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 _LG_H06XF_H_
|
||||
#define _LG_H06XF_H_
|
||||
#include "dvb-pll.h"
|
||||
|
||||
static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap,
|
||||
struct dvb_frontend_parameters* params)
|
||||
{
|
||||
u8 buf[4];
|
||||
struct i2c_msg msg = { .addr = 0x61, .flags = 0,
|
||||
.buf = buf, .len = sizeof(buf) };
|
||||
int err;
|
||||
|
||||
dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
|
||||
printk(KERN_WARNING "lg_h06xf: %s error "
|
||||
"(addr %02x <- %02x, err = %i)\n",
|
||||
__FUNCTION__, buf[0], buf[1], err);
|
||||
if (err < 0)
|
||||
return err;
|
||||
else
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
/* Set the Auxiliary Byte. */
|
||||
buf[0] = buf[2];
|
||||
buf[0] &= ~0x20;
|
||||
buf[0] |= 0x18;
|
||||
buf[1] = 0x50;
|
||||
msg.len = 2;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
|
||||
printk(KERN_WARNING "lg_h06xf: %s error "
|
||||
"(addr %02x <- %02x, err = %i)\n",
|
||||
__FUNCTION__, buf[0], buf[1], err);
|
||||
if (err < 0)
|
||||
return err;
|
||||
else
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -31,9 +31,6 @@
|
|||
* Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
|
||||
* pcHDTV HD5500
|
||||
*
|
||||
* TODO:
|
||||
* signal strength always returns 0.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
@ -46,9 +43,13 @@
|
|||
#include <asm/byteorder.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_math.h"
|
||||
#include "lgdt330x_priv.h"
|
||||
#include "lgdt330x.h"
|
||||
|
||||
/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
|
||||
/* #define USE_EQMSE */
|
||||
|
||||
static int debug = 0;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
|
||||
|
@ -68,6 +69,7 @@ struct lgdt330x_state
|
|||
|
||||
/* Demodulator private data */
|
||||
fe_modulation_t current_modulation;
|
||||
u32 snr; /* Result of last SNR calculation */
|
||||
|
||||
/* Tuner private data */
|
||||
u32 current_frequency;
|
||||
|
@ -302,10 +304,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
|
|||
static u8 lgdt3303_8vsb_44_data[] = {
|
||||
0x04, 0x00,
|
||||
0x0d, 0x40,
|
||||
0x0e, 0x87,
|
||||
0x0f, 0x8e,
|
||||
0x10, 0x01,
|
||||
0x47, 0x8b };
|
||||
0x0e, 0x87,
|
||||
0x0f, 0x8e,
|
||||
0x10, 0x01,
|
||||
0x47, 0x8b };
|
||||
|
||||
/*
|
||||
* Array of byte pairs <address, value>
|
||||
|
@ -435,9 +437,6 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
|||
/* Test signal does not exist flag */
|
||||
/* as well as the AGC lock flag. */
|
||||
*status |= FE_HAS_SIGNAL;
|
||||
} else {
|
||||
/* Without a signal all other status bits are meaningless */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -500,9 +499,6 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
|||
/* Test input signal does not exist flag */
|
||||
/* as well as the AGC lock flag. */
|
||||
*status |= FE_HAS_SIGNAL;
|
||||
} else {
|
||||
/* Without a signal all other status bits are meaningless */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Carrier Recovery Lock Status Register */
|
||||
|
@ -543,151 +539,150 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
|
||||
/* Calculate SNR estimation (scaled by 2^24)
|
||||
|
||||
8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM
|
||||
equations from LGDT3303 datasheet. VSB is the same between the '02
|
||||
and '03, so maybe QAM is too? Perhaps someone with a newer datasheet
|
||||
that has QAM information could verify?
|
||||
|
||||
For 8-VSB: (two ways, take your pick)
|
||||
LGDT3302:
|
||||
SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE)
|
||||
LGDT3303:
|
||||
SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE)
|
||||
LGDT3302 & LGDT3303:
|
||||
SNR_PT = 10 * log10(25 * 32^2 / PT_MSE) (we use this one)
|
||||
For 64-QAM:
|
||||
SNR = 10 * log10( 688128 / MSEQAM)
|
||||
For 256-QAM:
|
||||
SNR = 10 * log10( 696320 / MSEQAM)
|
||||
|
||||
We re-write the snr equation as:
|
||||
SNR * 2^24 = 10*(c - intlog10(MSE))
|
||||
Where for 256-QAM, c = log10(696320) * 2^24, and so on. */
|
||||
|
||||
static u32 calculate_snr(u32 mse, u32 c)
|
||||
{
|
||||
/* not directly available. */
|
||||
*strength = 0;
|
||||
return 0;
|
||||
if (mse == 0) /* No signal */
|
||||
return 0;
|
||||
|
||||
mse = intlog10(mse);
|
||||
if (mse > c) {
|
||||
/* Negative SNR, which is possible, but realisticly the
|
||||
demod will lose lock before the signal gets this bad. The
|
||||
API only allows for unsigned values, so just return 0 */
|
||||
return 0;
|
||||
}
|
||||
return 10*(c - mse);
|
||||
}
|
||||
|
||||
static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
|
||||
{
|
||||
#ifdef SNR_IN_DB
|
||||
/*
|
||||
* Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise)
|
||||
* and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker
|
||||
* respectively. The following tables are built on these formulas.
|
||||
* The usual definition is SNR = 20 log10(signal/noise)
|
||||
* If the specification is wrong the value retuned is 1/2 the actual SNR in db.
|
||||
*
|
||||
* This table is a an ordered list of noise values computed by the
|
||||
* formula from the spec sheet such that the index into the table
|
||||
* starting at 43 or 45 is the SNR value in db. There are duplicate noise
|
||||
* value entries at the beginning because the SNR varies more than
|
||||
* 1 db for a change of 1 digit in noise at very small values of noise.
|
||||
*
|
||||
* Examples from SNR_EQ table:
|
||||
* noise SNR
|
||||
* 0 43
|
||||
* 1 42
|
||||
* 2 39
|
||||
* 3 37
|
||||
* 4 36
|
||||
* 5 35
|
||||
* 6 34
|
||||
* 7 33
|
||||
* 8 33
|
||||
* 9 32
|
||||
* 10 32
|
||||
* 11 31
|
||||
* 12 31
|
||||
* 13 30
|
||||
*/
|
||||
|
||||
static const u32 SNR_EQ[] =
|
||||
{ 1, 2, 2, 2, 3, 3, 4, 4, 5, 7,
|
||||
9, 11, 13, 17, 21, 26, 33, 41, 52, 65,
|
||||
81, 102, 129, 162, 204, 257, 323, 406, 511, 644,
|
||||
810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433,
|
||||
8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323,
|
||||
80978, 101945, 128341, 161571, 203406, 256073, 0x40000
|
||||
};
|
||||
|
||||
static const u32 SNR_PH[] =
|
||||
{ 1, 2, 2, 2, 3, 3, 4, 5, 6, 8,
|
||||
10, 12, 15, 19, 23, 29, 37, 46, 58, 73,
|
||||
91, 115, 144, 182, 229, 288, 362, 456, 574, 722,
|
||||
909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216,
|
||||
9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151,
|
||||
90833, 114351, 143960, 181235, 228161, 0x080000
|
||||
};
|
||||
|
||||
static u8 buf[5];/* read data buffer */
|
||||
static u32 noise; /* noise value */
|
||||
static u32 snr_db; /* index into SNR_EQ[] */
|
||||
struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
|
||||
u8 buf[5]; /* read data buffer */
|
||||
u32 noise; /* noise value */
|
||||
u32 c; /* per-modulation SNR calculation constant */
|
||||
|
||||
/* read both equalizer and phase tracker noise data */
|
||||
i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
|
||||
|
||||
if (state->current_modulation == VSB_8) {
|
||||
/* Equalizer Mean-Square Error Register for VSB */
|
||||
switch(state->current_modulation) {
|
||||
case VSB_8:
|
||||
i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5);
|
||||
#ifdef USE_EQMSE
|
||||
/* Use Equalizer Mean-Square Error Register */
|
||||
/* SNR for ranges from -15.61 to +41.58 */
|
||||
noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
|
||||
|
||||
/*
|
||||
* Look up noise value in table.
|
||||
* A better search algorithm could be used...
|
||||
* watch out there are duplicate entries.
|
||||
*/
|
||||
for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) {
|
||||
if (noise < SNR_EQ[snr_db]) {
|
||||
*snr = 43 - snr_db;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Phase Tracker Mean-Square Error Register for QAM */
|
||||
noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
|
||||
|
||||
/* Look up noise value in table. */
|
||||
for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) {
|
||||
if (noise < SNR_PH[snr_db]) {
|
||||
*snr = 45 - snr_db;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
c = 69765745; /* log10(25*24^2)*2^24 */
|
||||
#else
|
||||
/* Return the raw noise value */
|
||||
static u8 buf[5];/* read data buffer */
|
||||
static u32 noise; /* noise value */
|
||||
struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
|
||||
|
||||
/* read both equalizer and pase tracker noise data */
|
||||
i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
|
||||
|
||||
if (state->current_modulation == VSB_8) {
|
||||
/* Phase Tracker Mean-Square Error Register for VSB */
|
||||
/* Use Phase Tracker Mean-Square Error Register */
|
||||
/* SNR for ranges from -13.11 to +44.08 */
|
||||
noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
|
||||
} else {
|
||||
|
||||
/* Carrier Recovery Mean-Square Error for QAM */
|
||||
i2c_read_demod_bytes(state, 0x1a, buf, 2);
|
||||
c = 73957994; /* log10(25*32^2)*2^24 */
|
||||
#endif
|
||||
break;
|
||||
case QAM_64:
|
||||
case QAM_256:
|
||||
i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
|
||||
noise = ((buf[0] & 3) << 8) | buf[1];
|
||||
c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
|
||||
/* log10(688128)*2^24 and log10(696320)*2^24 */
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
|
||||
__FUNCTION__);
|
||||
return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
|
||||
}
|
||||
|
||||
/* Small values for noise mean signal is better so invert noise */
|
||||
*snr = ~noise;
|
||||
#endif
|
||||
state->snr = calculate_snr(noise, c);
|
||||
*snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
|
||||
|
||||
dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
|
||||
dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
|
||||
state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
|
||||
{
|
||||
/* Return the raw noise value */
|
||||
static u8 buf[5];/* read data buffer */
|
||||
static u32 noise; /* noise value */
|
||||
struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
|
||||
u8 buf[5]; /* read data buffer */
|
||||
u32 noise; /* noise value */
|
||||
u32 c; /* per-modulation SNR calculation constant */
|
||||
|
||||
if (state->current_modulation == VSB_8) {
|
||||
|
||||
i2c_read_demod_bytes(state, 0x6e, buf, 5);
|
||||
/* Phase Tracker Mean-Square Error Register for VSB */
|
||||
switch(state->current_modulation) {
|
||||
case VSB_8:
|
||||
i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5);
|
||||
#ifdef USE_EQMSE
|
||||
/* Use Equalizer Mean-Square Error Register */
|
||||
/* SNR for ranges from -16.12 to +44.08 */
|
||||
noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2];
|
||||
c = 73957994; /* log10(25*32^2)*2^24 */
|
||||
#else
|
||||
/* Use Phase Tracker Mean-Square Error Register */
|
||||
/* SNR for ranges from -13.11 to +44.08 */
|
||||
noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
|
||||
} else {
|
||||
|
||||
/* Carrier Recovery Mean-Square Error for QAM */
|
||||
i2c_read_demod_bytes(state, 0x1a, buf, 2);
|
||||
c = 73957994; /* log10(25*32^2)*2^24 */
|
||||
#endif
|
||||
break;
|
||||
case QAM_64:
|
||||
case QAM_256:
|
||||
i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
|
||||
noise = (buf[0] << 8) | buf[1];
|
||||
c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
|
||||
/* log10(688128)*2^24 and log10(696320)*2^24 */
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
|
||||
__FUNCTION__);
|
||||
return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
|
||||
}
|
||||
|
||||
/* Small values for noise mean signal is better so invert noise */
|
||||
*snr = ~noise;
|
||||
state->snr = calculate_snr(noise, c);
|
||||
*snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
|
||||
|
||||
dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr);
|
||||
dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
|
||||
state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
|
||||
{
|
||||
/* Calculate Strength from SNR up to 35dB */
|
||||
/* Even though the SNR can go higher than 35dB, there is some comfort */
|
||||
/* factor in having a range of strong signals that can show at 100% */
|
||||
struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
|
||||
u16 snr;
|
||||
int ret;
|
||||
|
||||
ret = fe->ops.read_snr(fe, &snr);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
/* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
|
||||
/* scale the range 0 - 35*2^24 into 0 - 65535 */
|
||||
if (state->snr >= 8960 * 0x10000)
|
||||
*strength = 0xffff;
|
||||
else
|
||||
*strength = state->snr / 8960;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -51,14 +51,19 @@ enum I2C_REG {
|
|||
AGC_RFIF_ACC2= 0x3b,
|
||||
AGC_STATUS= 0x3f,
|
||||
SYNC_STATUS_VSB= 0x43,
|
||||
EQPH_ERR0= 0x47,
|
||||
EQ_ERR1= 0x48,
|
||||
EQ_ERR2= 0x49,
|
||||
PH_ERR1= 0x4a,
|
||||
PH_ERR2= 0x4b,
|
||||
DEMUX_CONTROL= 0x66,
|
||||
LGDT3302_EQPH_ERR0= 0x47,
|
||||
LGDT3302_EQ_ERR1= 0x48,
|
||||
LGDT3302_EQ_ERR2= 0x49,
|
||||
LGDT3302_PH_ERR1= 0x4a,
|
||||
LGDT3302_PH_ERR2= 0x4b,
|
||||
LGDT3302_PACKET_ERR_COUNTER1= 0x6a,
|
||||
LGDT3302_PACKET_ERR_COUNTER2= 0x6b,
|
||||
LGDT3303_EQPH_ERR0= 0x6e,
|
||||
LGDT3303_EQ_ERR1= 0x6f,
|
||||
LGDT3303_EQ_ERR2= 0x70,
|
||||
LGDT3303_PH_ERR1= 0x71,
|
||||
LGDT3303_PH_ERR2= 0x72,
|
||||
LGDT3303_PACKET_ERR_COUNTER1= 0x8b,
|
||||
LGDT3303_PACKET_ERR_COUNTER2= 0x8c,
|
||||
};
|
||||
|
|
134
drivers/media/dvb/frontends/lgh06xf.c
Normal file
134
drivers/media/dvb/frontends/lgh06xf.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* lgh06xf.c - ATSC Tuner support for LG TDVS-H06xF
|
||||
*
|
||||
* 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 "dvb-pll.h"
|
||||
#include "lgh06xf.h"
|
||||
|
||||
#define LG_H06XF_PLL_I2C_ADDR 0x61
|
||||
|
||||
struct lgh06xf_priv {
|
||||
struct i2c_adapter *i2c;
|
||||
u32 frequency;
|
||||
};
|
||||
|
||||
static int lgh06xf_release(struct dvb_frontend *fe)
|
||||
{
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lgh06xf_set_params(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters* params)
|
||||
{
|
||||
struct lgh06xf_priv *priv = fe->tuner_priv;
|
||||
u8 buf[4];
|
||||
struct i2c_msg msg = { .addr = LG_H06XF_PLL_I2C_ADDR, .flags = 0,
|
||||
.buf = buf, .len = sizeof(buf) };
|
||||
u32 frequency;
|
||||
int result;
|
||||
|
||||
if ((result = dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf,
|
||||
params->frequency, 0)) < 0)
|
||||
return result;
|
||||
else
|
||||
frequency = result;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
|
||||
printk(KERN_WARNING "lgh06xf: %s error "
|
||||
"(addr %02x <- %02x, result = %i)\n",
|
||||
__FUNCTION__, buf[0], buf[1], result);
|
||||
if (result < 0)
|
||||
return result;
|
||||
else
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
/* Set the Auxiliary Byte. */
|
||||
buf[0] = buf[2];
|
||||
buf[0] &= ~0x20;
|
||||
buf[0] |= 0x18;
|
||||
buf[1] = 0x50;
|
||||
msg.len = 2;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
|
||||
printk(KERN_WARNING "lgh06xf: %s error "
|
||||
"(addr %02x <- %02x, result = %i)\n",
|
||||
__FUNCTION__, buf[0], buf[1], result);
|
||||
if (result < 0)
|
||||
return result;
|
||||
else
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
priv->frequency = frequency;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lgh06xf_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct lgh06xf_priv *priv = fe->tuner_priv;
|
||||
*frequency = priv->frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_tuner_ops lgh06xf_tuner_ops = {
|
||||
.release = lgh06xf_release,
|
||||
.set_params = lgh06xf_set_params,
|
||||
.get_frequency = lgh06xf_get_frequency,
|
||||
};
|
||||
|
||||
struct dvb_frontend* lgh06xf_attach(struct dvb_frontend *fe,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
struct lgh06xf_priv *priv = NULL;
|
||||
|
||||
priv = kzalloc(sizeof(struct lgh06xf_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
priv->i2c = i2c;
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &lgh06xf_tuner_ops,
|
||||
sizeof(struct dvb_tuner_ops));
|
||||
|
||||
strlcpy(fe->ops.tuner_ops.info.name, dvb_pll_lg_tdvs_h06xf.name,
|
||||
sizeof(fe->ops.tuner_ops.info.name));
|
||||
|
||||
fe->ops.tuner_ops.info.frequency_min = dvb_pll_lg_tdvs_h06xf.min;
|
||||
fe->ops.tuner_ops.info.frequency_max = dvb_pll_lg_tdvs_h06xf.max;
|
||||
|
||||
fe->tuner_priv = priv;
|
||||
return fe;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(lgh06xf_attach);
|
||||
|
||||
MODULE_DESCRIPTION("LG TDVS-H06xF ATSC Tuner support");
|
||||
MODULE_AUTHOR("Michael Krufky");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
* End:
|
||||
*/
|
35
drivers/media/dvb/frontends/lgh06xf.h
Normal file
35
drivers/media/dvb/frontends/lgh06xf.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* lgh06xf.h - ATSC Tuner support for LG TDVS-H06xF
|
||||
*
|
||||
* 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 _LGH06XF_H_
|
||||
#define _LGH06XF_H_
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
#if defined(CONFIG_DVB_TUNER_LGH06XF) || (defined(CONFIG_DVB_TUNER_LGH06XF_MODULE) && defined(MODULE))
|
||||
extern struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe,
|
||||
struct i2c_adapter *i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* lgh06xf_attach(struct dvb_frontend* fe,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_DVB_TUNER_LGH06XF */
|
||||
|
||||
#endif /* _LGH06XF_H_ */
|
|
@ -40,6 +40,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "dvb_math.h"
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb-pll.h"
|
||||
#include "or51132.h"
|
||||
|
@ -62,6 +63,7 @@ struct or51132_state
|
|||
|
||||
/* Demodulator private data */
|
||||
fe_modulation_t current_modulation;
|
||||
u32 snr; /* Result of last SNR calculation */
|
||||
|
||||
/* Tuner private data */
|
||||
u32 current_frequency;
|
||||
|
@ -465,124 +467,128 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* log10-1 table at .5 increments from 1 to 100.5 */
|
||||
static unsigned int i100x20log10[] = {
|
||||
0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480,
|
||||
1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
|
||||
2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
|
||||
2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
|
||||
2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
|
||||
2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
|
||||
2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
|
||||
3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
|
||||
3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
|
||||
3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
|
||||
3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
|
||||
3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
|
||||
3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
|
||||
3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
|
||||
3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
|
||||
3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
|
||||
3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
|
||||
3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
|
||||
3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
|
||||
3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
|
||||
};
|
||||
/* Calculate SNR estimation (scaled by 2^24)
|
||||
|
||||
static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
|
||||
8-VSB SNR and QAM equations from Oren datasheets
|
||||
|
||||
static unsigned int i20Log10(unsigned short val)
|
||||
For 8-VSB:
|
||||
SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K
|
||||
|
||||
Where K = 0 if NTSC rejection filter is OFF; and
|
||||
K = 3 if NTSC rejection filter is ON
|
||||
|
||||
For QAM64:
|
||||
SNR[dB] = 10 * log10(897152044.8282 / MSE^2 )
|
||||
|
||||
For QAM256:
|
||||
SNR[dB] = 10 * log10(907832426.314266 / MSE^2 )
|
||||
|
||||
We re-write the snr equation as:
|
||||
SNR * 2^24 = 10*(c - 2*intlog10(MSE))
|
||||
Where for QAM256, c = log10(907832426.314266) * 2^24
|
||||
and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */
|
||||
|
||||
static u32 calculate_snr(u32 mse, u32 c)
|
||||
{
|
||||
unsigned int rntval = 100;
|
||||
unsigned int tmp = val;
|
||||
unsigned int exp = 1;
|
||||
if (mse == 0) /* No signal */
|
||||
return 0;
|
||||
|
||||
while(tmp > 100) {tmp /= 100; exp++;}
|
||||
|
||||
val = (2 * val)/denom[exp];
|
||||
if (exp > 1) rntval = 2000*exp;
|
||||
|
||||
rntval += i100x20log10[val];
|
||||
return rntval;
|
||||
}
|
||||
|
||||
static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
|
||||
{
|
||||
struct or51132_state* state = fe->demodulator_priv;
|
||||
unsigned char rec_buf[2];
|
||||
unsigned char snd_buf[2];
|
||||
u8 rcvr_stat;
|
||||
u16 snr_equ;
|
||||
u32 signal_strength;
|
||||
int usK;
|
||||
|
||||
snd_buf[0]=0x04;
|
||||
snd_buf[1]=0x02; /* SNR after Equalizer */
|
||||
msleep(30); /* 30ms */
|
||||
if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
|
||||
printk(KERN_WARNING "or51132: read_status write error\n");
|
||||
return -1;
|
||||
mse = 2*intlog10(mse);
|
||||
if (mse > c) {
|
||||
/* Negative SNR, which is possible, but realisticly the
|
||||
demod will lose lock before the signal gets this bad. The
|
||||
API only allows for unsigned values, so just return 0 */
|
||||
return 0;
|
||||
}
|
||||
msleep(30); /* 30ms */
|
||||
if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
|
||||
printk(KERN_WARNING "or51132: read_status read error\n");
|
||||
return -1;
|
||||
}
|
||||
snr_equ = rec_buf[0] | (rec_buf[1] << 8);
|
||||
dprintk("read_signal_strength snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
|
||||
|
||||
/* Receiver Status */
|
||||
snd_buf[0]=0x04;
|
||||
snd_buf[1]=0x00;
|
||||
msleep(30); /* 30ms */
|
||||
if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
|
||||
printk(KERN_WARNING "or51132: read_signal_strength read_status write error\n");
|
||||
return -1;
|
||||
}
|
||||
msleep(30); /* 30ms */
|
||||
if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
|
||||
printk(KERN_WARNING "or51132: read_signal_strength read_status read error\n");
|
||||
return -1;
|
||||
}
|
||||
dprintk("read_signal_strength read_status %x %x\n",rec_buf[0],rec_buf[1]);
|
||||
rcvr_stat = rec_buf[1];
|
||||
usK = (rcvr_stat & 0x10) ? 3 : 0;
|
||||
|
||||
/* The value reported back from the frontend will be FFFF=100% 0000=0% */
|
||||
signal_strength = (((8952 - i20Log10(snr_equ) - usK*100)/3+5)*65535)/1000;
|
||||
if (signal_strength > 0xffff)
|
||||
*strength = 0xffff;
|
||||
else
|
||||
*strength = signal_strength;
|
||||
dprintk("read_signal_strength %i\n",*strength);
|
||||
|
||||
return 0;
|
||||
return 10*(c - mse);
|
||||
}
|
||||
|
||||
static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
|
||||
{
|
||||
struct or51132_state* state = fe->demodulator_priv;
|
||||
unsigned char rec_buf[2];
|
||||
unsigned char snd_buf[2];
|
||||
u16 snr_equ;
|
||||
u8 rec_buf[2];
|
||||
u8 snd_buf[2];
|
||||
u32 noise;
|
||||
u32 c;
|
||||
u32 usK;
|
||||
|
||||
/* Register is same for VSB or QAM firmware */
|
||||
snd_buf[0]=0x04;
|
||||
snd_buf[1]=0x02; /* SNR after Equalizer */
|
||||
msleep(30); /* 30ms */
|
||||
if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
|
||||
printk(KERN_WARNING "or51132: read_snr write error\n");
|
||||
return -1;
|
||||
printk(KERN_WARNING "or51132: snr write error\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
msleep(30); /* 30ms */
|
||||
if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
|
||||
printk(KERN_WARNING "or51132: read_snr dvr read error\n");
|
||||
return -1;
|
||||
printk(KERN_WARNING "or51132: snr read error\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
snr_equ = rec_buf[0] | (rec_buf[1] << 8);
|
||||
dprintk("read_snr snr_equ %x %x (%i)\n",rec_buf[0],rec_buf[1],snr_equ);
|
||||
noise = rec_buf[0] | (rec_buf[1] << 8);
|
||||
dprintk("read_snr noise %x %x (%i)\n",rec_buf[0],rec_buf[1],noise);
|
||||
|
||||
*snr = 0xFFFF - snr_equ;
|
||||
dprintk("read_snr %i\n",*snr);
|
||||
/* Read status, contains modulation type for QAM_AUTO and
|
||||
NTSC filter for VSB */
|
||||
snd_buf[0]=0x04;
|
||||
snd_buf[1]=0x00; /* Status register */
|
||||
msleep(30); /* 30ms */
|
||||
if (i2c_writebytes(state,state->config->demod_address,snd_buf,2)) {
|
||||
printk(KERN_WARNING "or51132: status write error\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
msleep(30); /* 30ms */
|
||||
if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
|
||||
printk(KERN_WARNING "or51132: status read error\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
usK = 0;
|
||||
switch (rec_buf[0]) {
|
||||
case 0x06:
|
||||
usK = (rec_buf[1] & 0x10) ? 0x03000000 : 0;
|
||||
/* Fall through to QAM64 case */
|
||||
case 0x43:
|
||||
c = 150204167;
|
||||
break;
|
||||
case 0x45:
|
||||
c = 150290396;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "or51132: unknown status 0x%02x\n", rec_buf[0]);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
dprintk("%s: modulation %02x, NTSC rej O%s\n", __FUNCTION__,
|
||||
rec_buf[0], rec_buf[1]&0x10?"n":"ff");
|
||||
|
||||
/* Calculate SNR using noise, c, and NTSC rejection correction */
|
||||
state->snr = calculate_snr(noise, c) - usK;
|
||||
*snr = (state->snr) >> 16;
|
||||
|
||||
dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
|
||||
state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
|
||||
{
|
||||
/* Calculate Strength from SNR up to 35dB */
|
||||
/* Even though the SNR can go higher than 35dB, there is some comfort */
|
||||
/* factor in having a range of strong signals that can show at 100% */
|
||||
struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
|
||||
u16 snr;
|
||||
int ret;
|
||||
|
||||
ret = fe->ops.read_snr(fe, &snr);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
/* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
|
||||
/* scale the range 0 - 35*2^24 into 0 - 65535 */
|
||||
if (state->snr >= 8960 * 0x10000)
|
||||
*strength = 0xffff;
|
||||
else
|
||||
*strength = state->snr / 8960;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include "dvb_math.h"
|
||||
#include "dvb_frontend.h"
|
||||
#include "or51211.h"
|
||||
|
||||
|
@ -63,6 +64,7 @@ struct or51211_state {
|
|||
|
||||
/* Demodulator private data */
|
||||
u8 initialized:1;
|
||||
u32 snr; /* Result of last SNR claculation */
|
||||
|
||||
/* Tuner private data */
|
||||
u32 current_frequency;
|
||||
|
@ -292,107 +294,81 @@ static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* log10-1 table at .5 increments from 1 to 100.5 */
|
||||
static unsigned int i100x20log10[] = {
|
||||
0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480,
|
||||
1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
|
||||
2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
|
||||
2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
|
||||
2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
|
||||
2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
|
||||
2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
|
||||
3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
|
||||
3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
|
||||
3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
|
||||
3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
|
||||
3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
|
||||
3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
|
||||
3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
|
||||
3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
|
||||
3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
|
||||
3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
|
||||
3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
|
||||
3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
|
||||
3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
|
||||
};
|
||||
/* Calculate SNR estimation (scaled by 2^24)
|
||||
|
||||
static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
|
||||
8-VSB SNR equation from Oren datasheets
|
||||
|
||||
static unsigned int i20Log10(unsigned short val)
|
||||
For 8-VSB:
|
||||
SNR[dB] = 10 * log10(219037.9454 / MSE^2 )
|
||||
|
||||
We re-write the snr equation as:
|
||||
SNR * 2^24 = 10*(c - 2*intlog10(MSE))
|
||||
Where for 8-VSB, c = log10(219037.9454) * 2^24 */
|
||||
|
||||
static u32 calculate_snr(u32 mse, u32 c)
|
||||
{
|
||||
unsigned int rntval = 100;
|
||||
unsigned int tmp = val;
|
||||
unsigned int exp = 1;
|
||||
if (mse == 0) /* No signal */
|
||||
return 0;
|
||||
|
||||
while(tmp > 100) {tmp /= 100; exp++;}
|
||||
|
||||
val = (2 * val)/denom[exp];
|
||||
if (exp > 1) rntval = 2000*exp;
|
||||
|
||||
rntval += i100x20log10[val];
|
||||
return rntval;
|
||||
}
|
||||
|
||||
static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
|
||||
{
|
||||
struct or51211_state* state = fe->demodulator_priv;
|
||||
u8 rec_buf[2];
|
||||
u8 snd_buf[4];
|
||||
u8 snr_equ;
|
||||
u32 signal_strength;
|
||||
|
||||
/* SNR after Equalizer */
|
||||
snd_buf[0] = 0x04;
|
||||
snd_buf[1] = 0x00;
|
||||
snd_buf[2] = 0x04;
|
||||
snd_buf[3] = 0x00;
|
||||
|
||||
if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
|
||||
printk(KERN_WARNING "or51211: read_status write error\n");
|
||||
return -1;
|
||||
mse = 2*intlog10(mse);
|
||||
if (mse > c) {
|
||||
/* Negative SNR, which is possible, but realisticly the
|
||||
demod will lose lock before the signal gets this bad. The
|
||||
API only allows for unsigned values, so just return 0 */
|
||||
return 0;
|
||||
}
|
||||
msleep(3);
|
||||
if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
|
||||
printk(KERN_WARNING "or51211: read_status read error\n");
|
||||
return -1;
|
||||
}
|
||||
snr_equ = rec_buf[0] & 0xff;
|
||||
|
||||
/* The value reported back from the frontend will be FFFF=100% 0000=0% */
|
||||
signal_strength = (((5334 - i20Log10(snr_equ))/3+5)*65535)/1000;
|
||||
if (signal_strength > 0xffff)
|
||||
*strength = 0xffff;
|
||||
else
|
||||
*strength = signal_strength;
|
||||
dprintk("read_signal_strength %i\n",*strength);
|
||||
|
||||
return 0;
|
||||
return 10*(c - mse);
|
||||
}
|
||||
|
||||
static int or51211_read_snr(struct dvb_frontend* fe, u16* snr)
|
||||
{
|
||||
struct or51211_state* state = fe->demodulator_priv;
|
||||
u8 rec_buf[2];
|
||||
u8 snd_buf[4];
|
||||
u8 snd_buf[3];
|
||||
|
||||
/* SNR after Equalizer */
|
||||
snd_buf[0] = 0x04;
|
||||
snd_buf[1] = 0x00;
|
||||
snd_buf[2] = 0x04;
|
||||
snd_buf[3] = 0x00;
|
||||
|
||||
if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
|
||||
printk(KERN_WARNING "or51211: read_status write error\n");
|
||||
printk(KERN_WARNING "%s: error writing snr reg\n",
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
msleep(3);
|
||||
if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
|
||||
printk(KERN_WARNING "or51211: read_status read error\n");
|
||||
printk(KERN_WARNING "%s: read_status read error\n",
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
*snr = rec_buf[0] & 0xff;
|
||||
|
||||
dprintk("read_snr %i\n",*snr);
|
||||
state->snr = calculate_snr(rec_buf[0], 89599047);
|
||||
*snr = (state->snr) >> 16;
|
||||
|
||||
dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __FUNCTION__, rec_buf[0],
|
||||
state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
|
||||
{
|
||||
/* Calculate Strength from SNR up to 35dB */
|
||||
/* Even though the SNR can go higher than 35dB, there is some comfort */
|
||||
/* factor in having a range of strong signals that can show at 100% */
|
||||
struct or51211_state* state = (struct or51211_state*)fe->demodulator_priv;
|
||||
u16 snr;
|
||||
int ret;
|
||||
|
||||
ret = fe->ops.read_snr(fe, &snr);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
/* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
|
||||
/* scale the range 0 - 35*2^24 into 0 - 65535 */
|
||||
if (state->snr >= 8960 * 0x10000)
|
||||
*strength = 0xffff;
|
||||
else
|
||||
*strength = state->snr / 8960;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -648,18 +648,24 @@ static int tda10046_init(struct dvb_frontend* fe)
|
|||
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
|
||||
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities
|
||||
break;
|
||||
case TDA10046_AGC_TDA827X:
|
||||
case TDA10046_AGC_TDA827X_GP11:
|
||||
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
|
||||
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
|
||||
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
|
||||
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities
|
||||
break;
|
||||
case TDA10046_AGC_TDA827X_GPL:
|
||||
case TDA10046_AGC_TDA827X_GP00:
|
||||
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
|
||||
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
|
||||
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
|
||||
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
|
||||
break;
|
||||
case TDA10046_AGC_TDA827X_GP01:
|
||||
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
|
||||
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
|
||||
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
|
||||
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x62); // set AGC polarities
|
||||
break;
|
||||
}
|
||||
tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
|
||||
tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
|
||||
|
|
|
@ -35,8 +35,9 @@ enum tda10046_agc {
|
|||
TDA10046_AGC_DEFAULT, /* original configuration */
|
||||
TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */
|
||||
TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */
|
||||
TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */
|
||||
TDA10046_AGC_TDA827X_GPL, /* same as above, but GPIOs 0 */
|
||||
TDA10046_AGC_TDA827X_GP11, /* IF AGC only, special setup for tda827x */
|
||||
TDA10046_AGC_TDA827X_GP00, /* same as above, but GPIOs 0 */
|
||||
TDA10046_AGC_TDA827X_GP01, /* same as above, but GPIO3=0 GPIO1=1*/
|
||||
};
|
||||
|
||||
enum tda10046_if {
|
||||
|
|
|
@ -262,12 +262,29 @@ static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
|||
if (sync & 0x10)
|
||||
*status |= FE_HAS_SYNC;
|
||||
|
||||
if (sync & 0x20) /* frontend can not lock */
|
||||
*status |= FE_TIMEDOUT;
|
||||
|
||||
if ((sync & 0x1f) == 0x1f)
|
||||
*status |= FE_HAS_LOCK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber)
|
||||
{
|
||||
struct tda8083_state* state = fe->demodulator_priv;
|
||||
int ret;
|
||||
u8 buf[3];
|
||||
|
||||
if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf))))
|
||||
return ret;
|
||||
|
||||
*ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
|
||||
{
|
||||
struct tda8083_state* state = fe->demodulator_priv;
|
||||
|
@ -288,6 +305,17 @@ static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
|
||||
{
|
||||
struct tda8083_state* state = fe->demodulator_priv;
|
||||
|
||||
*ucblocks = tda8083_readreg(state, 0x0f);
|
||||
if (*ucblocks == 0xff)
|
||||
*ucblocks = 0xffffffff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct tda8083_state* state = fe->demodulator_priv;
|
||||
|
@ -440,6 +468,8 @@ static struct dvb_frontend_ops tda8083_ops = {
|
|||
.read_status = tda8083_read_status,
|
||||
.read_signal_strength = tda8083_read_signal_strength,
|
||||
.read_snr = tda8083_read_snr,
|
||||
.read_ber = tda8083_read_ber,
|
||||
.read_ucblocks = tda8083_read_ucblocks,
|
||||
|
||||
.diseqc_send_master_cmd = tda8083_send_diseqc_msg,
|
||||
.diseqc_send_burst = tda8083_diseqc_send_burst,
|
||||
|
|
|
@ -42,8 +42,7 @@ struct tda826x_priv {
|
|||
|
||||
static int tda826x_release(struct dvb_frontend *fe)
|
||||
{
|
||||
if (fe->tuner_priv)
|
||||
kfree(fe->tuner_priv);
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -133,18 +132,21 @@ struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2
|
|||
{
|
||||
struct tda826x_priv *priv = NULL;
|
||||
u8 b1 [] = { 0, 0 };
|
||||
struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 };
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = addr, .flags = 0, .buf = NULL, .len = 0 },
|
||||
{ .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 }
|
||||
};
|
||||
int ret;
|
||||
|
||||
dprintk("%s:\n", __FUNCTION__);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
ret = i2c_transfer (i2c, &msg, 1);
|
||||
ret = i2c_transfer (i2c, msg, 2);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
if (ret != 1)
|
||||
if (ret != 2)
|
||||
return NULL;
|
||||
if (!(b1[1] & 0x80))
|
||||
return NULL;
|
||||
|
|
|
@ -43,8 +43,7 @@ struct tua6100_priv {
|
|||
|
||||
static int tua6100_release(struct dvb_frontend *fe)
|
||||
{
|
||||
if (fe->tuner_priv)
|
||||
kfree(fe->tuner_priv);
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -92,6 +92,7 @@ config DVB_BUDGET_CI
|
|||
select DVB_STV0299 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
|
||||
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
|
||||
select VIDEO_IR
|
||||
help
|
||||
Support for simple SAA7146 based DVB cards
|
||||
(so called Budget- or Nova-PCI cards) without onboard
|
||||
|
|
|
@ -2828,7 +2828,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
|
|||
|
||||
static struct saa7146_extension av7110_extension = {
|
||||
.name = "dvb",
|
||||
.flags = SAA7146_I2C_SHORT_DELAY,
|
||||
.flags = SAA7146_USE_I2C_IRQ,
|
||||
|
||||
.module = THIS_MODULE,
|
||||
.pci_tbl = &pci_tbl[0],
|
||||
|
|
|
@ -48,7 +48,8 @@ static void av7110_emit_keyup(unsigned long data)
|
|||
if (!data || !test_bit(data, input_dev->key))
|
||||
return;
|
||||
|
||||
input_event(input_dev, EV_KEY, data, !!0);
|
||||
input_report_key(input_dev, data, 0);
|
||||
input_sync(input_dev);
|
||||
}
|
||||
|
||||
|
||||
|
@ -115,14 +116,17 @@ static void av7110_emit_key(unsigned long parm)
|
|||
del_timer(&keyup_timer);
|
||||
if (keyup_timer.data != keycode || new_toggle != old_toggle) {
|
||||
delay_timer_finished = 0;
|
||||
input_event(input_dev, EV_KEY, keyup_timer.data, !!0);
|
||||
input_event(input_dev, EV_KEY, keycode, !0);
|
||||
} else
|
||||
if (delay_timer_finished)
|
||||
input_event(input_dev, EV_KEY, keycode, 2);
|
||||
input_event(input_dev, EV_KEY, keyup_timer.data, 0);
|
||||
input_event(input_dev, EV_KEY, keycode, 1);
|
||||
input_sync(input_dev);
|
||||
} else if (delay_timer_finished) {
|
||||
input_event(input_dev, EV_KEY, keycode, 2);
|
||||
input_sync(input_dev);
|
||||
}
|
||||
} else {
|
||||
delay_timer_finished = 0;
|
||||
input_event(input_dev, EV_KEY, keycode, !0);
|
||||
input_event(input_dev, EV_KEY, keycode, 1);
|
||||
input_sync(input_dev);
|
||||
}
|
||||
|
||||
keyup_timer.expires = jiffies + UP_TIMEOUT;
|
||||
|
@ -211,6 +215,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom)
|
|||
int __devinit av7110_ir_init(struct av7110 *av7110)
|
||||
{
|
||||
static struct proc_dir_entry *e;
|
||||
int err;
|
||||
|
||||
if (av_cnt >= sizeof av_list/sizeof av_list[0])
|
||||
return -ENOSPC;
|
||||
|
@ -231,7 +236,11 @@ int __devinit av7110_ir_init(struct av7110 *av7110)
|
|||
set_bit(EV_KEY, input_dev->evbit);
|
||||
set_bit(EV_REP, input_dev->evbit);
|
||||
input_register_keys();
|
||||
input_register_device(input_dev);
|
||||
err = input_register_device(input_dev);
|
||||
if (err) {
|
||||
input_free_device(input_dev);
|
||||
return err;
|
||||
}
|
||||
input_dev->timer.function = input_repeat_key;
|
||||
|
||||
e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
|
||||
|
|
|
@ -360,7 +360,7 @@ static int ciintf_init(struct budget_av *budget_av)
|
|||
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
|
||||
|
||||
/* Enable DEBI pins */
|
||||
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
|
||||
saa7146_write(saa, MC1, MASK_27 | MASK_11);
|
||||
|
||||
/* register CI interface */
|
||||
budget_av->ca.owner = THIS_MODULE;
|
||||
|
@ -386,7 +386,7 @@ static int ciintf_init(struct budget_av *budget_av)
|
|||
return 0;
|
||||
|
||||
error:
|
||||
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
|
||||
saa7146_write(saa, MC1, MASK_27);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -403,7 +403,7 @@ static void ciintf_deinit(struct budget_av *budget_av)
|
|||
dvb_ca_en50221_release(&budget_av->ca);
|
||||
|
||||
/* disable DEBI pins */
|
||||
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
|
||||
saa7146_write(saa, MC1, MASK_27);
|
||||
}
|
||||
|
||||
|
||||
|
@ -655,6 +655,10 @@ static struct tda10021_config philips_cu1216_config = {
|
|||
.demod_address = 0x0c,
|
||||
};
|
||||
|
||||
static struct tda10021_config philips_cu1216_config_altaddress = {
|
||||
.demod_address = 0x0d,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -831,7 +835,7 @@ static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe,
|
|||
return -EINVAL;
|
||||
|
||||
rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf,
|
||||
params->frequency, 0);
|
||||
params->frequency, 0);
|
||||
if(rc < 0) return rc;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
|
@ -914,6 +918,7 @@ static u8 read_pwm(struct budget_av *budget_av)
|
|||
#define SUBID_DVBS_TV_STAR_CI 0x0016
|
||||
#define SUBID_DVBS_EASYWATCH_1 0x001a
|
||||
#define SUBID_DVBS_EASYWATCH 0x001e
|
||||
#define SUBID_DVBC_EASYWATCH 0x002a
|
||||
#define SUBID_DVBC_KNC1 0x0020
|
||||
#define SUBID_DVBC_KNC1_PLUS 0x0021
|
||||
#define SUBID_DVBC_CINERGY1200 0x1156
|
||||
|
@ -947,11 +952,15 @@ static void frontend_init(struct budget_av *budget_av)
|
|||
/* Enable / PowerON Frontend */
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
|
||||
|
||||
/* Wait for PowerON */
|
||||
msleep(100);
|
||||
|
||||
/* additional setup necessary for the PLUS cards */
|
||||
switch (saa->pci->subsystem_device) {
|
||||
case SUBID_DVBS_KNC1_PLUS:
|
||||
case SUBID_DVBC_KNC1_PLUS:
|
||||
case SUBID_DVBT_KNC1_PLUS:
|
||||
case SUBID_DVBC_EASYWATCH:
|
||||
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
|
||||
break;
|
||||
}
|
||||
|
@ -1006,10 +1015,15 @@ static void frontend_init(struct budget_av *budget_av)
|
|||
case SUBID_DVBC_KNC1:
|
||||
case SUBID_DVBC_KNC1_PLUS:
|
||||
case SUBID_DVBC_CINERGY1200:
|
||||
case SUBID_DVBC_EASYWATCH:
|
||||
budget_av->reinitialise_demod = 1;
|
||||
fe = dvb_attach(tda10021_attach, &philips_cu1216_config,
|
||||
&budget_av->budget.i2c_adap,
|
||||
read_pwm(budget_av));
|
||||
if (fe == NULL)
|
||||
fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress,
|
||||
&budget_av->budget.i2c_adap,
|
||||
read_pwm(budget_av));
|
||||
if (fe) {
|
||||
budget_av->tda10021_poclkp = 1;
|
||||
budget_av->tda10021_set_frontend = fe->ops.set_frontend;
|
||||
|
@ -1242,6 +1256,7 @@ MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
|
|||
MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
|
||||
MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
|
||||
MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
|
||||
MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);
|
||||
MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
|
||||
MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
|
||||
MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
|
||||
|
@ -1260,6 +1275,7 @@ static struct pci_device_id pci_tbl[] = {
|
|||
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
|
||||
MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
|
||||
MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
|
||||
MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
|
||||
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
|
||||
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
|
||||
MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
|
||||
|
@ -1277,7 +1293,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
|
|||
|
||||
static struct saa7146_extension budget_extension = {
|
||||
.name = "budget_av",
|
||||
.flags = SAA7146_I2C_SHORT_DELAY,
|
||||
.flags = SAA7146_USE_I2C_IRQ,
|
||||
|
||||
.pci_tbl = pci_tbl,
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <media/ir-common.h>
|
||||
|
||||
#include "dvb_ca_en50221.h"
|
||||
#include "stv0299.h"
|
||||
|
@ -72,162 +73,218 @@
|
|||
#define SLOTSTATUS_READY 8
|
||||
#define SLOTSTATUS_OCCUPIED (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
|
||||
|
||||
/* Milliseconds during which key presses are regarded as key repeat and during
|
||||
* which the debounce logic is active
|
||||
*/
|
||||
#define IR_REPEAT_TIMEOUT 350
|
||||
|
||||
/* RC5 device wildcard */
|
||||
#define IR_DEVICE_ANY 255
|
||||
|
||||
/* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two),
|
||||
* this setting allows the superflous sequences to be ignored
|
||||
*/
|
||||
static int debounce = 0;
|
||||
module_param(debounce, int, 0644);
|
||||
MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)");
|
||||
|
||||
static int rc5_device = -1;
|
||||
module_param(rc5_device, int, 0644);
|
||||
MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
|
||||
|
||||
static int ir_debug = 0;
|
||||
module_param(ir_debug, int, 0644);
|
||||
MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
|
||||
|
||||
struct budget_ci_ir {
|
||||
struct input_dev *dev;
|
||||
struct tasklet_struct msp430_irq_tasklet;
|
||||
char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
|
||||
char phys[32];
|
||||
struct ir_input_state state;
|
||||
int rc5_device;
|
||||
};
|
||||
|
||||
struct budget_ci {
|
||||
struct budget budget;
|
||||
struct input_dev *input_dev;
|
||||
struct tasklet_struct msp430_irq_tasklet;
|
||||
struct tasklet_struct ciintf_irq_tasklet;
|
||||
int slot_status;
|
||||
int ci_irq;
|
||||
struct dvb_ca_en50221 ca;
|
||||
char ir_dev_name[50];
|
||||
struct budget_ci_ir ir;
|
||||
u8 tuner_pll_address; /* used for philips_tdm1316l configs */
|
||||
};
|
||||
|
||||
/* from reading the following remotes:
|
||||
Zenith Universal 7 / TV Mode 807 / VCR Mode 837
|
||||
Hauppauge (from NOVA-CI-s box product)
|
||||
i've taken a "middle of the road" approach and note the differences
|
||||
*/
|
||||
static u16 key_map[64] = {
|
||||
/* 0x0X */
|
||||
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8,
|
||||
KEY_9,
|
||||
KEY_ENTER,
|
||||
KEY_RED,
|
||||
KEY_POWER, /* RADIO on Hauppauge */
|
||||
KEY_MUTE,
|
||||
0,
|
||||
KEY_A, /* TV on Hauppauge */
|
||||
/* 0x1X */
|
||||
KEY_VOLUMEUP, KEY_VOLUMEDOWN,
|
||||
0, 0,
|
||||
KEY_B,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
KEY_UP, KEY_DOWN,
|
||||
KEY_OPTION, /* RESERVED on Hauppauge */
|
||||
KEY_BREAK,
|
||||
/* 0x2X */
|
||||
KEY_CHANNELUP, KEY_CHANNELDOWN,
|
||||
KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */
|
||||
0, KEY_RESTART, KEY_OK,
|
||||
KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */
|
||||
0,
|
||||
KEY_ENTER, /* VCR mode on Zenith */
|
||||
KEY_PAUSE,
|
||||
0,
|
||||
KEY_RIGHT, KEY_LEFT,
|
||||
0,
|
||||
KEY_MENU, /* FULL SCREEN on Hauppauge */
|
||||
0,
|
||||
/* 0x3X */
|
||||
KEY_SLOW,
|
||||
KEY_PREVIOUS, /* VCR mode on Zenith */
|
||||
KEY_REWIND,
|
||||
0,
|
||||
KEY_FASTFORWARD,
|
||||
KEY_PLAY, KEY_STOP,
|
||||
KEY_RECORD,
|
||||
KEY_TUNER, /* TV/VCR on Zenith */
|
||||
0,
|
||||
KEY_C,
|
||||
0,
|
||||
KEY_EXIT,
|
||||
KEY_POWER2,
|
||||
KEY_TUNER, /* VCR mode on Zenith */
|
||||
0,
|
||||
};
|
||||
|
||||
static void msp430_ir_debounce(unsigned long data)
|
||||
static void msp430_ir_keyup(unsigned long data)
|
||||
{
|
||||
struct input_dev *dev = (struct input_dev *) data;
|
||||
|
||||
if (dev->rep[0] == 0 || dev->rep[0] == ~0) {
|
||||
input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
|
||||
return;
|
||||
}
|
||||
|
||||
dev->rep[0] = 0;
|
||||
dev->timer.expires = jiffies + HZ * 350 / 1000;
|
||||
add_timer(&dev->timer);
|
||||
input_event(dev, EV_KEY, key_map[dev->repeat_key], 2); /* REPEAT */
|
||||
struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
|
||||
ir_input_nokey(ir->dev, &ir->state);
|
||||
}
|
||||
|
||||
static void msp430_ir_interrupt(unsigned long data)
|
||||
{
|
||||
struct budget_ci *budget_ci = (struct budget_ci *) data;
|
||||
struct input_dev *dev = budget_ci->input_dev;
|
||||
unsigned int code =
|
||||
ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
|
||||
struct input_dev *dev = budget_ci->ir.dev;
|
||||
static int bounces = 0;
|
||||
int device;
|
||||
int toggle;
|
||||
static int prev_toggle = -1;
|
||||
static u32 ir_key;
|
||||
u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
|
||||
|
||||
if (code & 0x40) {
|
||||
code &= 0x3f;
|
||||
/*
|
||||
* The msp430 chip can generate two different bytes, command and device
|
||||
*
|
||||
* type1: X1CCCCCC, C = command bits (0 - 63)
|
||||
* type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
|
||||
*
|
||||
* More than one command byte may be generated before the device byte
|
||||
* Only when we have both, a correct keypress is generated
|
||||
*/
|
||||
|
||||
if (timer_pending(&dev->timer)) {
|
||||
if (code == dev->repeat_key) {
|
||||
++dev->rep[0];
|
||||
return;
|
||||
}
|
||||
del_timer(&dev->timer);
|
||||
input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
|
||||
}
|
||||
/* Is this a RC5 command byte? */
|
||||
if (command & 0x40) {
|
||||
if (ir_debug)
|
||||
printk("budget_ci: received command byte 0x%02x\n", command);
|
||||
ir_key = command & 0x3f;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!key_map[code]) {
|
||||
printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
|
||||
return;
|
||||
}
|
||||
/* It's a RC5 device byte */
|
||||
if (ir_debug)
|
||||
printk("budget_ci: received device byte 0x%02x\n", command);
|
||||
device = command & 0x1f;
|
||||
toggle = command & 0x20;
|
||||
|
||||
/* initialize debounce and repeat */
|
||||
dev->repeat_key = code;
|
||||
/* Zenith remote _always_ sends 2 sequences */
|
||||
dev->rep[0] = ~0;
|
||||
/* 350 milliseconds */
|
||||
dev->timer.expires = jiffies + HZ * 350 / 1000;
|
||||
/* MAKE */
|
||||
input_event(dev, EV_KEY, key_map[code], !0);
|
||||
add_timer(&dev->timer);
|
||||
if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device)
|
||||
return;
|
||||
|
||||
/* Ignore repeated key sequences if requested */
|
||||
if (toggle == prev_toggle && ir_key == dev->repeat_key &&
|
||||
bounces > 0 && timer_pending(&dev->timer)) {
|
||||
if (ir_debug)
|
||||
printk("budget_ci: debounce logic ignored IR command\n");
|
||||
bounces--;
|
||||
return;
|
||||
}
|
||||
prev_toggle = toggle;
|
||||
|
||||
/* Are we still waiting for a keyup event? */
|
||||
if (del_timer(&dev->timer))
|
||||
ir_input_nokey(dev, &budget_ci->ir.state);
|
||||
|
||||
/* Generate keypress */
|
||||
if (ir_debug)
|
||||
printk("budget_ci: generating keypress 0x%02x\n", ir_key);
|
||||
ir_input_keydown(dev, &budget_ci->ir.state, ir_key, (ir_key & (command << 8)));
|
||||
|
||||
/* Do we want to delay the keyup event? */
|
||||
if (debounce) {
|
||||
bounces = debounce;
|
||||
mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT));
|
||||
} else {
|
||||
ir_input_nokey(dev, &budget_ci->ir.state);
|
||||
}
|
||||
}
|
||||
|
||||
static int msp430_ir_init(struct budget_ci *budget_ci)
|
||||
{
|
||||
struct saa7146_dev *saa = budget_ci->budget.dev;
|
||||
struct input_dev *input_dev;
|
||||
int i;
|
||||
struct input_dev *input_dev = budget_ci->ir.dev;
|
||||
int error;
|
||||
|
||||
budget_ci->input_dev = input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
budget_ci->ir.dev = input_dev = input_allocate_device();
|
||||
if (!input_dev) {
|
||||
printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
|
||||
error = -ENOMEM;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
sprintf(budget_ci->ir_dev_name, "Budget-CI dvb ir receiver %s", saa->name);
|
||||
snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
|
||||
"Budget-CI dvb ir receiver %s", saa->name);
|
||||
snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
|
||||
"pci-%s/ir0", pci_name(saa->pci));
|
||||
|
||||
input_dev->name = budget_ci->ir_dev_name;
|
||||
input_dev->name = budget_ci->ir.name;
|
||||
|
||||
set_bit(EV_KEY, input_dev->evbit);
|
||||
for (i = 0; i < ARRAY_SIZE(key_map); i++)
|
||||
if (key_map[i])
|
||||
set_bit(key_map[i], input_dev->keybit);
|
||||
input_dev->phys = budget_ci->ir.phys;
|
||||
input_dev->id.bustype = BUS_PCI;
|
||||
input_dev->id.version = 1;
|
||||
if (saa->pci->subsystem_vendor) {
|
||||
input_dev->id.vendor = saa->pci->subsystem_vendor;
|
||||
input_dev->id.product = saa->pci->subsystem_device;
|
||||
} else {
|
||||
input_dev->id.vendor = saa->pci->vendor;
|
||||
input_dev->id.product = saa->pci->device;
|
||||
}
|
||||
input_dev->cdev.dev = &saa->pci->dev;
|
||||
|
||||
input_register_device(budget_ci->input_dev);
|
||||
/* Select keymap and address */
|
||||
switch (budget_ci->budget.dev->pci->subsystem_device) {
|
||||
case 0x100c:
|
||||
case 0x100f:
|
||||
case 0x1010:
|
||||
case 0x1011:
|
||||
case 0x1012:
|
||||
case 0x1017:
|
||||
/* The hauppauge keymap is a superset of these remotes */
|
||||
ir_input_init(input_dev, &budget_ci->ir.state,
|
||||
IR_TYPE_RC5, ir_codes_hauppauge_new);
|
||||
|
||||
input_dev->timer.function = msp430_ir_debounce;
|
||||
if (rc5_device < 0)
|
||||
budget_ci->ir.rc5_device = 0x1f;
|
||||
else
|
||||
budget_ci->ir.rc5_device = rc5_device;
|
||||
break;
|
||||
default:
|
||||
/* unknown remote */
|
||||
ir_input_init(input_dev, &budget_ci->ir.state,
|
||||
IR_TYPE_RC5, ir_codes_budget_ci_old);
|
||||
|
||||
saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
|
||||
if (rc5_device < 0)
|
||||
budget_ci->ir.rc5_device = IR_DEVICE_ANY;
|
||||
else
|
||||
budget_ci->ir.rc5_device = rc5_device;
|
||||
break;
|
||||
}
|
||||
|
||||
/* initialise the key-up debounce timeout handler */
|
||||
input_dev->timer.function = msp430_ir_keyup;
|
||||
input_dev->timer.data = (unsigned long) &budget_ci->ir;
|
||||
|
||||
error = input_register_device(input_dev);
|
||||
if (error) {
|
||||
printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
|
||||
goto out2;
|
||||
}
|
||||
|
||||
tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
|
||||
(unsigned long) budget_ci);
|
||||
|
||||
SAA7146_IER_ENABLE(saa, MASK_06);
|
||||
saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
|
||||
|
||||
return 0;
|
||||
|
||||
out2:
|
||||
input_free_device(input_dev);
|
||||
out1:
|
||||
return error;
|
||||
}
|
||||
|
||||
static void msp430_ir_deinit(struct budget_ci *budget_ci)
|
||||
{
|
||||
struct saa7146_dev *saa = budget_ci->budget.dev;
|
||||
struct input_dev *dev = budget_ci->input_dev;
|
||||
struct input_dev *dev = budget_ci->ir.dev;
|
||||
|
||||
saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
|
||||
SAA7146_IER_DISABLE(saa, MASK_06);
|
||||
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
|
||||
tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
|
||||
|
||||
if (del_timer(&dev->timer))
|
||||
input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
|
||||
if (del_timer(&dev->timer)) {
|
||||
ir_input_nokey(dev, &budget_ci->ir.state);
|
||||
input_sync(dev);
|
||||
}
|
||||
|
||||
input_unregister_device(dev);
|
||||
}
|
||||
|
@ -428,7 +485,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
|
|||
memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
|
||||
|
||||
// enable DEBI pins
|
||||
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
|
||||
saa7146_write(saa, MC1, MASK_27 | MASK_11);
|
||||
|
||||
// test if it is there
|
||||
ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
|
||||
|
@ -480,7 +537,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
|
|||
} else {
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
|
||||
}
|
||||
saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03);
|
||||
SAA7146_IER_ENABLE(saa, MASK_03);
|
||||
}
|
||||
|
||||
// enable interface
|
||||
|
@ -502,7 +559,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
|
|||
return 0;
|
||||
|
||||
error:
|
||||
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
|
||||
saa7146_write(saa, MC1, MASK_27);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -512,7 +569,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci)
|
|||
|
||||
// disable CI interrupts
|
||||
if (budget_ci->ci_irq) {
|
||||
saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03);
|
||||
SAA7146_IER_DISABLE(saa, MASK_03);
|
||||
saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
|
||||
tasklet_kill(&budget_ci->ciintf_irq_tasklet);
|
||||
}
|
||||
|
@ -530,7 +587,7 @@ static void ciintf_deinit(struct budget_ci *budget_ci)
|
|||
dvb_ca_en50221_release(&budget_ci->ca);
|
||||
|
||||
// disable DEBI pins
|
||||
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16));
|
||||
saa7146_write(saa, MC1, MASK_27);
|
||||
}
|
||||
|
||||
static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
|
||||
|
@ -540,7 +597,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
|
|||
dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
|
||||
|
||||
if (*isr & MASK_06)
|
||||
tasklet_schedule(&budget_ci->msp430_irq_tasklet);
|
||||
tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
|
||||
|
||||
if (*isr & MASK_10)
|
||||
ttpci_budget_irq10_handler(dev, isr);
|
||||
|
@ -835,7 +892,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
|
|||
band = 1;
|
||||
} else if (tuner_frequency < 200000000) {
|
||||
cp = 6;
|
||||
band = 1;
|
||||
band = 2;
|
||||
} else if (tuner_frequency < 290000000) {
|
||||
cp = 3;
|
||||
band = 2;
|
||||
|
@ -1083,24 +1140,23 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
|
|||
struct budget_ci *budget_ci;
|
||||
int err;
|
||||
|
||||
if (!(budget_ci = kmalloc(sizeof(struct budget_ci), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
|
||||
if (!budget_ci) {
|
||||
err = -ENOMEM;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
dprintk(2, "budget_ci: %p\n", budget_ci);
|
||||
|
||||
budget_ci->budget.ci_present = 0;
|
||||
|
||||
dev->ext_priv = budget_ci;
|
||||
|
||||
if ((err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE))) {
|
||||
kfree(budget_ci);
|
||||
return err;
|
||||
}
|
||||
err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE);
|
||||
if (err)
|
||||
goto out2;
|
||||
|
||||
tasklet_init(&budget_ci->msp430_irq_tasklet, msp430_ir_interrupt,
|
||||
(unsigned long) budget_ci);
|
||||
|
||||
msp430_ir_init(budget_ci);
|
||||
err = msp430_ir_init(budget_ci);
|
||||
if (err)
|
||||
goto out3;
|
||||
|
||||
ciintf_init(budget_ci);
|
||||
|
||||
|
@ -1110,6 +1166,13 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
|
|||
ttpci_budget_init_hooks(&budget_ci->budget);
|
||||
|
||||
return 0;
|
||||
|
||||
out3:
|
||||
ttpci_budget_deinit(&budget_ci->budget);
|
||||
out2:
|
||||
kfree(budget_ci);
|
||||
out1:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int budget_ci_detach(struct saa7146_dev *dev)
|
||||
|
@ -1120,16 +1183,13 @@ static int budget_ci_detach(struct saa7146_dev *dev)
|
|||
|
||||
if (budget_ci->budget.ci_present)
|
||||
ciintf_deinit(budget_ci);
|
||||
msp430_ir_deinit(budget_ci);
|
||||
if (budget_ci->budget.dvb_frontend) {
|
||||
dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
|
||||
dvb_frontend_detach(budget_ci->budget.dvb_frontend);
|
||||
}
|
||||
err = ttpci_budget_deinit(&budget_ci->budget);
|
||||
|
||||
tasklet_kill(&budget_ci->msp430_irq_tasklet);
|
||||
|
||||
msp430_ir_deinit(budget_ci);
|
||||
|
||||
// disable frontend and CI interface
|
||||
saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
|
||||
|
||||
|
@ -1162,7 +1222,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
|
|||
|
||||
static struct saa7146_extension budget_extension = {
|
||||
.name = "budget_ci dvb",
|
||||
.flags = SAA7146_I2C_SHORT_DELAY,
|
||||
.flags = SAA7146_USE_I2C_IRQ,
|
||||
|
||||
.module = THIS_MODULE,
|
||||
.pci_tbl = &pci_tbl[0],
|
||||
|
|
|
@ -555,7 +555,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
|
|||
|
||||
static struct saa7146_extension budget_extension = {
|
||||
.name = "budget dvb",
|
||||
.flags = SAA7146_I2C_SHORT_DELAY,
|
||||
.flags = SAA7146_USE_I2C_IRQ,
|
||||
|
||||
.module = THIS_MODULE,
|
||||
.pci_tbl = pci_tbl,
|
||||
|
|
|
@ -238,6 +238,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
|
|||
* for now lets report each signal as a key down and up*/
|
||||
dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
|
||||
input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
|
||||
input_sync(dec->rc_input_dev);
|
||||
input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
|
||||
input_sync(dec->rc_input_dev);
|
||||
}
|
||||
|
@ -1187,11 +1188,12 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
|
|||
struct input_dev *input_dev;
|
||||
u8 b[] = { 0x00, 0x01 };
|
||||
int i;
|
||||
int err;
|
||||
|
||||
usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys));
|
||||
strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys));
|
||||
|
||||
dec->rc_input_dev = input_dev = input_allocate_device();
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1205,8 +1207,13 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
|
|||
for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
|
||||
set_bit(rc_keys[i], input_dev->keybit);
|
||||
|
||||
input_register_device(input_dev);
|
||||
err = input_register_device(input_dev);
|
||||
if (err) {
|
||||
input_free_device(input_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
dec->rc_input_dev = input_dev;
|
||||
if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
|
||||
printk("%s: usb_submit_urb failed\n",__FUNCTION__);
|
||||
/* enable irq pipe */
|
||||
|
|
|
@ -184,6 +184,14 @@ config VIDEO_KS0127
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called ks0127.
|
||||
|
||||
config VIDEO_OV7670
|
||||
tristate "OmniVision OV7670 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the OmniVision
|
||||
OV7670 VGA camera. It currently only works with the M88ALP01
|
||||
controller.
|
||||
|
||||
config VIDEO_SAA7110
|
||||
tristate "Philips SAA7110 video decoder"
|
||||
depends on VIDEO_V4L1 && I2C
|
||||
|
@ -567,18 +575,6 @@ config VIDEO_ZORAN_AVS6EYES
|
|||
help
|
||||
Support for the AverMedia 6 Eyes video surveillance card.
|
||||
|
||||
config VIDEO_ZR36120
|
||||
tristate "Zoran ZR36120/36125 Video For Linux"
|
||||
depends on PCI && I2C && VIDEO_V4L1 && BROKEN
|
||||
help
|
||||
Support for ZR36120/ZR36125 based frame grabber/overlay boards.
|
||||
This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV,
|
||||
and Buster boards. Please read the material in
|
||||
<file:Documentation/video4linux/zr36120.txt> for more information.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called zr36120.
|
||||
|
||||
config VIDEO_MEYE
|
||||
tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
|
||||
depends on PCI && SONYPI && VIDEO_V4L1
|
||||
|
@ -670,6 +666,15 @@ config VIDEO_M32R_AR_M64278
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called arv.
|
||||
|
||||
config VIDEO_CAFE_CCIC
|
||||
tristate "Marvell 88ALP01 (Cafe) CMOS Camera Controller support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
select VIDEO_OV7670
|
||||
---help---
|
||||
This is a video4linux2 driver for the Marvell 88ALP01 integrated
|
||||
CMOS camera controller. This is the controller found on first-
|
||||
generation OLPC systems.
|
||||
|
||||
#
|
||||
# USB Multimedia device configuration
|
||||
#
|
||||
|
@ -681,6 +686,8 @@ source "drivers/media/video/pvrusb2/Kconfig"
|
|||
|
||||
source "drivers/media/video/em28xx/Kconfig"
|
||||
|
||||
source "drivers/media/video/usbvision/Kconfig"
|
||||
|
||||
source "drivers/media/video/usbvideo/Kconfig"
|
||||
|
||||
source "drivers/media/video/et61x251/Kconfig"
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# Makefile for the video capture/playback device drivers.
|
||||
#
|
||||
|
||||
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o
|
||||
zr36067-objs := zoran_procfs.o zoran_device.o \
|
||||
zoran_driver.o zoran_card.o
|
||||
tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \
|
||||
|
@ -23,7 +22,6 @@ obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
|
|||
obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
|
||||
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
|
||||
obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
|
||||
obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
|
||||
obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o
|
||||
|
@ -64,6 +62,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o
|
|||
obj-$(CONFIG_VIDEO_SAA7134) += ir-kbd-i2c.o saa7134/
|
||||
obj-$(CONFIG_VIDEO_CX88) += cx88/
|
||||
obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
|
||||
obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
|
||||
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
|
||||
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
|
||||
obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
|
||||
|
@ -92,6 +91,9 @@ obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
|
|||
obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
|
||||
obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
|
||||
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
|
||||
|
||||
obj-$(CONFIG_USB_DABUSB) += dabusb.o
|
||||
obj-$(CONFIG_USB_OV511) += ov511.o
|
||||
obj-$(CONFIG_USB_SE401) += se401.o
|
||||
|
|
|
@ -1793,7 +1793,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
|
|||
memset(i,0,sizeof(*i));
|
||||
i->index = n;
|
||||
i->type = V4L2_INPUT_TYPE_CAMERA;
|
||||
i->audioset = 0;
|
||||
i->audioset = 1;
|
||||
if (i->index == bttv_tvcards[btv->c.type].tuner) {
|
||||
sprintf(i->name, "Television");
|
||||
i->type = V4L2_INPUT_TYPE_TUNER;
|
||||
|
|
|
@ -259,24 +259,59 @@ static void bttv_rc5_timer_keyup(unsigned long data)
|
|||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
|
||||
{
|
||||
if (ir->polling) {
|
||||
init_timer(&ir->timer);
|
||||
ir->timer.function = bttv_input_timer;
|
||||
ir->timer.data = (unsigned long)btv;
|
||||
ir->timer.expires = jiffies + HZ;
|
||||
add_timer(&ir->timer);
|
||||
} else if (ir->rc5_gpio) {
|
||||
/* set timer_end for code completion */
|
||||
init_timer(&ir->timer_end);
|
||||
ir->timer_end.function = bttv_rc5_timer_end;
|
||||
ir->timer_end.data = (unsigned long)ir;
|
||||
|
||||
init_timer(&ir->timer_keyup);
|
||||
ir->timer_keyup.function = bttv_rc5_timer_keyup;
|
||||
ir->timer_keyup.data = (unsigned long)ir;
|
||||
}
|
||||
}
|
||||
|
||||
static void bttv_ir_stop(struct bttv *btv)
|
||||
{
|
||||
if (btv->remote->polling) {
|
||||
del_timer_sync(&btv->remote->timer);
|
||||
flush_scheduled_work();
|
||||
}
|
||||
|
||||
if (btv->remote->rc5_gpio) {
|
||||
u32 gpio;
|
||||
|
||||
del_timer_sync(&btv->remote->timer_end);
|
||||
flush_scheduled_work();
|
||||
|
||||
gpio = bttv_gpio_read(&btv->c);
|
||||
bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
|
||||
}
|
||||
}
|
||||
|
||||
int bttv_input_init(struct bttv *btv)
|
||||
{
|
||||
struct bttv_ir *ir;
|
||||
IR_KEYTAB_TYPE *ir_codes = NULL;
|
||||
struct input_dev *input_dev;
|
||||
int ir_type = IR_TYPE_OTHER;
|
||||
int err = -ENOMEM;
|
||||
|
||||
if (!btv->has_remote)
|
||||
return -ENODEV;
|
||||
|
||||
ir = kzalloc(sizeof(*ir),GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!ir || !input_dev) {
|
||||
kfree(ir);
|
||||
input_free_device(input_dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(ir,0,sizeof(*ir));
|
||||
if (!ir || !input_dev)
|
||||
goto err_out_free;
|
||||
|
||||
/* detect & configure */
|
||||
switch (btv->c.type) {
|
||||
|
@ -348,10 +383,9 @@ int bttv_input_init(struct bttv *btv)
|
|||
break;
|
||||
}
|
||||
if (NULL == ir_codes) {
|
||||
dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type);
|
||||
kfree(ir);
|
||||
input_free_device(input_dev);
|
||||
return -ENODEV;
|
||||
dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
|
||||
err = -ENODEV;
|
||||
goto err_out_free;
|
||||
}
|
||||
|
||||
if (ir->rc5_gpio) {
|
||||
|
@ -389,32 +423,26 @@ int bttv_input_init(struct bttv *btv)
|
|||
input_dev->cdev.dev = &btv->c.pci->dev;
|
||||
|
||||
btv->remote = ir;
|
||||
if (ir->polling) {
|
||||
init_timer(&ir->timer);
|
||||
ir->timer.function = bttv_input_timer;
|
||||
ir->timer.data = (unsigned long)btv;
|
||||
ir->timer.expires = jiffies + HZ;
|
||||
add_timer(&ir->timer);
|
||||
} else if (ir->rc5_gpio) {
|
||||
/* set timer_end for code completion */
|
||||
init_timer(&ir->timer_end);
|
||||
ir->timer_end.function = bttv_rc5_timer_end;
|
||||
ir->timer_end.data = (unsigned long)ir;
|
||||
|
||||
init_timer(&ir->timer_keyup);
|
||||
ir->timer_keyup.function = bttv_rc5_timer_keyup;
|
||||
ir->timer_keyup.data = (unsigned long)ir;
|
||||
}
|
||||
bttv_ir_start(btv, ir);
|
||||
|
||||
/* all done */
|
||||
input_register_device(btv->remote->dev);
|
||||
printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys);
|
||||
err = input_register_device(btv->remote->dev);
|
||||
if (err)
|
||||
goto err_out_stop;
|
||||
|
||||
/* the remote isn't as bouncy as a keyboard */
|
||||
ir->dev->rep[REP_DELAY] = repeat_delay;
|
||||
ir->dev->rep[REP_PERIOD] = repeat_period;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_stop:
|
||||
bttv_ir_stop(btv);
|
||||
btv->remote = NULL;
|
||||
err_out_free:
|
||||
input_free_device(input_dev);
|
||||
kfree(ir);
|
||||
return err;
|
||||
}
|
||||
|
||||
void bttv_input_fini(struct bttv *btv)
|
||||
|
@ -422,22 +450,7 @@ void bttv_input_fini(struct bttv *btv)
|
|||
if (btv->remote == NULL)
|
||||
return;
|
||||
|
||||
if (btv->remote->polling) {
|
||||
del_timer_sync(&btv->remote->timer);
|
||||
flush_scheduled_work();
|
||||
}
|
||||
|
||||
|
||||
if (btv->remote->rc5_gpio) {
|
||||
u32 gpio;
|
||||
|
||||
del_timer_sync(&btv->remote->timer_end);
|
||||
flush_scheduled_work();
|
||||
|
||||
gpio = bttv_gpio_read(&btv->c);
|
||||
bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
|
||||
}
|
||||
|
||||
bttv_ir_stop(btv);
|
||||
input_unregister_device(btv->remote->dev);
|
||||
kfree(btv->remote);
|
||||
btv->remote = NULL;
|
||||
|
|
160
drivers/media/video/cafe_ccic-regs.h
Normal file
160
drivers/media/video/cafe_ccic-regs.h
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Register definitions for the m88alp01 camera interface. Offsets in bytes
|
||||
* as given in the spec.
|
||||
*
|
||||
* Copyright 2006 One Laptop Per Child Association, Inc.
|
||||
*
|
||||
* Written by Jonathan Corbet, corbet@lwn.net.
|
||||
*
|
||||
* This file may be distributed under the terms of the GNU General
|
||||
* Public License, version 2.
|
||||
*/
|
||||
#define REG_Y0BAR 0x00
|
||||
#define REG_Y1BAR 0x04
|
||||
#define REG_Y2BAR 0x08
|
||||
/* ... */
|
||||
|
||||
#define REG_IMGPITCH 0x24 /* Image pitch register */
|
||||
#define IMGP_YP_SHFT 2 /* Y pitch params */
|
||||
#define IMGP_YP_MASK 0x00003ffc /* Y pitch field */
|
||||
#define IMGP_UVP_SHFT 18 /* UV pitch (planar) */
|
||||
#define IMGP_UVP_MASK 0x3ffc0000
|
||||
#define REG_IRQSTATRAW 0x28 /* RAW IRQ Status */
|
||||
#define IRQ_EOF0 0x00000001 /* End of frame 0 */
|
||||
#define IRQ_EOF1 0x00000002 /* End of frame 1 */
|
||||
#define IRQ_EOF2 0x00000004 /* End of frame 2 */
|
||||
#define IRQ_SOF0 0x00000008 /* Start of frame 0 */
|
||||
#define IRQ_SOF1 0x00000010 /* Start of frame 1 */
|
||||
#define IRQ_SOF2 0x00000020 /* Start of frame 2 */
|
||||
#define IRQ_OVERFLOW 0x00000040 /* FIFO overflow */
|
||||
#define IRQ_TWSIW 0x00010000 /* TWSI (smbus) write */
|
||||
#define IRQ_TWSIR 0x00020000 /* TWSI read */
|
||||
#define IRQ_TWSIE 0x00040000 /* TWSI error */
|
||||
#define TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE)
|
||||
#define FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2)
|
||||
#define ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW)
|
||||
#define REG_IRQMASK 0x2c /* IRQ mask - same bits as IRQSTAT */
|
||||
#define REG_IRQSTAT 0x30 /* IRQ status / clear */
|
||||
|
||||
#define REG_IMGSIZE 0x34 /* Image size */
|
||||
#define IMGSZ_V_MASK 0x1fff0000
|
||||
#define IMGSZ_V_SHIFT 16
|
||||
#define IMGSZ_H_MASK 0x00003fff
|
||||
#define REG_IMGOFFSET 0x38 /* IMage offset */
|
||||
|
||||
#define REG_CTRL0 0x3c /* Control 0 */
|
||||
#define C0_ENABLE 0x00000001 /* Makes the whole thing go */
|
||||
|
||||
/* Mask for all the format bits */
|
||||
#define C0_DF_MASK 0x00fffffc /* Bits 2-23 */
|
||||
|
||||
/* RGB ordering */
|
||||
#define C0_RGB4_RGBX 0x00000000
|
||||
#define C0_RGB4_XRGB 0x00000004
|
||||
#define C0_RGB4_BGRX 0x00000008
|
||||
#define C0_RGB4_XBGR 0x0000000c
|
||||
#define C0_RGB5_RGGB 0x00000000
|
||||
#define C0_RGB5_GRBG 0x00000004
|
||||
#define C0_RGB5_GBRG 0x00000008
|
||||
#define C0_RGB5_BGGR 0x0000000c
|
||||
|
||||
/* Spec has two fields for DIN and DOUT, but they must match, so
|
||||
combine them here. */
|
||||
#define C0_DF_YUV 0x00000000 /* Data is YUV */
|
||||
#define C0_DF_RGB 0x000000a0 /* ... RGB */
|
||||
#define C0_DF_BAYER 0x00000140 /* ... Bayer */
|
||||
/* 8-8-8 must be missing from the below - ask */
|
||||
#define C0_RGBF_565 0x00000000
|
||||
#define C0_RGBF_444 0x00000800
|
||||
#define C0_RGB_BGR 0x00001000 /* Blue comes first */
|
||||
#define C0_YUV_PLANAR 0x00000000 /* YUV 422 planar format */
|
||||
#define C0_YUV_PACKED 0x00008000 /* YUV 422 packed */
|
||||
#define C0_YUV_420PL 0x0000a000 /* YUV 420 planar */
|
||||
/* Think that 420 packed must be 111 - ask */
|
||||
#define C0_YUVE_YUYV 0x00000000 /* Y1CbY0Cr */
|
||||
#define C0_YUVE_YVYU 0x00010000 /* Y1CrY0Cb */
|
||||
#define C0_YUVE_VYUY 0x00020000 /* CrY1CbY0 */
|
||||
#define C0_YUVE_UYVY 0x00030000 /* CbY1CrY0 */
|
||||
#define C0_YUVE_XYUV 0x00000000 /* 420: .YUV */
|
||||
#define C0_YUVE_XYVU 0x00010000 /* 420: .YVU */
|
||||
#define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */
|
||||
#define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */
|
||||
/* Bayer bits 18,19 if needed */
|
||||
#define C0_HPOL_LOW 0x01000000 /* HSYNC polarity active low */
|
||||
#define C0_VPOL_LOW 0x02000000 /* VSYNC polarity active low */
|
||||
#define C0_VCLK_LOW 0x04000000 /* VCLK on falling edge */
|
||||
#define C0_DOWNSCALE 0x08000000 /* Enable downscaler */
|
||||
#define C0_SIFM_MASK 0xc0000000 /* SIF mode bits */
|
||||
#define C0_SIF_HVSYNC 0x00000000 /* Use H/VSYNC */
|
||||
#define CO_SOF_NOSYNC 0x40000000 /* Use inband active signaling */
|
||||
|
||||
|
||||
#define REG_CTRL1 0x40 /* Control 1 */
|
||||
#define C1_444ALPHA 0x00f00000 /* Alpha field in RGB444 */
|
||||
#define C1_ALPHA_SHFT 20
|
||||
#define C1_DMAB32 0x00000000 /* 32-byte DMA burst */
|
||||
#define C1_DMAB16 0x02000000 /* 16-byte DMA burst */
|
||||
#define C1_DMAB64 0x04000000 /* 64-byte DMA burst */
|
||||
#define C1_DMAB_MASK 0x06000000
|
||||
#define C1_TWOBUFS 0x08000000 /* Use only two DMA buffers */
|
||||
#define C1_PWRDWN 0x10000000 /* Power down */
|
||||
|
||||
#define REG_CLKCTRL 0x88 /* Clock control */
|
||||
#define CLK_DIV_MASK 0x0000ffff /* Upper bits RW "reserved" */
|
||||
|
||||
#define REG_GPR 0xb4 /* General purpose register. This
|
||||
controls inputs to the power and reset
|
||||
pins on the OV7670 used with OLPC;
|
||||
other deployments could differ. */
|
||||
#define GPR_C1EN 0x00000020 /* Pad 1 (power down) enable */
|
||||
#define GPR_C0EN 0x00000010 /* Pad 0 (reset) enable */
|
||||
#define GPR_C1 0x00000002 /* Control 1 value */
|
||||
/*
|
||||
* Control 0 is wired to reset on OLPC machines. For ov7x sensors,
|
||||
* it is active low, for 0v6x, instead, it's active high. What
|
||||
* fun.
|
||||
*/
|
||||
#define GPR_C0 0x00000001 /* Control 0 value */
|
||||
|
||||
#define REG_TWSIC0 0xb8 /* TWSI (smbus) control 0 */
|
||||
#define TWSIC0_EN 0x00000001 /* TWSI enable */
|
||||
#define TWSIC0_MODE 0x00000002 /* 1 = 16-bit, 0 = 8-bit */
|
||||
#define TWSIC0_SID 0x000003fc /* Slave ID */
|
||||
#define TWSIC0_SID_SHIFT 2
|
||||
#define TWSIC0_CLKDIV 0x0007fc00 /* Clock divider */
|
||||
#define TWSIC0_MASKACK 0x00400000 /* Mask ack from sensor */
|
||||
#define TWSIC0_OVMAGIC 0x00800000 /* Make it work on OV sensors */
|
||||
|
||||
#define REG_TWSIC1 0xbc /* TWSI control 1 */
|
||||
#define TWSIC1_DATA 0x0000ffff /* Data to/from camchip */
|
||||
#define TWSIC1_ADDR 0x00ff0000 /* Address (register) */
|
||||
#define TWSIC1_ADDR_SHIFT 16
|
||||
#define TWSIC1_READ 0x01000000 /* Set for read op */
|
||||
#define TWSIC1_WSTAT 0x02000000 /* Write status */
|
||||
#define TWSIC1_RVALID 0x04000000 /* Read data valid */
|
||||
#define TWSIC1_ERROR 0x08000000 /* Something screwed up */
|
||||
|
||||
|
||||
#define REG_UBAR 0xc4 /* Upper base address register */
|
||||
|
||||
/*
|
||||
* Here's the weird global control registers which are said to live
|
||||
* way up here.
|
||||
*/
|
||||
#define REG_GL_CSR 0x3004 /* Control/status register */
|
||||
#define GCSR_SRS 0x00000001 /* SW Reset set */
|
||||
#define GCSR_SRC 0x00000002 /* SW Reset clear */
|
||||
#define GCSR_MRS 0x00000004 /* Master reset set */
|
||||
#define GCSR_MRC 0x00000008 /* HW Reset clear */
|
||||
#define GCSR_CCIC_EN 0x00004000 /* CCIC Clock enable */
|
||||
#define REG_GL_IMASK 0x300c /* Interrupt mask register */
|
||||
#define GIMSK_CCIC_EN 0x00000004 /* CCIC Interrupt enable */
|
||||
|
||||
#define REG_LEN REG_GL_IMASK + 4
|
||||
|
||||
|
||||
/*
|
||||
* Useful stuff that probably belongs somewhere global.
|
||||
*/
|
||||
#define VGA_WIDTH 640
|
||||
#define VGA_HEIGHT 480
|
2228
drivers/media/video/cafe_ccic.c
Normal file
2228
drivers/media/video/cafe_ccic.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -53,6 +53,7 @@ config VIDEO_CX88_DVB
|
|||
select DVB_OR51132 if !DVB_FE_CUSTOMISE
|
||||
select DVB_CX22702 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
|
||||
select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
|
||||
select DVB_NXT200X if !DVB_FE_CUSTOMISE
|
||||
select DVB_CX24123 if !DVB_FE_CUSTOMISE
|
||||
select DVB_ISL6421 if !DVB_FE_CUSTOMISE
|
||||
|
|
|
@ -50,7 +50,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
|
|||
#define dprintk(level,fmt, arg...) if (debug >= level) \
|
||||
printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
|
||||
|
||||
static LIST_HEAD(cx8802_devlist);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
|
@ -882,7 +881,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
|
|||
BLACKBIRD_MPEG_CAPTURE,
|
||||
BLACKBIRD_RAW_BITS_NONE);
|
||||
|
||||
cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
|
||||
cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
|
||||
|
||||
blackbird_initialize_codec(dev);
|
||||
cx88_set_scale(dev->core, dev->width, dev->height,
|
||||
|
@ -914,11 +913,15 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
|
|||
}
|
||||
|
||||
default:
|
||||
return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
|
||||
return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, void *arg);
|
||||
unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
|
||||
|
||||
static unsigned int mpeg_translate_ioctl(unsigned int cmd)
|
||||
{
|
||||
return cmd;
|
||||
|
@ -927,33 +930,49 @@ static unsigned int mpeg_translate_ioctl(unsigned int cmd)
|
|||
static int mpeg_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
cmd = mpeg_translate_ioctl( cmd );
|
||||
return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
|
||||
cmd = cx88_ioctl_translator( cmd );
|
||||
return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
|
||||
}
|
||||
|
||||
static int mpeg_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int minor = iminor(inode);
|
||||
struct cx8802_dev *h,*dev = NULL;
|
||||
struct cx8802_dev *dev = NULL;
|
||||
struct cx8802_fh *fh;
|
||||
struct list_head *list;
|
||||
struct cx8802_driver *drv = NULL;
|
||||
int err;
|
||||
|
||||
list_for_each(list,&cx8802_devlist) {
|
||||
h = list_entry(list, struct cx8802_dev, devlist);
|
||||
if (h->mpeg_dev->minor == minor)
|
||||
dev = h;
|
||||
}
|
||||
if (NULL == dev)
|
||||
dev = cx8802_get_device(inode);
|
||||
|
||||
dprintk( 1, "%s\n", __FUNCTION__);
|
||||
|
||||
if (dev == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (blackbird_initialize_codec(dev) < 0)
|
||||
/* Make sure we can acquire the hardware */
|
||||
drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
|
||||
if (drv) {
|
||||
err = drv->request_acquire(drv);
|
||||
if(err != 0) {
|
||||
dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (blackbird_initialize_codec(dev) < 0) {
|
||||
if (drv)
|
||||
drv->request_release(drv);
|
||||
return -EINVAL;
|
||||
}
|
||||
dprintk(1,"open minor=%d\n",minor);
|
||||
|
||||
/* allocate + initialize per filehandle data */
|
||||
fh = kzalloc(sizeof(*fh),GFP_KERNEL);
|
||||
if (NULL == fh)
|
||||
if (NULL == fh) {
|
||||
if (drv)
|
||||
drv->request_release(drv);
|
||||
return -ENOMEM;
|
||||
}
|
||||
file->private_data = fh;
|
||||
fh->dev = dev;
|
||||
|
||||
|
@ -974,6 +993,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
|
|||
static int mpeg_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct cx8802_fh *fh = file->private_data;
|
||||
struct cx8802_dev *dev = NULL;
|
||||
struct cx8802_driver *drv = NULL;
|
||||
|
||||
/* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
|
||||
blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
|
||||
|
@ -992,6 +1013,16 @@ static int mpeg_release(struct inode *inode, struct file *file)
|
|||
videobuf_mmap_free(&fh->mpegq);
|
||||
file->private_data = NULL;
|
||||
kfree(fh);
|
||||
|
||||
/* Make sure we release the hardware */
|
||||
dev = cx8802_get_device(inode);
|
||||
if (dev == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
|
||||
if (drv)
|
||||
drv->request_release(drv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1043,6 +1074,44 @@ static struct video_device cx8802_mpeg_template =
|
|||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/* The CX8802 MPEG API will call this when we can use the hardware */
|
||||
static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx88_core *core = drv->core;
|
||||
int err = 0;
|
||||
|
||||
switch (core->board) {
|
||||
case CX88_BOARD_HAUPPAUGE_HVR1300:
|
||||
/* By default, core setup will leave the cx22702 out of reset, on the bus.
|
||||
* We left the hardware on power up with the cx22702 active.
|
||||
* We're being given access to re-arrange the GPIOs.
|
||||
* Take the bus off the cx22702 and put the cx23416 on it.
|
||||
*/
|
||||
cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */
|
||||
cx_set(MO_GP0_IO, 0x00000004); /* Disable the cx22702 */
|
||||
break;
|
||||
default:
|
||||
err = -ENODEV;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* The CX8802 MPEG API will call this when we need to release the hardware */
|
||||
static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx88_core *core = drv->core;
|
||||
int err = 0;
|
||||
|
||||
switch (core->board) {
|
||||
case CX88_BOARD_HAUPPAUGE_HVR1300:
|
||||
/* Exit leaving the cx23416 on the bus */
|
||||
break;
|
||||
default:
|
||||
err = -ENODEV;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void blackbird_unregister_video(struct cx8802_dev *dev)
|
||||
{
|
||||
if (dev->mpeg_dev) {
|
||||
|
@ -1073,28 +1142,23 @@ static int blackbird_register_video(struct cx8802_dev *dev)
|
|||
|
||||
/* ----------------------------------------------------------- */
|
||||
|
||||
static int __devinit blackbird_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *pci_id)
|
||||
static int cx8802_blackbird_probe(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx8802_dev *dev;
|
||||
struct cx88_core *core;
|
||||
struct cx88_core *core = drv->core;
|
||||
struct cx8802_dev *dev = core->dvbdev;
|
||||
int err;
|
||||
|
||||
/* general setup */
|
||||
core = cx88_core_get(pci_dev);
|
||||
if (NULL == core)
|
||||
return -EINVAL;
|
||||
dprintk( 1, "%s\n", __FUNCTION__);
|
||||
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
|
||||
core->board,
|
||||
core->name,
|
||||
core->pci_bus,
|
||||
core->pci_slot);
|
||||
|
||||
err = -ENODEV;
|
||||
if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))
|
||||
goto fail_core;
|
||||
|
||||
err = -ENOMEM;
|
||||
dev = kzalloc(sizeof(*dev),GFP_KERNEL);
|
||||
if (NULL == dev)
|
||||
goto fail_core;
|
||||
dev->pci = pci_dev;
|
||||
dev->core = core;
|
||||
dev->width = 720;
|
||||
dev->height = 576;
|
||||
cx2341x_fill_defaults(&dev->params);
|
||||
|
@ -1106,64 +1170,36 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
|
|||
dev->height = 576;
|
||||
}
|
||||
|
||||
err = cx8802_init_common(dev);
|
||||
if (0 != err)
|
||||
goto fail_free;
|
||||
|
||||
/* blackbird stuff */
|
||||
printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
|
||||
core->name);
|
||||
host_setup(dev->core);
|
||||
|
||||
list_add_tail(&dev->devlist,&cx8802_devlist);
|
||||
blackbird_register_video(dev);
|
||||
|
||||
/* initial device configuration: needed ? */
|
||||
|
||||
return 0;
|
||||
|
||||
fail_free:
|
||||
kfree(dev);
|
||||
fail_core:
|
||||
cx88_core_put(core,pci_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit blackbird_remove(struct pci_dev *pci_dev)
|
||||
static int cx8802_blackbird_remove(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
|
||||
|
||||
/* blackbird */
|
||||
blackbird_unregister_video(dev);
|
||||
list_del(&dev->devlist);
|
||||
blackbird_unregister_video(drv->core->dvbdev);
|
||||
|
||||
/* common */
|
||||
cx8802_fini_common(dev);
|
||||
cx88_core_put(dev->core,dev->pci);
|
||||
kfree(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pci_device_id cx8802_pci_tbl[] = {
|
||||
{
|
||||
.vendor = 0x14f1,
|
||||
.device = 0x8802,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
},{
|
||||
/* --- end of list --- */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
|
||||
|
||||
static struct pci_driver blackbird_pci_driver = {
|
||||
.name = "cx88-blackbird",
|
||||
.id_table = cx8802_pci_tbl,
|
||||
.probe = blackbird_probe,
|
||||
.remove = __devexit_p(blackbird_remove),
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = cx8802_suspend_common,
|
||||
.resume = cx8802_resume_common,
|
||||
#endif
|
||||
static struct cx8802_driver cx8802_blackbird_driver = {
|
||||
.type_id = CX88_MPEG_BLACKBIRD,
|
||||
.hw_access = CX8802_DRVCTL_SHARED,
|
||||
.probe = cx8802_blackbird_probe,
|
||||
.remove = cx8802_blackbird_remove,
|
||||
.advise_acquire = cx8802_blackbird_advise_acquire,
|
||||
.advise_release = cx8802_blackbird_advise_release,
|
||||
};
|
||||
|
||||
static int blackbird_init(void)
|
||||
|
@ -1176,17 +1212,22 @@ static int blackbird_init(void)
|
|||
printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
|
||||
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
|
||||
#endif
|
||||
return pci_register_driver(&blackbird_pci_driver);
|
||||
cx88_ioctl_hook = mpeg_do_ioctl;
|
||||
cx88_ioctl_translator = mpeg_translate_ioctl;
|
||||
return cx8802_register_driver(&cx8802_blackbird_driver);
|
||||
}
|
||||
|
||||
static void blackbird_fini(void)
|
||||
{
|
||||
pci_unregister_driver(&blackbird_pci_driver);
|
||||
cx8802_unregister_driver(&cx8802_blackbird_driver);
|
||||
}
|
||||
|
||||
module_init(blackbird_init);
|
||||
module_exit(blackbird_fini);
|
||||
|
||||
EXPORT_SYMBOL(cx88_ioctl_hook);
|
||||
EXPORT_SYMBOL(cx88_ioctl_translator);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/*
|
||||
* Local variables:
|
||||
|
|
|
@ -281,18 +281,22 @@ struct cx88_board cx88_boards[] = {
|
|||
.type = CX88_VMUX_TELEVISION,
|
||||
.vmux = 0,
|
||||
.gpio0 = 0x0000bde2,
|
||||
.extadc = 1,
|
||||
},{
|
||||
.type = CX88_VMUX_COMPOSITE1,
|
||||
.vmux = 1,
|
||||
.gpio0 = 0x0000bde6,
|
||||
.extadc = 1,
|
||||
},{
|
||||
.type = CX88_VMUX_SVIDEO,
|
||||
.vmux = 2,
|
||||
.gpio0 = 0x0000bde6,
|
||||
.extadc = 1,
|
||||
}},
|
||||
.radio = {
|
||||
.type = CX88_RADIO,
|
||||
.gpio0 = 0x0000bd62,
|
||||
.extadc = 1,
|
||||
},
|
||||
.mpeg = CX88_MPEG_BLACKBIRD,
|
||||
},
|
||||
|
@ -353,6 +357,7 @@ struct cx88_board cx88_boards[] = {
|
|||
.type = CX88_VMUX_SVIDEO,
|
||||
.vmux = 2,
|
||||
.gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
|
||||
.extadc = 1,
|
||||
}},
|
||||
.radio = {
|
||||
.type = CX88_RADIO,
|
||||
|
@ -523,6 +528,7 @@ struct cx88_board cx88_boards[] = {
|
|||
.input = {{
|
||||
.type = CX88_VMUX_TELEVISION,
|
||||
.vmux = 0,
|
||||
.extadc = 1,
|
||||
}},
|
||||
.mpeg = CX88_MPEG_BLACKBIRD,
|
||||
},
|
||||
|
@ -646,18 +652,22 @@ struct cx88_board cx88_boards[] = {
|
|||
.type = CX88_VMUX_TELEVISION,
|
||||
.vmux = 0,
|
||||
.gpio0 = 0x00009d80,
|
||||
.extadc = 1,
|
||||
},{
|
||||
.type = CX88_VMUX_COMPOSITE1,
|
||||
.vmux = 1,
|
||||
.gpio0 = 0x00009d76,
|
||||
.extadc = 1,
|
||||
},{
|
||||
.type = CX88_VMUX_SVIDEO,
|
||||
.vmux = 2,
|
||||
.gpio0 = 0x00009d76,
|
||||
.extadc = 1,
|
||||
}},
|
||||
.radio = {
|
||||
.type = CX88_RADIO,
|
||||
.gpio0 = 0x00009d00,
|
||||
.extadc = 1,
|
||||
},
|
||||
.mpeg = CX88_MPEG_BLACKBIRD,
|
||||
},
|
||||
|
@ -786,25 +796,29 @@ struct cx88_board cx88_boards[] = {
|
|||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.tda9887_conf = TDA9887_PRESENT,
|
||||
.mpeg = CX88_MPEG_BLACKBIRD,
|
||||
.input = {{
|
||||
.type = CX88_VMUX_COMPOSITE1,
|
||||
.vmux = 0,
|
||||
.gpio0 = 0x0000cd73,
|
||||
.extadc = 1,
|
||||
},{
|
||||
.type = CX88_VMUX_SVIDEO,
|
||||
.vmux = 1,
|
||||
.gpio0 = 0x0000cd73,
|
||||
.extadc = 1,
|
||||
},{
|
||||
.type = CX88_VMUX_TELEVISION,
|
||||
.vmux = 3,
|
||||
.gpio0 = 0x0000cdb3,
|
||||
.extadc = 1,
|
||||
}},
|
||||
.radio = {
|
||||
.type = CX88_RADIO,
|
||||
.vmux = 2,
|
||||
.gpio0 = 0x0000cdf3,
|
||||
.extadc = 1,
|
||||
},
|
||||
.mpeg = CX88_MPEG_BLACKBIRD,
|
||||
},
|
||||
[CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = {
|
||||
/* Alexander Wold <awold@bigfoot.com> */
|
||||
|
@ -1050,7 +1064,6 @@ struct cx88_board cx88_boards[] = {
|
|||
.mpeg = CX88_MPEG_DVB,
|
||||
},
|
||||
[CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
|
||||
/* FIXME: Audio not working for s-video / composite inputs. */
|
||||
.name = "KWorld HardwareMpegTV XPert",
|
||||
.tuner_type = TUNER_PHILIPS_TDA8290,
|
||||
.radio_type = UNSET,
|
||||
|
@ -1065,10 +1078,12 @@ struct cx88_board cx88_boards[] = {
|
|||
.type = CX88_VMUX_COMPOSITE1,
|
||||
.vmux = 1,
|
||||
.gpio0 = 0x3de6,
|
||||
.extadc = 1,
|
||||
},{
|
||||
.type = CX88_VMUX_SVIDEO,
|
||||
.vmux = 2,
|
||||
.gpio0 = 0x3de6,
|
||||
.extadc = 1,
|
||||
}},
|
||||
.radio = {
|
||||
.type = CX88_RADIO,
|
||||
|
@ -1252,35 +1267,35 @@ struct cx88_board cx88_boards[] = {
|
|||
.gpio0 = 0x070b,
|
||||
}},
|
||||
},
|
||||
[CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
|
||||
.name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
|
||||
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.input = {{
|
||||
.type = CX88_VMUX_TELEVISION,
|
||||
.vmux = 0,
|
||||
.gpio0 = 0x003fffff,
|
||||
.gpio1 = 0x00e00000,
|
||||
.gpio2 = 0x003fffff,
|
||||
.gpio3 = 0x02000000,
|
||||
},{
|
||||
.type = CX88_VMUX_COMPOSITE1,
|
||||
.vmux = 1,
|
||||
.gpio0 = 0x003fffff,
|
||||
.gpio1 = 0x00e00000,
|
||||
.gpio2 = 0x003fffff,
|
||||
.gpio3 = 0x02000000,
|
||||
[CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
|
||||
.name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
|
||||
.tuner_type = TUNER_LG_PAL_NEW_TAPC,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.input = {{
|
||||
.type = CX88_VMUX_TELEVISION,
|
||||
.vmux = 0,
|
||||
.gpio0 = 0x003fffff,
|
||||
.gpio1 = 0x00e00000,
|
||||
.gpio2 = 0x003fffff,
|
||||
.gpio3 = 0x02000000,
|
||||
},{
|
||||
.type = CX88_VMUX_SVIDEO,
|
||||
.vmux = 2,
|
||||
.gpio0 = 0x003fffff,
|
||||
.gpio1 = 0x00e00000,
|
||||
.gpio2 = 0x003fffff,
|
||||
.gpio3 = 0x02000000,
|
||||
}},
|
||||
},
|
||||
.type = CX88_VMUX_COMPOSITE1,
|
||||
.vmux = 1,
|
||||
.gpio0 = 0x003fffff,
|
||||
.gpio1 = 0x00e00000,
|
||||
.gpio2 = 0x003fffff,
|
||||
.gpio3 = 0x02000000,
|
||||
},{
|
||||
.type = CX88_VMUX_SVIDEO,
|
||||
.vmux = 2,
|
||||
.gpio0 = 0x003fffff,
|
||||
.gpio1 = 0x00e00000,
|
||||
.gpio2 = 0x003fffff,
|
||||
.gpio3 = 0x02000000,
|
||||
}},
|
||||
},
|
||||
[CX88_BOARD_HAUPPAUGE_HVR1300] = {
|
||||
.name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder",
|
||||
.tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
|
||||
|
@ -1293,17 +1308,20 @@ struct cx88_board cx88_boards[] = {
|
|||
.type = CX88_VMUX_TELEVISION,
|
||||
.vmux = 0,
|
||||
.gpio0 = 0xe780,
|
||||
.extadc = 1,
|
||||
},{
|
||||
.type = CX88_VMUX_COMPOSITE1,
|
||||
.vmux = 1,
|
||||
.gpio0 = 0xe780,
|
||||
.extadc = 1,
|
||||
},{
|
||||
.type = CX88_VMUX_SVIDEO,
|
||||
.vmux = 2,
|
||||
.gpio0 = 0xe780,
|
||||
.extadc = 1,
|
||||
}},
|
||||
/* fixme: Add radio support */
|
||||
.mpeg = CX88_MPEG_DVB,
|
||||
.mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
|
||||
},
|
||||
};
|
||||
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
|
||||
|
@ -1513,6 +1531,10 @@ struct cx88_subid cx88_subids[] = {
|
|||
},{
|
||||
.subvendor = 0x17de,
|
||||
.subdevice = 0x0840,
|
||||
.card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
|
||||
},{
|
||||
.subvendor = 0x1421,
|
||||
.subdevice = 0x0305,
|
||||
.card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
|
||||
},{
|
||||
.subvendor = 0x18ac,
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include "cx22702.h"
|
||||
#include "or51132.h"
|
||||
#include "lgdt330x.h"
|
||||
#include "lg_h06xf.h"
|
||||
#include "lgh06xf.h"
|
||||
#include "nxt200x.h"
|
||||
#include "cx24123.h"
|
||||
#include "isl6421.h"
|
||||
|
@ -57,7 +57,7 @@ module_param(debug, int, 0644);
|
|||
MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
|
||||
|
||||
#define dprintk(level,fmt, arg...) if (debug >= level) \
|
||||
printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg)
|
||||
printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
|
@ -74,8 +74,8 @@ static int dvb_buf_setup(struct videobuf_queue *q,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
|
||||
enum v4l2_field field)
|
||||
static int dvb_buf_prepare(struct videobuf_queue *q,
|
||||
struct videobuf_buffer *vb, enum v4l2_field field)
|
||||
{
|
||||
struct cx8802_dev *dev = q->priv_data;
|
||||
return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
|
||||
|
@ -87,7 +87,8 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
|||
cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
|
||||
}
|
||||
|
||||
static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
||||
static void dvb_buf_release(struct videobuf_queue *q,
|
||||
struct videobuf_buffer *vb)
|
||||
{
|
||||
cx88_free_buffer(q, (struct cx88_buffer*)vb);
|
||||
}
|
||||
|
@ -100,6 +101,26 @@ static struct videobuf_queue_ops dvb_qops = {
|
|||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
|
||||
{
|
||||
struct cx8802_dev *dev= fe->dvb->priv;
|
||||
struct cx8802_driver *drv = NULL;
|
||||
int ret = 0;
|
||||
|
||||
drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
|
||||
if (drv) {
|
||||
if (acquire)
|
||||
ret = drv->request_acquire(drv);
|
||||
else
|
||||
ret = drv->request_release(drv);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
|
||||
{
|
||||
static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 };
|
||||
|
@ -268,35 +289,6 @@ static struct mt352_config dntv_live_dvbt_pro_config = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
u8 pllbuf[4];
|
||||
struct cx8802_dev *dev= fe->dvb->priv;
|
||||
struct i2c_msg msg =
|
||||
{ .addr = dev->core->pll_addr, .flags = 0,
|
||||
.buf = pllbuf, .len = 4 };
|
||||
int err;
|
||||
|
||||
dvb_pll_configure(dev->core->pll_desc, pllbuf,
|
||||
params->frequency,
|
||||
params->u.ofdm.bandwidth);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
|
||||
printk(KERN_WARNING "cx88-dvb: %s error "
|
||||
"(addr %02x <- %02x, err = %i)\n",
|
||||
__FUNCTION__, pllbuf[0], pllbuf[1], err);
|
||||
if (err < 0)
|
||||
return err;
|
||||
else
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct zl10353_config dvico_fusionhdtv_hybrid = {
|
||||
.demod_address = 0x0f,
|
||||
.no_tuner = 1,
|
||||
|
@ -311,28 +303,12 @@ static struct cx22702_config connexant_refboard_config = {
|
|||
.output_mode = CX22702_SERIAL_OUTPUT,
|
||||
};
|
||||
|
||||
static struct cx22702_config hauppauge_novat_config = {
|
||||
.demod_address = 0x43,
|
||||
.output_mode = CX22702_SERIAL_OUTPUT,
|
||||
};
|
||||
|
||||
static struct cx22702_config hauppauge_hvr1100_config = {
|
||||
static struct cx22702_config hauppauge_hvr_config = {
|
||||
.demod_address = 0x63,
|
||||
.output_mode = CX22702_SERIAL_OUTPUT,
|
||||
};
|
||||
|
||||
static struct cx22702_config hauppauge_hvr1300_config = {
|
||||
.demod_address = 0x63,
|
||||
.output_mode = CX22702_SERIAL_OUTPUT,
|
||||
};
|
||||
|
||||
static struct cx22702_config hauppauge_hvr3000_config = {
|
||||
.demod_address = 0x63,
|
||||
.output_mode = CX22702_SERIAL_OUTPUT,
|
||||
};
|
||||
|
||||
static int or51132_set_ts_param(struct dvb_frontend* fe,
|
||||
int is_punctured)
|
||||
static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured)
|
||||
{
|
||||
struct cx8802_dev *dev= fe->dvb->priv;
|
||||
dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
|
||||
|
@ -344,50 +320,6 @@ static struct or51132_config pchdtv_hd3000 = {
|
|||
.set_ts_params = or51132_set_ts_param,
|
||||
};
|
||||
|
||||
static int lgdt3302_tuner_set_params(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters* params)
|
||||
{
|
||||
/* FIXME make this routine use the tuner-simple code.
|
||||
* It could probably be shared with a number of ATSC
|
||||
* frontends. Many share the same tuner with analog TV. */
|
||||
|
||||
struct cx8802_dev *dev= fe->dvb->priv;
|
||||
struct cx88_core *core = dev->core;
|
||||
u8 buf[4];
|
||||
struct i2c_msg msg =
|
||||
{ .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
|
||||
int err;
|
||||
|
||||
dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
|
||||
dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
|
||||
__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
|
||||
printk(KERN_WARNING "cx88-dvb: %s error "
|
||||
"(addr %02x <- %02x, err = %i)\n",
|
||||
__FUNCTION__, buf[0], buf[1], err);
|
||||
if (err < 0)
|
||||
return err;
|
||||
else
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lgdt3303_tuner_set_params(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters* params)
|
||||
{
|
||||
struct cx8802_dev *dev= fe->dvb->priv;
|
||||
struct cx88_core *core = dev->core;
|
||||
|
||||
/* Put the analog decoder in standby to keep it quiet */
|
||||
cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
|
||||
|
||||
return lg_h06xf_pll_set(fe, &core->i2c_adap, params);
|
||||
}
|
||||
|
||||
static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
|
||||
{
|
||||
struct cx8802_dev *dev= fe->dvb->priv;
|
||||
|
@ -432,8 +364,7 @@ static struct lgdt330x_config pchdtv_hd5500 = {
|
|||
.set_ts_params = lgdt330x_set_ts_param,
|
||||
};
|
||||
|
||||
static int nxt200x_set_ts_param(struct dvb_frontend* fe,
|
||||
int is_punctured)
|
||||
static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
|
||||
{
|
||||
struct cx8802_dev *dev= fe->dvb->priv;
|
||||
dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
|
||||
|
@ -469,11 +400,10 @@ static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
|
|||
struct cx8802_dev *dev= fe->dvb->priv;
|
||||
struct cx88_core *core = dev->core;
|
||||
|
||||
if (voltage == SEC_VOLTAGE_OFF) {
|
||||
if (voltage == SEC_VOLTAGE_OFF)
|
||||
cx_write(MO_GP0_IO, 0x000006fb);
|
||||
} else {
|
||||
else
|
||||
cx_write(MO_GP0_IO, 0x000006f9);
|
||||
}
|
||||
|
||||
if (core->prev_set_voltage)
|
||||
return core->prev_set_voltage(fe, voltage);
|
||||
|
@ -522,7 +452,7 @@ static int dvb_register(struct cx8802_dev *dev)
|
|||
switch (dev->core->board) {
|
||||
case CX88_BOARD_HAUPPAUGE_DVB_T1:
|
||||
dev->dvb.frontend = dvb_attach(cx22702_attach,
|
||||
&hauppauge_novat_config,
|
||||
&connexant_refboard_config,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
|
||||
|
@ -547,32 +477,11 @@ static int dvb_register(struct cx8802_dev *dev)
|
|||
case CX88_BOARD_HAUPPAUGE_HVR1100:
|
||||
case CX88_BOARD_HAUPPAUGE_HVR1100LP:
|
||||
dev->dvb.frontend = dvb_attach(cx22702_attach,
|
||||
&hauppauge_hvr1100_config,
|
||||
&hauppauge_hvr_config,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
|
||||
&dev->core->i2c_adap,
|
||||
&dvb_pll_fmd1216me);
|
||||
}
|
||||
break;
|
||||
case CX88_BOARD_HAUPPAUGE_HVR1300:
|
||||
dev->dvb.frontend = dvb_attach(cx22702_attach,
|
||||
&hauppauge_hvr1300_config,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
|
||||
&dev->core->i2c_adap,
|
||||
&dvb_pll_fmd1216me);
|
||||
}
|
||||
break;
|
||||
case CX88_BOARD_HAUPPAUGE_HVR3000:
|
||||
dev->dvb.frontend = dvb_attach(cx22702_attach,
|
||||
&hauppauge_hvr3000_config,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
|
||||
&dev->core->i2c_adap,
|
||||
&dvb_pll_fmd1216me);
|
||||
&dev->core->i2c_adap, &dvb_pll_fmd1216me);
|
||||
}
|
||||
break;
|
||||
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
|
||||
|
@ -647,18 +556,17 @@ static int dvb_register(struct cx8802_dev *dev)
|
|||
#endif
|
||||
break;
|
||||
case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
|
||||
dev->core->pll_addr = 0x61;
|
||||
dev->core->pll_desc = &dvb_pll_thomson_fe6600;
|
||||
dev->dvb.frontend = dvb_attach(zl10353_attach,
|
||||
&dvico_fusionhdtv_hybrid,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params;
|
||||
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
|
||||
&dev->core->i2c_adap,
|
||||
&dvb_pll_thomson_fe6600);
|
||||
}
|
||||
break;
|
||||
case CX88_BOARD_PCHDTV_HD3000:
|
||||
dev->dvb.frontend = dvb_attach(or51132_attach,
|
||||
&pchdtv_hd3000,
|
||||
dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
|
||||
|
@ -679,13 +587,13 @@ static int dvb_register(struct cx8802_dev *dev)
|
|||
|
||||
/* Select RF connector callback */
|
||||
fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
|
||||
dev->core->pll_addr = 0x61;
|
||||
dev->core->pll_desc = &dvb_pll_microtune_4042;
|
||||
dev->dvb.frontend = dvb_attach(lgdt330x_attach,
|
||||
&fusionhdtv_3_gold,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
|
||||
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
|
||||
&dev->core->i2c_adap,
|
||||
&dvb_pll_microtune_4042);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -699,13 +607,13 @@ static int dvb_register(struct cx8802_dev *dev)
|
|||
mdelay(100);
|
||||
cx_set(MO_GP0_IO, 9);
|
||||
mdelay(200);
|
||||
dev->core->pll_addr = 0x61;
|
||||
dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
|
||||
dev->dvb.frontend = dvb_attach(lgdt330x_attach,
|
||||
&fusionhdtv_3_gold,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
|
||||
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
|
||||
&dev->core->i2c_adap,
|
||||
&dvb_pll_thomson_dtt761x);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -723,7 +631,8 @@ static int dvb_register(struct cx8802_dev *dev)
|
|||
&fusionhdtv_5_gold,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
|
||||
dvb_attach(lgh06xf_attach, dev->dvb.frontend,
|
||||
&dev->core->i2c_adap);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -741,7 +650,8 @@ static int dvb_register(struct cx8802_dev *dev)
|
|||
&pchdtv_hd5500,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
|
||||
dvb_attach(lgh06xf_attach, dev->dvb.frontend,
|
||||
&dev->core->i2c_adap);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -782,6 +692,24 @@ static int dvb_register(struct cx8802_dev *dev)
|
|||
dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
|
||||
}
|
||||
break;
|
||||
case CX88_BOARD_HAUPPAUGE_HVR1300:
|
||||
dev->dvb.frontend = dvb_attach(cx22702_attach,
|
||||
&hauppauge_hvr_config,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
|
||||
&dev->core->i2c_adap, &dvb_pll_fmd1216me);
|
||||
}
|
||||
break;
|
||||
case CX88_BOARD_HAUPPAUGE_HVR3000:
|
||||
dev->dvb.frontend = dvb_attach(cx22702_attach,
|
||||
&hauppauge_hvr_config,
|
||||
&dev->core->i2c_adap);
|
||||
if (dev->dvb.frontend != NULL) {
|
||||
dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
|
||||
&dev->core->i2c_adap, &dvb_pll_fmd1216me);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
|
||||
dev->core->name);
|
||||
|
@ -796,6 +724,8 @@ static int dvb_register(struct cx8802_dev *dev)
|
|||
dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min;
|
||||
dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max;
|
||||
}
|
||||
/* Ensure all frontends negotiate bus access */
|
||||
dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
|
||||
|
||||
/* Put the analog decoder in standby to keep it quiet */
|
||||
cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
|
||||
|
@ -806,37 +736,67 @@ static int dvb_register(struct cx8802_dev *dev)
|
|||
|
||||
/* ----------------------------------------------------------- */
|
||||
|
||||
static int __devinit dvb_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *pci_id)
|
||||
/* CX8802 MPEG -> mini driver - We have been given the hardware */
|
||||
static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx8802_dev *dev;
|
||||
struct cx88_core *core;
|
||||
struct cx88_core *core = drv->core;
|
||||
int err = 0;
|
||||
dprintk( 1, "%s\n", __FUNCTION__);
|
||||
|
||||
switch (core->board) {
|
||||
case CX88_BOARD_HAUPPAUGE_HVR1300:
|
||||
/* We arrive here with either the cx23416 or the cx22702
|
||||
* on the bus. Take the bus from the cx23416 and enable the
|
||||
* cx22702 demod
|
||||
*/
|
||||
cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */
|
||||
cx_clear(MO_GP0_IO, 0x00000004);
|
||||
udelay(1000);
|
||||
break;
|
||||
default:
|
||||
err = -ENODEV;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* CX8802 MPEG -> mini driver - We no longer have the hardware */
|
||||
static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx88_core *core = drv->core;
|
||||
int err = 0;
|
||||
dprintk( 1, "%s\n", __FUNCTION__);
|
||||
|
||||
switch (core->board) {
|
||||
case CX88_BOARD_HAUPPAUGE_HVR1300:
|
||||
/* Do Nothing, leave the cx22702 on the bus. */
|
||||
break;
|
||||
default:
|
||||
err = -ENODEV;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cx8802_dvb_probe(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx88_core *core = drv->core;
|
||||
struct cx8802_dev *dev = drv->core->dvbdev;
|
||||
int err;
|
||||
|
||||
/* general setup */
|
||||
core = cx88_core_get(pci_dev);
|
||||
if (NULL == core)
|
||||
return -EINVAL;
|
||||
dprintk( 1, "%s\n", __FUNCTION__);
|
||||
dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
|
||||
core->board,
|
||||
core->name,
|
||||
core->pci_bus,
|
||||
core->pci_slot);
|
||||
|
||||
err = -ENODEV;
|
||||
if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB))
|
||||
goto fail_core;
|
||||
|
||||
err = -ENOMEM;
|
||||
dev = kzalloc(sizeof(*dev),GFP_KERNEL);
|
||||
if (NULL == dev)
|
||||
goto fail_core;
|
||||
dev->pci = pci_dev;
|
||||
dev->core = core;
|
||||
|
||||
err = cx8802_init_common(dev);
|
||||
if (0 != err)
|
||||
goto fail_free;
|
||||
|
||||
#ifdef HAVE_VP3054_I2C
|
||||
err = vp3054_i2c_probe(dev);
|
||||
if (0 != err)
|
||||
goto fail_free;
|
||||
goto fail_core;
|
||||
#endif
|
||||
|
||||
/* dvb stuff */
|
||||
|
@ -848,28 +808,16 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
|
|||
sizeof(struct cx88_buffer),
|
||||
dev);
|
||||
err = dvb_register(dev);
|
||||
if (0 != err)
|
||||
goto fail_fini;
|
||||
if (err != 0)
|
||||
printk("%s dvb_register failed err = %d\n", __FUNCTION__, err);
|
||||
|
||||
/* Maintain a reference to cx88-video can query the 8802 device. */
|
||||
core->dvbdev = dev;
|
||||
return 0;
|
||||
|
||||
fail_fini:
|
||||
cx8802_fini_common(dev);
|
||||
fail_free:
|
||||
kfree(dev);
|
||||
fail_core:
|
||||
cx88_core_put(core,pci_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit dvb_remove(struct pci_dev *pci_dev)
|
||||
static int cx8802_dvb_remove(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
|
||||
|
||||
/* Destroy any 8802 reference. */
|
||||
dev->core->dvbdev = NULL;
|
||||
struct cx8802_dev *dev = drv->core->dvbdev;
|
||||
|
||||
/* dvb */
|
||||
videobuf_dvb_unregister(&dev->dvb);
|
||||
|
@ -878,33 +826,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev)
|
|||
vp3054_i2c_remove(dev);
|
||||
#endif
|
||||
|
||||
/* common */
|
||||
cx8802_fini_common(dev);
|
||||
cx88_core_put(dev->core,dev->pci);
|
||||
kfree(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pci_device_id cx8802_pci_tbl[] = {
|
||||
{
|
||||
.vendor = 0x14f1,
|
||||
.device = 0x8802,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
},{
|
||||
/* --- end of list --- */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
|
||||
|
||||
static struct pci_driver dvb_pci_driver = {
|
||||
.name = "cx88-dvb",
|
||||
.id_table = cx8802_pci_tbl,
|
||||
.probe = dvb_probe,
|
||||
.remove = __devexit_p(dvb_remove),
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = cx8802_suspend_common,
|
||||
.resume = cx8802_resume_common,
|
||||
#endif
|
||||
static struct cx8802_driver cx8802_dvb_driver = {
|
||||
.type_id = CX88_MPEG_DVB,
|
||||
.hw_access = CX8802_DRVCTL_SHARED,
|
||||
.probe = cx8802_dvb_probe,
|
||||
.remove = cx8802_dvb_remove,
|
||||
.advise_acquire = cx8802_dvb_advise_acquire,
|
||||
.advise_release = cx8802_dvb_advise_release,
|
||||
};
|
||||
|
||||
static int dvb_init(void)
|
||||
|
@ -917,12 +848,12 @@ static int dvb_init(void)
|
|||
printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
|
||||
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
|
||||
#endif
|
||||
return pci_register_driver(&dvb_pci_driver);
|
||||
return cx8802_register_driver(&cx8802_dvb_driver);
|
||||
}
|
||||
|
||||
static void dvb_fini(void)
|
||||
{
|
||||
pci_unregister_driver(&dvb_pci_driver);
|
||||
cx8802_unregister_driver(&cx8802_dvb_driver);
|
||||
}
|
||||
|
||||
module_init(dvb_init);
|
||||
|
|
|
@ -155,6 +155,35 @@ static void cx88_ir_work(struct work_struct *work)
|
|||
mod_timer(&ir->timer, timeout);
|
||||
}
|
||||
|
||||
static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
|
||||
{
|
||||
if (ir->polling) {
|
||||
INIT_WORK(&ir->work, cx88_ir_work);
|
||||
init_timer(&ir->timer);
|
||||
ir->timer.function = ir_timer;
|
||||
ir->timer.data = (unsigned long)ir;
|
||||
schedule_work(&ir->work);
|
||||
}
|
||||
if (ir->sampling) {
|
||||
core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
|
||||
cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */
|
||||
cx_write(MO_DDSCFG_IO, 0x5); /* enable */
|
||||
}
|
||||
}
|
||||
|
||||
static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir)
|
||||
{
|
||||
if (ir->sampling) {
|
||||
cx_write(MO_DDSCFG_IO, 0x0);
|
||||
core->pci_irqmask &= ~(1 << 18);
|
||||
}
|
||||
|
||||
if (ir->polling) {
|
||||
del_timer_sync(&ir->timer);
|
||||
flush_scheduled_work();
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
|
||||
|
@ -163,14 +192,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
|
|||
struct input_dev *input_dev;
|
||||
IR_KEYTAB_TYPE *ir_codes = NULL;
|
||||
int ir_type = IR_TYPE_OTHER;
|
||||
int err = -ENOMEM;
|
||||
|
||||
ir = kzalloc(sizeof(*ir), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!ir || !input_dev) {
|
||||
kfree(ir);
|
||||
input_free_device(input_dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (!ir || !input_dev)
|
||||
goto err_out_free;
|
||||
|
||||
ir->input = input_dev;
|
||||
|
||||
|
@ -280,9 +307,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
|
|||
}
|
||||
|
||||
if (NULL == ir_codes) {
|
||||
kfree(ir);
|
||||
input_free_device(input_dev);
|
||||
return -ENODEV;
|
||||
err = -ENODEV;
|
||||
goto err_out_free;
|
||||
}
|
||||
|
||||
/* init input device */
|
||||
|
@ -307,23 +333,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
|
|||
ir->core = core;
|
||||
core->ir = ir;
|
||||
|
||||
if (ir->polling) {
|
||||
INIT_WORK(&ir->work, cx88_ir_work);
|
||||
init_timer(&ir->timer);
|
||||
ir->timer.function = ir_timer;
|
||||
ir->timer.data = (unsigned long)ir;
|
||||
schedule_work(&ir->work);
|
||||
}
|
||||
if (ir->sampling) {
|
||||
core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
|
||||
cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */
|
||||
cx_write(MO_DDSCFG_IO, 0x5); /* enable */
|
||||
}
|
||||
cx88_ir_start(core, ir);
|
||||
|
||||
/* all done */
|
||||
input_register_device(ir->input);
|
||||
err = input_register_device(ir->input);
|
||||
if (err)
|
||||
goto err_out_stop;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_stop:
|
||||
cx88_ir_stop(core, ir);
|
||||
core->ir = NULL;
|
||||
err_out_free:
|
||||
input_free_device(input_dev);
|
||||
kfree(ir);
|
||||
return err;
|
||||
}
|
||||
|
||||
int cx88_ir_fini(struct cx88_core *core)
|
||||
|
@ -334,15 +359,7 @@ int cx88_ir_fini(struct cx88_core *core)
|
|||
if (NULL == ir)
|
||||
return 0;
|
||||
|
||||
if (ir->sampling) {
|
||||
cx_write(MO_DDSCFG_IO, 0x0);
|
||||
core->pci_irqmask &= ~(1 << 18);
|
||||
}
|
||||
if (ir->polling) {
|
||||
del_timer(&ir->timer);
|
||||
flush_scheduled_work();
|
||||
}
|
||||
|
||||
cx88_ir_stop(core, ir);
|
||||
input_unregister_device(ir->input);
|
||||
kfree(ir);
|
||||
|
||||
|
|
|
@ -44,8 +44,12 @@ module_param(debug,int,0644);
|
|||
MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
|
||||
|
||||
#define dprintk(level,fmt, arg...) if (debug >= level) \
|
||||
printk(KERN_DEBUG "%s/2: " fmt, dev->core->name , ## arg)
|
||||
printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
|
||||
|
||||
#define mpeg_dbg(level,fmt, arg...) if (debug >= level) \
|
||||
printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
|
||||
|
||||
static LIST_HEAD(cx8802_devlist);
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int cx8802_start_dma(struct cx8802_dev *dev,
|
||||
|
@ -65,17 +69,13 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
|
|||
|
||||
/* FIXME: this needs a review.
|
||||
* also: move to cx88-blackbird + cx88-dvb source files? */
|
||||
if (cx88_boards[core->board].mpeg == (CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) ) {
|
||||
/* Report a warning until the mini driver patch is applied,
|
||||
* else the following conditions will set the dma registers incorrectly.
|
||||
* This will be removed in the next major patch and changes to the conditions
|
||||
* will be made.
|
||||
*/
|
||||
printk(KERN_INFO "%s() board->(CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) is invalid\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) {
|
||||
dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
|
||||
|
||||
if ( (core->active_type_id == CX88_MPEG_DVB) &&
|
||||
(cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) {
|
||||
|
||||
dprintk( 1, "cx8802_start_dma doing .dvb\n");
|
||||
/* negedge driven & software reset */
|
||||
cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
|
||||
udelay(100);
|
||||
|
@ -93,15 +93,17 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
|
|||
cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
|
||||
udelay(100);
|
||||
break;
|
||||
case CX88_BOARD_HAUPPAUGE_HVR1300:
|
||||
break;
|
||||
default:
|
||||
cx_write(TS_SOP_STAT, 0x00);
|
||||
break;
|
||||
}
|
||||
cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
|
||||
} else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
|
||||
(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) {
|
||||
dprintk( 1, "cx8802_start_dma doing .blackbird\n");
|
||||
cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
|
||||
|
||||
cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
|
||||
|
@ -112,6 +114,10 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
|
|||
|
||||
cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
|
||||
udelay(100);
|
||||
} else {
|
||||
printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
|
||||
cx88_boards[core->board].mpeg );
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* reset counter */
|
||||
|
@ -542,8 +548,315 @@ int cx8802_resume_common(struct pci_dev *pci_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
struct cx8802_dev * cx8802_get_device(struct inode *inode)
|
||||
{
|
||||
int minor = iminor(inode);
|
||||
struct cx8802_dev *h = NULL;
|
||||
struct list_head *list;
|
||||
|
||||
list_for_each(list,&cx8802_devlist) {
|
||||
h = list_entry(list, struct cx8802_dev, devlist);
|
||||
if (h->mpeg_dev->minor == minor)
|
||||
return h;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
|
||||
{
|
||||
struct cx8802_dev *h = NULL;
|
||||
struct cx8802_driver *d = NULL;
|
||||
struct list_head *list;
|
||||
struct list_head *list2;
|
||||
|
||||
list_for_each(list,&cx8802_devlist) {
|
||||
h = list_entry(list, struct cx8802_dev, devlist);
|
||||
if (h != dev)
|
||||
continue;
|
||||
|
||||
list_for_each(list2, &h->drvlist.devlist) {
|
||||
d = list_entry(list2, struct cx8802_driver, devlist);
|
||||
|
||||
/* only unregister the correct driver type */
|
||||
if (d->type_id == btype) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Driver asked for hardware access. */
|
||||
int cx8802_request_acquire(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx88_core *core = drv->core;
|
||||
|
||||
/* Fail a request for hardware if the device is busy. */
|
||||
if (core->active_type_id != CX88_BOARD_NONE)
|
||||
return -EBUSY;
|
||||
|
||||
if (drv->advise_acquire)
|
||||
{
|
||||
core->active_type_id = drv->type_id;
|
||||
drv->advise_acquire(drv);
|
||||
|
||||
mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Driver asked to release hardware. */
|
||||
int cx8802_request_release(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx88_core *core = drv->core;
|
||||
|
||||
if (drv->advise_release)
|
||||
{
|
||||
drv->advise_release(drv);
|
||||
core->active_type_id = CX88_BOARD_NONE;
|
||||
mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx8802_check_driver(struct cx8802_driver *drv)
|
||||
{
|
||||
if (drv == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if ((drv->type_id != CX88_MPEG_DVB) &&
|
||||
(drv->type_id != CX88_MPEG_BLACKBIRD))
|
||||
return -EINVAL;
|
||||
|
||||
if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
|
||||
(drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
|
||||
return -EINVAL;
|
||||
|
||||
if ((drv->probe == NULL) ||
|
||||
(drv->remove == NULL) ||
|
||||
(drv->advise_acquire == NULL) ||
|
||||
(drv->advise_release == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cx8802_register_driver(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx8802_dev *h;
|
||||
struct cx8802_driver *driver;
|
||||
struct list_head *list;
|
||||
int err = 0, i = 0;
|
||||
|
||||
printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ ,
|
||||
drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
|
||||
drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
|
||||
|
||||
if ((err = cx8802_check_driver(drv)) != 0) {
|
||||
printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ );
|
||||
return err;
|
||||
}
|
||||
|
||||
list_for_each(list,&cx8802_devlist) {
|
||||
h = list_entry(list, struct cx8802_dev, devlist);
|
||||
|
||||
printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
|
||||
h->core->name,h->pci->subsystem_vendor,
|
||||
h->pci->subsystem_device,cx88_boards[h->core->board].name,
|
||||
h->core->board);
|
||||
|
||||
/* Bring up a new struct for each driver instance */
|
||||
driver = kzalloc(sizeof(*drv),GFP_KERNEL);
|
||||
if (driver == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Snapshot of the driver registration data */
|
||||
drv->core = h->core;
|
||||
drv->suspend = cx8802_suspend_common;
|
||||
drv->resume = cx8802_resume_common;
|
||||
drv->request_acquire = cx8802_request_acquire;
|
||||
drv->request_release = cx8802_request_release;
|
||||
memcpy(driver, drv, sizeof(*driver));
|
||||
|
||||
err = drv->probe(driver);
|
||||
if (err == 0) {
|
||||
i++;
|
||||
mutex_lock(&drv->core->lock);
|
||||
list_add_tail(&driver->devlist,&h->drvlist.devlist);
|
||||
mutex_unlock(&drv->core->lock);
|
||||
} else {
|
||||
printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err);
|
||||
}
|
||||
|
||||
}
|
||||
if (i == 0)
|
||||
err = -ENODEV;
|
||||
else
|
||||
err = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int cx8802_unregister_driver(struct cx8802_driver *drv)
|
||||
{
|
||||
struct cx8802_dev *h;
|
||||
struct cx8802_driver *d;
|
||||
struct list_head *list;
|
||||
struct list_head *list2, *q;
|
||||
int err = 0, i = 0;
|
||||
|
||||
printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ ,
|
||||
drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird");
|
||||
|
||||
list_for_each(list,&cx8802_devlist) {
|
||||
i++;
|
||||
h = list_entry(list, struct cx8802_dev, devlist);
|
||||
|
||||
printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
|
||||
h->core->name,h->pci->subsystem_vendor,
|
||||
h->pci->subsystem_device,cx88_boards[h->core->board].name,
|
||||
h->core->board);
|
||||
|
||||
list_for_each_safe(list2, q, &h->drvlist.devlist) {
|
||||
d = list_entry(list2, struct cx8802_driver, devlist);
|
||||
|
||||
/* only unregister the correct driver type */
|
||||
if (d->type_id != drv->type_id)
|
||||
continue;
|
||||
|
||||
err = d->remove(d);
|
||||
if (err == 0) {
|
||||
mutex_lock(&drv->core->lock);
|
||||
list_del(list2);
|
||||
mutex_unlock(&drv->core->lock);
|
||||
} else
|
||||
printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
static int __devinit cx8802_probe(struct pci_dev *pci_dev,
|
||||
const struct pci_device_id *pci_id)
|
||||
{
|
||||
struct cx8802_dev *dev;
|
||||
struct cx88_core *core;
|
||||
int err;
|
||||
|
||||
/* general setup */
|
||||
core = cx88_core_get(pci_dev);
|
||||
if (NULL == core)
|
||||
return -EINVAL;
|
||||
|
||||
printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
|
||||
|
||||
err = -ENODEV;
|
||||
if (!cx88_boards[core->board].mpeg)
|
||||
goto fail_core;
|
||||
|
||||
err = -ENOMEM;
|
||||
dev = kzalloc(sizeof(*dev),GFP_KERNEL);
|
||||
if (NULL == dev)
|
||||
goto fail_core;
|
||||
dev->pci = pci_dev;
|
||||
dev->core = core;
|
||||
|
||||
err = cx8802_init_common(dev);
|
||||
if (err != 0)
|
||||
goto fail_free;
|
||||
|
||||
INIT_LIST_HEAD(&dev->drvlist.devlist);
|
||||
list_add_tail(&dev->devlist,&cx8802_devlist);
|
||||
|
||||
/* Maintain a reference so cx88-video can query the 8802 device. */
|
||||
core->dvbdev = dev;
|
||||
return 0;
|
||||
|
||||
fail_free:
|
||||
kfree(dev);
|
||||
fail_core:
|
||||
cx88_core_put(core,pci_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit cx8802_remove(struct pci_dev *pci_dev)
|
||||
{
|
||||
struct cx8802_dev *dev;
|
||||
struct cx8802_driver *h;
|
||||
struct list_head *list;
|
||||
|
||||
dev = pci_get_drvdata(pci_dev);
|
||||
|
||||
dprintk( 1, "%s\n", __FUNCTION__);
|
||||
|
||||
list_for_each(list,&dev->drvlist.devlist) {
|
||||
h = list_entry(list, struct cx8802_driver, devlist);
|
||||
dprintk( 1, " ->driver\n");
|
||||
if (h->remove == NULL) {
|
||||
printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__);
|
||||
continue;
|
||||
}
|
||||
printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id);
|
||||
cx8802_unregister_driver(h);
|
||||
list_del(&dev->drvlist.devlist);
|
||||
}
|
||||
|
||||
/* Destroy any 8802 reference. */
|
||||
dev->core->dvbdev = NULL;
|
||||
|
||||
/* common */
|
||||
cx8802_fini_common(dev);
|
||||
cx88_core_put(dev->core,dev->pci);
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
static struct pci_device_id cx8802_pci_tbl[] = {
|
||||
{
|
||||
.vendor = 0x14f1,
|
||||
.device = 0x8802,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
},{
|
||||
/* --- end of list --- */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
|
||||
|
||||
static struct pci_driver cx8802_pci_driver = {
|
||||
.name = "cx88-mpeg driver manager",
|
||||
.id_table = cx8802_pci_tbl,
|
||||
.probe = cx8802_probe,
|
||||
.remove = __devexit_p(cx8802_remove),
|
||||
};
|
||||
|
||||
static int cx8802_init(void)
|
||||
{
|
||||
printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n",
|
||||
(CX88_VERSION_CODE >> 16) & 0xff,
|
||||
(CX88_VERSION_CODE >> 8) & 0xff,
|
||||
CX88_VERSION_CODE & 0xff);
|
||||
#ifdef SNAPSHOT
|
||||
printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
|
||||
SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
|
||||
#endif
|
||||
return pci_register_driver(&cx8802_pci_driver);
|
||||
}
|
||||
|
||||
static void cx8802_fini(void)
|
||||
{
|
||||
pci_unregister_driver(&cx8802_pci_driver);
|
||||
}
|
||||
|
||||
module_init(cx8802_init);
|
||||
module_exit(cx8802_fini);
|
||||
EXPORT_SYMBOL(cx8802_buf_prepare);
|
||||
EXPORT_SYMBOL(cx8802_buf_queue);
|
||||
EXPORT_SYMBOL(cx8802_cancel_buffers);
|
||||
|
@ -551,9 +864,10 @@ EXPORT_SYMBOL(cx8802_cancel_buffers);
|
|||
EXPORT_SYMBOL(cx8802_init_common);
|
||||
EXPORT_SYMBOL(cx8802_fini_common);
|
||||
|
||||
EXPORT_SYMBOL(cx8802_suspend_common);
|
||||
EXPORT_SYMBOL(cx8802_resume_common);
|
||||
|
||||
EXPORT_SYMBOL(cx8802_register_driver);
|
||||
EXPORT_SYMBOL(cx8802_unregister_driver);
|
||||
EXPORT_SYMBOL(cx8802_get_device);
|
||||
EXPORT_SYMBOL(cx8802_get_driver);
|
||||
/* ----------------------------------------------------------- */
|
||||
/*
|
||||
* Local variables:
|
||||
|
|
|
@ -143,19 +143,6 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
|
|||
cx88_start_audio_dma(core);
|
||||
|
||||
if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
|
||||
/* sets sound input from external adc */
|
||||
switch (core->board) {
|
||||
case CX88_BOARD_HAUPPAUGE_ROSLYN:
|
||||
case CX88_BOARD_KWORLD_MCE200_DELUXE:
|
||||
case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT:
|
||||
case CX88_BOARD_PIXELVIEW_PLAYTV_P7000:
|
||||
case CX88_BOARD_ASUS_PVR_416:
|
||||
cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
|
||||
break;
|
||||
default:
|
||||
cx_set(AUD_CTL, EN_I2SIN_ENABLE);
|
||||
}
|
||||
|
||||
cx_write(AUD_I2SINPUTCNTL, 4);
|
||||
cx_write(AUD_BAUDRATE, 1);
|
||||
/* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
|
||||
|
|
|
@ -454,6 +454,14 @@ static int video_mux(struct cx88_core *core, unsigned int input)
|
|||
cx_clear(MO_FILTER_ODD, 0x00002020);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
|
||||
/* sets sound input from external adc */
|
||||
if (INPUT(input)->extadc)
|
||||
cx_set(AUD_CTL, EN_I2SIN_ENABLE);
|
||||
else
|
||||
cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1490,6 +1498,30 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
|
|||
mutex_unlock(&core->lock);
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
/* ioctls to allow direct acces to the cx2388x registers */
|
||||
case VIDIOC_INT_G_REGISTER:
|
||||
{
|
||||
struct v4l2_register *reg = arg;
|
||||
|
||||
if (reg->i2c_id != 0)
|
||||
return -EINVAL;
|
||||
/* cx2388x has a 24-bit register space */
|
||||
reg->val = cx_read(reg->reg&0xffffff);
|
||||
return 0;
|
||||
}
|
||||
case VIDIOC_INT_S_REGISTER:
|
||||
{
|
||||
struct v4l2_register *reg = arg;
|
||||
|
||||
if (reg->i2c_id != 0)
|
||||
return -EINVAL;
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
cx_write(reg->reg&0xffffff, reg->val);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
return v4l_compat_translate_ioctl(inode,file,cmd,arg,
|
||||
|
|
|
@ -74,6 +74,11 @@ enum cx88_board_type {
|
|||
CX88_MPEG_BLACKBIRD
|
||||
};
|
||||
|
||||
enum cx8802_board_access {
|
||||
CX8802_DRVCTL_SHARED = 1,
|
||||
CX8802_DRVCTL_EXCLUSIVE = 2,
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* tv norms */
|
||||
|
||||
|
@ -220,6 +225,7 @@ struct cx88_input {
|
|||
enum cx88_itype type;
|
||||
unsigned int vmux;
|
||||
u32 gpio0, gpio1, gpio2, gpio3;
|
||||
unsigned int extadc:1;
|
||||
};
|
||||
|
||||
struct cx88_board {
|
||||
|
@ -330,6 +336,7 @@ struct cx88_core {
|
|||
|
||||
/* cx88-video needs to access cx8802 for hybrid tuner pll access. */
|
||||
struct cx8802_dev *dvbdev;
|
||||
enum cx88_board_type active_type_id;
|
||||
};
|
||||
|
||||
struct cx8800_dev;
|
||||
|
@ -405,6 +412,31 @@ struct cx8802_suspend_state {
|
|||
int disabled;
|
||||
};
|
||||
|
||||
struct cx8802_driver {
|
||||
struct cx88_core *core;
|
||||
struct list_head devlist;
|
||||
|
||||
/* Type of driver and access required */
|
||||
enum cx88_board_type type_id;
|
||||
enum cx8802_board_access hw_access;
|
||||
|
||||
/* MPEG 8802 internal only */
|
||||
int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
|
||||
int (*resume)(struct pci_dev *pci_dev);
|
||||
|
||||
/* MPEG 8802 -> mini driver - Driver probe and configuration */
|
||||
int (*probe)(struct cx8802_driver *drv);
|
||||
int (*remove)(struct cx8802_driver *drv);
|
||||
|
||||
/* MPEG 8802 -> mini driver - Access for hardware control */
|
||||
int (*advise_acquire)(struct cx8802_driver *drv);
|
||||
int (*advise_release)(struct cx8802_driver *drv);
|
||||
|
||||
/* MPEG 8802 <- mini driver - Access for hardware control */
|
||||
int (*request_acquire)(struct cx8802_driver *drv);
|
||||
int (*request_release)(struct cx8802_driver *drv);
|
||||
};
|
||||
|
||||
struct cx8802_dev {
|
||||
struct cx88_core *core;
|
||||
spinlock_t slock;
|
||||
|
@ -439,6 +471,9 @@ struct cx8802_dev {
|
|||
|
||||
/* mpeg params */
|
||||
struct cx2341x_mpeg_params params;
|
||||
|
||||
/* List of attached drivers */
|
||||
struct cx8802_driver drvlist;
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
|
@ -571,6 +606,11 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
|
|||
void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
|
||||
int cx88_audio_thread(void *data);
|
||||
|
||||
int cx8802_register_driver(struct cx8802_driver *drv);
|
||||
int cx8802_unregister_driver(struct cx8802_driver *drv);
|
||||
struct cx8802_dev * cx8802_get_device(struct inode *inode);
|
||||
struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* cx88-input.c */
|
||||
|
||||
|
@ -600,6 +640,13 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
|
|||
extern const u32 cx88_user_ctrls[];
|
||||
extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
/* cx88-blackbird.c */
|
||||
/* used by cx88-ivtv ioctl emulation layer */
|
||||
extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, void *arg);
|
||||
extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
|
|
|
@ -305,15 +305,14 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
|
|||
int ir_type;
|
||||
struct IR_i2c *ir;
|
||||
struct input_dev *input_dev;
|
||||
int err;
|
||||
|
||||
ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!ir || !input_dev) {
|
||||
input_free_device(input_dev);
|
||||
kfree(ir);
|
||||
return -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto err_out_free;
|
||||
}
|
||||
memset(ir,0,sizeof(*ir));
|
||||
|
||||
ir->c = client_template;
|
||||
ir->input = input_dev;
|
||||
|
@ -355,32 +354,34 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
|
|||
break;
|
||||
case 0x7a:
|
||||
case 0x47:
|
||||
case 0x71:
|
||||
/* Handled by saa7134-input */
|
||||
name = "SAA713x remote";
|
||||
ir_type = IR_TYPE_OTHER;
|
||||
break;
|
||||
default:
|
||||
/* shouldn't happen */
|
||||
printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr);
|
||||
kfree(ir);
|
||||
return -1;
|
||||
printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
|
||||
err = -ENODEV;
|
||||
goto err_out_free;
|
||||
}
|
||||
|
||||
/* Sets name */
|
||||
snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
|
||||
ir->ir_codes=ir_codes;
|
||||
ir->ir_codes = ir_codes;
|
||||
|
||||
/* register i2c device
|
||||
* At device register, IR codes may be changed to be
|
||||
* board dependent.
|
||||
*/
|
||||
i2c_attach_client(&ir->c);
|
||||
err = i2c_attach_client(&ir->c);
|
||||
if (err)
|
||||
goto err_out_free;
|
||||
|
||||
/* If IR not supported or disabled, unregisters driver */
|
||||
if (ir->get_key == NULL) {
|
||||
i2c_detach_client(&ir->c);
|
||||
kfree(ir);
|
||||
return -1;
|
||||
err = -ENODEV;
|
||||
goto err_out_detach;
|
||||
}
|
||||
|
||||
/* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */
|
||||
|
@ -389,15 +390,17 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
|
|||
ir->c.dev.bus_id);
|
||||
|
||||
/* init + register input device */
|
||||
ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes);
|
||||
ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
|
||||
input_dev->id.bustype = BUS_I2C;
|
||||
input_dev->name = ir->c.name;
|
||||
input_dev->phys = ir->phys;
|
||||
|
||||
/* register event device */
|
||||
input_register_device(ir->input);
|
||||
err = input_register_device(ir->input);
|
||||
if (err)
|
||||
goto err_out_detach;
|
||||
|
||||
printk(DEVNAME ": %s detected at %s [%s]\n",
|
||||
ir->input->name,ir->input->phys,adap->name);
|
||||
ir->input->name, ir->input->phys, adap->name);
|
||||
|
||||
/* start polling via eventd */
|
||||
INIT_WORK(&ir->work, ir_work);
|
||||
|
@ -407,6 +410,13 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
|
|||
schedule_work(&ir->work);
|
||||
|
||||
return 0;
|
||||
|
||||
err_out_detach:
|
||||
i2c_detach_client(&ir->c);
|
||||
err_out_free:
|
||||
input_free_device(input_dev);
|
||||
kfree(ir);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ir_detach(struct i2c_client *client)
|
||||
|
@ -414,7 +424,7 @@ static int ir_detach(struct i2c_client *client)
|
|||
struct IR_i2c *ir = i2c_get_clientdata(client);
|
||||
|
||||
/* kill outstanding polls */
|
||||
del_timer(&ir->timer);
|
||||
del_timer_sync(&ir->timer);
|
||||
flush_scheduled_work();
|
||||
|
||||
/* unregister devices */
|
||||
|
@ -439,7 +449,7 @@ static int ir_probe(struct i2c_adapter *adap)
|
|||
*/
|
||||
|
||||
static const int probe_bttv[] = { 0x1a, 0x18, 0x4b, 0x64, 0x30, -1};
|
||||
static const int probe_saa7134[] = { 0x7a, 0x47, -1 };
|
||||
static const int probe_saa7134[] = { 0x7a, 0x47, 0x71, -1 };
|
||||
static const int probe_em28XX[] = { 0x30, 0x47, -1 };
|
||||
const int *probe = NULL;
|
||||
struct i2c_client c;
|
||||
|
|
|
@ -160,10 +160,6 @@ static int mxb_probe(struct saa7146_dev* dev)
|
|||
printk("mxb: saa7111 i2c module not available.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if ((result = request_module("tuner")) < 0) {
|
||||
printk("mxb: tuner i2c module not available.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if ((result = request_module("tea6420")) < 0) {
|
||||
printk("mxb: tea6420 i2c module not available.\n");
|
||||
return -ENODEV;
|
||||
|
@ -176,6 +172,10 @@ static int mxb_probe(struct saa7146_dev* dev)
|
|||
printk("mxb: tda9840 i2c module not available.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if ((result = request_module("tuner")) < 0) {
|
||||
printk("mxb: tuner i2c module not available.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL);
|
||||
if( NULL == mxb ) {
|
||||
|
|
1333
drivers/media/video/ov7670.c
Normal file
1333
drivers/media/video/ov7670.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -260,6 +260,22 @@ int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
|
|||
sizeof(decoder_ops[0]))) - 1;
|
||||
hdw->decoder_ctrl = &ctxt->ctrl;
|
||||
cp->handler = &ctxt->handler;
|
||||
{
|
||||
/*
|
||||
Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit
|
||||
of nuttiness for cx25840 causes that module to
|
||||
correctly set up its video scaling. This is really
|
||||
a problem in the cx25840 module itself, but we work
|
||||
around it here. The problem has not been seen in
|
||||
ivtv because there VBI is supported and set up. We
|
||||
don't do VBI here (at least not yet) and thus we
|
||||
never attempted to even set it up.
|
||||
*/
|
||||
struct v4l2_format fmt;
|
||||
memset(&fmt,0,sizeof(fmt));
|
||||
fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
|
||||
pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_FMT,&fmt);
|
||||
}
|
||||
pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up",
|
||||
cp->client->addr);
|
||||
return !0;
|
||||
|
|
|
@ -356,28 +356,6 @@ static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp)
|
||||
{
|
||||
/* If we're dealing with a 24xxx device, force the horizontal
|
||||
maximum to be 720 no matter what, since we can't get the device
|
||||
to work properly with any other value. Otherwise just return
|
||||
the normal value. */
|
||||
*vp = cptr->info->def.type_int.max_value;
|
||||
if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp)
|
||||
{
|
||||
/* If we're dealing with a 24xxx device, force the horizontal
|
||||
minimum to be 720 no matter what, since we can't get the device
|
||||
to work properly with any other value. Otherwise just return
|
||||
the normal value. */
|
||||
*vp = cptr->info->def.type_int.min_value;
|
||||
if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
|
||||
{
|
||||
/* Actual maximum depends on the video standard in effect. */
|
||||
|
@ -758,10 +736,6 @@ static const struct pvr2_ctl_info control_defs[] = {
|
|||
.default_value = 720,
|
||||
DEFREF(res_hor),
|
||||
DEFINT(19,720),
|
||||
/* Hook in check for clamp on horizontal resolution in
|
||||
order to avoid unsolved problem involving cx25840. */
|
||||
.get_max_value = ctrl_hres_max_get,
|
||||
.get_min_value = ctrl_hres_min_get,
|
||||
},{
|
||||
.desc = "Vertical capture resolution",
|
||||
.name = "resolution_ver",
|
||||
|
|
|
@ -185,6 +185,79 @@ static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* This is a special entry point for cases of I2C transaction attempts to
|
||||
the IR receiver. The implementation here simulates the IR receiver by
|
||||
issuing a command to the FX2 firmware and using that response to return
|
||||
what the real I2C receiver would have returned. We use this for 24xxx
|
||||
devices, where the IR receiver chip has been removed and replaced with
|
||||
FX2 related logic. */
|
||||
static int i2c_24xxx_ir(struct pvr2_hdw *hdw,
|
||||
u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
|
||||
{
|
||||
u8 dat[4];
|
||||
unsigned int stat;
|
||||
|
||||
if (!(rlen || wlen)) {
|
||||
/* This is a probe attempt. Just let it succeed. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We don't understand this kind of transaction */
|
||||
if ((wlen != 0) || (rlen == 0)) return -EIO;
|
||||
|
||||
if (rlen < 3) {
|
||||
/* Mike Isely <isely@pobox.com> Appears to be a probe
|
||||
attempt from lirc. Just fill in zeroes and return. If
|
||||
we try instead to do the full transaction here, then bad
|
||||
things seem to happen within the lirc driver module
|
||||
(version 0.8.0-7 sources from Debian, when run under
|
||||
vanilla 2.6.17.6 kernel) - and I don't have the patience
|
||||
to chase it down. */
|
||||
if (rlen > 0) rdata[0] = 0;
|
||||
if (rlen > 1) rdata[1] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Issue a command to the FX2 to read the IR receiver. */
|
||||
LOCK_TAKE(hdw->ctl_lock); do {
|
||||
hdw->cmd_buffer[0] = 0xec;
|
||||
stat = pvr2_send_request(hdw,
|
||||
hdw->cmd_buffer,1,
|
||||
hdw->cmd_buffer,4);
|
||||
dat[0] = hdw->cmd_buffer[0];
|
||||
dat[1] = hdw->cmd_buffer[1];
|
||||
dat[2] = hdw->cmd_buffer[2];
|
||||
dat[3] = hdw->cmd_buffer[3];
|
||||
} while (0); LOCK_GIVE(hdw->ctl_lock);
|
||||
|
||||
/* Give up if that operation failed. */
|
||||
if (stat != 0) return stat;
|
||||
|
||||
/* Mangle the results into something that looks like the real IR
|
||||
receiver. */
|
||||
rdata[2] = 0xc1;
|
||||
if (dat[0] != 1) {
|
||||
/* No code received. */
|
||||
rdata[0] = 0;
|
||||
rdata[1] = 0;
|
||||
} else {
|
||||
u16 val;
|
||||
/* Mash the FX2 firmware-provided IR code into something
|
||||
that the normal i2c chip-level driver expects. */
|
||||
val = dat[1];
|
||||
val <<= 8;
|
||||
val |= dat[2];
|
||||
val >>= 1;
|
||||
val &= ~0x0003;
|
||||
val |= 0x8000;
|
||||
rdata[0] = (val >> 8) & 0xffu;
|
||||
rdata[1] = val & 0xffu;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is a special entry point that is entered if an I2C operation is
|
||||
attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this
|
||||
part doesn't work, but we know it is really there. So let's look for
|
||||
|
@ -887,17 +960,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
|
|||
{
|
||||
unsigned int idx;
|
||||
|
||||
// The default action for all possible I2C addresses is just to do
|
||||
// the transfer normally.
|
||||
/* The default action for all possible I2C addresses is just to do
|
||||
the transfer normally. */
|
||||
for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
|
||||
hdw->i2c_func[idx] = pvr2_i2c_basic_op;
|
||||
}
|
||||
|
||||
// If however we're dealing with new hardware, insert some hacks in
|
||||
// the I2C transfer stack to let things work better.
|
||||
/* However, deal with various special cases for 24xxx hardware. */
|
||||
if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
|
||||
hdw->i2c_func[0x1b] = i2c_hack_wm8775;
|
||||
hdw->i2c_func[0x44] = i2c_hack_cx25840;
|
||||
hdw->i2c_func[0x18] = i2c_24xxx_ir;
|
||||
}
|
||||
|
||||
// Configure the adapter and set up everything else related to it.
|
||||
|
|
|
@ -851,7 +851,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height)
|
|||
|
||||
/* On 60Hz, it is using a higher Vertical Output Size */
|
||||
if (!is_50hz)
|
||||
res+=(VRES_60HZ-480)>>1;
|
||||
res += (VRES_60HZ - 480) >> 1;
|
||||
|
||||
/* height */
|
||||
saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
|
||||
|
@ -907,7 +907,7 @@ static int saa711x_set_size(struct i2c_client *client, int width, int height)
|
|||
|
||||
/* Activates task "B" */
|
||||
saa711x_write(client, R_80_GLOBAL_CNTL_1,
|
||||
saa711x_read(client,R_80_GLOBAL_CNTL_1)|0x20);
|
||||
saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -932,11 +932,11 @@ static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
|
|||
if (std & V4L2_STD_525_60) {
|
||||
v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n");
|
||||
saa711x_writeregs(client, saa7115_cfg_60hz_video);
|
||||
saa711x_set_size(client,720,480);
|
||||
saa711x_set_size(client, 720, 480);
|
||||
} else {
|
||||
v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n");
|
||||
saa711x_writeregs(client, saa7115_cfg_50hz_video);
|
||||
saa711x_set_size(client,720,576);
|
||||
saa711x_set_size(client, 720, 576);
|
||||
}
|
||||
|
||||
/* Register 0E - Bits D6-D4 on NO-AUTO mode
|
||||
|
@ -1464,13 +1464,13 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
|
|||
client->driver = &i2c_driver_saa711x;
|
||||
snprintf(client->name, sizeof(client->name) - 1, "saa7115");
|
||||
|
||||
for (i=0;i<0x0f;i++) {
|
||||
for (i = 0; i < 0x0f; i++) {
|
||||
saa711x_write(client, 0, i);
|
||||
name[i] = (saa711x_read(client, 0) &0x0f) +'0';
|
||||
if (name[i]>'9')
|
||||
name[i]+='a'-'9'-1;
|
||||
name[i] = (saa711x_read(client, 0) & 0x0f) + '0';
|
||||
if (name[i] > '9')
|
||||
name[i] += 'a' - '9' - 1;
|
||||
}
|
||||
name[i]='\0';
|
||||
name[i] = '\0';
|
||||
|
||||
saa711x_write(client, 0, 5);
|
||||
chip_id = saa711x_read(client, 0) & 0x0f;
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
/*
|
||||
* SAA713x ALSA support for V4L
|
||||
*
|
||||
*
|
||||
* Caveats:
|
||||
* - Volume doesn't work (it's always at max)
|
||||
*
|
||||
* 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, version 2
|
||||
|
@ -614,13 +610,18 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
|
|||
snd_card_saa7134_pcm_t *pcm;
|
||||
snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
|
||||
struct saa7134_dev *dev = saa7134->dev;
|
||||
int err;
|
||||
int amux, err;
|
||||
|
||||
mutex_lock(&dev->dmasound.lock);
|
||||
|
||||
dev->dmasound.read_count = 0;
|
||||
dev->dmasound.read_offset = 0;
|
||||
|
||||
amux = dev->input->amux;
|
||||
if ((amux < 1) || (amux > 3))
|
||||
amux = 1;
|
||||
dev->dmasound.input = amux - 1;
|
||||
|
||||
mutex_unlock(&dev->dmasound.lock);
|
||||
|
||||
pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
|
||||
|
@ -713,6 +714,8 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol,
|
|||
struct snd_ctl_elem_value * ucontrol)
|
||||
{
|
||||
snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
|
||||
struct saa7134_dev *dev = chip->dev;
|
||||
|
||||
int change, addr = kcontrol->private_value;
|
||||
int left, right;
|
||||
|
||||
|
@ -727,10 +730,52 @@ static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol,
|
|||
if (right > 20)
|
||||
right = 20;
|
||||
spin_lock_irq(&chip->mixer_lock);
|
||||
change = chip->mixer_volume[addr][0] != left ||
|
||||
chip->mixer_volume[addr][1] != right;
|
||||
chip->mixer_volume[addr][0] = left;
|
||||
chip->mixer_volume[addr][1] = right;
|
||||
change = 0;
|
||||
if (chip->mixer_volume[addr][0] != left) {
|
||||
change = 1;
|
||||
right = left;
|
||||
}
|
||||
if (chip->mixer_volume[addr][1] != right) {
|
||||
change = 1;
|
||||
left = right;
|
||||
}
|
||||
if (change) {
|
||||
switch (dev->pci->device) {
|
||||
case PCI_DEVICE_ID_PHILIPS_SAA7134:
|
||||
switch (addr) {
|
||||
case MIXER_ADDR_TVTUNER:
|
||||
left = 20;
|
||||
break;
|
||||
case MIXER_ADDR_LINE1:
|
||||
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x10,
|
||||
(left > 10) ? 0x00 : 0x10);
|
||||
break;
|
||||
case MIXER_ADDR_LINE2:
|
||||
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x20,
|
||||
(left > 10) ? 0x00 : 0x20);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PCI_DEVICE_ID_PHILIPS_SAA7133:
|
||||
case PCI_DEVICE_ID_PHILIPS_SAA7135:
|
||||
switch (addr) {
|
||||
case MIXER_ADDR_TVTUNER:
|
||||
left = 20;
|
||||
break;
|
||||
case MIXER_ADDR_LINE1:
|
||||
saa_andorb(0x0594, 0x10,
|
||||
(left > 10) ? 0x00 : 0x10);
|
||||
break;
|
||||
case MIXER_ADDR_LINE2:
|
||||
saa_andorb(0x0594, 0x20,
|
||||
(left > 10) ? 0x00 : 0x20);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
chip->mixer_volume[addr][0] = left;
|
||||
chip->mixer_volume[addr][1] = right;
|
||||
}
|
||||
spin_unlock_irq(&chip->mixer_lock);
|
||||
return change;
|
||||
}
|
||||
|
|
|
@ -2462,14 +2462,17 @@ struct saa7134_board saa7134_boards[] = {
|
|||
.vmux = 1,
|
||||
.amux = TV,
|
||||
.tv = 1,
|
||||
.gpio = 0x0000000,
|
||||
},{
|
||||
.name = name_comp1,
|
||||
.vmux = 3,
|
||||
.amux = LINE2,
|
||||
.gpio = 0x0200000,
|
||||
},{
|
||||
.name = name_svideo,
|
||||
.vmux = 8,
|
||||
.amux = LINE2,
|
||||
.gpio = 0x0200000,
|
||||
}},
|
||||
.radio = {
|
||||
.name = name_radio,
|
||||
|
@ -3022,6 +3025,158 @@ struct saa7134_board saa7134_boards[] = {
|
|||
.amux = LINE1,
|
||||
},
|
||||
},
|
||||
[SAA7134_BOARD_PINNACLE_PCTV_310i] = {
|
||||
.name = "Pinnacle PCTV 310i",
|
||||
.audio_clock = 0x00187de7,
|
||||
.tuner_type = TUNER_PHILIPS_TDA8290,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.mpeg = SAA7134_MPEG_DVB,
|
||||
.gpiomask = 0x000200000,
|
||||
.inputs = {{
|
||||
.name = name_tv,
|
||||
.vmux = 4,
|
||||
.amux = TV,
|
||||
.tv = 1,
|
||||
},{
|
||||
.name = name_comp1,
|
||||
.vmux = 1,
|
||||
.amux = LINE2,
|
||||
},{
|
||||
.name = name_comp2,
|
||||
.vmux = 0,
|
||||
.amux = LINE2,
|
||||
},{
|
||||
.name = name_svideo,
|
||||
.vmux = 8,
|
||||
.amux = LINE2,
|
||||
}},
|
||||
.radio = {
|
||||
.name = name_radio,
|
||||
.amux = TV,
|
||||
.gpio = 0x0200000,
|
||||
},
|
||||
},
|
||||
[SAA7134_BOARD_AVERMEDIA_STUDIO_507] = {
|
||||
/* Mikhail Fedotov <mo_fedotov@mail.ru> */
|
||||
.name = "Avermedia AVerTV Studio 507",
|
||||
.audio_clock = 0x00187de7,
|
||||
.tuner_type = TUNER_PHILIPS_FM1256_IH3,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.tda9887_conf = TDA9887_PRESENT,
|
||||
.gpiomask = 0x03,
|
||||
.inputs = {{
|
||||
.name = name_tv,
|
||||
.vmux = 1,
|
||||
.amux = TV,
|
||||
.tv = 1,
|
||||
.gpio = 0x00,
|
||||
},{
|
||||
.name = name_comp1,
|
||||
.vmux = 0,
|
||||
.amux = LINE2,
|
||||
.gpio = 0x00,
|
||||
},{
|
||||
.name = name_comp2,
|
||||
.vmux = 3,
|
||||
.amux = LINE2,
|
||||
.gpio = 0x00,
|
||||
},{
|
||||
.name = name_svideo,
|
||||
.vmux = 8,
|
||||
.amux = LINE2,
|
||||
.gpio = 0x00,
|
||||
}},
|
||||
.radio = {
|
||||
.name = name_radio,
|
||||
.amux = LINE2,
|
||||
.gpio = 0x01,
|
||||
},
|
||||
.mute = {
|
||||
.name = name_mute,
|
||||
.amux = LINE1,
|
||||
.gpio = 0x00,
|
||||
},
|
||||
},
|
||||
[SAA7134_BOARD_VIDEOMATE_DVBT_200A] = {
|
||||
/* Francis Barber <fedora@barber-family.id.au> */
|
||||
.name = "Compro Videomate DVB-T200A",
|
||||
.audio_clock = 0x00187de7,
|
||||
.tuner_type = TUNER_ABSENT,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
|
||||
.mpeg = SAA7134_MPEG_DVB,
|
||||
.inputs = {{
|
||||
.name = name_tv,
|
||||
.vmux = 3,
|
||||
.amux = TV,
|
||||
.tv = 1,
|
||||
},{
|
||||
.name = name_comp1,
|
||||
.vmux = 1,
|
||||
.amux = LINE2,
|
||||
},{
|
||||
.name = name_svideo,
|
||||
.vmux = 8,
|
||||
.amux = LINE2,
|
||||
}},
|
||||
},
|
||||
[SAA7134_BOARD_HAUPPAUGE_HVR1110] = {
|
||||
/* Thomas Genty <tomlohave@gmail.com> */
|
||||
.name = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid",
|
||||
.audio_clock = 0x00187de7,
|
||||
.tuner_type = TUNER_PHILIPS_TDA8290,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.mpeg = SAA7134_MPEG_DVB,
|
||||
.inputs = {{
|
||||
.name = name_tv,
|
||||
.vmux = 1,
|
||||
.amux = TV,
|
||||
.tv = 1,
|
||||
},{
|
||||
.name = name_comp1,
|
||||
.vmux = 3,
|
||||
.amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */
|
||||
},{
|
||||
.name = name_svideo,
|
||||
.vmux = 8,
|
||||
.amux = LINE2, /* FIXME: audio doesn't work on svideo/composite */
|
||||
}},
|
||||
.radio = {
|
||||
.name = name_radio,
|
||||
.amux = TV,
|
||||
},
|
||||
},
|
||||
[SAA7134_BOARD_CINERGY_HT_PCMCIA] = {
|
||||
.name = "Terratec Cinergy HT PCMCIA",
|
||||
.audio_clock = 0x00187de7,
|
||||
.tuner_type = TUNER_PHILIPS_TDA8290,
|
||||
.radio_type = UNSET,
|
||||
.tuner_addr = ADDR_UNSET,
|
||||
.radio_addr = ADDR_UNSET,
|
||||
.mpeg = SAA7134_MPEG_DVB,
|
||||
.inputs = {{
|
||||
.name = name_tv,
|
||||
.vmux = 1,
|
||||
.amux = TV,
|
||||
.tv = 1,
|
||||
},{
|
||||
.name = name_comp1,
|
||||
.vmux = 0,
|
||||
.amux = LINE1,
|
||||
},{
|
||||
.name = name_svideo,
|
||||
.vmux = 6,
|
||||
.amux = LINE1,
|
||||
}},
|
||||
},
|
||||
};
|
||||
|
||||
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
|
||||
|
@ -3630,6 +3785,36 @@ struct pci_device_id saa7134_pci_tbl[] = {
|
|||
.subvendor = 0x1043,
|
||||
.subdevice = 0x4860,
|
||||
.driver_data = SAA7134_BOARD_ASUS_EUROPA2_HYBRID,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
|
||||
.subvendor = 0x11bd,
|
||||
.subdevice = 0x002f,
|
||||
.driver_data = SAA7134_BOARD_PINNACLE_PCTV_310i,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
|
||||
.subvendor = 0x1461, /* Avermedia Technologies Inc */
|
||||
.subdevice = 0x9715,
|
||||
.driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_507,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
|
||||
.subvendor = 0x1043,
|
||||
.subdevice = 0x4876,
|
||||
.driver_data = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x6701,
|
||||
.driver_data = SAA7134_BOARD_HAUPPAUGE_HVR1110,
|
||||
},{
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
|
||||
.subvendor = 0x153b,
|
||||
.subdevice = 0x1172,
|
||||
.driver_data = SAA7134_BOARD_CINERGY_HT_PCMCIA,
|
||||
},{
|
||||
/* --- boards without eeprom + subsystem ID --- */
|
||||
.vendor = PCI_VENDOR_ID_PHILIPS,
|
||||
|
@ -3717,6 +3902,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
|
|||
case SAA7134_BOARD_AVERMEDIA_305:
|
||||
case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
|
||||
case SAA7134_BOARD_AVERMEDIA_307:
|
||||
case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
|
||||
case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
|
||||
case SAA7134_BOARD_AVERMEDIA_777:
|
||||
/* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */
|
||||
|
@ -3725,6 +3911,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
|
|||
case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
|
||||
case SAA7134_BOARD_VIDEOMATE_DVBT_300:
|
||||
case SAA7134_BOARD_VIDEOMATE_DVBT_200:
|
||||
case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
|
||||
case SAA7134_BOARD_MANLI_MTV001:
|
||||
case SAA7134_BOARD_MANLI_MTV002:
|
||||
case SAA7134_BOARD_BEHOLD_409FM:
|
||||
|
@ -3793,7 +3980,9 @@ int saa7134_board_init1(struct saa7134_dev *dev)
|
|||
break;
|
||||
/* i2c remotes */
|
||||
case SAA7134_BOARD_PINNACLE_PCTV_110i:
|
||||
case SAA7134_BOARD_PINNACLE_PCTV_310i:
|
||||
case SAA7134_BOARD_UPMOST_PURPLE_TV:
|
||||
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
|
||||
dev->has_remote = SAA7134_REMOTE_I2C;
|
||||
break;
|
||||
case SAA7134_BOARD_AVERMEDIA_A169_B:
|
||||
|
@ -3924,9 +4113,11 @@ int saa7134_board_init2(struct saa7134_dev *dev)
|
|||
}
|
||||
break;
|
||||
case SAA7134_BOARD_PHILIPS_TIGER:
|
||||
case SAA7134_BOARD_PINNACLE_PCTV_310i:
|
||||
case SAA7134_BOARD_TEVION_DVBT_220RF:
|
||||
case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
|
||||
case SAA7134_BOARD_MEDION_MD8800_QUADRO:
|
||||
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
|
||||
/* this is a hybrid board, initialize to analog mode
|
||||
* and configure firmware eeprom address
|
||||
*/
|
||||
|
@ -3952,6 +4143,14 @@ int saa7134_board_init2(struct saa7134_dev *dev)
|
|||
i2c_transfer(&dev->i2c_adap, &msg, 1);
|
||||
}
|
||||
break;
|
||||
case SAA7134_BOARD_CINERGY_HT_PCMCIA:
|
||||
/* make the tda10046 find its eeprom */
|
||||
{
|
||||
u8 data[] = { 0x3c, 0x33, 0x60};
|
||||
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
|
||||
i2c_transfer(&dev->i2c_adap, &msg, 1);
|
||||
}
|
||||
break;
|
||||
case SAA7134_BOARD_KWORLD_ATSC110:
|
||||
{
|
||||
/* enable tuner */
|
||||
|
@ -3964,6 +4163,29 @@ int saa7134_board_init2(struct saa7134_dev *dev)
|
|||
dev->name, i);
|
||||
}
|
||||
break;
|
||||
case SAA7134_BOARD_VIDEOMATE_DVBT_200:
|
||||
case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
|
||||
/* The T200 and the T200A share the same pci id. Consequently,
|
||||
* we are going to query eeprom to try to find out which one we
|
||||
* are actually looking at. */
|
||||
|
||||
/* Don't do this if the board was specifically selected with an
|
||||
* insmod option or if we have the default configuration T200*/
|
||||
if(!dev->autodetected || (dev->eedata[0x41] == 0xd0))
|
||||
break;
|
||||
if(dev->eedata[0x41] == 0x02) {
|
||||
/* Reconfigure board as T200A */
|
||||
dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A;
|
||||
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
|
||||
dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
|
||||
printk(KERN_INFO "%s: Reconfigured board as %s\n",
|
||||
dev->name, saa7134_boards[dev->board].name);
|
||||
} else {
|
||||
printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n",
|
||||
dev->name, dev->eedata[0x41]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -889,15 +889,16 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
|
|||
must_configure_manually();
|
||||
dev->board = SAA7134_BOARD_UNKNOWN;
|
||||
}
|
||||
dev->autodetected = card[dev->nr] != dev->board;
|
||||
dev->tuner_type = saa7134_boards[dev->board].tuner_type;
|
||||
dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
|
||||
if (UNSET != tuner[dev->nr])
|
||||
dev->tuner_type = tuner[dev->nr];
|
||||
printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
|
||||
dev->name,pci_dev->subsystem_vendor,
|
||||
pci_dev->subsystem_device,saa7134_boards[dev->board].name,
|
||||
dev->board, card[dev->nr] == dev->board ?
|
||||
"insmod option" : "autodetected");
|
||||
printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
|
||||
dev->name,pci_dev->subsystem_vendor,
|
||||
pci_dev->subsystem_device,saa7134_boards[dev->board].name,
|
||||
dev->board, dev->autodetected ?
|
||||
"autodetected" : "insmod option");
|
||||
|
||||
/* get mmio */
|
||||
if (!request_mem_region(pci_resource_start(pci_dev,0),
|
||||
|
|
|
@ -50,6 +50,10 @@ static unsigned int antenna_pwr = 0;
|
|||
module_param(antenna_pwr, int, 0444);
|
||||
MODULE_PARM_DESC(antenna_pwr,"enable antenna power (Pinnacle 300i)");
|
||||
|
||||
static int use_frontent = 0;
|
||||
module_param(use_frontent, int, 0644);
|
||||
MODULE_PARM_DESC(use_frontent,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
|
||||
{
|
||||
|
@ -293,7 +297,7 @@ static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dv
|
|||
return philips_tda6651_pll_set(0x60, fe, params);
|
||||
}
|
||||
|
||||
static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
|
||||
static int philips_tda1004x_request_firmware(struct dvb_frontend *fe,
|
||||
const struct firmware **fw, char *name)
|
||||
{
|
||||
struct saa7134_dev *dev = fe->dvb->priv;
|
||||
|
@ -308,7 +312,7 @@ static struct tda1004x_config philips_tu1216_60_config = {
|
|||
.xtal_freq = TDA10046_XTAL_4M,
|
||||
.agc_config = TDA10046_AGC_DEFAULT,
|
||||
.if_freq = TDA10046_FREQ_3617,
|
||||
.request_firmware = philips_tu1216_request_firmware,
|
||||
.request_firmware = philips_tda1004x_request_firmware,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
@ -331,12 +335,12 @@ static struct tda1004x_config philips_tu1216_61_config = {
|
|||
.xtal_freq = TDA10046_XTAL_4M,
|
||||
.agc_config = TDA10046_AGC_DEFAULT,
|
||||
.if_freq = TDA10046_FREQ_3617,
|
||||
.request_firmware = philips_tu1216_request_firmware,
|
||||
.request_firmware = philips_tda1004x_request_firmware,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int philips_europa_tuner_init(struct dvb_frontend *fe)
|
||||
static int philips_td1316_tuner_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct saa7134_dev *dev = fe->dvb->priv;
|
||||
static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab };
|
||||
|
@ -347,18 +351,8 @@ static int philips_europa_tuner_init(struct dvb_frontend *fe)
|
|||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
|
||||
return -EIO;
|
||||
msleep(1);
|
||||
|
||||
/* switch the board to dvb mode */
|
||||
init_msg.addr = 0x43;
|
||||
init_msg.len = 0x02;
|
||||
msg[0] = 0x00;
|
||||
msg[1] = 0x40;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
|
||||
return -EIO;
|
||||
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -367,6 +361,22 @@ static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_f
|
|||
return philips_tda6651_pll_set(0x61, fe, params);
|
||||
}
|
||||
|
||||
static int philips_europa_tuner_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct saa7134_dev *dev = fe->dvb->priv;
|
||||
static u8 msg[] = { 0x00, 0x40};
|
||||
struct i2c_msg init_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) };
|
||||
|
||||
|
||||
if (philips_td1316_tuner_init(fe))
|
||||
return -EIO;
|
||||
msleep(1);
|
||||
if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int philips_europa_tuner_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct saa7134_dev *dev = fe->dvb->priv;
|
||||
|
@ -671,7 +681,7 @@ static struct tda1004x_config tda827x_lifeview_config = {
|
|||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GP11,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.request_firmware = NULL,
|
||||
};
|
||||
|
@ -812,6 +822,27 @@ static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe)
|
|||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int tda8290_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
|
||||
{
|
||||
struct saa7134_dev *dev = fe->dvb->priv;
|
||||
static u8 tda8290_close[] = { 0x21, 0xc0};
|
||||
static u8 tda8290_open[] = { 0x21, 0x80};
|
||||
struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2};
|
||||
if (enable) {
|
||||
tda8290_msg.buf = tda8290_close;
|
||||
} else {
|
||||
tda8290_msg.buf = tda8290_open;
|
||||
}
|
||||
if (i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1) != 1)
|
||||
return -EIO;
|
||||
msleep(20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -820,24 +851,11 @@ static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe)
|
|||
static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
|
||||
{
|
||||
int ret;
|
||||
struct saa7134_dev *dev = fe->dvb->priv;
|
||||
static u8 tda8290_close[] = { 0x21, 0xc0};
|
||||
static u8 tda8290_open[] = { 0x21, 0x80};
|
||||
struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2};
|
||||
|
||||
/* close tda8290 i2c bridge */
|
||||
tda8290_msg.buf = tda8290_close;
|
||||
ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
|
||||
if (ret != 1)
|
||||
return -EIO;
|
||||
msleep(20);
|
||||
ret = philips_tda827xa_pll_set(0x61, fe, params);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
/* open tda8290 i2c bridge */
|
||||
tda8290_msg.buf = tda8290_open;
|
||||
i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int philips_tiger_tuner_init(struct dvb_frontend *fe)
|
||||
|
@ -867,13 +885,80 @@ static struct tda1004x_config philips_tiger_config = {
|
|||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GP11,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.request_firmware = NULL,
|
||||
};
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int cinergy_ht_tuner_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct saa7134_dev *dev = fe->dvb->priv;
|
||||
static u8 data[] = { 0x3c, 0x33, 0x62};
|
||||
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
|
||||
|
||||
if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cinergy_ht_tuner_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct saa7134_dev *dev = fe->dvb->priv;
|
||||
static u8 data[] = { 0x3c, 0x33, 0x60};
|
||||
struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
|
||||
|
||||
i2c_transfer(&dev->i2c_adap, &msg, 1);
|
||||
philips_tda827xa_tuner_sleep( 0x61, fe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct tda1004x_config cinergy_ht_config = {
|
||||
.demod_address = 0x08,
|
||||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GP01,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.request_firmware = NULL,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static struct tda1004x_config pinnacle_pctv_310i_config = {
|
||||
.demod_address = 0x08,
|
||||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GP11,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.request_firmware = philips_tda1004x_request_firmware,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static struct tda1004x_config hauppauge_hvr_1110_config = {
|
||||
.demod_address = 0x08,
|
||||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GP11,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.request_firmware = philips_tda1004x_request_firmware,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static struct tda1004x_config asus_p7131_dual_config = {
|
||||
.demod_address = 0x08,
|
||||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GP11,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.request_firmware = philips_tda1004x_request_firmware,
|
||||
};
|
||||
|
||||
static int asus_p7131_dual_tuner_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct saa7134_dev *dev = fe->dvb->priv;
|
||||
|
@ -921,7 +1006,7 @@ static struct tda1004x_config lifeview_trio_config = {
|
|||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GPL,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GP00,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.request_firmware = NULL,
|
||||
};
|
||||
|
@ -958,7 +1043,7 @@ static struct tda1004x_config ads_tech_duo_config = {
|
|||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GPL,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GP00,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.request_firmware = NULL,
|
||||
};
|
||||
|
@ -983,7 +1068,7 @@ static struct tda1004x_config tevion_dvbt220rf_config = {
|
|||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GP11,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.request_firmware = NULL,
|
||||
};
|
||||
|
@ -1028,7 +1113,7 @@ static struct tda1004x_config md8800_dvbt_config = {
|
|||
.invert = 1,
|
||||
.invert_oclk = 0,
|
||||
.xtal_freq = TDA10046_XTAL_16M,
|
||||
.agc_config = TDA10046_AGC_TDA827X,
|
||||
.agc_config = TDA10046_AGC_TDA827X_GP11,
|
||||
.if_freq = TDA10046_FREQ_045,
|
||||
.request_firmware = NULL,
|
||||
};
|
||||
|
@ -1168,6 +1253,29 @@ static int dvb_init(struct saa7134_dev *dev)
|
|||
&philips_tiger_config,
|
||||
&dev->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
|
||||
dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
|
||||
dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
|
||||
}
|
||||
break;
|
||||
case SAA7134_BOARD_PINNACLE_PCTV_310i:
|
||||
dev->dvb.frontend = dvb_attach(tda10046_attach,
|
||||
&pinnacle_pctv_310i_config,
|
||||
&dev->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
|
||||
dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
|
||||
dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
|
||||
}
|
||||
break;
|
||||
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
|
||||
dev->dvb.frontend = dvb_attach(tda10046_attach,
|
||||
&hauppauge_hvr_1110_config,
|
||||
&dev->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
|
||||
dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
|
||||
dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
|
||||
|
@ -1175,9 +1283,10 @@ static int dvb_init(struct saa7134_dev *dev)
|
|||
break;
|
||||
case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
|
||||
dev->dvb.frontend = dvb_attach(tda10046_attach,
|
||||
&philips_tiger_config,
|
||||
&asus_p7131_dual_config,
|
||||
&dev->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
|
||||
dev->dvb.frontend->ops.tuner_ops.init = asus_p7131_dual_tuner_init;
|
||||
dev->dvb.frontend->ops.tuner_ops.sleep = asus_p7131_dual_tuner_sleep;
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
|
||||
|
@ -1194,12 +1303,27 @@ static int dvb_init(struct saa7134_dev *dev)
|
|||
}
|
||||
break;
|
||||
case SAA7134_BOARD_FLYDVB_TRIO:
|
||||
dev->dvb.frontend = dvb_attach(tda10046_attach,
|
||||
&lifeview_trio_config,
|
||||
&dev->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params;
|
||||
if(! use_frontent) { //terrestrial
|
||||
dev->dvb.frontend = dvb_attach(tda10046_attach,
|
||||
&lifeview_trio_config,
|
||||
&dev->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params =
|
||||
lifeview_trio_tuner_set_params;
|
||||
}
|
||||
} else { //satellite
|
||||
dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63,
|
||||
&dev->i2c_adap, 0) == NULL) {
|
||||
printk("%s: Lifeview Trio, No tda826x found!\n", __FUNCTION__);
|
||||
}
|
||||
if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap,
|
||||
0x08, 0, 0) == NULL) {
|
||||
printk("%s: Lifeview Trio, No ISL6421 found!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
|
||||
|
@ -1281,7 +1405,27 @@ static int dvb_init(struct saa7134_dev *dev)
|
|||
dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params;
|
||||
}
|
||||
break;
|
||||
case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
|
||||
dev->dvb.frontend = dvb_attach(tda10046_attach,
|
||||
&philips_europa_config,
|
||||
&dev->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
|
||||
}
|
||||
break;
|
||||
case SAA7134_BOARD_CINERGY_HT_PCMCIA:
|
||||
dev->dvb.frontend = dvb_attach(tda10046_attach,
|
||||
&cinergy_ht_config,
|
||||
&dev->i2c_adap);
|
||||
if (dev->dvb.frontend) {
|
||||
dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
|
||||
dev->dvb.frontend->ops.tuner_ops.init = cinergy_ht_tuner_init;
|
||||
dev->dvb.frontend->ops.tuner_ops.sleep = cinergy_ht_tuner_sleep;
|
||||
dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk("%s: Huh? unknown DVB card?\n",dev->name);
|
||||
break;
|
||||
|
|
|
@ -341,6 +341,7 @@ static int attach_inform(struct i2c_client *client)
|
|||
switch (client->addr) {
|
||||
case 0x7a:
|
||||
case 0x47:
|
||||
case 0x71:
|
||||
{
|
||||
struct IR_i2c *ir = i2c_get_clientdata(client);
|
||||
d1printk("%s i2c IR detected (%s).\n",
|
||||
|
|
|
@ -112,6 +112,27 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
|
||||
{
|
||||
unsigned char buf[5], cod4, code3, code4;
|
||||
|
||||
/* poll IR chip */
|
||||
if (5 != i2c_master_recv(&ir->c,buf,5))
|
||||
return -EIO;
|
||||
|
||||
cod4 = buf[4];
|
||||
code4 = (cod4 >> 2);
|
||||
code3 = buf[3];
|
||||
if (code3 == 0)
|
||||
/* no key pressed */
|
||||
return 0;
|
||||
|
||||
/* return key */
|
||||
*ir_key = code4;
|
||||
*ir_raw = code4;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void saa7134_input_irq(struct saa7134_dev *dev)
|
||||
{
|
||||
struct saa7134_ir *ir = dev->remote;
|
||||
|
@ -131,6 +152,23 @@ static void saa7134_input_timer(unsigned long data)
|
|||
mod_timer(&ir->timer, timeout);
|
||||
}
|
||||
|
||||
static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir)
|
||||
{
|
||||
if (ir->polling) {
|
||||
init_timer(&ir->timer);
|
||||
ir->timer.function = saa7134_input_timer;
|
||||
ir->timer.data = (unsigned long)dev;
|
||||
ir->timer.expires = jiffies + HZ;
|
||||
add_timer(&ir->timer);
|
||||
}
|
||||
}
|
||||
|
||||
static void saa7134_ir_stop(struct saa7134_dev *dev)
|
||||
{
|
||||
if (dev->remote->polling)
|
||||
del_timer_sync(&dev->remote->timer);
|
||||
}
|
||||
|
||||
int saa7134_input_init1(struct saa7134_dev *dev)
|
||||
{
|
||||
struct saa7134_ir *ir;
|
||||
|
@ -141,6 +179,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
|
|||
u32 mask_keyup = 0;
|
||||
int polling = 0;
|
||||
int ir_type = IR_TYPE_OTHER;
|
||||
int err;
|
||||
|
||||
if (dev->has_remote != SAA7134_REMOTE_GPIO)
|
||||
return -ENODEV;
|
||||
|
@ -184,6 +223,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
|
|||
case SAA7134_BOARD_AVERMEDIA_307:
|
||||
case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
|
||||
case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
|
||||
case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
|
||||
case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
|
||||
ir_codes = ir_codes_avermedia;
|
||||
mask_keycode = 0x0007C8;
|
||||
|
@ -266,9 +306,8 @@ int saa7134_input_init1(struct saa7134_dev *dev)
|
|||
ir = kzalloc(sizeof(*ir), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!ir || !input_dev) {
|
||||
kfree(ir);
|
||||
input_free_device(input_dev);
|
||||
return -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto err_out_free;
|
||||
}
|
||||
|
||||
ir->dev = input_dev;
|
||||
|
@ -299,18 +338,22 @@ int saa7134_input_init1(struct saa7134_dev *dev)
|
|||
}
|
||||
input_dev->cdev.dev = &dev->pci->dev;
|
||||
|
||||
/* all done */
|
||||
dev->remote = ir;
|
||||
if (ir->polling) {
|
||||
init_timer(&ir->timer);
|
||||
ir->timer.function = saa7134_input_timer;
|
||||
ir->timer.data = (unsigned long)dev;
|
||||
ir->timer.expires = jiffies + HZ;
|
||||
add_timer(&ir->timer);
|
||||
}
|
||||
saa7134_ir_start(dev, ir);
|
||||
|
||||
err = input_register_device(ir->dev);
|
||||
if (err)
|
||||
goto err_out_stop;
|
||||
|
||||
input_register_device(ir->dev);
|
||||
return 0;
|
||||
|
||||
err_out_stop:
|
||||
saa7134_ir_stop(dev);
|
||||
dev->remote = NULL;
|
||||
err_out_free:
|
||||
input_free_device(input_dev);
|
||||
kfree(ir);
|
||||
return err;
|
||||
}
|
||||
|
||||
void saa7134_input_fini(struct saa7134_dev *dev)
|
||||
|
@ -318,8 +361,7 @@ void saa7134_input_fini(struct saa7134_dev *dev)
|
|||
if (NULL == dev->remote)
|
||||
return;
|
||||
|
||||
if (dev->remote->polling)
|
||||
del_timer_sync(&dev->remote->timer);
|
||||
saa7134_ir_stop(dev);
|
||||
input_unregister_device(dev->remote->dev);
|
||||
kfree(dev->remote);
|
||||
dev->remote = NULL;
|
||||
|
@ -335,6 +377,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
|
|||
|
||||
switch (dev->board) {
|
||||
case SAA7134_BOARD_PINNACLE_PCTV_110i:
|
||||
case SAA7134_BOARD_PINNACLE_PCTV_310i:
|
||||
snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
|
||||
if (pinnacle_remote == 0) {
|
||||
ir->get_key = get_key_pinnacle_color;
|
||||
|
@ -349,6 +392,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
|
|||
ir->get_key = get_key_purpletv;
|
||||
ir->ir_codes = ir_codes_purpletv;
|
||||
break;
|
||||
case SAA7134_BOARD_HAUPPAUGE_HVR1110:
|
||||
snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110");
|
||||
ir->get_key = get_key_hvr1110;
|
||||
ir->ir_codes = ir_codes_hauppauge_new;
|
||||
break;
|
||||
default:
|
||||
dprintk("Shouldn't get here: Unknown board %x for I2C IR?\n",dev->board);
|
||||
break;
|
||||
|
|
|
@ -227,6 +227,11 @@ struct saa7134_format {
|
|||
#define SAA7134_BOARD_PROTEUS_2309 98
|
||||
#define SAA7134_BOARD_AVERMEDIA_A16AR 99
|
||||
#define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100
|
||||
#define SAA7134_BOARD_PINNACLE_PCTV_310i 101
|
||||
#define SAA7134_BOARD_AVERMEDIA_STUDIO_507 102
|
||||
#define SAA7134_BOARD_VIDEOMATE_DVBT_200A 103
|
||||
#define SAA7134_BOARD_HAUPPAUGE_HVR1110 104
|
||||
#define SAA7134_BOARD_CINERGY_HT_PCMCIA 105
|
||||
|
||||
#define SAA7134_MAXBOARDS 8
|
||||
#define SAA7134_INPUT_MAX 8
|
||||
|
@ -446,6 +451,9 @@ struct saa7134_dev {
|
|||
struct v4l2_prio_state prio;
|
||||
#endif
|
||||
|
||||
/* insmod option/autodetected */
|
||||
int autodetected;
|
||||
|
||||
/* various device info */
|
||||
unsigned int resources;
|
||||
struct video_device *video_dev;
|
||||
|
|
|
@ -687,7 +687,7 @@ static int stv680_start_stream (struct usb_stv *stv680)
|
|||
stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
|
||||
if (stv680->sbuf[i].data == NULL) {
|
||||
PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i);
|
||||
return -1;
|
||||
goto nomem_err;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -698,7 +698,7 @@ static int stv680_start_stream (struct usb_stv *stv680)
|
|||
stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL);
|
||||
if (stv680->scratch[i].data == NULL) {
|
||||
PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i);
|
||||
return -1;
|
||||
goto nomem_err;
|
||||
}
|
||||
stv680->scratch[i].state = BUFFER_UNUSED;
|
||||
}
|
||||
|
@ -706,7 +706,7 @@ static int stv680_start_stream (struct usb_stv *stv680)
|
|||
for (i = 0; i < STV680_NUMSBUF; i++) {
|
||||
urb = usb_alloc_urb (0, GFP_KERNEL);
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
goto nomem_err;
|
||||
|
||||
/* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */
|
||||
usb_fill_bulk_urb (urb, stv680->udev,
|
||||
|
@ -721,6 +721,21 @@ static int stv680_start_stream (struct usb_stv *stv680)
|
|||
|
||||
stv680->framecount = 0;
|
||||
return 0;
|
||||
|
||||
nomem_err:
|
||||
for (i = 0; i < STV680_NUMSCRATCH; i++) {
|
||||
kfree(stv680->scratch[i].data);
|
||||
stv680->scratch[i].data = NULL;
|
||||
}
|
||||
for (i = 0; i < STV680_NUMSBUF; i++) {
|
||||
usb_kill_urb(stv680->urb[i]);
|
||||
usb_free_urb(stv680->urb[i]);
|
||||
stv680->urb[i] = NULL;
|
||||
kfree(stv680->sbuf[i].data);
|
||||
stv680->sbuf[i].data = NULL;
|
||||
}
|
||||
return -ENOMEM;
|
||||
|
||||
}
|
||||
|
||||
static int stv680_stop_stream (struct usb_stv *stv680)
|
||||
|
|
|
@ -482,6 +482,12 @@ static int tda9887_set_config(struct tuner *t, char *buf)
|
|||
buf[1] &= ~cQSS;
|
||||
if (t->tda9887_config & TDA9887_GATING_18)
|
||||
buf[3] &= ~cGating_36;
|
||||
|
||||
if (t->tda9887_config & TDA9887_GAIN_NORMAL) {
|
||||
radio_stereo.e &= ~cTunerGainLow;
|
||||
radio_mono.e &= ~cTunerGainLow;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -443,6 +443,10 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
|
|||
printk("%02x ",buffer[i]);
|
||||
printk("\n");
|
||||
}
|
||||
/* HACK: This test were added to avoid tuner to probe tda9840 and tea6415c on the MXB card */
|
||||
if (adap->id == I2C_HW_SAA7146 && addr < 0x4a)
|
||||
return -ENODEV;
|
||||
|
||||
/* autodetection code based on the i2c addr */
|
||||
if (!no_autodetect) {
|
||||
switch (addr) {
|
||||
|
|
|
@ -108,6 +108,7 @@ static int tuner_stereo(struct i2c_client *c)
|
|||
case TUNER_PHILIPS_FM1216ME_MK3:
|
||||
case TUNER_PHILIPS_FM1236_MK3:
|
||||
case TUNER_PHILIPS_FM1256_IH3:
|
||||
case TUNER_LG_NTSC_TAPE:
|
||||
stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
|
||||
break;
|
||||
default:
|
||||
|
@ -421,6 +422,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
|
|||
case TUNER_PHILIPS_FM1216ME_MK3:
|
||||
case TUNER_PHILIPS_FM1236_MK3:
|
||||
case TUNER_PHILIPS_FMD1216ME_MK3:
|
||||
case TUNER_LG_NTSC_TAPE:
|
||||
buffer[3] = 0x19;
|
||||
break;
|
||||
case TUNER_TNF_5335MF:
|
||||
|
@ -465,6 +467,8 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
|
|||
config |= TDA9887_INTERCARRIER;
|
||||
/* if (params->port1_set_for_fm_mono)
|
||||
config &= ~TDA9887_PORT1_ACTIVE;*/
|
||||
if (params->fm_gain_normal)
|
||||
config |= TDA9887_GAIN_NORMAL;
|
||||
i2c_clients_command(c->adapter, TDA9887_SET_CONFIG, &config);
|
||||
}
|
||||
if (4 != (rc = i2c_master_send(c,buffer,4)))
|
||||
|
|
|
@ -651,6 +651,7 @@ static struct tuner_params tuner_microtune_4049_fm5_params[] = {
|
|||
.has_tda9887 = 1,
|
||||
.port1_invert_for_secam_lc = 1,
|
||||
.default_pll_gating_18 = 1,
|
||||
.fm_gain_normal=1,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -672,16 +673,6 @@ static struct tuner_params tuner_panasonic_vp27_params[] = {
|
|||
},
|
||||
};
|
||||
|
||||
/* ------------ TUNER_LG_NTSC_TAPE - LGINNOTEK NTSC ------------ */
|
||||
|
||||
static struct tuner_params tuner_lg_ntsc_tape_params[] = {
|
||||
{
|
||||
.type = TUNER_PARAM_TYPE_NTSC,
|
||||
.ranges = tuner_fm1236_mk3_ntsc_ranges,
|
||||
.count = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
|
||||
},
|
||||
};
|
||||
|
||||
/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */
|
||||
|
||||
static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = {
|
||||
|
@ -1331,8 +1322,8 @@ struct tunertype tuners[] = {
|
|||
},
|
||||
[TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
|
||||
.name = "LG NTSC (TAPE series)",
|
||||
.params = tuner_lg_ntsc_tape_params,
|
||||
.count = ARRAY_SIZE(tuner_lg_ntsc_tape_params),
|
||||
.params = tuner_fm1236_mk3_params,
|
||||
.count = ARRAY_SIZE(tuner_fm1236_mk3_params),
|
||||
},
|
||||
[TUNER_TNF_8831BGFF] = { /* Philips PAL */
|
||||
.name = "Tenna TNF 8831 BGFF)",
|
||||
|
|
|
@ -430,7 +430,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
|
|||
tvee->has_radio = eeprom_data[i+len-1];
|
||||
/* old style tag, don't know how to detect
|
||||
IR presence, mark as unknown. */
|
||||
tvee->has_ir = 2;
|
||||
tvee->has_ir = -1;
|
||||
tvee->model =
|
||||
eeprom_data[i+8] +
|
||||
(eeprom_data[i+9] << 8);
|
||||
|
@ -653,13 +653,14 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
|
|||
STRM(decoderIC, tvee->decoder_processor),
|
||||
tvee->decoder_processor);
|
||||
}
|
||||
if (tvee->has_ir == 2)
|
||||
if (tvee->has_ir == -1)
|
||||
tveeprom_info("has %sradio\n",
|
||||
tvee->has_radio ? "" : "no ");
|
||||
else
|
||||
tveeprom_info("has %sradio, has %sIR remote\n",
|
||||
tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n",
|
||||
tvee->has_radio ? "" : "no ",
|
||||
tvee->has_ir ? "" : "no ");
|
||||
(tvee->has_ir & 1) ? "" : "no ",
|
||||
(tvee->has_ir & 2) ? "" : "no ");
|
||||
}
|
||||
EXPORT_SYMBOL(tveeprom_hauppauge_analog);
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ MODULE_DEVICE_TABLE(usb, qcm_table);
|
|||
static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int error;
|
||||
|
||||
usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
|
||||
strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
|
||||
|
@ -106,7 +107,13 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
|
|||
|
||||
input_dev->private = cam;
|
||||
|
||||
input_register_device(cam->input);
|
||||
error = input_register_device(cam->input);
|
||||
if (error) {
|
||||
warn("Failed to register camera's input device, err: %d\n",
|
||||
error);
|
||||
input_free_device(cam->input);
|
||||
cam->input = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void qcm_unregister_input(struct qcm *cam)
|
||||
|
|
12
drivers/media/video/usbvision/Kconfig
Normal file
12
drivers/media/video/usbvision/Kconfig
Normal file
|
@ -0,0 +1,12 @@
|
|||
config VIDEO_USBVISION
|
||||
tristate "USB video devices based on Nogatech NT1003/1004/1005"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
select VIDEO_TUNER
|
||||
select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
|
||||
---help---
|
||||
There are more than 50 different USB video devices based on
|
||||
NT1003/1004/1005 USB Bridges. This driver enables using those
|
||||
devices.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called usbvision.
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue