Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb

This commit is contained in:
Linus Torvalds 2006-01-09 13:03:58 -08:00
commit f17578decc
203 changed files with 10715 additions and 5153 deletions

View file

@ -150,7 +150,8 @@ Getting the card going
The frontend module sp887x.o, requires an external firmware.
Please use the command "get_dvb_firmware sp887x" to download
it. Then copy it to /usr/lib/hotplug/firmware.
it. Then copy it to /usr/lib/hotplug/firmware or /lib/firmware/
(depending on configuration of firmware hotplug).
Receiving DVB-T in Australia

View file

@ -23,7 +23,7 @@ use IO::Handle;
@components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t",
"dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
"or51211", "or51132_qam", "or51132_vsb");
"or51211", "or51132_qam", "or51132_vsb", "bluebird");
# Check args
syntax() if (scalar(@ARGV) != 1);
@ -34,7 +34,11 @@ for ($i=0; $i < scalar(@components); $i++) {
if ($cid eq $components[$i]) {
$outfile = eval($cid);
die $@ if $@;
print STDERR "Firmware $outfile extracted successfully. Now copy it to either /lib/firmware or /usr/lib/hotplug/firmware/ (depending on your hotplug version).\n";
print STDERR <<EOF;
Firmware $outfile extracted successfully.
Now copy it to either /usr/lib/hotplug/firmware or /lib/firmware
(depending on configuration of firmware hotplug).
EOF
exit(0);
}
}
@ -243,7 +247,7 @@ sub nxt2002 {
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
checkstandard();
wgetfile($sourcefile, $url);
unzip($sourcefile, $tmpdir);
verify("$tmpdir/SkyNETU.sys", $hash);
@ -308,6 +312,19 @@ sub or51132_vsb {
$fwfile;
}
sub bluebird {
my $url = "http://www.linuxtv.org/download/dvb/firmware/dvb-usb-bluebird-01.fw";
my $outfile = "dvb-usb-bluebird-01.fw";
my $hash = "658397cb9eba9101af9031302671f49d";
checkstandard();
wgetfile($outfile, $url);
verify($outfile,$hash);
$outfile;
}
# ---------------------------------------------------------------
# Utilities

View file

@ -41,4 +41,5 @@ Hotplug Firmware Loading for 2.6 kernels
For 2.6 kernels the firmware is loaded at the point that the driver module is
loaded. See linux/Documentation/dvb/firmware.txt for more information.
Copy the three files downloaded above into the /usr/lib/hotplug/firmware directory.
Copy the three files downloaded above into the /usr/lib/hotplug/firmware or
/lib/firmware directory (depending on configuration of firmware hotplug).

View file

@ -141,3 +141,4 @@
140 -> Osprey 440 [0070:ff07]
141 -> Asound Skyeye PCTV
142 -> Sabrent TV-FM (bttv version)
143 -> Hauppauge ImpactVCB (bt878) [0070:13eb]

View file

@ -16,7 +16,7 @@
15 -> DViCO FusionHDTV DVB-T1 [18ac:db00]
16 -> KWorld LTV883RF
17 -> DViCO FusionHDTV 3 Gold-Q [18ac:d810]
18 -> Hauppauge Nova-T DVB-T [0070:9002]
18 -> Hauppauge Nova-T DVB-T [0070:9002,0070:9001]
19 -> Conexant DVB-T reference design [14f1:0187]
20 -> Provideo PV259 [1540:2580]
21 -> DViCO FusionHDTV DVB-T Plus [18ac:db10]
@ -35,3 +35,11 @@
34 -> ATI HDTV Wonder [1002:a101]
35 -> WinFast DTV1000-T [107d:665f]
36 -> AVerTV 303 (M126) [1461:000a]
37 -> Hauppauge Nova-S-Plus DVB-S [0070:9201,0070:9202]
38 -> Hauppauge Nova-SE2 DVB-S [0070:9200]
39 -> KWorld DVB-S 100 [17de:08b2]
40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid [0070:9400,0070:9402]
41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile) [0070:9800,0070:9802]
42 -> digitalnow DNTV Live! DVB-T Pro [1822:0025]
43 -> KWorld/VStream XPert DVB-T with cx22702 [17de:08a1]
44 -> DViCO FusionHDTV DVB-T Dual Digital [18ac:db50]

View file

@ -56,7 +56,7 @@
55 -> LifeView FlyDVB-T DUO [5168:0502,5168:0306]
56 -> Avermedia AVerTV 307 [1461:a70a]
57 -> Avermedia AVerTV GO 007 FM [1461:f31f]
58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0370,1421:1370]
58 -> ADS Tech Instant TV (saa7135) [1421:0350,1421:0351,1421:0370,1421:1370]
59 -> Kworld/Tevion V-Stream Xpert TV PVR7134
60 -> Typhoon DVB-T Duo Digital/Analog Cardbus [4e42:0502]
61 -> Philips TOUGH DVB-T reference design [1131:2004]
@ -81,4 +81,5 @@
80 -> ASUS Digimatrix TV [1043:0210]
81 -> Philips Tiger reference design [1131:2018]
82 -> MSI TV@Anywhere plus [1462:6231]
83 -> Terratec Cinergy 250 PCI TV [153b:1160]
84 -> LifeView FlyDVB Trio [5168:0319]

View file

@ -40,7 +40,7 @@ tuner=38 - Philips PAL/SECAM multi (FM1216ME MK3)
tuner=39 - LG NTSC (newer TAPC series)
tuner=40 - HITACHI V7-J180AT
tuner=41 - Philips PAL_MK (FI1216 MK)
tuner=42 - Philips 1236D ATSC/NTSC daul in
tuner=42 - Philips 1236D ATSC/NTSC dual in
tuner=43 - Philips NTSC MK3 (FM1236MK3 or FM1236/F)
tuner=44 - Philips 4 in 1 (ATI TV Wonder Pro/Conexant)
tuner=45 - Microtune 4049 FM5
@ -50,7 +50,7 @@ tuner=48 - Tenna TNF 8831 BGFF)
tuner=49 - Microtune 4042 FI5 ATSC/NTSC dual in
tuner=50 - TCL 2002N
tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3)
tuner=52 - Thomson DDT 7610 (ATSC/NTSC)
tuner=52 - Thomson DTT 7610 (ATSC/NTSC)
tuner=53 - Philips FQ1286
tuner=54 - tda8290+75
tuner=55 - TCL 2002MB
@ -58,7 +58,7 @@ tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4)
tuner=57 - Philips FQ1236A MK4
tuner=58 - Ymec TVision TVF-8531MF/8831MF/8731MF
tuner=59 - Ymec TVision TVF-5533MF
tuner=60 - Thomson DDT 7611 (ATSC/NTSC)
tuner=60 - Thomson DTT 761X (ATSC/NTSC)
tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
tuner=62 - Philips TEA5767HN FM Radio
tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner

View file

@ -253,7 +253,10 @@ static int fops_open(struct inode *inode, struct file *file)
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
DEB_S(("initializing vbi...\n"));
result = saa7146_vbi_uops.open(dev,file);
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
result = saa7146_vbi_uops.open(dev,file);
if (dev->ext_vv_data->vbi_fops.open)
dev->ext_vv_data->vbi_fops.open(inode, file);
} else {
DEB_S(("initializing video...\n"));
result = saa7146_video_uops.open(dev,file);
@ -289,7 +292,10 @@ static int fops_release(struct inode *inode, struct file *file)
return -ERESTARTSYS;
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
saa7146_vbi_uops.release(dev,file);
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
saa7146_vbi_uops.release(dev,file);
if (dev->ext_vv_data->vbi_fops.release)
dev->ext_vv_data->vbi_fops.release(inode, file);
} else {
saa7146_video_uops.release(dev,file);
}
@ -332,6 +338,7 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
BUG();
return 0;
}
return videobuf_mmap_mapper(q,vma);
}
@ -381,7 +388,10 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
}
case V4L2_BUF_TYPE_VBI_CAPTURE: {
// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
return saa7146_vbi_uops.read(file,data,count,ppos);
if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
return saa7146_vbi_uops.read(file,data,count,ppos);
else
return -EINVAL;
}
break;
default:
@ -390,12 +400,31 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
}
}
static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
{
struct saa7146_fh *fh = file->private_data;
switch (fh->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
return -EINVAL;
case V4L2_BUF_TYPE_VBI_CAPTURE:
if (fh->dev->ext_vv_data->vbi_fops.write)
return fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
else
return -EINVAL;
default:
BUG();
return -EINVAL;
}
}
static struct file_operations video_fops =
{
.owner = THIS_MODULE,
.open = fops_open,
.release = fops_release,
.read = fops_read,
.write = fops_write,
.poll = fops_poll,
.mmap = fops_mmap,
.ioctl = fops_ioctl,
@ -467,7 +496,8 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
saa7146_video_uops.init(dev,vv);
saa7146_vbi_uops.init(dev,vv);
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
saa7146_vbi_uops.init(dev,vv);
dev->vv_data = vv;
dev->vv_callback = &vv_callback;

View file

@ -562,19 +562,26 @@ static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int
int b_depth = vv->ov_fmt->depth;
int b_bpl = vv->ov_fb.fmt.bytesperline;
u32 base = (u32)vv->ov_fb.base;
/* The unsigned long cast is to remove a 64-bit compile warning since
it looks like a 64-bit address is cast to a 32-bit value, even
though the base pointer is really a 32-bit physical address that
goes into a 32-bit DMA register.
FIXME: might not work on some 64-bit platforms, but see the FIXME
in struct v4l2_framebuffer (videodev2.h) for that.
*/
u32 base = (u32)(unsigned long)vv->ov_fb.base;
struct saa7146_video_dma vdma1;
/* calculate memory offsets for picture, look if we shall top-down-flip */
vdma1.pitch = 2*b_bpl;
if ( 0 == vv->vflip ) {
vdma1.base_even = (u32)base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
vdma1.base_odd = vdma1.base_even + (vdma1.pitch / 2);
vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
}
else {
vdma1.base_even = (u32)base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
vdma1.base_odd = vdma1.base_even - (vdma1.pitch / 2);
vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
}

View file

@ -500,9 +500,9 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
}
struct saa7146_use_ops saa7146_vbi_uops = {
.init = vbi_init,
.open = vbi_open,
.init = vbi_init,
.open = vbi_open,
.release = vbi_close,
.irq_done = vbi_irq_done,
.read = vbi_read,
.read = vbi_read,
};

View file

@ -151,8 +151,8 @@ static int try_win(struct saa7146_dev *dev, struct v4l2_window *win)
if (V4L2_FIELD_ANY == field) {
field = (win->w.height > maxh/2)
? V4L2_FIELD_INTERLACED
: V4L2_FIELD_TOP;
? V4L2_FIELD_INTERLACED
: V4L2_FIELD_TOP;
}
switch (field) {
case V4L2_FIELD_TOP:
@ -1114,10 +1114,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
return 0;
}
case VIDIOC_OVERLAY:
{
int on = *(int *)arg;
int err = 0;
@ -1359,7 +1355,6 @@ static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
}
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
struct file *file = q->priv_data;

View file

@ -298,7 +298,7 @@ static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct fir
}
static int lgdt3303_pll_set(struct dvb_frontend* fe,
struct dvb_frontend_parameters* params)
struct dvb_frontend_parameters* params)
{
struct flexcop_device *fc = fe->dvb->priv;
u8 buf[4];
@ -485,12 +485,16 @@ static struct stv0297_config alps_tdee4_stv0297_config = {
/* try to figure out the frontend, each card/box can have on of the following list */
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) {
fc->fe->ops->set_voltage = flexcop_set_voltage;
ops = fc->fe->ops;
fc->fe_sleep = fc->fe->ops->sleep;
fc->fe->ops->sleep = flexcop_sleep;
ops->set_voltage = flexcop_set_voltage;
fc->fe_sleep = ops->sleep;
ops->sleep = flexcop_sleep;
fc->dev_type = FC_SKY;
info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
@ -522,15 +526,17 @@ int flexcop_frontend_init(struct flexcop_device *fc)
} else
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
fc->fe->ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
fc->fe->ops->diseqc_send_burst = flexcop_diseqc_send_burst;
fc->fe->ops->set_tone = flexcop_set_tone;
fc->fe->ops->set_voltage = flexcop_set_voltage;
ops = fc->fe->ops;
fc->fe_sleep = fc->fe->ops->sleep;
fc->fe->ops->sleep = flexcop_sleep;
ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
ops->diseqc_send_burst = flexcop_diseqc_send_burst;
ops->set_tone = flexcop_set_tone;
ops->set_voltage = flexcop_set_voltage;
fc->dev_type = FC_SKY_OLD;
fc->fe_sleep = ops->sleep;
ops->sleep = flexcop_sleep;
fc->dev_type = FC_SKY_OLD;
info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
}
@ -540,8 +546,9 @@ int flexcop_frontend_init(struct flexcop_device *fc)
} else {
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
err("frontend registration failed!");
if (fc->fe->ops->release != NULL)
fc->fe->ops->release(fc->fe);
ops = fc->fe->ops;
if (ops->release != NULL)
ops->release(fc->fe);
fc->fe = NULL;
return -EINVAL;
}

View file

@ -39,11 +39,13 @@ extern const char *flexcop_device_names[];
/* FlexCop IBI Registers */
#if defined(__LITTLE_ENDIAN)
#include "flexcop_ibi_value_le.h"
#elif defined(__BIG_ENDIAN)
#else
#if defined(__BIG_ENDIAN)
#include "flexcop_ibi_value_be.h"
#else
#error no endian defined
#endif
#endif
#define fc_data_Tag_ID_DVB 0x3e
#define fc_data_Tag_ID_ATSC 0x3f

View file

@ -1341,30 +1341,40 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
return 0;
}
static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
static int dst_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters* p,
unsigned int mode_flags,
int *delay,
fe_status_t *status)
{
struct dst_state *state = fe->demodulator_priv;
dst_set_freq(state, p->frequency);
dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
if (p != NULL) {
dst_set_freq(state, p->frequency);
dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
if (state->dst_type == DST_TYPE_IS_SAT) {
if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
dst_set_inversion(state, p->inversion);
dst_set_fec(state, p->u.qpsk.fec_inner);
dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
dst_set_polarization(state);
dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
if (state->dst_type == DST_TYPE_IS_SAT) {
if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
dst_set_inversion(state, p->inversion);
dst_set_fec(state, p->u.qpsk.fec_inner);
dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
dst_set_polarization(state);
dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
} else if (state->dst_type == DST_TYPE_IS_TERR)
dst_set_bandwidth(state, p->u.ofdm.bandwidth);
else if (state->dst_type == DST_TYPE_IS_CABLE) {
dst_set_fec(state, p->u.qam.fec_inner);
dst_set_symbolrate(state, p->u.qam.symbol_rate);
dst_set_modulation(state, p->u.qam.modulation);
} else if (state->dst_type == DST_TYPE_IS_TERR)
dst_set_bandwidth(state, p->u.ofdm.bandwidth);
else if (state->dst_type == DST_TYPE_IS_CABLE) {
dst_set_fec(state, p->u.qam.fec_inner);
dst_set_symbolrate(state, p->u.qam.symbol_rate);
dst_set_modulation(state, p->u.qam.modulation);
}
dst_write_tuna(fe);
}
dst_write_tuna(fe);
if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
dst_read_status(fe, status);
*delay = HZ/10;
return 0;
}
@ -1445,7 +1455,7 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
.release = dst_release,
.init = dst_init,
.set_frontend = dst_set_frontend,
.tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
@ -1469,7 +1479,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
.release = dst_release,
.init = dst_init,
.set_frontend = dst_set_frontend,
.tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,
@ -1496,7 +1506,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
.release = dst_release,
.init = dst_init,
.set_frontend = dst_set_frontend,
.tune = dst_set_frontend,
.get_frontend = dst_get_frontend,
.read_status = dst_read_status,
.read_signal_strength = dst_read_signal_strength,

View file

@ -283,16 +283,17 @@ static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message,
hw_buffer->msg[4] = 0x03;
hw_buffer->msg[5] = length & 0xff;
hw_buffer->msg[6] = 0x00;
/*
* Need to compute length for EN50221 section 8.3.2, for the time being
* assuming 8.3.2 is not applicable
*/
memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
}
return 0;
}
static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
{
if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) {

View file

@ -600,7 +600,6 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
struct dst_state* state = NULL;
switch(type) {
#ifdef BTTV_BOARD_DVICO_DVBT_LITE
case BTTV_BOARD_DVICO_DVBT_LITE:
card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
if (card->fe != NULL) {
@ -608,22 +607,15 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
card->fe->ops->info.frequency_max = 862000000;
}
break;
#endif
#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
lgdt330x_reset(card);
card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
if (card->fe != NULL)
dprintk ("dvb_bt8xx: lgdt330x detected\n");
break;
#endif
#ifdef BTTV_BOARD_TWINHAN_VP3021
case BTTV_BOARD_TWINHAN_VP3021:
#else
case BTTV_BOARD_NEBULA_DIGITV:
#endif
/*
* It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK);
* this would be a cleaner solution than trying each frontend in turn.
@ -812,9 +804,7 @@ static int dvb_bt8xx_probe(struct device *dev)
card->irq_err_ignore = 0;
break;
#ifdef BTTV_BOARD_DVICO_DVBT_LITE
case BTTV_BOARD_DVICO_DVBT_LITE:
#endif
card->gpio_mode = 0x0400C060;
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
@ -823,19 +813,13 @@ static int dvb_bt8xx_probe(struct device *dev)
* DA_APP(parallel) */
break;
#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
#endif
card->gpio_mode = 0x0400c060;
card->op_sync_orin = BT878_RISC_SYNC_MASK;
card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
break;
#ifdef BTTV_BOARD_TWINHAN_VP3021
case BTTV_BOARD_TWINHAN_VP3021:
#else
case BTTV_BOARD_NEBULA_DIGITV:
#endif
case BTTV_BOARD_AVDVBT_761:
card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
card->op_sync_orin = 0;

View file

@ -21,35 +21,35 @@ config DVB_CINERGYT2_TUNING
config DVB_CINERGYT2_STREAM_URB_COUNT
int "Number of queued USB Request Blocks for Highspeed Stream Transfers"
depends on DVB_CINERGYT2_TUNING
default "32"
default "32"
help
USB Request Blocks for Highspeed Stream transfers are scheduled in
a queue for the Host Controller.
Usually the default value is a safe choice.
You may increase this number if you are using this device in a
Server Environment with many high-traffic USB Highspeed devices
You may increase this number if you are using this device in a
Server Environment with many high-traffic USB Highspeed devices
sharing the same USB bus.
config DVB_CINERGYT2_STREAM_BUF_SIZE
int "Size of URB Stream Buffers for Highspeed Transfers"
depends on DVB_CINERGYT2_TUNING
default "512"
default "512"
help
Should be a multiple of native buffer size of 512 bytes.
Default value is a safe choice.
You may increase this number if you are using this device in a
Server Environment with many high-traffic USB Highspeed devices
You may increase this number if you are using this device in a
Server Environment with many high-traffic USB Highspeed devices
sharing the same USB bus.
config DVB_CINERGYT2_QUERY_INTERVAL
int "Status update interval [milliseconds]"
depends on DVB_CINERGYT2_TUNING
default "250"
default "250"
help
This is the interval for status readouts from the demodulator.
You may try lower values if you need more responsive signal quality
@ -64,9 +64,9 @@ config DVB_CINERGYT2_QUERY_INTERVAL
config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
bool "Register the onboard IR Remote Control Receiver as Input Device"
depends on DVB_CINERGYT2_TUNING
default "yes"
default "yes"
help
Enable this option if you want to use the onboard Infrared Remote
Enable this option if you want to use the onboard Infrared Remote
Control Receiver as Linux-Input device.
Right now only the keycode table for the default Remote Control
@ -77,7 +77,7 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
config DVB_CINERGYT2_RC_QUERY_INTERVAL
int "Infrared Remote Controller update interval [milliseconds]"
depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
default "50"
default "50"
help
If you have a very fast-repeating remote control you can try lower
values, for normal consumer receivers the default value should be

View file

@ -131,6 +131,8 @@ struct cinergyt2 {
wait_queue_head_t poll_wq;
int pending_fe_events;
int disconnect_pending;
atomic_t inuse;
void *streambuf;
dma_addr_t streambuf_dmahandle;
@ -343,7 +345,7 @@ static int cinergyt2_start_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *demux = dvbdmxfeed->demux;
struct cinergyt2 *cinergyt2 = demux->priv;
if (down_interruptible(&cinergyt2->sem))
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (cinergyt2->streaming == 0)
@ -359,7 +361,7 @@ static int cinergyt2_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
struct dvb_demux *demux = dvbdmxfeed->demux;
struct cinergyt2 *cinergyt2 = demux->priv;
if (down_interruptible(&cinergyt2->sem))
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (--cinergyt2->streaming == 0)
@ -479,23 +481,37 @@ static int cinergyt2_open (struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
int err;
int err = -ERESTARTSYS;
if ((err = dvb_generic_open(inode, file)))
return err;
if (down_interruptible(&cinergyt2->sem))
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if ((err = dvb_generic_open(inode, file))) {
up(&cinergyt2->sem);
return err;
}
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
cinergyt2_sleep(cinergyt2, 0);
schedule_delayed_work(&cinergyt2->query_work, HZ/2);
}
atomic_inc(&cinergyt2->inuse);
up(&cinergyt2->sem);
return 0;
}
static void cinergyt2_unregister(struct cinergyt2 *cinergyt2)
{
dvb_unregister_device(cinergyt2->fedev);
dvb_unregister_adapter(&cinergyt2->adapter);
cinergyt2_free_stream_urbs(cinergyt2);
kfree(cinergyt2);
}
static int cinergyt2_release (struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
@ -504,7 +520,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
if (down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
cancel_delayed_work(&cinergyt2->query_work);
flush_scheduled_work();
cinergyt2_sleep(cinergyt2, 1);
@ -512,6 +528,11 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
up(&cinergyt2->sem);
if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) {
warn("delayed unregister in release");
cinergyt2_unregister(cinergyt2);
}
return dvb_generic_release(inode, file);
}
@ -519,7 +540,14 @@ static unsigned int cinergyt2_poll (struct file *file, struct poll_table_struct
{
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
poll_wait(file, &cinergyt2->poll_wq, wait);
up(&cinergyt2->sem);
return (POLLIN | POLLRDNORM | POLLPRI);
}
@ -564,10 +592,15 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
(__u16 __user *) arg);
case FE_READ_UNCORRECTED_BLOCKS:
/* UNC are already converted to host byte order... */
return put_user(stat->uncorrected_block_count,
(__u32 __user *) arg);
{
uint32_t unc_count;
unc_count = stat->uncorrected_block_count;
stat->uncorrected_block_count = 0;
/* UNC are already converted to host byte order... */
return put_user(unc_count,(__u32 __user *) arg);
}
case FE_SET_FRONTEND:
{
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
@ -580,7 +613,7 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
if (copy_from_user(&p, (void __user*) arg, sizeof(p)))
return -EFAULT;
if (down_interruptible(&cinergyt2->sem))
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
@ -691,7 +724,7 @@ static void cinergyt2_query_rc (void *data)
struct cinergyt2_rc_event rc_events[12];
int n, len, i;
if (down_interruptible(&cinergyt2->sem))
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return;
len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
@ -786,7 +819,6 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
{
cancel_delayed_work(&cinergyt2->rc_query_work);
flush_scheduled_work();
input_unregister_device(cinergyt2->rc_input_dev);
}
@ -817,7 +849,7 @@ static void cinergyt2_query (void *data)
uint8_t lock_bits;
uint32_t unc;
if (down_interruptible(&cinergyt2->sem))
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return;
unc = s->uncorrected_block_count;
@ -917,28 +949,25 @@ static void cinergyt2_disconnect (struct usb_interface *intf)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
if (down_interruptible(&cinergyt2->sem))
return;
flush_scheduled_work();
cinergyt2_unregister_rc(cinergyt2);
cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
dvb_net_release(&cinergyt2->dvbnet);
dvb_dmxdev_release(&cinergyt2->dmxdev);
dvb_dmx_release(&cinergyt2->demux);
dvb_unregister_device(cinergyt2->fedev);
dvb_unregister_adapter(&cinergyt2->adapter);
cancel_delayed_work(&cinergyt2->query_work);
wake_up_interruptible(&cinergyt2->poll_wq);
cinergyt2_free_stream_urbs(cinergyt2);
up(&cinergyt2->sem);
kfree(cinergyt2);
cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
cinergyt2->disconnect_pending = 1;
if (!atomic_read(&cinergyt2->inuse))
cinergyt2_unregister(cinergyt2);
}
static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
if (down_interruptible(&cinergyt2->sem))
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (state.event > PM_EVENT_ON) {
@ -961,7 +990,7 @@ static int cinergyt2_resume (struct usb_interface *intf)
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
if (down_interruptible(&cinergyt2->sem))
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
return -ERESTARTSYS;
if (!cinergyt2->sleeping) {
@ -1014,4 +1043,3 @@ module_exit (cinergyt2_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Holger Waechtler, Daniel Mack");

View file

@ -5,7 +5,7 @@ config DVB_CORE
help
DVB core utility functions for device handling, software fallbacks etc.
Say Y when you have a DVB card and want to use it. Say Y if your want
to build your drivers outside the kernel, but need the DVB core. All
to build your drivers outside the kernel, but need the DVB core. All
in-kernel drivers will select this automatically if needed.
If unsure say N.

View file

@ -3,7 +3,7 @@
#
dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
dvb_ca_en50221.o dvb_frontend.o \
dvb_ca_en50221.o dvb_frontend.o \
dvb_net.o dvb_ringbuffer.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o

View file

@ -1745,9 +1745,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
for (i = 0; i < ca->slot_count; i++) {
dvb_ca_en50221_slot_shutdown(ca, i);
if (ca->slot_info[i].rx_buffer.data != NULL) {
vfree(ca->slot_info[i].rx_buffer.data);
}
vfree(ca->slot_info[i].rx_buffer.data);
}
kfree(ca->slot_info);
dvb_unregister_device(ca->dvbdev);

View file

@ -409,16 +409,16 @@ static u8 *skip_pes_header(u8 **bufp)
if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
if (buf[7] & PTS_ONLY)
pts = buf+9;
pts = buf+9;
else pts = NULL;
buf = inbuf + 9 + inbuf[8];
} else { /* mpeg1 */
for (buf = inbuf + 6; *buf == 0xff; buf++)
if (buf == inbuf + 6 + 16) {
break;
}
if (buf == inbuf + 6 + 16) {
break;
}
if ((*buf & 0xc0) == 0x40)
buf += 2;
buf += 2;
skip = mpeg1_skip_table [*buf >> 4];
if (skip == 5 || skip == 10) pts = buf;
else pts = NULL;
@ -529,9 +529,9 @@ static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_t
pic->picture_header = 0;
pic->sequence_header_data
= ( INIT_HORIZONTAL_SIZE << 20 )
| ( INIT_VERTICAL_SIZE << 8 )
| ( INIT_ASPECT_RATIO << 4 )
| ( INIT_FRAME_RATE );
| ( INIT_VERTICAL_SIZE << 8 )
| ( INIT_ASPECT_RATIO << 4 )
| ( INIT_FRAME_RATE );
pic->mpeg1_flag = 0;
pic->vinfo.horizontal_size
= INIT_DISP_HORIZONTAL_SIZE;

View file

@ -92,6 +92,7 @@ static DECLARE_MUTEX(frontend_mutex);
struct dvb_frontend_private {
/* thread/frontend values */
struct dvb_device *dvbdev;
struct dvb_frontend_parameters parameters;
struct dvb_fe_events events;
@ -100,20 +101,25 @@ struct dvb_frontend_private {
wait_queue_head_t wait_queue;
pid_t thread_pid;
unsigned long release_jiffies;
int state;
int bending;
int lnb_drift;
int inversion;
int auto_step;
int auto_sub_step;
int started_auto_step;
int min_delay;
int max_drift;
int step_size;
int exit;
int wakeup;
unsigned int exit;
unsigned int wakeup;
fe_status_t status;
fe_sec_tone_mode_t tone;
unsigned long tune_mode_flags;
unsigned int delay;
/* swzigzag values */
unsigned int state;
unsigned int bending;
int lnb_drift;
unsigned int inversion;
unsigned int auto_step;
unsigned int auto_sub_step;
unsigned int started_auto_step;
unsigned int min_delay;
unsigned int max_drift;
unsigned int step_size;
int quality;
unsigned int check_wrapped;
};
@ -208,21 +214,21 @@ static void dvb_frontend_init(struct dvb_frontend *fe)
fe->ops->init(fe);
}
static void update_delay(int *quality, int *delay, int min_delay, int locked)
static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
{
int q2;
int q2;
dprintk ("%s\n", __FUNCTION__);
dprintk ("%s\n", __FUNCTION__);
if (locked)
(*quality) = (*quality * 220 + 36*256) / 256;
else
(*quality) = (*quality * 220 + 0) / 256;
if (locked)
(fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
else
(fepriv->quality) = (fepriv->quality * 220 + 0) / 256;
q2 = *quality - 128;
q2 *= q2;
q2 = fepriv->quality - 128;
q2 *= q2;
*delay = min_delay + q2 * HZ / (128*128);
fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128);
}
/**
@ -232,7 +238,7 @@ static void update_delay(int *quality, int *delay, int min_delay, int locked)
* @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
* @returns Number of complete iterations that have been performed.
*/
static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped)
{
int autoinversion;
int ready = 0;
@ -321,6 +327,129 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
return 0;
}
static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
{
fe_status_t s;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
/* if we've got no parameters, just keep idling */
if (fepriv->state & FESTATE_IDLE) {
fepriv->delay = 3*HZ;
fepriv->quality = 0;
return;
}
/* in SCAN mode, we just set the frontend when asked and leave it alone */
if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
if (fepriv->state & FESTATE_RETUNE) {
if (fe->ops->set_frontend)
fe->ops->set_frontend(fe, &fepriv->parameters);
fepriv->state = FESTATE_TUNED;
}
fepriv->delay = 3*HZ;
fepriv->quality = 0;
return;
}
/* get the frontend status */
if (fepriv->state & FESTATE_RETUNE) {
s = 0;
} else {
if (fe->ops->read_status)
fe->ops->read_status(fe, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s);
fepriv->status = s;
}
}
/* if we're not tuned, and we have a lock, move to the TUNED state */
if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
fepriv->state = FESTATE_TUNED;
/* if we're tuned, then we have determined the correct inversion */
if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
(fepriv->parameters.inversion == INVERSION_AUTO)) {
fepriv->parameters.inversion = fepriv->inversion;
}
return;
}
/* if we are tuned already, check we're still locked */
if (fepriv->state & FESTATE_TUNED) {
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
/* we're tuned, and the lock is still good... */
if (s & FE_HAS_LOCK) {
return;
} else { /* if we _WERE_ tuned, but now don't have a lock */
fepriv->state = FESTATE_ZIGZAG_FAST;
fepriv->started_auto_step = fepriv->auto_step;
fepriv->check_wrapped = 0;
}
}
/* don't actually do anything if we're in the LOSTLOCK state,
* the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
if ((fepriv->state & FESTATE_LOSTLOCK) &&
(fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
return;
}
/* don't do anything if we're in the DISEQC state, since this
* might be someone with a motorized dish controlled by DISEQC.
* If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
if (fepriv->state & FESTATE_DISEQC) {
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
return;
}
/* if we're in the RETUNE state, set everything up for a brand
* new scan, keeping the current inversion setting, as the next
* tune is _very_ likely to require the same */
if (fepriv->state & FESTATE_RETUNE) {
fepriv->lnb_drift = 0;
fepriv->auto_step = 0;
fepriv->auto_sub_step = 0;
fepriv->started_auto_step = 0;
fepriv->check_wrapped = 0;
}
/* fast zigzag. */
if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
fepriv->delay = fepriv->min_delay;
/* peform a tune */
if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) {
/* OK, if we've run out of trials at the fast speed.
* Drop back to slow for the _next_ attempt */
fepriv->state = FESTATE_SEARCHING_SLOW;
fepriv->started_auto_step = fepriv->auto_step;
return;
}
fepriv->check_wrapped = 1;
/* if we've just retuned, enter the ZIGZAG_FAST state.
* This ensures we cannot return from an
* FE_SET_FRONTEND ioctl before the first frontend tune
* occurs */
if (fepriv->state & FESTATE_RETUNE) {
fepriv->state = FESTATE_TUNING_FAST;
}
}
/* slow zigzag */
if (fepriv->state & FESTATE_SEARCHING_SLOW) {
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
/* Note: don't bother checking for wrapping; we stay in this
* state until we get a lock */
dvb_frontend_swzigzag_autotune(fe, 0);
}
}
static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
@ -330,7 +459,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
if (fepriv->dvbdev->writers == 1)
if (time_after(jiffies, fepriv->release_jiffies +
dvb_shutdown_timeout * HZ))
dvb_shutdown_timeout * HZ))
return 1;
return 0;
@ -355,18 +484,14 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
wake_up_interruptible(&fepriv->wait_queue);
}
/*
* FIXME: use linux/kthread.h
*/
static int dvb_frontend_thread(void *data)
{
struct dvb_frontend *fe = data;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
unsigned long timeout;
char name [15];
int quality = 0, delay = 3*HZ;
fe_status_t s;
int check_wrapped = 0;
struct dvb_frontend_parameters *params;
dprintk("%s\n", __FUNCTION__);
@ -377,6 +502,9 @@ static int dvb_frontend_thread(void *data)
sigfillset(&current->blocked);
unlock_kernel();
fepriv->check_wrapped = 0;
fepriv->quality = 0;
fepriv->delay = 3*HZ;
fepriv->status = 0;
dvb_frontend_init(fe);
fepriv->wakeup = 0;
@ -386,7 +514,7 @@ static int dvb_frontend_thread(void *data)
timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe),
delay);
fepriv->delay);
if (0 != dvb_frontend_is_exiting(fe)) {
/* got signal or quitting */
break;
@ -397,108 +525,22 @@ static int dvb_frontend_thread(void *data)
if (down_interruptible(&fepriv->sem))
break;
/* if we've got no parameters, just keep idling */
if (fepriv->state & FESTATE_IDLE) {
delay = 3*HZ;
quality = 0;
continue;
}
/* do an iteration of the tuning loop */
if (fe->ops->tune) {
/* have we been asked to retune? */
params = NULL;
if (fepriv->state & FESTATE_RETUNE) {
params = &fepriv->parameters;
fepriv->state = FESTATE_TUNED;
}
/* get the frontend status */
if (fepriv->state & FESTATE_RETUNE) {
s = 0;
} else {
if (fe->ops->read_status)
fe->ops->read_status(fe, &s);
fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s);
fepriv->status = s;
}
}
/* if we're not tuned, and we have a lock, move to the TUNED state */
if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
fepriv->state = FESTATE_TUNED;
/* if we're tuned, then we have determined the correct inversion */
if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
(fepriv->parameters.inversion == INVERSION_AUTO)) {
fepriv->parameters.inversion = fepriv->inversion;
}
continue;
}
/* if we are tuned already, check we're still locked */
if (fepriv->state & FESTATE_TUNED) {
update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
/* we're tuned, and the lock is still good... */
if (s & FE_HAS_LOCK)
continue;
else { /* if we _WERE_ tuned, but now don't have a lock */
fepriv->state = FESTATE_ZIGZAG_FAST;
fepriv->started_auto_step = fepriv->auto_step;
check_wrapped = 0;
}
}
/* don't actually do anything if we're in the LOSTLOCK state,
* the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
if ((fepriv->state & FESTATE_LOSTLOCK) &&
(fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
continue;
}
/* don't do anything if we're in the DISEQC state, since this
* might be someone with a motorized dish controlled by DISEQC.
* If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
if (fepriv->state & FESTATE_DISEQC) {
update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
continue;
}
/* if we're in the RETUNE state, set everything up for a brand
* new scan, keeping the current inversion setting, as the next
* tune is _very_ likely to require the same */
if (fepriv->state & FESTATE_RETUNE) {
fepriv->lnb_drift = 0;
fepriv->auto_step = 0;
fepriv->auto_sub_step = 0;
fepriv->started_auto_step = 0;
check_wrapped = 0;
}
/* fast zigzag. */
if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
delay = fepriv->min_delay;
/* peform a tune */
if (dvb_frontend_autotune(fe, check_wrapped)) {
/* OK, if we've run out of trials at the fast speed.
* Drop back to slow for the _next_ attempt */
fepriv->state = FESTATE_SEARCHING_SLOW;
fepriv->started_auto_step = fepriv->auto_step;
continue;
}
check_wrapped = 1;
/* if we've just retuned, enter the ZIGZAG_FAST state.
* This ensures we cannot return from an
* FE_SET_FRONTEND ioctl before the first frontend tune
* occurs */
if (fepriv->state & FESTATE_RETUNE) {
fepriv->state = FESTATE_TUNING_FAST;
}
}
/* slow zigzag */
if (fepriv->state & FESTATE_SEARCHING_SLOW) {
update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
/* Note: don't bother checking for wrapping; we stay in this
* state until we get a lock */
dvb_frontend_autotune(fe, 0);
} else {
dvb_frontend_swzigzag(fe);
}
}
@ -733,7 +775,6 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
fepriv->tone = (fe_sec_tone_mode_t) parg;
}
break;
@ -747,7 +788,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_DISHNETWORK_SEND_LEGACY_CMD:
if (fe->ops->dishnetwork_send_legacy_command) {
err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned int) parg);
err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
} else if (fe->ops->set_voltage) {
@ -767,13 +808,13 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
* initialization, so parg is 8 bits and does not
* include the initialization or start bit
*/
unsigned int cmd = ((unsigned int) parg) << 1;
unsigned long cmd = ((unsigned long) parg) << 1;
struct timeval nexttime;
struct timeval tv[10];
int i;
u8 last = 1;
if (dvb_frontend_debug)
printk("%s switch command: 0x%04x\n", __FUNCTION__, cmd);
printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd);
do_gettimeofday(&nexttime);
if (dvb_frontend_debug)
memcpy(&tv[0], &nexttime, sizeof(struct timeval));
@ -814,7 +855,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
case FE_ENABLE_HIGH_LNB_VOLTAGE:
if (fe->ops->enable_high_lnb_voltage)
err = fe->ops->enable_high_lnb_voltage(fe, (int) parg);
err = fe->ops->enable_high_lnb_voltage(fe, (long) parg);
break;
case FE_SET_FRONTEND: {
@ -891,6 +932,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
}
break;
case FE_SET_FRONTEND_TUNE_MODE:
fepriv->tune_mode_flags = (unsigned long) parg;
break;
};
up (&fepriv->sem);
@ -932,6 +977,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
/* empty event queue */
fepriv->events.eventr = fepriv->events.eventw = 0;
/* normal tune mode when opened R/W */
fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
}
return ret;
@ -990,7 +1038,6 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
init_MUTEX (&fepriv->events.sem);
fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF;
fepriv->tone = SEC_TONE_OFF;
printk ("DVB: registering frontend %i (%s)...\n",
fe->dvb->num,

View file

@ -58,10 +58,19 @@ struct dvb_frontend_ops {
int (*init)(struct dvb_frontend* fe);
int (*sleep)(struct dvb_frontend* fe);
/* if this is set, it overrides the default swzigzag */
int (*tune)(struct dvb_frontend* fe,
struct dvb_frontend_parameters* params,
unsigned int mode_flags,
int *delay,
fe_status_t *status);
/* these two are only used for the swzigzag code */
int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
@ -74,8 +83,9 @@ struct dvb_frontend_ops {
int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, int arg);
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
};
#define MAX_EVENT 8

View file

@ -1222,7 +1222,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
return if_num;
}
static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num)
static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num)
{
struct net_device *net = dvbnet->device[num];
struct dvb_net_priv *priv;
@ -1296,9 +1296,9 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if ((unsigned int) parg >= DVB_NET_DEVICES_MAX)
if ((unsigned long) parg >= DVB_NET_DEVICES_MAX)
return -EINVAL;
ret = dvb_net_remove_if(dvbnet, (unsigned int) parg);
ret = dvb_net_remove_if(dvbnet, (unsigned long) parg);
if (!ret)
module_put(dvbdev->adapter->module);
return ret;

View file

@ -112,10 +112,10 @@ ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, in
split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
if (split > 0) {
if (!usermem)
memcpy(buf, rbuf->data+rbuf->pread, split);
memcpy(buf, rbuf->data+rbuf->pread, split);
else
if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
return -EFAULT;
if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
return -EFAULT;
buf += split;
todo -= split;
rbuf->pread = 0;
@ -124,7 +124,7 @@ ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, in
memcpy(buf, rbuf->data+rbuf->pread, todo);
else
if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
return -EFAULT;
return -EFAULT;
rbuf->pread = (rbuf->pread + todo) % rbuf->size;
@ -167,7 +167,7 @@ ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t le
}
ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
int offset, u8* buf, size_t len, int usermem)
int offset, u8* buf, size_t len, int usermem)
{
size_t todo;
size_t split;
@ -183,10 +183,10 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
if (split > 0) {
if (!usermem)
memcpy(buf, rbuf->data+idx, split);
memcpy(buf, rbuf->data+idx, split);
else
if (copy_to_user(buf, rbuf->data+idx, split))
return -EFAULT;
if (copy_to_user(buf, rbuf->data+idx, split))
return -EFAULT;
buf += split;
todo -= split;
idx = 0;
@ -195,7 +195,7 @@ ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
memcpy(buf, rbuf->data+idx, todo);
else
if (copy_to_user(buf, rbuf->data+idx, todo))
return -EFAULT;
return -EFAULT;
return len;
}
@ -209,12 +209,12 @@ void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx)
// clean up disposed packets
while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) {
if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) {
pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
} else {
// first packet is not disposed, so we stop cleaning now
break;
// first packet is not disposed, so we stop cleaning now
break;
}
}
}
@ -242,8 +242,8 @@ ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t*
curpktstatus = rbuf->data[(idx + 2) % rbuf->size];
if (curpktstatus == PKT_READY) {
*pktlen = curpktlen;
return idx;
*pktlen = curpktlen;
return idx;
}
consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE;

View file

@ -106,7 +106,7 @@ extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
size_t len, int usermem);
size_t len, int usermem);
/* write routines & macros */
@ -121,7 +121,7 @@ extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf,
** returns number of bytes transferred or -EFAULT
*/
extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
size_t len);
size_t len);
/**
@ -133,7 +133,7 @@ extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
* returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
*/
extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
size_t len);
size_t len);
/**
* Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this
@ -149,7 +149,7 @@ extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
* returns Number of bytes read, or -EFAULT.
*/
extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
int offset, u8* buf, size_t len, int usermem);
int offset, u8* buf, size_t len, int usermem);
/**
* Dispose of a packet in the ring buffer.

View file

@ -92,10 +92,10 @@ static int dvb_device_open(struct inode *inode, struct file *file)
old_fops = file->f_op;
file->f_op = fops_get(dvbdev->fops);
if(file->f_op->open)
err = file->f_op->open(inode,file);
err = file->f_op->open(inode,file);
if (err) {
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
fops_put(file->f_op);
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
return err;
@ -356,18 +356,18 @@ int dvb_usercopy(struct inode *inode, struct file *file,
case _IOC_WRITE:
case (_IOC_WRITE | _IOC_READ):
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
parg = sbuf;
parg = sbuf;
} else {
/* too big to allocate from stack */
mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
if (NULL == mbuf)
return -ENOMEM;
parg = mbuf;
/* too big to allocate from stack */
mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
if (NULL == mbuf)
return -ENOMEM;
parg = mbuf;
}
err = -EFAULT;
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
goto out;
goto out;
break;
}
@ -384,7 +384,7 @@ int dvb_usercopy(struct inode *inode, struct file *file,
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
err = -EFAULT;
err = -EFAULT;
break;
}

View file

@ -97,7 +97,7 @@ we simply define out own dvb_usercopy(), which will hopefully become
generic_usercopy() someday... */
extern int dvb_usercopy(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg,
unsigned int cmd, unsigned long arg,
int (*func)(struct inode *inode, struct file *file,
unsigned int cmd, void *arg));

View file

@ -37,16 +37,16 @@ config DVB_USB_DIBUSB_MB
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
Devices supported by this driver:
TwinhanDTV USB-Ter (VP7041)
TwinhanDTV Magic Box (VP7041e)
KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
Hama DVB-T USB1.1-Box
DiBcom USB1.1 reference devices (non-public)
Ultima Electronic/Artec T1 USB TVBOX
Compro Videomate DVB-U2000 - DVB-T USB
Grandtec DVB-T USB
Avermedia AverTV DVBT USB1.1
Artec T1 USB1.1 boxes
Avermedia AverTV DVBT USB1.1
Compro Videomate DVB-U2000 - DVB-T USB
DiBcom USB1.1 reference devices (non-public)
Grandtec DVB-T USB
Hama DVB-T USB1.1-Box
KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
TwinhanDTV Magic Box (VP7041e)
TwinhanDTV USB-Ter (VP7041)
Ultima Electronic/Artec T1 USB TVBOX
The VP7041 seems to be identical to "CTS Portable" (Chinese
Television System).
@ -54,6 +54,12 @@ config DVB_USB_DIBUSB_MB
Say Y if you own such a device and want to use it. You should build it as
a module.
config DVB_USB_DIBUSB_MB_FAULTY
bool "Support faulty USB IDs"
depends on DVB_USB_DIBUSB_MB
help
Support for faulty USB IDs due to an invalid EEPROM on some Artec devices.
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
@ -63,8 +69,8 @@ config DVB_USB_DIBUSB_MC
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
Devices supported by this driver:
DiBcom USB2.0 reference devices (non-public)
Artec T1 USB2.0 boxes
DiBcom USB2.0 reference devices (non-public)
Say Y if you own such a device and want to use it. You should build it as
a module.

View file

@ -11,10 +11,11 @@
* design, so it can be reused for the "analogue-only" device (if it will
* appear at all).
*
* TODO: check if the cx25840-driver (from ivtv) can be used for the analogue
* part
* TODO: Use the cx25840-driver for the analogue part
*
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
* Copyright (C) 2005 Michael Krufky (mkrufky@m1k.net)
* Copyright (C) 2006 Chris Pascoe (c.pascoe@itee.uq.edu.au)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@ -25,6 +26,9 @@
#include "cxusb.h"
#include "cx22702.h"
#include "lgdt330x.h"
#include "mt352.h"
#include "mt352_priv.h"
/* debug */
int dvb_usb_cxusb_debug;
@ -156,6 +160,99 @@ static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
return 0;
}
static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
u8 ircode[4];
int i;
cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4);
*event = 0;
*state = REMOTE_NO_KEY_PRESSED;
for (i = 0; i < d->props.rc_key_map_size; i++) {
if (keymap[i].custom == ircode[2] &&
keymap[i].data == ircode[3]) {
*event = keymap[i].event;
*state = REMOTE_KEY_PRESSED;
return 0;
}
}
return 0;
}
struct dvb_usb_rc_key dvico_mce_rc_keys[] = {
{ 0xfe, 0x02, KEY_TV },
{ 0xfe, 0x0e, KEY_MP3 },
{ 0xfe, 0x1a, KEY_DVD },
{ 0xfe, 0x1e, KEY_FAVORITES },
{ 0xfe, 0x16, KEY_SETUP },
{ 0xfe, 0x46, KEY_POWER2 },
{ 0xfe, 0x0a, KEY_EPG },
{ 0xfe, 0x49, KEY_BACK },
{ 0xfe, 0x4d, KEY_MENU },
{ 0xfe, 0x51, KEY_UP },
{ 0xfe, 0x5b, KEY_LEFT },
{ 0xfe, 0x5f, KEY_RIGHT },
{ 0xfe, 0x53, KEY_DOWN },
{ 0xfe, 0x5e, KEY_OK },
{ 0xfe, 0x59, KEY_INFO },
{ 0xfe, 0x55, KEY_TAB },
{ 0xfe, 0x0f, KEY_PREVIOUSSONG },/* Replay */
{ 0xfe, 0x12, KEY_NEXTSONG }, /* Skip */
{ 0xfe, 0x42, KEY_ENTER }, /* Windows/Start */
{ 0xfe, 0x15, KEY_VOLUMEUP },
{ 0xfe, 0x05, KEY_VOLUMEDOWN },
{ 0xfe, 0x11, KEY_CHANNELUP },
{ 0xfe, 0x09, KEY_CHANNELDOWN },
{ 0xfe, 0x52, KEY_CAMERA },
{ 0xfe, 0x5a, KEY_TUNER }, /* Live */
{ 0xfe, 0x19, KEY_OPEN },
{ 0xfe, 0x0b, KEY_1 },
{ 0xfe, 0x17, KEY_2 },
{ 0xfe, 0x1b, KEY_3 },
{ 0xfe, 0x07, KEY_4 },
{ 0xfe, 0x50, KEY_5 },
{ 0xfe, 0x54, KEY_6 },
{ 0xfe, 0x48, KEY_7 },
{ 0xfe, 0x4c, KEY_8 },
{ 0xfe, 0x58, KEY_9 },
{ 0xfe, 0x13, KEY_ANGLE }, /* Aspect */
{ 0xfe, 0x03, KEY_0 },
{ 0xfe, 0x1f, KEY_ZOOM },
{ 0xfe, 0x43, KEY_REWIND },
{ 0xfe, 0x47, KEY_PLAYPAUSE },
{ 0xfe, 0x4f, KEY_FASTFORWARD },
{ 0xfe, 0x57, KEY_MUTE },
{ 0xfe, 0x0d, KEY_STOP },
{ 0xfe, 0x01, KEY_RECORD },
{ 0xfe, 0x4e, KEY_POWER },
};
static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
{
static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 };
static u8 reset [] = { RESET, 0x80 };
static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 };
static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 };
static u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 };
static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
mt352_write(fe, clock_config, sizeof(clock_config));
udelay(200);
mt352_write(fe, reset, sizeof(reset));
mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg));
mt352_write(fe, agc_cfg, sizeof(agc_cfg));
mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg));
mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
return 0;
}
struct cx22702_config cxusb_cx22702_config = {
.demod_address = 0x63,
@ -165,17 +262,47 @@ struct cx22702_config cxusb_cx22702_config = {
.pll_set = dvb_usb_pll_set_i2c,
};
struct lgdt330x_config cxusb_lgdt330x_config = {
.demod_address = 0x0e,
.demod_chip = LGDT3303,
.pll_set = dvb_usb_pll_set_i2c,
};
struct mt352_config cxusb_dee1601_config = {
.demod_address = 0x0f,
.demod_init = cxusb_dee1601_demod_init,
.pll_set = dvb_usb_pll_set,
};
/* Callbacks for DVB USB */
static int cxusb_tuner_attach(struct dvb_usb_device *d)
static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d)
{
u8 bpll[4] = { 0x0b, 0xdc, 0x9c, 0xa0 };
d->pll_addr = 0x61;
memcpy(d->pll_init,bpll,4);
memcpy(d->pll_init, bpll, 4);
d->pll_desc = &dvb_pll_fmd1216me;
return 0;
}
static int cxusb_frontend_attach(struct dvb_usb_device *d)
static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d)
{
u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 };
/* bpll[2] : unset bit 3, set bits 4&5
bpll[3] : 0x50 - digital, 0x20 - analog */
d->pll_addr = 0x61;
memcpy(d->pll_init, bpll, 4);
d->pll_desc = &dvb_pll_tdvs_tua6034;
return 0;
}
static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d)
{
d->pll_addr = 0x61;
d->pll_desc = &dvb_pll_thomson_dtt7579;
return 0;
}
static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d)
{
u8 b;
if (usb_set_interface(d->udev,0,6) < 0)
@ -189,22 +316,84 @@ static int cxusb_frontend_attach(struct dvb_usb_device *d)
return -EIO;
}
static int cxusb_lgdt330x_frontend_attach(struct dvb_usb_device *d)
{
if (usb_set_interface(d->udev,0,7) < 0)
err("set interface failed");
cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
if ((d->fe = lgdt330x_attach(&cxusb_lgdt330x_config, &d->i2c_adap)) != NULL)
return 0;
return -EIO;
}
static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
{
if (usb_set_interface(d->udev,0,0) < 0)
err("set interface failed");
cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL)
return 0;
return -EIO;
}
/*
* DViCO bluebird firmware needs the "warm" product ID to be patched into the
* firmware file before download.
*/
#define BLUEBIRD_01_ID_OFFSET 6638
static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, const struct firmware *fw)
{
if (fw->size < BLUEBIRD_01_ID_OFFSET + 4)
return -EINVAL;
if (fw->data[BLUEBIRD_01_ID_OFFSET] == (USB_VID_DVICO & 0xff) &&
fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) {
/* FIXME: are we allowed to change the fw-data ? */
fw->data[BLUEBIRD_01_ID_OFFSET + 2] = udev->descriptor.idProduct + 1;
fw->data[BLUEBIRD_01_ID_OFFSET + 3] = udev->descriptor.idProduct >> 8;
return usb_cypress_load_firmware(udev,fw,CYPRESS_FX2);
}
return -EINVAL;
}
/* DVB USB Driver stuff */
static struct dvb_usb_properties cxusb_properties;
static struct dvb_usb_properties cxusb_medion_properties;
static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties;
static struct dvb_usb_properties cxusb_bluebird_dee1601_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
return dvb_usb_device_init(intf,&cxusb_properties,THIS_MODULE,NULL);
if (dvb_usb_device_init(intf,&cxusb_medion_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_lgh064f_properties,THIS_MODULE,NULL) == 0 ||
dvb_usb_device_init(intf,&cxusb_bluebird_dee1601_properties,THIS_MODULE,NULL) == 0) {
return 0;
}
return -EINVAL;
}
static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_COLD) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_WARM) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
static struct dvb_usb_properties cxusb_properties = {
static struct dvb_usb_properties cxusb_medion_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2,
@ -213,8 +402,8 @@ static struct dvb_usb_properties cxusb_properties = {
.streaming_ctrl = cxusb_streaming_ctrl,
.power_ctrl = cxusb_power_ctrl,
.frontend_attach = cxusb_frontend_attach,
.tuner_attach = cxusb_tuner_attach,
.frontend_attach = cxusb_cx22702_frontend_attach,
.tuner_attach = cxusb_fmd1216me_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
@ -240,6 +429,91 @@ static struct dvb_usb_properties cxusb_properties = {
}
};
static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-bluebird-01.fw",
.download_firmware = bluebird_patch_dvico_firmware_download,
/* use usb alt setting 0 for EP4 transfer (dvb-t),
use usb alt setting 7 for EP2 transfer (atsc) */
.size_of_priv = sizeof(struct cxusb_state),
.streaming_ctrl = cxusb_streaming_ctrl,
.power_ctrl = cxusb_power_ctrl,
.frontend_attach = cxusb_lgdt330x_frontend_attach,
.tuner_attach = cxusb_lgh064f_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x01,
/* parameter for the MPEG2-data transfer */
.urb = {
.type = DVB_USB_BULK,
.count = 5,
.endpoint = 0x02,
.u = {
.bulk = {
.buffersize = 8192,
}
}
},
.num_device_descs = 1,
.devices = {
{ "DViCO FusionHDTV5 USB Gold",
{ &cxusb_table[1], NULL },
{ &cxusb_table[2], NULL },
},
}
};
static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-bluebird-01.fw",
.download_firmware = bluebird_patch_dvico_firmware_download,
/* use usb alt setting 0 for EP4 transfer (dvb-t),
use usb alt setting 7 for EP2 transfer (atsc) */
.size_of_priv = sizeof(struct cxusb_state),
.streaming_ctrl = cxusb_streaming_ctrl,
.power_ctrl = cxusb_power_ctrl,
.frontend_attach = cxusb_dee1601_frontend_attach,
.tuner_attach = cxusb_dee1601_tuner_attach,
.i2c_algo = &cxusb_i2c_algo,
.rc_interval = 150,
.rc_key_map = dvico_mce_rc_keys,
.rc_key_map_size = ARRAY_SIZE(dvico_mce_rc_keys),
.rc_query = cxusb_rc_query,
.generic_bulk_ctrl_endpoint = 0x01,
/* parameter for the MPEG2-data transfer */
.urb = {
.type = DVB_USB_BULK,
.count = 5,
.endpoint = 0x04,
.u = {
.bulk = {
.buffersize = 8192,
}
}
},
.num_device_descs = 1,
.devices = {
{ "DViCO FusionHDTV DVB-T Dual USB",
{ &cxusb_table[3], NULL },
{ &cxusb_table[4], NULL },
},
}
};
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,

View file

@ -21,6 +21,8 @@ extern int dvb_usb_cxusb_debug;
#define CMD_STREAMING_ON 0x36
#define CMD_STREAMING_OFF 0x37
#define CMD_GET_IR_CODE 0x47
#define CMD_ANALOG 0x50
#define CMD_DIGITAL 0x51

View file

@ -65,11 +65,11 @@ static int dibusb_tuner_probe_and_attach(struct dvb_usb_device *d)
d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
if (b2[0] == 0xfe) {
info("this device has the Thomson Cable onboard. Which is default.");
info("This device has the Thomson Cable onboard. Which is default.");
dibusb_thomson_tuner_attach(d);
} else {
u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
info("this device has the Panasonic ENV77H11D5 onboard.");
info("This device has the Panasonic ENV77H11D5 onboard.");
d->pll_addr = 0x60;
memcpy(d->pll_init,bpll,4);
d->pll_desc = &dvb_pll_tda665x;
@ -98,15 +98,15 @@ static int dibusb_probe(struct usb_interface *intf,
/* do not change the order of the ID table */
static struct usb_device_id dibusb_dib3000mb_table [] = {
/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD)},
/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM)},
/* 00 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_COLD) },
/* 01 */ { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_AVERMEDIA_DVBT_USB_WARM) },
/* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) },
/* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) },
/* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) },
/* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) },
/* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) },
/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
/* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) },
/* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) },
/* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) },
@ -117,27 +117,34 @@ static struct usb_device_id dibusb_dib3000mb_table [] = {
/* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) },
/* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) },
/* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) },
/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
/* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) },
/* device ID with default DIBUSB2_0-firmware and with the hacked firmware */
/* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) },
/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) },
/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) },
/* 25 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_COLD) },
/* 26 */ { USB_DEVICE(USB_VID_KYE, USB_PID_KYE_DVB_T_WARM) },
/* 27 */ { USB_DEVICE(USB_VID_KWORLD, USB_PID_KWORLD_VSTREAM_COLD) },
/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) },
/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
/* 29 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) },
// #define DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
/*
* XXX: As Artec just 'forgot' to program the EEPROM on some Artec T1 devices
* we don't catch these faulty IDs (namely 'Cypress FX1 USB controller') that
* have been left on the device. If you don't have such a device but an Artec
* device that's supposed to work with this driver but is not detected by it,
* free to enable CONFIG_DVB_USB_DIBUSB_MB_FAULTY via your kernel config.
*/
#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
/* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
#endif
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
@ -257,7 +264,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
}
},
#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
.num_device_descs = 2,
#else
.num_device_descs = 1,
@ -267,11 +274,12 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = {
{ &dibusb_dib3000mb_table[20], NULL },
{ &dibusb_dib3000mb_table[21], NULL },
},
#ifdef DVB_USB_DIBUSB_MB_FAULTY_USB_IDs
#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
{ "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
{ &dibusb_dib3000mb_table[30], NULL },
{ NULL },
},
{ NULL },
#endif
}
};
@ -323,6 +331,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
{ &dibusb_dib3000mb_table[27], NULL },
{ NULL }
},
{ NULL },
}
};
@ -369,6 +378,7 @@ static struct dvb_usb_properties artec_t1_usb2_properties = {
{ &dibusb_dib3000mb_table[28], NULL },
{ &dibusb_dib3000mb_table[29], NULL },
},
{ NULL },
}
};

View file

@ -32,7 +32,7 @@ static int digitv_ctrl_msg(struct dvb_usb_device *d,
sndbuf[1] = vv;
sndbuf[2] = wo ? wlen : rlen;
if (!wo) {
if (wo) {
memcpy(&sndbuf[3],wbuf,wlen);
dvb_usb_generic_write(d,sndbuf,7);
} else {

View file

@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = {
.cold_ids = { &dtt200u_usb_table[0], NULL },
.warm_ids = { &dtt200u_usb_table[1], NULL },
},
{ NULL },
{ 0 },
}
};
@ -160,7 +160,7 @@ static struct dvb_usb_properties wt220u_properties = {
.pid_filter_count = 15,
.usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-wt220u-01.fw",
.firmware = "dvb-usb-wt220u-02.fw",
.power_ctrl = dtt200u_power_ctrl,
.streaming_ctrl = dtt200u_streaming_ctrl,
@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_properties = {
.cold_ids = { &dtt200u_usb_table[2], NULL },
.warm_ids = { &dtt200u_usb_table[3], NULL },
},
{ NULL },
{ 0 },
}
};

View file

@ -13,6 +13,7 @@
#define _DVB_USB_DTT200U_H_
#define DVB_USB_LOG_PREFIX "dtt200u"
#include "dvb-usb.h"
extern int dvb_usb_dtt200u_debug;
@ -25,15 +26,15 @@ extern int dvb_usb_dtt200u_debug;
* 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
*/
#define GET_SPEED 0x00
#define GET_TUNE_STATUS 0x81
#define GET_RC_CODE 0x84
#define GET_CONFIGURATION 0x88
#define GET_AGC 0x89
#define GET_SNR 0x8a
#define GET_VIT_ERR_CNT 0x8c
#define GET_RS_ERR_CNT 0x8d
#define GET_RS_UNCOR_BLK_CNT 0x8e
#define GET_SPEED 0x00
#define GET_TUNE_STATUS 0x81
#define GET_RC_CODE 0x84
#define GET_CONFIGURATION 0x88
#define GET_AGC 0x89
#define GET_SNR 0x8a
#define GET_VIT_ERR_CNT 0x8c
#define GET_RS_ERR_CNT 0x8d
#define GET_RS_UNCOR_BLK_CNT 0x8e
/* write
* 01 - init
@ -44,12 +45,12 @@ extern int dvb_usb_dtt200u_debug;
* 08 - transfer switch
*/
#define SET_INIT 0x01
#define SET_RF_FREQ 0x02
#define SET_BANDWIDTH 0x03
#define SET_PID_FILTER 0x04
#define RESET_PID_FILTER 0x05
#define SET_STREAMING 0x08
#define SET_INIT 0x01
#define SET_RF_FREQ 0x02
#define SET_BANDWIDTH 0x03
#define SET_PID_FILTER 0x04
#define RESET_PID_FILTER 0x05
#define SET_STREAMING 0x08
extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d);

View file

@ -24,7 +24,7 @@ extern int dvb_usb_disable_rc_polling;
#define deb_mem(args...) dprintk(dvb_usb_debug,0x80,args)
/* commonly used methods */
extern int usb_cypress_load_firmware(struct usb_device *, const char *, int);
extern int dvb_usb_download_firmware(struct usb_device *, struct dvb_usb_properties *);
extern int dvb_usb_urb_submit(struct dvb_usb_device *);
extern int dvb_usb_urb_kill(struct dvb_usb_device *);

View file

@ -9,7 +9,6 @@
*/
#include "dvb-usb-common.h"
#include <linux/firmware.h>
#include <linux/usb.h>
struct usb_cypress_controller {
@ -19,9 +18,10 @@ struct usb_cypress_controller {
};
static struct usb_cypress_controller cypress[] = {
{ .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
{ .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
{ .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
{ .id = DEVICE_SPECIFIC, .name = "Device specific", .cpu_cs_register = 0 },
{ .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
{ .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
{ .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
};
/*
@ -30,71 +30,117 @@ static struct usb_cypress_controller cypress[] = {
static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
{
return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
}
int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type)
int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type)
{
const struct firmware *fw = NULL;
u16 addr;
u8 *b,*p;
int ret = 0,i;
struct hexline hx;
u8 reset;
int ret,pos=0;
if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details on firmware-problems.",
filename);
/* stop the CPU */
reset = 1;
if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
err("could not stop the USB controller CPU.");
while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) {
deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk);
ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len);
if (ret != hx.len) {
err("error while transferring firmware "
"(transferred size: %d, block size: %d)",
ret,hx.len);
ret = -EINVAL;
break;
}
}
if (ret < 0) {
err("firmware download failed at %d with %d",pos,ret);
return ret;
}
info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name);
p = kmalloc(fw->size,GFP_KERNEL);
if (p != NULL) {
u8 reset;
/*
* you cannot use the fw->data as buffer for
* usb_control_msg, a new buffer has to be
* created
*/
memcpy(p,fw->data,fw->size);
/* stop the CPU */
reset = 1;
if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
err("could not stop the USB controller CPU.");
for(i = 0; p[i+3] == 0 && i < fw->size; ) {
b = (u8 *) &p[i];
addr = cpu_to_le16( *((u16 *) &b[1]) );
deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]);
ret = usb_cypress_writemem(udev,addr,&b[4],b[0]);
if (ret != b[0]) {
err("error while transferring firmware "
"(transferred size: %d, block size: %d)",
ret,b[0]);
ret = -EINVAL;
break;
}
i += 5 + b[0];
}
/* length in ret */
if (ret > 0)
ret = 0;
if (ret == 0) {
/* restart the CPU */
reset = 0;
if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
kfree(p);
} else {
ret = -ENOMEM;
}
release_firmware(fw);
} else
ret = -EIO;
return ret;
}
EXPORT_SYMBOL(usb_cypress_load_firmware);
int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties *props)
{
int ret;
const struct firmware *fw = NULL;
if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
props->firmware,ret);
return ret;
}
info("downloading firmware from file '%s'",props->firmware);
switch (props->usb_ctrl) {
case CYPRESS_AN2135:
case CYPRESS_AN2235:
case CYPRESS_FX2:
ret = usb_cypress_load_firmware(udev, fw, props->usb_ctrl);
break;
case DEVICE_SPECIFIC:
if (props->download_firmware)
ret = props->download_firmware(udev,fw);
else {
err("BUG: driver didn't specified a download_firmware-callback, although it claims to have a DEVICE_SPECIFIC one.");
ret = -EINVAL;
}
break;
default:
ret = -EINVAL;
break;
}
release_firmware(fw);
return ret;
}
int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos)
{
u8 *b = (u8 *) &fw->data[*pos];
int data_offs = 4;
if (*pos >= fw->size)
return 0;
memset(hx,0,sizeof(struct hexline));
hx->len = b[0];
if ((*pos + hx->len + 4) >= fw->size)
return -EINVAL;
hx->addr = le16_to_cpu( *((u16 *) &b[1]) );
hx->type = b[3];
if (hx->type == 0x04) {
/* b[4] and b[5] are the Extended linear address record data field */
hx->addr |= (b[4] << 24) | (b[5] << 16);
/* hx->len -= 2;
data_offs += 2; */
}
memcpy(hx->data,&b[data_offs],hx->len);
hx->chk = b[hx->len + data_offs];
*pos += hx->len + 5;
return *pos;
}
EXPORT_SYMBOL(dvb_usb_get_hexline);

View file

@ -52,9 +52,8 @@ int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
int ret = 0;
/* if there is nothing to initialize */
if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 &&
d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00)
/* if pll_desc is not used */
if (d->pll_desc == NULL)
return 0;
if (d->tuner_pass_ctrl)
@ -80,6 +79,9 @@ int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep
{
struct dvb_usb_device *d = fe->dvb->priv;
if (d->pll_desc == NULL)
return 0;
deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
b[0] = d->pll_addr << 1;

View file

@ -86,11 +86,15 @@
#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_LGZ201 0xdb00
#define USB_PID_DVICO_BLUEBIRD_TH7579 0xdb10
#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
#define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01
#define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
#define USB_PID_DVICO_BLUEBIRD_LG064F_WARM 0xd501
#define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD 0xdb00
#define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM 0xdb01
#define USB_PID_DVICO_BLUEBIRD_TH7579_COLD 0xdb10
#define USB_PID_DVICO_BLUEBIRD_TH7579_WARM 0xdb11
#define USB_PID_DVICO_BLUEBIRD_DEE1601_COLD 0xdb50
#define USB_PID_DVICO_BLUEBIRD_DEE1601_WARM 0xdb51
#define USB_PID_MEDION_MD95700 0x0932
#define USB_PID_KYE_DVB_T_COLD 0x701e
#define USB_PID_KYE_DVB_T_WARM 0x701f

View file

@ -138,6 +138,9 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
int ret = -ENOMEM,cold=0;
if (du != NULL)
*du = NULL;
if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
return -ENODEV;
@ -145,39 +148,41 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
if (cold) {
info("found a '%s' in cold state, will try to load a firmware",desc->name);
ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl);
} else {
info("found a '%s' in warm state.",desc->name);
d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
if (d == NULL) {
err("no memory for 'struct dvb_usb_device'");
ret = dvb_usb_download_firmware(udev,props);
if (!props->no_reconnect)
return ret;
}
memset(d,0,sizeof(struct dvb_usb_device));
d->udev = udev;
memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
d->desc = desc;
d->owner = owner;
if (d->props.size_of_priv > 0) {
d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL);
if (d->priv == NULL) {
err("no memory for priv in 'struct dvb_usb_device'");
kfree(d);
return -ENOMEM;
}
memset(d->priv,0,d->props.size_of_priv);
}
usb_set_intfdata(intf, d);
if (du != NULL)
*du = d;
ret = dvb_usb_init(d);
}
info("found a '%s' in warm state.",desc->name);
d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
if (d == NULL) {
err("no memory for 'struct dvb_usb_device'");
return ret;
}
memset(d,0,sizeof(struct dvb_usb_device));
d->udev = udev;
memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
d->desc = desc;
d->owner = owner;
if (d->props.size_of_priv > 0) {
d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL);
if (d->priv == NULL) {
err("no memory for priv in 'struct dvb_usb_device'");
kfree(d);
return -ENOMEM;
}
memset(d->priv,0,d->props.size_of_priv);
}
usb_set_intfdata(intf, d);
if (du != NULL)
*du = d;
ret = dvb_usb_init(d);
if (ret == 0)
info("%s successfully initialized and connected.",desc->name);
else

View file

@ -10,8 +10,8 @@
#include <linux/config.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/firmware.h>
#include "dvb_frontend.h"
#include "dvb_demux.h"
@ -94,7 +94,11 @@ struct dvb_usb_device;
* @usb_ctrl: which USB device-side controller is in use. Needed for firmware
* download.
* @firmware: name of the firmware file.
*
* @download_firmware: called to download the firmware when the usb_ctrl is
* DEVICE_SPECIFIC.
* @no_reconnect: device doesn't do a reconnect after downloading the firmware,
so do the warm initialization right after it
* @size_of_priv: how many bytes shall be allocated for the private field
* of struct dvb_usb_device.
*
@ -142,11 +146,14 @@ struct dvb_usb_properties {
int caps;
int pid_filter_count;
#define CYPRESS_AN2135 0
#define CYPRESS_AN2235 1
#define CYPRESS_FX2 2
#define DEVICE_SPECIFIC 0
#define CYPRESS_AN2135 1
#define CYPRESS_AN2235 2
#define CYPRESS_FX2 3
int usb_ctrl;
const char *firmware;
const char firmware[FIRMWARE_NAME_MAX];
int (*download_firmware) (struct usb_device *, const struct firmware *);
int no_reconnect;
int size_of_priv;
@ -326,5 +333,15 @@ extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
/* commonly used firmware download types and function */
struct hexline {
u8 len;
u32 addr;
u8 type;
u8 data[255];
u8 chk;
};
extern int dvb_usb_get_hexline(const struct firmware *, struct hexline *, int *);
extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type);
#endif

View file

@ -129,10 +129,6 @@ static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
dibusb_read_eeprom_byte(d,i, &b);
mac[5 - (i - 136)] = b;
/* deb_ee("%02x ",b);
if ((i+1) % 16 == 0)
deb_ee("\n");*/
}
return 0;
@ -153,7 +149,7 @@ static struct usb_device_id nova_t_table [] = {
/* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, nova_t_table);
MODULE_DEVICE_TABLE(usb, nova_t_table);
static struct dvb_usb_properties nova_t_properties = {
.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
@ -198,6 +194,7 @@ static struct dvb_usb_properties nova_t_properties = {
{ &nova_t_table[0], NULL },
{ &nova_t_table[1], NULL },
},
{ NULL },
}
};

View file

@ -190,7 +190,7 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
}
static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *m)
struct dvb_diseqc_master_cmd *m)
{
struct vp702x_fe_state *st = fe->demodulator_priv;
u8 cmd[8],ibuf[10];

View file

@ -13,47 +13,47 @@ extern int dvb_usb_vp702x_debug;
/* commands are read and written with USB control messages */
/* consecutive read/write operation */
#define REQUEST_OUT 0xB2
#define REQUEST_IN 0xB3
#define REQUEST_OUT 0xB2
#define REQUEST_IN 0xB3
/* the out-buffer of these consecutive operations contain sub-commands when b[0] = 0
* request: 0xB2; i: 0; v: 0; b[0] = 0, b[1] = subcmd, additional buffer
* the returning buffer looks as follows
* request: 0xB3; i: 0; v: 0; b[0] = 0xB3, additional buffer */
#define GET_TUNER_STATUS 0x05
#define GET_TUNER_STATUS 0x05
/* additional in buffer:
* 0 1 2 3 4 5 6 7 8
* N/A N/A 0x05 signal-quality N/A N/A signal-strength lock==0 N/A */
#define GET_SYSTEM_STRING 0x06
#define GET_SYSTEM_STRING 0x06
/* additional in buffer:
* 0 1 2 3 4 5 6 7 8
* N/A 'U' 'S' 'B' '7' '0' '2' 'X' N/A */
#define SET_DISEQC_CMD 0x08
#define SET_DISEQC_CMD 0x08
/* additional out buffer:
* 0 1 2 3 4
* len X1 X2 X3 X4
* additional in buffer:
* 0 1 2
* N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */
* N/A 0 0 b[1] == b[2] == 0 -> success, failure otherwise */
#define SET_LNB_POWER 0x09
#define SET_LNB_POWER 0x09
/* additional out buffer:
* 0 1 2
* 0x00 0xff 1 = on, 0 = off
* additional in buffer:
* 0 1 2
* N/A 0 0 b[1] == b[2] == 0 -> success otherwise not */
* N/A 0 0 b[1] == b[2] == 0 -> success failure otherwise */
#define GET_MAC_ADDRESS 0x0A
#define GET_MAC_ADDRESS 0x0A
/* #define GET_MAC_ADDRESS 0x0B */
/* additional in buffer:
* 0 1 2 3 4 5 6 7 8
* N/A N/A 0x0A or 0x0B MAC0 MAC1 MAC2 MAC3 MAC4 MAC5 */
#define SET_PID_FILTER 0x11
#define SET_PID_FILTER 0x11
/* additional in buffer:
* 0 1 ... 14 15 16
* PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */
@ -64,39 +64,38 @@ extern int dvb_usb_vp702x_debug;
* freq0 freq1 divstep srate0 srate1 srate2 flag chksum
*/
/* one direction requests */
#define READ_REMOTE_REQ 0xB4
#define READ_REMOTE_REQ 0xB4
/* IN i: 0; v: 0; b[0] == request, b[1] == key */
#define READ_PID_NUMBER_REQ 0xB5
#define READ_PID_NUMBER_REQ 0xB5
/* IN i: 0; v: 0; b[0] == request, b[1] == 0, b[2] = pid number */
#define WRITE_EEPROM_REQ 0xB6
#define WRITE_EEPROM_REQ 0xB6
/* OUT i: offset; v: value to write; no extra buffer */
#define READ_EEPROM_REQ 0xB7
#define READ_EEPROM_REQ 0xB7
/* IN i: bufferlen; v: offset; buffer with bufferlen bytes */
#define READ_STATUS 0xB8
#define READ_STATUS 0xB8
/* IN i: 0; v: 0; bufferlen 10 */
#define READ_TUNER_REG_REQ 0xB9
#define READ_TUNER_REG_REQ 0xB9
/* IN i: 0; v: register; b[0] = value */
#define READ_FX2_REG_REQ 0xBA
#define READ_FX2_REG_REQ 0xBA
/* IN i: offset; v: 0; b[0] = value */
#define WRITE_FX2_REG_REQ 0xBB
#define WRITE_FX2_REG_REQ 0xBB
/* OUT i: offset; v: value to write; 1 byte extra buffer */
#define SET_TUNER_POWER_REQ 0xBC
#define SET_TUNER_POWER_REQ 0xBC
/* IN i: 0 = power off, 1 = power on */
#define WRITE_TUNER_REG_REQ 0xBD
#define WRITE_TUNER_REG_REQ 0xBD
/* IN i: register, v: value to write, no extra buffer */
#define RESET_TUNER 0xBE
#define RESET_TUNER 0xBE
/* IN i: 0, v: 0, no extra buffer */
extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);

View file

@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = {
.cold_ids = { &vp7045_usb_table[2], NULL },
.warm_ids = { &vp7045_usb_table[3], NULL },
},
{ NULL },
{ 0 },
}
};

View file

@ -16,6 +16,12 @@ config DVB_CX24110
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
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
@ -50,18 +56,19 @@ comment "DVB-T (terrestrial) frontends"
depends on DVB_CORE
config DVB_SP8870
tristate "Spase sp8870 based"
tristate "Spase sp8870 based"
depends on DVB_CORE
select FW_LOADER
help
A DVB-T tuner module. Say Y when you want to support this frontend.
A DVB-T tuner module. Say Y when you want to support this frontend.
This driver needs external firmware. Please use the command
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp8870" to
download/extract it, and then copy it to /usr/lib/hotplug/firmware.
download/extract it, and then copy it to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_SP887X
tristate "Spase sp887x based"
tristate "Spase sp887x based"
depends on DVB_CORE
select FW_LOADER
help
@ -69,7 +76,8 @@ config DVB_SP887X
This driver needs external firmware. Please use the command
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
download/extract it, and then copy it to /usr/lib/hotplug/firmware.
download/extract it, and then copy it to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_CX22700
tristate "Conexant CX22700 based"
@ -78,10 +86,10 @@ config DVB_CX22700
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
help
A DVB-T tuner module. Say Y when you want to support this frontend.
tristate "Conexant cx22702 demodulator (OFDM)"
depends on DVB_CORE
help
A DVB-T tuner module. Say Y when you want to support this frontend.
config DVB_L64781
tristate "LSI L64781"
@ -98,8 +106,9 @@ config DVB_TDA1004X
This driver needs external firmware. Please use the commands
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
download/extract them, and then copy them to /usr/lib/hotplug/firmware.
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
download/extract them, and then copy them to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_NXT6000
tristate "NxtWave Communications NXT6000 based"
@ -140,13 +149,13 @@ config DVB_VES1820
tristate "VLSI VES1820 based"
depends on DVB_CORE
help
A DVB-C tuner module. Say Y when you want to support this frontend.
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
help
A DVB-C tuner module. Say Y when you want to support this frontend.
A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_STV0297
tristate "ST STV0297 based"
@ -164,6 +173,11 @@ config DVB_NXT2002
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
This driver needs external firmware. Please use the command
"<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
download/extract it, and then copy it to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_NXT200X
tristate "Nextwave NXT2002/NXT2004 based"
depends on DVB_CORE
@ -172,6 +186,12 @@ config DVB_NXT200X
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
to support this frontend.
This driver needs external firmware. Please use the commands
"<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" and
"<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
download/extract them, and then copy them to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
config DVB_OR51211
tristate "or51211 based (pcHDTV HD2000 card)"
depends on DVB_CORE

View file

@ -32,3 +32,4 @@ obj-$(CONFIG_DVB_OR51132) += or51132.o
obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
obj-$(CONFIG_DVB_CX24123) += cx24123.o

View file

@ -255,7 +255,7 @@ static int bcm3510_bert_reset(struct bcm3510_state *st)
bcm3510_register_value b;
int ret;
if ((ret < bcm3510_readB(st,0xfa,&b)) < 0)
if ((ret = bcm3510_readB(st,0xfa,&b)) < 0)
return ret;
b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
@ -623,13 +623,13 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe)
err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
return ret;
}
deb_info("got firmware: %d\n",fw->size);
deb_info("got firmware: %zd\n",fw->size);
b = fw->data;
for (i = 0; i < fw->size;) {
addr = le16_to_cpu( *( (u16 *)&b[i] ) );
len = le16_to_cpu( *( (u16 *)&b[i+2] ) );
deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04x\n",addr,len,fw->size);
deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size);
if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
err("firmware download failed: %d\n",ret);
return ret;

View file

@ -195,6 +195,16 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
return 0;
}
static int cx22702_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
{
struct cx22702_state* state = fe->demodulator_priv;
dprintk ("%s(%d)\n", __FUNCTION__, enable);
if (enable)
return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) & 0xfe);
else
return cx22702_writereg (state, 0x0D, cx22702_readreg(state, 0x0D) | 1);
}
/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
@ -202,7 +212,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
struct cx22702_state* state = fe->demodulator_priv;
/* set PLL */
cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
cx22702_i2c_gate_ctrl(fe, 1);
if (state->config->pll_set) {
state->config->pll_set(fe, p);
} else if (state->config->pll_desc) {
@ -216,7 +226,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
} else {
BUG();
}
cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
cx22702_i2c_gate_ctrl(fe, 0);
/* set inversion */
cx22702_set_inversion (state, p->inversion);
@ -349,11 +359,10 @@ static int cx22702_init (struct dvb_frontend* fe)
cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
/* init PLL */
if (state->config->pll_init) {
cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) & 0xfe);
if (state->config->pll_init)
state->config->pll_init(fe);
cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
}
cx22702_i2c_gate_ctrl(fe, 0);
return 0;
}
@ -531,6 +540,7 @@ static struct dvb_frontend_ops cx22702_ops = {
.read_signal_strength = cx22702_read_signal_strength,
.read_snr = cx22702_read_snr,
.read_ucblocks = cx22702_read_ucblocks,
.i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
};
module_param(debug, int, 0644);

View file

@ -27,7 +27,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include "dvb_frontend.h"
#include "cx24110.h"
@ -56,7 +55,7 @@ static int debug;
static struct {u8 reg; u8 data;} cx24110_regdata[]=
/* Comments beginning with @ denote this value should
be the default */
be the default */
{{0x09,0x01}, /* SoftResetAll */
{0x09,0x00}, /* release reset */
{0x01,0xe8}, /* MSB of code rate 27.5MS/s */
@ -67,26 +66,26 @@ static struct {u8 reg; u8 data;} cx24110_regdata[]=
{0x07,0x01}, /* @ Fclk, i.e. sampling clock, 60MHz */
{0x0a,0x00}, /* @ partial chip disables, do not set */
{0x0b,0x01}, /* set output clock in gapped mode, start signal low
active for first byte */
active for first byte */
{0x0c,0x11}, /* no parity bytes, large hold time, serial data out */
{0x0d,0x6f}, /* @ RS Sync/Unsync thresholds */
{0x10,0x40}, /* chip doc is misleading here: write bit 6 as 1
to avoid starting the BER counter. Reset the
CRC test bit. Finite counting selected */
to avoid starting the BER counter. Reset the
CRC test bit. Finite counting selected */
{0x15,0xff}, /* @ size of the limited time window for RS BER
estimation. It is <value>*256 RS blocks, this
gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
estimation. It is <value>*256 RS blocks, this
gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
{0x16,0x00}, /* @ enable all RS output ports */
{0x17,0x04}, /* @ time window allowed for the RS to sync */
{0x18,0xae}, /* @ allow all standard DVB code rates to be scanned
for automatically */
for automatically */
/* leave the current code rate and normalization
registers as they are after reset... */
registers as they are after reset... */
{0x21,0x10}, /* @ during AutoAcq, search each viterbi setting
only once */
only once */
{0x23,0x18}, /* @ size of the limited time window for Viterbi BER
estimation. It is <value>*65536 channel bits, i.e.
approx. 38ms at 27.5MS/s, rate 3/4 */
estimation. It is <value>*65536 channel bits, i.e.
approx. 38ms at 27.5MS/s, rate 3/4 */
{0x24,0x24}, /* do not trigger Viterbi CRC test. Finite count window */
/* leave front-end AGC parameters at default values */
/* leave decimation AGC parameters at default values */

View file

@ -0,0 +1,889 @@
/*
Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
Copyright (C) 2005 Steven Toth <stoth@hauppauge.com>
Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
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/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include "dvb_frontend.h"
#include "cx24123.h"
static int debug;
#define dprintk(args...) \
do { \
if (debug) printk (KERN_DEBUG "cx24123: " args); \
} while (0)
struct cx24123_state
{
struct i2c_adapter* i2c;
struct dvb_frontend_ops ops;
const struct cx24123_config* config;
struct dvb_frontend frontend;
u32 lastber;
u16 snr;
u8 lnbreg;
/* Some PLL specifics for tuning */
u32 VCAarg;
u32 VGAarg;
u32 bandselectarg;
u32 pllarg;
/* The Demod/Tuner can't easily provide these, we cache them */
u32 currentfreq;
u32 currentsymbolrate;
};
/* Various tuner defaults need to be established for a given symbol rate Sps */
static struct
{
u32 symbolrate_low;
u32 symbolrate_high;
u32 VCAslope;
u32 VCAoffset;
u32 VGA1offset;
u32 VGA2offset;
u32 VCAprogdata;
u32 VGAprogdata;
} cx24123_AGC_vals[] =
{
{
.symbolrate_low = 1000000,
.symbolrate_high = 4999999,
.VCAslope = 0x07,
.VCAoffset = 0x0f,
.VGA1offset = 0x1f8,
.VGA2offset = 0x1f8,
.VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8,
.VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07,
},
{
.symbolrate_low = 5000000,
.symbolrate_high = 14999999,
.VCAslope = 0x1f,
.VCAoffset = 0x1f,
.VGA1offset = 0x1e0,
.VGA2offset = 0x180,
.VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0,
.VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f,
},
{
.symbolrate_low = 15000000,
.symbolrate_high = 45000000,
.VCAslope = 0x3f,
.VCAoffset = 0x3f,
.VGA1offset = 0x180,
.VGA2offset = 0x100,
.VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180,
.VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f,
},
};
/*
* Various tuner defaults need to be established for a given frequency kHz.
* fixme: The bounds on the bands do not match the doc in real life.
* fixme: Some of them have been moved, other might need adjustment.
*/
static struct
{
u32 freq_low;
u32 freq_high;
u32 bandselect;
u32 VCOdivider;
u32 VCOnumber;
u32 progdata;
} cx24123_bandselect_vals[] =
{
{
.freq_low = 950000,
.freq_high = 1018999,
.bandselect = 0x40,
.VCOdivider = 4,
.VCOnumber = 7,
.progdata = (0 << 18) | (0 << 9) | 0x40,
},
{
.freq_low = 1019000,
.freq_high = 1074999,
.bandselect = 0x80,
.VCOdivider = 4,
.VCOnumber = 8,
.progdata = (0 << 18) | (0 << 9) | 0x80,
},
{
.freq_low = 1075000,
.freq_high = 1227999,
.bandselect = 0x01,
.VCOdivider = 2,
.VCOnumber = 1,
.progdata = (0 << 18) | (1 << 9) | 0x01,
},
{
.freq_low = 1228000,
.freq_high = 1349999,
.bandselect = 0x02,
.VCOdivider = 2,
.VCOnumber = 2,
.progdata = (0 << 18) | (1 << 9) | 0x02,
},
{
.freq_low = 1350000,
.freq_high = 1481999,
.bandselect = 0x04,
.VCOdivider = 2,
.VCOnumber = 3,
.progdata = (0 << 18) | (1 << 9) | 0x04,
},
{
.freq_low = 1482000,
.freq_high = 1595999,
.bandselect = 0x08,
.VCOdivider = 2,
.VCOnumber = 4,
.progdata = (0 << 18) | (1 << 9) | 0x08,
},
{
.freq_low = 1596000,
.freq_high = 1717999,
.bandselect = 0x10,
.VCOdivider = 2,
.VCOnumber = 5,
.progdata = (0 << 18) | (1 << 9) | 0x10,
},
{
.freq_low = 1718000,
.freq_high = 1855999,
.bandselect = 0x20,
.VCOdivider = 2,
.VCOnumber = 6,
.progdata = (0 << 18) | (1 << 9) | 0x20,
},
{
.freq_low = 1856000,
.freq_high = 2035999,
.bandselect = 0x40,
.VCOdivider = 2,
.VCOnumber = 7,
.progdata = (0 << 18) | (1 << 9) | 0x40,
},
{
.freq_low = 2036000,
.freq_high = 2149999,
.bandselect = 0x80,
.VCOdivider = 2,
.VCOnumber = 8,
.progdata = (0 << 18) | (1 << 9) | 0x80,
},
};
static struct {
u8 reg;
u8 data;
} cx24123_regdata[] =
{
{0x00, 0x03}, /* Reset system */
{0x00, 0x00}, /* Clear reset */
{0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */
{0x03, 0x07},
{0x04, 0x10},
{0x05, 0x04},
{0x06, 0x31},
{0x0d, 0x02},
{0x0e, 0x03},
{0x0f, 0xfe},
{0x10, 0x01},
{0x14, 0x01},
{0x15, 0x98},
{0x16, 0x00},
{0x17, 0x01},
{0x1b, 0x05},
{0x1c, 0x80},
{0x1d, 0x00},
{0x1e, 0x00},
{0x20, 0x41},
{0x21, 0x15},
{0x27, 0x14},
{0x28, 0x46},
{0x29, 0x00},
{0x2a, 0xb0},
{0x2b, 0x73},
{0x2c, 0x00},
{0x2d, 0x00},
{0x2e, 0x00},
{0x2f, 0x00},
{0x30, 0x00},
{0x31, 0x00},
{0x32, 0x8c},
{0x33, 0x00},
{0x34, 0x00},
{0x35, 0x03},
{0x36, 0x02},
{0x37, 0x3a},
{0x3a, 0x00}, /* Enable AGC accumulator */
{0x44, 0x00},
{0x45, 0x00},
{0x46, 0x05},
{0x56, 0x41},
{0x57, 0xff},
{0x67, 0x83},
};
static int cx24123_writereg(struct cx24123_state* state, int reg, int data)
{
u8 buf[] = { reg, data };
struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
int err;
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
printk("%s: writereg error(err == %i, reg == 0x%02x,"
" data == 0x%02x)\n", __FUNCTION__, err, reg, data);
return -EREMOTEIO;
}
return 0;
}
static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
{
u8 buf[] = { reg, data };
/* fixme: put the intersil addr int the config */
struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
int err;
if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
" data == 0x%02x)\n", __FUNCTION__, err, reg, data);
return -EREMOTEIO;
}
/* cache the write, no way to read back */
state->lnbreg = data;
return 0;
}
static int cx24123_readreg(struct cx24123_state* state, u8 reg)
{
int ret;
u8 b0[] = { reg };
u8 b1[] = { 0 };
struct i2c_msg msg[] = {
{ .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 }
};
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) {
printk("%s: reg=0x%x (error=%d)\n", __FUNCTION__, reg, ret);
return ret;
}
return b1[0];
}
static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
{
return state->lnbreg;
}
static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
{
switch (inversion) {
case INVERSION_OFF:
cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f);
cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
break;
case INVERSION_ON:
cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80);
cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80);
break;
case INVERSION_AUTO:
cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f);
break;
default:
return -EINVAL;
}
return 0;
}
static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_inversion_t *inversion)
{
u8 val;
val = cx24123_readreg(state, 0x1b) >> 7;
if (val == 0)
*inversion = INVERSION_OFF;
else
*inversion = INVERSION_ON;
return 0;
}
static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec)
{
if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
fec = FEC_AUTO;
/* Hardware has 5/11 and 3/5 but are never unused */
switch (fec) {
case FEC_NONE:
return cx24123_writereg(state, 0x0f, 0x01);
case FEC_1_2:
return cx24123_writereg(state, 0x0f, 0x02);
case FEC_2_3:
return cx24123_writereg(state, 0x0f, 0x04);
case FEC_3_4:
return cx24123_writereg(state, 0x0f, 0x08);
case FEC_5_6:
return cx24123_writereg(state, 0x0f, 0x20);
case FEC_7_8:
return cx24123_writereg(state, 0x0f, 0x80);
case FEC_AUTO:
return cx24123_writereg(state, 0x0f, 0xae);
default:
return -EOPNOTSUPP;
}
}
static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec)
{
int ret;
u8 val;
ret = cx24123_readreg (state, 0x1b);
if (ret < 0)
return ret;
val = ret & 0x07;
switch (val) {
case 1:
*fec = FEC_1_2;
break;
case 3:
*fec = FEC_2_3;
break;
case 4:
*fec = FEC_3_4;
break;
case 5:
*fec = FEC_4_5;
break;
case 6:
*fec = FEC_5_6;
break;
case 7:
*fec = FEC_7_8;
break;
case 2: /* *fec = FEC_3_5; break; */
case 0: /* *fec = FEC_5_11; break; */
*fec = FEC_AUTO;
break;
default:
*fec = FEC_NONE; // can't happen
}
return 0;
}
/* fixme: Symbol rates < 3MSps may not work because of precision loss */
static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate)
{
u32 val;
val = (srate / 1185) * 100;
/* Compensate for scaling up, by removing 17 symbols per 1Msps */
val = val - (17 * (srate / 1000000));
cx24123_writereg(state, 0x08, (val >> 16) & 0xff );
cx24123_writereg(state, 0x09, (val >> 8) & 0xff );
cx24123_writereg(state, 0x0a, (val ) & 0xff );
return 0;
}
/*
* Based on the required frequency and symbolrate, the tuner AGC has to be configured
* and the correct band selected. Calculate those values
*/
static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
u32 ndiv = 0, adiv = 0, vco_div = 0;
int i = 0;
/* Defaults for low freq, low rate */
state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
state->VGAarg = cx24123_AGC_vals[0].VGAprogdata;
state->bandselectarg = cx24123_bandselect_vals[0].progdata;
vco_div = cx24123_bandselect_vals[0].VCOdivider;
/* For the given symbolerate, determine the VCA and VGA programming bits */
for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++)
{
if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) &&
(cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) {
state->VCAarg = cx24123_AGC_vals[i].VCAprogdata;
state->VGAarg = cx24123_AGC_vals[i].VGAprogdata;
}
}
/* For the given frequency, determine the bandselect programming bits */
for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++)
{
if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) &&
(cx24123_bandselect_vals[i].freq_high >= p->frequency) ) {
state->bandselectarg = cx24123_bandselect_vals[i].progdata;
vco_div = cx24123_bandselect_vals[i].VCOdivider;
}
}
/* Determine the N/A dividers for the requested lband freq (in kHz). */
/* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */
ndiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) / 32) & 0x1ff;
adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f;
if (adiv == 0)
adiv++;
/* determine the correct pll frequency values. */
/* Command 11, refdiv 11, cpump polarity 1, cpump current 3mA 10. */
state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (2 << 14);
state->pllarg |= (ndiv << 5) | adiv;
return 0;
}
/*
* Tuner data is 21 bits long, must be left-aligned in data.
* Tuner cx24109 is written through a dedicated 3wire interface on the demod chip.
*/
static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_parameters *p, u32 data)
{
struct cx24123_state *state = fe->demodulator_priv;
unsigned long timeout;
/* align the 21 bytes into to bit23 boundary */
data = data << 3;
/* Reset the demod pll word length to 0x15 bits */
cx24123_writereg(state, 0x21, 0x15);
/* write the msb 8 bits, wait for the send to be completed */
timeout = jiffies + msecs_to_jiffies(40);
cx24123_writereg(state, 0x22, (data >> 16) & 0xff);
while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
if (time_after(jiffies, timeout)) {
printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
return -EREMOTEIO;
}
msleep(10);
}
/* send another 8 bytes, wait for the send to be completed */
timeout = jiffies + msecs_to_jiffies(40);
cx24123_writereg(state, 0x22, (data>>8) & 0xff );
while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
if (time_after(jiffies, timeout)) {
printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
return -EREMOTEIO;
}
msleep(10);
}
/* send the lower 5 bits of this byte, padded with 3 LBB, wait for the send to be completed */
timeout = jiffies + msecs_to_jiffies(40);
cx24123_writereg(state, 0x22, (data) & 0xff );
while ((cx24123_readreg(state, 0x20) & 0x80)) {
if (time_after(jiffies, timeout)) {
printk("%s: demodulator is not responding, possibly hung, aborting.\n", __FUNCTION__);
return -EREMOTEIO;
}
msleep(10);
}
/* Trigger the demod to configure the tuner */
cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) | 2);
cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) & 0xfd);
return 0;
}
static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
if (cx24123_pll_calculate(fe, p) != 0) {
printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__);
return -EINVAL;
}
/* Write the new VCO/VGA */
cx24123_pll_writereg(fe, p, state->VCAarg);
cx24123_pll_writereg(fe, p, state->VGAarg);
/* Write the new bandselect and pll args */
cx24123_pll_writereg(fe, p, state->bandselectarg);
cx24123_pll_writereg(fe, p, state->pllarg);
return 0;
}
static int cx24123_initfe(struct dvb_frontend* fe)
{
struct cx24123_state *state = fe->demodulator_priv;
int i;
/* Configure the demod to a good set of defaults */
for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
if (state->config->pll_init)
state->config->pll_init(fe);
/* Configure the LNB for 14V */
if (state->config->use_isl6421)
cx24123_writelnbreg(state, 0x0, 0x2a);
return 0;
}
static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
switch (state->config->use_isl6421) {
case 1:
val = cx24123_readlnbreg(state, 0x0);
switch (voltage) {
case SEC_VOLTAGE_13:
return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
case SEC_VOLTAGE_18:
return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
case SEC_VOLTAGE_OFF:
return cx24123_writelnbreg(state, 0x0, val & 0x30);
default:
return -EINVAL;
};
case 0:
val = cx24123_readreg(state, 0x29);
switch (voltage) {
case SEC_VOLTAGE_13:
dprintk("%s: setting voltage 13V\n", __FUNCTION__);
if (state->config->enable_lnb_voltage)
state->config->enable_lnb_voltage(fe, 1);
return cx24123_writereg(state, 0x29, val | 0x80);
case SEC_VOLTAGE_18:
dprintk("%s: setting voltage 18V\n", __FUNCTION__);
if (state->config->enable_lnb_voltage)
state->config->enable_lnb_voltage(fe, 1);
return cx24123_writereg(state, 0x29, val & 0x7f);
case SEC_VOLTAGE_OFF:
dprintk("%s: setting voltage off\n", __FUNCTION__);
if (state->config->enable_lnb_voltage)
state->config->enable_lnb_voltage(fe, 0);
return 0;
default:
return -EINVAL;
};
}
return 0;
}
static int cx24123_send_diseqc_msg(struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *cmd)
{
/* fixme: Implement diseqc */
printk("%s: No support yet\n",__FUNCTION__);
return -ENOTSUPP;
}
static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
struct cx24123_state *state = fe->demodulator_priv;
int sync = cx24123_readreg(state, 0x14);
int lock = cx24123_readreg(state, 0x20);
*status = 0;
if (lock & 0x01)
*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
if (sync & 0x04)
*status |= FE_HAS_VITERBI;
if (sync & 0x08)
*status |= FE_HAS_CARRIER;
if (sync & 0x80)
*status |= FE_HAS_SYNC | FE_HAS_LOCK;
return 0;
}
/*
* Configured to return the measurement of errors in blocks, because no UCBLOCKS value
* is available, so this value doubles up to satisfy both measurements
*/
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) |
(cx24123_readreg(state, 0x1d) << 8 |
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;
*ber = state->lastber;
return 0;
}
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 */
return 0;
}
static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
{
struct cx24123_state *state = fe->demodulator_priv;
*snr = state->snr;
return 0;
}
static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
struct cx24123_state *state = fe->demodulator_priv;
*ucblocks = state->lastber;
return 0;
}
static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
if (state->config->set_ts_params)
state->config->set_ts_params(fe, 0);
state->currentfreq=p->frequency;
state->currentsymbolrate = p->u.qpsk.symbol_rate;
cx24123_set_inversion(state, p->inversion);
cx24123_set_fec(state, p->u.qpsk.fec_inner);
cx24123_set_symbolrate(state, p->u.qpsk.symbol_rate);
cx24123_pll_tune(fe, p);
/* Enable automatic aquisition and reset cycle */
cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
cx24123_writereg(state, 0x00, 0x10);
cx24123_writereg(state, 0x00, 0);
return 0;
}
static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct cx24123_state *state = fe->demodulator_priv;
if (cx24123_get_inversion(state, &p->inversion) != 0) {
printk("%s: Failed to get inversion status\n",__FUNCTION__);
return -EREMOTEIO;
}
if (cx24123_get_fec(state, &p->u.qpsk.fec_inner) != 0) {
printk("%s: Failed to get fec status\n",__FUNCTION__);
return -EREMOTEIO;
}
p->frequency = state->currentfreq;
p->u.qpsk.symbol_rate = state->currentsymbolrate;
return 0;
}
static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct cx24123_state *state = fe->demodulator_priv;
u8 val;
switch (state->config->use_isl6421) {
case 1:
val = cx24123_readlnbreg(state, 0x0);
switch (tone) {
case SEC_TONE_ON:
return cx24123_writelnbreg(state, 0x0, val | 0x10);
case SEC_TONE_OFF:
return cx24123_writelnbreg(state, 0x0, val & 0x2f);
default:
printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
return -EINVAL;
}
case 0:
val = cx24123_readreg(state, 0x29);
switch (tone) {
case SEC_TONE_ON:
dprintk("%s: setting tone on\n", __FUNCTION__);
return cx24123_writereg(state, 0x29, val | 0x10);
case SEC_TONE_OFF:
dprintk("%s: setting tone off\n",__FUNCTION__);
return cx24123_writereg(state, 0x29, val & 0xef);
default:
printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
return -EINVAL;
}
}
return 0;
}
static void cx24123_release(struct dvb_frontend* fe)
{
struct cx24123_state* state = fe->demodulator_priv;
dprintk("%s\n",__FUNCTION__);
kfree(state);
}
static struct dvb_frontend_ops cx24123_ops;
struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
struct i2c_adapter* i2c)
{
struct cx24123_state* state = NULL;
int ret;
dprintk("%s\n",__FUNCTION__);
/* allocate memory for the internal state */
state = kmalloc(sizeof(struct cx24123_state), GFP_KERNEL);
if (state == NULL) {
printk("Unable to kmalloc\n");
goto error;
}
/* setup the state */
state->config = config;
state->i2c = i2c;
memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
state->lastber = 0;
state->snr = 0;
state->lnbreg = 0;
state->VCAarg = 0;
state->VGAarg = 0;
state->bandselectarg = 0;
state->pllarg = 0;
state->currentfreq = 0;
state->currentsymbolrate = 0;
/* check if the demod is there */
ret = cx24123_readreg(state, 0x00);
if ((ret != 0xd1) && (ret != 0xe1)) {
printk("Version != d1 or e1\n");
goto error;
}
/* create dvb_frontend */
state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
return &state->frontend;
error:
kfree(state);
return NULL;
}
static struct dvb_frontend_ops cx24123_ops = {
.info = {
.name = "Conexant CX24123/CX24109",
.type = FE_QPSK,
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 1011, /* kHz for QPSK frontends */
.frequency_tolerance = 29500,
.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_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_RECOVER
},
.release = cx24123_release,
.init = cx24123_initfe,
.set_frontend = cx24123_set_frontend,
.get_frontend = cx24123_get_frontend,
.read_status = cx24123_read_status,
.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,
.set_tone = cx24123_set_tone,
.set_voltage = cx24123_set_voltage,
};
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware");
MODULE_AUTHOR("Steven Toth");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(cx24123_attach);

View file

@ -0,0 +1,51 @@
/*
Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
Copyright (C) 2005 Steven Toth <stoth@hauppauge.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 CX24123_H
#define CX24123_H
#include <linux/dvb/frontend.h>
struct cx24123_config
{
/* the demodulator's i2c address */
u8 demod_address;
/*
cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
from register 0x29 of the CX24123 demodulator
*/
int use_isl6421;
/* PLL maintenance */
int (*pll_init)(struct dvb_frontend* fe);
int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
/* Need to set device param for start_dma */
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
};
extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
struct i2c_adapter* i2c);
#endif /* CX24123_H */

View file

@ -107,18 +107,19 @@ struct dvb_pll_desc dvb_pll_microtune_4042 = {
};
EXPORT_SYMBOL(dvb_pll_microtune_4042);
struct dvb_pll_desc dvb_pll_thomson_dtt7611 = {
.name = "Thomson dtt7611",
.min = 44000000,
.max = 958000000,
struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
.name = "Thomson dtt761x",
.min = 57000000,
.max = 863000000,
.count = 3,
.entries = {
{ 157250000, 44000000, 62500, 0x8e, 0x39 },
{ 454000000, 44000000, 62500, 0x8e, 0x3a },
{ 147000000, 44000000, 62500, 0x8e, 0x39 },
{ 417000000, 44000000, 62500, 0x8e, 0x3a },
{ 999999999, 44000000, 62500, 0x8e, 0x3c },
},
};
EXPORT_SYMBOL(dvb_pll_thomson_dtt7611);
EXPORT_SYMBOL(dvb_pll_thomson_dtt761x);
struct dvb_pll_desc dvb_pll_unknown_1 = {
.name = "unknown 1", /* used by dntv live dvb-t */

View file

@ -25,7 +25,7 @@ extern struct dvb_pll_desc dvb_pll_thomson_dtt759x;
extern struct dvb_pll_desc dvb_pll_thomson_dtt7610;
extern struct dvb_pll_desc dvb_pll_lg_z201;
extern struct dvb_pll_desc dvb_pll_microtune_4042;
extern struct dvb_pll_desc dvb_pll_thomson_dtt7611;
extern struct dvb_pll_desc dvb_pll_thomson_dtt761x;
extern struct dvb_pll_desc dvb_pll_unknown_1;
extern struct dvb_pll_desc dvb_pll_tua6010xs;

View file

@ -27,6 +27,7 @@
* DViCO FusionHDTV 3 Gold-T
* DViCO FusionHDTV 5 Gold
* DViCO FusionHDTV 5 Lite
* DViCO FusionHDTV 5 USB Gold
* Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
*
* TODO:
@ -402,6 +403,8 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
state->config->pll_set(fe, param);
/* Keep track of the new frequency */
/* FIXME this is the wrong way to do this... */
/* The tuner is shared with the video4linux analog API */
state->current_frequency = param->frequency;
lgdt330x_SwReset(state);

View file

@ -22,7 +22,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
* download/extract it, and then copy it to /usr/lib/hotplug/firmware.
* download/extract it, and then copy it to /usr/lib/hotplug/firmware
* or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
#define CRC_CCIT_MASK 0x1021

View file

@ -574,11 +574,11 @@ static struct dvb_frontend_ops nxt6000_ops = {
.symbol_rate_max = 9360000, /* FIXME */
.symbol_rate_tolerance = 4000,
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO,
FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO,
},
.release = nxt6000_release,

View file

@ -25,7 +25,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
* download/extract it, and then copy it to /usr/lib/hotplug/firmware.
* download/extract it, and then copy it to /usr/lib/hotplug/firmware
* or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw"
@ -112,7 +113,7 @@ static int or51211_load_firmware (struct dvb_frontend* fe,
u8 tudata[585];
int i;
dprintk("Firmware is %d bytes\n",fw->size);
dprintk("Firmware is %zd bytes\n",fw->size);
/* Get eprom data */
tudata[0] = 17;

View file

@ -521,8 +521,8 @@ static void s5h1420_setfec_inversion(struct s5h1420_state* state,
case FEC_3_4:
s5h1420_writereg(state, 0x30, 0x04);
s5h1420_writereg(state, 0x31, 0x12 | inversion);
break;
s5h1420_writereg(state, 0x31, 0x12 | inversion);
break;
case FEC_5_6:
s5h1420_writereg(state, 0x30, 0x08);

View file

@ -22,7 +22,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware alps_tdlb7" to
* download/extract it, and then copy it to /usr/lib/hotplug/firmware.
* download/extract it, and then copy it to /usr/lib/hotplug/firmware
* or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"

View file

@ -5,7 +5,8 @@
/*
* This driver needs external firmware. Please use the command
* "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
* download/extract it, and then copy it to /usr/lib/hotplug/firmware.
* download/extract it, and then copy it to /usr/lib/hotplug/firmware
* or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw"
@ -581,7 +582,7 @@ static struct dvb_frontend_ops sp887x_ops = {
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
FE_CAN_RECOVER
FE_CAN_RECOVER
},
.release = sp887x_release,

View file

@ -131,6 +131,13 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
return ret == 2 ? 0 : ret;
}
int stv0299_enable_plli2c (struct dvb_frontend* fe)
{
struct stv0299_state* state = fe->demodulator_priv;
return stv0299_writeregI(state, 0x05, 0xb5); /* enable i2c repeater on stv0299 */
}
static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
{
dprintk ("%s\n", __FUNCTION__);
@ -387,7 +394,7 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
};
}
static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
{
struct stv0299_state* state = fe->demodulator_priv;
u8 reg0x08;
@ -407,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
cmd = cmd << 1;
if (debug_legacy_dish_switch)
printk ("%s switch command: 0x%04x\n",__FUNCTION__, cmd);
printk ("%s switch command: 0x%04lx\n",__FUNCTION__, cmd);
do_gettimeofday (&nexttime);
if (debug_legacy_dish_switch)
@ -717,5 +724,6 @@ MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
"Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(stv0299_enable_plli2c);
EXPORT_SYMBOL(stv0299_writereg);
EXPORT_SYMBOL(stv0299_attach);

View file

@ -94,6 +94,7 @@ struct stv0299_config
};
extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
extern int stv0299_enable_plli2c (struct dvb_frontend* fe);
extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
struct i2c_adapter* i2c);

View file

@ -95,7 +95,7 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
u8 b0 [] = { reg };
u8 b1 [] = { 0 };
struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
int ret;
ret = i2c_transfer (state->i2c, msg, 2);
@ -434,7 +434,7 @@ static struct dvb_frontend_ops tda10021_ops = {
.frequency_max = 858000000,
.symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */
.symbol_rate_max = (XIN/2)/4, /* SACLK/4 */
#if 0
#if 0
.frequency_tolerance = ???,
.symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */
#endif

View file

@ -23,7 +23,8 @@
* This driver needs external firmware. Please use the commands
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
* download/extract them, and then copy them to /usr/lib/hotplug/firmware.
* download/extract them, and then copy them to /usr/lib/hotplug/firmware
* or /lib/firmware (depending on configuration of firmware hotplug).
*/
#define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw"
#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw"
@ -271,32 +272,57 @@ static int tda10045h_set_bandwidth(struct tda1004x_state *state,
static int tda10046h_set_bandwidth(struct tda1004x_state *state,
fe_bandwidth_t bandwidth)
{
static u8 bandwidth_6mhz[] = { 0x80, 0x15, 0xfe, 0xab, 0x8e };
static u8 bandwidth_7mhz[] = { 0x6e, 0x02, 0x53, 0xc8, 0x25 };
static u8 bandwidth_8mhz[] = { 0x60, 0x12, 0xa8, 0xe4, 0xbd };
static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 };
static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f };
static u8 bandwidth_8mhz_53M[] = { 0x5c, 0x32, 0xc2, 0x96, 0x6d };
static u8 bandwidth_6mhz_48M[] = { 0x70, 0x02, 0x49, 0x24, 0x92 };
static u8 bandwidth_7mhz_48M[] = { 0x60, 0x02, 0xaa, 0xaa, 0xab };
static u8 bandwidth_8mhz_48M[] = { 0x54, 0x03, 0x0c, 0x30, 0xc3 };
int tda10046_clk53m;
if ((state->config->if_freq == TDA10046_FREQ_045) ||
(state->config->if_freq == TDA10046_FREQ_052))
tda10046_clk53m = 0;
else
tda10046_clk53m = 1;
switch (bandwidth) {
case BANDWIDTH_6_MHZ:
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz));
if (tda10046_clk53m)
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M,
sizeof(bandwidth_6mhz_53M));
else
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_48M,
sizeof(bandwidth_6mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x09);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x4f);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab);
}
break;
case BANDWIDTH_7_MHZ:
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz));
if (tda10046_clk53m)
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M,
sizeof(bandwidth_7mhz_53M));
else
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_48M,
sizeof(bandwidth_7mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x79);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
}
break;
case BANDWIDTH_8_MHZ:
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz));
if (tda10046_clk53m)
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M,
sizeof(bandwidth_8mhz_53M));
else
tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_48M,
sizeof(bandwidth_8mhz_48M));
if (state->config->if_freq == TDA10046_FREQ_045) {
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55);
}
break;
@ -418,9 +444,22 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
static void tda10046_init_plls(struct dvb_frontend* fe)
{
struct tda1004x_state* state = fe->demodulator_priv;
int tda10046_clk53m;
if ((state->config->if_freq == TDA10046_FREQ_045) ||
(state->config->if_freq == TDA10046_FREQ_052))
tda10046_clk53m = 0;
else
tda10046_clk53m = 1;
tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0);
tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x0a); // PLL M = 10
if(tda10046_clk53m) {
printk(KERN_INFO "tda1004x: setting up plls for 53MHz sampling clock\n");
tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x08); // PLL M = 8
} else {
printk(KERN_INFO "tda1004x: setting up plls for 48MHz sampling clock\n");
tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
}
if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
@ -428,26 +467,32 @@ static void tda10046_init_plls(struct dvb_frontend* fe)
dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __FUNCTION__);
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
}
tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99);
if(tda10046_clk53m)
tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x67);
else
tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x72);
/* Note clock frequency is handled implicitly */
switch (state->config->if_freq) {
case TDA10046_FREQ_3617:
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c);
break;
case TDA10046_FREQ_3613:
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x13);
break;
case TDA10046_FREQ_045:
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
break;
case TDA10046_FREQ_052:
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x06);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xc7);
break;
case TDA10046_FREQ_3617:
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x59);
break;
case TDA10046_FREQ_3613:
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f);
break;
}
tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz
/* let the PLLs settle */
msleep(120);
}
static int tda10046_fwupload(struct dvb_frontend* fe)
@ -462,13 +507,13 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
/* let the clocks recover from sleep */
msleep(5);
/* The PLLs need to be reprogrammed after sleep */
tda10046_init_plls(fe);
/* don't re-upload unless necessary */
if (tda1004x_check_upload_ok(state) == 0)
return 0;
/* set parameters */
tda10046_init_plls(fe);
if (state->config->request_firmware != NULL) {
/* request the firmware, this will block until someone uploads it */
printk(KERN_INFO "tda1004x: waiting for firmware upload...\n");
@ -484,7 +529,6 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
return ret;
} else {
/* boot from firmware eeprom */
/* Hac Note: we might need to do some GPIO Magic here */
printk(KERN_INFO "tda1004x: booting from eeprom\n");
tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4);
msleep(300);
@ -606,10 +650,9 @@ static int tda10046_init(struct dvb_frontend* fe)
// tda setup
tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
tda1004x_write_byteI(state, TDA1004X_AUTO, 7); // select HP stream
tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87); // 100 ppm crystal, select HP stream
tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
tda10046_init_plls(fe);
switch (state->config->agc_config) {
case TDA10046_AGC_DEFAULT:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup
@ -626,25 +669,22 @@ static int tda10046_init(struct dvb_frontend* fe)
case TDA10046_AGC_TDA827X:
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70); // AGC Threshold
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x0E); // Gain Renormalize
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities
break;
}
tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // }
tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // }
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff); // }
tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1
tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 0x12); // IF gain 2, TUN gain 1
tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits
tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config
tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config
tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup
tda1004x_write_byteI(state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config
tda1004x_write_byteI(state, TDA10046H_GPIO_SELECT, 8); // GPIO select
state->initialised = 1;
return 0;
}
@ -686,9 +726,9 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// Set standard params.. or put them to auto
if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) ||
(fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
(fe_params->u.ofdm.constellation == QAM_AUTO) ||
(fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
(fe_params->u.ofdm.code_rate_LP == FEC_AUTO) ||
(fe_params->u.ofdm.constellation == QAM_AUTO) ||
(fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) {
tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1); // enable auto
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits
tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits
@ -851,6 +891,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
{
struct tda1004x_state* state = fe->demodulator_priv;
dprintk("%s\n", __FUNCTION__);
// inversion status
@ -875,16 +916,18 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
break;
}
break;
case TDA1004X_DEMOD_TDA10046:
switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
case 0x60:
case 0x5c:
case 0x54:
fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
break;
case 0x6e:
case 0x6a:
case 0x60:
fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
break;
case 0x80:
case 0x7b:
case 0x70:
fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
break;
}

View file

@ -8,7 +8,7 @@ config DVB_PLUTO2
Support for PCI cards based on the Pluto2 FPGA like the Satelco
Easywatch Mobile Terrestrial DVB-T Receiver.
Since these cards have no MPEG decoder onboard, they transmit
Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the PCI bus, so you need
an external software decoder to watch TV on your computer.

View file

@ -18,9 +18,10 @@ config DVB_AV7110
This driver only supports the fullfeatured cards with
onboard MPEG2 decoder.
This driver needs an external firmware. Please use the script
"<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
download/extract it, and then copy it to /usr/lib/hotplug/firmware.
This driver needs an external firmware. Please use the script
"<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
download/extract it, and then copy it to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
Say Y if you own such a card and want to use it.

View file

@ -16,7 +16,7 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
hostprogs-y := fdump
ifdef CONFIG_DVB_AV7110_FIRMWARE
$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
$(obj)/av7110_firm.h:
$(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@

View file

@ -133,7 +133,13 @@ static void init_av7110_av(struct av7110 *av7110)
/* remaining inits according to card and frontend type */
av7110->analog_tuner_flags = 0;
av7110->current_input = 0;
if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) {
printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n",
av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_MSP34x5;
av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
}
else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_CRYSTAL;
@ -156,10 +162,10 @@ static void init_av7110_av(struct av7110 *av7110)
else {
av7110->adac_type = adac;
printk("dvb-ttpci: adac type set to %d @ card %d\n",
av7110->dvb_adapter.num, av7110->adac_type);
av7110->adac_type, av7110->dvb_adapter.num);
}
if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) {
if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
// switch DVB SCART on
ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
if (ret < 0)
@ -190,19 +196,17 @@ static void recover_arm(struct av7110 *av7110)
av7110_bootarm(av7110);
msleep(100);
init_av7110_av(av7110);
/* card-specific recovery */
if (av7110->recover)
av7110->recover(av7110);
restart_feeds(av7110);
av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
}
static void arm_error(struct av7110 *av7110)
{
dprintk(4, "%p\n",av7110);
av7110->arm_errors++;
av7110->arm_ready = 0;
recover_arm(av7110);
}
static void av7110_arm_sync(struct av7110 *av7110)
{
av7110->arm_rmmod = 1;
@ -240,26 +244,22 @@ static int arm_thread(void *data)
if (down_interruptible(&av7110->dcomlock))
break;
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
up(&av7110->dcomlock);
if (newloops == av7110->arm_loops) {
if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
av7110->dvb_adapter.num);
arm_error(av7110);
av7710_set_video_mode(av7110, vidmode);
init_av7110_av(av7110);
recover_arm(av7110);
if (down_interruptible(&av7110->dcomlock))
break;
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
up(&av7110->dcomlock);
}
av7110->arm_loops = newloops;
av7110->arm_errors = 0;
}
av7110->arm_thread = NULL;
@ -510,10 +510,6 @@ static void gpioirq(unsigned long data)
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
av7110->video_size.h = h_ar & 0xfff;
dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
av7110->video_size.w,
av7110->video_size.h,
av7110->video_size.aspect_ratio);
event.type = VIDEO_EVENT_SIZE_CHANGED;
event.u.size.w = av7110->video_size.w;
@ -535,6 +531,11 @@ static void gpioirq(unsigned long data)
event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
av7110->videostate.video_format = VIDEO_FORMAT_4_3;
}
dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
av7110->video_size.w, av7110->video_size.h,
av7110->video_size.aspect_ratio);
dvb_video_add_event(av7110, &event);
break;
}
@ -714,6 +715,8 @@ static struct dvb_device dvbdev_osd = {
static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
u16 subpid, u16 pcrpid)
{
u16 aflags = 0;
dprintk(4, "%p\n", av7110);
if (vpid == 0x1fff || apid == 0x1fff ||
@ -725,8 +728,11 @@ static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
av7110->pids[DMX_PES_PCR] = 0;
}
return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 5,
pcrpid, vpid, apid, ttpid, subpid);
if (av7110->audiostate.bypass_mode)
aflags |= 0x8000;
return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
pcrpid, vpid, apid, ttpid, subpid, aflags);
}
int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
@ -1043,7 +1049,7 @@ static void restart_feeds(struct av7110 *av7110)
struct dvb_demux *dvbdmx = &av7110->demux;
struct dvb_demux_feed *feed;
int mode;
int i;
int i, j;
dprintk(4, "%p\n", av7110);
@ -1051,10 +1057,21 @@ static void restart_feeds(struct av7110 *av7110)
av7110->playing = 0;
av7110->rec_mode = 0;
for (i = 0; i < dvbdmx->filternum; i++) {
for (i = 0; i < dvbdmx->feednum; i++) {
feed = &dvbdmx->feed[i];
if (feed->state == DMX_STATE_GO)
if (feed->state == DMX_STATE_GO) {
if (feed->type == DMX_TYPE_SEC) {
for (j = 0; j < dvbdmx->filternum; j++) {
if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
continue;
if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
continue;
if (dvbdmx->filter[j].state == DMX_STATE_GO)
dvbdmx->filter[j].state = DMX_STATE_READY;
}
}
av7110_start_feed(feed);
}
}
if (mode)
@ -1483,9 +1500,9 @@ static int get_firmware(struct av7110* av7110)
if (ret == -ENOENT) {
printk(KERN_ERR "dvb-ttpci: could not load firmware,"
" file not found: dvb-ttpci-01.fw\n");
printk(KERN_ERR "dvb-ttpci: usually this should be in"
" /usr/lib/hotplug/firmware\n");
printk(KERN_ERR "dvb-ttpci: and can be downloaded here"
printk(KERN_ERR "dvb-ttpci: usually this should be in "
"/usr/lib/hotplug/firmware or /lib/firmware\n");
printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
" http://www.linuxtv.org/download/dvb/firmware/\n");
} else
printk(KERN_ERR "dvb-ttpci: cannot request firmware"
@ -2110,8 +2127,10 @@ static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_p
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
if (!ret)
if (!ret) {
av7110->saved_fe_params = *params;
ret = av7110->fe_set_frontend(fe, params);
}
return ret;
}
@ -2153,8 +2172,10 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
if (!ret)
if (!ret) {
av7110->saved_master_cmd = *cmd;
ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
}
return ret;
}
@ -2163,8 +2184,10 @@ static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
if (!ret)
if (!ret) {
av7110->saved_minicmd = minicmd;
ret = av7110->fe_diseqc_send_burst(fe, minicmd);
}
return ret;
}
@ -2173,8 +2196,10 @@ static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
if (!ret)
if (!ret) {
av7110->saved_tone = tone;
ret = av7110->fe_set_tone(fe, tone);
}
return ret;
}
@ -2183,12 +2208,14 @@ static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t volta
struct av7110* av7110 = fe->dvb->priv;
int ret = av7110_fe_lock_fix(av7110, 0);
if (!ret)
if (!ret) {
av7110->saved_voltage = voltage;
ret = av7110->fe_set_voltage(fe, voltage);
}
return ret;
}
static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd)
static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
{
struct av7110* av7110 = fe->dvb->priv;
@ -2198,6 +2225,23 @@ static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, un
return ret;
}
static void dvb_s_recover(struct av7110* av7110)
{
av7110_fe_init(av7110->fe);
av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
if (av7110->saved_master_cmd.msg_len) {
msleep(20);
av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
}
msleep(20);
av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
msleep(20);
av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
av7110_fe_set_frontend(av7110->fe, &av7110->saved_fe_params);
}
static u8 read_pwm(struct av7110* av7110)
{
u8 b = 0xff;
@ -2235,6 +2279,7 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
av7110->recover = dvb_s_recover;
break;
}
@ -2244,15 +2289,17 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
av7110->recover = dvb_s_recover;
break;
}
// Try the grundig 29504-451
av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
if (av7110->fe) {
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
av7110->recover = dvb_s_recover;
break;
}
@ -2274,12 +2321,12 @@ static int frontend_init(struct av7110 *av7110)
case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
// ALPS TDLB7
av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
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 = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
break;
case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
@ -2289,6 +2336,7 @@ static int frontend_init(struct av7110 *av7110)
av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
av7110->fe->ops->set_tone = av7110_set_tone;
av7110->recover = dvb_s_recover;
}
break;
@ -2314,8 +2362,11 @@ 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);
if (av7110->fe)
if (av7110->fe) {
av7110->fe->ops->set_voltage = lnbp21_set_voltage;
av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
av7110->recover = dvb_s_recover;
}
break;
}
}

View file

@ -98,7 +98,8 @@ struct av7110 {
int adac_type; /* audio DAC type */
#define DVB_ADAC_TI 0
#define DVB_ADAC_CRYSTAL 1
#define DVB_ADAC_MSP 2
#define DVB_ADAC_MSP34x0 2
#define DVB_ADAC_MSP34x5 3
#define DVB_ADAC_NONE -1
@ -228,6 +229,9 @@ struct av7110 {
struct dvb_video_events video_events;
video_size_t video_size;
u16 wssMode;
u16 wssData;
u32 ir_config;
u32 ir_command;
void (*ir_handler)(struct av7110 *av7110, u32 ircom);
@ -245,6 +249,15 @@ struct av7110 {
struct dvb_frontend* fe;
fe_status_t fe_status;
/* crash recovery */
void (*recover)(struct av7110* av7110);
struct dvb_frontend_parameters saved_fe_params;
fe_sec_voltage_t saved_voltage;
fe_sec_tone_mode_t saved_tone;
struct dvb_diseqc_master_cmd saved_master_cmd;
fe_sec_mini_cmd_t saved_minicmd;
int (*fe_init)(struct dvb_frontend* fe);
int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status);
int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe);
@ -252,7 +265,7 @@ struct av7110 {
int (*fe_diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
int (*fe_set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
};

View file

@ -309,7 +309,7 @@ int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
i2c_writereg(av7110, 0x20, 0x04, volright);
return 0;
case DVB_ADAC_MSP:
case DVB_ADAC_MSP34x0:
vol = (volleft > volright) ? volleft : volright;
val = (vol * 0x73 / 255) << 8;
if (vol > 0)
@ -1256,7 +1256,9 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
break;
case AUDIO_SET_BYPASS_MODE:
ret = -EINVAL;
if (FW_VERSION(av7110->arm_app) < 0x2621)
ret = -EINVAL;
av7110->audiostate.bypass_mode = (int)arg;
break;
case AUDIO_CHANNEL_SELECT:
@ -1295,7 +1297,11 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
break;
case AUDIO_GET_CAPABILITIES:
*(int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
if (FW_VERSION(av7110->arm_app) < 0x2621)
*(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
else
*(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_DTS | AUDIO_CAP_AC3 |
AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
break;
case AUDIO_CLEAR_BUFFER:

View file

@ -230,6 +230,8 @@ int av7110_bootarm(struct av7110 *av7110)
dprintk(4, "%p\n", av7110);
av7110->arm_ready = 0;
saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
/* Disable DEBI and GPIO irq */
@ -361,6 +363,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
break;
if (err) {
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
av7110->arm_errors++;
return -ETIMEDOUT;
}
msleep(1);
@ -1206,9 +1209,9 @@ int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
switch (cap->cmd) {
case OSD_CAP_MEMSIZE:
if (FW_4M_SDRAM(av7110->arm_app))
cap->val = 1000000;
cap->val = 1000000;
else
cap->val = 92000;
cap->val = 92000;
return 0;
default:
return -EINVAL;

View file

@ -167,7 +167,8 @@ enum av7110_encoder_command {
LoadVidCode,
SetMonitorType,
SetPanScanType,
SetFreezeMode
SetFreezeMode,
SetWSSConfig
};
enum av7110_rec_play_state {

View file

@ -17,6 +17,8 @@ static int av_cnt;
static struct av7110 *av_list[4];
static struct input_dev *input_dev;
static u8 delay_timer_finished;
static u16 key_map [256] = {
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
KEY_8, KEY_9, KEY_BACK, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO,
@ -112,13 +114,16 @@ static void av7110_emit_key(unsigned long parm)
if (timer_pending(&keyup_timer)) {
del_timer(&keyup_timer);
if (keyup_timer.data != keycode || new_toggle != old_toggle) {
delay_timer_finished = 0;
input_event(input_dev, EV_KEY, keyup_timer.data, !!0);
input_event(input_dev, EV_KEY, keycode, !0);
} else
input_event(input_dev, EV_KEY, keycode, 2);
} else
if (delay_timer_finished)
input_event(input_dev, EV_KEY, keycode, 2);
} else {
delay_timer_finished = 0;
input_event(input_dev, EV_KEY, keycode, !0);
}
keyup_timer.expires = jiffies + UP_TIMEOUT;
keyup_timer.data = keycode;
@ -145,7 +150,8 @@ static void input_register_keys(void)
static void input_repeat_key(unsigned long data)
{
/* dummy routine to disable autorepeat in the input driver */
/* called by the input driver after rep[REP_DELAY] ms */
delay_timer_finished = 1;
}

View file

@ -490,6 +490,58 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
break;
}
case VIDIOC_G_SLICED_VBI_CAP:
{
struct v4l2_sliced_vbi_cap *cap = arg;
dprintk(2, "VIDIOC_G_SLICED_VBI_CAP\n");
memset(cap, 0, sizeof *cap);
if (FW_VERSION(av7110->arm_app) >= 0x2623) {
cap->service_set = V4L2_SLICED_WSS_625;
cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
}
break;
}
case VIDIOC_G_FMT:
{
struct v4l2_format *f = arg;
dprintk(2, "VIDIOC_G_FMT:\n");
if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
FW_VERSION(av7110->arm_app) < 0x2623)
return -EAGAIN; /* handled by core driver */
memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
if (av7110->wssMode) {
f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
}
break;
}
case VIDIOC_S_FMT:
{
struct v4l2_format *f = arg;
dprintk(2, "VIDIOC_S_FMT\n");
if (f->type != V4L2_BUF_TYPE_SLICED_VBI_OUTPUT ||
FW_VERSION(av7110->arm_app) < 0x2623)
return -EAGAIN; /* handled by core driver */
if (f->fmt.sliced.service_set != V4L2_SLICED_WSS_625 &&
f->fmt.sliced.service_lines[0][23] != V4L2_SLICED_WSS_625) {
memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
/* WSS controlled by firmware */
av7110->wssMode = 0;
av7110->wssData = 0;
return av7110_fw_cmd(av7110, COMTYPE_ENCODER,
SetWSSConfig, 1, 0);
} else {
memset(&f->fmt.sliced, 0, sizeof f->fmt.sliced);
f->fmt.sliced.service_set = V4L2_SLICED_WSS_625;
f->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
f->fmt.sliced.io_size = sizeof (struct v4l2_sliced_vbi_data);
/* WSS controlled by userspace */
av7110->wssMode = 1;
av7110->wssData = 0;
}
break;
}
default:
printk("no such ioctl\n");
return -ENOIOCTLCMD;
@ -497,6 +549,46 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
return 0;
}
static int av7110_vbi_reset(struct inode *inode, struct file *file)
{
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
dprintk(2, "%s\n", __FUNCTION__);
av7110->wssMode = 0;
av7110->wssData = 0;
if (FW_VERSION(av7110->arm_app) < 0x2623)
return 0;
else
return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
}
static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
{
struct saa7146_fh *fh = file->private_data;
struct saa7146_dev *dev = fh->dev;
struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
struct v4l2_sliced_vbi_data d;
int rc;
dprintk(2, "%s\n", __FUNCTION__);
if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
return -EINVAL;
if (copy_from_user(&d, data, count))
return -EFAULT;
if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)
return -EINVAL;
if (d.id) {
av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];
rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig,
2, 1, av7110->wssData);
} else {
av7110->wssData = 0;
rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
}
return (rc < 0) ? rc : count;
}
/****************************************************************************
* INITIALIZATION
@ -512,6 +604,9 @@ static struct saa7146_extension_ioctls ioctls[] = {
{ VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
{ VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
{ VIDIOC_S_AUDIO, SAA7146_EXCLUSIVE },
{ VIDIOC_G_SLICED_VBI_CAP, SAA7146_EXCLUSIVE },
{ VIDIOC_G_FMT, SAA7146_BEFORE },
{ VIDIOC_S_FMT, SAA7146_BEFORE },
{ 0, 0 }
};
@ -587,7 +682,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_MSP;
av7110->adac_type = DVB_ADAC_MSP34x0;
msleep(100); // the probing above resets the msp...
msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
@ -692,12 +787,11 @@ int av7110_init_v4l(struct av7110 *av7110)
saa7146_vv_release(dev);
return -ENODEV;
}
if (av7110->analog_tuner_flags) {
if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
ERR(("cannot register vbi v4l2 device. skipping.\n"));
} else {
if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
ERR(("cannot register vbi v4l2 device. skipping.\n"));
} else {
if (av7110->analog_tuner_flags)
av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
}
}
return 0;
}
@ -778,7 +872,7 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
static struct saa7146_ext_vv av7110_vv_data_st = {
.inputs = 1,
.audios = 1,
.capabilities = 0,
.capabilities = V4L2_CAP_SLICED_VBI_OUTPUT,
.flags = 0,
.stds = &standard[0],
@ -787,12 +881,16 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
.ioctls = &ioctls[0],
.ioctl = av7110_ioctl,
.vbi_fops.open = av7110_vbi_reset,
.vbi_fops.release = av7110_vbi_reset,
.vbi_fops.write = av7110_vbi_write,
};
static struct saa7146_ext_vv av7110_vv_data_c = {
.inputs = 1,
.audios = 1,
.capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE,
.capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT,
.flags = SAA7146_USE_PORT_B_FOR_VBI,
.stds = &standard[0],
@ -801,5 +899,9 @@ static struct saa7146_ext_vv av7110_vv_data_c = {
.ioctls = &ioctls[0],
.ioctl = av7110_ioctl,
.vbi_fops.open = av7110_vbi_reset,
.vbi_fops.release = av7110_vbi_reset,
.vbi_fops.write = av7110_vbi_write,
};

View file

@ -127,7 +127,7 @@ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int ad
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
udelay(1);
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 0);
result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
@ -145,7 +145,7 @@ static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int a
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
udelay(1);
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 0);
result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
if (result == -ETIMEDOUT)
budget_av->slot_status = 0;
@ -192,7 +192,7 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
int timeout = 500; // 5 seconds (4.4.6 Ready)
int timeout = 50; // 5 seconds (4.4.6 Ready)
if (slot != 0)
return -EINVAL;
@ -256,19 +256,37 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
int cam_present = 0;
if (slot != 0)
return -EINVAL;
if (!budget_av->slot_status) {
if (!budget_av->slot_status)
{
// first of all test the card detect line
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
udelay(1);
if (saa7146_read(saa, PSR) & MASK_06)
{
cam_present = 1;
}
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
// that is unreliable however, so try and read from IO memory
if (!cam_present)
{
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT)
{
cam_present = 1;
}
}
// did we find something?
if (cam_present) {
printk(KERN_INFO "budget-av: cam inserted\n");
budget_av->slot_status = 1;
}
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
} else if (!open) {
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
@ -484,6 +502,140 @@ static int philips_su1278_ty_ci_pll_set(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_pll_set(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
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;
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 */
msg.buf = reg0;
msg.len = sizeof(reg0);
if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
stv0299_enable_plli2c(fe);
msg.buf = reg1;
msg.len = sizeof(reg1);
if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
stv0299_enable_plli2c(fe);
msg.buf = reg2;
msg.len = sizeof(reg2);
if (i2c_transfer(i2c, &msg, 1) != 1)
return -EIO;
return 0;
}
static u8 typhoon_cinergy1200s_inittab[] = {
0x01, 0x15,
0x02, 0x30,
@ -553,6 +705,18 @@ static struct stv0299_config cinergy_1200s_config = {
.pll_set = philips_su1278_ty_ci_pll_set,
};
static struct stv0299_config cinergy_1200s_1894_0010_config = {
.demod_address = 0x68,
.inittab = typhoon_cinergy1200s_inittab,
.mclk = 88000000UL,
.invert = 1,
.skip_reinit = 0,
.lock_output = STV0229_LOCKOUTPUT_1,
.volt13_op0_op1 = STV0299_VOLT13_OP0,
.min_delay_ms = 100,
.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
.pll_set = philips_su1278sh2_tua6100_pll_set,
};
static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
{
@ -749,6 +913,15 @@ static void frontend_init(struct budget_av *budget_av)
switch (saa->pci->subsystem_device) {
case SUBID_DVBS_KNC1:
if (saa->pci->subsystem_vendor == 0x1894) {
fe = stv0299_attach(&cinergy_1200s_1894_0010_config,
&budget_av->budget.i2c_adap);
} else {
fe = stv0299_attach(&typhoon_config,
&budget_av->budget.i2c_adap);
}
break;
case SUBID_DVBS_KNC1_PLUS:
case SUBID_DVBS_TYPHOON:
fe = stv0299_attach(&typhoon_config,
@ -1003,6 +1176,7 @@ MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),

View file

@ -404,9 +404,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
tasklet_init(&budget->vpe_tasklet, vpeirq, (unsigned long) budget);
/* frontend power on */
if (bi->type == BUDGET_FS_ACTIVY)
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
else
if (bi->type != BUDGET_FS_ACTIVY)
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
if (budget_register(budget) == 0) {

View file

@ -112,6 +112,7 @@ static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long
* Routines for the Fujitsu Siemens Activy budget card
* 22 kHz tone and DiSEqC are handled by the frontend.
* Voltage must be set here.
* GPIO 1: LNBP EN, GPIO 2: LNBP VSEL
*/
static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
{
@ -121,11 +122,16 @@ static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
switch (voltage) {
case SEC_VOLTAGE_13:
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
break;
case SEC_VOLTAGE_18:
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
break;
case SEC_VOLTAGE_OFF:
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO);
break;
default:
return -EINVAL;
}
@ -206,7 +212,7 @@ static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
return 0;
}
static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, int arg)
static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend* fe, long arg)
{
struct budget* budget = (struct budget*) fe->dvb->priv;
u8 buf;
@ -580,6 +586,7 @@ static void frontend_init(struct budget *budget)
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
budget->dvb_frontend->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
if (lnbp21_init(budget)) {
printk("%s: No LNBP21 found!\n", __FUNCTION__);
goto error_out;
@ -624,7 +631,7 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
break;
budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
}
break;
@ -632,7 +639,7 @@ static void frontend_init(struct budget *budget)
budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
if (budget->dvb_frontend) {
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
break;
budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
}
break;

View file

@ -13,7 +13,7 @@
Holger Waechtler Convergence
Copyright (C) 2002-2003 Ralph Metzler <rjkm@metzlerbros.de>
Metzler Brothers Systementwicklung GbR
Metzler Brothers Systementwicklung GbR
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

View file

@ -10,7 +10,7 @@ config DVB_TTUSB_BUDGET
Support for external USB adapters designed by Technotrend and
produced by Hauppauge, shipped under the brand name 'Nova-USB'.
These devices don't have a MPEG decoder built in, so you need
These devices don't have a MPEG decoder built in, so you need
an external software decoder to watch TV.
Say Y if you own such a device and want to use it.

View file

@ -8,14 +8,15 @@ config DVB_TTUSB_DEC
produced by Hauppauge, shipped under the brand name 'DEC2000-t'
and 'DEC3000-s'.
Even if these devices have a MPEG decoder built in, they transmit
Even if these devices have a MPEG decoder built in, they transmit
only compressed MPEG data over the USB bus, so you need
an external software decoder to watch TV on your computer.
This driver needs external firmware. Please use the commands
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
download/extract them, and then copy them to /usr/lib/hotplug/firmware.
This driver needs external firmware. Please use the commands
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
download/extract them, and then copy them to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
Say Y if you own such a device and want to use it.

View file

@ -369,7 +369,7 @@ static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
{
struct ttusb_dec *dec = (struct ttusb_dec *)priv;
struct ttusb_dec *dec = priv;
dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
&dec->audio_filter->feed->feed.ts,
@ -380,7 +380,7 @@ static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
{
struct ttusb_dec *dec = (struct ttusb_dec *)priv;
struct ttusb_dec *dec = priv;
dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
&dec->video_filter->feed->feed.ts,
@ -965,8 +965,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
case DMX_TS_PES_TELETEXT:
dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid;
dprintk(" pes_type: DMX_TS_PES_TELETEXT\n");
break;
dprintk(" pes_type: DMX_TS_PES_TELETEXT(not supported)\n");
return -ENOSYS;
case DMX_TS_PES_PCR:
dprintk(" pes_type: DMX_TS_PES_PCR\n");
@ -975,8 +975,8 @@ static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
break;
case DMX_TS_PES_OTHER:
dprintk(" pes_type: DMX_TS_PES_OTHER\n");
break;
dprintk(" pes_type: DMX_TS_PES_OTHER(not supported)\n");
return -ENOSYS;
default:
dprintk(" pes_type: unknown (%d)\n", dvbdmxfeed->pes_type);
@ -1182,7 +1182,7 @@ static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
(unsigned long)dec);
}
static int ttusb_init_rc(struct ttusb_dec *dec)
static int ttusb_init_rc( struct ttusb_dec *dec)
{
struct input_dev *input_dev;
u8 b[] = { 0x00, 0x01 };
@ -1203,13 +1203,12 @@ static int ttusb_init_rc(struct ttusb_dec *dec)
input_dev->keycode = rc_keys;
for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
set_bit(rc_keys[i], input_dev->keybit);
set_bit(rc_keys[i], input_dev->keybit);
input_register_device(input_dev);
if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
printk("%s: usb_submit_urb failed\n",__FUNCTION__);
/* enable irq pipe */
ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
@ -1395,6 +1394,7 @@ static int ttusb_dec_init_stb(struct ttusb_dec *dec)
/* We can't trust the USB IDs that some firmwares
give the box */
switch (model) {
case 0x00070001:
case 0x00070008:
case 0x0007000c:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
@ -1588,7 +1588,7 @@ static int fe_send_command(struct dvb_frontend* fe, const u8 command,
int param_length, const u8 params[],
int *result_length, u8 cmd_result[])
{
struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv;
struct ttusb_dec* dec = fe->dvb->priv;
return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result);
}

View file

@ -42,8 +42,39 @@ struct ttusbdecfe_state {
static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
struct ttusbdecfe_state* state = fe->demodulator_priv;
u8 b[] = { 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
u8 result[4];
int len, ret;
*status=0;
ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result);
if(ret)
return ret;
if(len != 4) {
printk(KERN_ERR "%s: unexpected reply\n", __FUNCTION__);
return -EIO;
}
switch(result[3]) {
case 1: /* not tuned yet */
case 2: /* no signal/no lock*/
break;
case 3: /* signal found and locked*/
*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
break;
case 4:
*status = FE_TIMEDOUT;
break;
default:
pr_info("%s: returned unknown value: %d\n",
__FUNCTION__, result[3]);
return -EIO;
}
return 0;
}
@ -64,6 +95,16 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_fron
return 0;
}
static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
struct dvb_frontend_tune_settings* fesettings)
{
fesettings->min_delay_ms = 1500;
/* Drift compensation makes no sense for DVB-T */
fesettings->step_size = 0;
fesettings->max_drift = 0;
return 0;
}
static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
@ -212,6 +253,8 @@ static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
.set_frontend = ttusbdecfe_dvbt_set_frontend,
.get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
.read_status = ttusbdecfe_read_status,
};
@ -223,11 +266,11 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
.frequency_min = 950000,
.frequency_max = 2150000,
.frequency_stepsize = 125,
.symbol_rate_min = 1000000, /* guessed */
.symbol_rate_max = 45000000, /* guessed */
.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO,
FE_CAN_QPSK
},
.release = ttusbdecfe_release,

View file

@ -220,6 +220,7 @@ static struct file_operations pcm20_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = pcm20_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -299,6 +299,7 @@ static struct file_operations rtrack_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = rt_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -256,6 +256,7 @@ static struct file_operations aztech_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = az_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -490,6 +490,7 @@ static struct file_operations cadet_fops = {
.release = cadet_release,
.read = cadet_read,
.ioctl = cadet_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -301,6 +301,7 @@ static struct file_operations gemtek_pci_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = gemtek_pci_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -233,6 +233,7 @@ static struct file_operations gemtek_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = gemtek_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -72,6 +72,7 @@ static struct file_operations maestro_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = radio_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -80,6 +80,7 @@ static struct file_operations maxiradio_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = radio_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};
static struct video_device maxiradio_radio =

View file

@ -199,6 +199,7 @@ static struct file_operations rtrack2_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = rt_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -225,6 +225,7 @@ static struct file_operations fmi_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = fmi_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -356,6 +356,7 @@ static struct file_operations fmr2_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = fmr2_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -276,6 +276,7 @@ static struct file_operations terratec_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = tt_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -255,6 +255,7 @@ static struct file_operations trust_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = tr_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -261,6 +261,7 @@ static struct file_operations typhoon_fops = {
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = typhoon_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -313,6 +313,7 @@ static struct file_operations zoltrix_fops =
.open = video_exclusive_open,
.release = video_exclusive_release,
.ioctl = zol_ioctl,
.compat_ioctl = v4l_compat_ioctl32,
.llseek = no_llseek,
};

View file

@ -7,6 +7,15 @@ menu "Video For Linux"
comment "Video Adapters"
config VIDEO_ADV_DEBUG
bool "Enable advanced debug functionality"
depends on VIDEO_DEV
default n
---help---
Say Y here to enable advanced debugging functionality on some
V4L devices.
In doubt, say N.
config VIDEO_BT848
tristate "BT848 Video For Linux"
depends on VIDEO_DEV && PCI && I2C
@ -342,6 +351,6 @@ config VIDEO_DECODER
depends on VIDEO_DEV && I2C && EXPERIMENTAL
---help---
Say Y here to compile drivers for SAA7115, SAA7127 and CX25840
video decoders.
video decoders.
endmenu

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