Commit bb7320d1 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 6aa8b732 1de1bf06
......@@ -22,10 +22,10 @@ o Frontends drivers:
- ves1x93 : Alps BSRV2 (ves1893 demodulator) and dbox2 (ves1993)
- cx24110 : Conexant HM1221/HM1811 (cx24110 or cx24106 demod, cx24108 PLL)
- grundig_29504-491 : Grundig 29504-491 (Philips TDA8083 demodulator), tsa5522 PLL
- mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLL
- mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLLi, Technisat Sky2Pc with bios Rev. 2.3
- stv0299 : Alps BSRU6 (tsa5059 PLL), LG TDQB-S00x (tsa5059 PLL),
LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL),
Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB
Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB, Technisat Sky2Pc with bios Rev. 2.6
DVB-C:
- ves1820 : various (ves1820 demodulator, sp5659c or spXXXX PLL)
- at76c651 : Atmel AT76c651(B) with DAT7021 PLL
......
......@@ -43,7 +43,7 @@
42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025,1822:0019]
43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1,12ab:2300]
44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50,18ac:db54]
45 -> KWorld HardwareMpegTV XPert [17de:0840]
45 -> KWorld HardwareMpegTV XPert [17de:0840,1421:0305]
46 -> DViCO FusionHDTV DVB-T Hybrid [18ac:db40,18ac:db44]
47 -> pcHDTV HD5500 HDTV [7063:5500]
48 -> Kworld MCE 200 Deluxe [17de:0841]
......
......@@ -76,7 +76,7 @@
75 -> AVerMedia AVerTVHD MCE A180 [1461:1044]
76 -> SKNet MonsterTV Mobile [1131:4ee9]
77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e]
78 -> ASUSTeK P7131 Dual [1043:4862]
78 -> ASUSTeK P7131 Dual [1043:4862,1043:4876]
79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)
80 -> ASUS Digimatrix TV [1043:0210]
81 -> Philips Tiger reference design [1131:2018]
......@@ -99,3 +99,8 @@
98 -> Proteus Pro 2309 [0919:2003]
99 -> AVerMedia TV Hybrid A16AR [1461:2c00]
100 -> Asus Europa2 OEM [1043:4860]
101 -> Pinnacle PCTV 310i [11bd:002f]
102 -> Avermedia AVerTV Studio 507 [1461:9715]
103 -> Compro Videomate DVB-T200A
104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid [0070:6701]
105 -> Terratec Cinergy HT PCMCIA [153b:1172]
"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
Driver for Trust Computer Products Framegrabber, version 0.6.1
------ --- ----- -------- -------- ------------ ------- - - -
- ZORAN ------------------------------------------------------
Author: Pauline Middelink <middelin@polyware.nl>
Date: 18 September 1999
Version: 0.6.1
- Description ------------------------------------------------
Video4Linux compatible driver for an unknown brand framegrabber
(Sold in the Netherlands by TRUST Computer Products) and various
other zoran zr36120 based framegrabbers.
The card contains a ZR36120 Multimedia PCI Interface and a Philips
SAA7110 Onechip Frontend videodecoder. There is also an DSP of
which I have forgotten the number, since i will never get that thing
to work without specs from the vendor itself.
The SAA711x are capable of processing 6 different video inputs,
CVBS1..6 and Y1+C1, Y2+C2, Y3+C3. All in 50/60Hz, NTSC, PAL or
SECAM and delivering a YUV datastream. On my card the input
'CVBS-0' corresponds to channel CVBS2 and 'S-Video' to Y2+C2.
I have some reports of other cards working with the mentioned
chip sets. For a list of other working cards please have a look
at the cards named in the tvcards struct in the beginning of
zr36120.c
After some testing, I discovered that the carddesigner messed up
on the I2C interface. The Zoran chip includes 2 lines SDA and SCL
which (s)he connected reversely. So we have to clock on the SDA
and r/w data on the SCL pin. Life is fun... Each cardtype now has
a bit which signifies if you have a card with the same deficiency.
Oh, for the completeness of this story I must mention that my
card delivers the VSYNC pulse of the SAA chip to GIRQ1, not
GIRQ0 as some other cards have. This is also incorporated in
the driver be clearing/setting the 'useirq1' bit in the tvcard
description.
Another problems of continuous capturing data with a Zoran chip
is something nasty inside the chip. It effectively halves the
fps we ought to get... Here is the scenario: capturing frames
to memory is done in the so-called snapshot mode. In this mode
the Zoran stops after capturing a frame worth of data and wait
till the application set GRAB bit to indicate readiness for the
next frame. After detecting a set bit, the chip neatly waits
till the start of a frame, captures it and it goes back to off.
Smart ppl will notice the problem here. Its the waiting on the
_next_ frame each time we set the GRAB bit... Oh well, 12,5 fps
is still plenty fast for me.
-- update 28/7/1999 --
Don't believe a word I just said... Proof is the output
of `streamer -t 300 -r 25 -f avi15 -o /dev/null`
++--+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+- 25/25
+-s+-+-+-+-+-+-+-+-+-+-+-+-+-s+-+-+-+-+-+-+-+-+-+-+-
syncer: done
writer: done
(note the /dev/null is prudent here, my system is not able to
grab /and/ write 25 fps to a file... gifts welcome :) )
The technical reasoning follows: The zoran completed the last
frame, the VSYNC goes low, and GRAB is cleared. The interrupt
routine starts to work since its VSYNC driven, and again
activates the GRAB bit. A few ms later the VSYNC (re-)rises and
the zoran starts to work on a new and freshly broadcasted frame....
For pointers I used the specs of both chips. Below are the URLs:
http://www.zoran.com/ftp/download/devices/pci/ZR36120/36120data.pdf
http://www-us.semiconductor.philips.com/acrobat/datasheets/SAA_7110_A_1.pdf
Some alternatives for the Philips SAA 7110 datasheet are:
http://www.datasheetcatalog.com/datasheets_pdf/S/A/A/7/SAA7110.shtml
http://www.datasheetarchive.com/search.php?search=SAA7110&sType=part
The documentation has very little on absolute numbers or timings
needed for the various modes/resolutions, but there are other
programs you can borrow those from.
------ Install --------------------------------------------
Read the file called TODO. Note its long list of limitations.
Build a kernel with VIDEO4LINUX enabled. Activate the
BT848 driver; we need this because we have need for the
other modules (i2c and videodev) it enables.
To install this software, extract it into a suitable directory.
Examine the makefile and change anything you don't like. Type "make".
After making the modules check if you have the much needed
/dev/video devices. If not, execute the following 4 lines:
mknod /dev/video c 81 0
mknod /dev/video1 c 81 1
mknod /dev/video2 c 81 2
mknod /dev/video3 c 81 3
mknod /dev/video4 c 81 4
After making/checking the devices do:
modprobe i2c
modprobe videodev
modprobe saa7110 (optional)
modprobe saa7111 (optional)
modprobe tuner (optional)
insmod zoran cardtype=<n>
<n> is the cardtype of the card you have. The cardnumber can
be found in the source of zr36120. Look for tvcards. If your
card is not there, please try if any other card gives some
response, and mail me if you got a working tvcard addition.
PS. <TVCard editors behold!)
Don't forget to set video_input to the number of inputs
you defined in the video_mux part of the tvcard definition.
It's a common error to add a channel but not incrementing
video_input and getting angry with me/v4l/linux/linus :(
You are now ready to test the framegrabber with your favorite
video4linux compatible tool
------ Application ----------------------------------------
This device works with all Video4Linux compatible applications,
given the limitations in the TODO file.
------ API ------------------------------------------------
This uses the V4L interface as of kernel release 2.1.116, and in
fact has not been tested on any lower version. There are a couple
of minor differences due to the fact that the amount of data returned
with each frame varies, and no doubt there are discrepancies due to my
misunderstanding of the API. I intend to convert this driver to the
new V4L2 API when it has stabilized more.
------ Current state --------------------------------------
The driver is capable of overlaying a video image in screen, and
even capable of grabbing frames. It uses the BIGPHYSAREA patch
to allocate lots of large memory blocks when tis patch is
found in the kernel, but it doesn't need it.
The consequence is that, when loading the driver as a module,
the module may tell you it's out of memory, but 'free' says
otherwise. The reason is simple; the modules wants its memory
contiguous, not fragmented, and after a long uptime there
probably isn't a fragment of memory large enough...
The driver uses a double buffering scheme, which should really
be an n-way buffer, depending on the size of allocated framebuffer
and the requested grab-size/format.
This current version also fixes a dead-lock situation during irq
time, which really, really froze my system... :)
Good luck.
Pauline
......@@ -67,6 +67,7 @@ source "drivers/media/common/Kconfig"
config VIDEO_TUNER
tristate
depends on I2C
config VIDEO_BUF
tristate
......@@ -82,6 +83,7 @@ config VIDEO_IR
config VIDEO_TVEEPROM
tristate
depends on I2C
config USB_DABUSB
tristate "DABUSB driver"
......
......@@ -1552,3 +1552,58 @@ IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = {
};
EXPORT_SYMBOL_GPL(ir_codes_norwood);
/* From reading the following remotes:
* Zenith Universal 7 / TV Mode 807 / VCR Mode 837
* Hauppauge (from NOVA-CI-s box product)
* This is a "middle of the road" approach, differences are noted
*/
IR_KEYTAB_TYPE ir_codes_budget_ci_old[IR_KEYTAB_SIZE] = {
[ 0x00 ] = KEY_0,
[ 0x01 ] = KEY_1,
[ 0x02 ] = KEY_2,
[ 0x03 ] = KEY_3,
[ 0x04 ] = KEY_4,
[ 0x05 ] = KEY_5,
[ 0x06 ] = KEY_6,
[ 0x07 ] = KEY_7,
[ 0x08 ] = KEY_8,
[ 0x09 ] = KEY_9,
[ 0x0a ] = KEY_ENTER,
[ 0x0b ] = KEY_RED,
[ 0x0c ] = KEY_POWER, /* RADIO on Hauppauge */
[ 0x0d ] = KEY_MUTE,
[ 0x0f ] = KEY_A, /* TV on Hauppauge */
[ 0x10 ] = KEY_VOLUMEUP,
[ 0x11 ] = KEY_VOLUMEDOWN,
[ 0x14 ] = KEY_B,
[ 0x1c ] = KEY_UP,
[ 0x1d ] = KEY_DOWN,
[ 0x1e ] = KEY_OPTION, /* RESERVED on Hauppauge */
[ 0x1f ] = KEY_BREAK,
[ 0x20 ] = KEY_CHANNELUP,
[ 0x21 ] = KEY_CHANNELDOWN,
[ 0x22 ] = KEY_PREVIOUS, /* Prev. Ch on Zenith, SOURCE on Hauppauge */
[ 0x24 ] = KEY_RESTART,
[ 0x25 ] = KEY_OK,
[ 0x26 ] = KEY_CYCLEWINDOWS, /* MINIMIZE on Hauppauge */
[ 0x28 ] = KEY_ENTER, /* VCR mode on Zenith */
[ 0x29 ] = KEY_PAUSE,
[ 0x2b ] = KEY_RIGHT,
[ 0x2c ] = KEY_LEFT,
[ 0x2e ] = KEY_MENU, /* FULL SCREEN on Hauppauge */
[ 0x30 ] = KEY_SLOW,
[ 0x31 ] = KEY_PREVIOUS, /* VCR mode on Zenith */
[ 0x32 ] = KEY_REWIND,
[ 0x34 ] = KEY_FASTFORWARD,
[ 0x35 ] = KEY_PLAY,
[ 0x36 ] = KEY_STOP,
[ 0x37 ] = KEY_RECORD,
[ 0x38 ] = KEY_TUNER, /* TV/VCR on Zenith */
[ 0x3a ] = KEY_C,
[ 0x3c ] = KEY_EXIT,
[ 0x3d ] = KEY_POWER2,
[ 0x3e ] = KEY_TUNER,
};
EXPORT_SYMBOL_GPL(ir_codes_budget_ci_old);
......@@ -189,13 +189,21 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
saa7146_write(dev, I2C_TRANSFER, *dword);
dev->i2c_op = 1;
SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
saa7146_write(dev, MC2, (MASK_00 | MASK_16));
wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0);
if (signal_pending (current)) {
timeout = HZ/100 + 1; /* 10ms */
timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout);
if (timeout == -ERESTARTSYS || dev->i2c_op) {
SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
if (timeout == -ERESTARTSYS)
/* a signal arrived */
return -ERESTARTSYS;
printk(KERN_WARNING "saa7146_i2c_writeout: timed out waiting for end of xfer\n");
return -EIO;
}
status = saa7146_read(dev, I2C_STATUS);
} else {
......
......@@ -9,6 +9,7 @@ config DVB_B2C2_FLEXCOP
select DVB_STV0297 if !DVB_FE_CUSTOMISE
select DVB_BCM3510 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
help
Support for the digital TV receiver chip made by B2C2 Inc. included in
Technisats PCI cards and USB boxes.
......
......@@ -14,7 +14,7 @@
#include "stv0297.h"
#include "mt312.h"
#include "lgdt330x.h"
#include "lg_h06xf.h"
#include "lgh06xf.h"
#include "dvb-pll.h"
/* lnb control */
......@@ -303,12 +303,6 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
return request_firmware(fw, name, fc->dev);
}
static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
{
struct flexcop_device *fc = fe->dvb->priv;
return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
}
static struct lgdt330x_config air2pc_atsc_hd5000_config = {
.demod_address = 0x59,
.demod_chip = LGDT3303,
......@@ -533,7 +527,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
/* try the air atsc 3nd generation (lgdt3303) */
if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
fc->dev_type = FC_AIR_ATSC3;
fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
dvb_attach(lgh06xf_attach, fc->fe, &fc->i2c_adap);
info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
} else
/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
......
config DVB_BT8XX
tristate "BT8xx based PCI cards"
depends on DVB_CORE && PCI && I2C && VIDEO_BT848
select DVB_PLL
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_SP887X if !DVB_FE_CUSTOMISE
select DVB_NXT6000 if !DVB_FE_CUSTOMISE
select DVB_CX24110 if !DVB_FE_CUSTOMISE
select DVB_OR51211 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
select FW_LOADER
help
......
......@@ -34,7 +34,6 @@
#include "dvb_frontend.h"
#include "dvb-bt8xx.h"
#include "bt878.h"
#include "dvb-pll.h"
static int debug;
......@@ -568,12 +567,6 @@ static struct mt352_config digitv_alps_tded4_config = {
.demod_init = digitv_alps_tded4_demod_init,
};
static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
return lg_h06xf_pll_set(fe, card->i2c_adapter, params);
}
static struct lgdt330x_config tdvs_tua6034_config = {
.demod_address = 0x0e,
.demod_chip = LGDT3303,
......@@ -616,7 +609,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
lgdt330x_reset(card);
card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
if (card->fe != NULL) {
card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter);
dprintk ("dvb_bt8xx: lgdt330x detected\n");
}
break;
......
......@@ -37,7 +37,7 @@
#include "cx24110.h"
#include "or51211.h"
#include "lgdt330x.h"
#include "lg_h06xf.h"
#include "lgh06xf.h"
#include "zl10353.h"
struct dvb_bt8xx_card {
......
......@@ -746,6 +746,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
input_report_key(cinergyt2->rc_input_dev,
cinergyt2->rc_input_event, 0);
input_sync(cinergyt2->rc_input_dev);
cinergyt2->rc_input_event = KEY_MAX;
}
cinergyt2->rc_last_code = ~0;
......@@ -783,6 +784,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
input_report_key(cinergyt2->rc_input_dev,
cinergyt2->rc_input_event, 1);
input_sync(cinergyt2->rc_input_dev);
cinergyt2->rc_last_code = rc_events[n].value;
}
}
......@@ -798,8 +800,9 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
{
struct input_dev *input_dev;
int i;
int err;
cinergyt2->rc_input_dev = input_dev = input_allocate_device();
input_dev = input_allocate_device();
if (!input_dev)
return -ENOMEM;
......@@ -817,7 +820,13 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
input_dev->keycodesize = 0;
input_dev->keycodemax = 0;
input_register_device(cinergyt2->rc_input_dev);
err = input_register_device(input_dev);
if (err) {
input_free_device(input_dev);
return err;
}
cinergyt2->rc_input_dev = input_dev;
schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
return 0;
......
......@@ -69,6 +69,8 @@ config DVB_USB_DIBUSB_MC
config DVB_USB_DIB0700
tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
depends on DVB_USB
select DVB_DIB7000P
select DVB_DIB7000M
select DVB_DIB3000MC
select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
help
......@@ -96,6 +98,7 @@ config DVB_USB_CXUSB
depends on DVB_USB
select DVB_CX22702 if !DVB_FE_CUSTOMISE
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
select DVB_MT352 if !DVB_FE_CUSTOMISE
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
help
......@@ -157,6 +160,17 @@ config DVB_USB_NOVA_T_USB2
help
Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
config DVB_USB_TTUSB2
tristate "Pinnacle 400e DVB-S USB2.0 support"
depends on DVB_USB
select DVB_TDA10086 if !DVB_FE_CUSTOMISE
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
select DVB_TDA826X if !DVB_FE_CUSTOMISE
help
Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The
firmware protocol used by this module is similar to the one used by the
old ttusb-driver - that's why the module is called dvb-usb-ttusb2.ko.
config DVB_USB_DTT200U
tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
depends on DVB_USB
......
......@@ -36,6 +36,9 @@ obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
dvb-usb-cxusb-objs = cxusb.o
obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o
dvb-usb-ttusb2-objs = ttusb2.o
obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o
dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o
obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o
......
......@@ -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,14 +27,14 @@
#include "cx22702.h"
#include "lgdt330x.h"
#include "lg_h06xf.h"
#include "lgh06xf.h"
#include "mt352.h"
#include "mt352_priv.h"
#include "zl10353.h"
/* debug */
int dvb_usb_cxusb_debug;
module_param_named(debug,dvb_usb_cxusb_debug, int, 0644);
module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
static int cxusb_ctrl_msg(struct dvb_usb_device *d,
......@@ -42,14 +42,14 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
{
int wo = (rbuf == NULL || rlen == 0); /* write-only */
u8 sndbuf[1+wlen];
memset(sndbuf,0,1+wlen);
memset(sndbuf, 0, 1+wlen);
sndbuf[0] = cmd;
memcpy(&sndbuf[1],wbuf,wlen);
memcpy(&sndbuf[1], wbuf, wlen);
if (wo)
dvb_usb_generic_write(d,sndbuf,1+wlen);
dvb_usb_generic_write(d, sndbuf, 1+wlen);
else
dvb_usb_generic_rw(d,sndbuf,1+wlen,rbuf,rlen,0);
dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
return 0;
}
......@@ -58,14 +58,14 @@ static int cxusb_ctrl_msg(struct dvb_usb_device *d,
static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
{
struct cxusb_state *st = d->priv;
u8 o[2],i;
u8 o[2], i;
if (st->gpio_write_state[GPIO_TUNER] == onoff)
return;
o[0] = GPIO_TUNER;
o[1] = onoff;
cxusb_ctrl_msg(d,CMD_GPIO_WRITE,o,2,&i,1);
cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
if (i != 0x01)
deb_info("gpio_write failed.\n");
......@@ -74,7 +74,8 @@ static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
}
/* I2C */
static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i;
......@@ -90,10 +91,10 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
if (d->udev->descriptor.idVendor == USB_VID_MEDION)
switch (msg[i].addr) {
case 0x63:
cxusb_gpio_tuner(d,0);
cxusb_gpio_tuner(d, 0);
break;
default:
cxusb_gpio_tuner(d,1);
cxusb_gpio_tuner(d, 1);
break;
}
......@@ -103,7 +104,7 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
obuf[0] = msg[i].len;
obuf[1] = msg[i+1].len;
obuf[2] = msg[i].addr;
memcpy(&obuf[3],msg[i].buf,msg[i].len);
memcpy(&obuf[3], msg[i].buf, msg[i].len);
if (cxusb_ctrl_msg(d, CMD_I2C_READ,
obuf, 3+msg[i].len,
......@@ -113,16 +114,17 @@ static int cxusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
if (ibuf[0] != 0x08)
deb_i2c("i2c read may have failed\n");
memcpy(msg[i+1].buf,&ibuf[1],msg[i+1].len);
memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len);
i++;
} else { /* write */
u8 obuf[2+msg[i].len], ibuf;
obuf[0] = msg[i].addr;
obuf[1] = msg[i].len;
memcpy(&obuf[2],msg[i].buf,msg[i].len);
memcpy(&obuf[2], msg[i].buf, msg[i].len);
if (cxusb_ctrl_msg(d,CMD_I2C_WRITE, obuf, 2+msg[i].len, &ibuf,1) < 0)
if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf,
2+msg[i].len, &ibuf,1) < 0)
break;
if (ibuf != 0x08)
deb_i2c("i2c write may have failed\n");
......@@ -324,16 +326,8 @@ static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
return 0;
}
static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe,
struct dvb_frontend_parameters *fep)
{
struct dvb_usb_adapter *adap = fe->dvb->priv;
return lg_h06xf_pll_set(fe, &adap->dev->i2c_adap, fep);
}
static struct cx22702_config cxusb_cx22702_config = {
.demod_address = 0x63,
.output_mode = CX22702_PARALLEL_OUTPUT,
};
......@@ -374,31 +368,27 @@ static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
{
adap->pll_addr = 0x61;
adap->pll_desc = &dvb_pll_thomson_dtt7579;
adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
dvb_attach(dvb_pll_attach, adap->fe, 0x61,
NULL, &dvb_pll_thomson_dtt7579);
return 0;
}
static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
{
adap->pll_addr = 0x61;
adap->pll_desc = &dvb_pll_lg_z201;
adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
dvb_attach(dvb_pll_attach, adap->fe, 0x61, NULL, &dvb_pll_lg_z201);
return 0;
}
static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
{
adap->pll_addr = 0x60;
adap->pll_desc = &dvb_pll_thomson_dtt7579;
adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
dvb_attach(dvb_pll_attach, adap->fe, 0x60,
NULL, &dvb_pll_thomson_dtt7579);
return 0;
}
static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_adapter *adap)
static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
{
adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
dvb_attach(lgh06xf_attach, adap->fe, &adap->dev->i2c_adap);
return 0;
}
......@@ -410,7 +400,8 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &adap->dev->i2c_adap)) != NULL)
if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
&adap->dev->i2c_adap)) != NULL)
return 0;
return -EIO;
......@@ -423,7 +414,8 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &adap->dev->i2c_adap)) != NULL)
if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config,
&adap->dev->i2c_adap)) != NULL)
return 0;
return -EIO;
......@@ -437,7 +429,8 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &adap->dev->i2c_adap)) != NULL)
if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
&adap->dev->i2c_adap)) != NULL)
return 0;
return -EIO;
......@@ -450,8 +443,11 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &adap->dev->i2c_adap)) != NULL) ||
((adap->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &adap->dev->i2c_adap)) != NULL))
if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
&adap->dev->i2c_adap)) != NULL) ||
((adap->fe = dvb_attach(zl10353_attach,
&cxusb_zl10353_dee1601_config,
&adap->dev->i2c_adap)) != NULL))
return 0;
return -EIO;
......@@ -463,7 +459,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
*/
#define BLUEBIRD_01_ID_OFFSET 6638
static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw)
static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
const struct firmware *fw)
{
if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
return -EINVAL;
......@@ -471,10 +468,12 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const
if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;
fw->data[BLUEBIRD_01_ID_OFFSET + 2] =
udev->descriptor.idProduct + 1;
fw->data[BLUEBIRD_01_ID_OFFSET + 3] =
udev->descriptor.idProduct >> 8;
return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2);
return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2);
}
return -EINVAL;
......@@ -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");
......
......@@ -24,18 +24,23 @@ extern int dvb_usb_dib0700_debug;
#define REQUEST_I2C_WRITE 0x3
#define REQUEST_POLL_RC 0x4
#define REQUEST_JUMPRAM 0x8
#define REQUEST_SET_CLOCK 0xB
#define REQUEST_SET_GPIO 0xC
#define REQUEST_ENABLE_VIDEO 0xF
// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
// 2 Byte: MPEG2 mode: 4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines) 4LSB( " " )
#define REQUEST_GET_VERSION 0x15
struct dib0700_state {
u8 channel_state;
u16 mt2060_if1[2];
u8 is_dib7000pc;
};
extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
extern struct i2c_algorithm dib0700_i2c_algo;
......
......@@ -135,14 +135,46 @@ struct i2c_algorithm dib0700_i2c_algo = {
int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
struct dvb_usb_device_description **desc, int *cold)
{
u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C
*cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3;
u8 b[16];
s16 ret = usb_control_msg(udev, usb_rcvctrlpipe(udev,0),
REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT);
deb_info("FW GET_VERSION length: %d\n",ret);
*cold = ret <= 0;
deb_info("cold: %d\n", *cold);
return 0;
}
static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv,
u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
{
u8 b[10];
b[0] = REQUEST_SET_CLOCK;
b[1] = (en_pll << 7) | (pll_src << 6) | (pll_range << 5) | (clock_gpio3 << 4);
b[2] = (pll_prediv >> 8) & 0xff; // MSB
b[3] = pll_prediv & 0xff; // LSB
b[4] = (pll_loopdiv >> 8) & 0xff; // MSB
b[5] = pll_loopdiv & 0xff; // LSB
b[6] = (free_div >> 8) & 0xff; // MSB
b[7] = free_div & 0xff; // LSB
b[8] = (dsuScaler >> 8) & 0xff; // MSB
b[9] = dsuScaler & 0xff; // LSB
return dib0700_ctrl_wr(d, b, 10);
}
int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
{
switch (clk_MHz) {
case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break;
default: return -EINVAL;
}
return 0;
}
static int dib0700_jumpram(struct usb_device *udev, u32 address)
{
int ret, actlen;
......@@ -197,7 +229,7 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
/* start the firmware */
if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) {
info("firmware started successfully.");
msleep(100);
msleep(500);
}
} else
ret = -EIO;
......
......@@ -9,6 +9,8 @@
#include "dib0700.h"
#include "dib3000mc.h"
#include "dib7000m.h"
#include "dib7000p.h"
#include "mt2060.h"
static int force_lna_activation;
......@@ -95,37 +97,189 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
}
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
/*
static struct mt2060_config stk7000p_mt2060_config = {
0x60
static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
BAND_UHF | BAND_VHF, // band_caps
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
712, // inv_gain
41, // time_stabiliz
0, // alpha_level
118, // thlock
0, // wbd_inv
4095, // wbd_ref
0, // wbd_sel
0, // wbd_alpha
42598, // agc1_max
17694, // agc1_min
45875, // agc2_max
2621, // agc2_min
0, // agc1_pt1
76, // agc1_pt2
139, // agc1_pt3
52, // agc1_slope1
59, // agc1_slope2
107, // agc2_pt1
172, // agc2_pt2
57, // agc2_slope1
70, // agc2_slope2
21, // alpha_mant
25, // alpha_exp
28, // beta_mant
48, // beta_exp
1, // perform_agc_softsplit
{ 0, // split_min
107, // split_max
51800, // global_split_min
24700 // global_split_max
},
};
static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = {
BAND_UHF | BAND_VHF,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup
712, // inv_gain
41, // time_stabiliz
0, // alpha_level
118, // thlock
0, // wbd_inv
4095, // wbd_ref
0, // wbd_sel
0, // wbd_alpha
42598, // agc1_max
16384, // agc1_min
42598, // agc2_max
0, // agc2_min
0, // agc1_pt1
137, // agc1_pt2
255, // agc1_pt3
0, // agc1_slope1
255, // agc1_slope2
0, // agc2_pt1
0, // agc2_pt2
0, // agc2_slope1
41, // agc2_slope2
15, // alpha_mant
25, // alpha_exp
28, // beta_mant
48, // beta_exp
0, // perform_agc_softsplit
};
static struct dibx000_bandwidth_config stk7700p_pll_config = {
60000, 30000, // internal, sampling
1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass
0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo
(3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k
60258167, // ifreq
20452225, // timf
};
static struct dib7000m_config stk7700p_dib7000m_config = {
.dvbt_mode = 1,
.output_mpeg2_in_188_bytes = 1,
.quartz_direct = 1,
.agc_config_count = 1,
.agc = &stk7700p_7000m_mt2060_agc_config,
.bw = &stk7700p_pll_config,
.gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
.gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
};
static struct dib7000p_config stk7700p_dib7000p_config = {
.output_mpeg2_in_188_bytes = 1,
.agc = &stk7700p_7000p_mt2060_agc_config,
.bw = &stk7700p_pll_config,
.gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
.gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
.gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
};
*/
static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
/* unless there is no real power management in DVB - we leave the device on GPIO6 */
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10);
dib0700_set_gpio(adap->dev, 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, GPIO10, 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);
// adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18);
return 0;
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 },
},
}
......
......@@ -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,
......
......@@ -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
......@@ -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);
......
/* 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");
/* 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
......@@ -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)
......
......@@ -172,6 +172,22 @@ config DVB_DIB3000MC
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
to support this frontend.
config DVB_DIB7000M
tristate "DiBcom 7000MA/MB/PA/PB/MC"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
to support this frontend.
config DVB_DIB7000P
tristate "DiBcom 7000PC"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
help
A DVB-T tuner module. Designed for mobile usage. Say Y when you want
to support this frontend.
comment "DVB-C (cable) frontends"
depends on DVB_CORE
......@@ -281,6 +297,14 @@ config DVB_TUNER_MT2060
help
A driver for the silicon IF tuner MT2060 from Microtune.
config DVB_TUNER_LGH06XF
tristate "LG TDVS-H06xF ATSC tuner"
depends on DVB_CORE && I2C
select DVB_PLL
default m if DVB_FE_CUSTOMISE
help
A driver for the LG TDVS-H06xF ATSC tuner family.
comment "Miscellaneous devices"
depends on DVB_CORE
......
......@@ -13,6 +13,8 @@ obj-$(CONFIG_DVB_TDA8083) += tda8083.o
obj-$(CONFIG_DVB_L64781) += l64781.o
obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o
obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o
obj-$(CONFIG_DVB_MT312) += mt312.o
obj-$(CONFIG_DVB_VES1820) += ves1820.o
obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
......@@ -37,3 +39,4 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
obj-$(CONFIG_DVB_TDA826X) += tda826x.o
obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
obj-$(CONFIG_DVB_TUA6100) += tua6100.o
obj-$(CONFIG_DVB_TUNER_LGH06XF) += lgh06xf.o
......@@ -511,16 +511,11 @@ static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000
/* a channel for autosearch */
reg = 0;
if (chan->nfft == -1 && chan->guard == -1) reg = 7;
if (chan->nfft == -1 && chan->guard != -1) reg = 2;
if (chan->nfft != -1 && chan->guard == -1) reg = 3;
fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2;
fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2;
fchan.vit_hrch = 0; fchan.vit_select_hp = 1;
dib3000mc_set_channel_cfg(state, &fchan, reg);
dib3000mc_set_channel_cfg(state, &fchan, 7);
reg = dib3000mc_read_word(state, 0);
dib3000mc_write_word(state, 0, reg | (1 << 8));
......
This diff is collapsed.
#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
This diff is collapsed.
#ifndef DIB7000P_H
#define DIB7000P_H
#include "dibx000_common.h"
struct dib7000p_config {
u8 output_mpeg2_in_188_bytes;
u8 hostbus_diversity;
u8 tuner_is_baseband;
int (*update_lna) (struct dvb_frontend *, u16 agc_global);
struct dibx000_agc_config *agc;
struct dibx000_bandwidth_config *bw;
#define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff
u16 gpio_dir;
#define DIB7000P_GPIO_DEFAULT_VALUES 0x0000
u16 gpio_val;
#define DIB7000P_GPIO_PWM_POS0(v) ((v & 0xf) << 12)
#define DIB7000P_GPIO_PWM_POS1(v) ((v & 0xf) << 8 )
#define DIB7000P_GPIO_PWM_POS2(v) ((v & 0xf) << 4 )
#define DIB7000P_GPIO_PWM_POS3(v) (v & 0xf)
#define DIB7000P_GPIO_DEFAULT_PWM_POS 0xffff
u16 gpio_pwm_pos;
u16 pwm_freq_div;
u8 quartz_direct;
int (*agc_control) (struct dvb_frontend *, u8 before);
};
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
extern struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
extern struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
/* TODO
extern INT dib7000p_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
extern INT dib7000p_enable_vbg_voltage(struct dibDemod *demod);
extern void dib7000p_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
extern USHORT dib7000p_get_current_agc_global(struct dibDemod *demod);
*/
#endif
......@@ -32,6 +32,13 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
#define BAND_LBAND 0x01
#define BAND_UHF 0x02
#define BAND_VHF 0x04
#define BAND_SBAND 0x08
#define BAND_FM 0x10
#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \
(freq_kHz) <= 250000 ? BAND_VHF : \
(freq_kHz) <= 863000 ? BAND_UHF : \
(freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND )
struct dibx000_agc_config {
/* defines the capabilities of this AGC-setting - using the BAND_-defines*/
......@@ -129,6 +136,7 @@ enum dibx000_adc_states {
/* I hope I can get rid of the following kludge in the near future */
struct dibx000_ofdm_channel {
u32 RF_kHz;
u8 Bw;
s16 nfft;
s16 guard;
......@@ -138,9 +146,11 @@ struct dibx000_ofdm_channel {
s16 vit_alpha;
s16 vit_code_rate_hp;
s16 vit_code_rate_lp;
u8 intlv_native;
};
#define FEP2DIB(fep,ch) \
(ch)->RF_kHz = (fep)->frequency / 1000; \
(ch)->Bw = (fep)->u.ofdm.bandwidth; \
(ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \
(ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \
......@@ -149,7 +159,8 @@ struct dibx000_ofdm_channel {
(ch)->vit_select_hp = 1; \
(ch)->vit_alpha = 1; \
(ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \
(ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP;
(ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \
(ch)->intlv_native = 1;
#define INIT_OFDM_CHANNEL(ch) do {\
(ch)->Bw = 0; \
......
......@@ -472,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;
......
......@@ -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
This diff is collapsed.
......@@ -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,
};
......
/*
* 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:
*/
/*
* lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF
* 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
......@@ -16,49 +16,20 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _LG_H06XF_H_
#define _LG_H06XF_H_
#include "dvb-pll.h"
#ifndef _LGH06XF_H_
#define _LGH06XF_H_
#include "dvb_frontend.h"
static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap,
struct dvb_frontend_parameters* params)
#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)
{
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;
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
return NULL;
}
#endif
#endif /* CONFIG_DVB_TUNER_LGH06XF */
#endif /* _LGH06XF_H_ */
......@@ -40,6 +40,7 @@
#include <linux/slab.h>
#include <asm/byteorder.h>
#include "dvb_math.h"
#include "dvb_frontend.h"
#include "dvb-pll.h"
#include "or51132.h"
......@@ -62,6 +63,7 @@ struct or51132_state
/* Demodulator private data */
fe_modulation_t current_modulation;
u32 snr; /* Result of last SNR calculation */
/* Tuner private data */
u32 current_frequency;
......@@ -465,124 +467,128 @@ static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
return 0;
}
/* log10-1 table at .5 increments from 1 to 100.5 */
static unsigned int i100x20log10[] = {
0, 352, 602, 795, 954, 1088, 1204, 1306, 1397, 1480,
1556, 1625, 1690, 1750, 1806, 1858, 1908, 1955, 2000, 2042,
2082, 2121, 2158, 2193, 2227, 2260, 2292, 2322, 2352, 2380,
2408, 2434, 2460, 2486, 2510, 2534, 2557, 2580, 2602, 2623,
2644, 2664, 2684, 2704, 2723, 2742, 2760, 2778, 2795, 2813,
2829, 2846, 2862, 2878, 2894, 2909, 2924, 2939, 2954, 2968,
2982, 2996, 3010, 3023, 3037, 3050, 3062, 3075, 3088, 3100,
3112, 3124, 3136, 3148, 3159, 3170, 3182, 3193, 3204, 3214,
3225, 3236, 3246, 3256, 3266, 3276, 3286, 3296, 3306, 3316,
3325, 3334, 3344, 3353, 3362, 3371, 3380, 3389, 3397, 3406,
3415, 3423, 3432, 3440, 3448, 3456, 3464, 3472, 3480, 3488,
3496, 3504, 3511, 3519, 3526, 3534, 3541, 3549, 3556, 3563,
3570, 3577, 3584, 3591, 3598, 3605, 3612, 3619, 3625, 3632,
3639, 3645, 3652, 3658, 3665, 3671, 3677, 3683, 3690, 3696,
3702, 3708, 3714, 3720, 3726, 3732, 3738, 3744, 3750, 3755,
3761, 3767, 3772, 3778, 3784, 3789, 3795, 3800, 3806, 3811,
3816, 3822, 3827, 3832, 3838, 3843, 3848, 3853, 3858, 3863,
3868, 3874, 3879, 3884, 3888, 3893, 3898, 3903, 3908, 3913,
3918, 3922, 3927, 3932, 3936, 3941, 3946, 3950, 3955, 3960,
3964, 3969, 3973, 3978, 3982, 3986, 3991, 3995, 4000, 4004,
};
/* Calculate SNR estimation (scaled by 2^24)
static unsigned int denom[] = {1,1,100,1000,10000,100000,1000000,10000000,100000000};
8-VSB SNR and QAM equations from Oren datasheets
static unsigned int i20Log10(unsigned short val)
{
unsigned int rntval = 100;
unsigned int tmp = val;
unsigned int exp = 1;
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 )
while(tmp > 100) {tmp /= 100; exp++;}
For QAM256:
SNR[dB] = 10 * log10(907832426.314266 / MSE^2 )
val = (2 * val)/denom[exp];
if (exp > 1) rntval = 2000*exp;
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)
{
if (mse == 0) /* No signal */
return 0;
rntval += i100x20log10[val];
return rntval;
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_signal_strength(struct dvb_frontend* fe, u16* strength)
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];
u8 rcvr_stat;
u16 snr_equ;
u32 signal_strength;
int usK;
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_status 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_status 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_signal_strength 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);
/* Receiver Status */
/* Read status, contains modulation type for QAM_AUTO and
NTSC filter for VSB */
snd_buf[0]=0x04;
snd_buf[1]=0x00;
snd_buf[1]=0x00; /* Status register */
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;
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: read_signal_strength read_status read error\n");
return -1;
printk(KERN_WARNING "or51132: status read error\n");
return -EREMOTEIO;
}
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);
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_snr(struct dvb_frontend* fe, u16* snr)
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];
u16 snr_equ;
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;
}
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;
}
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);
/* 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;
*snr = 0xFFFF - snr_equ;
dprintk("read_snr %i\n",*snr);
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;
}
......
This diff is collapsed.
......@@ -648,18 +648,24 @@ static int tda10046_init(struct dvb_frontend* fe)
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x00); // set AGC polarities
break;
case TDA10046_AGC_TDA827X:
case TDA10046_AGC_TDA827X_GP11:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities
break;
case TDA10046_AGC_TDA827X_GPL:
case TDA10046_AGC_TDA827X_GP00:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
break;
case TDA10046_AGC_TDA827X_GP01:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x62); // set AGC polarities
break;
}
tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
......
......@@ -35,8 +35,9 @@ enum tda10046_agc {
TDA10046_AGC_DEFAULT, /* original configuration */
TDA10046_AGC_IFO_AUTO_NEG, /* IF AGC only, automatic, negtive */
TDA10046_AGC_IFO_AUTO_POS, /* IF AGC only, automatic, positive */
TDA10046_AGC_TDA827X, /* IF AGC only, special setup for tda827x */
TDA10046_AGC_TDA827X_GPL, /* same as above, but GPIOs 0 */
TDA10046_AGC_TDA827X_GP11, /* IF AGC only, special setup for tda827x */
TDA10046_AGC_TDA827X_GP00, /* same as above, but GPIOs 0 */
TDA10046_AGC_TDA827X_GP01, /* same as above, but GPIO3=0 GPIO1=1*/
};
enum tda10046_if {
......
......@@ -262,12 +262,29 @@ static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
if (sync & 0x10)
*status |= FE_HAS_SYNC;
if (sync & 0x20) /* frontend can not lock */
*status |= FE_TIMEDOUT;
if ((sync & 0x1f) == 0x1f)
*status |= FE_HAS_LOCK;
return 0;
}
static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber)
{
struct tda8083_state* state = fe->demodulator_priv;
int ret;
u8 buf[3];
if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf))))
return ret;
*ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
return 0;
}
static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
struct tda8083_state* state = fe->demodulator_priv;
......@@ -288,6 +305,17 @@ static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
return 0;
}
static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct tda8083_state* state = fe->demodulator_priv;
*ucblocks = tda8083_readreg(state, 0x0f);
if (*ucblocks == 0xff)
*ucblocks = 0xffffffff;
return 0;
}
static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct tda8083_state* state = fe->demodulator_priv;
......@@ -440,6 +468,8 @@ static struct dvb_frontend_ops tda8083_ops = {
.read_status = tda8083_read_status,
.read_signal_strength = tda8083_read_signal_strength,
.read_snr = tda8083_read_snr,
.read_ber = tda8083_read_ber,
.read_ucblocks = tda8083_read_ucblocks,
.diseqc_send_master_cmd = tda8083_send_diseqc_msg,
.diseqc_send_burst = tda8083_diseqc_send_burst,
......
This diff is collapsed.
......@@ -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;
......
......@@ -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
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment