mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-12 13:34:10 +08:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
This commit is contained in:
commit
f17578decc
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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).
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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(¤t->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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 },
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 },
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 *);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 },
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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 },
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
889
drivers/media/dvb/frontends/cx24123.c
Normal file
889
drivers/media/dvb/frontends/cx24123.c
Normal 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);
|
51
drivers/media/dvb/frontends/cx24123.h
Normal file
51
drivers/media/dvb/frontends/cx24123.h
Normal 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 */
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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 $@
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -167,7 +167,8 @@ enum av7110_encoder_command {
|
||||
LoadVidCode,
|
||||
SetMonitorType,
|
||||
SetPanScanType,
|
||||
SetFreezeMode
|
||||
SetFreezeMode,
|
||||
SetWSSConfig
|
||||
};
|
||||
|
||||
enum av7110_rec_play_state {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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 =
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user