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:
Linus Torvalds 2006-12-10 09:59:18 -08:00
commit bb7320d1d9
124 changed files with 15660 additions and 4354 deletions

View file

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

View file

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

View file

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

View 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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -14,7 +14,7 @@
* 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
@ -27,7 +27,7 @@
#include "cx22702.h"
#include "lgdt330x.h"
#include "lg_h06xf.h"
#include "lgh06xf.h"
#include "mt352.h"
#include "mt352_priv.h"
#include "zl10353.h"
@ -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;
@ -122,7 +123,8 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
obuf[1] = 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,8 +468,10 @@ 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);
}
@ -577,7 +576,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_lgdt3303_frontend_attach,
.tuner_attach = cxusb_lgdt3303_tuner_attach,
.tuner_attach = cxusb_lgh064f_tuner_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
@ -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");

View file

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

View file

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

View file

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

View file

@ -317,6 +317,7 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
.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,

View file

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

View file

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

View 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");

View 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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View 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

File diff suppressed because it is too large Load diff

View 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

View file

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

View file

@ -472,13 +472,13 @@ 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);
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;

View file

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

View file

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

View file

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

View file

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

View 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:
*/

View 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_ */

View file

@ -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;
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;
}
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);
if (mse == 0) /* No signal */
return 0;
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;
}
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;
}

View file

@ -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;
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;
}
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);
if (mse == 0) /* No signal */
return 0;
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;
}
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;
}

View file

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

View file

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

View file

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

View file

@ -42,7 +42,6 @@ struct tda826x_priv {
static int tda826x_release(struct dvb_frontend *fe)
{
if (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;

View file

@ -43,7 +43,6 @@ struct tua6100_priv {
static int tua6100_release(struct dvb_frontend *fe)
{
if (fe->tuner_priv)
kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
return 0;

View file

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

View file

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

View file

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

View file

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

View file

@ -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);
}
if (!key_map[code]) {
printk("DVB (%s): no key for %02x!\n", __FUNCTION__, code);
/* 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;
}
/* 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);
/* 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;
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],

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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) {
@ -349,9 +384,8 @@ int bttv_input_init(struct bttv *btv)
}
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;
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;

View 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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -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,
@ -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);
@ -1514,6 +1532,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,
.subdevice = 0xdb40,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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,6 +354,7 @@ 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;
@ -362,8 +362,8 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
default:
/* shouldn't happen */
printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
kfree(ir);
return -1;
err = -ENODEV;
goto err_out_free;
}
/* Sets name */
@ -374,13 +374,14 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
* 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) */
@ -394,8 +395,10 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
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);
@ -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;

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -889,6 +889,7 @@ 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])
@ -896,8 +897,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
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");
dev->board, dev->autodetected ?
"autodetected" : "insmod option");
/* get mmio */
if (!request_mem_region(pci_resource_start(pci_dev,0),

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

@ -0,0 +1,5 @@
usbvision-objs := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o
obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
EXTRA_CFLAGS += -Idrivers/media/video

View file

@ -0,0 +1,157 @@
/*
* USBVISION.H
* usbvision header file
*
* Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
*
* This module is part of usbvision driver project.
* Updates to driver completed by Dwaine P. Garden
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/list.h>
#include <linux/i2c.h>
#include <media/v4l2-dev.h>
#include <media/tuner.h>
#include "usbvision.h"
/* Supported Devices: A table for usbvision.c*/
struct usbvision_device_data_st usbvision_device_data[] = {
{0xFFF0, 0xFFF0, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Custom Dummy USBVision Device"},
{0x0A6F, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "Xanboo"},
{0x050D, 0x0208, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Belkin USBView II"},
{0x0571, 0x0002, 0, CODEC_SAA7111, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, -1, -1, 7, "echoFX InterView Lite"},
{0x0573, 0x0003, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "USBGear USBG-V1 resp. HAMA USB"},
{0x0573, 0x0400, -1, CODEC_SAA7113, 4, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "D-Link V100"},
{0x0573, 0x2000, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, -1, -1, -1, "X10 USB Camera"},
{0x0573, 0x2d00, -1, CODEC_SAA7111, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, -1, 3, 7, "Osprey 50"},
{0x0573, 0x2d01, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Hauppauge USB-Live Model 600"},
{0x0573, 0x2101, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 2, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Zoran Co. PMD (Nogatech) AV-grabber Manhattan"},
{0x0573, 0x4100, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Nogatech USB-TV (NTSC) FM"},
{0x0573, 0x4110, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "PNY USB-TV (NTSC) FM"},
{0x0573, 0x4450, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "PixelView PlayTv-USB PRO (PAL) FM"},
{0x0573, 0x4550, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "ZTV ZT-721 2.4GHz USB A/V Receiver"},
{0x0573, 0x4d00, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, 20, -1, "Hauppauge WinTv-USB USA"},
{0x0573, 0x4d01, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"},
{0x0573, 0x4d02, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC)"},
{0x0573, 0x4d03, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (SECAM) "},
{0x0573, 0x4d10, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (NTSC) FM"},
{0x0573, 0x4d11, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"},
{0x0573, 0x4d12, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB (PAL) FM"},
{0x0573, 0x4d2a, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B285"},
{0x0573, 0x4d2b, 0, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (NTSC) FM Model 602 40201 Rev B282"},
{0x0573, 0x4d2c, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTv USB (PAL/SECAM) 40209 Rev E1A5"},
{0x0573, 0x4d20, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226"},
{0x0573, 0x4d21, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL)"},
{0x0573, 0x4d22, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB II (PAL) MODEL 566"},
{0x0573, 0x4d23, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) 4D23"},
{0x0573, 0x4d25, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B234"},
{0x0573, 0x4d26, -1, CODEC_SAA7113, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB (SECAM) Model 40209 Rev B243"},
{0x0573, 0x4d27, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B281"},
{0x0573, 0x4d28, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_ALPS_TSBE1_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40204 Rev B283"},
{0x0573, 0x4d29, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB Model 40205 Rev B298"},
{0x0573, 0x4d30, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB FM Model 40211 Rev B123"},
{0x0573, 0x4d31, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 568"},
{0x0573, 0x4d32, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 573"},
{0x0573, 0x4d35, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_MICROTUNE_4049FM5, -1, -1, 0, 3, 7, "Hauppauge WinTv-USB III (PAL) FM Model 40219 Rev B252"},
{0x0573, 0x4d37, 0, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_FM1216ME_MK3, -1, -1, 0, 3, 7, "Hauppauge WinTV USB device Model 40219 Rev E189"},
{0x0768, 0x0006, -1, CODEC_SAA7113, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, 5, 5, -1, "Camtel Technology USB TV Genie Pro FM Model TVB330"},
{0x07d0, 0x0001, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Digital Video Creator I"},
{0x07d0, 0x0002, -1, CODEC_SAA7111, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 82, 20, 7, "Global Village GV-007 (NTSC)"},
{0x07d0, 0x0003, 0, CODEC_SAA7113, 2, V4L2_STD_NTSC, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)"},
{0x07d0, 0x0004, 0, CODEC_SAA7113, 2, V4L2_STD_PAL, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-80 Rev 1 (PAL)"},
{0x07d0, 0x0005, 0, CODEC_SAA7113, 2, V4L2_STD_SECAM, 0, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)"},
{0x2304, 0x010d, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 0, 1, TUNER_TEMIC_4066FY5_PAL_I, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (PAL)"},
{0x2304, 0x0109, -1, CODEC_SAA7111, 3, V4L2_STD_SECAM, 1, 0, 1, 1, TUNER_PHILIPS_SECAM, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (SECAM)"},
{0x2304, 0x0110, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_PHILIPS_PAL, -1, -1,128, 23, -1, "Pinnacle Studio PCTV USB (PAL) FM"},
{0x2304, 0x0111, -1, CODEC_SAA7111, 3, V4L2_STD_PAL, 1, 0, 1, 1, TUNER_PHILIPS_PAL, -1, -1, -1, -1, -1, "Miro PCTV USB"},
{0x2304, 0x0112, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Pinnacle Studio PCTV USB (NTSC) FM"},
{0x2304, 0x0210, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"},
{0x2304, 0x0212, -1, CODEC_SAA7111, 3, V4L2_STD_NTSC, 1, 1, 1, 1, TUNER_TEMIC_4039FR5_NTSC, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (NTSC) FM"},
{0x2304, 0x0214, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle Studio PCTV USB (PAL) FM"},
{0x2304, 0x0300, -1, CODEC_SAA7113, 2, V4L2_STD_NTSC, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (NTSC)"},
{0x2304, 0x0301, -1, CODEC_SAA7113, 2, V4L2_STD_PAL, 1, 0, 1, 0, 0, -1, -1, 0, 3, 7, "Pinnacle Studio Linx Video input cable (PAL)"},
{0x2304, 0x0419, -1, CODEC_SAA7113, 3, V4L2_STD_PAL, 1, 1, 1, 1, TUNER_TEMIC_4009FR5_PAL, -1, -1, 0, 3, 7, "Pinnacle PCTV Bungee USB (PAL) FM"},
{0x2400, 0x4200, -1, CODEC_SAA7111, 3, VIDEO_MODE_NTSC, 1, 0, 1, 1, TUNER_PHILIPS_NTSC_M, -1, -1, -1, -1, -1, "Hauppauge WinTv-USB"},
{} /* Terminating entry */
};
/* Supported Devices */
struct usb_device_id usbvision_table [] = {
{ USB_DEVICE(0xFFF0, 0xFFF0) }, /* Custom Dummy USBVision Device */
{ USB_DEVICE(0x0A6F, 0x0400) }, /* Xanboo */
{ USB_DEVICE(0x050d, 0x0208) }, /* Belkin USBView II */
{ USB_DEVICE(0x0571, 0x0002) }, /* echoFX InterView Lite */
{ USB_DEVICE(0x0573, 0x0003) }, /* USBGear USBG-V1 */
{ USB_DEVICE(0x0573, 0x0400) }, /* D-Link V100 */
{ USB_DEVICE(0x0573, 0x2000) }, /* X10 USB Camera */
{ USB_DEVICE(0x0573, 0x2d00) }, /* Osprey 50 */
{ USB_DEVICE(0x0573, 0x2d01) }, /* Hauppauge USB-Live Model 600 */
{ USB_DEVICE(0x0573, 0x2101) }, /* Zoran Co. PMD (Nogatech) AV-grabber Manhattan */
{ USB_DEVICE(0x0573, 0x4100) }, /* Nogatech USB-TV FM (NTSC) */
{ USB_DEVICE(0x0573, 0x4110) }, /* PNY USB-TV (NTSC) FM */
{ USB_DEVICE(0x0573, 0x4450) }, /* PixelView PlayTv-USB PRO (PAL) FM */
{ USB_DEVICE(0x0573, 0x4550) }, /* ZTV ZT-721 2.4GHz USB A/V Receiver */
{ USB_DEVICE(0x0573, 0x4d00) }, /* Hauppauge WinTv-USB USA */
{ USB_DEVICE(0x0573, 0x4d01) }, /* Hauppauge WinTv-USB */
{ USB_DEVICE(0x0573, 0x4d02) }, /* Hauppauge WinTv-USB UK */
{ USB_DEVICE(0x0573, 0x4d03) }, /* Hauppauge WinTv-USB France */
{ USB_DEVICE(0x0573, 0x4d10) }, /* Hauppauge WinTv-USB with FM USA radio */
{ USB_DEVICE(0x0573, 0x4d11) }, /* Hauppauge WinTv-USB (PAL) with FM radio */
{ USB_DEVICE(0x0573, 0x4d12) }, /* Hauppauge WinTv-USB UK with FM Radio */
{ USB_DEVICE(0x0573, 0x4d2a) }, /* Hauppague WinTv USB Model 602 40201 Rev B285 */
{ USB_DEVICE(0x0573, 0x4d2b) }, /* Hauppague WinTv USB Model 602 40201 Rev B282 */
{ USB_DEVICE(0x0573, 0x4d2c) }, /* Hauppague WinTv USB Model 40209 Rev. E1A5 PAL*/
{ USB_DEVICE(0x0573, 0x4d20) }, /* Hauppauge WinTv-USB II (PAL) FM Model 40201 Rev B226 */
{ USB_DEVICE(0x0573, 0x4d21) }, /* Hauppauge WinTv-USB II (PAL) with FM radio*/
{ USB_DEVICE(0x0573, 0x4d22) }, /* Hauppauge WinTv-USB II (PAL) Model 566 */
{ USB_DEVICE(0x0573, 0x4d23) }, /* Hauppauge WinTv-USB France 4D23*/
{ USB_DEVICE(0x0573, 0x4d25) }, /* Hauppauge WinTv-USB Model 40209 rev B234 */
{ USB_DEVICE(0x0573, 0x4d26) }, /* Hauppauge WinTv-USB Model 40209 Rev B243 */
{ USB_DEVICE(0x0573, 0x4d27) }, /* Hauppauge WinTv-USB Model 40204 Rev B281 */
{ USB_DEVICE(0x0573, 0x4d28) }, /* Hauppauge WinTv-USB Model 40204 Rev B283 */
{ USB_DEVICE(0x0573, 0x4d29) }, /* Hauppauge WinTv-USB Model 40205 Rev B298 */
{ USB_DEVICE(0x0573, 0x4d30) }, /* Hauppauge WinTv-USB FM Model 40211 Rev B123 */
{ USB_DEVICE(0x0573, 0x4d31) }, /* Hauppauge WinTv-USB III (PAL) with FM radio Model 568 */
{ USB_DEVICE(0x0573, 0x4d32) }, /* Hauppauge WinTv-USB III (PAL) FM Model 573 */
{ USB_DEVICE(0x0573, 0x4d35) }, /* Hauppauge WinTv-USB III (SECAM) FM Model 40219 Rev B252 */
{ USB_DEVICE(0x0573, 0x4d37) }, /* Hauppauge WinTv-USB Model 40219 Rev E189 */
{ USB_DEVICE(0x0768, 0x0006) }, /* Camtel Technology USB TV Genie Pro FM Model TVB330 */
{ USB_DEVICE(0x07d0, 0x0001) }, /* Digital Video Creator I */
{ USB_DEVICE(0x07d0, 0x0002) }, /* Global Village GV-007 (NTSC) */
{ USB_DEVICE(0x07d0, 0x0003) }, /* Dazzle Fusion Model DVC-50 Rev 1 (NTSC) */
{ USB_DEVICE(0x07d0, 0x0004) }, /* Dazzle Fusion Model DVC-80 Rev 1 (PAL) */
{ USB_DEVICE(0x07d0, 0x0005) }, /* Dazzle Fusion Model DVC-90 Rev 1 (SECAM) */
{ USB_DEVICE(0x2304, 0x010d) }, /* Pinnacle Studio PCTV USB (PAL) */
{ USB_DEVICE(0x2304, 0x0109) }, /* Pinnacle Studio PCTV USB (SECAM) */
{ USB_DEVICE(0x2304, 0x0110) }, /* Pinnacle Studio PCTV USB (PAL) */
{ USB_DEVICE(0x2304, 0x0111) }, /* Miro PCTV USB */
{ USB_DEVICE(0x2304, 0x0112) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */
{ USB_DEVICE(0x2304, 0x0210) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */
{ USB_DEVICE(0x2304, 0x0212) }, /* Pinnacle Studio PCTV USB (NTSC) with FM radio */
{ USB_DEVICE(0x2304, 0x0214) }, /* Pinnacle Studio PCTV USB (PAL) with FM radio */
{ USB_DEVICE(0x2304, 0x0300) }, /* Pinnacle Studio Linx Video input cable (NTSC) */
{ USB_DEVICE(0x2304, 0x0301) }, /* Pinnacle Studio Linx Video input cable (PAL) */
{ USB_DEVICE(0x2304, 0x0419) }, /* Pinnacle PCTV Bungee USB (PAL) FM */
{ USB_DEVICE(0x2400, 0x4200) }, /* Hauppauge WinTv-USB2 Model 42012 */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, usbvision_table);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,567 @@
/*
* I2C_ALGO_USB.C
* i2c algorithm for USB-I2C Bridges
*
* Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
* Dwaine Garden <dwainegarden@rogers.com>
*
* This module is part of usbvision driver project.
* Updates to driver completed by Dwaine P. Garden
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/utsname.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/usb.h>
#include <linux/i2c.h>
#include "usbvision.h"
#define DBG_I2C 1<<0
#define DBG_ALGO 1<<1
static int i2c_debug = 0;
module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver
MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
#define PDEBUG(level, fmt, args...) \
if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args)
static inline int try_write_address(struct i2c_adapter *i2c_adap,
unsigned char addr, int retries)
{
struct i2c_algo_usb_data *adap = i2c_adap->algo_data;
void *data;
int i, ret = -1;
char buf[4];
data = i2c_get_adapdata(i2c_adap);
buf[0] = 0x00;
for (i = 0; i <= retries; i++) {
ret = (adap->outb(data, addr, buf, 1));
if (ret == 1)
break; /* success! */
udelay(5 /*adap->udelay */ );
if (i == retries) /* no success */
break;
udelay(adap->udelay);
}
if (i) {
PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr);
PDEBUG(DBG_ALGO,"Maybe there's no device at this address");
}
return ret;
}
static inline int try_read_address(struct i2c_adapter *i2c_adap,
unsigned char addr, int retries)
{
struct i2c_algo_usb_data *adap = i2c_adap->algo_data;
void *data;
int i, ret = -1;
char buf[4];
data = i2c_get_adapdata(i2c_adap);
for (i = 0; i <= retries; i++) {
ret = (adap->inb(data, addr, buf, 1));
if (ret == 1)
break; /* success! */
udelay(5 /*adap->udelay */ );
if (i == retries) /* no success */
break;
udelay(adap->udelay);
}
if (i) {
PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr);
PDEBUG(DBG_ALGO,"Maybe there's no device at this address");
}
return ret;
}
static inline int usb_find_address(struct i2c_adapter *i2c_adap,
struct i2c_msg *msg, int retries,
unsigned char *add)
{
unsigned short flags = msg->flags;
unsigned char addr;
int ret;
if ((flags & I2C_M_TEN)) {
/* a ten bit address */
addr = 0xf0 | ((msg->addr >> 7) & 0x03);
/* try extended address code... */
ret = try_write_address(i2c_adap, addr, retries);
if (ret != 1) {
err("died at extended address code, while writing");
return -EREMOTEIO;
}
add[0] = addr;
if (flags & I2C_M_RD) {
/* okay, now switch into reading mode */
addr |= 0x01;
ret = try_read_address(i2c_adap, addr, retries);
if (ret != 1) {
err("died at extended address code, while reading");
return -EREMOTEIO;
}
}
} else { /* normal 7bit address */
addr = (msg->addr << 1);
if (flags & I2C_M_RD)
addr |= 1;
if (flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
add[0] = addr;
if (flags & I2C_M_RD)
ret = try_read_address(i2c_adap, addr, retries);
else
ret = try_write_address(i2c_adap, addr, retries);
if (ret != 1) {
return -EREMOTEIO;
}
}
return 0;
}
static int
usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
{
struct i2c_msg *pmsg;
struct i2c_algo_usb_data *adap = i2c_adap->algo_data;
void *data;
int i, ret;
unsigned char addr;
data = i2c_get_adapdata(i2c_adap);
for (i = 0; i < num; i++) {
pmsg = &msgs[i];
ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr);
if (ret != 0) {
PDEBUG(DBG_ALGO,"got NAK from device, message #%d", i);
return (ret < 0) ? ret : -EREMOTEIO;
}
if (pmsg->flags & I2C_M_RD) {
/* read bytes into buffer */
ret = (adap->inb(data, addr, pmsg->buf, pmsg->len));
if (ret < pmsg->len) {
return (ret < 0) ? ret : -EREMOTEIO;
}
} else {
/* write bytes from buffer */
ret = (adap->outb(data, addr, pmsg->buf, pmsg->len));
if (ret < pmsg->len) {
return (ret < 0) ? ret : -EREMOTEIO;
}
}
}
return num;
}
static int algo_control(struct i2c_adapter *adapter, unsigned int cmd, unsigned long arg)
{
return 0;
}
static u32 usb_func(struct i2c_adapter *adap)
{
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
}
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm i2c_usb_algo = {
.master_xfer = usb_xfer,
.smbus_xfer = NULL,
.algo_control = algo_control,
.functionality = usb_func,
};
/*
* registering functions to load algorithms at runtime
*/
int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap)
{
PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]");
PDEBUG(DBG_ALGO, "ALGO debugging is enabled [i2c]");
/* register new adapter to i2c module... */
adap->algo = &i2c_usb_algo;
adap->timeout = 100; /* default values, should */
adap->retries = 3; /* be replaced by defines */
i2c_add_adapter(adap);
PDEBUG(DBG_ALGO,"i2c bus for %s registered", adap->name);
return 0;
}
int usbvision_i2c_usb_del_bus(struct i2c_adapter *adap)
{
i2c_del_adapter(adap);
PDEBUG(DBG_ALGO,"i2c bus for %s unregistered", adap->name);
return 0;
}
/* ----------------------------------------------------------------------- */
/* usbvision specific I2C functions */
/* ----------------------------------------------------------------------- */
static struct i2c_adapter i2c_adap_template;
static struct i2c_algo_usb_data i2c_algo_template;
static struct i2c_client i2c_client_template;
int usbvision_init_i2c(struct usb_usbvision *usbvision)
{
memcpy(&usbvision->i2c_adap, &i2c_adap_template,
sizeof(struct i2c_adapter));
memcpy(&usbvision->i2c_algo, &i2c_algo_template,
sizeof(struct i2c_algo_usb_data));
memcpy(&usbvision->i2c_client, &i2c_client_template,
sizeof(struct i2c_client));
sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name),
" #%d", usbvision->vdev->minor & 0x1f);
PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name);
i2c_set_adapdata(&usbvision->i2c_adap, usbvision);
i2c_set_clientdata(&usbvision->i2c_client, usbvision);
i2c_set_algo_usb_data(&usbvision->i2c_algo, usbvision);
usbvision->i2c_adap.algo_data = &usbvision->i2c_algo;
usbvision->i2c_client.adapter = &usbvision->i2c_adap;
if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) {
printk(KERN_ERR "usbvision_init_i2c: can't write reg\n");
return -EBUSY;
}
#ifdef CONFIG_MODULES
/* Request the load of the i2c modules we need */
switch (usbvision_device_data[usbvision->DevModel].Codec) {
case CODEC_SAA7113:
request_module("saa7115");
break;
case CODEC_SAA7111:
request_module("saa7115");
break;
}
if (usbvision_device_data[usbvision->DevModel].Tuner == 1) {
request_module("tuner");
}
#endif
return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap);
}
void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,
void *arg)
{
BUG_ON(NULL == usbvision->i2c_adap.algo_data);
i2c_clients_command(&usbvision->i2c_adap, cmd, arg);
}
static int attach_inform(struct i2c_client *client)
{
struct usb_usbvision *usbvision;
usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter);
switch (client->addr << 1) {
case 0x43:
case 0x4b:
{
struct tuner_setup tun_setup;
tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
tun_setup.type = TUNER_TDA9887;
tun_setup.addr = client->addr;
call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup);
break;
}
case 0x42:
PDEBUG(DBG_I2C,"attach_inform: saa7114 detected.");
break;
case 0x4a:
PDEBUG(DBG_I2C,"attach_inform: saa7113 detected.");
break;
case 0xa0:
PDEBUG(DBG_I2C,"attach_inform: eeprom detected.");
break;
default:
{
struct tuner_setup tun_setup;
PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1);
usbvision->tuner_addr = client->addr;
if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) {
tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
tun_setup.type = usbvision->tuner_type;
tun_setup.addr = usbvision->tuner_addr;
call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup);
}
}
break;
}
return 0;
}
static int detach_inform(struct i2c_client *client)
{
struct usb_usbvision *usbvision;
usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter);
PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name);
return 0;
}
static int
usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr,
char *buf, short len)
{
int rc, retries;
for (retries = 5;;) {
rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr);
if (rc < 0)
return rc;
/* Initiate byte read cycle */
/* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */
/* d3 0=Wr 1=Rd */
rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT,
(len & 0x07) | 0x18);
if (rc < 0)
return rc;
/* Test for Busy and ACK */
do {
/* USBVISION_SER_CONT -> d4 == 0 busy */
rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT);
} while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */
if (rc < 0)
return rc;
/* USBVISION_SER_CONT -> d5 == 1 Not ack */
if ((rc & 0x20) == 0) /* Ack? */
break;
/* I2C abort */
rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00);
if (rc < 0)
return rc;
if (--retries < 0)
return -1;
}
switch (len) {
case 4:
buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4);
case 3:
buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3);
case 2:
buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2);
case 1:
buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1);
break;
default:
printk(KERN_ERR
"usbvision_i2c_read_max4: buffer length > 4\n");
}
if (i2c_debug & DBG_I2C) {
int idx;
for (idx = 0; idx < len; idx++) {
PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr);
}
}
return len;
}
static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision,
unsigned char addr, const char *buf,
short len)
{
int rc, retries;
int i;
unsigned char value[6];
unsigned char ser_cont;
ser_cont = (len & 0x07) | 0x10;
value[0] = addr;
value[1] = ser_cont;
for (i = 0; i < len; i++)
value[i + 2] = buf[i];
for (retries = 5;;) {
rc = usb_control_msg(usbvision->dev,
usb_sndctrlpipe(usbvision->dev, 1),
USBVISION_OP_CODE,
USB_DIR_OUT | USB_TYPE_VENDOR |
USB_RECIP_ENDPOINT, 0,
(__u16) USBVISION_SER_ADRS, value,
len + 2, HZ);
if (rc < 0)
return rc;
rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT,
(len & 0x07) | 0x10);
if (rc < 0)
return rc;
/* Test for Busy and ACK */
do {
rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT);
} while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */
if (rc < 0)
return rc;
if ((rc & 0x20) == 0) /* Ack? */
break;
/* I2C abort */
usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00);
if (--retries < 0)
return -1;
}
if (i2c_debug & DBG_I2C) {
int idx;
for (idx = 0; idx < len; idx++) {
PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr);
}
}
return len;
}
static int usbvision_i2c_write(void *data, unsigned char addr, char *buf,
short len)
{
char *bufPtr = buf;
int retval;
int wrcount = 0;
int count;
int maxLen = 4;
struct usb_usbvision *usbvision = (struct usb_usbvision *) data;
while (len > 0) {
count = (len > maxLen) ? maxLen : len;
retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count);
if (retval > 0) {
len -= count;
bufPtr += count;
wrcount += count;
} else
return (retval < 0) ? retval : -EFAULT;
}
return wrcount;
}
static int usbvision_i2c_read(void *data, unsigned char addr, char *buf,
short len)
{
char temp[4];
int retval, i;
int rdcount = 0;
int count;
struct usb_usbvision *usbvision = (struct usb_usbvision *) data;
while (len > 0) {
count = (len > 3) ? 4 : len;
retval = usbvision_i2c_read_max4(usbvision, addr, temp, count);
if (retval > 0) {
for (i = 0; i < len; i++)
buf[rdcount + i] = temp[i];
len -= count;
rdcount += count;
} else
return (retval < 0) ? retval : -EFAULT;
}
return rdcount;
}
static struct i2c_algo_usb_data i2c_algo_template = {
.data = NULL,
.inb = usbvision_i2c_read,
.outb = usbvision_i2c_write,
.udelay = 10,
.mdelay = 10,
.timeout = 100,
};
static struct i2c_adapter i2c_adap_template = {
.owner = THIS_MODULE,
.name = "usbvision",
.id = I2C_HW_B_BT848, /* FIXME */
.algo = NULL,
.algo_data = NULL,
.client_register = attach_inform,
.client_unregister = detach_inform,
#ifdef I2C_ADAP_CLASS_TV_ANALOG
.class = I2C_ADAP_CLASS_TV_ANALOG,
#else
.class = I2C_CLASS_TV_ANALOG,
#endif
};
static struct i2c_client i2c_client_template = {
.name = "usbvision internal",
};
EXPORT_SYMBOL(usbvision_i2c_usb_add_bus);
EXPORT_SYMBOL(usbvision_i2c_usb_del_bus);
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* ---------------------------------------------------------------------------
* Local variables:
* c-basic-offset: 8
* End:
*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,558 @@
/*
* USBVISION.H
* usbvision header file
*
* Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
* Dwaine Garden <dwainegarden@rogers.com>
*
*
* Report problems to v4l MailingList : http://www.redhat.com/mailman/listinfo/video4linux-list
*
* This module is part of usbvision driver project.
* Updates to driver completed by Dwaine P. Garden
* v4l2 conversion by Thierry Merle <thierry.merle@free.fr>
*
* 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 __LINUX_USBVISION_H
#define __LINUX_USBVISION_H
#include <linux/list.h>
#include <linux/usb.h>
#include <media/v4l2-common.h>
#include <media/tuner.h>
#include <linux/videodev2.h>
#define USBVISION_DEBUG /* Turn on debug messages */
#ifndef VID_HARDWARE_USBVISION
#define VID_HARDWARE_USBVISION 34 /* USBVision Video Grabber */
#endif
#define USBVISION_PWR_REG 0x00
#define USBVISION_SSPND_EN (1 << 1)
#define USBVISION_RES2 (1 << 2)
#define USBVISION_PWR_VID (1 << 5)
#define USBVISION_E2_EN (1 << 7)
#define USBVISION_CONFIG_REG 0x01
#define USBVISION_ADRS_REG 0x02
#define USBVISION_ALTER_REG 0x03
#define USBVISION_FORCE_ALTER_REG 0x04
#define USBVISION_STATUS_REG 0x05
#define USBVISION_IOPIN_REG 0x06
#define USBVISION_IO_1 (1 << 0)
#define USBVISION_IO_2 (1 << 1)
#define USBVISION_AUDIO_IN 0
#define USBVISION_AUDIO_TV 1
#define USBVISION_AUDIO_RADIO 2
#define USBVISION_AUDIO_MUTE 3
#define USBVISION_SER_MODE 0x07
#define USBVISION_SER_ADRS 0x08
#define USBVISION_SER_CONT 0x09
#define USBVISION_SER_DAT1 0x0A
#define USBVISION_SER_DAT2 0x0B
#define USBVISION_SER_DAT3 0x0C
#define USBVISION_SER_DAT4 0x0D
#define USBVISION_EE_DATA 0x0E
#define USBVISION_EE_LSBAD 0x0F
#define USBVISION_EE_CONT 0x10
#define USBVISION_DRM_CONT 0x12
#define USBVISION_REF (1 << 0)
#define USBVISION_RES_UR (1 << 2)
#define USBVISION_RES_FDL (1 << 3)
#define USBVISION_RES_VDW (1 << 4)
#define USBVISION_DRM_PRM1 0x13
#define USBVISION_DRM_PRM2 0x14
#define USBVISION_DRM_PRM3 0x15
#define USBVISION_DRM_PRM4 0x16
#define USBVISION_DRM_PRM5 0x17
#define USBVISION_DRM_PRM6 0x18
#define USBVISION_DRM_PRM7 0x19
#define USBVISION_DRM_PRM8 0x1A
#define USBVISION_VIN_REG1 0x1B
#define USBVISION_8_422_SYNC 0x01
#define USBVISION_16_422_SYNC 0x02
#define USBVISION_VSNC_POL (1 << 3)
#define USBVISION_HSNC_POL (1 << 4)
#define USBVISION_FID_POL (1 << 5)
#define USBVISION_HVALID_PO (1 << 6)
#define USBVISION_VCLK_POL (1 << 7)
#define USBVISION_VIN_REG2 0x1C
#define USBVISION_AUTO_FID (1 << 0)
#define USBVISION_NONE_INTER (1 << 1)
#define USBVISION_NOHVALID (1 << 2)
#define USBVISION_UV_ID (1 << 3)
#define USBVISION_FIX_2C (1 << 4)
#define USBVISION_SEND_FID (1 << 5)
#define USBVISION_KEEP_BLANK (1 << 7)
#define USBVISION_LXSIZE_I 0x1D
#define USBVISION_MXSIZE_I 0x1E
#define USBVISION_LYSIZE_I 0x1F
#define USBVISION_MYSIZE_I 0x20
#define USBVISION_LX_OFFST 0x21
#define USBVISION_MX_OFFST 0x22
#define USBVISION_LY_OFFST 0x23
#define USBVISION_MY_OFFST 0x24
#define USBVISION_FRM_RATE 0x25
#define USBVISION_LXSIZE_O 0x26
#define USBVISION_MXSIZE_O 0x27
#define USBVISION_LYSIZE_O 0x28
#define USBVISION_MYSIZE_O 0x29
#define USBVISION_FILT_CONT 0x2A
#define USBVISION_VO_MODE 0x2B
#define USBVISION_INTRA_CYC 0x2C
#define USBVISION_STRIP_SZ 0x2D
#define USBVISION_FORCE_INTRA 0x2E
#define USBVISION_FORCE_UP 0x2F
#define USBVISION_BUF_THR 0x30
#define USBVISION_DVI_YUV 0x31
#define USBVISION_AUDIO_CONT 0x32
#define USBVISION_AUD_PK_LEN 0x33
#define USBVISION_BLK_PK_LEN 0x34
#define USBVISION_PCM_THR1 0x38
#define USBVISION_PCM_THR2 0x39
#define USBVISION_DIST_THR_L 0x3A
#define USBVISION_DIST_THR_H 0x3B
#define USBVISION_MAX_DIST_L 0x3C
#define USBVISION_MAX_DIST_H 0x3D
#define USBVISION_OP_CODE 0x33
#define MAX_BYTES_PER_PIXEL 4
#define MIN_FRAME_WIDTH 64
#define MAX_USB_WIDTH 320 //384
#define MAX_FRAME_WIDTH 320 //384 /*streching sometimes causes crashes*/
#define MIN_FRAME_HEIGHT 48
#define MAX_USB_HEIGHT 240 //288
#define MAX_FRAME_HEIGHT 240 //288 /*Streching sometimes causes crashes*/
#define MAX_FRAME_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL)
#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask
#define USBVISION_URB_FRAMES 32
#define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023
#define USBVISION_NUM_HEADERMARKER 20
#define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */
#define USBVISION_NUMSBUF 2 /* Dimensioning the USB S buffering */
#define USBVISION_POWEROFF_TIME 3 * (HZ) // 3 seconds
#define FRAMERATE_MIN 0
#define FRAMERATE_MAX 31
enum {
ISOC_MODE_YUV422 = 0x03,
ISOC_MODE_YUV420 = 0x14,
ISOC_MODE_COMPRESS = 0x60,
};
/* This macro restricts an int variable to an inclusive range */
#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
/*
* We use macros to do YUV -> RGB conversion because this is
* very important for speed and totally unimportant for size.
*
* YUV -> RGB Conversion
* ---------------------
*
* B = 1.164*(Y-16) + 2.018*(V-128)
* G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
* R = 1.164*(Y-16) + 1.596*(U-128)
*
* If you fancy integer arithmetics (as you should), hear this:
*
* 65536*B = 76284*(Y-16) + 132252*(V-128)
* 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128)
* 65536*R = 76284*(Y-16) + 104595*(U-128)
*
* Make sure the output values are within [0..255] range.
*/
#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
mm_y = (my) - 16; \
mm_u = (mu) - 128; \
mm_v = (mv) - 128; \
mm_yc= mm_y * 76284; \
mm_b = (mm_yc + 132252*mm_v ) >> 16; \
mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \
mm_r = (mm_yc + 104595*mm_u ) >> 16; \
mb = LIMIT_RGB(mm_b); \
mg = LIMIT_RGB(mm_g); \
mr = LIMIT_RGB(mm_r); \
}
/* Debugging aid */
#define USBVISION_SAY_AND_WAIT(what) { \
wait_queue_head_t wq; \
init_waitqueue_head(&wq); \
printk(KERN_INFO "Say: %s\n", what); \
interruptible_sleep_on_timeout (&wq, HZ*3); \
}
/*
* This macro checks if usbvision is still operational. The 'usbvision'
* pointer must be valid, usbvision->dev must be valid, we are not
* removing the device and the device has not erred on us.
*/
#define USBVISION_IS_OPERATIONAL(udevice) (\
(udevice != NULL) && \
((udevice)->dev != NULL) && \
((udevice)->last_error == 0) && \
(!(udevice)->remove_pending))
/* I2C structures */
struct i2c_algo_usb_data {
void *data; /* private data for lowlevel routines */
int (*inb) (void *data, unsigned char addr, char *buf, short len);
int (*outb) (void *data, unsigned char addr, char *buf, short len);
/* local settings */
int udelay;
int mdelay;
int timeout;
};
#define I2C_USB_ADAP_MAX 16
/* ----------------------------------------------------------------- */
/* usbvision video structures */
/* ----------------------------------------------------------------- */
enum ScanState {
ScanState_Scanning, /* Scanning for header */
ScanState_Lines /* Parsing lines */
};
/* Completion states of the data parser */
enum ParseState {
ParseState_Continue, /* Just parse next item */
ParseState_NextFrame, /* Frame done, send it to V4L */
ParseState_Out, /* Not enough data for frame */
ParseState_EndParse /* End parsing */
};
enum FrameState {
FrameState_Unused, /* Unused (no MCAPTURE) */
FrameState_Ready, /* Ready to start grabbing */
FrameState_Grabbing, /* In the process of being grabbed into */
FrameState_Done, /* Finished grabbing, but not been synced yet */
FrameState_DoneHold, /* Are syncing or reading */
FrameState_Error, /* Something bad happened while processing */
};
/* stream states */
enum StreamState {
Stream_Off, /* Driver streaming is completely OFF */
Stream_Idle, /* Driver streaming is ready to be put ON by the application */
Stream_Interrupt, /* Driver streaming must be interrupted */
Stream_On, /* Driver streaming is put ON by the application */
};
enum IsocState {
IsocState_InFrame, /* Isoc packet is member of frame */
IsocState_NoFrame, /* Isoc packet is not member of any frame */
};
struct usb_device;
struct usbvision_sbuf {
char *data;
struct urb *urb;
};
#define USBVISION_MAGIC_1 0x55
#define USBVISION_MAGIC_2 0xAA
#define USBVISION_HEADER_LENGTH 0x0c
#define USBVISION_SAA7111_ADDR 0x48
#define USBVISION_SAA7113_ADDR 0x4a
#define USBVISION_IIC_LRACK 0x20
#define USBVISION_IIC_LRNACK 0x30
#define USBVISION_FRAME_FORMAT_PARAM_INTRA (1<<7)
struct usbvision_v4l2_format_st {
int supported;
int bytes_per_pixel;
int depth;
int format;
char *desc;
};
#define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format)
struct usbvision_frame_header {
unsigned char magic_1; /* 0 magic */
unsigned char magic_2; /* 1 magic */
unsigned char headerLength; /* 2 */
unsigned char frameNum; /* 3 */
unsigned char framePhase; /* 4 */
unsigned char frameLatency; /* 5 */
unsigned char dataFormat; /* 6 */
unsigned char formatParam; /* 7 */
unsigned char frameWidthLo; /* 8 */
unsigned char frameWidthHi; /* 9 */
unsigned char frameHeightLo; /* 10 */
unsigned char frameHeightHi; /* 11 */
__u16 frameWidth; /* 8 - 9 after endian correction*/
__u16 frameHeight; /* 10 - 11 after endian correction*/
};
/* tvnorms */
struct usbvision_tvnorm {
char *name;
v4l2_std_id id;
/* mode for saa7113h */
int mode;
};
struct usbvision_frame {
char *data; /* Frame buffer */
struct usbvision_frame_header isocHeader; /* Header from stream */
int width; /* Width application is expecting */
int height; /* Height */
int index; /* Frame index */
int frmwidth; /* Width the frame actually is */
int frmheight; /* Height */
volatile int grabstate; /* State of grabbing */
int scanstate; /* State of scanning */
struct list_head frame;
int curline; /* Line of frame we're working on */
long scanlength; /* uncompressed, raw data length of frame */
long bytes_read; /* amount of scanlength that has been read from data */
struct usbvision_v4l2_format_st v4l2_format; /* format the user needs*/
int v4l2_linesize; /* bytes for one videoline*/
struct timeval timestamp;
int sequence; // How many video frames we send to user
};
#define CODEC_SAA7113 7113
#define CODEC_SAA7111 7111
#define BRIDGE_NT1003 1003
#define BRIDGE_NT1004 1004
#define BRIDGE_NT1005 1005
struct usbvision_device_data_st {
int idVendor;
int idProduct;
int Interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */
int Codec;
int VideoChannels;
__u64 VideoNorm;
int AudioChannels;
int Radio;
int vbi;
int Tuner;
int TunerType;
int Vin_Reg1;
int Vin_Reg2;
int X_Offset;
int Y_Offset;
int Dvi_yuv;
char *ModelString;
};
/* Declared on usbvision-cards.c */
extern struct usbvision_device_data_st usbvision_device_data[];
extern struct usb_device_id usbvision_table[];
struct usb_usbvision {
struct video_device *vdev; /* Video Device */
struct video_device *rdev; /* Radio Device */
struct video_device *vbi; /* VBI Device */
/* i2c Declaration Section*/
struct i2c_adapter i2c_adap;
struct i2c_algo_usb_data i2c_algo;
struct i2c_client i2c_client;
struct urb *ctrlUrb;
unsigned char ctrlUrbBuffer[8];
int ctrlUrbBusy;
struct usb_ctrlrequest ctrlUrbSetup;
wait_queue_head_t ctrlUrb_wq; // Processes waiting
struct semaphore ctrlUrbLock;
/* configuration part */
int have_tuner;
int tuner_type;
int tuner_addr;
int bridgeType; // NT1003, NT1004, NT1005
int channel;
int radio;
int video_inputs; // # of inputs
unsigned long freq;
int AudioMute;
int AudioChannel;
int isocMode; // format of video data for the usb isoc-transfer
unsigned int nr; // Number of the device
/* Device structure */
struct usb_device *dev;
unsigned char iface; /* Video interface number */
unsigned char ifaceAltActive, ifaceAltInactive; /* Alt settings */
unsigned char Vin_Reg2_Preset;
struct semaphore lock;
struct timer_list powerOffTimer;
struct work_struct powerOffWork;
int power; /* is the device powered on? */
int user; /* user count for exclusive use */
int initialized; /* Had we already sent init sequence? */
int DevModel; /* What type of USBVISION device we got? */
enum StreamState streaming; /* Are we streaming Isochronous? */
int last_error; /* What calamity struck us? */
int curwidth; /* width of the frame the device is currently set to*/
int curheight; /* height of the frame the device is currently set to*/
int stretch_width; /* stretch-factor for frame width (from usb to screen)*/
int stretch_height; /* stretch-factor for frame height (from usb to screen)*/
char *fbuf; /* Videodev buffer area for mmap*/
int max_frame_size; /* Bytes in one video frame */
int fbuf_size; /* Videodev buffer size */
spinlock_t queue_lock; /* spinlock for protecting mods on inqueue and outqueue */
struct list_head inqueue, outqueue; /* queued frame list and ready to dequeue frame list */
wait_queue_head_t wait_frame; /* Processes waiting */
wait_queue_head_t wait_stream; /* Processes waiting */
struct usbvision_frame *curFrame; // pointer to current frame, set by usbvision_find_header
struct usbvision_frame frame[USBVISION_NUMFRAMES]; // frame buffer
struct usbvision_sbuf sbuf[USBVISION_NUMSBUF]; // S buffering
volatile int remove_pending; /* If set then about to exit */
/* Scratch space from the Isochronous Pipe.*/
unsigned char *scratch;
int scratch_read_ptr;
int scratch_write_ptr;
int scratch_headermarker[USBVISION_NUM_HEADERMARKER];
int scratch_headermarker_read_ptr;
int scratch_headermarker_write_ptr;
enum IsocState isocstate;
struct usbvision_v4l2_format_st palette;
struct v4l2_capability vcap; /* Video capabilities */
unsigned int ctl_input; /* selected input */
struct usbvision_tvnorm *tvnorm; /* selected tv norm */
unsigned char video_endp; /* 0x82 for USBVISION devices based */
// Decompression stuff:
unsigned char *IntraFrameBuffer; /* Buffer for reference frame */
int BlockPos; //for test only
int requestIntra; // 0 = normal; 1 = intra frame is requested;
int lastIsocFrameNum; // check for lost isoc frames
int isocPacketSize; // need to calculate usedBandwidth
int usedBandwidth; // used bandwidth 0-100%, need to set comprLevel
int comprLevel; // How strong (100) or weak (0) is compression
int lastComprLevel; // How strong (100) or weak (0) was compression
int usb_bandwidth; /* Mbit/s */
/* Statistics that can be overlayed on the screen */
unsigned long isocUrbCount; // How many URBs we received so far
unsigned long urb_length; /* Length of last URB */
unsigned long isocDataCount; /* How many bytes we received */
unsigned long header_count; /* How many frame headers we found */
unsigned long scratch_ovf_count; /* How many times we overflowed scratch */
unsigned long isocSkipCount; /* How many empty ISO packets received */
unsigned long isocErrCount; /* How many bad ISO packets received */
unsigned long isocPacketCount; // How many packets we totally got
unsigned long timeInIrq; // How long do we need for interrupt
int isocMeasureBandwidthCount;
int frame_num; // How many video frames we send to user
int maxStripLen; // How big is the biggest strip
int comprBlockPos;
int stripLenErrors; // How many times was BlockPos greater than StripLen
int stripMagicErrors;
int stripLineNumberErrors;
int ComprBlockTypes[4];
};
/* --------------------------------------------------------------- */
/* defined in usbvision-i2c.c */
/* i2c-algo-usb declaration */
/* --------------------------------------------------------------- */
int usbvision_i2c_usb_add_bus(struct i2c_adapter *);
int usbvision_i2c_usb_del_bus(struct i2c_adapter *);
static inline void *i2c_get_algo_usb_data (struct i2c_algo_usb_data *dev)
{
return dev->data;
}
static inline void i2c_set_algo_usb_data (struct i2c_algo_usb_data *dev, void *data)
{
dev->data = data;
}
/* ----------------------------------------------------------------------- */
/* usbvision specific I2C functions */
/* ----------------------------------------------------------------------- */
int usbvision_init_i2c(struct usb_usbvision *usbvision);
void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd,void *arg);
/* defined in usbvision-core.c */
void *usbvision_rvmalloc(unsigned long size);
void usbvision_rvfree(void *mem, unsigned long size);
int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg);
int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
unsigned char value);
int usbvision_frames_alloc(struct usb_usbvision *usbvision);
void usbvision_frames_free(struct usb_usbvision *usbvision);
int usbvision_scratch_alloc(struct usb_usbvision *usbvision);
void usbvision_scratch_free(struct usb_usbvision *usbvision);
int usbvision_sbuf_alloc(struct usb_usbvision *usbvision);
void usbvision_sbuf_free(struct usb_usbvision *usbvision);
int usbvision_decompress_alloc(struct usb_usbvision *usbvision);
void usbvision_decompress_free(struct usb_usbvision *usbvision);
int usbvision_setup(struct usb_usbvision *usbvision,int format);
int usbvision_init_isoc(struct usb_usbvision *usbvision);
int usbvision_restart_isoc(struct usb_usbvision *usbvision);
void usbvision_stop_isoc(struct usb_usbvision *usbvision);
int usbvision_set_audio(struct usb_usbvision *usbvision, int AudioChannel);
int usbvision_audio_off(struct usb_usbvision *usbvision);
int usbvision_begin_streaming(struct usb_usbvision *usbvision);
void usbvision_empty_framequeues(struct usb_usbvision *dev);
int usbvision_stream_interrupt(struct usb_usbvision *dev);
int usbvision_muxsel(struct usb_usbvision *usbvision, int channel);
int usbvision_set_input(struct usb_usbvision *usbvision);
int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height);
void usbvision_init_powerOffTimer(struct usb_usbvision *usbvision);
void usbvision_set_powerOffTimer(struct usb_usbvision *usbvision);
void usbvision_reset_powerOffTimer(struct usb_usbvision *usbvision);
int usbvision_power_off(struct usb_usbvision *usbvision);
int usbvision_power_on(struct usb_usbvision *usbvision);
#endif /* __LINUX_USBVISION_H */
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* ---------------------------------------------------------------------------
* Local variables:
* c-basic-offset: 8
* End:
*/

View file

@ -350,6 +350,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
struct video_buffer *buffer = arg;
memset(buffer, 0, sizeof(*buffer));
memset(&fbuf2, 0, sizeof(fbuf2));
err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
if (err < 0) {
@ -616,6 +617,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCSPICT: /* set tone controls & partial capture format */
{
struct video_picture *pict = arg;
memset(&fbuf2, 0, sizeof(fbuf2));
set_v4l_control(inode, file,
V4L2_CID_BRIGHTNESS, pict->brightness, drv);
@ -708,12 +710,22 @@ v4l_compat_translate_ioctl(struct inode *inode,
}
case VIDIOCSTUNER: /* select a tuner input */
{
err = 0;
struct video_tuner *tun = arg;
struct v4l2_tuner t;
memset(&t,0,sizeof(t));
t.index=tun->tuner;
err = drv(inode, file, VIDIOC_S_INPUT, &t);
if (err < 0)
dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
break;
}
case VIDIOCGFREQ: /* get frequency */
{
unsigned long *freq = arg;
memset(&freq2,0,sizeof(freq2));
freq2.tuner = 0;
err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
@ -726,8 +738,8 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCSFREQ: /* set frequency */
{
unsigned long *freq = arg;
memset(&freq2,0,sizeof(freq2));
freq2.tuner = 0;
drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
freq2.frequency = *freq;
err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
@ -738,6 +750,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
case VIDIOCGAUDIO: /* get audio properties/controls */
{
struct video_audio *aud = arg;
memset(&aud2,0,sizeof(aud2));
err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
if (err < 0) {
@ -898,6 +911,7 @@ v4l_compat_translate_ioctl(struct inode *inode,
{
int *i = arg;
memset(&buf2,0,sizeof(buf2));
buf2.index = *i;
buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);

View file

@ -87,6 +87,78 @@ MODULE_LICENSE("GPL");
*/
char *v4l2_norm_to_name(v4l2_std_id id)
{
char *name;
switch (id) {
case V4L2_STD_PAL:
name="PAL"; break;
case V4L2_STD_PAL_BG:
name="PAL-BG"; break;
case V4L2_STD_PAL_DK:
name="PAL-DK"; break;
case V4L2_STD_PAL_B:
name="PAL-B"; break;
case V4L2_STD_PAL_B1:
name="PAL-B1"; break;
case V4L2_STD_PAL_G:
name="PAL-G"; break;
case V4L2_STD_PAL_H:
name="PAL-H"; break;
case V4L2_STD_PAL_I:
name="PAL-I"; break;
case V4L2_STD_PAL_D:
name="PAL-D"; break;
case V4L2_STD_PAL_D1:
name="PAL-D1"; break;
case V4L2_STD_PAL_K:
name="PAL-K"; break;
case V4L2_STD_PAL_M:
name="PAL-M"; break;
case V4L2_STD_PAL_N:
name="PAL-N"; break;
case V4L2_STD_PAL_Nc:
name="PAL-Nc"; break;
case V4L2_STD_PAL_60:
name="PAL-60"; break;
case V4L2_STD_NTSC:
name="NTSC"; break;
case V4L2_STD_NTSC_M:
name="NTSC-M"; break;
case V4L2_STD_NTSC_M_JP:
name="NTSC-M-JP"; break;
case V4L2_STD_NTSC_443:
name="NTSC-443"; break;
case V4L2_STD_NTSC_M_KR:
name="NTSC-M-KR"; break;
case V4L2_STD_SECAM:
name="SECAM"; break;
case V4L2_STD_SECAM_DK:
name="SECAM-DK"; break;
case V4L2_STD_SECAM_B:
name="SECAM-B"; break;
case V4L2_STD_SECAM_D:
name="SECAM-D"; break;
case V4L2_STD_SECAM_G:
name="SECAM-G"; break;
case V4L2_STD_SECAM_H:
name="SECAM-H"; break;
case V4L2_STD_SECAM_K:
name="SECAM-K"; break;
case V4L2_STD_SECAM_K1:
name="SECAM-K1"; break;
case V4L2_STD_SECAM_L:
name="SECAM-L"; break;
case V4L2_STD_SECAM_LC:
name="SECAM-LC"; break;
default:
name="Unknown"; break;
}
return name;
}
/* Fill in the fields of a v4l2_standard structure according to the
'id' and 'transmission' parameters. Returns negative on error. */
int v4l2_video_std_construct(struct v4l2_standard *vs,
@ -189,6 +261,8 @@ char *v4l2_type_names[] = {
[V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out",
[V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
[V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
[V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
[V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out",
};
static char *v4l2_memory_names[] = {
@ -1451,6 +1525,7 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
/* ----------------------------------------------------------------- */
EXPORT_SYMBOL(v4l2_norm_to_name);
EXPORT_SYMBOL(v4l2_video_std_construct);
EXPORT_SYMBOL(v4l2_prio_init);

View file

@ -342,7 +342,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
"bytesused=%d, flags=0x%08d, "
"field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n",
"field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
(p->timestamp.tv_sec/3600),
(int)(p->timestamp.tv_sec/60)%60,
(int)(p->timestamp.tv_sec%60),
@ -352,7 +352,7 @@ static void dbgbuf(unsigned int cmd, struct video_device *vfd,
p->bytesused,p->flags,
p->field,p->sequence,
prt_names(p->memory,v4l2_memory_names),
p->m.userptr);
p->m.userptr, p->length);
dbgarg2 ("timecode= %02d:%02d:%02d type=%d, "
"flags=0x%08d, frames=%d, userbits=0x%08x\n",
tc->hours,tc->minutes,tc->seconds,
@ -369,9 +369,13 @@ static inline void dbgrect(struct video_device *vfd, char *s,
static inline void v4l_print_pix_fmt (struct video_device *vfd,
struct v4l2_pix_format *fmt)
{
dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, "
dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, "
"bytesperline=%d sizeimage=%d, colorspace=%d\n",
fmt->width,fmt->height,fmt->pixelformat,
fmt->width,fmt->height,
(fmt->pixelformat & 0xff),
(fmt->pixelformat >> 8) & 0xff,
(fmt->pixelformat >> 16) & 0xff,
(fmt->pixelformat >> 24) & 0xff,
prt_names(fmt->field,v4l2_field_names_FIXME),
fmt->bytesperline,fmt->sizeimage,fmt->colorspace);
};
@ -428,6 +432,10 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
v4l_print_ioctl(vfd->name, cmd);
}
if (_IOC_TYPE(cmd)=='v')
return v4l_compat_translate_ioctl(inode,file,cmd,arg,
__video_do_ioctl);
switch(cmd) {
/* --- capabilities ------------------------------------------ */
case VIDIOC_QUERYCAP:
@ -526,12 +534,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
}
if (!ret)
dbgarg (cmd, "index=%d, type=%d, flags=%d, "
"description=%s,"
" pixelformat=0x%8x\n",
"pixelformat=%c%c%c%c, description='%s'\n",
f->index, f->type, f->flags,
f->description,
f->pixelformat);
(f->pixelformat & 0xff),
(f->pixelformat >> 8) & 0xff,
(f->pixelformat >> 16) & 0xff,
(f->pixelformat >> 24) & 0xff,
f->description);
break;
}
case VIDIOC_G_FMT:
@ -829,20 +838,85 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_ENUMSTD:
{
struct v4l2_standard *p = arg;
unsigned int index = p->index;
v4l2_std_id id = vfd->tvnorms,curr_id=0;
unsigned int index = p->index,i;
if (!vfd->tvnormsize) {
printk (KERN_WARNING "%s: no TV norms defined!\n",
vfd->name);
break;
}
if (index<0 || index >= vfd->tvnormsize) {
if (index<0) {
ret=-EINVAL;
break;
}
v4l2_video_std_construct(p, vfd->tvnorms[p->index].id,
vfd->tvnorms[p->index].name);
/* Return norm array on a canonical way */
for (i=0;i<= index && id; i++) {
if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) {
curr_id = V4L2_STD_PAL;
} else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) {
curr_id = V4L2_STD_PAL_BG;
} else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) {
curr_id = V4L2_STD_PAL_DK;
} else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) {
curr_id = V4L2_STD_PAL_B;
} else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) {
curr_id = V4L2_STD_PAL_B1;
} else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) {
curr_id = V4L2_STD_PAL_G;
} else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) {
curr_id = V4L2_STD_PAL_H;
} else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) {
curr_id = V4L2_STD_PAL_I;
} else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) {
curr_id = V4L2_STD_PAL_D;
} else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) {
curr_id = V4L2_STD_PAL_D1;
} else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) {
curr_id = V4L2_STD_PAL_K;
} else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) {
curr_id = V4L2_STD_PAL_M;
} else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) {
curr_id = V4L2_STD_PAL_N;
} else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) {
curr_id = V4L2_STD_PAL_Nc;
} else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) {
curr_id = V4L2_STD_PAL_60;
} else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
curr_id = V4L2_STD_NTSC;
} else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) {
curr_id = V4L2_STD_NTSC_M;
} else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) {
curr_id = V4L2_STD_NTSC_M_JP;
} else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) {
curr_id = V4L2_STD_NTSC_443;
} else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) {
curr_id = V4L2_STD_NTSC_M_KR;
} else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
curr_id = V4L2_STD_SECAM;
} else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) {
curr_id = V4L2_STD_SECAM_DK;
} else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) {
curr_id = V4L2_STD_SECAM_B;
} else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) {
curr_id = V4L2_STD_SECAM_D;
} else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) {
curr_id = V4L2_STD_SECAM_G;
} else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) {
curr_id = V4L2_STD_SECAM_H;
} else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) {
curr_id = V4L2_STD_SECAM_K;
} else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) {
curr_id = V4L2_STD_SECAM_K1;
} else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) {
curr_id = V4L2_STD_SECAM_L;
} else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) {
curr_id = V4L2_STD_SECAM_LC;
} else {
break;
}
id &= ~curr_id;
}
if (i<=index)
return -EINVAL;
v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id));
p->index = index;
dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
@ -868,39 +942,23 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
}
case VIDIOC_S_STD:
{
v4l2_std_id *id = arg;
unsigned int i;
if (!vfd->tvnormsize) {
printk (KERN_WARNING "%s: no TV norms defined!\n",
vfd->name);
break;
}
v4l2_std_id *id = arg,norm;
dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
/* First search for exact match */
for (i = 0; i < vfd->tvnormsize; i++)
if (*id == vfd->tvnorms[i].id)
norm = (*id) & vfd->tvnorms;
if ( vfd->tvnorms && !norm) /* Check if std is supported */
break;
/* Then for a generic video std that contains desired std */
if (i == vfd->tvnormsize)
for (i = 0; i < vfd->tvnormsize; i++)
if (*id & vfd->tvnorms[i].id)
break;
if (i == vfd->tvnormsize) {
break;
}
/* Calls the specific handler */
if (vfd->vidioc_s_std)
ret=vfd->vidioc_s_std(file, fh, i);
ret=vfd->vidioc_s_std(file, fh, &norm);
else
ret=-EINVAL;
/* Updates standard information */
if (!ret)
vfd->current_norm=*id;
if (ret>=0)
vfd->current_norm=norm;
break;
}
@ -1088,9 +1146,13 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_G_AUDIO:
{
struct v4l2_audio *p=arg;
__u32 index=p->index;
if (!vfd->vidioc_g_audio)
break;
memset(p,0,sizeof(*p));
p->index=index;
dbgarg(cmd, "Get for index=%d\n", p->index);
ret=vfd->vidioc_g_audio(file, fh, p);
if (!ret)
@ -1288,25 +1350,12 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret=vfd->vidioc_g_parm(file, fh, p);
} else {
struct v4l2_standard s;
int i;
if (!vfd->tvnormsize) {
printk (KERN_WARNING "%s: no TV norms defined!\n",
vfd->name);
break;
}
if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
for (i = 0; i < vfd->tvnormsize; i++)
if (vfd->tvnorms[i].id == vfd->current_norm)
break;
if (i >= vfd->tvnormsize)
return -EINVAL;
v4l2_video_std_construct(&s, vfd->current_norm,
vfd->tvnorms[i].name);
v4l2_norm_to_name(vfd->current_norm));
memset(p,0,sizeof(*p));
@ -1329,8 +1378,14 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
case VIDIOC_G_TUNER:
{
struct v4l2_tuner *p=arg;
__u32 index=p->index;
if (!vfd->vidioc_g_tuner)
break;
memset(p,0,sizeof(*p));
p->index=index;
ret=vfd->vidioc_g_tuner(file, fh, p);
if (!ret)
dbgarg (cmd, "index=%d, name=%s, type=%d, "
@ -1363,6 +1418,9 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
struct v4l2_frequency *p=arg;
if (!vfd->vidioc_g_frequency)
break;
memset(p,0,sizeof(*p));
ret=vfd->vidioc_g_frequency(file, fh, p);
if (!ret)
dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
@ -1396,12 +1454,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
ret=vfd->vidioc_log_status(file, fh);
break;
}
/* --- Others --------------------------------------------- */
default:
ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl);
}
} /* switch */
if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
if (ret<0) {

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