Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (180 commits) V4L/DVB (4641): Trivial: use lowercase letters in hex subsystem ids V4L/DVB (4639): Cx88: add autodetection for alternate revision of Leadtek PVR V4L/DVB (4638): Basic DVB-T and analog TV support for the HVR1300. V4L/DVB (4637): Add a default method for VIDIOC_G_PARM V4L/DVB (4635): Extend bttv and saa7134 to check for both AGP and PCI PCI failure case V4L/DVB (4634): Zr36120: implement pcipci checks V4L/DVB (4632): Zoran: Implement pcipci failure check V4L/DVB (4631): Av7110: remove V4L2_CAP_VBI_CAPTURE flag V4L/DVB (4630): Av7110: FW_LOADER depemdency fixed V4L/DVB (4629): Saa7134: add card support for Proteus Pro 2309 V4L/DVB (4628): Fix VIDIOC_ENUMSTD ioctl in videodev.c V4L/DVB (4627): Vivi crashes with mplayer V4L/DVB (4626): On saa7111/7113, LUMA_CTRL need a different value V4L/DVB (4624): Tvaudio: Replaced kernel_thread() with kthread_run() V4L/DVB (4622): Copy-paste bug in videodev.c V4L/DVB (4620): Fix AGC configuration for MOD3000P-based boards V4L/DVB (4619): Fixes some I2C dependencies on V4L devices V4L/DVB (4617): Problem with dibusb-mb.c USB IDs V4L/DVB (4616): [PATCH] Nebula DigiTV USB RC support V4L/DVB (4614): Export symbol saa7134_tvaudio_setmute from saa7134 for saa7134-alsa ...
This commit is contained in:
commit
5ffd1a6aaa
|
@ -47,7 +47,7 @@ Who: Jody McIntyre <scjody@modernduck.com>
|
|||
---------------------------
|
||||
|
||||
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
|
||||
When: July 2006
|
||||
When: December 2006
|
||||
Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
|
||||
series. The old API have lots of drawbacks and don't provide enough
|
||||
means to work with all video and audio standards. The newer API is
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
6 -> AverTV Studio 303 (M126) [1461:000b]
|
||||
7 -> MSI TV-@nywhere Master [1462:8606]
|
||||
8 -> Leadtek Winfast DV2000 [107d:6620]
|
||||
9 -> Leadtek PVR 2000 [107d:663b,107d:663C]
|
||||
9 -> Leadtek PVR 2000 [107d:663b,107d:663c,107d:6632]
|
||||
10 -> IODATA GV-VCP3/PCI [10fc:d003]
|
||||
11 -> Prolink PlayTV PVR
|
||||
12 -> ASUS PVR-416 [1043:4823]
|
||||
12 -> ASUS PVR-416 [1043:4823,1461:c111]
|
||||
13 -> MSI TV-@nywhere
|
||||
14 -> KWorld/VStream XPert DVB-T [17de:08a6]
|
||||
15 -> DViCO FusionHDTV DVB-T1 [18ac:db00]
|
||||
|
@ -51,3 +51,7 @@
|
|||
50 -> NPG Tech Real TV FM Top 10 [14f1:0842]
|
||||
51 -> WinFast DTV2000 H [107d:665e]
|
||||
52 -> Geniatech DVB-S [14f1:0084]
|
||||
53 -> Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T [0070:1404]
|
||||
54 -> Norwood Micro TV Tuner
|
||||
55 -> Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM [c180:c980]
|
||||
56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder [0070:9600,0070:9601,0070:9602]
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
57 -> Avermedia AVerTV GO 007 FM [1461:f31f]
|
||||
58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0351,1421:0370,1421:1370]
|
||||
59 -> Kworld/Tevion V-Stream Xpert TV PVR7134
|
||||
60 -> LifeView/Typhoon FlyDVB-T Duo Cardbus [5168:0502,4e42:0502]
|
||||
60 -> LifeView/Typhoon/Genius FlyDVB-T Duo Cardbus [5168:0502,4e42:0502,1489:0502]
|
||||
61 -> Philips TOUGH DVB-T reference design [1131:2004]
|
||||
62 -> Compro VideoMate TV Gold+II
|
||||
63 -> Kworld Xpert TV PVR7134
|
||||
|
@ -83,7 +83,7 @@
|
|||
82 -> MSI TV@Anywhere plus [1462:6231]
|
||||
83 -> Terratec Cinergy 250 PCI TV [153b:1160]
|
||||
84 -> LifeView FlyDVB Trio [5168:0319]
|
||||
85 -> AverTV DVB-T 777 [1461:2c05]
|
||||
85 -> AverTV DVB-T 777 [1461:2c05,1461:2c05]
|
||||
86 -> LifeView FlyDVB-T / Genius VideoWonder DVB-T [5168:0301,1489:0301]
|
||||
87 -> ADS Instant TV Duo Cardbus PTV331 [0331:1421]
|
||||
88 -> Tevion/KWorld DVB-T 220RF [17de:7201]
|
||||
|
@ -94,3 +94,6 @@
|
|||
93 -> Medion 7134 Bridge #2 [16be:0005]
|
||||
94 -> LifeView FlyDVB-T Hybrid Cardbus [5168:3306,5168:3502]
|
||||
95 -> LifeView FlyVIDEO3000 (NTSC) [5169:0138]
|
||||
96 -> Medion Md8800 Quadro [16be:0007,16be:0008]
|
||||
97 -> LifeView FlyDVB-S /Acorp TV134DS [5168:0300,4e42:0300]
|
||||
98 -> Proteus Pro 2309 [0919:2003]
|
||||
|
|
|
@ -54,6 +54,12 @@ bttv.o
|
|||
dropouts.
|
||||
chroma_agc=0/1 AGC of chroma signal, off by default.
|
||||
adc_crush=0/1 Luminance ADC crush, on by default.
|
||||
i2c_udelay= Allow reduce I2C speed. Default is 5 usecs
|
||||
(meaning 66,67 Kbps). The default is the
|
||||
maximum supported speed by kernel bitbang
|
||||
algoritm. You may use lower numbers, if I2C
|
||||
messages are lost (16 is known to work on
|
||||
all supported cards).
|
||||
|
||||
bttv_gpio=0/1
|
||||
gpiomask=
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
The cx23416 can produce (and the cx23415 can also read) raw YUV output. The
|
||||
format of a YUV frame is specific to this chip and is called HM12. 'HM' stands
|
||||
for 'Hauppauge Macroblock', which is a misnomer as 'Conexant Macroblock' would
|
||||
be more accurate.
|
||||
|
||||
The format is YUV 4:2:0 which uses 1 Y byte per pixel and 1 U and V byte per
|
||||
four pixels.
|
||||
|
||||
The data is encoded as two macroblock planes, the first containing the Y
|
||||
values, the second containing UV macroblocks.
|
||||
|
||||
The Y plane is divided into blocks of 16x16 pixels from left to right
|
||||
and from top to bottom. Each block is transmitted in turn, line-by-line.
|
||||
|
||||
So the first 16 bytes are the first line of the top-left block, the
|
||||
second 16 bytes are the second line of the top-left block, etc. After
|
||||
transmitting this block the first line of the block on the right to the
|
||||
first block is transmitted, etc.
|
||||
|
||||
The UV plane is divided into blocks of 16x8 UV values going from left
|
||||
to right, top to bottom. Each block is transmitted in turn, line-by-line.
|
||||
|
||||
So the first 16 bytes are the first line of the top-left block and
|
||||
contain 8 UV value pairs (16 bytes in total). The second 16 bytes are the
|
||||
second line of 8 UV pairs of the top-left block, etc. After transmitting
|
||||
this block the first line of the block on the right to the first block is
|
||||
transmitted, etc.
|
||||
|
||||
The code below is given as an example on how to convert HM12 to separate
|
||||
Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels.
|
||||
|
||||
The width of a frame is always 720 pixels, regardless of the actual specified
|
||||
width.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static unsigned char frame[576*720*3/2];
|
||||
static unsigned char framey[576*720];
|
||||
static unsigned char frameu[576*720 / 4];
|
||||
static unsigned char framev[576*720 / 4];
|
||||
|
||||
static void de_macro_y(unsigned char* dst, unsigned char *src, int dstride, int w, int h)
|
||||
{
|
||||
unsigned int y, x, i;
|
||||
|
||||
// descramble Y plane
|
||||
// dstride = 720 = w
|
||||
// The Y plane is divided into blocks of 16x16 pixels
|
||||
// Each block in transmitted in turn, line-by-line.
|
||||
for (y = 0; y < h; y += 16) {
|
||||
for (x = 0; x < w; x += 16) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
memcpy(dst + x + (y + i) * dstride, src, 16);
|
||||
src += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void de_macro_uv(unsigned char *dstu, unsigned char *dstv, unsigned char *src, int dstride, int w, int h)
|
||||
{
|
||||
unsigned int y, x, i;
|
||||
|
||||
// descramble U/V plane
|
||||
// dstride = 720 / 2 = w
|
||||
// The U/V values are interlaced (UVUV...).
|
||||
// Again, the UV plane is divided into blocks of 16x16 UV values.
|
||||
// Each block in transmitted in turn, line-by-line.
|
||||
for (y = 0; y < h; y += 16) {
|
||||
for (x = 0; x < w; x += 8) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
int idx = x + (y + i) * dstride;
|
||||
|
||||
dstu[idx+0] = src[0]; dstv[idx+0] = src[1];
|
||||
dstu[idx+1] = src[2]; dstv[idx+1] = src[3];
|
||||
dstu[idx+2] = src[4]; dstv[idx+2] = src[5];
|
||||
dstu[idx+3] = src[6]; dstv[idx+3] = src[7];
|
||||
dstu[idx+4] = src[8]; dstv[idx+4] = src[9];
|
||||
dstu[idx+5] = src[10]; dstv[idx+5] = src[11];
|
||||
dstu[idx+6] = src[12]; dstv[idx+6] = src[13];
|
||||
dstu[idx+7] = src[14]; dstv[idx+7] = src[15];
|
||||
src += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fin;
|
||||
int i;
|
||||
|
||||
if (argc == 1) fin = stdin;
|
||||
else fin = fopen(argv[1], "r");
|
||||
|
||||
if (fin == NULL) {
|
||||
fprintf(stderr, "cannot open input\n");
|
||||
exit(-1);
|
||||
}
|
||||
while (fread(frame, sizeof(frame), 1, fin) == 1) {
|
||||
de_macro_y(framey, frame, 720, 720, 576);
|
||||
de_macro_uv(frameu, framev, frame + 720 * 576, 720 / 2, 720 / 2, 576 / 2);
|
||||
fwrite(framey, sizeof(framey), 1, stdout);
|
||||
fwrite(framev, sizeof(framev), 1, stdout);
|
||||
fwrite(frameu, sizeof(frameu), 1, stdout);
|
||||
}
|
||||
fclose(fin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
Format of embedded V4L2_MPEG_STREAM_VBI_FMT_IVTV VBI data
|
||||
=========================================================
|
||||
|
||||
This document describes the V4L2_MPEG_STREAM_VBI_FMT_IVTV format of the VBI data
|
||||
embedded in an MPEG-2 program stream. This format is in part dictated by some
|
||||
hardware limitations of the ivtv driver (the driver for the Conexant cx23415/6
|
||||
chips), in particular a maximum size for the VBI data. Anything longer is cut
|
||||
off when the MPEG stream is played back through the cx23415.
|
||||
|
||||
The advantage of this format is it is very compact and that all VBI data for
|
||||
all lines can be stored while still fitting within the maximum allowed size.
|
||||
|
||||
The stream ID of the VBI data is 0xBD. The maximum size of the embedded data is
|
||||
4 + 43 * 36, which is 4 bytes for a header and 2 * 18 VBI lines with a 1 byte
|
||||
header and a 42 bytes payload each. Anything beyond this limit is cut off by
|
||||
the cx23415/6 firmware. Besides the data for the VBI lines we also need 36 bits
|
||||
for a bitmask determining which lines are captured and 4 bytes for a magic cookie,
|
||||
signifying that this data package contains V4L2_MPEG_STREAM_VBI_FMT_IVTV VBI data.
|
||||
If all lines are used, then there is no longer room for the bitmask. To solve this
|
||||
two different magic numbers were introduced:
|
||||
|
||||
'itv0': After this magic number two unsigned longs follow. Bits 0-17 of the first
|
||||
unsigned long denote which lines of the first field are captured. Bits 18-31 of
|
||||
the first unsigned long and bits 0-3 of the second unsigned long are used for the
|
||||
second field.
|
||||
|
||||
'ITV0': This magic number assumes all VBI lines are captured, i.e. it implicitly
|
||||
implies that the bitmasks are 0xffffffff and 0xf.
|
||||
|
||||
After these magic cookies (and the 8 byte bitmask in case of cookie 'itv0') the
|
||||
captured VBI lines start:
|
||||
|
||||
For each line the least significant 4 bits of the first byte contain the data type.
|
||||
Possible values are shown in the table below. The payload is in the following 42
|
||||
bytes.
|
||||
|
||||
Here is the list of possible data types:
|
||||
|
||||
#define IVTV_SLICED_TYPE_TELETEXT 0x1 // Teletext (uses lines 6-22 for PAL)
|
||||
#define IVTV_SLICED_TYPE_CC 0x4 // Closed Captions (line 21 NTSC)
|
||||
#define IVTV_SLICED_TYPE_WSS 0x5 // Wide Screen Signal (line 23 PAL)
|
||||
#define IVTV_SLICED_TYPE_VPS 0x7 // Video Programming System (PAL) (line 16)
|
||||
|
||||
Hans Verkuil <hverkuil@xs4all.nl>
|
|
@ -4,7 +4,6 @@ config VIDEO_SAA7146
|
|||
|
||||
config VIDEO_SAA7146_VV
|
||||
tristate
|
||||
select VIDEO_V4L2
|
||||
select VIDEO_BUF
|
||||
select VIDEO_VIDEOBUF
|
||||
select VIDEO_SAA7146
|
||||
|
|
|
@ -32,6 +32,37 @@ IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE] = {
|
|||
|
||||
EXPORT_SYMBOL_GPL(ir_codes_empty);
|
||||
|
||||
/* Michal Majchrowicz <mmajchrowicz@gmail.com> */
|
||||
IR_KEYTAB_TYPE ir_codes_proteus_2309[IR_KEYTAB_SIZE] = {
|
||||
/* numeric */
|
||||
[ 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,
|
||||
|
||||
[ 0x5c ] = KEY_POWER, /* power */
|
||||
[ 0x20 ] = KEY_F, /* full screen */
|
||||
[ 0x0f ] = KEY_BACKSPACE, /* recall */
|
||||
[ 0x1b ] = KEY_ENTER, /* mute */
|
||||
[ 0x41 ] = KEY_RECORD, /* record */
|
||||
[ 0x43 ] = KEY_STOP, /* stop */
|
||||
[ 0x16 ] = KEY_S,
|
||||
[ 0x1a ] = KEY_Q, /* off */
|
||||
[ 0x2e ] = KEY_RED,
|
||||
[ 0x1f ] = KEY_DOWN, /* channel - */
|
||||
[ 0x1c ] = KEY_UP, /* channel + */
|
||||
[ 0x10 ] = KEY_LEFT, /* volume - */
|
||||
[ 0x1e ] = KEY_RIGHT, /* volume + */
|
||||
[ 0x14 ] = KEY_F1,
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(ir_codes_proteus_2309);
|
||||
/* Matt Jesson <dvb@jesson.eclipse.co.uk */
|
||||
IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = {
|
||||
[ 0x28 ] = KEY_0, //'0' / 'enter'
|
||||
|
@ -1473,3 +1504,51 @@ IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = {
|
|||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(ir_codes_npgtech);
|
||||
|
||||
/* Norwood Micro (non-Pro) TV Tuner
|
||||
By Peter Naulls <peter@chocky.org>
|
||||
Key comments are the functions given in the manual */
|
||||
IR_KEYTAB_TYPE ir_codes_norwood[IR_KEYTAB_SIZE] = {
|
||||
/* Keys 0 to 9 */
|
||||
[ 0x20 ] = KEY_0,
|
||||
[ 0x21 ] = KEY_1,
|
||||
[ 0x22 ] = KEY_2,
|
||||
[ 0x23 ] = KEY_3,
|
||||
[ 0x24 ] = KEY_4,
|
||||
[ 0x25 ] = KEY_5,
|
||||
[ 0x26 ] = KEY_6,
|
||||
[ 0x27 ] = KEY_7,
|
||||
[ 0x28 ] = KEY_8,
|
||||
[ 0x29 ] = KEY_9,
|
||||
|
||||
[ 0x78 ] = KEY_TUNER, /* Video Source */
|
||||
[ 0x2c ] = KEY_EXIT, /* Open/Close software */
|
||||
[ 0x2a ] = KEY_SELECT, /* 2 Digit Select */
|
||||
[ 0x69 ] = KEY_AGAIN, /* Recall */
|
||||
|
||||
[ 0x32 ] = KEY_BRIGHTNESSUP, /* Brightness increase */
|
||||
[ 0x33 ] = KEY_BRIGHTNESSDOWN, /* Brightness decrease */
|
||||
[ 0x6b ] = KEY_KPPLUS, /* (not named >>>>>) */
|
||||
[ 0x6c ] = KEY_KPMINUS, /* (not named <<<<<) */
|
||||
|
||||
[ 0x2d ] = KEY_MUTE, /* Mute */
|
||||
[ 0x30 ] = KEY_VOLUMEUP, /* Volume up */
|
||||
[ 0x31 ] = KEY_VOLUMEDOWN, /* Volume down */
|
||||
[ 0x60 ] = KEY_CHANNELUP, /* Channel up */
|
||||
[ 0x61 ] = KEY_CHANNELDOWN, /* Channel down */
|
||||
|
||||
[ 0x3f ] = KEY_RECORD, /* Record */
|
||||
[ 0x37 ] = KEY_PLAY, /* Play */
|
||||
[ 0x36 ] = KEY_PAUSE, /* Pause */
|
||||
[ 0x2b ] = KEY_STOP, /* Stop */
|
||||
[ 0x67 ] = KEY_FASTFORWARD, /* Foward */
|
||||
[ 0x66 ] = KEY_REWIND, /* Rewind */
|
||||
[ 0x3e ] = KEY_SEARCH, /* Auto Scan */
|
||||
[ 0x2e ] = KEY_CAMERA, /* Capture Video */
|
||||
[ 0x6d ] = KEY_MENU, /* Show/Hide Control */
|
||||
[ 0x2f ] = KEY_ZOOM, /* Full Screen */
|
||||
[ 0x34 ] = KEY_RADIO, /* FM */
|
||||
[ 0x65 ] = KEY_POWER, /* Computer power */
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL_GPL(ir_codes_norwood);
|
||||
|
|
|
@ -455,7 +455,6 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status)
|
|||
|
||||
static struct video_device device_template =
|
||||
{
|
||||
.hardware = VID_HARDWARE_SAA7146,
|
||||
.fops = &video_fops,
|
||||
.minor = -1,
|
||||
};
|
||||
|
|
|
@ -2,13 +2,13 @@ config DVB_B2C2_FLEXCOP
|
|||
tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters"
|
||||
depends on DVB_CORE && I2C
|
||||
select DVB_PLL
|
||||
select DVB_STV0299
|
||||
select DVB_MT352
|
||||
select DVB_MT312
|
||||
select DVB_NXT200X
|
||||
select DVB_STV0297
|
||||
select DVB_BCM3510
|
||||
select DVB_LGDT330X
|
||||
select DVB_STV0299 if !DVB_FE_CUSTOMISE
|
||||
select DVB_MT352 if !DVB_FE_CUSTOMISE
|
||||
select DVB_MT312 if !DVB_FE_CUSTOMISE
|
||||
select DVB_NXT200X if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0297 if !DVB_FE_CUSTOMISE
|
||||
select DVB_BCM3510 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Support for the digital TV receiver chip made by B2C2 Inc. included in
|
||||
Technisats PCI cards and USB boxes.
|
||||
|
|
|
@ -505,7 +505,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
struct dvb_frontend_ops *ops;
|
||||
|
||||
/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
|
||||
if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
|
||||
if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
|
||||
ops = &fc->fe->ops;
|
||||
|
||||
ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
|
||||
|
@ -519,36 +519,36 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
|
||||
} else
|
||||
/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
|
||||
if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
|
||||
if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
|
||||
fc->dev_type = FC_AIR_DVB;
|
||||
fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
|
||||
info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
|
||||
} else
|
||||
/* try the air atsc 2nd generation (nxt2002) */
|
||||
if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
|
||||
if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
|
||||
fc->dev_type = FC_AIR_ATSC2;
|
||||
dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
|
||||
dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL, &dvb_pll_samsung_tbmv);
|
||||
info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
|
||||
} else
|
||||
/* try the air atsc 3nd generation (lgdt3303) */
|
||||
if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
|
||||
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;
|
||||
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 */
|
||||
if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
|
||||
if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
|
||||
fc->dev_type = FC_AIR_ATSC1;
|
||||
info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
|
||||
} else
|
||||
/* try the cable dvb (stv0297) */
|
||||
if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
|
||||
if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
|
||||
fc->dev_type = FC_CABLE;
|
||||
fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
|
||||
info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
|
||||
} else
|
||||
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
|
||||
if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
|
||||
if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
|
||||
ops = &fc->fe->ops;
|
||||
|
||||
ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
|
||||
|
@ -571,9 +571,7 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
} else {
|
||||
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
|
||||
err("frontend registration failed!");
|
||||
ops = &fc->fe->ops;
|
||||
if (ops->release != NULL)
|
||||
ops->release(fc->fe);
|
||||
dvb_frontend_detach(fc->fe);
|
||||
fc->fe = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -584,8 +582,10 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||
|
||||
void flexcop_frontend_exit(struct flexcop_device *fc)
|
||||
{
|
||||
if (fc->init_state & FC_STATE_FE_INIT)
|
||||
if (fc->init_state & FC_STATE_FE_INIT) {
|
||||
dvb_unregister_frontend(fc->fe);
|
||||
dvb_frontend_detach(fc->fe);
|
||||
}
|
||||
|
||||
fc->init_state &= ~FC_STATE_FE_INIT;
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ config DVB_BT8XX
|
|||
tristate "BT8xx based PCI cards"
|
||||
depends on DVB_CORE && PCI && I2C && VIDEO_BT848
|
||||
select DVB_PLL
|
||||
select DVB_MT352
|
||||
select DVB_SP887X
|
||||
select DVB_NXT6000
|
||||
select DVB_CX24110
|
||||
select DVB_OR51211
|
||||
select DVB_LGDT330X
|
||||
select DVB_ZL10353
|
||||
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_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
select FW_LOADER
|
||||
help
|
||||
Support for PCI cards based on the Bt8xx PCI bridge. Examples are
|
||||
|
|
|
@ -1715,6 +1715,15 @@ static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
|
|||
static void dst_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct dst_state *state = fe->demodulator_priv;
|
||||
if (state->dst_ca) {
|
||||
dvb_unregister_device(state->dst_ca);
|
||||
#ifdef CONFIG_DVB_CORE_ATTACH
|
||||
symbol_put(dst_ca_attach);
|
||||
#endif
|
||||
}
|
||||
#ifdef CONFIG_DVB_CORE_ATTACH
|
||||
symbol_put(dst_attach);
|
||||
#endif
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
|
|
|
@ -699,12 +699,17 @@ static struct dvb_device dvbdev_ca = {
|
|||
.fops = &dst_ca_fops
|
||||
};
|
||||
|
||||
int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
|
||||
struct dvb_device *dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
|
||||
{
|
||||
struct dvb_device *dvbdev;
|
||||
|
||||
dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
|
||||
dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA);
|
||||
return 0;
|
||||
if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA) == 0) {
|
||||
dst->dst_ca = dvbdev;
|
||||
return dst->dst_ca;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dst_ca_attach);
|
||||
|
|
|
@ -140,6 +140,7 @@ struct dst_state {
|
|||
char *tuner_name;
|
||||
struct mutex dst_mutex;
|
||||
u8 fw_name[8];
|
||||
struct dvb_device *dst_ca;
|
||||
};
|
||||
|
||||
struct tuner_types {
|
||||
|
@ -178,7 +179,7 @@ int write_dst(struct dst_state *state, u8 * data, u8 len);
|
|||
int read_dst(struct dst_state *state, u8 * ret, u8 len);
|
||||
u8 dst_check_sum(u8 * buf, u32 len);
|
||||
struct dst_state* dst_attach(struct dst_state* state, struct dvb_adapter *dvb_adapter);
|
||||
int dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
|
||||
struct dvb_device *dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
|
||||
int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay);
|
||||
|
||||
int dst_command(struct dst_state* state, u8 * data, u8 len);
|
||||
|
|
|
@ -67,7 +67,7 @@ static void dvb_bt8xx_task(unsigned long data)
|
|||
|
||||
static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
|
||||
{
|
||||
struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
|
||||
struct dvb_demux*dvbdmx = dvbdmxfeed->demux;
|
||||
struct dvb_bt8xx_card *card = dvbdmx->priv;
|
||||
int rc;
|
||||
|
||||
|
@ -595,15 +595,14 @@ static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
|
|||
|
||||
static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
||||
{
|
||||
int ret;
|
||||
struct dst_state* state = NULL;
|
||||
|
||||
switch(type) {
|
||||
case BTTV_BOARD_DVICO_DVBT_LITE:
|
||||
card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
|
||||
card->fe = dvb_attach(mt352_attach, &thomson_dtt7579_config, card->i2c_adapter);
|
||||
|
||||
if (card->fe == NULL)
|
||||
card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config,
|
||||
card->fe = dvb_attach(zl10353_attach, &thomson_dtt7579_zl10353_config,
|
||||
card->i2c_adapter);
|
||||
|
||||
if (card->fe != NULL) {
|
||||
|
@ -615,7 +614,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
|
||||
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
|
||||
lgdt330x_reset(card);
|
||||
card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
|
||||
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;
|
||||
dprintk ("dvb_bt8xx: lgdt330x detected\n");
|
||||
|
@ -630,7 +629,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
|
||||
/* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */
|
||||
digitv_alps_tded4_reset(card);
|
||||
card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
|
||||
card->fe = dvb_attach(nxt6000_attach, &vp3021_alps_tded4_config, card->i2c_adapter);
|
||||
if (card->fe != NULL) {
|
||||
card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
|
||||
dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
|
||||
|
@ -639,7 +638,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
|
||||
/* New Nebula (marked (c)2005 on low profile pci card) has mt352 demod */
|
||||
digitv_alps_tded4_reset(card);
|
||||
card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
|
||||
card->fe = dvb_attach(mt352_attach, &digitv_alps_tded4_config, card->i2c_adapter);
|
||||
|
||||
if (card->fe != NULL) {
|
||||
card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
|
||||
|
@ -648,14 +647,14 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
break;
|
||||
|
||||
case BTTV_BOARD_AVDVBT_761:
|
||||
card->fe = sp887x_attach(µtune_mt7202dtf_config, card->i2c_adapter);
|
||||
card->fe = dvb_attach(sp887x_attach, µtune_mt7202dtf_config, card->i2c_adapter);
|
||||
if (card->fe) {
|
||||
card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTTV_BOARD_AVDVBT_771:
|
||||
card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
|
||||
card->fe = dvb_attach(mt352_attach, &advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
|
||||
if (card->fe != NULL) {
|
||||
card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
|
||||
card->fe->ops.info.frequency_min = 174000000;
|
||||
|
@ -670,22 +669,21 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
state->config = &dst_config;
|
||||
state->i2c = card->i2c_adapter;
|
||||
state->bt = card->bt;
|
||||
|
||||
state->dst_ca = NULL;
|
||||
/* DST is not a frontend, attaching the ASIC */
|
||||
if ((dst_attach(state, &card->dvb_adapter)) == NULL) {
|
||||
if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
|
||||
printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
card->fe = &state->frontend;
|
||||
|
||||
/* Attach other DST peripherals if any */
|
||||
/* Conditional Access device */
|
||||
card->fe = &state->frontend;
|
||||
if (state->dst_hw_cap & DST_TYPE_HAS_CA)
|
||||
ret = dst_ca_attach(state, &card->dvb_adapter);
|
||||
dvb_attach(dst_ca_attach, state, &card->dvb_adapter);
|
||||
break;
|
||||
|
||||
case BTTV_BOARD_PINNACLESAT:
|
||||
card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
|
||||
card->fe = dvb_attach(cx24110_attach, &pctvsat_config, card->i2c_adapter);
|
||||
if (card->fe) {
|
||||
card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
|
||||
card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
|
||||
|
@ -694,7 +692,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
break;
|
||||
|
||||
case BTTV_BOARD_PC_HDTV:
|
||||
card->fe = or51211_attach(&or51211_config, card->i2c_adapter);
|
||||
card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -707,8 +705,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
|
|||
else
|
||||
if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
|
||||
printk("dvb-bt8xx: Frontend registration failed!\n");
|
||||
if (card->fe->ops.release)
|
||||
card->fe->ops.release(card->fe);
|
||||
dvb_frontend_detach(card->fe);
|
||||
card->fe = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -925,8 +922,10 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub)
|
|||
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
|
||||
dvb_dmxdev_release(&card->dmxdev);
|
||||
dvb_dmx_release(&card->demux);
|
||||
if (card->fe)
|
||||
if (card->fe) {
|
||||
dvb_unregister_frontend(card->fe);
|
||||
dvb_frontend_detach(card->fe);
|
||||
}
|
||||
dvb_unregister_adapter(&card->dvb_adapter);
|
||||
|
||||
kfree(card);
|
||||
|
|
|
@ -9,3 +9,16 @@ config DVB_CORE
|
|||
in-kernel drivers will select this automatically if needed.
|
||||
If unsure say N.
|
||||
|
||||
config DVB_CORE_ATTACH
|
||||
bool "Load and attach frontend modules as needed"
|
||||
depends on DVB_CORE
|
||||
depends on MODULES
|
||||
help
|
||||
Remove the static dependency of DVB card drivers on all
|
||||
frontend modules for all possible card variants. Instead,
|
||||
allow the card drivers to only load the frontend modules
|
||||
they require. This saves several KBytes of memory.
|
||||
|
||||
Note: You will need moudule-init-tools v3.2 or later for this feature.
|
||||
|
||||
If unsure say Y.
|
||||
|
|
|
@ -1105,18 +1105,42 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
|
|||
mutex_lock(&frontend_mutex);
|
||||
dvb_unregister_device (fepriv->dvbdev);
|
||||
dvb_frontend_stop (fe);
|
||||
if (fe->ops.tuner_ops.release) {
|
||||
fe->ops.tuner_ops.release(fe);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
if (fe->ops.release)
|
||||
fe->ops.release(fe);
|
||||
else
|
||||
printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name);
|
||||
|
||||
/* fe is invalid now */
|
||||
kfree(fepriv);
|
||||
mutex_unlock(&frontend_mutex);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_unregister_frontend);
|
||||
|
||||
#ifdef CONFIG_DVB_CORE_ATTACH
|
||||
void dvb_frontend_detach(struct dvb_frontend* fe)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (fe->ops.release_sec) {
|
||||
fe->ops.release_sec(fe);
|
||||
symbol_put_addr(fe->ops.release_sec);
|
||||
}
|
||||
if (fe->ops.tuner_ops.release) {
|
||||
fe->ops.tuner_ops.release(fe);
|
||||
symbol_put_addr(fe->ops.tuner_ops.release);
|
||||
}
|
||||
ptr = (void*)fe->ops.release;
|
||||
if (ptr) {
|
||||
fe->ops.release(fe);
|
||||
symbol_put_addr(ptr);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void dvb_frontend_detach(struct dvb_frontend* fe)
|
||||
{
|
||||
if (fe->ops.release_sec)
|
||||
fe->ops.release_sec(fe);
|
||||
if (fe->ops.tuner_ops.release)
|
||||
fe->ops.tuner_ops.release(fe);
|
||||
if (fe->ops.release)
|
||||
fe->ops.release(fe);
|
||||
}
|
||||
#endif
|
||||
EXPORT_SYMBOL(dvb_frontend_detach);
|
||||
|
|
|
@ -92,10 +92,13 @@ struct dvb_frontend_ops {
|
|||
struct dvb_frontend_info info;
|
||||
|
||||
void (*release)(struct dvb_frontend* fe);
|
||||
void (*release_sec)(struct dvb_frontend* fe);
|
||||
|
||||
int (*init)(struct dvb_frontend* fe);
|
||||
int (*sleep)(struct dvb_frontend* fe);
|
||||
|
||||
int (*write)(struct dvb_frontend* fe, u8* buf, int len);
|
||||
|
||||
/* if this is set, it overrides the default swzigzag */
|
||||
int (*tune)(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters* params,
|
||||
|
@ -147,7 +150,7 @@ struct dvb_frontend {
|
|||
void* demodulator_priv;
|
||||
void* tuner_priv;
|
||||
void* frontend_priv;
|
||||
void* misc_priv;
|
||||
void* sec_priv;
|
||||
};
|
||||
|
||||
extern int dvb_register_frontend(struct dvb_adapter* dvb,
|
||||
|
@ -155,6 +158,8 @@ extern int dvb_register_frontend(struct dvb_adapter* dvb,
|
|||
|
||||
extern int dvb_unregister_frontend(struct dvb_frontend* fe);
|
||||
|
||||
extern void dvb_frontend_detach(struct dvb_frontend* fe);
|
||||
|
||||
extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
|
||||
|
||||
extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
|
||||
|
|
|
@ -102,4 +102,26 @@ extern int dvb_usercopy(struct inode *inode, struct file *file,
|
|||
int (*func)(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, void *arg));
|
||||
|
||||
/** generic DVB attach function. */
|
||||
#ifdef CONFIG_DVB_CORE_ATTACH
|
||||
#define dvb_attach(FUNCTION, ARGS...) ({ \
|
||||
void *__r = NULL; \
|
||||
typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
|
||||
if (__a) { \
|
||||
__r = (void *) __a(ARGS); \
|
||||
if (__r == NULL) \
|
||||
symbol_put(FUNCTION); \
|
||||
} else { \
|
||||
printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \
|
||||
} \
|
||||
__r; \
|
||||
})
|
||||
|
||||
#else
|
||||
#define dvb_attach(FUNCTION, ARGS...) ({ \
|
||||
FUNCTION(ARGS); \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef _DVBDEV_H_ */
|
||||
|
|
|
@ -26,6 +26,7 @@ config DVB_USB_A800
|
|||
tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
|
||||
depends on DVB_USB
|
||||
select DVB_DIB3000MC
|
||||
select DVB_TUNER_MT2060
|
||||
help
|
||||
Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
|
||||
|
||||
|
@ -33,6 +34,7 @@ config DVB_USB_DIBUSB_MB
|
|||
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
|
||||
depends on DVB_USB
|
||||
select DVB_DIB3000MB
|
||||
select DVB_TUNER_MT2060
|
||||
help
|
||||
Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
|
||||
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
|
||||
|
@ -65,6 +67,7 @@ config DVB_USB_DIBUSB_MC
|
|||
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
|
||||
depends on DVB_USB
|
||||
select DVB_DIB3000MC
|
||||
select DVB_TUNER_MT2060
|
||||
help
|
||||
Support for 2.0 DVB-T receivers based on reference designs made by
|
||||
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
|
||||
|
@ -80,16 +83,17 @@ config DVB_USB_UMT_010
|
|||
tristate "HanfTek UMT-010 DVB-T USB2.0 support"
|
||||
depends on DVB_USB
|
||||
select DVB_DIB3000MC
|
||||
select DVB_TUNER_MT2060
|
||||
help
|
||||
Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
|
||||
|
||||
config DVB_USB_CXUSB
|
||||
tristate "Conexant USB2.0 hybrid reference design support"
|
||||
depends on DVB_USB
|
||||
select DVB_CX22702
|
||||
select DVB_LGDT330X
|
||||
select DVB_MT352
|
||||
select DVB_ZL10353
|
||||
select DVB_CX22702 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LGDT330X if !DVB_FE_CUSTOMISE
|
||||
select DVB_MT352 if !DVB_FE_CUSTOMISE
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Conexant USB2.0 hybrid reference design.
|
||||
Currently, only DVB and ATSC modes are supported, analog mode
|
||||
|
@ -101,8 +105,8 @@ config DVB_USB_CXUSB
|
|||
config DVB_USB_DIGITV
|
||||
tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
|
||||
depends on DVB_USB
|
||||
select DVB_NXT6000
|
||||
select DVB_MT352
|
||||
select DVB_NXT6000 if !DVB_FE_CUSTOMISE
|
||||
select DVB_MT352 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
|
||||
|
||||
|
@ -145,6 +149,7 @@ config DVB_USB_NOVA_T_USB2
|
|||
tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
|
||||
depends on DVB_USB
|
||||
select DVB_DIB3000MC
|
||||
select DVB_TUNER_MT2060
|
||||
help
|
||||
Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
|
||||
|
||||
|
|
|
@ -26,6 +26,13 @@ static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* assure to put cold to 0 for iManufacturer == 1 */
|
||||
static int a800_identify_state(struct usb_device *udev, struct dvb_usb_properties *props,struct dvb_usb_device_description **desc, int *cold)
|
||||
{
|
||||
*cold = udev->descriptor.iManufacturer != 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key a800_rc_keys[] = {
|
||||
{ 0x02, 0x01, KEY_PROG1 }, /* SOURCE */
|
||||
{ 0x02, 0x00, KEY_POWER }, /* POWER */
|
||||
|
@ -113,6 +120,7 @@ static struct dvb_usb_properties a800_properties = {
|
|||
.power_ctrl = a800_power_ctrl,
|
||||
.frontend_attach = dibusb_dib3000mc_frontend_attach,
|
||||
.tuner_attach = dibusb_dib3000mc_tuner_attach,
|
||||
.identify_state = a800_identify_state,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = a800_rc_keys,
|
||||
|
|
|
@ -349,6 +349,7 @@ static struct mt352_config cxusb_dee1601_config = {
|
|||
|
||||
static struct zl10353_config cxusb_zl10353_dee1601_config = {
|
||||
.demod_address = 0x0f,
|
||||
.parallel_ts = 1,
|
||||
};
|
||||
|
||||
static struct mt352_config cxusb_mt352_config = {
|
||||
|
@ -409,7 +410,7 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d)
|
|||
|
||||
cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, &b, 1);
|
||||
|
||||
if ((d->fe = cx22702_attach(&cxusb_cx22702_config, &d->i2c_adap)) != NULL)
|
||||
if ((d->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &d->i2c_adap)) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
|
@ -422,7 +423,7 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_device *d)
|
|||
|
||||
cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
|
||||
|
||||
if ((d->fe = lgdt330x_attach(&cxusb_lgdt3303_config, &d->i2c_adap)) != NULL)
|
||||
if ((d->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &d->i2c_adap)) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
|
@ -435,7 +436,7 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_device *d)
|
|||
|
||||
cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
|
||||
|
||||
if ((d->fe = mt352_attach(&cxusb_mt352_config, &d->i2c_adap)) != NULL)
|
||||
if ((d->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &d->i2c_adap)) != NULL)
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
|
@ -448,8 +449,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
|
|||
|
||||
cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
|
||||
|
||||
if (((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
|
||||
((d->fe = zl10353_attach(&cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
|
||||
if (((d->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
|
||||
((d->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
|
||||
return 0;
|
||||
|
||||
return -EIO;
|
||||
|
|
|
@ -131,9 +131,6 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num
|
|||
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++) {
|
||||
/* write/read request */
|
||||
if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
|
||||
|
@ -168,31 +165,137 @@ int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
|
|||
}
|
||||
EXPORT_SYMBOL(dibusb_read_eeprom_byte);
|
||||
|
||||
/* 3000MC/P stuff */
|
||||
// Config Adjacent channels Perf -cal22
|
||||
static struct dibx000_agc_config dib3000p_mt2060_agc_config = {
|
||||
.band_caps = BAND_VHF | BAND_UHF,
|
||||
.setup = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0),
|
||||
|
||||
.agc1_max = 48497,
|
||||
.agc1_min = 23593,
|
||||
.agc2_max = 46531,
|
||||
.agc2_min = 24904,
|
||||
|
||||
.agc1_pt1 = 0x65,
|
||||
.agc1_pt2 = 0x69,
|
||||
|
||||
.agc1_slope1 = 0x51,
|
||||
.agc1_slope2 = 0x27,
|
||||
|
||||
.agc2_pt1 = 0,
|
||||
.agc2_pt2 = 0x33,
|
||||
|
||||
.agc2_slope1 = 0x35,
|
||||
.agc2_slope2 = 0x37,
|
||||
};
|
||||
|
||||
static struct dib3000mc_config stk3000p_dib3000p_config = {
|
||||
&dib3000p_mt2060_agc_config,
|
||||
|
||||
.max_time = 0x196,
|
||||
.ln_adc_level = 0x1cc7,
|
||||
|
||||
.output_mpeg2_in_188_bytes = 1,
|
||||
};
|
||||
|
||||
static struct dibx000_agc_config dib3000p_panasonic_agc_config = {
|
||||
.setup = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0),
|
||||
|
||||
.agc1_max = 56361,
|
||||
.agc1_min = 22282,
|
||||
.agc2_max = 47841,
|
||||
.agc2_min = 36045,
|
||||
|
||||
.agc1_pt1 = 0x3b,
|
||||
.agc1_pt2 = 0x6b,
|
||||
|
||||
.agc1_slope1 = 0x55,
|
||||
.agc1_slope2 = 0x1d,
|
||||
|
||||
.agc2_pt1 = 0,
|
||||
.agc2_pt2 = 0x0a,
|
||||
|
||||
.agc2_slope1 = 0x95,
|
||||
.agc2_slope2 = 0x1e,
|
||||
};
|
||||
|
||||
static struct dib3000mc_config mod3000p_dib3000p_config = {
|
||||
&dib3000p_panasonic_agc_config,
|
||||
|
||||
.max_time = 0x51,
|
||||
.ln_adc_level = 0x1cc7,
|
||||
|
||||
.output_mpeg2_in_188_bytes = 1,
|
||||
};
|
||||
|
||||
int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
|
||||
{
|
||||
struct dib3000_config demod_cfg;
|
||||
struct dibusb_state *st = d->priv;
|
||||
|
||||
for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
|
||||
if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
|
||||
d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
|
||||
d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
|
||||
d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
|
||||
return 0;
|
||||
if (dib3000mc_attach(&d->i2c_adap, 1, DEFAULT_DIB3000P_I2C_ADDRESS, 0, &mod3000p_dib3000p_config, &d->fe) == 0 ||
|
||||
dib3000mc_attach(&d->i2c_adap, 1, DEFAULT_DIB3000MC_I2C_ADDRESS, 0, &mod3000p_dib3000p_config, &d->fe) == 0) {
|
||||
if (d->priv != NULL) {
|
||||
struct dibusb_state *st = d->priv;
|
||||
st->ops.pid_parse = dib3000mc_pid_parse;
|
||||
st->ops.pid_ctrl = dib3000mc_pid_control;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
|
||||
|
||||
static struct mt2060_config stk3000p_mt2060_config = {
|
||||
0x60
|
||||
};
|
||||
|
||||
int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
|
||||
{
|
||||
d->pll_addr = 0x60;
|
||||
d->pll_desc = &dvb_pll_env57h1xd5;
|
||||
struct dibusb_state *st = d->priv;
|
||||
int ret;
|
||||
u8 a,b;
|
||||
u16 if1 = 1220;
|
||||
struct i2c_adapter *tun_i2c;
|
||||
|
||||
d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
|
||||
d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
|
||||
// First IF calibration for Liteon Sticks
|
||||
if (d->udev->descriptor.idVendor == USB_VID_LITEON &&
|
||||
d->udev->descriptor.idProduct == USB_PID_LITEON_DVB_T_WARM) {
|
||||
|
||||
dibusb_read_eeprom_byte(d,0x7E,&a);
|
||||
dibusb_read_eeprom_byte(d,0x7F,&b);
|
||||
|
||||
if (a == 0x00)
|
||||
if1 += b;
|
||||
else if (a == 0x80)
|
||||
if1 -= b;
|
||||
else
|
||||
warn("LITE-ON DVB-T: Strange IF1 calibration :%2X %2X\n", a, b);
|
||||
|
||||
} else if (d->udev->descriptor.idVendor == USB_VID_DIBCOM &&
|
||||
d->udev->descriptor.idProduct == USB_PID_DIBCOM_MOD3001_WARM) {
|
||||
u8 desc;
|
||||
dibusb_read_eeprom_byte(d, 7, &desc);
|
||||
if (desc == 2) {
|
||||
a = 127;
|
||||
do {
|
||||
dibusb_read_eeprom_byte(d, a, &desc);
|
||||
a--;
|
||||
} while (a > 7 && (desc == 0xff || desc == 0x00));
|
||||
if (desc & 0x80)
|
||||
if1 -= (0xff - desc);
|
||||
else
|
||||
if1 += desc;
|
||||
}
|
||||
}
|
||||
|
||||
tun_i2c = dib3000mc_get_tuner_i2c_master(d->fe, 1);
|
||||
if ((ret = mt2060_attach(d->fe, tun_i2c, &stk3000p_mt2060_config, if1)) != 0) {
|
||||
/* not found - use panasonic pll parameters */
|
||||
if (dvb_pll_attach(d->fe, 0x60, tun_i2c, &dvb_pll_env57h1xd5) == NULL)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
st->mt2060_present = 1;
|
||||
/* set the correct parameters for the dib3000p */
|
||||
dib3000mc_set_config(d->fe, &stk3000p_dib3000p_config);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
|
||||
|
@ -267,6 +370,67 @@ struct dvb_usb_rc_key dibusb_rc_keys[] = {
|
|||
{ 0x86, 0x1e, KEY_DOWN },
|
||||
{ 0x86, 0x1f, KEY_LEFT },
|
||||
{ 0x86, 0x1b, KEY_RIGHT },
|
||||
|
||||
/* Key codes for the DiBcom MOD3000 remote. */
|
||||
{ 0x80, 0x00, KEY_MUTE },
|
||||
{ 0x80, 0x01, KEY_TEXT },
|
||||
{ 0x80, 0x02, KEY_HOME },
|
||||
{ 0x80, 0x03, KEY_POWER },
|
||||
|
||||
{ 0x80, 0x04, KEY_RED },
|
||||
{ 0x80, 0x05, KEY_GREEN },
|
||||
{ 0x80, 0x06, KEY_YELLOW },
|
||||
{ 0x80, 0x07, KEY_BLUE },
|
||||
|
||||
{ 0x80, 0x08, KEY_DVD },
|
||||
{ 0x80, 0x09, KEY_AUDIO },
|
||||
{ 0x80, 0x0a, KEY_MEDIA }, /* Pictures */
|
||||
{ 0x80, 0x0b, KEY_VIDEO },
|
||||
|
||||
{ 0x80, 0x0c, KEY_BACK },
|
||||
{ 0x80, 0x0d, KEY_UP },
|
||||
{ 0x80, 0x0e, KEY_RADIO },
|
||||
{ 0x80, 0x0f, KEY_EPG },
|
||||
|
||||
{ 0x80, 0x10, KEY_LEFT },
|
||||
{ 0x80, 0x11, KEY_OK },
|
||||
{ 0x80, 0x12, KEY_RIGHT },
|
||||
{ 0x80, 0x13, KEY_UNKNOWN }, /* SAP */
|
||||
|
||||
{ 0x80, 0x14, KEY_TV },
|
||||
{ 0x80, 0x15, KEY_DOWN },
|
||||
{ 0x80, 0x16, KEY_MENU }, /* DVD Menu */
|
||||
{ 0x80, 0x17, KEY_LAST },
|
||||
|
||||
{ 0x80, 0x18, KEY_RECORD },
|
||||
{ 0x80, 0x19, KEY_STOP },
|
||||
{ 0x80, 0x1a, KEY_PAUSE },
|
||||
{ 0x80, 0x1b, KEY_PLAY },
|
||||
|
||||
{ 0x80, 0x1c, KEY_PREVIOUS },
|
||||
{ 0x80, 0x1d, KEY_REWIND },
|
||||
{ 0x80, 0x1e, KEY_FASTFORWARD },
|
||||
{ 0x80, 0x1f, KEY_NEXT},
|
||||
|
||||
{ 0x80, 0x40, KEY_1 },
|
||||
{ 0x80, 0x41, KEY_2 },
|
||||
{ 0x80, 0x42, KEY_3 },
|
||||
{ 0x80, 0x43, KEY_CHANNELUP },
|
||||
|
||||
{ 0x80, 0x44, KEY_4 },
|
||||
{ 0x80, 0x45, KEY_5 },
|
||||
{ 0x80, 0x46, KEY_6 },
|
||||
{ 0x80, 0x47, KEY_CHANNELDOWN },
|
||||
|
||||
{ 0x80, 0x48, KEY_7 },
|
||||
{ 0x80, 0x49, KEY_8 },
|
||||
{ 0x80, 0x4a, KEY_9 },
|
||||
{ 0x80, 0x4b, KEY_VOLUMEUP },
|
||||
|
||||
{ 0x80, 0x4c, KEY_CLEAR },
|
||||
{ 0x80, 0x4d, KEY_0 },
|
||||
{ 0x80, 0x4e, KEY_ENTER },
|
||||
{ 0x80, 0x4f, KEY_VOLUMEDOWN },
|
||||
};
|
||||
EXPORT_SYMBOL(dibusb_rc_keys);
|
||||
|
||||
|
|
|
@ -21,11 +21,11 @@ static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
|
|||
|
||||
demod_cfg.demod_address = 0x8;
|
||||
|
||||
if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
|
||||
d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
|
||||
d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
|
||||
if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
|
||||
d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
|
||||
|
||||
d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
|
||||
|
||||
|
@ -169,7 +169,7 @@ static struct dvb_usb_properties dibusb1_1_properties = {
|
|||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = dibusb_rc_keys,
|
||||
.rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
@ -247,7 +247,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
|
|||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = dibusb_rc_keys,
|
||||
.rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
@ -272,8 +272,8 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
|
|||
#endif
|
||||
.devices = {
|
||||
{ "Artec T1 USB1.1 TVBOX with AN2235",
|
||||
{ &dibusb_dib3000mb_table[20], NULL },
|
||||
{ &dibusb_dib3000mb_table[21], NULL },
|
||||
{ &dibusb_dib3000mb_table[22], NULL },
|
||||
},
|
||||
#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
|
||||
{ "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
|
||||
|
@ -304,7 +304,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
|
|||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = dibusb_rc_keys,
|
||||
.rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
@ -355,7 +355,7 @@ static struct dvb_usb_properties artec_t1_usb2_properties = {
|
|||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = dibusb_rc_keys,
|
||||
.rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
|
|
@ -28,6 +28,17 @@ static struct usb_device_id dibusb_dib3000mc_table [] = {
|
|||
/* 00 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) },
|
||||
/* 01 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) },
|
||||
/* 02 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
|
||||
/* 03 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, // ( ? )
|
||||
/* 04 */ { USB_DEVICE(USB_VID_LITEON, USB_PID_LITEON_DVB_T_COLD) },
|
||||
/* 05 */ { USB_DEVICE(USB_VID_LITEON, USB_PID_LITEON_DVB_T_WARM) },
|
||||
/* 06 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_DIGIVOX_MINI_SL_COLD) },
|
||||
/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_DIGIVOX_MINI_SL_WARM) },
|
||||
/* 08 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB2_COLD) },
|
||||
/* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB2_WARM) },
|
||||
/* 10 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_COLD) },
|
||||
/* 11 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_WARM) },
|
||||
/* 12 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_COLD) },
|
||||
/* 13 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_WARM) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
|
||||
|
@ -50,7 +61,7 @@ static struct dvb_usb_properties dibusb_mc_properties = {
|
|||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = dibusb_rc_keys,
|
||||
.rc_key_map_size = 63, /* FIXME */
|
||||
.rc_key_map_size = 111, /* FIXME */
|
||||
.rc_query = dibusb_rc_query,
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
@ -68,16 +79,38 @@ static struct dvb_usb_properties dibusb_mc_properties = {
|
|||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 2,
|
||||
.num_device_descs = 7,
|
||||
.devices = {
|
||||
{ "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
|
||||
{ &dibusb_dib3000mc_table[0], NULL },
|
||||
{ &dibusb_dib3000mc_table[1], NULL },
|
||||
},
|
||||
{ "Artec T1 USB2.0 TVBOX (please report the warm ID)",
|
||||
{ "Artec T1 USB2.0 TVBOX (please check the warm ID)",
|
||||
{ &dibusb_dib3000mc_table[2], NULL },
|
||||
{ NULL },
|
||||
{ &dibusb_dib3000mc_table[3], NULL },
|
||||
},
|
||||
{ "LITE-ON USB2.0 DVB-T Tuner",
|
||||
/* Also rebranded as Intuix S800, Toshiba */
|
||||
{ &dibusb_dib3000mc_table[4], NULL },
|
||||
{ &dibusb_dib3000mc_table[5], NULL },
|
||||
},
|
||||
{ "MSI Digivox Mini SL",
|
||||
{ &dibusb_dib3000mc_table[6], NULL },
|
||||
{ &dibusb_dib3000mc_table[7], NULL },
|
||||
},
|
||||
{ "GRAND - USB2.0 DVB-T adapter",
|
||||
{ &dibusb_dib3000mc_table[8], NULL },
|
||||
{ &dibusb_dib3000mc_table[9], NULL },
|
||||
},
|
||||
{ "Artec T14 - USB2.0 DVB-T",
|
||||
{ &dibusb_dib3000mc_table[10], NULL },
|
||||
{ &dibusb_dib3000mc_table[11], NULL },
|
||||
},
|
||||
{ "Leadtek - USB2.0 Winfast DTV dongle",
|
||||
{ &dibusb_dib3000mc_table[12], NULL },
|
||||
{ &dibusb_dib3000mc_table[13], NULL },
|
||||
},
|
||||
{ NULL },
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include "dvb-usb.h"
|
||||
|
||||
#include "dib3000.h"
|
||||
#include "dib3000mc.h"
|
||||
#include "mt2060.h"
|
||||
|
||||
/*
|
||||
* protocol of all dibusb related devices
|
||||
|
@ -96,6 +98,7 @@
|
|||
|
||||
struct dibusb_state {
|
||||
struct dib_fe_xfer_ops ops;
|
||||
int mt2060_present;
|
||||
|
||||
/* for RC5 remote control */
|
||||
int old_toggle;
|
||||
|
|
|
@ -128,11 +128,11 @@ static struct nxt6000_config digitv_nxt6000_config = {
|
|||
|
||||
static int digitv_frontend_attach(struct dvb_usb_device *d)
|
||||
{
|
||||
if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL) {
|
||||
if ((d->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &d->i2c_adap)) != NULL) {
|
||||
d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
|
||||
return 0;
|
||||
}
|
||||
if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
|
||||
if ((d->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
|
||||
d->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
|
||||
return 0;
|
||||
}
|
||||
|
@ -147,21 +147,91 @@ static int digitv_tuner_attach(struct dvb_usb_device *d)
|
|||
}
|
||||
|
||||
static struct dvb_usb_rc_key digitv_rc_keys[] = {
|
||||
{ 0x00, 0x16, KEY_POWER }, /* dummy key */
|
||||
{ 0x5f, 0x55, KEY_0 },
|
||||
{ 0x6f, 0x55, KEY_1 },
|
||||
{ 0x9f, 0x55, KEY_2 },
|
||||
{ 0xaf, 0x55, KEY_3 },
|
||||
{ 0x5f, 0x56, KEY_4 },
|
||||
{ 0x6f, 0x56, KEY_5 },
|
||||
{ 0x9f, 0x56, KEY_6 },
|
||||
{ 0xaf, 0x56, KEY_7 },
|
||||
{ 0x5f, 0x59, KEY_8 },
|
||||
{ 0x6f, 0x59, KEY_9 },
|
||||
{ 0x9f, 0x59, KEY_TV },
|
||||
{ 0xaf, 0x59, KEY_AUX },
|
||||
{ 0x5f, 0x5a, KEY_DVD },
|
||||
{ 0x6f, 0x5a, KEY_POWER },
|
||||
{ 0x9f, 0x5a, KEY_MHP }, /* labelled 'Picture' */
|
||||
{ 0xaf, 0x5a, KEY_AUDIO },
|
||||
{ 0x5f, 0x65, KEY_INFO },
|
||||
{ 0x6f, 0x65, KEY_F13 }, /* 16:9 */
|
||||
{ 0x9f, 0x65, KEY_F14 }, /* 14:9 */
|
||||
{ 0xaf, 0x65, KEY_EPG },
|
||||
{ 0x5f, 0x66, KEY_EXIT },
|
||||
{ 0x6f, 0x66, KEY_MENU },
|
||||
{ 0x9f, 0x66, KEY_UP },
|
||||
{ 0xaf, 0x66, KEY_DOWN },
|
||||
{ 0x5f, 0x69, KEY_LEFT },
|
||||
{ 0x6f, 0x69, KEY_RIGHT },
|
||||
{ 0x9f, 0x69, KEY_ENTER },
|
||||
{ 0xaf, 0x69, KEY_CHANNELUP },
|
||||
{ 0x5f, 0x6a, KEY_CHANNELDOWN },
|
||||
{ 0x6f, 0x6a, KEY_VOLUMEUP },
|
||||
{ 0x9f, 0x6a, KEY_VOLUMEDOWN },
|
||||
{ 0xaf, 0x6a, KEY_RED },
|
||||
{ 0x5f, 0x95, KEY_GREEN },
|
||||
{ 0x6f, 0x95, KEY_YELLOW },
|
||||
{ 0x9f, 0x95, KEY_BLUE },
|
||||
{ 0xaf, 0x95, KEY_SUBTITLE },
|
||||
{ 0x5f, 0x96, KEY_F15 }, /* AD */
|
||||
{ 0x6f, 0x96, KEY_TEXT },
|
||||
{ 0x9f, 0x96, KEY_MUTE },
|
||||
{ 0xaf, 0x96, KEY_REWIND },
|
||||
{ 0x5f, 0x99, KEY_STOP },
|
||||
{ 0x6f, 0x99, KEY_PLAY },
|
||||
{ 0x9f, 0x99, KEY_FASTFORWARD },
|
||||
{ 0xaf, 0x99, KEY_F16 }, /* chapter */
|
||||
{ 0x5f, 0x9a, KEY_PAUSE },
|
||||
{ 0x6f, 0x9a, KEY_PLAY },
|
||||
{ 0x9f, 0x9a, KEY_RECORD },
|
||||
{ 0xaf, 0x9a, KEY_F17 }, /* picture in picture */
|
||||
{ 0x5f, 0xa5, KEY_KPPLUS }, /* zoom in */
|
||||
{ 0x6f, 0xa5, KEY_KPMINUS }, /* zoom out */
|
||||
{ 0x9f, 0xa5, KEY_F18 }, /* capture */
|
||||
{ 0xaf, 0xa5, KEY_F19 }, /* web */
|
||||
{ 0x5f, 0xa6, KEY_EMAIL },
|
||||
{ 0x6f, 0xa6, KEY_PHONE },
|
||||
{ 0x9f, 0xa6, KEY_PC },
|
||||
};
|
||||
|
||||
/* TODO is it really the NEC protocol ? */
|
||||
static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
int i;
|
||||
u8 key[5];
|
||||
u8 b[4] = { 0 };
|
||||
|
||||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
|
||||
/* TODO state, maybe it is VV ? */
|
||||
if (key[1] != 0)
|
||||
key[0] = 0x01; /* if something is inside the buffer, simulate key press */
|
||||
|
||||
/* call the universal NEC remote processor, to find out the key's state and event */
|
||||
dvb_usb_nec_rc_key_to_event(d,key,event,state);
|
||||
/* Tell the device we've read the remote. Not sure how necessary
|
||||
this is, but the Nebula SDK does it. */
|
||||
digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
|
||||
|
||||
/* if something is inside the buffer, simulate key press */
|
||||
if (key[1] != 0)
|
||||
{
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
if (d->props.rc_key_map[i].custom == key[1] &&
|
||||
d->props.rc_key_map[i].data == key[2]) {
|
||||
*event = d->props.rc_key_map[i].event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (key[0] != 0)
|
||||
deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
|
||||
return 0;
|
||||
|
|
|
@ -93,6 +93,7 @@ static int dtt200u_frontend_attach(struct dvb_usb_device *d)
|
|||
}
|
||||
|
||||
static struct dvb_usb_properties dtt200u_properties;
|
||||
static struct dvb_usb_properties wt220u_fc_properties;
|
||||
static struct dvb_usb_properties wt220u_properties;
|
||||
static struct dvb_usb_properties wt220u_zl0353_properties;
|
||||
|
||||
|
@ -101,6 +102,7 @@ static int dtt200u_usb_probe(struct usb_interface *intf,
|
|||
{
|
||||
if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE,NULL) == 0 ||
|
||||
dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE,NULL) == 0 ||
|
||||
dvb_usb_device_init(intf,&wt220u_fc_properties,THIS_MODULE,NULL) == 0 ||
|
||||
dvb_usb_device_init(intf,&wt220u_zl0353_properties,THIS_MODULE,NULL) == 0)
|
||||
return 0;
|
||||
|
||||
|
@ -114,6 +116,9 @@ static struct usb_device_id dtt200u_usb_table [] = {
|
|||
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM) },
|
||||
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD) },
|
||||
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM) },
|
||||
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD) },
|
||||
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM) },
|
||||
{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD) },
|
||||
{ 0 },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
|
||||
|
@ -193,13 +198,54 @@ static struct dvb_usb_properties wt220u_properties = {
|
|||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
|
||||
.cold_ids = { &dtt200u_usb_table[2], NULL },
|
||||
.cold_ids = { &dtt200u_usb_table[2], &dtt200u_usb_table[8], NULL },
|
||||
.warm_ids = { &dtt200u_usb_table[3], NULL },
|
||||
},
|
||||
{ NULL },
|
||||
}
|
||||
};
|
||||
|
||||
static struct dvb_usb_properties wt220u_fc_properties = {
|
||||
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
|
||||
.pid_filter_count = 15,
|
||||
|
||||
.usb_ctrl = CYPRESS_FX2,
|
||||
.firmware = "dvb-usb-wt220u-fc03.fw",
|
||||
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
.streaming_ctrl = dtt200u_streaming_ctrl,
|
||||
.pid_filter = dtt200u_pid_filter,
|
||||
.frontend_attach = dtt200u_frontend_attach,
|
||||
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = dtt200u_rc_keys,
|
||||
.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.urb = {
|
||||
.type = DVB_USB_BULK,
|
||||
.count = 7,
|
||||
.endpoint = 0x86,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
|
||||
.cold_ids = { &dtt200u_usb_table[6], NULL },
|
||||
.warm_ids = { &dtt200u_usb_table[7], NULL },
|
||||
},
|
||||
{ NULL },
|
||||
}
|
||||
};
|
||||
|
||||
static struct dvb_usb_properties wt220u_zl0353_properties = {
|
||||
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
|
||||
.pid_filter_count = 15,
|
||||
|
@ -271,6 +317,6 @@ module_init(dtt200u_usb_module_init);
|
|||
module_exit(dtt200u_usb_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
|
||||
MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon DVB-T USB2.0 devices");
|
||||
MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D DVB-T USB2.0 devices");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -175,36 +175,36 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
|
|||
int dvb_usb_fe_init(struct dvb_usb_device* d)
|
||||
{
|
||||
if (d->props.frontend_attach == NULL) {
|
||||
err("strange '%s' doesn't want to attach a frontend.",d->desc->name);
|
||||
err("strange: '%s' doesn't want to attach a frontend.",d->desc->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
d->props.frontend_attach(d);
|
||||
|
||||
/* re-assign sleep and wakeup functions */
|
||||
if (d->fe != NULL) {
|
||||
if (d->props.frontend_attach(d) == 0 && d->fe != NULL) {
|
||||
d->fe_init = d->fe->ops.init; d->fe->ops.init = dvb_usb_fe_wakeup;
|
||||
d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep;
|
||||
|
||||
if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
|
||||
err("Frontend registration failed.");
|
||||
if (d->fe->ops.release)
|
||||
d->fe->ops.release(d->fe);
|
||||
dvb_frontend_detach(d->fe);
|
||||
d->fe = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* only attach the tuner if the demod is there */
|
||||
if (d->props.tuner_attach != NULL)
|
||||
d->props.tuner_attach(d);
|
||||
} else
|
||||
err("no frontend was attached by '%s'",d->desc->name);
|
||||
|
||||
if (d->props.tuner_attach != NULL)
|
||||
d->props.tuner_attach(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvb_usb_fe_exit(struct dvb_usb_device *d)
|
||||
{
|
||||
if (d->fe != NULL)
|
||||
if (d->fe != NULL) {
|
||||
dvb_unregister_frontend(d->fe);
|
||||
dvb_frontend_detach(d->fe);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -10,51 +10,53 @@
|
|||
#define _DVB_USB_IDS_H_
|
||||
|
||||
/* Vendor IDs */
|
||||
#define USB_VID_ADSTECH 0x06e1
|
||||
#define USB_VID_ANCHOR 0x0547
|
||||
#define USB_VID_WIDEVIEW 0x14aa
|
||||
#define USB_VID_AVERMEDIA 0x07ca
|
||||
#define USB_VID_COMPRO 0x185b
|
||||
#define USB_VID_COMPRO_UNK 0x145f
|
||||
#define USB_VID_CYPRESS 0x04b4
|
||||
#define USB_VID_DIBCOM 0x10b8
|
||||
#define USB_VID_DVICO 0x0fe9
|
||||
#define USB_VID_EMPIA 0xeb1a
|
||||
#define USB_VID_GRANDTEC 0x5032
|
||||
#define USB_VID_HANFTEK 0x15f4
|
||||
#define USB_VID_HAUPPAUGE 0x2040
|
||||
#define USB_VID_HYPER_PALTEK 0x1025
|
||||
#define USB_VID_KWORLD 0xeb2a
|
||||
#define USB_VID_KYE 0x0458
|
||||
#define USB_VID_MEDION 0x1660
|
||||
#define USB_VID_PINNACLE 0x2304
|
||||
#define USB_VID_VISIONPLUS 0x13d3
|
||||
#define USB_VID_TWINHAN 0x1822
|
||||
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
|
||||
#define USB_VID_GENPIX 0x09c0
|
||||
#define USB_VID_ADSTECH 0x06e1
|
||||
#define USB_VID_ANCHOR 0x0547
|
||||
#define USB_VID_AVERMEDIA 0x07ca
|
||||
#define USB_VID_COMPRO 0x185b
|
||||
#define USB_VID_COMPRO_UNK 0x145f
|
||||
#define USB_VID_CYPRESS 0x04b4
|
||||
#define USB_VID_DIBCOM 0x10b8
|
||||
#define USB_VID_DVICO 0x0fe9
|
||||
#define USB_VID_EMPIA 0xeb1a
|
||||
#define USB_VID_GENPIX 0x09c0
|
||||
#define USB_VID_GRANDTEC 0x5032
|
||||
#define USB_VID_HANFTEK 0x15f4
|
||||
#define USB_VID_HAUPPAUGE 0x2040
|
||||
#define USB_VID_HYPER_PALTEK 0x1025
|
||||
#define USB_VID_KWORLD 0xeb2a
|
||||
#define USB_VID_KYE 0x0458
|
||||
#define USB_VID_LEADTEK 0x0413
|
||||
#define USB_VID_LITEON 0x04ca
|
||||
#define USB_VID_MEDION 0x1660
|
||||
#define USB_VID_PINNACLE 0x2304
|
||||
#define USB_VID_VISIONPLUS 0x13d3
|
||||
#define USB_VID_TWINHAN 0x1822
|
||||
#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
|
||||
#define USB_VID_WIDEVIEW 0x14aa
|
||||
|
||||
/* Product IDs */
|
||||
#define USB_PID_ADSTECH_USB2_COLD 0xa333
|
||||
#define USB_PID_ADSTECH_USB2_WARM 0xa334
|
||||
#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
|
||||
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
|
||||
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
|
||||
#define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801
|
||||
#define USB_PID_COMPRO_DVBU2000_COLD 0xd000
|
||||
#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_AVERMEDIA_DVBT_USB_COLD 0x0001
|
||||
#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
|
||||
#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
|
||||
#define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801
|
||||
#define USB_PID_COMPRO_DVBU2000_COLD 0xd000
|
||||
#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_DIBCOM_HOOK_DEFAULT 0x0064
|
||||
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
|
||||
#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065
|
||||
#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
|
||||
#define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9
|
||||
#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6
|
||||
#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
|
||||
#define USB_PID_DIBCOM_STK7700 0x1e14
|
||||
#define USB_PID_DIBCOM_STK7700_REENUM 0x1e15
|
||||
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
|
||||
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
|
||||
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
|
||||
#define USB_PID_DIBCOM_STK7700_REENUM 0x1e15
|
||||
#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
|
||||
#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
|
||||
#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
|
||||
#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
|
||||
#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
|
||||
#define USB_PID_TWINHAN_VP7041_COLD 0x3201
|
||||
|
@ -69,25 +71,30 @@
|
|||
#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
|
||||
#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
|
||||
#define USB_PID_ULTIMA_TVBOX_WARM 0x8106
|
||||
#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
|
||||
#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108
|
||||
#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235
|
||||
#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109
|
||||
#define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a
|
||||
#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
|
||||
#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
|
||||
#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
|
||||
#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f
|
||||
#define USB_PID_HANFTEK_UMT_010_COLD 0x0001
|
||||
#define USB_PID_HANFTEK_UMT_010_WARM 0x0015
|
||||
#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
|
||||
#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108
|
||||
#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235
|
||||
#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109
|
||||
#define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a
|
||||
#define USB_PID_ARTEC_T14_COLD 0x810b
|
||||
#define USB_PID_ARTEC_T14_WARM 0x810c
|
||||
#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
|
||||
#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
|
||||
#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
|
||||
#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f
|
||||
#define USB_PID_HANFTEK_UMT_010_COLD 0x0001
|
||||
#define USB_PID_HANFTEK_UMT_010_WARM 0x0015
|
||||
#define USB_PID_DTT200U_COLD 0x0201
|
||||
#define USB_PID_DTT200U_WARM 0x0301
|
||||
#define USB_PID_WT220U_COLD 0x0222
|
||||
#define USB_PID_WT220U_WARM 0x0221
|
||||
#define USB_PID_WT220U_ZAP250_COLD 0x0220
|
||||
#define USB_PID_WT220U_COLD 0x0222
|
||||
#define USB_PID_WT220U_WARM 0x0221
|
||||
#define USB_PID_WT220U_FC_COLD 0x0225
|
||||
#define USB_PID_WT220U_FC_WARM 0x0226
|
||||
#define USB_PID_WT220U_ZL0353_COLD 0x022a
|
||||
#define USB_PID_WT220U_ZL0353_WARM 0x022b
|
||||
#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
|
||||
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
|
||||
#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
|
||||
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
|
||||
#define USB_PID_NEBULA_DIGITV 0x0201
|
||||
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
|
||||
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
|
||||
|
@ -103,8 +110,17 @@
|
|||
#define USB_PID_MEDION_MD95700 0x0932
|
||||
#define USB_PID_KYE_DVB_T_COLD 0x701e
|
||||
#define USB_PID_KYE_DVB_T_WARM 0x701f
|
||||
#define USB_PID_PCTV_200E 0x020e
|
||||
#define USB_PID_PCTV_400E 0x020f
|
||||
#define USB_PID_GENPIX_8PSK_COLD 0x0200
|
||||
#define USB_PID_GENPIX_8PSK_WARM 0x0201
|
||||
#define USB_PID_PCTV_200E 0x020e
|
||||
#define USB_PID_PCTV_400E 0x020f
|
||||
#define USB_PID_LITEON_DVB_T_COLD 0xf000
|
||||
#define USB_PID_LITEON_DVB_T_WARM 0xf001
|
||||
#define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360
|
||||
#define USB_PID_DIGIVOX_MINI_SL_WARM 0xe361
|
||||
#define USB_PID_GRANDTEC_DVBT_USB2_COLD 0x0bc6
|
||||
#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_GENPIX_8PSK_COLD 0x0200
|
||||
#define USB_PID_GENPIX_8PSK_WARM 0x0201
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* This file contains functions for initializing the the input-device and for handling remote-control-queries.
|
||||
*/
|
||||
#include "dvb-usb-common.h"
|
||||
#include <linux/usb/input.h>
|
||||
|
||||
/* Remote-control poll function - called every dib->rc_query_interval ms to see
|
||||
* whether the remote control has received anything.
|
||||
|
@ -96,7 +97,7 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
|
|||
return 0;
|
||||
|
||||
usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
|
||||
strlcpy(d->rc_phys, "/ir0", 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)
|
||||
|
@ -107,6 +108,8 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
|
|||
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;
|
||||
|
||||
/* set the bits for the keys */
|
||||
deb_rc("key map size: %d\n", d->props.rc_key_map_size);
|
||||
|
|
|
@ -156,7 +156,7 @@ static struct dvb_usb_properties nova_t_properties = {
|
|||
.pid_filter_count = 32,
|
||||
|
||||
.usb_ctrl = CYPRESS_FX2,
|
||||
.firmware = "dvb-usb-nova-t-usb2-01.fw",
|
||||
.firmware = "dvb-usb-nova-t-usb2-02.fw",
|
||||
|
||||
.size_of_priv = sizeof(struct dibusb_state),
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
|
|||
umt_config.demod_init = umt_mt352_demod_init;
|
||||
umt_config.demod_address = 0xf;
|
||||
|
||||
d->fe = mt352_attach(&umt_config, &d->i2c_adap);
|
||||
d->fe = dvb_attach(mt352_attach, &umt_config, &d->i2c_adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,48 +1,73 @@
|
|||
menu "Customise DVB Frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_FE_CUSTOMISE
|
||||
bool "Customise the frontend modules to build"
|
||||
default N
|
||||
help
|
||||
This allows the user to deselect frontend drivers unnecessary
|
||||
for their hardware from the build. Use this option with care
|
||||
as deselecting frontends which are in fact necessary will result
|
||||
in DVB devices which cannot be tuned due to lack of driver support.
|
||||
|
||||
If unsure say N.
|
||||
|
||||
comment "DVB-S (satellite) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_STV0299
|
||||
tristate "ST STV0299 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_CX24110
|
||||
tristate "Conexant CX24110 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_CX24123
|
||||
tristate "Conexant CX24123 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA8083
|
||||
tristate "Philips TDA8083 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_MT312
|
||||
tristate "Zarlink VP310/MT312 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_VES1X93
|
||||
tristate "VLSI VES1893 or VES1993 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_S5H1420
|
||||
tristate "Samsung S5H1420 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA10086
|
||||
tristate "Philips TDA10086 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
|
@ -52,6 +77,7 @@ comment "DVB-T (terrestrial) frontends"
|
|||
config DVB_SP8870
|
||||
tristate "Spase sp8870 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
select FW_LOADER
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
@ -64,6 +90,7 @@ config DVB_SP8870
|
|||
config DVB_SP887X
|
||||
tristate "Spase sp887x based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
select FW_LOADER
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
@ -76,24 +103,28 @@ config DVB_SP887X
|
|||
config DVB_CX22700
|
||||
tristate "Conexant CX22700 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_CX22702
|
||||
tristate "Conexant cx22702 demodulator (OFDM)"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_L64781
|
||||
tristate "LSI L64781"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA1004X
|
||||
tristate "Philips TDA10045H/TDA10046H based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
select FW_LOADER
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
@ -107,24 +138,28 @@ config DVB_TDA1004X
|
|||
config DVB_NXT6000
|
||||
tristate "NxtWave Communications NXT6000 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_MT352
|
||||
tristate "Zarlink MT352 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_ZL10353
|
||||
tristate "Zarlink ZL10353 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-T tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_DIB3000MB
|
||||
tristate "DiBcom 3000M-B"
|
||||
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.
|
||||
|
@ -132,6 +167,7 @@ config DVB_DIB3000MB
|
|||
config DVB_DIB3000MC
|
||||
tristate "DiBcom 3000P/M-C"
|
||||
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.
|
||||
|
@ -142,18 +178,21 @@ comment "DVB-C (cable) frontends"
|
|||
config DVB_VES1820
|
||||
tristate "VLSI VES1820 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_TDA10021
|
||||
tristate "Philips TDA10021 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
config DVB_STV0297
|
||||
tristate "ST STV0297 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-C tuner module. Say Y when you want to support this frontend.
|
||||
|
||||
|
@ -163,6 +202,7 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
|
|||
config DVB_NXT200X
|
||||
tristate "NxtWave Communications NXT2002/NXT2004 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
select FW_LOADER
|
||||
help
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
|
@ -177,6 +217,7 @@ config DVB_NXT200X
|
|||
config DVB_OR51211
|
||||
tristate "Oren OR51211 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
select FW_LOADER
|
||||
help
|
||||
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
|
||||
|
@ -189,6 +230,7 @@ config DVB_OR51211
|
|||
config DVB_OR51132
|
||||
tristate "Oren OR51132 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
select FW_LOADER
|
||||
help
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
|
@ -204,6 +246,7 @@ config DVB_OR51132
|
|||
config DVB_BCM3510
|
||||
tristate "Broadcom BCM3510"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
select FW_LOADER
|
||||
help
|
||||
An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
|
||||
|
@ -212,28 +255,52 @@ config DVB_BCM3510
|
|||
config DVB_LGDT330X
|
||||
tristate "LG Electronics LGDT3302/LGDT3303 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
|
||||
comment "Miscellaneous devices"
|
||||
comment "Tuners/PLL support"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_PLL
|
||||
tristate
|
||||
depends on DVB_CORE && I2C
|
||||
|
||||
config DVB_TDA826X
|
||||
tristate "Philips TDA826X silicon tuner"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVB-S silicon tuner module. Say Y when you want to support this tuner.
|
||||
|
||||
config DVB_TUNER_MT2060
|
||||
tristate "Microtune MT2060 silicon IF tuner"
|
||||
help
|
||||
A driver for the silicon IF tuner MT2060 from Microtune.
|
||||
|
||||
comment "Miscellaneous devices"
|
||||
depends on DVB_CORE
|
||||
|
||||
config DVB_LNBP21
|
||||
tristate "LNBP21 SEC controller"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
An SEC control chip.
|
||||
|
||||
config DVB_ISL6421
|
||||
tristate "ISL6421 SEC controller"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
An SEC control chip.
|
||||
|
||||
config DVB_TUA6100
|
||||
tristate "TUA6100 PLL"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DVBS PLL chip.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -11,8 +11,8 @@ obj-$(CONFIG_DVB_CX22700) += cx22700.o
|
|||
obj-$(CONFIG_DVB_CX24110) += cx24110.o
|
||||
obj-$(CONFIG_DVB_TDA8083) += tda8083.o
|
||||
obj-$(CONFIG_DVB_L64781) += l64781.o
|
||||
obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o dib3000-common.o
|
||||
obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dib3000-common.o
|
||||
obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
|
||||
obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
|
||||
obj-$(CONFIG_DVB_MT312) += mt312.o
|
||||
obj-$(CONFIG_DVB_VES1820) += ves1820.o
|
||||
obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
|
||||
|
@ -33,3 +33,7 @@ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
|
|||
obj-$(CONFIG_DVB_CX24123) += cx24123.o
|
||||
obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
|
||||
obj-$(CONFIG_DVB_ISL6421) += isl6421.o
|
||||
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
|
||||
|
|
|
@ -34,7 +34,16 @@ struct bcm3510_config
|
|||
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_BCM3510) || defined(CONFIG_DVB_BCM3510_MODULE)
|
||||
extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_BCM3510
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,16 @@ struct cx22700_config
|
|||
u8 demod_address;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_CX22700) || defined(CONFIG_DVB_CX22700_MODULE)
|
||||
extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_CX22700
|
||||
|
||||
#endif // CX22700_H
|
||||
|
|
|
@ -399,7 +399,9 @@ static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
|
|||
{
|
||||
struct cx22702_state* state = fe->demodulator_priv;
|
||||
|
||||
*signal_strength = cx22702_readreg (state, 0x23);
|
||||
u16 rs_ber = 0;
|
||||
rs_ber = cx22702_readreg (state, 0x23);
|
||||
*signal_strength = (rs_ber << 8) | rs_ber;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,16 @@ struct cx22702_config
|
|||
u8 output_mode;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_CX22702) || defined(CONFIG_DVB_CX22702_MODULE)
|
||||
extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_CX22702
|
||||
|
||||
#endif // CX22702_H
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
cx24110 - Single Chip Satellite Channel Receiver driver module
|
||||
|
||||
Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
|
||||
|
@ -311,16 +311,17 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
|
|||
|
||||
}
|
||||
|
||||
int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
|
||||
static int _cx24110_pll_write (struct dvb_frontend* fe, u8 *buf, int len)
|
||||
{
|
||||
struct cx24110_state *state = fe->demodulator_priv;
|
||||
|
||||
if (len != 3)
|
||||
return -EINVAL;
|
||||
|
||||
/* tuner data is 21 bits long, must be left-aligned in data */
|
||||
/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */
|
||||
/* FIXME (low): add error handling, avoid infinite loops if HW fails... */
|
||||
|
||||
dprintk("cx24110 debug: cx24108_write(%8.8x)\n",data);
|
||||
|
||||
cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */
|
||||
cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */
|
||||
|
||||
|
@ -329,19 +330,19 @@ int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
|
|||
cx24110_writereg(state,0x72,0);
|
||||
|
||||
/* write the topmost 8 bits */
|
||||
cx24110_writereg(state,0x72,(data>>24)&0xff);
|
||||
cx24110_writereg(state,0x72,buf[0]);
|
||||
|
||||
/* wait for the send to be completed */
|
||||
while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
|
||||
;
|
||||
|
||||
/* send another 8 bytes */
|
||||
cx24110_writereg(state,0x72,(data>>16)&0xff);
|
||||
cx24110_writereg(state,0x72,buf[1]);
|
||||
while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
|
||||
;
|
||||
|
||||
/* and the topmost 5 bits of this byte */
|
||||
cx24110_writereg(state,0x72,(data>>8)&0xff);
|
||||
cx24110_writereg(state,0x72,buf[2]);
|
||||
while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
|
||||
;
|
||||
|
||||
|
@ -642,6 +643,7 @@ static struct dvb_frontend_ops cx24110_ops = {
|
|||
.release = cx24110_release,
|
||||
|
||||
.init = cx24110_initfe,
|
||||
.write = _cx24110_pll_write,
|
||||
.set_frontend = cx24110_set_frontend,
|
||||
.get_frontend = cx24110_get_frontend,
|
||||
.read_status = cx24110_read_status,
|
||||
|
@ -664,4 +666,3 @@ MODULE_AUTHOR("Peter Hettkamp");
|
|||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(cx24110_attach);
|
||||
EXPORT_SYMBOL(cx24110_pll_write);
|
||||
|
|
|
@ -33,9 +33,24 @@ struct cx24110_config
|
|||
u8 demod_address;
|
||||
};
|
||||
|
||||
static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) {
|
||||
int r = 0;
|
||||
u8 buf[] = {(u8) (val>>24), (u8) (val>>16), (u8) (val>>8)};
|
||||
if (fe->ops.write)
|
||||
r = fe->ops.write(fe, buf, 3);
|
||||
return r;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DVB_CX24110) || defined(CONFIG_DVB_CX24110_MODULE)
|
||||
extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
|
||||
extern int cx24110_pll_write(struct dvb_frontend* fe, u32 data);
|
||||
#else
|
||||
static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_CX24110
|
||||
|
||||
#endif // CX24110_H
|
||||
|
|
|
@ -45,9 +45,6 @@ struct cx24123_state
|
|||
|
||||
struct dvb_frontend frontend;
|
||||
|
||||
u32 lastber;
|
||||
u16 snr;
|
||||
|
||||
/* Some PLL specifics for tuning */
|
||||
u32 VCAarg;
|
||||
u32 VGAarg;
|
||||
|
@ -194,7 +191,7 @@ static struct {
|
|||
{0x06, 0x31}, /* MPEG (default) */
|
||||
{0x0b, 0x00}, /* Freq search start point (default) */
|
||||
{0x0c, 0x00}, /* Demodulator sample gain (default) */
|
||||
{0x0d, 0x02}, /* Frequency search range = Fsymbol / 4 (default) */
|
||||
{0x0d, 0x7f}, /* Force driver to shift until the maximum (+-10 MHz) */
|
||||
{0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */
|
||||
{0x0f, 0xfe}, /* FEC search mask (all supported codes) */
|
||||
{0x10, 0x01}, /* Default search inversion, no repeat (default) */
|
||||
|
@ -223,8 +220,9 @@ static struct {
|
|||
{0x44, 0x00}, /* Constellation (default) */
|
||||
{0x45, 0x00}, /* Symbol count (default) */
|
||||
{0x46, 0x0d}, /* Symbol rate estimator on (default) */
|
||||
{0x56, 0x41}, /* Various (default) */
|
||||
{0x56, 0xc1}, /* Error Counter = Viterbi BER */
|
||||
{0x57, 0xff}, /* Error Counter Window (default) */
|
||||
{0x5c, 0x20}, /* Acquisition AFC Expiration window (default is 0x10) */
|
||||
{0x67, 0x83}, /* Non-DCII symbol clock */
|
||||
};
|
||||
|
||||
|
@ -321,6 +319,12 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
|
|||
if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
|
||||
fec = FEC_AUTO;
|
||||
|
||||
/* Set the soft decision threshold */
|
||||
if(fec == FEC_1_2)
|
||||
cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) | 0x01);
|
||||
else
|
||||
cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) & ~0x01);
|
||||
|
||||
switch (fec) {
|
||||
case FEC_1_2:
|
||||
dprintk("%s: set FEC to 1/2\n",__FUNCTION__);
|
||||
|
@ -657,6 +661,10 @@ static int cx24123_initfe(struct dvb_frontend* fe)
|
|||
for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
|
||||
cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
|
||||
|
||||
/* Set the LNB polarity */
|
||||
if(state->config->lnb_polarity)
|
||||
cx24123_writereg(state, 0x32, cx24123_readreg(state, 0x32) | 0x02);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -674,6 +682,9 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
|
|||
case SEC_VOLTAGE_18:
|
||||
dprintk("%s: setting voltage 18V\n", __FUNCTION__);
|
||||
return cx24123_writereg(state, 0x29, val | 0x80);
|
||||
case SEC_VOLTAGE_OFF:
|
||||
/* already handled in cx88-dvb */
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
|
@ -776,13 +787,15 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
|||
if (lock & 0x01)
|
||||
*status |= FE_HAS_SIGNAL;
|
||||
if (sync & 0x02)
|
||||
*status |= FE_HAS_CARRIER;
|
||||
*status |= FE_HAS_CARRIER; /* Phase locked */
|
||||
if (sync & 0x04)
|
||||
*status |= FE_HAS_VITERBI;
|
||||
|
||||
/* Reed-Solomon Status */
|
||||
if (sync & 0x08)
|
||||
*status |= FE_HAS_SYNC;
|
||||
if (sync & 0x80)
|
||||
*status |= FE_HAS_LOCK;
|
||||
*status |= FE_HAS_LOCK; /*Full Sync */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -795,29 +808,13 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
|
|||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
|
||||
state->lastber =
|
||||
((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
|
||||
/* The true bit error rate is this value divided by
|
||||
the window size (set as 256 * 255) */
|
||||
*ber = ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
|
||||
(cx24123_readreg(state, 0x1d) << 8 |
|
||||
cx24123_readreg(state, 0x1e));
|
||||
cx24123_readreg(state, 0x1e));
|
||||
|
||||
/* Do the signal quality processing here, it's derived from the BER. */
|
||||
/* Scale the BER from a 24bit to a SNR 16 bit where higher = better */
|
||||
if (state->lastber < 5000)
|
||||
state->snr = 655*100;
|
||||
else if ( (state->lastber >= 5000) && (state->lastber < 55000) )
|
||||
state->snr = 655*90;
|
||||
else if ( (state->lastber >= 55000) && (state->lastber < 150000) )
|
||||
state->snr = 655*80;
|
||||
else if ( (state->lastber >= 150000) && (state->lastber < 250000) )
|
||||
state->snr = 655*70;
|
||||
else if ( (state->lastber >= 250000) && (state->lastber < 450000) )
|
||||
state->snr = 655*65;
|
||||
else
|
||||
state->snr = 0;
|
||||
|
||||
dprintk("%s: BER = %d, S/N index = %d\n",__FUNCTION__,state->lastber, state->snr);
|
||||
|
||||
*ber = state->lastber;
|
||||
dprintk("%s: BER = %d\n",__FUNCTION__,*ber);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -825,6 +822,7 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber)
|
|||
static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
|
||||
*signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */
|
||||
|
||||
dprintk("%s: Signal strength = %d\n",__FUNCTION__,*signal_strength);
|
||||
|
@ -835,23 +833,17 @@ static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
|
|||
static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
*snr = state->snr;
|
||||
|
||||
/* Inverted raw Es/N0 count, totally bogus but better than the
|
||||
BER threshold. */
|
||||
*snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) |
|
||||
(u16)cx24123_readreg(state, 0x19));
|
||||
|
||||
dprintk("%s: read S/N index = %d\n",__FUNCTION__,*snr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
*ucblocks = state->lastber;
|
||||
|
||||
dprintk("%s: ucblocks (ber) = %d\n",__FUNCTION__,*ucblocks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
|
||||
{
|
||||
struct cx24123_state *state = fe->demodulator_priv;
|
||||
|
@ -922,6 +914,29 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cx24123_tune(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters* params,
|
||||
unsigned int mode_flags,
|
||||
int *delay,
|
||||
fe_status_t *status)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (params != NULL)
|
||||
retval = cx24123_set_frontend(fe, params);
|
||||
|
||||
if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
|
||||
cx24123_read_status(fe, status);
|
||||
*delay = HZ/10;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int cx24123_get_algo(struct dvb_frontend *fe)
|
||||
{
|
||||
return 1; //FE_ALGO_HW
|
||||
}
|
||||
|
||||
static void cx24123_release(struct dvb_frontend* fe)
|
||||
{
|
||||
struct cx24123_state* state = fe->demodulator_priv;
|
||||
|
@ -949,8 +964,6 @@ struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
|
|||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
state->lastber = 0;
|
||||
state->snr = 0;
|
||||
state->VCAarg = 0;
|
||||
state->VGAarg = 0;
|
||||
state->bandselectarg = 0;
|
||||
|
@ -1003,11 +1016,12 @@ static struct dvb_frontend_ops cx24123_ops = {
|
|||
.read_ber = cx24123_read_ber,
|
||||
.read_signal_strength = cx24123_read_signal_strength,
|
||||
.read_snr = cx24123_read_snr,
|
||||
.read_ucblocks = cx24123_read_ucblocks,
|
||||
.diseqc_send_master_cmd = cx24123_send_diseqc_msg,
|
||||
.diseqc_send_burst = cx24123_diseqc_send_burst,
|
||||
.set_tone = cx24123_set_tone,
|
||||
.set_voltage = cx24123_set_voltage,
|
||||
.tune = cx24123_tune,
|
||||
.get_frontend_algo = cx24123_get_algo,
|
||||
};
|
||||
|
||||
module_param(debug, int, 0644);
|
||||
|
|
|
@ -30,9 +30,21 @@ struct cx24123_config
|
|||
|
||||
/* Need to set device param for start_dma */
|
||||
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
|
||||
|
||||
/* 0 = LNB voltage normal, 1 = LNB voltage inverted */
|
||||
int lnb_polarity;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_CX24123) || defined(CONFIG_DVB_CX24123_MODULE)
|
||||
extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_CX24123
|
||||
|
||||
#endif /* CX24123_H */
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
#include "dib3000-common.h"
|
||||
|
||||
#ifdef CONFIG_DVB_DIBCOM_DEBUG
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
|
||||
#endif
|
||||
#define deb_info(args...) dprintk(0x01,args)
|
||||
#define deb_i2c(args...) dprintk(0x02,args)
|
||||
#define deb_srch(args...) dprintk(0x04,args)
|
||||
|
||||
|
||||
int dib3000_read_reg(struct dib3000_state *state, u16 reg)
|
||||
{
|
||||
u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
|
||||
u8 rb[2];
|
||||
struct i2c_msg msg[] = {
|
||||
{ .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 },
|
||||
{ .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
|
||||
};
|
||||
|
||||
if (i2c_transfer(state->i2c, msg, 2) != 2)
|
||||
deb_i2c("i2c read error\n");
|
||||
|
||||
deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
|
||||
(rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);
|
||||
|
||||
return (rb[0] << 8) | rb[1];
|
||||
}
|
||||
|
||||
int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg[] = {
|
||||
{ .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }
|
||||
};
|
||||
deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);
|
||||
|
||||
return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
int dib3000_search_status(u16 irq,u16 lock)
|
||||
{
|
||||
if (irq & 0x02) {
|
||||
if (lock & 0x01) {
|
||||
deb_srch("auto search succeeded\n");
|
||||
return 1; // auto search succeeded
|
||||
} else {
|
||||
deb_srch("auto search not successful\n");
|
||||
return 0; // auto search failed
|
||||
}
|
||||
} else if (irq & 0x01) {
|
||||
deb_srch("auto search failed\n");
|
||||
return 0; // auto search failed
|
||||
}
|
||||
return -1; // try again
|
||||
}
|
||||
|
||||
/* for auto search */
|
||||
u16 dib3000_seq[2][2][2] = /* fft,gua, inv */
|
||||
{ /* fft */
|
||||
{ /* gua */
|
||||
{ 0, 1 }, /* 0 0 { 0,1 } */
|
||||
{ 3, 9 }, /* 0 1 { 0,1 } */
|
||||
},
|
||||
{
|
||||
{ 2, 5 }, /* 1 0 { 0,1 } */
|
||||
{ 6, 11 }, /* 1 1 { 0,1 } */
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
|
||||
MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(dib3000_seq);
|
||||
|
||||
EXPORT_SYMBOL(dib3000_read_reg);
|
||||
EXPORT_SYMBOL(dib3000_write_reg);
|
||||
EXPORT_SYMBOL(dib3000_search_status);
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* .h-files for the common use of the frontend drivers made by DiBcom
|
||||
* DiBcom 3000M-B/C, 3000P
|
||||
*
|
||||
* DiBcom (http://www.dibcom.fr/)
|
||||
*
|
||||
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
|
||||
*
|
||||
* based on GPL code from DibCom, which has
|
||||
*
|
||||
* Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.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, version 2.
|
||||
*
|
||||
* Acknowledgements
|
||||
*
|
||||
* Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
|
||||
* sources, on which this driver (and the dvb-dibusb) are based.
|
||||
*
|
||||
* see Documentation/dvb/README.dibusb for more information
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DIB3000_COMMON_H
|
||||
#define DIB3000_COMMON_H
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "dib3000.h"
|
||||
|
||||
/* info and err, taken from usb.h, if there is anything available like by default. */
|
||||
#define err(format, arg...) printk(KERN_ERR "dib3000: " format "\n" , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "dib3000: " format "\n" , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
|
||||
|
||||
/* frontend state */
|
||||
struct dib3000_state {
|
||||
struct i2c_adapter* i2c;
|
||||
|
||||
/* configuration settings */
|
||||
struct dib3000_config config;
|
||||
|
||||
struct dvb_frontend frontend;
|
||||
int timing_offset;
|
||||
int timing_offset_comp_done;
|
||||
|
||||
fe_bandwidth_t last_tuned_bw;
|
||||
u32 last_tuned_freq;
|
||||
};
|
||||
|
||||
/* commonly used methods by the dib3000mb/mc/p frontend */
|
||||
extern int dib3000_read_reg(struct dib3000_state *state, u16 reg);
|
||||
extern int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val);
|
||||
|
||||
extern int dib3000_search_status(u16 irq,u16 lock);
|
||||
|
||||
/* handy shortcuts */
|
||||
#define rd(reg) dib3000_read_reg(state,reg)
|
||||
|
||||
#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
|
||||
{ err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
|
||||
|
||||
#define wr_foreach(a,v) { int i; \
|
||||
if (sizeof(a) != sizeof(v)) \
|
||||
err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
|
||||
for (i=0; i < sizeof(a)/sizeof(u16); i++) \
|
||||
wr(a[i],v[i]); \
|
||||
}
|
||||
|
||||
#define set_or(reg,val) wr(reg,rd(reg) | val)
|
||||
|
||||
#define set_and(reg,val) wr(reg,rd(reg) & val)
|
||||
|
||||
|
||||
/* debug */
|
||||
|
||||
#ifdef CONFIG_DVB_DIBCOM_DEBUG
|
||||
#define dprintk(level,args...) \
|
||||
do { if ((debug & level)) { printk(args); } } while (0)
|
||||
#else
|
||||
#define dprintk(args...) do { } while (0)
|
||||
#endif
|
||||
|
||||
/* mask for enabling a specific pid for the pid_filter */
|
||||
#define DIB3000_ACTIVATE_PID_FILTERING (0x2000)
|
||||
|
||||
/* common values for tuning */
|
||||
#define DIB3000_ALPHA_0 ( 0)
|
||||
#define DIB3000_ALPHA_1 ( 1)
|
||||
#define DIB3000_ALPHA_2 ( 2)
|
||||
#define DIB3000_ALPHA_4 ( 4)
|
||||
|
||||
#define DIB3000_CONSTELLATION_QPSK ( 0)
|
||||
#define DIB3000_CONSTELLATION_16QAM ( 1)
|
||||
#define DIB3000_CONSTELLATION_64QAM ( 2)
|
||||
|
||||
#define DIB3000_GUARD_TIME_1_32 ( 0)
|
||||
#define DIB3000_GUARD_TIME_1_16 ( 1)
|
||||
#define DIB3000_GUARD_TIME_1_8 ( 2)
|
||||
#define DIB3000_GUARD_TIME_1_4 ( 3)
|
||||
|
||||
#define DIB3000_TRANSMISSION_MODE_2K ( 0)
|
||||
#define DIB3000_TRANSMISSION_MODE_8K ( 1)
|
||||
|
||||
#define DIB3000_SELECT_LP ( 0)
|
||||
#define DIB3000_SELECT_HP ( 1)
|
||||
|
||||
#define DIB3000_FEC_1_2 ( 1)
|
||||
#define DIB3000_FEC_2_3 ( 2)
|
||||
#define DIB3000_FEC_3_4 ( 3)
|
||||
#define DIB3000_FEC_5_6 ( 5)
|
||||
#define DIB3000_FEC_7_8 ( 7)
|
||||
|
||||
#define DIB3000_HRCH_OFF ( 0)
|
||||
#define DIB3000_HRCH_ON ( 1)
|
||||
|
||||
#define DIB3000_DDS_INVERSION_OFF ( 0)
|
||||
#define DIB3000_DDS_INVERSION_ON ( 1)
|
||||
|
||||
#define DIB3000_TUNER_WRITE_ENABLE(a) (0xffff & (a << 8))
|
||||
#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7)))
|
||||
|
||||
/* for auto search */
|
||||
extern u16 dib3000_seq[2][2][2];
|
||||
|
||||
#define DIB3000_REG_MANUFACTOR_ID ( 1025)
|
||||
#define DIB3000_I2C_ID_DIBCOM (0x01b3)
|
||||
|
||||
#define DIB3000_REG_DEVICE_ID ( 1026)
|
||||
#define DIB3000MB_DEVICE_ID (0x3000)
|
||||
#define DIB3000MC_DEVICE_ID (0x3001)
|
||||
#define DIB3000P_DEVICE_ID (0x3002)
|
||||
|
||||
#endif // DIB3000_COMMON_H
|
|
@ -41,9 +41,16 @@ struct dib_fe_xfer_ops
|
|||
int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_DIB3000MB) || defined(CONFIG_DVB_DIB3000MB_MODULE)
|
||||
extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
|
||||
struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
|
||||
#else
|
||||
static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
|
||||
struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_DIB3000MB
|
||||
|
||||
extern struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
|
||||
struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
|
||||
#endif // DIB3000_H
|
||||
|
|
|
@ -29,9 +29,10 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "dib3000-common.h"
|
||||
#include "dib3000mb_priv.h"
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
#include "dib3000.h"
|
||||
#include "dib3000mb_priv.h"
|
||||
|
||||
/* Version information */
|
||||
#define DRIVER_VERSION "0.1"
|
||||
|
@ -44,10 +45,81 @@ module_param(debug, int, 0644);
|
|||
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");
|
||||
#endif
|
||||
#define deb_info(args...) dprintk(0x01,args)
|
||||
#define deb_i2c(args...) dprintk(0x02,args)
|
||||
#define deb_srch(args...) dprintk(0x04,args)
|
||||
#define deb_info(args...) dprintk(0x01,args)
|
||||
#define deb_xfer(args...) dprintk(0x02,args)
|
||||
#define deb_setf(args...) dprintk(0x04,args)
|
||||
#define deb_getf(args...) dprintk(0x08,args)
|
||||
|
||||
#ifdef CONFIG_DVB_DIBCOM_DEBUG
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
|
||||
#endif
|
||||
|
||||
static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
|
||||
{
|
||||
u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
|
||||
u8 rb[2];
|
||||
struct i2c_msg msg[] = {
|
||||
{ .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 },
|
||||
{ .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
|
||||
};
|
||||
|
||||
if (i2c_transfer(state->i2c, msg, 2) != 2)
|
||||
deb_i2c("i2c read error\n");
|
||||
|
||||
deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
|
||||
(rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);
|
||||
|
||||
return (rb[0] << 8) | rb[1];
|
||||
}
|
||||
|
||||
static int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg[] = {
|
||||
{ .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }
|
||||
};
|
||||
deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);
|
||||
|
||||
return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
static int dib3000_search_status(u16 irq,u16 lock)
|
||||
{
|
||||
if (irq & 0x02) {
|
||||
if (lock & 0x01) {
|
||||
deb_srch("auto search succeeded\n");
|
||||
return 1; // auto search succeeded
|
||||
} else {
|
||||
deb_srch("auto search not successful\n");
|
||||
return 0; // auto search failed
|
||||
}
|
||||
} else if (irq & 0x01) {
|
||||
deb_srch("auto search failed\n");
|
||||
return 0; // auto search failed
|
||||
}
|
||||
return -1; // try again
|
||||
}
|
||||
|
||||
/* for auto search */
|
||||
static u16 dib3000_seq[2][2][2] = /* fft,gua, inv */
|
||||
{ /* fft */
|
||||
{ /* gua */
|
||||
{ 0, 1 }, /* 0 0 { 0,1 } */
|
||||
{ 3, 9 }, /* 0 1 { 0,1 } */
|
||||
},
|
||||
{
|
||||
{ 2, 5 }, /* 1 0 { 0,1 } */
|
||||
{ 6, 11 }, /* 1 1 { 0,1 } */
|
||||
}
|
||||
};
|
||||
|
||||
static int dib3000mb_get_frontend(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters *fep);
|
||||
|
||||
|
|
|
@ -13,6 +13,99 @@
|
|||
#ifndef __DIB3000MB_PRIV_H_INCLUDED__
|
||||
#define __DIB3000MB_PRIV_H_INCLUDED__
|
||||
|
||||
/* info and err, taken from usb.h, if there is anything available like by default. */
|
||||
#define err(format, arg...) printk(KERN_ERR "dib3000: " format "\n" , ## arg)
|
||||
#define info(format, arg...) printk(KERN_INFO "dib3000: " format "\n" , ## arg)
|
||||
#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
|
||||
|
||||
/* handy shortcuts */
|
||||
#define rd(reg) dib3000_read_reg(state,reg)
|
||||
|
||||
#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
|
||||
{ err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
|
||||
|
||||
#define wr_foreach(a,v) { int i; \
|
||||
if (sizeof(a) != sizeof(v)) \
|
||||
err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
|
||||
for (i=0; i < sizeof(a)/sizeof(u16); i++) \
|
||||
wr(a[i],v[i]); \
|
||||
}
|
||||
|
||||
#define set_or(reg,val) wr(reg,rd(reg) | val)
|
||||
|
||||
#define set_and(reg,val) wr(reg,rd(reg) & val)
|
||||
|
||||
/* debug */
|
||||
|
||||
#ifdef CONFIG_DVB_DIBCOM_DEBUG
|
||||
#define dprintk(level,args...) \
|
||||
do { if ((debug & level)) { printk(args); } } while (0)
|
||||
#else
|
||||
#define dprintk(args...) do { } while (0)
|
||||
#endif
|
||||
|
||||
/* mask for enabling a specific pid for the pid_filter */
|
||||
#define DIB3000_ACTIVATE_PID_FILTERING (0x2000)
|
||||
|
||||
/* common values for tuning */
|
||||
#define DIB3000_ALPHA_0 ( 0)
|
||||
#define DIB3000_ALPHA_1 ( 1)
|
||||
#define DIB3000_ALPHA_2 ( 2)
|
||||
#define DIB3000_ALPHA_4 ( 4)
|
||||
|
||||
#define DIB3000_CONSTELLATION_QPSK ( 0)
|
||||
#define DIB3000_CONSTELLATION_16QAM ( 1)
|
||||
#define DIB3000_CONSTELLATION_64QAM ( 2)
|
||||
|
||||
#define DIB3000_GUARD_TIME_1_32 ( 0)
|
||||
#define DIB3000_GUARD_TIME_1_16 ( 1)
|
||||
#define DIB3000_GUARD_TIME_1_8 ( 2)
|
||||
#define DIB3000_GUARD_TIME_1_4 ( 3)
|
||||
|
||||
#define DIB3000_TRANSMISSION_MODE_2K ( 0)
|
||||
#define DIB3000_TRANSMISSION_MODE_8K ( 1)
|
||||
|
||||
#define DIB3000_SELECT_LP ( 0)
|
||||
#define DIB3000_SELECT_HP ( 1)
|
||||
|
||||
#define DIB3000_FEC_1_2 ( 1)
|
||||
#define DIB3000_FEC_2_3 ( 2)
|
||||
#define DIB3000_FEC_3_4 ( 3)
|
||||
#define DIB3000_FEC_5_6 ( 5)
|
||||
#define DIB3000_FEC_7_8 ( 7)
|
||||
|
||||
#define DIB3000_HRCH_OFF ( 0)
|
||||
#define DIB3000_HRCH_ON ( 1)
|
||||
|
||||
#define DIB3000_DDS_INVERSION_OFF ( 0)
|
||||
#define DIB3000_DDS_INVERSION_ON ( 1)
|
||||
|
||||
#define DIB3000_TUNER_WRITE_ENABLE(a) (0xffff & (a << 8))
|
||||
#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7)))
|
||||
|
||||
#define DIB3000_REG_MANUFACTOR_ID ( 1025)
|
||||
#define DIB3000_I2C_ID_DIBCOM (0x01b3)
|
||||
|
||||
#define DIB3000_REG_DEVICE_ID ( 1026)
|
||||
#define DIB3000MB_DEVICE_ID (0x3000)
|
||||
#define DIB3000MC_DEVICE_ID (0x3001)
|
||||
#define DIB3000P_DEVICE_ID (0x3002)
|
||||
|
||||
/* frontend state */
|
||||
struct dib3000_state {
|
||||
struct i2c_adapter* i2c;
|
||||
|
||||
/* configuration settings */
|
||||
struct dib3000_config config;
|
||||
|
||||
struct dvb_frontend frontend;
|
||||
int timing_offset;
|
||||
int timing_offset_comp_done;
|
||||
|
||||
fe_bandwidth_t last_tuned_bw;
|
||||
u32 last_tuned_freq;
|
||||
};
|
||||
|
||||
/* register addresses and some of their default values */
|
||||
|
||||
/* restart subsystems */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Driver for DiBcom DiB3000MC/P-demodulator.
|
||||
*
|
||||
* Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
|
||||
* Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher\@desy.de)
|
||||
*
|
||||
* This code is partially based on the previous dib3000mc.c .
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef DIB3000MC_H
|
||||
#define DIB3000MC_H
|
||||
|
||||
#include "dibx000_common.h"
|
||||
|
||||
struct dib3000mc_config {
|
||||
struct dibx000_agc_config *agc;
|
||||
|
||||
u8 phase_noise_mode;
|
||||
u8 impulse_noise_mode;
|
||||
|
||||
u8 pwm3_inversion;
|
||||
u8 use_pwm3;
|
||||
u16 pwm3_value;
|
||||
|
||||
u16 max_time;
|
||||
u16 ln_adc_level;
|
||||
|
||||
u8 mobile_mode;
|
||||
|
||||
u8 output_mpeg2_in_188_bytes;
|
||||
};
|
||||
|
||||
#define DEFAULT_DIB3000MC_I2C_ADDRESS 16
|
||||
#define DEFAULT_DIB3000P_I2C_ADDRESS 24
|
||||
|
||||
#if defined(CONFIG_DVB_DIB3000MC) || defined(CONFIG_DVB_DIB3000MC_MODULE)
|
||||
extern int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr,
|
||||
u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[]);
|
||||
#else
|
||||
static inline struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
|
||||
struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_DIB3000MC
|
||||
|
||||
extern struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating);
|
||||
|
||||
extern int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff);
|
||||
extern int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff);
|
||||
|
||||
extern void dib3000mc_set_config(struct dvb_frontend *, struct dib3000mc_config *);
|
||||
|
||||
#endif
|
|
@ -1,428 +0,0 @@
|
|||
/*
|
||||
* dib3000mc_priv.h
|
||||
*
|
||||
* Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.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.
|
||||
*
|
||||
* for more information see dib3000mc.c .
|
||||
*/
|
||||
|
||||
#ifndef __DIB3000MC_PRIV_H__
|
||||
#define __DIB3000MC_PRIV_H__
|
||||
|
||||
/*
|
||||
* Demodulator parameters
|
||||
* reg: 0 1 1 1 11 11 111
|
||||
* | | | | | |
|
||||
* | | | | | +-- alpha (000=0, 001=1, 010=2, 100=4)
|
||||
* | | | | +----- constellation (00=QPSK, 01=16QAM, 10=64QAM)
|
||||
* | | | +-------- guard (00=1/32, 01=1/16, 10=1/8, 11=1/4)
|
||||
* | | +----------- transmission mode (0=2k, 1=8k)
|
||||
* | |
|
||||
* | +-------------- restart autosearch for parameters
|
||||
* +---------------- restart the demodulator
|
||||
* reg: 181 1 111 1
|
||||
* | | |
|
||||
* | | +- FEC applies for HP or LP (0=LP, 1=HP)
|
||||
* | +---- FEC rate (001=1/2, 010=2/3, 011=3/4, 101=5/6, 111=7/8)
|
||||
* +------- hierarchy on (0=no, 1=yes)
|
||||
*/
|
||||
|
||||
/* demodulator tuning parameter and restart options */
|
||||
#define DIB3000MC_REG_DEMOD_PARM ( 0)
|
||||
#define DIB3000MC_DEMOD_PARM(a,c,g,t) ( \
|
||||
(0x7 & a) | \
|
||||
((0x3 & c) << 3) | \
|
||||
((0x3 & g) << 5) | \
|
||||
((0x1 & t) << 7) )
|
||||
#define DIB3000MC_DEMOD_RST_AUTO_SRCH_ON (1 << 8)
|
||||
#define DIB3000MC_DEMOD_RST_AUTO_SRCH_OFF (0 << 8)
|
||||
#define DIB3000MC_DEMOD_RST_DEMOD_ON (1 << 9)
|
||||
#define DIB3000MC_DEMOD_RST_DEMOD_OFF (0 << 9)
|
||||
|
||||
/* register for hierarchy parameters */
|
||||
#define DIB3000MC_REG_HRCH_PARM ( 181)
|
||||
#define DIB3000MC_HRCH_PARM(s,f,h) ( \
|
||||
(0x1 & s) | \
|
||||
((0x7 & f) << 1) | \
|
||||
((0x1 & h) << 4) )
|
||||
|
||||
/* timeout ??? */
|
||||
#define DIB3000MC_REG_UNK_1 ( 1)
|
||||
#define DIB3000MC_UNK_1 ( 0x04)
|
||||
|
||||
/* timeout ??? */
|
||||
#define DIB3000MC_REG_UNK_2 ( 2)
|
||||
#define DIB3000MC_UNK_2 ( 0x04)
|
||||
|
||||
/* timeout ??? */
|
||||
#define DIB3000MC_REG_UNK_3 ( 3)
|
||||
#define DIB3000MC_UNK_3 (0x1000)
|
||||
|
||||
#define DIB3000MC_REG_UNK_4 ( 4)
|
||||
#define DIB3000MC_UNK_4 (0x0814)
|
||||
|
||||
/* timeout ??? */
|
||||
#define DIB3000MC_REG_SEQ_TPS ( 5)
|
||||
#define DIB3000MC_SEQ_TPS_DEFAULT ( 1)
|
||||
#define DIB3000MC_SEQ_TPS(s,t) ( \
|
||||
((s & 0x0f) << 4) | \
|
||||
((t & 0x01) << 8) )
|
||||
#define DIB3000MC_IS_TPS(v) ((v << 8) & 0x1)
|
||||
#define DIB3000MC_IS_AS(v) ((v >> 4) & 0xf)
|
||||
|
||||
/* parameters for the bandwidth */
|
||||
#define DIB3000MC_REG_BW_TIMOUT_MSB ( 6)
|
||||
#define DIB3000MC_REG_BW_TIMOUT_LSB ( 7)
|
||||
|
||||
static u16 dib3000mc_reg_bandwidth[] = { 6,7,8,9,10,11,16,17 };
|
||||
|
||||
/*static u16 dib3000mc_bandwidth_5mhz[] =
|
||||
{ 0x28, 0x9380, 0x87, 0x4100, 0x2a4, 0x4500, 0x1, 0xb0d0 };*/
|
||||
|
||||
static u16 dib3000mc_bandwidth_6mhz[] =
|
||||
{ 0x21, 0xd040, 0x70, 0xb62b, 0x233, 0x8ed5, 0x1, 0xb0d0 };
|
||||
|
||||
static u16 dib3000mc_bandwidth_7mhz[] =
|
||||
{ 0x1c, 0xfba5, 0x60, 0x9c25, 0x1e3, 0x0cb7, 0x1, 0xb0d0 };
|
||||
|
||||
static u16 dib3000mc_bandwidth_8mhz[] =
|
||||
{ 0x19, 0x5c30, 0x54, 0x88a0, 0x1a6, 0xab20, 0x1, 0xb0d0 };
|
||||
|
||||
static u16 dib3000mc_reg_bandwidth_general[] = { 12,13,14,15 };
|
||||
static u16 dib3000mc_bandwidth_general[] = { 0x0000, 0x03e8, 0x0000, 0x03f2 };
|
||||
|
||||
/* lock mask */
|
||||
#define DIB3000MC_REG_LOCK_MASK ( 15)
|
||||
#define DIB3000MC_ACTIVATE_LOCK_MASK (0x0800)
|
||||
|
||||
/* reset the uncorrected packet count (??? do it 5 times) */
|
||||
#define DIB3000MC_REG_RST_UNC ( 18)
|
||||
#define DIB3000MC_RST_UNC_ON ( 1)
|
||||
#define DIB3000MC_RST_UNC_OFF ( 0)
|
||||
|
||||
#define DIB3000MC_REG_UNK_19 ( 19)
|
||||
#define DIB3000MC_UNK_19 ( 0)
|
||||
|
||||
/* DDS frequency value (IF position) and inversion bit */
|
||||
#define DIB3000MC_REG_INVERSION ( 21)
|
||||
#define DIB3000MC_REG_SET_DDS_FREQ_MSB ( 21)
|
||||
#define DIB3000MC_DDS_FREQ_MSB_INV_OFF (0x0164)
|
||||
#define DIB3000MC_DDS_FREQ_MSB_INV_ON (0x0364)
|
||||
|
||||
#define DIB3000MC_REG_SET_DDS_FREQ_LSB ( 22)
|
||||
#define DIB3000MC_DDS_FREQ_LSB (0x463d)
|
||||
|
||||
/* timing frequencies setting */
|
||||
#define DIB3000MC_REG_TIMING_FREQ_MSB ( 23)
|
||||
#define DIB3000MC_REG_TIMING_FREQ_LSB ( 24)
|
||||
#define DIB3000MC_CLOCK_REF (0x151fd1)
|
||||
|
||||
//static u16 dib3000mc_reg_timing_freq[] = { 23,24 };
|
||||
|
||||
//static u16 dib3000mc_timing_freq[][2] = {
|
||||
// { 0x69, 0x9f18 }, /* 5 MHz */
|
||||
// { 0x7e ,0xbee9 }, /* 6 MHz */
|
||||
// { 0x93 ,0xdebb }, /* 7 MHz */
|
||||
// { 0xa8 ,0xfe8c }, /* 8 MHz */
|
||||
//};
|
||||
|
||||
/* timeout ??? */
|
||||
static u16 dib3000mc_reg_offset[] = { 26,33 };
|
||||
|
||||
static u16 dib3000mc_offset[][2] = {
|
||||
{ 26240, 5 }, /* default */
|
||||
{ 30336, 6 }, /* 8K */
|
||||
{ 38528, 8 }, /* 2K */
|
||||
};
|
||||
|
||||
#define DIB3000MC_REG_ISI ( 29)
|
||||
#define DIB3000MC_ISI_DEFAULT (0x1073)
|
||||
#define DIB3000MC_ISI_ACTIVATE (0x0000)
|
||||
#define DIB3000MC_ISI_INHIBIT (0x0200)
|
||||
|
||||
/* impulse noise control */
|
||||
static u16 dib3000mc_reg_imp_noise_ctl[] = { 34,35 };
|
||||
|
||||
static u16 dib3000mc_imp_noise_ctl[][2] = {
|
||||
{ 0x1294, 0x1ff8 }, /* mode 0 */
|
||||
{ 0x1294, 0x1ff8 }, /* mode 1 */
|
||||
{ 0x1294, 0x1ff8 }, /* mode 2 */
|
||||
{ 0x1294, 0x1ff8 }, /* mode 3 */
|
||||
{ 0x1294, 0x1ff8 }, /* mode 4 */
|
||||
};
|
||||
|
||||
/* AGC registers */
|
||||
static u16 dib3000mc_reg_agc[] = {
|
||||
36,37,38,39,42,43,44,45,46,47,48,49
|
||||
};
|
||||
|
||||
static u16 dib3000mc_agc_tuner[][12] = {
|
||||
{ 0x0051, 0x301d, 0x0000, 0x1cc7, 0xcf5c, 0x6666,
|
||||
0xbae1, 0xa148, 0x3b5e, 0x3c1c, 0x001a, 0x2019
|
||||
}, /* TUNER_PANASONIC_ENV77H04D5, */
|
||||
|
||||
{ 0x0051, 0x301d, 0x0000, 0x1cc7, 0xdc29, 0x570a,
|
||||
0xbae1, 0x8ccd, 0x3b6d, 0x551d, 0x000a, 0x951e
|
||||
}, /* TUNER_PANASONIC_ENV57H13D5, TUNER_PANASONIC_ENV57H12D5 */
|
||||
|
||||
{ 0x0051, 0x301d, 0x0000, 0x1cc7, 0xffff, 0xffff,
|
||||
0xffff, 0x0000, 0xfdfd, 0x4040, 0x00fd, 0x4040
|
||||
}, /* TUNER_SAMSUNG_DTOS333IH102, TUNER_RFAGCIN_UNKNOWN */
|
||||
|
||||
{ 0x0196, 0x301d, 0x0000, 0x1cc7, 0xbd71, 0x5c29,
|
||||
0xb5c3, 0x6148, 0x6569, 0x5127, 0x0033, 0x3537
|
||||
}, /* TUNER_PROVIDER_X */
|
||||
/* TODO TUNER_PANASONIC_ENV57H10D8, TUNER_PANASONIC_ENV57H11D8 */
|
||||
};
|
||||
|
||||
/* AGC loop bandwidth */
|
||||
static u16 dib3000mc_reg_agc_bandwidth[] = { 40,41 };
|
||||
static u16 dib3000mc_agc_bandwidth[] = { 0x119,0x330 };
|
||||
|
||||
static u16 dib3000mc_reg_agc_bandwidth_general[] = { 50,51,52,53,54 };
|
||||
static u16 dib3000mc_agc_bandwidth_general[] =
|
||||
{ 0x8000, 0x91ca, 0x01ba, 0x0087, 0x0087 };
|
||||
|
||||
#define DIB3000MC_REG_IMP_NOISE_55 ( 55)
|
||||
#define DIB3000MC_IMP_NEW_ALGO(w) (w | (1<<10))
|
||||
|
||||
/* Impulse noise params */
|
||||
static u16 dib3000mc_reg_impulse_noise[] = { 55,56,57 };
|
||||
static u16 dib3000mc_impluse_noise[][3] = {
|
||||
{ 0x489, 0x89, 0x72 }, /* 5 MHz */
|
||||
{ 0x4a5, 0xa5, 0x89 }, /* 6 MHz */
|
||||
{ 0x4c0, 0xc0, 0xa0 }, /* 7 MHz */
|
||||
{ 0x4db, 0xdb, 0xb7 }, /* 8 Mhz */
|
||||
};
|
||||
|
||||
static u16 dib3000mc_reg_fft[] = {
|
||||
58,59,60,61,62,63,64,65,66,67,68,69,
|
||||
70,71,72,73,74,75,76,77,78,79,80,81,
|
||||
82,83,84,85,86
|
||||
};
|
||||
|
||||
static u16 dib3000mc_fft_modes[][29] = {
|
||||
{ 0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c,
|
||||
0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d,
|
||||
0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3,
|
||||
0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
|
||||
0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0, 0xd
|
||||
}, /* fft mode 0 */
|
||||
{ 0x3b, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c,
|
||||
0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d,
|
||||
0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3,
|
||||
0x3feb, 0x7d2, 0x365e, 0x76, 0x48c,
|
||||
0x3ffe, 0x5b3, 0x3feb, 0x0, 0x8200, 0xd
|
||||
}, /* fft mode 1 */
|
||||
};
|
||||
|
||||
#define DIB3000MC_REG_UNK_88 ( 88)
|
||||
#define DIB3000MC_UNK_88 (0x0410)
|
||||
|
||||
static u16 dib3000mc_reg_bw[] = { 93,94,95,96,97,98 };
|
||||
static u16 dib3000mc_bw[][6] = {
|
||||
{ 0,0,0,0,0,0 }, /* 5 MHz */
|
||||
{ 0,0,0,0,0,0 }, /* 6 MHz */
|
||||
{ 0,0,0,0,0,0 }, /* 7 MHz */
|
||||
{ 0x20, 0x21, 0x20, 0x23, 0x20, 0x27 }, /* 8 MHz */
|
||||
};
|
||||
|
||||
|
||||
/* phase noise control */
|
||||
#define DIB3000MC_REG_UNK_99 ( 99)
|
||||
#define DIB3000MC_UNK_99 (0x0220)
|
||||
|
||||
#define DIB3000MC_REG_SCAN_BOOST ( 100)
|
||||
#define DIB3000MC_SCAN_BOOST_ON ((11 << 6) + 6)
|
||||
#define DIB3000MC_SCAN_BOOST_OFF ((16 << 6) + 9)
|
||||
|
||||
/* timeout ??? */
|
||||
#define DIB3000MC_REG_UNK_110 ( 110)
|
||||
#define DIB3000MC_UNK_110 ( 3277)
|
||||
|
||||
#define DIB3000MC_REG_UNK_111 ( 111)
|
||||
#define DIB3000MC_UNK_111_PH_N_MODE_0 ( 0)
|
||||
#define DIB3000MC_UNK_111_PH_N_MODE_1 (1 << 1)
|
||||
|
||||
/* superious rm config */
|
||||
#define DIB3000MC_REG_UNK_120 ( 120)
|
||||
#define DIB3000MC_UNK_120 ( 8207)
|
||||
|
||||
#define DIB3000MC_REG_UNK_133 ( 133)
|
||||
#define DIB3000MC_UNK_133 ( 15564)
|
||||
|
||||
#define DIB3000MC_REG_UNK_134 ( 134)
|
||||
#define DIB3000MC_UNK_134 ( 0)
|
||||
|
||||
/* adapter config for constellation */
|
||||
static u16 dib3000mc_reg_adp_cfg[] = { 129, 130, 131, 132 };
|
||||
|
||||
static u16 dib3000mc_adp_cfg[][4] = {
|
||||
{ 0x99a, 0x7fae, 0x333, 0x7ff0 }, /* QPSK */
|
||||
{ 0x23d, 0x7fdf, 0x0a4, 0x7ff0 }, /* 16-QAM */
|
||||
{ 0x148, 0x7ff0, 0x0a4, 0x7ff8 }, /* 64-QAM */
|
||||
};
|
||||
|
||||
static u16 dib3000mc_reg_mobile_mode[] = { 139, 140, 141, 175, 1032 };
|
||||
|
||||
static u16 dib3000mc_mobile_mode[][5] = {
|
||||
{ 0x01, 0x0, 0x0, 0x00, 0x12c }, /* fixed */
|
||||
{ 0x01, 0x0, 0x0, 0x00, 0x12c }, /* portable */
|
||||
{ 0x00, 0x0, 0x0, 0x02, 0x000 }, /* mobile */
|
||||
{ 0x00, 0x0, 0x0, 0x02, 0x000 }, /* auto */
|
||||
};
|
||||
|
||||
#define DIB3000MC_REG_DIVERSITY1 ( 177)
|
||||
#define DIB3000MC_DIVERSITY1_DEFAULT ( 1)
|
||||
|
||||
#define DIB3000MC_REG_DIVERSITY2 ( 178)
|
||||
#define DIB3000MC_DIVERSITY2_DEFAULT ( 1)
|
||||
|
||||
#define DIB3000MC_REG_DIVERSITY3 ( 180)
|
||||
#define DIB3000MC_DIVERSITY3_IN_OFF (0xfff0)
|
||||
#define DIB3000MC_DIVERSITY3_IN_ON (0xfff6)
|
||||
|
||||
#define DIB3000MC_REG_FEC_CFG ( 195)
|
||||
#define DIB3000MC_FEC_CFG ( 0x10)
|
||||
|
||||
/*
|
||||
* reg 206, output mode
|
||||
* 1111 1111
|
||||
* |||| ||||
|
||||
* |||| |||+- unk
|
||||
* |||| ||+-- unk
|
||||
* |||| |+--- unk (on by default)
|
||||
* |||| +---- fifo_ctrl (1 = inhibit (flushed), 0 = active (unflushed))
|
||||
* |||+------ pid_parse (1 = enabled, 0 = disabled)
|
||||
* ||+------- outp_188 (1 = TS packet size 188, 0 = packet size 204)
|
||||
* |+-------- unk
|
||||
* +--------- unk
|
||||
*/
|
||||
|
||||
#define DIB3000MC_REG_SMO_MODE ( 206)
|
||||
#define DIB3000MC_SMO_MODE_DEFAULT (1 << 2)
|
||||
#define DIB3000MC_SMO_MODE_FIFO_FLUSH (1 << 3)
|
||||
#define DIB3000MC_SMO_MODE_FIFO_UNFLUSH (0xfff7)
|
||||
#define DIB3000MC_SMO_MODE_PID_PARSE (1 << 4)
|
||||
#define DIB3000MC_SMO_MODE_NO_PID_PARSE (0xffef)
|
||||
#define DIB3000MC_SMO_MODE_188 (1 << 5)
|
||||
#define DIB3000MC_SMO_MODE_SLAVE (DIB3000MC_SMO_MODE_DEFAULT | \
|
||||
DIB3000MC_SMO_MODE_188 | DIB3000MC_SMO_MODE_PID_PARSE | (1<<1))
|
||||
|
||||
#define DIB3000MC_REG_FIFO_THRESHOLD ( 207)
|
||||
#define DIB3000MC_FIFO_THRESHOLD_DEFAULT ( 1792)
|
||||
#define DIB3000MC_FIFO_THRESHOLD_SLAVE ( 512)
|
||||
/*
|
||||
* pidfilter
|
||||
* it is not a hardware pidfilter but a filter which drops all pids
|
||||
* except the ones set. When connected to USB1.1 bandwidth this is important.
|
||||
* DiB3000P/M-C can filter up to 32 PIDs
|
||||
*/
|
||||
#define DIB3000MC_REG_FIRST_PID ( 212)
|
||||
#define DIB3000MC_NUM_PIDS ( 32)
|
||||
|
||||
#define DIB3000MC_REG_OUTMODE ( 244)
|
||||
#define DIB3000MC_OM_PARALLEL_GATED_CLK ( 0)
|
||||
#define DIB3000MC_OM_PAR_CONT_CLK (1 << 11)
|
||||
#define DIB3000MC_OM_SERIAL (2 << 11)
|
||||
#define DIB3000MC_OM_DIVOUT_ON (4 << 11)
|
||||
#define DIB3000MC_OM_SLAVE (DIB3000MC_OM_DIVOUT_ON | DIB3000MC_OM_PAR_CONT_CLK)
|
||||
|
||||
#define DIB3000MC_REG_RF_POWER ( 392)
|
||||
|
||||
#define DIB3000MC_REG_FFT_POSITION ( 407)
|
||||
|
||||
#define DIB3000MC_REG_DDS_FREQ_MSB ( 414)
|
||||
#define DIB3000MC_REG_DDS_FREQ_LSB ( 415)
|
||||
|
||||
#define DIB3000MC_REG_TIMING_OFFS_MSB ( 416)
|
||||
#define DIB3000MC_REG_TIMING_OFFS_LSB ( 417)
|
||||
|
||||
#define DIB3000MC_REG_TUNING_PARM ( 458)
|
||||
#define DIB3000MC_TP_QAM(v) ((v >> 13) & 0x03)
|
||||
#define DIB3000MC_TP_HRCH(v) ((v >> 12) & 0x01)
|
||||
#define DIB3000MC_TP_ALPHA(v) ((v >> 9) & 0x07)
|
||||
#define DIB3000MC_TP_FFT(v) ((v >> 8) & 0x01)
|
||||
#define DIB3000MC_TP_FEC_CR_HP(v) ((v >> 5) & 0x07)
|
||||
#define DIB3000MC_TP_FEC_CR_LP(v) ((v >> 2) & 0x07)
|
||||
#define DIB3000MC_TP_GUARD(v) (v & 0x03)
|
||||
|
||||
#define DIB3000MC_REG_SIGNAL_NOISE_MSB ( 483)
|
||||
#define DIB3000MC_REG_SIGNAL_NOISE_LSB ( 484)
|
||||
|
||||
#define DIB3000MC_REG_MER ( 485)
|
||||
|
||||
#define DIB3000MC_REG_BER_MSB ( 500)
|
||||
#define DIB3000MC_REG_BER_LSB ( 501)
|
||||
|
||||
#define DIB3000MC_REG_PACKET_ERRORS ( 503)
|
||||
|
||||
#define DIB3000MC_REG_PACKET_ERROR_COUNT ( 506)
|
||||
|
||||
#define DIB3000MC_REG_LOCK_507 ( 507)
|
||||
#define DIB3000MC_LOCK_507 (0x0002) // ? name correct ?
|
||||
|
||||
#define DIB3000MC_REG_LOCKING ( 509)
|
||||
#define DIB3000MC_AGC_LOCK(v) (v & 0x8000)
|
||||
#define DIB3000MC_CARRIER_LOCK(v) (v & 0x2000)
|
||||
#define DIB3000MC_MPEG_SYNC_LOCK(v) (v & 0x0080)
|
||||
#define DIB3000MC_MPEG_DATA_LOCK(v) (v & 0x0040)
|
||||
#define DIB3000MC_TPS_LOCK(v) (v & 0x0004)
|
||||
|
||||
#define DIB3000MC_REG_AS_IRQ ( 511)
|
||||
#define DIB3000MC_AS_IRQ_SUCCESS (1 << 1)
|
||||
#define DIB3000MC_AS_IRQ_FAIL ( 1)
|
||||
|
||||
#define DIB3000MC_REG_TUNER ( 769)
|
||||
|
||||
#define DIB3000MC_REG_RST_I2C_ADDR ( 1024)
|
||||
#define DIB3000MC_DEMOD_ADDR_ON ( 1)
|
||||
#define DIB3000MC_DEMOD_ADDR(a) ((a << 4) & 0x03F0)
|
||||
|
||||
#define DIB3000MC_REG_RESTART ( 1027)
|
||||
#define DIB3000MC_RESTART_OFF (0x0000)
|
||||
#define DIB3000MC_RESTART_AGC (0x0800)
|
||||
#define DIB3000MC_RESTART_CONFIG (0x8000)
|
||||
|
||||
#define DIB3000MC_REG_RESTART_VIT ( 1028)
|
||||
#define DIB3000MC_RESTART_VIT_OFF ( 0)
|
||||
#define DIB3000MC_RESTART_VIT_ON ( 1)
|
||||
|
||||
#define DIB3000MC_REG_CLK_CFG_1 ( 1031)
|
||||
#define DIB3000MC_CLK_CFG_1_POWER_UP ( 0)
|
||||
#define DIB3000MC_CLK_CFG_1_POWER_DOWN (0xffff)
|
||||
|
||||
#define DIB3000MC_REG_CLK_CFG_2 ( 1032)
|
||||
#define DIB3000MC_CLK_CFG_2_PUP_FIXED (0x012c)
|
||||
#define DIB3000MC_CLK_CFG_2_PUP_PORT (0x0104)
|
||||
#define DIB3000MC_CLK_CFG_2_PUP_MOBILE (0x0000)
|
||||
#define DIB3000MC_CLK_CFG_2_POWER_DOWN (0xffff)
|
||||
|
||||
#define DIB3000MC_REG_CLK_CFG_3 ( 1033)
|
||||
#define DIB3000MC_CLK_CFG_3_POWER_UP ( 0)
|
||||
#define DIB3000MC_CLK_CFG_3_POWER_DOWN (0xfff5)
|
||||
|
||||
#define DIB3000MC_REG_CLK_CFG_7 ( 1037)
|
||||
#define DIB3000MC_CLK_CFG_7_INIT ( 12592)
|
||||
#define DIB3000MC_CLK_CFG_7_POWER_UP (~0x0003)
|
||||
#define DIB3000MC_CLK_CFG_7_PWR_DOWN (0x0003)
|
||||
#define DIB3000MC_CLK_CFG_7_DIV_IN_OFF (1 << 8)
|
||||
|
||||
/* was commented out ??? */
|
||||
#define DIB3000MC_REG_CLK_CFG_8 ( 1038)
|
||||
#define DIB3000MC_CLK_CFG_8_POWER_UP (0x160c)
|
||||
|
||||
#define DIB3000MC_REG_CLK_CFG_9 ( 1039)
|
||||
#define DIB3000MC_CLK_CFG_9_POWER_UP ( 0)
|
||||
|
||||
/* also clock ??? */
|
||||
#define DIB3000MC_REG_ELEC_OUT ( 1040)
|
||||
#define DIB3000MC_ELEC_OUT_HIGH_Z ( 0)
|
||||
#define DIB3000MC_ELEC_OUT_DIV_OUT_ON ( 1)
|
||||
#define DIB3000MC_ELEC_OUT_SLAVE ( 3)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,152 @@
|
|||
#include <linux/i2c.h>
|
||||
|
||||
#include "dibx000_common.h"
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
|
||||
|
||||
#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0)
|
||||
|
||||
static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
|
||||
{
|
||||
u8 b[4] = {
|
||||
(reg >> 8) & 0xff, reg & 0xff,
|
||||
(val >> 8) & 0xff, val & 0xff,
|
||||
};
|
||||
struct i2c_msg msg = {
|
||||
.addr = mst->i2c_addr, .flags = 0, .buf = b, .len = 4
|
||||
};
|
||||
return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
|
||||
static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf)
|
||||
{
|
||||
if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
|
||||
dprintk("selecting interface: %d\n",intf);
|
||||
mst->selected_interface = intf;
|
||||
return dibx000_write_word(mst, mst->base_reg + 4, intf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], u8 addr, int onoff)
|
||||
{
|
||||
u16 val;
|
||||
|
||||
|
||||
if (onoff)
|
||||
val = addr << 8; // bit 7 = use master or not, if 0, the gate is open
|
||||
else
|
||||
val = 1 << 7;
|
||||
|
||||
if (mst->device_rev > DIB7000)
|
||||
val <<= 1;
|
||||
|
||||
tx[0] = (((mst->base_reg + 1) >> 8) & 0xff);
|
||||
tx[1] = ( (mst->base_reg + 1) & 0xff);
|
||||
tx[2] = val >> 8;
|
||||
tx[3] = val & 0xff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
|
||||
struct i2c_msg m[2 + num];
|
||||
u8 tx_open[4], tx_close[4];
|
||||
|
||||
memset(m,0, sizeof(struct i2c_msg) * (2 + num));
|
||||
|
||||
dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
|
||||
|
||||
dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
|
||||
m[0].addr = mst->i2c_addr;
|
||||
m[0].buf = tx_open;
|
||||
m[0].len = 4;
|
||||
|
||||
memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
|
||||
|
||||
dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
|
||||
m[num+1].addr = mst->i2c_addr;
|
||||
m[num+1].buf = tx_close;
|
||||
m[num+1].len = 4;
|
||||
|
||||
return i2c_transfer(mst->i2c_adap, m, 2+num) == 2 + num ? num : -EIO;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
|
||||
.master_xfer = dibx000_i2c_gated_tuner_xfer,
|
||||
.functionality = dibx000_i2c_func,
|
||||
};
|
||||
|
||||
struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating)
|
||||
{
|
||||
struct i2c_adapter *i2c = NULL;
|
||||
|
||||
switch (intf) {
|
||||
case DIBX000_I2C_INTERFACE_TUNER:
|
||||
if (gating)
|
||||
i2c = &mst->gated_tuner_i2c_adap;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return i2c;
|
||||
}
|
||||
EXPORT_SYMBOL(dibx000_get_i2c_adapter);
|
||||
|
||||
static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char name[I2C_NAME_SIZE], struct dibx000_i2c_master *mst)
|
||||
{
|
||||
strncpy(i2c_adap->name, name, I2C_NAME_SIZE);
|
||||
i2c_adap->class = I2C_CLASS_TV_DIGITAL,
|
||||
i2c_adap->algo = algo;
|
||||
i2c_adap->algo_data = NULL;
|
||||
i2c_set_adapdata(i2c_adap, mst);
|
||||
if (i2c_add_adapter(i2c_adap) < 0)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr)
|
||||
{
|
||||
u8 tx[4];
|
||||
struct i2c_msg m = { .addr = i2c_addr >> 1, .buf = tx, .len = 4 };
|
||||
|
||||
mst->device_rev = device_rev;
|
||||
mst->i2c_adap = i2c_adap;
|
||||
mst->i2c_addr = i2c_addr >> 1;
|
||||
|
||||
if (device_rev == DIB7000P)
|
||||
mst->base_reg = 1024;
|
||||
else
|
||||
mst->base_reg = 768;
|
||||
|
||||
if (i2c_adapter_init(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo, "DiBX000 tuner I2C bus", mst) != 0)
|
||||
printk(KERN_ERR "DiBX000: could not initialize the tuner i2c_adapter\n");
|
||||
|
||||
/* initialize the i2c-master by closing the gate */
|
||||
dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
|
||||
|
||||
return i2c_transfer(i2c_adap, &m, 1) == 1;
|
||||
}
|
||||
EXPORT_SYMBOL(dibx000_init_i2c_master);
|
||||
|
||||
void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
|
||||
{
|
||||
i2c_del_adapter(&mst->gated_tuner_i2c_adap);
|
||||
}
|
||||
EXPORT_SYMBOL(dibx000_exit_i2c_master);
|
||||
|
||||
MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
|
||||
MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,166 @@
|
|||
#ifndef DIBX000_COMMON_H
|
||||
#define DIBX000_COMMON_H
|
||||
|
||||
enum dibx000_i2c_interface {
|
||||
DIBX000_I2C_INTERFACE_TUNER = 0,
|
||||
DIBX000_I2C_INTERFACE_GPIO_1_2 = 1,
|
||||
DIBX000_I2C_INTERFACE_GPIO_3_4 = 2
|
||||
};
|
||||
|
||||
struct dibx000_i2c_master {
|
||||
#define DIB3000MC 1
|
||||
#define DIB7000 2
|
||||
#define DIB7000P 11
|
||||
#define DIB7000MC 12
|
||||
u16 device_rev;
|
||||
|
||||
enum dibx000_i2c_interface selected_interface;
|
||||
|
||||
// struct i2c_adapter tuner_i2c_adap;
|
||||
struct i2c_adapter gated_tuner_i2c_adap;
|
||||
|
||||
struct i2c_adapter *i2c_adap;
|
||||
u8 i2c_addr;
|
||||
|
||||
u16 base_reg;
|
||||
};
|
||||
|
||||
extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr);
|
||||
extern struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating);
|
||||
extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
|
||||
|
||||
#define BAND_LBAND 0x01
|
||||
#define BAND_UHF 0x02
|
||||
#define BAND_VHF 0x04
|
||||
|
||||
struct dibx000_agc_config {
|
||||
/* defines the capabilities of this AGC-setting - using the BAND_-defines*/
|
||||
u8 band_caps;
|
||||
|
||||
u16 setup;
|
||||
|
||||
u16 inv_gain;
|
||||
u16 time_stabiliz;
|
||||
|
||||
u8 alpha_level;
|
||||
u16 thlock;
|
||||
|
||||
u8 wbd_inv;
|
||||
u16 wbd_ref;
|
||||
u8 wbd_sel;
|
||||
u8 wbd_alpha;
|
||||
|
||||
u16 agc1_max;
|
||||
u16 agc1_min;
|
||||
u16 agc2_max;
|
||||
u16 agc2_min;
|
||||
|
||||
u8 agc1_pt1;
|
||||
u8 agc1_pt2;
|
||||
u8 agc1_pt3;
|
||||
|
||||
u8 agc1_slope1;
|
||||
u8 agc1_slope2;
|
||||
|
||||
u8 agc2_pt1;
|
||||
u8 agc2_pt2;
|
||||
|
||||
u8 agc2_slope1;
|
||||
u8 agc2_slope2;
|
||||
|
||||
u8 alpha_mant;
|
||||
u8 alpha_exp;
|
||||
|
||||
u8 beta_mant;
|
||||
u8 beta_exp;
|
||||
|
||||
u8 perform_agc_softsplit;
|
||||
|
||||
struct {
|
||||
u16 min;
|
||||
u16 max;
|
||||
u16 min_thres;
|
||||
u16 max_thres;
|
||||
} split;
|
||||
};
|
||||
|
||||
struct dibx000_bandwidth_config {
|
||||
u32 internal;
|
||||
u32 sampling;
|
||||
|
||||
u8 pll_prediv;
|
||||
u8 pll_ratio;
|
||||
u8 pll_range;
|
||||
u8 pll_reset;
|
||||
u8 pll_bypass;
|
||||
|
||||
u8 enable_refdiv;
|
||||
u8 bypclk_div;
|
||||
u8 IO_CLK_en_core;
|
||||
u8 ADClkSrc;
|
||||
u8 modulo;
|
||||
|
||||
u16 sad_cfg;
|
||||
|
||||
u32 ifreq;
|
||||
u32 timf;
|
||||
};
|
||||
|
||||
enum dibx000_adc_states {
|
||||
DIBX000_SLOW_ADC_ON = 0,
|
||||
DIBX000_SLOW_ADC_OFF,
|
||||
DIBX000_ADC_ON,
|
||||
DIBX000_ADC_OFF,
|
||||
DIBX000_VBG_ENABLE,
|
||||
DIBX000_VBG_DISABLE,
|
||||
};
|
||||
|
||||
#define BW_INDEX_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ ? 8000 : \
|
||||
(v) == BANDWIDTH_7_MHZ ? 7000 : \
|
||||
(v) == BANDWIDTH_6_MHZ ? 6000 : 8000 )
|
||||
|
||||
/* Chip output mode. */
|
||||
#define OUTMODE_HIGH_Z 0
|
||||
#define OUTMODE_MPEG2_PAR_GATED_CLK 1
|
||||
#define OUTMODE_MPEG2_PAR_CONT_CLK 2
|
||||
#define OUTMODE_MPEG2_SERIAL 7
|
||||
#define OUTMODE_DIVERSITY 4
|
||||
#define OUTMODE_MPEG2_FIFO 5
|
||||
|
||||
/* I hope I can get rid of the following kludge in the near future */
|
||||
struct dibx000_ofdm_channel {
|
||||
u8 Bw;
|
||||
s16 nfft;
|
||||
s16 guard;
|
||||
s16 nqam;
|
||||
s16 vit_hrch;
|
||||
s16 vit_select_hp;
|
||||
s16 vit_alpha;
|
||||
s16 vit_code_rate_hp;
|
||||
s16 vit_code_rate_lp;
|
||||
};
|
||||
|
||||
#define FEP2DIB(fep,ch) \
|
||||
(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; \
|
||||
(ch)->nqam = (fep)->u.ofdm.constellation == QAM_AUTO ? -1 : (fep)->u.ofdm.constellation == QAM_64 ? 2 : (fep)->u.ofdm.constellation; \
|
||||
(ch)->vit_hrch = 0; /* linux-dvb is not prepared for HIERARCHICAL TRANSMISSION */ \
|
||||
(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;
|
||||
|
||||
#define INIT_OFDM_CHANNEL(ch) do {\
|
||||
(ch)->Bw = 0; \
|
||||
(ch)->nfft = -1; \
|
||||
(ch)->guard = -1; \
|
||||
(ch)->nqam = -1; \
|
||||
(ch)->vit_hrch = -1; \
|
||||
(ch)->vit_select_hp = -1; \
|
||||
(ch)->vit_alpha = -1; \
|
||||
(ch)->vit_code_rate_hp = -1; \
|
||||
(ch)->vit_code_rate_lp = -1; \
|
||||
} while (0)
|
||||
|
||||
#endif
|
|
@ -493,6 +493,9 @@ static int dvb_pll_sleep(struct dvb_frontend *fe)
|
|||
int i;
|
||||
int result;
|
||||
|
||||
if (priv->i2c == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < priv->pll_desc->count; i++) {
|
||||
if (priv->pll_desc->entries[i].limit == 0)
|
||||
break;
|
||||
|
@ -611,7 +614,7 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = {
|
|||
.get_bandwidth = dvb_pll_get_bandwidth,
|
||||
};
|
||||
|
||||
int 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 };
|
||||
|
@ -624,14 +627,14 @@ int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2
|
|||
|
||||
ret = i2c_transfer (i2c, &msg, 1);
|
||||
if (ret != 1)
|
||||
return -1;
|
||||
return NULL;
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
|
||||
priv->pll_i2c_address = pll_addr;
|
||||
priv->i2c = i2c;
|
||||
|
@ -643,7 +646,7 @@ int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2
|
|||
fe->ops.tuner_ops.info.frequency_min = desc->max;
|
||||
|
||||
fe->tuner_priv = priv;
|
||||
return 0;
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_pll_attach);
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
|
|||
* @param pll_addr i2c address of the PLL (if used).
|
||||
* @param i2c i2c adapter to use (set to NULL if not used).
|
||||
* @param desc dvb_pll_desc to use.
|
||||
* @return 0 on success, nonzero on failure.
|
||||
* @return Frontend pointer on success, NULL on failure
|
||||
*/
|
||||
extern int 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
|
||||
|
|
|
@ -42,12 +42,11 @@ struct isl6421 {
|
|||
u8 override_and;
|
||||
struct i2c_adapter *i2c;
|
||||
u8 i2c_addr;
|
||||
void (*release_chain)(struct dvb_frontend* fe);
|
||||
};
|
||||
|
||||
static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
|
||||
struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
|
||||
struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
|
||||
.buf = &isl6421->config,
|
||||
.len = sizeof(isl6421->config) };
|
||||
|
@ -75,7 +74,7 @@ static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
|
|||
|
||||
static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
||||
{
|
||||
struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
|
||||
struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
|
||||
struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
|
||||
.buf = &isl6421->config,
|
||||
.len = sizeof(isl6421->config) };
|
||||
|
@ -93,31 +92,26 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
|||
|
||||
static void isl6421_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
|
||||
|
||||
/* power off */
|
||||
isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
|
||||
/* free data & call next release routine */
|
||||
fe->ops.release = isl6421->release_chain;
|
||||
kfree(fe->misc_priv);
|
||||
fe->misc_priv = NULL;
|
||||
if (fe->ops.release)
|
||||
fe->ops.release(fe);
|
||||
/* free */
|
||||
kfree(fe->sec_priv);
|
||||
fe->sec_priv = NULL;
|
||||
}
|
||||
|
||||
int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
|
||||
struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
|
||||
u8 override_set, u8 override_clear)
|
||||
{
|
||||
struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
|
||||
if (!isl6421)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
|
||||
/* default configuration */
|
||||
isl6421->config = ISL6421_ISEL1;
|
||||
isl6421->i2c = i2c;
|
||||
isl6421->i2c_addr = i2c_addr;
|
||||
fe->misc_priv = isl6421;
|
||||
fe->sec_priv = isl6421;
|
||||
|
||||
/* bits which should be forced to '1' */
|
||||
isl6421->override_or = override_set;
|
||||
|
@ -128,19 +122,17 @@ int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr
|
|||
/* detect if it is present or not */
|
||||
if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
|
||||
kfree(isl6421);
|
||||
fe->misc_priv = NULL;
|
||||
return -EIO;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* install release callback */
|
||||
isl6421->release_chain = fe->ops.release;
|
||||
fe->ops.release = isl6421_release;
|
||||
fe->ops.release_sec = isl6421_release;
|
||||
|
||||
/* override frontend ops */
|
||||
fe->ops.set_voltage = isl6421_set_voltage;
|
||||
fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
|
||||
|
||||
return 0;
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(isl6421_attach);
|
||||
|
||||
|
|
|
@ -39,8 +39,17 @@
|
|||
#define ISL6421_ISEL1 0x20
|
||||
#define ISL6421_DCL 0x40
|
||||
|
||||
#if defined(CONFIG_DVB_ISL6421) || defined(CONFIG_DVB_ISL6421_MODULE)
|
||||
/* override_set and override_clear control which system register bits (above) to always set & clear */
|
||||
extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
|
||||
extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
|
||||
u8 override_set, u8 override_clear);
|
||||
#else
|
||||
static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
|
||||
u8 override_set, u8 override_clear)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_ISL6421
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,8 +31,16 @@ struct l64781_config
|
|||
u8 demod_address;
|
||||
};
|
||||
|
||||
|
||||
#if defined(CONFIG_DVB_L64781) || defined(CONFIG_DVB_L64781_MODULE)
|
||||
extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_L64781
|
||||
|
||||
#endif // L64781_H
|
||||
|
|
|
@ -52,8 +52,17 @@ struct lgdt330x_config
|
|||
int clock_polarity_flip;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_LGDT330X) || defined(CONFIG_DVB_LGDT330X_MODULE)
|
||||
extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_LGDT330X
|
||||
|
||||
#endif /* LGDT330X_H */
|
||||
|
||||
|
|
|
@ -40,12 +40,11 @@ struct lnbp21 {
|
|||
u8 override_or;
|
||||
u8 override_and;
|
||||
struct i2c_adapter *i2c;
|
||||
void (*release_chain)(struct dvb_frontend* fe);
|
||||
};
|
||||
|
||||
static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
|
||||
struct i2c_msg msg = { .addr = 0x08, .flags = 0,
|
||||
.buf = &lnbp21->config,
|
||||
.len = sizeof(lnbp21->config) };
|
||||
|
@ -73,7 +72,7 @@ static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
|||
|
||||
static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
|
||||
struct i2c_msg msg = { .addr = 0x08, .flags = 0,
|
||||
.buf = &lnbp21->config,
|
||||
.len = sizeof(lnbp21->config) };
|
||||
|
@ -91,29 +90,24 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
|
|||
|
||||
static void lnbp21_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
|
||||
|
||||
/* LNBP power off */
|
||||
lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
|
||||
|
||||
/* free data & call next release routine */
|
||||
fe->ops.release = lnbp21->release_chain;
|
||||
kfree(fe->misc_priv);
|
||||
fe->misc_priv = NULL;
|
||||
if (fe->ops.release)
|
||||
fe->ops.release(fe);
|
||||
/* free data */
|
||||
kfree(fe->sec_priv);
|
||||
fe->sec_priv = NULL;
|
||||
}
|
||||
|
||||
int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
|
||||
struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
|
||||
{
|
||||
struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
|
||||
if (!lnbp21)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
|
||||
/* default configuration */
|
||||
lnbp21->config = LNBP21_ISEL;
|
||||
lnbp21->i2c = i2c;
|
||||
fe->misc_priv = lnbp21;
|
||||
fe->sec_priv = lnbp21;
|
||||
|
||||
/* bits which should be forced to '1' */
|
||||
lnbp21->override_or = override_set;
|
||||
|
@ -124,19 +118,17 @@ int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_
|
|||
/* detect if it is present or not */
|
||||
if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
|
||||
kfree(lnbp21);
|
||||
fe->misc_priv = NULL;
|
||||
return -EIO;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* install release callback */
|
||||
lnbp21->release_chain = fe->ops.release;
|
||||
fe->ops.release = lnbp21_release;
|
||||
fe->ops.release_sec = lnbp21_release;
|
||||
|
||||
/* override frontend ops */
|
||||
fe->ops.set_voltage = lnbp21_set_voltage;
|
||||
fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
|
||||
|
||||
return 0;
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(lnbp21_attach);
|
||||
|
||||
|
|
|
@ -39,7 +39,15 @@
|
|||
|
||||
#include <linux/dvb/frontend.h>
|
||||
|
||||
#if defined(CONFIG_DVB_LNBP21) || defined(CONFIG_DVB_LNBP21_MODULE)
|
||||
/* override_set and override_clear control which system register bits (above) to always set & clear */
|
||||
extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
|
||||
extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
|
||||
#else
|
||||
static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_LNBP21
|
||||
|
||||
#endif
|
||||
#endif // _LNBP21_H
|
||||
|
|
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
* Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
|
||||
*
|
||||
* Copyright (c) 2006 Olivier DANET <odanet@caramail.com>
|
||||
*
|
||||
* 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.=
|
||||
*/
|
||||
|
||||
/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
#include "mt2060.h"
|
||||
#include "mt2060_priv.h"
|
||||
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
|
||||
|
||||
#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2060: " args); printk("\n"); }} while (0)
|
||||
|
||||
// Reads a single register
|
||||
static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val)
|
||||
{
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 },
|
||||
{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 },
|
||||
};
|
||||
|
||||
if (i2c_transfer(priv->i2c, msg, 2) != 2) {
|
||||
printk(KERN_WARNING "mt2060 I2C read failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Writes a single register
|
||||
static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val)
|
||||
{
|
||||
u8 buf[2] = { reg, val };
|
||||
struct i2c_msg msg = {
|
||||
.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
|
||||
};
|
||||
|
||||
if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
|
||||
printk(KERN_WARNING "mt2060 I2C write failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Writes a set of consecutive registers
|
||||
static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len)
|
||||
{
|
||||
struct i2c_msg msg = {
|
||||
.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
|
||||
};
|
||||
if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
|
||||
printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n",(int)len);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialisation sequences
|
||||
// LNABAND=3, NUM1=0x3C, DIV1=0x74, NUM2=0x1080, DIV2=0x49
|
||||
static u8 mt2060_config1[] = {
|
||||
REG_LO1C1,
|
||||
0x3F, 0x74, 0x00, 0x08, 0x93
|
||||
};
|
||||
|
||||
// FMCG=2, GP2=0, GP1=0
|
||||
static u8 mt2060_config2[] = {
|
||||
REG_MISC_CTRL,
|
||||
0x20, 0x1E, 0x30, 0xff, 0x80, 0xff, 0x00, 0x2c, 0x42
|
||||
};
|
||||
|
||||
// VGAG=3, V1CSE=1
|
||||
|
||||
#ifdef MT2060_SPURCHECK
|
||||
/* The function below calculates the frequency offset between the output frequency if2
|
||||
and the closer cross modulation subcarrier between lo1 and lo2 up to the tenth harmonic */
|
||||
static int mt2060_spurcalc(u32 lo1,u32 lo2,u32 if2)
|
||||
{
|
||||
int I,J;
|
||||
int dia,diamin,diff;
|
||||
diamin=1000000;
|
||||
for (I = 1; I < 10; I++) {
|
||||
J = ((2*I*lo1)/lo2+1)/2;
|
||||
diff = I*(int)lo1-J*(int)lo2;
|
||||
if (diff < 0) diff=-diff;
|
||||
dia = (diff-(int)if2);
|
||||
if (dia < 0) dia=-dia;
|
||||
if (diamin > dia) diamin=dia;
|
||||
}
|
||||
return diamin;
|
||||
}
|
||||
|
||||
#define BANDWIDTH 4000 // kHz
|
||||
|
||||
/* Calculates the frequency offset to add to avoid spurs. Returns 0 if no offset is needed */
|
||||
static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2)
|
||||
{
|
||||
u32 Spur,Sp1,Sp2;
|
||||
int I,J;
|
||||
I=0;
|
||||
J=1000;
|
||||
|
||||
Spur=mt2060_spurcalc(lo1,lo2,if2);
|
||||
if (Spur < BANDWIDTH) {
|
||||
/* Potential spurs detected */
|
||||
dprintk("Spurs before : f_lo1: %d f_lo2: %d (kHz)",
|
||||
(int)lo1,(int)lo2);
|
||||
I=1000;
|
||||
Sp1 = mt2060_spurcalc(lo1+I,lo2+I,if2);
|
||||
Sp2 = mt2060_spurcalc(lo1-I,lo2-I,if2);
|
||||
|
||||
if (Sp1 < Sp2) {
|
||||
J=-J; I=-I; Spur=Sp2;
|
||||
} else
|
||||
Spur=Sp1;
|
||||
|
||||
while (Spur < BANDWIDTH) {
|
||||
I += J;
|
||||
Spur = mt2060_spurcalc(lo1+I,lo2+I,if2);
|
||||
}
|
||||
dprintk("Spurs after : f_lo1: %d f_lo2: %d (kHz)",
|
||||
(int)(lo1+I),(int)(lo2+I));
|
||||
}
|
||||
return I;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define IF2 36150 // IF2 frequency = 36.150 MHz
|
||||
#define FREF 16000 // Quartz oscillator 16 MHz
|
||||
|
||||
static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct mt2060_priv *priv;
|
||||
int ret=0;
|
||||
int i=0;
|
||||
u32 freq;
|
||||
u8 lnaband;
|
||||
u32 f_lo1,f_lo2;
|
||||
u32 div1,num1,div2,num2;
|
||||
u8 b[8];
|
||||
u32 if1;
|
||||
|
||||
priv = fe->tuner_priv;
|
||||
|
||||
if1 = priv->if1_freq;
|
||||
b[0] = REG_LO1B1;
|
||||
b[1] = 0xFF;
|
||||
|
||||
mt2060_writeregs(priv,b,2);
|
||||
|
||||
freq = params->frequency / 1000; // Hz -> kHz
|
||||
priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0;
|
||||
|
||||
f_lo1 = freq + if1 * 1000;
|
||||
f_lo1 = (f_lo1 / 250) * 250;
|
||||
f_lo2 = f_lo1 - freq - IF2;
|
||||
// From the Comtech datasheet, the step used is 50kHz. The tuner chip could be more precise
|
||||
f_lo2 = ((f_lo2 + 25) / 50) * 50;
|
||||
priv->frequency = (f_lo1 - f_lo2 - IF2) * 1000,
|
||||
|
||||
#ifdef MT2060_SPURCHECK
|
||||
// LO-related spurs detection and correction
|
||||
num1 = mt2060_spurcheck(f_lo1,f_lo2,IF2);
|
||||
f_lo1 += num1;
|
||||
f_lo2 += num1;
|
||||
#endif
|
||||
//Frequency LO1 = 16MHz * (DIV1 + NUM1/64 )
|
||||
num1 = f_lo1 / (FREF / 64);
|
||||
div1 = num1 / 64;
|
||||
num1 &= 0x3f;
|
||||
|
||||
// Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 )
|
||||
num2 = f_lo2 * 64 / (FREF / 128);
|
||||
div2 = num2 / 8192;
|
||||
num2 &= 0x1fff;
|
||||
|
||||
if (freq <= 95000) lnaband = 0xB0; else
|
||||
if (freq <= 180000) lnaband = 0xA0; else
|
||||
if (freq <= 260000) lnaband = 0x90; else
|
||||
if (freq <= 335000) lnaband = 0x80; else
|
||||
if (freq <= 425000) lnaband = 0x70; else
|
||||
if (freq <= 480000) lnaband = 0x60; else
|
||||
if (freq <= 570000) lnaband = 0x50; else
|
||||
if (freq <= 645000) lnaband = 0x40; else
|
||||
if (freq <= 730000) lnaband = 0x30; else
|
||||
if (freq <= 810000) lnaband = 0x20; else lnaband = 0x10;
|
||||
|
||||
b[0] = REG_LO1C1;
|
||||
b[1] = lnaband | ((num1 >>2) & 0x0F);
|
||||
b[2] = div1;
|
||||
b[3] = (num2 & 0x0F) | ((num1 & 3) << 4);
|
||||
b[4] = num2 >> 4;
|
||||
b[5] = ((num2 >>12) & 1) | (div2 << 1);
|
||||
|
||||
dprintk("IF1: %dMHz",(int)if1);
|
||||
dprintk("PLL freq=%dkHz f_lo1=%dkHz f_lo2=%dkHz",(int)freq,(int)f_lo1,(int)f_lo2);
|
||||
dprintk("PLL div1=%d num1=%d div2=%d num2=%d",(int)div1,(int)num1,(int)div2,(int)num2);
|
||||
dprintk("PLL [1..5]: %2x %2x %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3],(int)b[4],(int)b[5]);
|
||||
|
||||
mt2060_writeregs(priv,b,6);
|
||||
|
||||
//Waits for pll lock or timeout
|
||||
i = 0;
|
||||
do {
|
||||
mt2060_readreg(priv,REG_LO_STATUS,b);
|
||||
if ((b[0] & 0x88)==0x88)
|
||||
break;
|
||||
msleep(4);
|
||||
i++;
|
||||
} while (i<10);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt2060_calibrate(struct mt2060_priv *priv)
|
||||
{
|
||||
u8 b = 0;
|
||||
int i = 0;
|
||||
|
||||
if (mt2060_writeregs(priv,mt2060_config1,sizeof(mt2060_config1)))
|
||||
return;
|
||||
if (mt2060_writeregs(priv,mt2060_config2,sizeof(mt2060_config2)))
|
||||
return;
|
||||
|
||||
do {
|
||||
b |= (1 << 6); // FM1SS;
|
||||
mt2060_writereg(priv, REG_LO2C1,b);
|
||||
msleep(20);
|
||||
|
||||
if (i == 0) {
|
||||
b |= (1 << 7); // FM1CA;
|
||||
mt2060_writereg(priv, REG_LO2C1,b);
|
||||
b &= ~(1 << 7); // FM1CA;
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
b &= ~(1 << 6); // FM1SS
|
||||
mt2060_writereg(priv, REG_LO2C1,b);
|
||||
|
||||
msleep(20);
|
||||
i++;
|
||||
} while (i < 9);
|
||||
|
||||
i = 0;
|
||||
while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
|
||||
msleep(20);
|
||||
|
||||
if (i < 10) {
|
||||
mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :)
|
||||
dprintk("calibration was successful: %d", (int)priv->fmfreq);
|
||||
} else
|
||||
dprintk("FMCAL timed out");
|
||||
}
|
||||
|
||||
static int mt2060_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct mt2060_priv *priv = fe->tuner_priv;
|
||||
*frequency = priv->frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
|
||||
{
|
||||
struct mt2060_priv *priv = fe->tuner_priv;
|
||||
*bandwidth = priv->bandwidth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt2060_init(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mt2060_priv *priv = fe->tuner_priv;
|
||||
return mt2060_writereg(priv, REG_VGAG,0x33);
|
||||
}
|
||||
|
||||
static int mt2060_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct mt2060_priv *priv = fe->tuner_priv;
|
||||
return mt2060_writereg(priv, REG_VGAG,0x30);
|
||||
}
|
||||
|
||||
static int mt2060_release(struct dvb_frontend *fe)
|
||||
{
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dvb_tuner_ops mt2060_tuner_ops = {
|
||||
.info = {
|
||||
.name = "Microtune MT2060",
|
||||
.frequency_min = 48000000,
|
||||
.frequency_max = 860000000,
|
||||
.frequency_step = 50000,
|
||||
},
|
||||
|
||||
.release = mt2060_release,
|
||||
|
||||
.init = mt2060_init,
|
||||
.sleep = mt2060_sleep,
|
||||
|
||||
.set_params = mt2060_set_params,
|
||||
.get_frequency = mt2060_get_frequency,
|
||||
.get_bandwidth = mt2060_get_bandwidth
|
||||
};
|
||||
|
||||
/* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */
|
||||
int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
|
||||
{
|
||||
struct mt2060_priv *priv = NULL;
|
||||
u8 id = 0;
|
||||
|
||||
priv = kzalloc(sizeof(struct mt2060_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->cfg = cfg;
|
||||
priv->i2c = i2c;
|
||||
priv->if1_freq = if1;
|
||||
|
||||
if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) {
|
||||
kfree(priv);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (id != PART_REV) {
|
||||
kfree(priv);
|
||||
return -ENODEV;
|
||||
}
|
||||
printk(KERN_INFO "MT2060: successfully identified (IF1 = %d)\n", if1);
|
||||
memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops));
|
||||
|
||||
fe->tuner_priv = priv;
|
||||
|
||||
mt2060_calibrate(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mt2060_attach);
|
||||
|
||||
MODULE_AUTHOR("Olivier DANET");
|
||||
MODULE_DESCRIPTION("Microtune MT2060 silicon tuner driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
|
||||
*
|
||||
* Copyright (c) 2006 Olivier DANET <odanet@caramail.com>
|
||||
*
|
||||
* 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 MT2060_H
|
||||
#define MT2060_H
|
||||
|
||||
struct dvb_frontend;
|
||||
struct i2c_adapter;
|
||||
|
||||
struct mt2060_config {
|
||||
u8 i2c_address;
|
||||
/* Shall we add settings for the discrete outputs ? */
|
||||
};
|
||||
|
||||
extern int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
|
||||
*
|
||||
* Copyright (c) 2006 Olivier DANET <odanet@caramail.com>
|
||||
*
|
||||
* 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 MT2060_PRIV_H
|
||||
#define MT2060_PRIV_H
|
||||
|
||||
// Uncomment the #define below to enable spurs checking. The results where quite unconvincing.
|
||||
// #define MT2060_SPURCHECK
|
||||
|
||||
/* This driver is based on the information available in the datasheet of the
|
||||
"Comtech SDVBT-3K6M" tuner ( K1000737843.pdf ) which features the MT2060 register map :
|
||||
|
||||
I2C Address : 0x60
|
||||
|
||||
Reg.No | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | ( defaults )
|
||||
--------------------------------------------------------------------------------
|
||||
00 | [ PART ] | [ REV ] | R = 0x63
|
||||
01 | [ LNABAND ] | [ NUM1(5:2) ] | RW = 0x3F
|
||||
02 | [ DIV1 ] | RW = 0x74
|
||||
03 | FM1CA | FM1SS | [ NUM1(1:0) ] | [ NUM2(3:0) ] | RW = 0x00
|
||||
04 | NUM2(11:4) ] | RW = 0x08
|
||||
05 | [ DIV2 ] |NUM2(12)| RW = 0x93
|
||||
06 | L1LK | [ TAD1 ] | L2LK | [ TAD2 ] | R
|
||||
07 | [ FMF ] | R
|
||||
08 | ? | FMCAL | ? | ? | ? | ? | ? | TEMP | R
|
||||
09 | 0 | 0 | [ FMGC ] | 0 | GP02 | GP01 | 0 | RW = 0x20
|
||||
0A | ??
|
||||
0B | 0 | 0 | 1 | 1 | 0 | 0 | [ VGAG ] | RW = 0x30
|
||||
0C | V1CSE | 1 | 1 | 1 | 1 | 1 | 1 | 1 | RW = 0xFF
|
||||
0D | 1 | 0 | [ V1CS ] | RW = 0xB0
|
||||
0E | ??
|
||||
0F | ??
|
||||
10 | ??
|
||||
11 | [ LOTO ] | 0 | 0 | 1 | 0 | RW = 0x42
|
||||
|
||||
PART : Part code : 6 for MT2060
|
||||
REV : Revision code : 3 for current revision
|
||||
LNABAND : Input frequency range : ( See code for details )
|
||||
NUM1 / DIV1 / NUM2 / DIV2 : Frequencies programming ( See code for details )
|
||||
FM1CA : Calibration Start Bit
|
||||
FM1SS : Calibration Single Step bit
|
||||
L1LK : LO1 Lock Detect
|
||||
TAD1 : Tune Line ADC ( ? )
|
||||
L2LK : LO2 Lock Detect
|
||||
TAD2 : Tune Line ADC ( ? )
|
||||
FMF : Estimated first IF Center frequency Offset ( ? )
|
||||
FM1CAL : Calibration done bit
|
||||
TEMP : On chip temperature sensor
|
||||
FMCG : Mixer 1 Cap Gain ( ? )
|
||||
GP01 / GP02 : Programmable digital outputs. Unconnected pins ?
|
||||
V1CSE : LO1 VCO Automatic Capacitor Select Enable ( ? )
|
||||
V1CS : LO1 Capacitor Selection Value ( ? )
|
||||
LOTO : LO Timeout ( ? )
|
||||
VGAG : Tuner Output gain
|
||||
*/
|
||||
|
||||
#define I2C_ADDRESS 0x60
|
||||
|
||||
#define REG_PART_REV 0
|
||||
#define REG_LO1C1 1
|
||||
#define REG_LO1C2 2
|
||||
#define REG_LO2C1 3
|
||||
#define REG_LO2C2 4
|
||||
#define REG_LO2C3 5
|
||||
#define REG_LO_STATUS 6
|
||||
#define REG_FM_FREQ 7
|
||||
#define REG_MISC_STAT 8
|
||||
#define REG_MISC_CTRL 9
|
||||
#define REG_RESERVED_A 0x0A
|
||||
#define REG_VGAG 0x0B
|
||||
#define REG_LO1B1 0x0C
|
||||
#define REG_LO1B2 0x0D
|
||||
#define REG_LOTO 0x11
|
||||
|
||||
#define PART_REV 0x63 // The current driver works only with PART=6 and REV=3 chips
|
||||
|
||||
struct mt2060_priv {
|
||||
struct mt2060_config *cfg;
|
||||
struct i2c_adapter *i2c;
|
||||
|
||||
u32 frequency;
|
||||
u32 bandwidth;
|
||||
u16 if1_freq;
|
||||
u8 fmfreq;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -34,8 +34,16 @@ struct mt312_config
|
|||
u8 demod_address;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_MT312) || defined(CONFIG_DVB_MT312_MODULE)
|
||||
struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
|
||||
#else
|
||||
static inline struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_MT312
|
||||
|
||||
#endif // MT312_H
|
||||
|
|
|
@ -70,7 +70,7 @@ static int mt352_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen)
|
||||
static int _mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen)
|
||||
{
|
||||
int err,i;
|
||||
for (i=0; i < ilen-1; i++)
|
||||
|
@ -107,7 +107,7 @@ static int mt352_sleep(struct dvb_frontend* fe)
|
|||
{
|
||||
static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 };
|
||||
|
||||
mt352_write(fe, mt352_softdown, sizeof(mt352_softdown));
|
||||
_mt352_write(fe, mt352_softdown, sizeof(mt352_softdown));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -293,14 +293,14 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
|
|||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
mt352_write(fe, buf, 8);
|
||||
mt352_write(fe, fsm_go, 2);
|
||||
_mt352_write(fe, buf, 8);
|
||||
_mt352_write(fe, fsm_go, 2);
|
||||
} else {
|
||||
if (fe->ops.tuner_ops.calc_regs) {
|
||||
fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5);
|
||||
buf[8] <<= 1;
|
||||
mt352_write(fe, buf, sizeof(buf));
|
||||
mt352_write(fe, tuner_go, 2);
|
||||
_mt352_write(fe, buf, sizeof(buf));
|
||||
_mt352_write(fe, tuner_go, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,7 +522,7 @@ static int mt352_init(struct dvb_frontend* fe)
|
|||
(mt352_read_register(state, CONFIG) & 0x20) == 0) {
|
||||
|
||||
/* Do a "hard" reset */
|
||||
mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
|
||||
_mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
|
||||
return state->config.demod_init(fe);
|
||||
}
|
||||
|
||||
|
@ -585,6 +585,7 @@ static struct dvb_frontend_ops mt352_ops = {
|
|||
|
||||
.init = mt352_init,
|
||||
.sleep = mt352_sleep,
|
||||
.write = _mt352_write,
|
||||
|
||||
.set_frontend = mt352_set_parameters,
|
||||
.get_frontend = mt352_get_parameters,
|
||||
|
@ -605,4 +606,3 @@ MODULE_AUTHOR("Holger Waechtler, Daniel Mack, Antonio Mancuso");
|
|||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(mt352_attach);
|
||||
EXPORT_SYMBOL(mt352_write);
|
||||
|
|
|
@ -51,9 +51,23 @@ struct mt352_config
|
|||
int (*demod_init)(struct dvb_frontend* fe);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_MT352) || defined(CONFIG_DVB_MT352_MODULE)
|
||||
extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_MT352
|
||||
|
||||
extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen);
|
||||
static inline int mt352_write(struct dvb_frontend *fe, u8 *buf, int len) {
|
||||
int r = 0;
|
||||
if (fe->ops.write)
|
||||
r = fe->ops.write(fe, buf, len);
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif // MT352_H
|
||||
|
|
|
@ -45,8 +45,17 @@ struct nxt200x_config
|
|||
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_NXT200X) || defined(CONFIG_DVB_NXT200X_MODULE)
|
||||
extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_NXT200X
|
||||
|
||||
#endif /* NXT200X_H */
|
||||
|
||||
|
|
|
@ -33,7 +33,16 @@ struct nxt6000_config
|
|||
u8 clock_inversion:1;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_NXT6000) || defined(CONFIG_DVB_NXT6000_MODULE)
|
||||
extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_NXT6000
|
||||
|
||||
#endif // NXT6000_H
|
||||
|
|
|
@ -34,8 +34,17 @@ struct or51132_config
|
|||
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_OR51132) || defined(CONFIG_DVB_OR51132_MODULE)
|
||||
extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_OR51132
|
||||
|
||||
#endif // OR51132_H
|
||||
|
||||
|
|
|
@ -37,8 +37,17 @@ struct or51211_config
|
|||
void (*sleep)(struct dvb_frontend * fe);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_OR51211) || defined(CONFIG_DVB_OR51211_MODULE)
|
||||
extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_OR51211
|
||||
|
||||
#endif // OR51211_H
|
||||
|
||||
|
|
|
@ -34,7 +34,16 @@ struct s5h1420_config
|
|||
u8 invert:1;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_S5H1420) || defined(CONFIG_DVB_S5H1420_MODULE)
|
||||
extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_S5H1420
|
||||
|
||||
#endif // S5H1420_H
|
||||
|
|
|
@ -35,7 +35,16 @@ struct sp8870_config
|
|||
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
|
||||
extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_SP8870
|
||||
|
||||
#endif // SP8870_H
|
||||
|
|
|
@ -17,7 +17,16 @@ struct sp887x_config
|
|||
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_SP887X) || defined(CONFIG_DVB_SP887X_MODULE)
|
||||
extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_SP887X
|
||||
|
||||
#endif // SP887X_H
|
||||
|
|
|
@ -42,7 +42,16 @@ struct stv0297_config
|
|||
u8 stop_during_read:1;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_STV0297) || defined(CONFIG_DVB_STV0297_MODULE)
|
||||
extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_STV0297
|
||||
|
||||
#endif // STV0297_H
|
||||
|
|
|
@ -92,11 +92,14 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
|
|||
return (ret != 1) ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data)
|
||||
int stv0299_write(struct dvb_frontend* fe, u8 *buf, int len)
|
||||
{
|
||||
struct stv0299_state* state = fe->demodulator_priv;
|
||||
|
||||
return stv0299_writeregI(state, reg, data);
|
||||
if (len != 2)
|
||||
return -EINVAL;
|
||||
|
||||
return stv0299_writeregI(state, buf[0], buf[1]);
|
||||
}
|
||||
|
||||
static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
|
||||
|
@ -694,6 +697,7 @@ static struct dvb_frontend_ops stv0299_ops = {
|
|||
|
||||
.init = stv0299_init,
|
||||
.sleep = stv0299_sleep,
|
||||
.write = stv0299_write,
|
||||
.i2c_gate_ctrl = stv0299_i2c_gate_ctrl,
|
||||
|
||||
.set_frontend = stv0299_set_frontend,
|
||||
|
@ -724,5 +728,4 @@ MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
|
|||
"Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(stv0299_writereg);
|
||||
EXPORT_SYMBOL(stv0299_attach);
|
||||
|
|
|
@ -89,9 +89,24 @@ struct stv0299_config
|
|||
int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
|
||||
};
|
||||
|
||||
extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
|
||||
|
||||
#if defined(CONFIG_DVB_STV0299) || defined(CONFIG_DVB_STV0299_MODULE)
|
||||
extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_STV0299
|
||||
|
||||
static inline int stv0299_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
|
||||
int r = 0;
|
||||
u8 buf[] = {reg, val};
|
||||
if (fe->ops.write)
|
||||
r = fe->ops.write(fe, buf, 2);
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif // STV0299_H
|
||||
|
|
|
@ -72,7 +72,7 @@ static u8 tda10021_inittab[0x40]=
|
|||
0x04, 0x2d, 0x2f, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
|
||||
static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
|
||||
{
|
||||
u8 buf[] = { reg, data };
|
||||
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
|
||||
|
@ -88,14 +88,6 @@ static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
|
|||
return (ret != 1) ? -EREMOTEIO : 0;
|
||||
}
|
||||
|
||||
int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data)
|
||||
{
|
||||
struct tda10021_state* state = fe->demodulator_priv;
|
||||
|
||||
return tda10021_writereg(state, reg, data);
|
||||
}
|
||||
EXPORT_SYMBOL(tda10021_write_byte);
|
||||
|
||||
static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
|
||||
{
|
||||
u8 b0 [] = { reg };
|
||||
|
@ -149,8 +141,8 @@ static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0,
|
|||
else if (INVERSION_OFF == inversion)
|
||||
DISABLE_INVERSION(reg0);
|
||||
|
||||
tda10021_writereg (state, 0x00, reg0 & 0xfe);
|
||||
tda10021_writereg (state, 0x00, reg0 | 0x01);
|
||||
_tda10021_writereg (state, 0x00, reg0 & 0xfe);
|
||||
_tda10021_writereg (state, 0x00, reg0 | 0x01);
|
||||
|
||||
state->reg0 = reg0;
|
||||
return 0;
|
||||
|
@ -198,17 +190,27 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate
|
|||
|
||||
NDEC = (NDEC << 6) | tda10021_inittab[0x03];
|
||||
|
||||
tda10021_writereg (state, 0x03, NDEC);
|
||||
tda10021_writereg (state, 0x0a, BDR&0xff);
|
||||
tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
|
||||
tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
|
||||
_tda10021_writereg (state, 0x03, NDEC);
|
||||
_tda10021_writereg (state, 0x0a, BDR&0xff);
|
||||
_tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
|
||||
_tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
|
||||
|
||||
tda10021_writereg (state, 0x0d, BDRI);
|
||||
tda10021_writereg (state, 0x0e, SFIL);
|
||||
_tda10021_writereg (state, 0x0d, BDRI);
|
||||
_tda10021_writereg (state, 0x0e, SFIL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len)
|
||||
{
|
||||
struct tda10021_state* state = fe->demodulator_priv;
|
||||
|
||||
if (len != 2)
|
||||
return -EINVAL;
|
||||
|
||||
return _tda10021_writereg(state, buf[0], buf[1]);
|
||||
}
|
||||
|
||||
static int tda10021_init (struct dvb_frontend *fe)
|
||||
{
|
||||
struct tda10021_state* state = fe->demodulator_priv;
|
||||
|
@ -216,12 +218,12 @@ static int tda10021_init (struct dvb_frontend *fe)
|
|||
|
||||
dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num);
|
||||
|
||||
//tda10021_writereg (fe, 0, 0);
|
||||
//_tda10021_writereg (fe, 0, 0);
|
||||
|
||||
for (i=0; i<tda10021_inittab_size; i++)
|
||||
tda10021_writereg (state, i, tda10021_inittab[i]);
|
||||
_tda10021_writereg (state, i, tda10021_inittab[i]);
|
||||
|
||||
tda10021_writereg (state, 0x34, state->pwm);
|
||||
_tda10021_writereg (state, 0x34, state->pwm);
|
||||
|
||||
//Comment by markus
|
||||
//0x2A[3-0] == PDIV -> P multiplaying factor (P=PDIV+1)(default 0)
|
||||
|
@ -230,7 +232,7 @@ static int tda10021_init (struct dvb_frontend *fe)
|
|||
//0x2A[6] == POLAXIN -> Polarity of the input reference clock (default 0)
|
||||
|
||||
//Activate PLL
|
||||
tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
|
||||
_tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -264,12 +266,12 @@ static int tda10021_set_parameters (struct dvb_frontend *fe,
|
|||
}
|
||||
|
||||
tda10021_set_symbolrate (state, p->u.qam.symbol_rate);
|
||||
tda10021_writereg (state, 0x34, state->pwm);
|
||||
_tda10021_writereg (state, 0x34, state->pwm);
|
||||
|
||||
tda10021_writereg (state, 0x01, reg0x01[qam]);
|
||||
tda10021_writereg (state, 0x05, reg0x05[qam]);
|
||||
tda10021_writereg (state, 0x08, reg0x08[qam]);
|
||||
tda10021_writereg (state, 0x09, reg0x09[qam]);
|
||||
_tda10021_writereg (state, 0x01, reg0x01[qam]);
|
||||
_tda10021_writereg (state, 0x05, reg0x05[qam]);
|
||||
_tda10021_writereg (state, 0x08, reg0x08[qam]);
|
||||
_tda10021_writereg (state, 0x09, reg0x09[qam]);
|
||||
|
||||
tda10021_setup_reg0 (state, reg0x00[qam], p->inversion);
|
||||
|
||||
|
@ -342,8 +344,8 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
|
|||
*ucblocks = 0xffffffff;
|
||||
|
||||
/* reset uncorrected block counter */
|
||||
tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
|
||||
tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
|
||||
_tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
|
||||
_tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -392,8 +394,8 @@ static int tda10021_sleep(struct dvb_frontend* fe)
|
|||
{
|
||||
struct tda10021_state* state = fe->demodulator_priv;
|
||||
|
||||
tda10021_writereg (state, 0x1b, 0x02); /* pdown ADC */
|
||||
tda10021_writereg (state, 0x00, 0x80); /* standby */
|
||||
_tda10021_writereg (state, 0x1b, 0x02); /* pdown ADC */
|
||||
_tda10021_writereg (state, 0x00, 0x80); /* standby */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -459,6 +461,7 @@ static struct dvb_frontend_ops tda10021_ops = {
|
|||
|
||||
.init = tda10021_init,
|
||||
.sleep = tda10021_sleep,
|
||||
.write = tda10021_write,
|
||||
.i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
|
||||
|
||||
.set_frontend = tda10021_set_parameters,
|
||||
|
|
|
@ -32,9 +32,24 @@ struct tda10021_config
|
|||
u8 demod_address;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_TDA10021) || defined(CONFIG_DVB_TDA10021_MODULE)
|
||||
extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
|
||||
struct i2c_adapter* i2c, u8 pwm);
|
||||
#else
|
||||
static inline struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
|
||||
struct i2c_adapter* i2c, u8 pwm)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_TDA10021
|
||||
|
||||
extern int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data);
|
||||
static inline int tda10021_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
|
||||
int r = 0;
|
||||
u8 buf[] = {reg, val};
|
||||
if (fe->ops.write)
|
||||
r = fe->ops.write(fe, buf, 2);
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif // TDA10021_H
|
||||
|
|
|
@ -579,11 +579,14 @@ static int tda1004x_decode_fec(int tdafec)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data)
|
||||
int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len)
|
||||
{
|
||||
struct tda1004x_state* state = fe->demodulator_priv;
|
||||
|
||||
return tda1004x_write_byteI(state, reg, data);
|
||||
if (len != 2)
|
||||
return -EINVAL;
|
||||
|
||||
return tda1004x_write_byteI(state, buf[0], buf[1]);
|
||||
}
|
||||
|
||||
static int tda10045_init(struct dvb_frontend* fe)
|
||||
|
@ -1216,6 +1219,7 @@ static struct dvb_frontend_ops tda10045_ops = {
|
|||
|
||||
.init = tda10045_init,
|
||||
.sleep = tda1004x_sleep,
|
||||
.write = tda1004x_write,
|
||||
.i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
|
||||
|
||||
.set_frontend = tda1004x_set_fe,
|
||||
|
@ -1274,6 +1278,7 @@ static struct dvb_frontend_ops tda10046_ops = {
|
|||
|
||||
.init = tda10046_init,
|
||||
.sleep = tda1004x_sleep,
|
||||
.write = tda1004x_write,
|
||||
.i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
|
||||
|
||||
.set_frontend = tda1004x_set_fe,
|
||||
|
@ -1323,4 +1328,3 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
EXPORT_SYMBOL(tda10045_attach);
|
||||
EXPORT_SYMBOL(tda10046_attach);
|
||||
EXPORT_SYMBOL(tda1004x_write_byte);
|
||||
|
|
|
@ -71,12 +71,33 @@ struct tda1004x_config
|
|||
int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_TDA1004X) || defined(CONFIG_DVB_TDA1004X_MODULE)
|
||||
extern struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
|
||||
extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_TDA1004X
|
||||
|
||||
extern int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data);
|
||||
static inline int tda1004x_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
|
||||
int r = 0;
|
||||
u8 buf[] = {reg, val};
|
||||
if (fe->ops.write)
|
||||
r = fe->ops.write(fe, buf, 2);
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif // TDA1004X_H
|
||||
|
|
|
@ -0,0 +1,740 @@
|
|||
/*
|
||||
Driver for Philips tda10086 DVBS Demodulator
|
||||
|
||||
(c) 2006 Andrew de Quincey
|
||||
|
||||
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/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "tda10086.h"
|
||||
|
||||
#define SACLK 96000000
|
||||
|
||||
struct tda10086_state {
|
||||
struct i2c_adapter* i2c;
|
||||
const struct tda10086_config* config;
|
||||
struct dvb_frontend frontend;
|
||||
|
||||
/* private demod data */
|
||||
u32 frequency;
|
||||
u32 symbol_rate;
|
||||
};
|
||||
|
||||
static int debug = 0;
|
||||
#define dprintk(args...) \
|
||||
do { \
|
||||
if (debug) printk(KERN_DEBUG "tda10086: " args); \
|
||||
} while (0)
|
||||
|
||||
static int tda10086_write_byte(struct tda10086_state *state, int reg, int data)
|
||||
{
|
||||
int ret;
|
||||
u8 b0[] = { reg, data };
|
||||
struct i2c_msg msg = { .flags = 0, .buf = b0, .len = 2 };
|
||||
|
||||
msg.addr = state->config->demod_address;
|
||||
ret = i2c_transfer(state->i2c, &msg, 1);
|
||||
|
||||
if (ret != 1)
|
||||
dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
|
||||
__FUNCTION__, reg, data, ret);
|
||||
|
||||
return (ret != 1) ? ret : 0;
|
||||
}
|
||||
|
||||
static int tda10086_read_byte(struct tda10086_state *state, int reg)
|
||||
{
|
||||
int ret;
|
||||
u8 b0[] = { reg };
|
||||
u8 b1[] = { 0 };
|
||||
struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
|
||||
{ .flags = I2C_M_RD, .buf = b1, .len = 1 }};
|
||||
|
||||
msg[0].addr = state->config->demod_address;
|
||||
msg[1].addr = state->config->demod_address;
|
||||
ret = i2c_transfer(state->i2c, msg, 2);
|
||||
|
||||
if (ret != 2) {
|
||||
dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return b1[0];
|
||||
}
|
||||
|
||||
static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask, int data)
|
||||
{
|
||||
int val;
|
||||
|
||||
// read a byte and check
|
||||
val = tda10086_read_byte(state, reg);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
// mask if off
|
||||
val = val & ~mask;
|
||||
val |= data & 0xff;
|
||||
|
||||
// write it out again
|
||||
return tda10086_write_byte(state, reg, val);
|
||||
}
|
||||
|
||||
static int tda10086_init(struct dvb_frontend* fe)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
// reset
|
||||
tda10086_write_byte(state, 0x00, 0x00);
|
||||
msleep(10);
|
||||
|
||||
// misc setup
|
||||
tda10086_write_byte(state, 0x01, 0x94);
|
||||
tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
|
||||
tda10086_write_byte(state, 0x03, 0x64);
|
||||
tda10086_write_byte(state, 0x04, 0x43);
|
||||
tda10086_write_byte(state, 0x0c, 0x0c);
|
||||
tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
|
||||
tda10086_write_byte(state, 0x20, 0x89); // misc
|
||||
tda10086_write_byte(state, 0x30, 0x04); // acquisition period length
|
||||
tda10086_write_byte(state, 0x32, 0x00); // irq off
|
||||
tda10086_write_byte(state, 0x31, 0x56); // setup AFC
|
||||
|
||||
// setup PLL (assumes 16Mhz XIN)
|
||||
tda10086_write_byte(state, 0x55, 0x2c); // misc PLL setup
|
||||
tda10086_write_byte(state, 0x3a, 0x0b); // M=12
|
||||
tda10086_write_byte(state, 0x3b, 0x01); // P=2
|
||||
tda10086_write_mask(state, 0x55, 0x20, 0x00); // powerup PLL
|
||||
|
||||
// setup TS interface
|
||||
tda10086_write_byte(state, 0x11, 0x81);
|
||||
tda10086_write_byte(state, 0x12, 0x81);
|
||||
tda10086_write_byte(state, 0x19, 0x40); // parallel mode A + MSBFIRST
|
||||
tda10086_write_byte(state, 0x56, 0x80); // powerdown WPLL - unused in the mode we use
|
||||
tda10086_write_byte(state, 0x57, 0x08); // bypass WPLL - unused in the mode we use
|
||||
tda10086_write_byte(state, 0x10, 0x2a);
|
||||
|
||||
// setup ADC
|
||||
tda10086_write_byte(state, 0x58, 0x61); // ADC setup
|
||||
tda10086_write_mask(state, 0x58, 0x01, 0x00); // powerup ADC
|
||||
|
||||
// setup AGC
|
||||
tda10086_write_byte(state, 0x05, 0x0B);
|
||||
tda10086_write_byte(state, 0x37, 0x63);
|
||||
tda10086_write_byte(state, 0x3f, 0x03); // NOTE: flydvb uses 0x0a and varies it
|
||||
tda10086_write_byte(state, 0x40, 0x64);
|
||||
tda10086_write_byte(state, 0x41, 0x4f);
|
||||
tda10086_write_byte(state, 0x42, 0x43);
|
||||
|
||||
// setup viterbi
|
||||
tda10086_write_byte(state, 0x1a, 0x11); // VBER 10^6, DVB, QPSK
|
||||
|
||||
// setup carrier recovery
|
||||
tda10086_write_byte(state, 0x3d, 0x80);
|
||||
|
||||
// setup SEC
|
||||
tda10086_write_byte(state, 0x36, 0x00); // all SEC off
|
||||
tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000))); // } tone frequency
|
||||
tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8); // }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tda10086_diseqc_wait(struct tda10086_state *state)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(200);
|
||||
while (!(tda10086_read_byte(state, 0x50) & 0x01)) {
|
||||
if(time_after(jiffies, timeout)) {
|
||||
printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
msleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
switch(tone) {
|
||||
case SEC_TONE_OFF:
|
||||
tda10086_write_byte(state, 0x36, 0x00);
|
||||
break;
|
||||
|
||||
case SEC_TONE_ON:
|
||||
tda10086_write_byte(state, 0x36, 0x01);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_send_master_cmd (struct dvb_frontend* fe,
|
||||
struct dvb_diseqc_master_cmd* cmd)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
int i;
|
||||
u8 oldval;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
if (cmd->msg_len > 6)
|
||||
return -EINVAL;
|
||||
oldval = tda10086_read_byte(state, 0x36);
|
||||
|
||||
for(i=0; i< cmd->msg_len; i++) {
|
||||
tda10086_write_byte(state, 0x48+i, cmd->msg[i]);
|
||||
}
|
||||
tda10086_write_byte(state, 0x36, 0x08 | ((cmd->msg_len + 1) << 4));
|
||||
|
||||
tda10086_diseqc_wait(state);
|
||||
|
||||
tda10086_write_byte(state, 0x36, oldval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
u8 oldval = tda10086_read_byte(state, 0x36);
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
switch(minicmd) {
|
||||
case SEC_MINI_A:
|
||||
tda10086_write_byte(state, 0x36, 0x04);
|
||||
break;
|
||||
|
||||
case SEC_MINI_B:
|
||||
tda10086_write_byte(state, 0x36, 0x06);
|
||||
break;
|
||||
}
|
||||
|
||||
tda10086_diseqc_wait(state);
|
||||
|
||||
tda10086_write_byte(state, 0x36, oldval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_set_inversion(struct tda10086_state *state,
|
||||
struct dvb_frontend_parameters *fe_params)
|
||||
{
|
||||
u8 invval = 0x80;
|
||||
|
||||
dprintk ("%s %i %i\n", __FUNCTION__, fe_params->inversion, state->config->invert);
|
||||
|
||||
switch(fe_params->inversion) {
|
||||
case INVERSION_OFF:
|
||||
if (state->config->invert)
|
||||
invval = 0x40;
|
||||
break;
|
||||
case INVERSION_ON:
|
||||
if (!state->config->invert)
|
||||
invval = 0x40;
|
||||
break;
|
||||
case INVERSION_AUTO:
|
||||
invval = 0x00;
|
||||
break;
|
||||
}
|
||||
tda10086_write_mask(state, 0x0c, 0xc0, invval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_set_symbol_rate(struct tda10086_state *state,
|
||||
struct dvb_frontend_parameters *fe_params)
|
||||
{
|
||||
u8 dfn = 0;
|
||||
u8 afs = 0;
|
||||
u8 byp = 0;
|
||||
u8 reg37 = 0x43;
|
||||
u8 reg42 = 0x43;
|
||||
u64 big;
|
||||
u32 tmp;
|
||||
u32 bdr;
|
||||
u32 bdri;
|
||||
u32 symbol_rate = fe_params->u.qpsk.symbol_rate;
|
||||
|
||||
dprintk ("%s %i\n", __FUNCTION__, symbol_rate);
|
||||
|
||||
// setup the decimation and anti-aliasing filters..
|
||||
if (symbol_rate < (u32) (SACLK * 0.0137)) {
|
||||
dfn=4;
|
||||
afs=1;
|
||||
} else if (symbol_rate < (u32) (SACLK * 0.0208)) {
|
||||
dfn=4;
|
||||
afs=0;
|
||||
} else if (symbol_rate < (u32) (SACLK * 0.0270)) {
|
||||
dfn=3;
|
||||
afs=1;
|
||||
} else if (symbol_rate < (u32) (SACLK * 0.0416)) {
|
||||
dfn=3;
|
||||
afs=0;
|
||||
} else if (symbol_rate < (u32) (SACLK * 0.0550)) {
|
||||
dfn=2;
|
||||
afs=1;
|
||||
} else if (symbol_rate < (u32) (SACLK * 0.0833)) {
|
||||
dfn=2;
|
||||
afs=0;
|
||||
} else if (symbol_rate < (u32) (SACLK * 0.1100)) {
|
||||
dfn=1;
|
||||
afs=1;
|
||||
} else if (symbol_rate < (u32) (SACLK * 0.1666)) {
|
||||
dfn=1;
|
||||
afs=0;
|
||||
} else if (symbol_rate < (u32) (SACLK * 0.2200)) {
|
||||
dfn=0;
|
||||
afs=1;
|
||||
} else if (symbol_rate < (u32) (SACLK * 0.3333)) {
|
||||
dfn=0;
|
||||
afs=0;
|
||||
} else {
|
||||
reg37 = 0x63;
|
||||
reg42 = 0x4f;
|
||||
byp=1;
|
||||
}
|
||||
|
||||
// calculate BDR
|
||||
big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
|
||||
big += ((SACLK/1000ULL)-1ULL);
|
||||
do_div(big, (SACLK/1000ULL));
|
||||
bdr = big & 0xfffff;
|
||||
|
||||
// calculate BDRI
|
||||
tmp = (1<<dfn)*(symbol_rate/1000);
|
||||
bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
|
||||
|
||||
tda10086_write_byte(state, 0x21, (afs << 7) | dfn);
|
||||
tda10086_write_mask(state, 0x20, 0x08, byp << 3);
|
||||
tda10086_write_byte(state, 0x06, bdr);
|
||||
tda10086_write_byte(state, 0x07, bdr >> 8);
|
||||
tda10086_write_byte(state, 0x08, bdr >> 16);
|
||||
tda10086_write_byte(state, 0x09, bdri);
|
||||
tda10086_write_byte(state, 0x37, reg37);
|
||||
tda10086_write_byte(state, 0x42, reg42);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_set_fec(struct tda10086_state *state,
|
||||
struct dvb_frontend_parameters *fe_params)
|
||||
{
|
||||
u8 fecval;
|
||||
|
||||
dprintk ("%s %i\n", __FUNCTION__, fe_params->u.qpsk.fec_inner);
|
||||
|
||||
switch(fe_params->u.qpsk.fec_inner) {
|
||||
case FEC_1_2:
|
||||
fecval = 0x00;
|
||||
break;
|
||||
case FEC_2_3:
|
||||
fecval = 0x01;
|
||||
break;
|
||||
case FEC_3_4:
|
||||
fecval = 0x02;
|
||||
break;
|
||||
case FEC_4_5:
|
||||
fecval = 0x03;
|
||||
break;
|
||||
case FEC_5_6:
|
||||
fecval = 0x04;
|
||||
break;
|
||||
case FEC_6_7:
|
||||
fecval = 0x05;
|
||||
break;
|
||||
case FEC_7_8:
|
||||
fecval = 0x06;
|
||||
break;
|
||||
case FEC_8_9:
|
||||
fecval = 0x07;
|
||||
break;
|
||||
case FEC_AUTO:
|
||||
fecval = 0x08;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
tda10086_write_byte(state, 0x0d, fecval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_set_frontend(struct dvb_frontend* fe,
|
||||
struct dvb_frontend_parameters *fe_params)
|
||||
{
|
||||
struct tda10086_state *state = fe->demodulator_priv;
|
||||
int ret;
|
||||
u32 freq = 0;
|
||||
int freqoff;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
// set params
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
fe->ops.tuner_ops.set_params(fe, fe_params);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
if (fe->ops.tuner_ops.get_frequency)
|
||||
fe->ops.tuner_ops.get_frequency(fe, &freq);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
}
|
||||
|
||||
// calcluate the frequency offset (in *Hz* not kHz)
|
||||
freqoff = fe_params->frequency - freq;
|
||||
freqoff = ((1<<16) * freqoff) / (SACLK/1000);
|
||||
tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));
|
||||
tda10086_write_byte(state, 0x3e, freqoff);
|
||||
|
||||
if ((ret = tda10086_set_inversion(state, fe_params)) < 0)
|
||||
return ret;
|
||||
if ((ret = tda10086_set_symbol_rate(state, fe_params)) < 0)
|
||||
return ret;
|
||||
if ((ret = tda10086_set_fec(state, fe_params)) < 0)
|
||||
return ret;
|
||||
|
||||
// soft reset + disable TS output until lock
|
||||
tda10086_write_mask(state, 0x10, 0x40, 0x40);
|
||||
tda10086_write_mask(state, 0x00, 0x01, 0x00);
|
||||
|
||||
state->symbol_rate = fe_params->u.qpsk.symbol_rate;
|
||||
state->frequency = fe_params->frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
u8 val;
|
||||
int tmp;
|
||||
u64 tmp64;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
// calculate the updated frequency (note: we convert from Hz->kHz)
|
||||
tmp64 = tda10086_read_byte(state, 0x52);
|
||||
tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
|
||||
if (tmp64 & 0x8000)
|
||||
tmp64 |= 0xffffffffffff0000ULL;
|
||||
tmp64 = (tmp64 * (SACLK/1000ULL));
|
||||
do_div(tmp64, (1ULL<<15) * (1ULL<<1));
|
||||
fe_params->frequency = (int) state->frequency + (int) tmp64;
|
||||
|
||||
// the inversion
|
||||
val = tda10086_read_byte(state, 0x0c);
|
||||
if (val & 0x80) {
|
||||
switch(val & 0x40) {
|
||||
case 0x00:
|
||||
fe_params->inversion = INVERSION_OFF;
|
||||
if (state->config->invert)
|
||||
fe_params->inversion = INVERSION_ON;
|
||||
break;
|
||||
default:
|
||||
fe_params->inversion = INVERSION_ON;
|
||||
if (state->config->invert)
|
||||
fe_params->inversion = INVERSION_OFF;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
tda10086_read_byte(state, 0x0f);
|
||||
switch(val & 0x02) {
|
||||
case 0x00:
|
||||
fe_params->inversion = INVERSION_OFF;
|
||||
if (state->config->invert)
|
||||
fe_params->inversion = INVERSION_ON;
|
||||
break;
|
||||
default:
|
||||
fe_params->inversion = INVERSION_ON;
|
||||
if (state->config->invert)
|
||||
fe_params->inversion = INVERSION_OFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate the updated symbol rate
|
||||
tmp = tda10086_read_byte(state, 0x1d);
|
||||
if (tmp & 0x80)
|
||||
tmp |= 0xffffff00;
|
||||
tmp = (tmp * 480 * (1<<1)) / 128;
|
||||
tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
|
||||
fe_params->u.qpsk.symbol_rate = state->symbol_rate + tmp;
|
||||
|
||||
// the FEC
|
||||
val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
|
||||
switch(val) {
|
||||
case 0x00:
|
||||
fe_params->u.qpsk.fec_inner = FEC_1_2;
|
||||
break;
|
||||
case 0x01:
|
||||
fe_params->u.qpsk.fec_inner = FEC_2_3;
|
||||
break;
|
||||
case 0x02:
|
||||
fe_params->u.qpsk.fec_inner = FEC_3_4;
|
||||
break;
|
||||
case 0x03:
|
||||
fe_params->u.qpsk.fec_inner = FEC_4_5;
|
||||
break;
|
||||
case 0x04:
|
||||
fe_params->u.qpsk.fec_inner = FEC_5_6;
|
||||
break;
|
||||
case 0x05:
|
||||
fe_params->u.qpsk.fec_inner = FEC_6_7;
|
||||
break;
|
||||
case 0x06:
|
||||
fe_params->u.qpsk.fec_inner = FEC_7_8;
|
||||
break;
|
||||
case 0x07:
|
||||
fe_params->u.qpsk.fec_inner = FEC_8_9;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
u8 val;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
val = tda10086_read_byte(state, 0x0e);
|
||||
*fe_status = 0;
|
||||
if (val & 0x01)
|
||||
*fe_status |= FE_HAS_SIGNAL;
|
||||
if (val & 0x02)
|
||||
*fe_status |= FE_HAS_CARRIER;
|
||||
if (val & 0x04)
|
||||
*fe_status |= FE_HAS_VITERBI;
|
||||
if (val & 0x08)
|
||||
*fe_status |= FE_HAS_SYNC;
|
||||
if (val & 0x10)
|
||||
*fe_status |= FE_HAS_LOCK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
u8 _str;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
_str = tda10086_read_byte(state, 0x43);
|
||||
*signal = (_str << 8) | _str;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
u8 _snr;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
_snr = tda10086_read_byte(state, 0x1c);
|
||||
*snr = (_snr << 8) | _snr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
// read it
|
||||
*ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
|
||||
|
||||
// reset counter
|
||||
tda10086_write_byte(state, 0x18, 0x00);
|
||||
tda10086_write_byte(state, 0x18, 0x80);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
// read it
|
||||
*ber = 0;
|
||||
*ber |= tda10086_read_byte(state, 0x15);
|
||||
*ber |= tda10086_read_byte(state, 0x16) << 8;
|
||||
*ber |= (tda10086_read_byte(state, 0x17) & 0xf) << 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_sleep(struct dvb_frontend* fe)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
tda10086_write_mask(state, 0x00, 0x08, 0x08);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
|
||||
{
|
||||
struct tda10086_state* state = fe->demodulator_priv;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
if (enable) {
|
||||
tda10086_write_mask(state, 0x00, 0x10, 0x10);
|
||||
} else {
|
||||
tda10086_write_mask(state, 0x00, 0x10, 0x00);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda10086_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
|
||||
{
|
||||
if (fesettings->parameters.u.qpsk.symbol_rate > 20000000) {
|
||||
fesettings->min_delay_ms = 50;
|
||||
fesettings->step_size = 2000;
|
||||
fesettings->max_drift = 8000;
|
||||
} else if (fesettings->parameters.u.qpsk.symbol_rate > 12000000) {
|
||||
fesettings->min_delay_ms = 100;
|
||||
fesettings->step_size = 1500;
|
||||
fesettings->max_drift = 9000;
|
||||
} else if (fesettings->parameters.u.qpsk.symbol_rate > 8000000) {
|
||||
fesettings->min_delay_ms = 100;
|
||||
fesettings->step_size = 1000;
|
||||
fesettings->max_drift = 8000;
|
||||
} else if (fesettings->parameters.u.qpsk.symbol_rate > 4000000) {
|
||||
fesettings->min_delay_ms = 100;
|
||||
fesettings->step_size = 500;
|
||||
fesettings->max_drift = 7000;
|
||||
} else if (fesettings->parameters.u.qpsk.symbol_rate > 2000000) {
|
||||
fesettings->min_delay_ms = 200;
|
||||
fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
|
||||
fesettings->max_drift = 14 * fesettings->step_size;
|
||||
} else {
|
||||
fesettings->min_delay_ms = 200;
|
||||
fesettings->step_size = (fesettings->parameters.u.qpsk.symbol_rate / 8000);
|
||||
fesettings->max_drift = 18 * fesettings->step_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tda10086_release(struct dvb_frontend* fe)
|
||||
{
|
||||
struct tda10086_state *state = fe->demodulator_priv;
|
||||
tda10086_sleep(fe);
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops tda10086_ops = {
|
||||
|
||||
.info = {
|
||||
.name = "Philips TDA10086 DVB-S",
|
||||
.type = FE_QPSK,
|
||||
.frequency_min = 950000,
|
||||
.frequency_max = 2150000,
|
||||
.frequency_stepsize = 125, /* kHz for QPSK frontends */
|
||||
.symbol_rate_min = 1000000,
|
||||
.symbol_rate_max = 45000000,
|
||||
.caps = FE_CAN_INVERSION_AUTO |
|
||||
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
|
||||
FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
|
||||
FE_CAN_QPSK
|
||||
},
|
||||
|
||||
.release = tda10086_release,
|
||||
|
||||
.init = tda10086_init,
|
||||
.sleep = tda10086_sleep,
|
||||
.i2c_gate_ctrl = tda10086_i2c_gate_ctrl,
|
||||
|
||||
.set_frontend = tda10086_set_frontend,
|
||||
.get_frontend = tda10086_get_frontend,
|
||||
.get_tune_settings = tda10086_get_tune_settings,
|
||||
|
||||
.read_status = tda10086_read_status,
|
||||
.read_ber = tda10086_read_ber,
|
||||
.read_signal_strength = tda10086_read_signal_strength,
|
||||
.read_snr = tda10086_read_snr,
|
||||
.read_ucblocks = tda10086_read_ucblocks,
|
||||
|
||||
.diseqc_send_master_cmd = tda10086_send_master_cmd,
|
||||
.diseqc_send_burst = tda10086_send_burst,
|
||||
.set_tone = tda10086_set_tone,
|
||||
};
|
||||
|
||||
struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
struct tda10086_state *state;
|
||||
|
||||
dprintk ("%s\n", __FUNCTION__);
|
||||
|
||||
/* allocate memory for the internal state */
|
||||
state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
/* setup the state */
|
||||
state->config = config;
|
||||
state->i2c = i2c;
|
||||
|
||||
/* check if the demod is there */
|
||||
if (tda10086_read_byte(state, 0x1e) != 0xe1) {
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create dvb_frontend */
|
||||
memcpy(&state->frontend.ops, &tda10086_ops, sizeof(struct dvb_frontend_ops));
|
||||
state->frontend.demodulator_priv = state;
|
||||
return &state->frontend;
|
||||
}
|
||||
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
|
||||
|
||||
MODULE_DESCRIPTION("Philips TDA10086 DVB-S Demodulator");
|
||||
MODULE_AUTHOR("Andrew de Quincey");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(tda10086_attach);
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
Driver for Philips tda10086 DVBS Frontend
|
||||
|
||||
(c) 2006 Andrew de Quincey
|
||||
|
||||
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 TDA10086_H
|
||||
#define TDA10086_H
|
||||
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
struct tda10086_config
|
||||
{
|
||||
/* the demodulator's i2c address */
|
||||
u8 demod_address;
|
||||
|
||||
/* does the "inversion" need inverted? */
|
||||
u8 invert;
|
||||
};
|
||||
|
||||
extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
|
||||
#endif // TDA10086_H
|
|
@ -35,7 +35,16 @@ struct tda8083_config
|
|||
u8 demod_address;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_TDA8083) || defined(CONFIG_DVB_TDA8083_MODULE)
|
||||
extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_TDA8083
|
||||
|
||||
#endif // TDA8083_H
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
Driver for Philips tda8262/tda8263 DVBS Silicon tuners
|
||||
|
||||
(c) 2006 Andrew de Quincey
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
#include "tda826x.h"
|
||||
|
||||
static int debug = 0;
|
||||
#define dprintk(args...) \
|
||||
do { \
|
||||
if (debug) printk(KERN_DEBUG "tda826x: " args); \
|
||||
} while (0)
|
||||
|
||||
struct tda826x_priv {
|
||||
/* i2c details */
|
||||
int i2c_address;
|
||||
struct i2c_adapter *i2c;
|
||||
u8 has_loopthrough:1;
|
||||
u32 frequency;
|
||||
};
|
||||
|
||||
static int tda826x_release(struct dvb_frontend *fe)
|
||||
{
|
||||
if (fe->tuner_priv)
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda826x_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tda826x_priv *priv = fe->tuner_priv;
|
||||
int ret;
|
||||
u8 buf [] = { 0x00, 0x8d };
|
||||
struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 };
|
||||
|
||||
dprintk("%s:\n", __FUNCTION__);
|
||||
|
||||
if (!priv->has_loopthrough)
|
||||
buf[1] = 0xad;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
|
||||
dprintk("%s: i2c error\n", __FUNCTION__);
|
||||
}
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
return (ret == 1) ? 0 : ret;
|
||||
}
|
||||
|
||||
static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct tda826x_priv *priv = fe->tuner_priv;
|
||||
int ret;
|
||||
u32 div;
|
||||
u8 buf [11];
|
||||
struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 };
|
||||
|
||||
dprintk("%s:\n", __FUNCTION__);
|
||||
|
||||
div = (params->frequency + (1000-1)) / 1000;
|
||||
|
||||
buf[0] = 0x00; // subaddress
|
||||
buf[1] = 0x09; // powerdown RSSI + the magic value 1
|
||||
if (!priv->has_loopthrough)
|
||||
buf[1] |= 0x20; // power down loopthrough if not needed
|
||||
buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
|
||||
buf[3] = div >> 7;
|
||||
buf[4] = div << 1;
|
||||
buf[5] = 0xff; // basedband filter to max
|
||||
buf[6] = 0xfe; // gains at max + no RF attenuation
|
||||
buf[7] = 0x83; // charge pumps at high, tests off
|
||||
buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
|
||||
buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL
|
||||
buf[10] = 0xd4; // recommended value 13 for BBIAS + unknown bit set on
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
|
||||
dprintk("%s: i2c error\n", __FUNCTION__);
|
||||
}
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
priv->frequency = div * 1000;
|
||||
|
||||
return (ret == 1) ? 0 : ret;
|
||||
}
|
||||
|
||||
static int tda826x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct tda826x_priv *priv = fe->tuner_priv;
|
||||
*frequency = priv->frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_tuner_ops tda826x_tuner_ops = {
|
||||
.info = {
|
||||
.name = "Philips TDA826X",
|
||||
.frequency_min = 950000,
|
||||
.frequency_min = 2175000
|
||||
},
|
||||
.release = tda826x_release,
|
||||
.sleep = tda826x_sleep,
|
||||
.set_params = tda826x_set_params,
|
||||
.get_frequency = tda826x_get_frequency,
|
||||
};
|
||||
|
||||
struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough)
|
||||
{
|
||||
struct tda826x_priv *priv = NULL;
|
||||
u8 b1 [] = { 0, 0 };
|
||||
struct i2c_msg msg = { .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);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
if (ret != 1)
|
||||
return NULL;
|
||||
if (!(b1[1] & 0x80))
|
||||
return NULL;
|
||||
|
||||
priv = kzalloc(sizeof(struct tda826x_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
priv->i2c_address = addr;
|
||||
priv->i2c = i2c;
|
||||
priv->has_loopthrough = has_loopthrough;
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &tda826x_tuner_ops, sizeof(struct dvb_tuner_ops));
|
||||
|
||||
fe->tuner_priv = priv;
|
||||
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(tda826x_attach);
|
||||
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
|
||||
|
||||
MODULE_DESCRIPTION("DVB TDA826x driver");
|
||||
MODULE_AUTHOR("Andrew de Quincey");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Driver for Philips tda8262/tda8263 DVBS Silicon tuners
|
||||
|
||||
(c) 2006 Andrew de Quincey
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __DVB_TDA826X_H__
|
||||
#define __DVB_TDA826X_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
/**
|
||||
* Attach a tda826x tuner to the supplied frontend structure.
|
||||
*
|
||||
* @param fe Frontend to attach to.
|
||||
* @param addr i2c address of the tuner.
|
||||
* @param i2c i2c adapter to use.
|
||||
* @param has_loopthrough Set to 1 if the card has a loopthrough RF connector.
|
||||
* @return FE pointer on success, NULL on failure.
|
||||
*/
|
||||
extern struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,205 @@
|
|||
/**
|
||||
* Driver for Infineon tua6100 pll.
|
||||
*
|
||||
* (c) 2006 Andrew de Quincey
|
||||
*
|
||||
* Based on code found in budget-av.c, which has the following:
|
||||
* Compiled from various sources by Michael Hunold <michael@mihu.de>
|
||||
*
|
||||
* CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
|
||||
* Andrew de Quincey <adq_dvb@lidskialf.net>
|
||||
*
|
||||
* Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
|
||||
*
|
||||
* Copyright (C) 1999-2002 Ralph Metzler
|
||||
* & Marcus Metzler for convergence integrated media GmbH
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/dvb/frontend.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
#include "tua6100.h"
|
||||
|
||||
struct tua6100_priv {
|
||||
/* i2c details */
|
||||
int i2c_address;
|
||||
struct i2c_adapter *i2c;
|
||||
u32 frequency;
|
||||
};
|
||||
|
||||
static int tua6100_release(struct dvb_frontend *fe)
|
||||
{
|
||||
if (fe->tuner_priv)
|
||||
kfree(fe->tuner_priv);
|
||||
fe->tuner_priv = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tua6100_sleep(struct dvb_frontend *fe)
|
||||
{
|
||||
struct tua6100_priv *priv = fe->tuner_priv;
|
||||
int ret;
|
||||
u8 reg0[] = { 0x00, 0x00 };
|
||||
struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = reg0, .len = 2 };
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
|
||||
printk("%s: i2c error\n", __FUNCTION__);
|
||||
}
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
return (ret == 1) ? 0 : ret;
|
||||
}
|
||||
|
||||
static int tua6100_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
struct tua6100_priv *priv = fe->tuner_priv;
|
||||
u32 div;
|
||||
u32 prediv;
|
||||
u8 reg0[] = { 0x00, 0x00 };
|
||||
u8 reg1[] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
u8 reg2[] = { 0x02, 0x00, 0x00 };
|
||||
struct i2c_msg msg0 = { .addr = priv->i2c_address, .flags = 0, .buf = reg0, .len = 2 };
|
||||
struct i2c_msg msg1 = { .addr = priv->i2c_address, .flags = 0, .buf = reg1, .len = 4 };
|
||||
struct i2c_msg msg2 = { .addr = priv->i2c_address, .flags = 0, .buf = reg2, .len = 3 };
|
||||
|
||||
#define _R 4
|
||||
#define _P 32
|
||||
#define _ri 4000000
|
||||
|
||||
// setup register 0
|
||||
if (params->frequency < 2000000) {
|
||||
reg0[1] = 0x03;
|
||||
} else {
|
||||
reg0[1] = 0x07;
|
||||
}
|
||||
|
||||
// setup register 1
|
||||
if (params->frequency < 1630000) {
|
||||
reg1[1] = 0x2c;
|
||||
} else {
|
||||
reg1[1] = 0x0c;
|
||||
}
|
||||
if (_P == 64)
|
||||
reg1[1] |= 0x40;
|
||||
if (params->frequency >= 1525000)
|
||||
reg1[1] |= 0x80;
|
||||
|
||||
// register 2
|
||||
reg2[1] = (_R >> 8) & 0x03;
|
||||
reg2[2] = _R;
|
||||
if (params->frequency < 1455000) {
|
||||
reg2[1] |= 0x1c;
|
||||
} else if (params->frequency < 1630000) {
|
||||
reg2[1] |= 0x0c;
|
||||
} else {
|
||||
reg2[1] |= 0x1c;
|
||||
}
|
||||
|
||||
// The N divisor ratio (note: params->frequency is in kHz, but we need it in Hz)
|
||||
prediv = (params->frequency * _R) / (_ri / 1000);
|
||||
div = prediv / _P;
|
||||
reg1[1] |= (div >> 9) & 0x03;
|
||||
reg1[2] = div >> 1;
|
||||
reg1[3] = (div << 7);
|
||||
priv->frequency = ((div * _P) * (_ri / 1000)) / _R;
|
||||
|
||||
// Finally, calculate and store the value for A
|
||||
reg1[3] |= (prediv - (div*_P)) & 0x7f;
|
||||
|
||||
#undef _R
|
||||
#undef _P
|
||||
#undef _ri
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer(priv->i2c, &msg0, 1) != 1)
|
||||
return -EIO;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer(priv->i2c, &msg2, 1) != 1)
|
||||
return -EIO;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
if (i2c_transfer(priv->i2c, &msg1, 1) != 1)
|
||||
return -EIO;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tua6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
|
||||
{
|
||||
struct tua6100_priv *priv = fe->tuner_priv;
|
||||
*frequency = priv->frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_tuner_ops tua6100_tuner_ops = {
|
||||
.info = {
|
||||
.name = "Infineon TUA6100",
|
||||
.frequency_min = 950000,
|
||||
.frequency_max = 2150000,
|
||||
.frequency_step = 1000,
|
||||
},
|
||||
.release = tua6100_release,
|
||||
.sleep = tua6100_sleep,
|
||||
.set_params = tua6100_set_params,
|
||||
.get_frequency = tua6100_get_frequency,
|
||||
};
|
||||
|
||||
struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
|
||||
{
|
||||
struct tua6100_priv *priv = NULL;
|
||||
u8 b1 [] = { 0x80 };
|
||||
u8 b2 [] = { 0x00 };
|
||||
struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b1, .len = 1 },
|
||||
{ .addr = addr, .flags = I2C_M_RD, .buf = b2, .len = 1 } };
|
||||
int ret;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
ret = i2c_transfer (i2c, msg, 2);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
|
||||
if (ret != 2)
|
||||
return NULL;
|
||||
|
||||
priv = kzalloc(sizeof(struct tua6100_priv), GFP_KERNEL);
|
||||
if (priv == NULL)
|
||||
return NULL;
|
||||
|
||||
priv->i2c_address = addr;
|
||||
priv->i2c = i2c;
|
||||
|
||||
memcpy(&fe->ops.tuner_ops, &tua6100_tuner_ops, sizeof(struct dvb_tuner_ops));
|
||||
fe->tuner_priv = priv;
|
||||
return fe;
|
||||
}
|
||||
EXPORT_SYMBOL(tua6100_attach);
|
||||
|
||||
MODULE_DESCRIPTION("DVB tua6100 driver");
|
||||
MODULE_AUTHOR("Andrew de Quincey");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Driver for Infineon tua6100 PLL.
|
||||
*
|
||||
* (c) 2006 Andrew de Quincey
|
||||
*
|
||||
* Based on code found in budget-av.c, which has the following:
|
||||
* Compiled from various sources by Michael Hunold <michael@mihu.de>
|
||||
*
|
||||
* CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
|
||||
* Andrew de Quincey <adq_dvb@lidskialf.net>
|
||||
*
|
||||
* Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
|
||||
*
|
||||
* Copyright (C) 1999-2002 Ralph Metzler
|
||||
* & Marcus Metzler for convergence integrated media GmbH
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __DVB_TUA6100_H__
|
||||
#define __DVB_TUA6100_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
#if defined(CONFIG_DVB_TUA6100) || defined(CONFIG_DVB_TUA6100_MODULE)
|
||||
extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_TUA6100
|
||||
|
||||
#endif
|
|
@ -41,7 +41,16 @@ struct ves1820_config
|
|||
u8 selagc:1;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_VES1820) || defined(CONFIG_DVB_VES1820_MODULE)
|
||||
extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
|
||||
struct i2c_adapter* i2c, u8 pwm);
|
||||
#else
|
||||
static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
|
||||
struct i2c_adapter* i2c, u8 pwm)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_VES1820
|
||||
|
||||
#endif // VES1820_H
|
||||
|
|
|
@ -40,7 +40,16 @@ struct ves1x93_config
|
|||
u8 invert_pwm:1;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_VES1X93) || defined(CONFIG_DVB_VES1X93_MODULE)
|
||||
extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
|
||||
struct i2c_adapter* i2c);
|
||||
#else
|
||||
static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
|
||||
struct i2c_adapter* i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_VES1X93
|
||||
|
||||
#endif // VES1X93_H
|
||||
|
|
|
@ -140,6 +140,8 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
|
|||
zl10353_single_write(fe, 0x5E, 0x00);
|
||||
zl10353_single_write(fe, 0x65, 0x5A);
|
||||
zl10353_single_write(fe, 0x66, 0xE9);
|
||||
zl10353_single_write(fe, 0x6C, 0xCD);
|
||||
zl10353_single_write(fe, 0x6D, 0x7E);
|
||||
zl10353_single_write(fe, 0x62, 0x0A);
|
||||
|
||||
// if there is no attached secondary tuner, we call set_params to program
|
||||
|
@ -168,6 +170,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe,
|
|||
// even if there isn't a PLL attached to the secondary bus
|
||||
zl10353_write(fe, pllbuf, sizeof(pllbuf));
|
||||
|
||||
zl10353_single_write(fe, 0x5F, 0x13);
|
||||
zl10353_single_write(fe, 0x70, 0x01);
|
||||
udelay(250);
|
||||
zl10353_single_write(fe, 0xE4, 0x00);
|
||||
|
@ -243,9 +246,12 @@ static int zl10353_init(struct dvb_frontend *fe)
|
|||
|
||||
if (debug_regs)
|
||||
zl10353_dump_regs(fe);
|
||||
if (state->config.parallel_ts)
|
||||
zl10353_reset_attach[2] &= ~0x20;
|
||||
|
||||
/* Do a "hard" reset if not already done */
|
||||
if (zl10353_read_register(state, 0x50) != 0x03) {
|
||||
if (zl10353_read_register(state, 0x50) != zl10353_reset_attach[1] ||
|
||||
zl10353_read_register(state, 0x51) != zl10353_reset_attach[2]) {
|
||||
rc = zl10353_write(fe, zl10353_reset_attach,
|
||||
sizeof(zl10353_reset_attach));
|
||||
if (debug_regs)
|
||||
|
@ -258,7 +264,6 @@ static int zl10353_init(struct dvb_frontend *fe)
|
|||
static void zl10353_release(struct dvb_frontend *fe)
|
||||
{
|
||||
struct zl10353_state *state = fe->demodulator_priv;
|
||||
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
|
@ -314,6 +319,7 @@ static struct dvb_frontend_ops zl10353_ops = {
|
|||
|
||||
.init = zl10353_init,
|
||||
.sleep = zl10353_sleep,
|
||||
.write = zl10353_write,
|
||||
|
||||
.set_frontend = zl10353_set_parameters,
|
||||
.get_tune_settings = zl10353_get_tune_settings,
|
||||
|
@ -330,4 +336,3 @@ MODULE_AUTHOR("Chris Pascoe");
|
|||
MODULE_LICENSE("GPL");
|
||||
|
||||
EXPORT_SYMBOL(zl10353_attach);
|
||||
EXPORT_SYMBOL(zl10353_write);
|
||||
|
|
|
@ -31,11 +31,21 @@ struct zl10353_config
|
|||
|
||||
/* set if no pll is connected to the secondary i2c bus */
|
||||
int no_tuner;
|
||||
|
||||
/* set if parallel ts output is required */
|
||||
int parallel_ts;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_ZL10353) || defined(CONFIG_DVB_ZL10353_MODULE)
|
||||
extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
|
||||
struct i2c_adapter *i2c);
|
||||
|
||||
extern int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen);
|
||||
#else
|
||||
static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
|
||||
struct i2c_adapter *i2c)
|
||||
{
|
||||
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
#endif // CONFIG_DVB_ZL10353
|
||||
|
||||
#endif /* ZL10353_H */
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
config DVB_AV7110
|
||||
tristate "AV7110 cards"
|
||||
depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
|
||||
select FW_LOADER
|
||||
select FW_LOADER if !DVB_AV7110_FIRMWARE
|
||||
select VIDEO_SAA7146_VV
|
||||
select DVB_PLL
|
||||
select DVB_VES1820
|
||||
select DVB_VES1X93
|
||||
select DVB_STV0299
|
||||
select DVB_TDA8083
|
||||
select DVB_SP8870
|
||||
select DVB_STV0297
|
||||
select DVB_L64781
|
||||
select DVB_LNBP21
|
||||
select DVB_VES1820 if !DVB_FE_CUSTOMISE
|
||||
select DVB_VES1X93 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0299 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA8083 if !DVB_FE_CUSTOMISE
|
||||
select DVB_SP8870 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0297 if !DVB_FE_CUSTOMISE
|
||||
select DVB_L64781 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Support for SAA7146 and AV7110 based DVB cards as produced
|
||||
by Fujitsu-Siemens, Technotrend, Hauppauge and others.
|
||||
|
@ -63,14 +63,16 @@ config DVB_BUDGET
|
|||
depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
|
||||
select VIDEO_SAA7146
|
||||
select DVB_PLL
|
||||
select DVB_STV0299
|
||||
select DVB_VES1X93
|
||||
select DVB_VES1820
|
||||
select DVB_L64781
|
||||
select DVB_TDA8083
|
||||
select DVB_TDA10021
|
||||
select DVB_S5H1420
|
||||
select DVB_LNBP21
|
||||
select DVB_STV0299 if !DVB_FE_CUSTOMISE
|
||||
select DVB_VES1X93 if !DVB_FE_CUSTOMISE
|
||||
select DVB_VES1820 if !DVB_FE_CUSTOMISE
|
||||
select DVB_L64781 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA8083 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA10021 if !DVB_FE_CUSTOMISE
|
||||
select DVB_S5H1420 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA10086 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA826X if !DVB_FE_CUSTOMISE
|
||||
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Support for simple SAA7146 based DVB cards
|
||||
(so called Budget- or Nova-PCI cards) without onboard
|
||||
|
@ -86,10 +88,10 @@ config DVB_BUDGET_CI
|
|||
depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
|
||||
select VIDEO_SAA7146
|
||||
select DVB_PLL
|
||||
select DVB_STV0297
|
||||
select DVB_STV0299
|
||||
select DVB_TDA1004X
|
||||
select DVB_LNBP21
|
||||
select DVB_STV0297 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0299 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
|
||||
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Support for simple SAA7146 based DVB cards
|
||||
(so called Budget- or Nova-PCI cards) without onboard
|
||||
|
@ -108,9 +110,10 @@ config DVB_BUDGET_AV
|
|||
depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
|
||||
select VIDEO_SAA7146_VV
|
||||
select DVB_PLL
|
||||
select DVB_STV0299
|
||||
select DVB_TDA1004X
|
||||
select DVB_TDA10021
|
||||
select DVB_STV0299 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA1004X if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA10021 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TUA6100 if !DVB_FE_CUSTOMISE
|
||||
select FW_LOADER
|
||||
help
|
||||
Support for simple SAA7146 based DVB cards
|
||||
|
@ -127,9 +130,9 @@ config DVB_BUDGET_PATCH
|
|||
depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1
|
||||
select DVB_AV7110
|
||||
select DVB_PLL
|
||||
select DVB_STV0299
|
||||
select DVB_VES1X93
|
||||
select DVB_TDA8083
|
||||
select DVB_STV0299 if !DVB_FE_CUSTOMISE
|
||||
select DVB_VES1X93 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA8083 if !DVB_FE_CUSTOMISE
|
||||
help
|
||||
Support for Budget Patch (full TS) modification on
|
||||
SAA7146+AV7110 based cards (DVB-S cards). This
|
||||
|
|
|
@ -1383,8 +1383,10 @@ static void dvb_unregister(struct av7110 *av7110)
|
|||
dvb_dmxdev_release(&av7110->dmxdev);
|
||||
dvb_dmx_release(&av7110->demux);
|
||||
|
||||
if (av7110->fe != NULL)
|
||||
if (av7110->fe != NULL) {
|
||||
dvb_unregister_frontend(av7110->fe);
|
||||
dvb_frontend_detach(av7110->fe);
|
||||
}
|
||||
dvb_unregister_device(av7110->osd_dev);
|
||||
av7110_av_unregister(av7110);
|
||||
av7110_ca_unregister(av7110);
|
||||
|
@ -1699,9 +1701,13 @@ static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_front
|
|||
|
||||
static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
|
||||
{
|
||||
#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
|
||||
struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
|
||||
|
||||
return request_firmware(fw, name, &av7110->dev->pci->dev);
|
||||
#else
|
||||
return -EINVAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct sp8870_config alps_tdlb7_config = {
|
||||
|
@ -2077,7 +2083,7 @@ static int frontend_init(struct av7110 *av7110)
|
|||
if (av7110->dev->pci->subsystem_vendor == 0x110a) {
|
||||
switch(av7110->dev->pci->subsystem_device) {
|
||||
case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
|
||||
av7110->fe = ves1820_attach(&philips_cd1516_config,
|
||||
av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
|
||||
&av7110->i2c_adap, read_pwm(av7110));
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
|
||||
|
@ -2092,7 +2098,7 @@ static int frontend_init(struct av7110 *av7110)
|
|||
case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
|
||||
|
||||
// try the ALPS BSRV2 first of all
|
||||
av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
|
||||
av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
|
||||
av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
||||
|
@ -2103,7 +2109,7 @@ static int frontend_init(struct av7110 *av7110)
|
|||
}
|
||||
|
||||
// try the ALPS BSRU6 now
|
||||
av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);
|
||||
av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
|
||||
av7110->fe->tuner_priv = &av7110->i2c_adap;
|
||||
|
@ -2116,7 +2122,7 @@ static int frontend_init(struct av7110 *av7110)
|
|||
}
|
||||
|
||||
// Try the grundig 29504-451
|
||||
av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
|
||||
av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
|
||||
av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
||||
|
@ -2130,7 +2136,7 @@ static int frontend_init(struct av7110 *av7110)
|
|||
switch(av7110->dev->pci->subsystem_device) {
|
||||
case 0x0000:
|
||||
/* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
|
||||
av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap,
|
||||
av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
|
||||
read_pwm(av7110));
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
|
||||
|
@ -2138,7 +2144,7 @@ static int frontend_init(struct av7110 *av7110)
|
|||
break;
|
||||
case 0x0003:
|
||||
/* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
|
||||
av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
|
||||
av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
|
||||
read_pwm(av7110));
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
|
||||
|
@ -2148,17 +2154,24 @@ static int frontend_init(struct av7110 *av7110)
|
|||
break;
|
||||
|
||||
case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
|
||||
|
||||
// ALPS TDLB7
|
||||
av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
|
||||
// try ALPS TDLB7 first, then Grundig 29504-401
|
||||
av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
|
||||
break;
|
||||
}
|
||||
/* fall-thru */
|
||||
|
||||
case 0x0008: // Hauppauge/TT DVB-T
|
||||
// Grundig 29504-401
|
||||
av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
|
||||
if (av7110->fe)
|
||||
av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
|
||||
break;
|
||||
|
||||
case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
|
||||
|
||||
av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
|
||||
av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
|
||||
}
|
||||
|
@ -2166,7 +2179,7 @@ static int frontend_init(struct av7110 *av7110)
|
|||
|
||||
case 0x0004: // Galaxis DVB-S rev1.3
|
||||
/* ALPS BSRV2 */
|
||||
av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
|
||||
av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
|
||||
av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
||||
|
@ -2178,7 +2191,7 @@ static int frontend_init(struct av7110 *av7110)
|
|||
|
||||
case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
|
||||
/* Grundig 29504-451 */
|
||||
av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
|
||||
av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
|
||||
av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
|
||||
|
@ -2188,17 +2201,9 @@ static int frontend_init(struct av7110 *av7110)
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x0008: // Hauppauge/TT DVB-T
|
||||
|
||||
av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
|
||||
|
||||
av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
|
||||
av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
|
||||
|
||||
|
@ -2214,12 +2219,12 @@ static int frontend_init(struct av7110 *av7110)
|
|||
|
||||
case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
|
||||
/* ALPS BSBE1 */
|
||||
av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
|
||||
av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
|
||||
if (av7110->fe) {
|
||||
av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
|
||||
av7110->fe->tuner_priv = &av7110->i2c_adap;
|
||||
|
||||
if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) {
|
||||
if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
|
||||
printk("dvb-ttpci: LNBP21 not found!\n");
|
||||
if (av7110->fe->ops.release)
|
||||
av7110->fe->ops.release(av7110->fe);
|
||||
|
@ -2255,8 +2260,7 @@ static int frontend_init(struct av7110 *av7110)
|
|||
ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
|
||||
if (ret < 0) {
|
||||
printk("av7110: Frontend registration failed!\n");
|
||||
if (av7110->fe->ops.release)
|
||||
av7110->fe->ops.release(av7110->fe);
|
||||
dvb_frontend_detach(av7110->fe);
|
||||
av7110->fe = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -2823,7 +2827,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
|
|||
|
||||
|
||||
static struct saa7146_extension av7110_extension = {
|
||||
.name = "dvb\0",
|
||||
.name = "dvb",
|
||||
.flags = SAA7146_I2C_SHORT_DELAY,
|
||||
|
||||
.module = THIS_MODULE,
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/byteorder/swabb.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <linux/fs.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/byteorder/swabb.h>
|
||||
#include <linux/smp_lock.h>
|
||||
|
||||
#include "av7110.h"
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/byteorder/swabb.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <linux/fs.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/byteorder/swabb.h>
|
||||
#include <linux/smp_lock.h>
|
||||
|
||||
#include "av7110.h"
|
||||
|
@ -922,7 +921,7 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
|
|||
static struct saa7146_ext_vv av7110_vv_data_c = {
|
||||
.inputs = 1,
|
||||
.audios = 1,
|
||||
.capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT,
|
||||
.capabilities = V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT,
|
||||
.flags = SAA7146_USE_PORT_B_FOR_VBI,
|
||||
|
||||
.stds = &standard[0],
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "stv0299.h"
|
||||
#include "tda10021.h"
|
||||
#include "tda1004x.h"
|
||||
#include "tua6100.h"
|
||||
#include "dvb-pll.h"
|
||||
#include <media/saa7146_vv.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -235,7 +236,7 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
|
|||
|
||||
/* set tda10021 back to original clock configuration on reset */
|
||||
if (budget_av->tda10021_poclkp) {
|
||||
tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
|
||||
tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0);
|
||||
budget_av->tda10021_ts_enabled = 0;
|
||||
}
|
||||
|
||||
|
@ -257,7 +258,7 @@ static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
|
|||
|
||||
/* set tda10021 back to original clock configuration when cam removed */
|
||||
if (budget_av->tda10021_poclkp) {
|
||||
tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
|
||||
tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0);
|
||||
budget_av->tda10021_ts_enabled = 0;
|
||||
}
|
||||
return 0;
|
||||
|
@ -277,7 +278,7 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
|
|||
|
||||
/* tda10021 seems to need a different TS clock config when data is routed to the CAM */
|
||||
if (budget_av->tda10021_poclkp) {
|
||||
tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
|
||||
tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa1);
|
||||
budget_av->tda10021_ts_enabled = 1;
|
||||
}
|
||||
|
||||
|
@ -548,144 +549,6 @@ static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define MIN2(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MIN3(a,b,c) MIN2(MIN2(a,b),c)
|
||||
|
||||
static int philips_su1278sh2_tua6100_tuner_set_params(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *params)
|
||||
{
|
||||
u8 reg0 [2] = { 0x00, 0x00 };
|
||||
u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 };
|
||||
u8 reg2 [3] = { 0x02, 0x00, 0x00 };
|
||||
int _fband;
|
||||
int first_ZF;
|
||||
int R, A, N, P, M;
|
||||
struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 };
|
||||
int freq = params->frequency;
|
||||
struct budget *budget = (struct budget *) fe->dvb->priv;
|
||||
|
||||
first_ZF = (freq) / 1000;
|
||||
|
||||
if (abs(MIN2(abs(first_ZF-1190),abs(first_ZF-1790))) <
|
||||
abs(MIN3(abs(first_ZF-1202),abs(first_ZF-1542),abs(first_ZF-1890))))
|
||||
_fband = 2;
|
||||
else
|
||||
_fband = 3;
|
||||
|
||||
if (_fband == 2) {
|
||||
if (((first_ZF >= 950) && (first_ZF < 1350)) ||
|
||||
((first_ZF >= 1430) && (first_ZF < 1950)))
|
||||
reg0[1] = 0x07;
|
||||
else if (((first_ZF >= 1350) && (first_ZF < 1430)) ||
|
||||
((first_ZF >= 1950) && (first_ZF < 2150)))
|
||||
reg0[1] = 0x0B;
|
||||
}
|
||||
|
||||
if(_fband == 3) {
|
||||
if (((first_ZF >= 950) && (first_ZF < 1350)) ||
|
||||
((first_ZF >= 1455) && (first_ZF < 1950)))
|
||||
reg0[1] = 0x07;
|
||||
else if (((first_ZF >= 1350) && (first_ZF < 1420)) ||
|
||||
((first_ZF >= 1950) && (first_ZF < 2150)))
|
||||
reg0[1] = 0x0B;
|
||||
else if ((first_ZF >= 1420) && (first_ZF < 1455))
|
||||
reg0[1] = 0x0F;
|
||||
}
|
||||
|
||||
if (first_ZF > 1525)
|
||||
reg1[1] |= 0x80;
|
||||
else
|
||||
reg1[1] &= 0x7F;
|
||||
|
||||
if (_fband == 2) {
|
||||
if (first_ZF > 1430) { /* 1430MHZ */
|
||||
reg1[1] &= 0xCF; /* N2 */
|
||||
reg2[1] &= 0xCF; /* R2 */
|
||||
reg2[1] |= 0x10;
|
||||
} else {
|
||||
reg1[1] &= 0xCF; /* N2 */
|
||||
reg1[1] |= 0x20;
|
||||
reg2[1] &= 0xCF; /* R2 */
|
||||
reg2[1] |= 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
if (_fband == 3) {
|
||||
if ((first_ZF >= 1455) &&
|
||||
(first_ZF < 1630)) {
|
||||
reg1[1] &= 0xCF; /* N2 */
|
||||
reg1[1] |= 0x20;
|
||||
reg2[1] &= 0xCF; /* R2 */
|
||||
} else {
|
||||
if (first_ZF < 1455) {
|
||||
reg1[1] &= 0xCF; /* N2 */
|
||||
reg1[1] |= 0x20;
|
||||
reg2[1] &= 0xCF; /* R2 */
|
||||
reg2[1] |= 0x10;
|
||||
} else {
|
||||
if (first_ZF >= 1630) {
|
||||
reg1[1] &= 0xCF; /* N2 */
|
||||
reg2[1] &= 0xCF; /* R2 */
|
||||
reg2[1] |= 0x10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set ports, enable P0 for symbol rates > 4Ms/s */
|
||||
if (params->u.qpsk.symbol_rate >= 4000000)
|
||||
reg1[1] |= 0x0c;
|
||||
else
|
||||
reg1[1] |= 0x04;
|
||||
|
||||
reg2[1] |= 0x0c;
|
||||
|
||||
R = 64;
|
||||
A = 64;
|
||||
P = 64; //32
|
||||
|
||||
M = (freq * R) / 4; /* in Mhz */
|
||||
N = (M - A * 1000) / (P * 1000);
|
||||
|
||||
reg1[1] |= (N >> 9) & 0x03;
|
||||
reg1[2] = (N >> 1) & 0xff;
|
||||
reg1[3] = (N << 7) & 0x80;
|
||||
|
||||
reg2[1] |= (R >> 8) & 0x03;
|
||||
reg2[2] = R & 0xFF; /* R */
|
||||
|
||||
reg1[3] |= A & 0x7f; /* A */
|
||||
|
||||
if (P == 64)
|
||||
reg1[1] |= 0x40; /* Prescaler 64/65 */
|
||||
|
||||
reg0[1] |= 0x03;
|
||||
|
||||
/* already enabled - do not reenable i2c repeater or TX fails */
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
msg.buf = reg0;
|
||||
msg.len = sizeof(reg0);
|
||||
if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
|
||||
return -EIO;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
msg.buf = reg1;
|
||||
msg.len = sizeof(reg1);
|
||||
if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
|
||||
return -EIO;
|
||||
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 1);
|
||||
msg.buf = reg2;
|
||||
msg.len = sizeof(reg2);
|
||||
if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 typhoon_cinergy1200s_inittab[] = {
|
||||
0x01, 0x15,
|
||||
0x02, 0x30,
|
||||
|
@ -1068,9 +931,9 @@ static int tda10021_set_frontend(struct dvb_frontend *fe,
|
|||
|
||||
result = budget_av->tda10021_set_frontend(fe, p);
|
||||
if (budget_av->tda10021_ts_enabled) {
|
||||
tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
|
||||
tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa1);
|
||||
} else {
|
||||
tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
|
||||
tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1096,15 +959,16 @@ static void frontend_init(struct budget_av *budget_av)
|
|||
switch (saa->pci->subsystem_device) {
|
||||
|
||||
case SUBID_DVBS_KNC1:
|
||||
case SUBID_DVBS_KNC1_PLUS:
|
||||
case SUBID_DVBS_EASYWATCH_1:
|
||||
if (saa->pci->subsystem_vendor == 0x1894) {
|
||||
fe = stv0299_attach(&cinergy_1200s_1894_0010_config,
|
||||
fe = dvb_attach(stv0299_attach, &cinergy_1200s_1894_0010_config,
|
||||
&budget_av->budget.i2c_adap);
|
||||
if (fe) {
|
||||
fe->ops.tuner_ops.set_params = philips_su1278sh2_tua6100_tuner_set_params;
|
||||
dvb_attach(tua6100_attach, fe, 0x60, &budget_av->budget.i2c_adap);
|
||||
}
|
||||
} else {
|
||||
fe = stv0299_attach(&typhoon_config,
|
||||
fe = dvb_attach(stv0299_attach, &typhoon_config,
|
||||
&budget_av->budget.i2c_adap);
|
||||
if (fe) {
|
||||
fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
|
||||
|
@ -1116,16 +980,15 @@ static void frontend_init(struct budget_av *budget_av)
|
|||
case SUBID_DVBS_TV_STAR_CI:
|
||||
case SUBID_DVBS_CYNERGY1200N:
|
||||
case SUBID_DVBS_EASYWATCH:
|
||||
fe = stv0299_attach(&philips_sd1878_config,
|
||||
fe = dvb_attach(stv0299_attach, &philips_sd1878_config,
|
||||
&budget_av->budget.i2c_adap);
|
||||
if (fe) {
|
||||
fe->ops.tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params;
|
||||
}
|
||||
break;
|
||||
|
||||
case SUBID_DVBS_KNC1_PLUS:
|
||||
case SUBID_DVBS_TYPHOON:
|
||||
fe = stv0299_attach(&typhoon_config,
|
||||
fe = dvb_attach(stv0299_attach, &typhoon_config,
|
||||
&budget_av->budget.i2c_adap);
|
||||
if (fe) {
|
||||
fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
|
||||
|
@ -1133,7 +996,7 @@ static void frontend_init(struct budget_av *budget_av)
|
|||
break;
|
||||
|
||||
case SUBID_DVBS_CINERGY1200:
|
||||
fe = stv0299_attach(&cinergy_1200s_config,
|
||||
fe = dvb_attach(stv0299_attach, &cinergy_1200s_config,
|
||||
&budget_av->budget.i2c_adap);
|
||||
if (fe) {
|
||||
fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
|
||||
|
@ -1141,19 +1004,10 @@ static void frontend_init(struct budget_av *budget_av)
|
|||
break;
|
||||
|
||||
case SUBID_DVBC_KNC1:
|
||||
budget_av->reinitialise_demod = 1;
|
||||
fe = tda10021_attach(&philips_cu1216_config,
|
||||
&budget_av->budget.i2c_adap,
|
||||
read_pwm(budget_av));
|
||||
if (fe) {
|
||||
fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
|
||||
}
|
||||
break;
|
||||
|
||||
case SUBID_DVBC_KNC1_PLUS:
|
||||
case SUBID_DVBC_CINERGY1200:
|
||||
budget_av->reinitialise_demod = 1;
|
||||
fe = tda10021_attach(&philips_cu1216_config,
|
||||
fe = dvb_attach(tda10021_attach, &philips_cu1216_config,
|
||||
&budget_av->budget.i2c_adap,
|
||||
read_pwm(budget_av));
|
||||
if (fe) {
|
||||
|
@ -1168,7 +1022,7 @@ static void frontend_init(struct budget_av *budget_av)
|
|||
case SUBID_DVBT_KNC1_PLUS:
|
||||
case SUBID_DVBT_CINERGY1200:
|
||||
budget_av->reinitialise_demod = 1;
|
||||
fe = tda10046_attach(&philips_tu1216_config,
|
||||
fe = dvb_attach(tda10046_attach, &philips_tu1216_config,
|
||||
&budget_av->budget.i2c_adap);
|
||||
if (fe) {
|
||||
fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
|
||||
|
@ -1192,8 +1046,7 @@ static void frontend_init(struct budget_av *budget_av)
|
|||
if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
|
||||
budget_av->budget.dvb_frontend)) {
|
||||
printk(KERN_ERR "budget-av: Frontend registration failed!\n");
|
||||
if (budget_av->budget.dvb_frontend->ops.release)
|
||||
budget_av->budget.dvb_frontend->ops.release(budget_av->budget.dvb_frontend);
|
||||
dvb_frontend_detach(budget_av->budget.dvb_frontend);
|
||||
budget_av->budget.dvb_frontend = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -1227,8 +1080,10 @@ static int budget_av_detach(struct saa7146_dev *dev)
|
|||
if (budget_av->budget.ci_present)
|
||||
ciintf_deinit(budget_av);
|
||||
|
||||
if (budget_av->budget.dvb_frontend != NULL)
|
||||
if (budget_av->budget.dvb_frontend != NULL) {
|
||||
dvb_unregister_frontend(budget_av->budget.dvb_frontend);
|
||||
dvb_frontend_detach(budget_av->budget.dvb_frontend);
|
||||
}
|
||||
err = ttpci_budget_deinit(&budget_av->budget);
|
||||
|
||||
kfree(budget_av);
|
||||
|
@ -1400,6 +1255,7 @@ static struct pci_device_id pci_tbl[] = {
|
|||
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
|
||||
MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
|
||||
MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
|
||||
MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011),
|
||||
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
|
||||
MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
|
||||
MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue