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.
|
The frontend module sp887x.o, requires an external firmware.
|
||||||
Please use the command "get_dvb_firmware sp887x" to download
|
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
|
Receiving DVB-T in Australia
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ use IO::Handle;
|
|||||||
|
|
||||||
@components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t",
|
@components = ( "sp8870", "sp887x", "tda10045", "tda10046", "av7110", "dec2000t",
|
||||||
"dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
|
"dec2540t", "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
|
||||||
"or51211", "or51132_qam", "or51132_vsb");
|
"or51211", "or51132_qam", "or51132_vsb", "bluebird");
|
||||||
|
|
||||||
# Check args
|
# Check args
|
||||||
syntax() if (scalar(@ARGV) != 1);
|
syntax() if (scalar(@ARGV) != 1);
|
||||||
@ -34,7 +34,11 @@ for ($i=0; $i < scalar(@components); $i++) {
|
|||||||
if ($cid eq $components[$i]) {
|
if ($cid eq $components[$i]) {
|
||||||
$outfile = eval($cid);
|
$outfile = eval($cid);
|
||||||
die $@ if $@;
|
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);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,6 +312,19 @@ sub or51132_vsb {
|
|||||||
$fwfile;
|
$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
|
# 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
|
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.
|
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]
|
140 -> Osprey 440 [0070:ff07]
|
||||||
141 -> Asound Skyeye PCTV
|
141 -> Asound Skyeye PCTV
|
||||||
142 -> Sabrent TV-FM (bttv version)
|
142 -> Sabrent TV-FM (bttv version)
|
||||||
|
143 -> Hauppauge ImpactVCB (bt878) [0070:13eb]
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
15 -> DViCO FusionHDTV DVB-T1 [18ac:db00]
|
15 -> DViCO FusionHDTV DVB-T1 [18ac:db00]
|
||||||
16 -> KWorld LTV883RF
|
16 -> KWorld LTV883RF
|
||||||
17 -> DViCO FusionHDTV 3 Gold-Q [18ac:d810]
|
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]
|
19 -> Conexant DVB-T reference design [14f1:0187]
|
||||||
20 -> Provideo PV259 [1540:2580]
|
20 -> Provideo PV259 [1540:2580]
|
||||||
21 -> DViCO FusionHDTV DVB-T Plus [18ac:db10]
|
21 -> DViCO FusionHDTV DVB-T Plus [18ac:db10]
|
||||||
@ -35,3 +35,11 @@
|
|||||||
34 -> ATI HDTV Wonder [1002:a101]
|
34 -> ATI HDTV Wonder [1002:a101]
|
||||||
35 -> WinFast DTV1000-T [107d:665f]
|
35 -> WinFast DTV1000-T [107d:665f]
|
||||||
36 -> AVerTV 303 (M126) [1461:000a]
|
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]
|
55 -> LifeView FlyDVB-T DUO [5168:0502,5168:0306]
|
||||||
56 -> Avermedia AVerTV 307 [1461:a70a]
|
56 -> Avermedia AVerTV 307 [1461:a70a]
|
||||||
57 -> Avermedia AVerTV GO 007 FM [1461:f31f]
|
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
|
59 -> Kworld/Tevion V-Stream Xpert TV PVR7134
|
||||||
60 -> Typhoon DVB-T Duo Digital/Analog Cardbus [4e42:0502]
|
60 -> Typhoon DVB-T Duo Digital/Analog Cardbus [4e42:0502]
|
||||||
61 -> Philips TOUGH DVB-T reference design [1131:2004]
|
61 -> Philips TOUGH DVB-T reference design [1131:2004]
|
||||||
@ -81,4 +81,5 @@
|
|||||||
80 -> ASUS Digimatrix TV [1043:0210]
|
80 -> ASUS Digimatrix TV [1043:0210]
|
||||||
81 -> Philips Tiger reference design [1131:2018]
|
81 -> Philips Tiger reference design [1131:2018]
|
||||||
82 -> MSI TV@Anywhere plus [1462:6231]
|
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=39 - LG NTSC (newer TAPC series)
|
||||||
tuner=40 - HITACHI V7-J180AT
|
tuner=40 - HITACHI V7-J180AT
|
||||||
tuner=41 - Philips PAL_MK (FI1216 MK)
|
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=43 - Philips NTSC MK3 (FM1236MK3 or FM1236/F)
|
||||||
tuner=44 - Philips 4 in 1 (ATI TV Wonder Pro/Conexant)
|
tuner=44 - Philips 4 in 1 (ATI TV Wonder Pro/Conexant)
|
||||||
tuner=45 - Microtune 4049 FM5
|
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=49 - Microtune 4042 FI5 ATSC/NTSC dual in
|
||||||
tuner=50 - TCL 2002N
|
tuner=50 - TCL 2002N
|
||||||
tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3)
|
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=53 - Philips FQ1286
|
||||||
tuner=54 - tda8290+75
|
tuner=54 - tda8290+75
|
||||||
tuner=55 - TCL 2002MB
|
tuner=55 - TCL 2002MB
|
||||||
@ -58,7 +58,7 @@ tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4)
|
|||||||
tuner=57 - Philips FQ1236A MK4
|
tuner=57 - Philips FQ1236A MK4
|
||||||
tuner=58 - Ymec TVision TVF-8531MF/8831MF/8731MF
|
tuner=58 - Ymec TVision TVF-8531MF/8831MF/8731MF
|
||||||
tuner=59 - Ymec TVision TVF-5533MF
|
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=61 - Tena TNF9533-D/IF/TNF9533-B/DF
|
||||||
tuner=62 - Philips TEA5767HN FM Radio
|
tuner=62 - Philips TEA5767HN FM Radio
|
||||||
tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
|
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) {
|
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
|
||||||
DEB_S(("initializing vbi...\n"));
|
DEB_S(("initializing vbi...\n"));
|
||||||
|
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
|
||||||
result = saa7146_vbi_uops.open(dev,file);
|
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 {
|
} else {
|
||||||
DEB_S(("initializing video...\n"));
|
DEB_S(("initializing video...\n"));
|
||||||
result = saa7146_video_uops.open(dev,file);
|
result = saa7146_video_uops.open(dev,file);
|
||||||
@ -289,7 +292,10 @@ static int fops_release(struct inode *inode, struct file *file)
|
|||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
|
if( fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
|
||||||
|
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
|
||||||
saa7146_vbi_uops.release(dev,file);
|
saa7146_vbi_uops.release(dev,file);
|
||||||
|
if (dev->ext_vv_data->vbi_fops.release)
|
||||||
|
dev->ext_vv_data->vbi_fops.release(inode, file);
|
||||||
} else {
|
} else {
|
||||||
saa7146_video_uops.release(dev,file);
|
saa7146_video_uops.release(dev,file);
|
||||||
}
|
}
|
||||||
@ -332,6 +338,7 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
|
|||||||
BUG();
|
BUG();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return videobuf_mmap_mapper(q,vma);
|
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: {
|
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));
|
// DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count));
|
||||||
|
if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
|
||||||
return saa7146_vbi_uops.read(file,data,count,ppos);
|
return saa7146_vbi_uops.read(file,data,count,ppos);
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
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 =
|
static struct file_operations video_fops =
|
||||||
{
|
{
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.open = fops_open,
|
.open = fops_open,
|
||||||
.release = fops_release,
|
.release = fops_release,
|
||||||
.read = fops_read,
|
.read = fops_read,
|
||||||
|
.write = fops_write,
|
||||||
.poll = fops_poll,
|
.poll = fops_poll,
|
||||||
.mmap = fops_mmap,
|
.mmap = fops_mmap,
|
||||||
.ioctl = fops_ioctl,
|
.ioctl = fops_ioctl,
|
||||||
@ -467,6 +496,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
|
|||||||
memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
|
memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
|
||||||
|
|
||||||
saa7146_video_uops.init(dev,vv);
|
saa7146_video_uops.init(dev,vv);
|
||||||
|
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
|
||||||
saa7146_vbi_uops.init(dev,vv);
|
saa7146_vbi_uops.init(dev,vv);
|
||||||
|
|
||||||
dev->vv_data = vv;
|
dev->vv_data = vv;
|
||||||
|
@ -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_depth = vv->ov_fmt->depth;
|
||||||
int b_bpl = vv->ov_fb.fmt.bytesperline;
|
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;
|
struct saa7146_video_dma vdma1;
|
||||||
|
|
||||||
/* calculate memory offsets for picture, look if we shall top-down-flip */
|
/* calculate memory offsets for picture, look if we shall top-down-flip */
|
||||||
vdma1.pitch = 2*b_bpl;
|
vdma1.pitch = 2*b_bpl;
|
||||||
if ( 0 == vv->vflip ) {
|
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.base_odd = vdma1.base_even + (vdma1.pitch / 2);
|
||||||
vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
|
vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
|
||||||
}
|
}
|
||||||
else {
|
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.base_odd = vdma1.base_even - (vdma1.pitch / 2);
|
||||||
vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
|
vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
|
||||||
}
|
}
|
||||||
|
@ -1114,10 +1114,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case VIDIOC_OVERLAY:
|
case VIDIOC_OVERLAY:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
int on = *(int *)arg;
|
int on = *(int *)arg;
|
||||||
int err = 0;
|
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);
|
saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
||||||
{
|
{
|
||||||
struct file *file = q->priv_data;
|
struct file *file = q->priv_data;
|
||||||
|
@ -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 */
|
/* try to figure out the frontend, each card/box can have on of the following list */
|
||||||
int flexcop_frontend_init(struct flexcop_device *fc)
|
int flexcop_frontend_init(struct flexcop_device *fc)
|
||||||
{
|
{
|
||||||
|
struct dvb_frontend_ops *ops;
|
||||||
|
|
||||||
/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
|
/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
|
||||||
if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
|
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;
|
ops->set_voltage = flexcop_set_voltage;
|
||||||
fc->fe->ops->sleep = flexcop_sleep;
|
|
||||||
|
fc->fe_sleep = ops->sleep;
|
||||||
|
ops->sleep = flexcop_sleep;
|
||||||
|
|
||||||
fc->dev_type = FC_SKY;
|
fc->dev_type = FC_SKY;
|
||||||
info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
|
info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
|
||||||
@ -522,13 +526,15 @@ int flexcop_frontend_init(struct flexcop_device *fc)
|
|||||||
} else
|
} else
|
||||||
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
|
/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
|
||||||
if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
|
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;
|
ops = fc->fe->ops;
|
||||||
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;
|
|
||||||
|
|
||||||
fc->fe_sleep = fc->fe->ops->sleep;
|
ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
|
||||||
fc->fe->ops->sleep = flexcop_sleep;
|
ops->diseqc_send_burst = flexcop_diseqc_send_burst;
|
||||||
|
ops->set_tone = flexcop_set_tone;
|
||||||
|
ops->set_voltage = flexcop_set_voltage;
|
||||||
|
|
||||||
|
fc->fe_sleep = ops->sleep;
|
||||||
|
ops->sleep = flexcop_sleep;
|
||||||
|
|
||||||
fc->dev_type = FC_SKY_OLD;
|
fc->dev_type = FC_SKY_OLD;
|
||||||
info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
|
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 {
|
} else {
|
||||||
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
|
if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
|
||||||
err("frontend registration failed!");
|
err("frontend registration failed!");
|
||||||
if (fc->fe->ops->release != NULL)
|
ops = fc->fe->ops;
|
||||||
fc->fe->ops->release(fc->fe);
|
if (ops->release != NULL)
|
||||||
|
ops->release(fc->fe);
|
||||||
fc->fe = NULL;
|
fc->fe = NULL;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,13 @@ extern const char *flexcop_device_names[];
|
|||||||
/* FlexCop IBI Registers */
|
/* FlexCop IBI Registers */
|
||||||
#if defined(__LITTLE_ENDIAN)
|
#if defined(__LITTLE_ENDIAN)
|
||||||
#include "flexcop_ibi_value_le.h"
|
#include "flexcop_ibi_value_le.h"
|
||||||
#elif defined(__BIG_ENDIAN)
|
#else
|
||||||
|
#if defined(__BIG_ENDIAN)
|
||||||
#include "flexcop_ibi_value_be.h"
|
#include "flexcop_ibi_value_be.h"
|
||||||
#else
|
#else
|
||||||
#error no endian defined
|
#error no endian defined
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define fc_data_Tag_ID_DVB 0x3e
|
#define fc_data_Tag_ID_DVB 0x3e
|
||||||
#define fc_data_Tag_ID_ATSC 0x3f
|
#define fc_data_Tag_ID_ATSC 0x3f
|
||||||
|
@ -1341,10 +1341,15 @@ static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
|
|||||||
return 0;
|
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;
|
struct dst_state *state = fe->demodulator_priv;
|
||||||
|
|
||||||
|
if (p != NULL) {
|
||||||
dst_set_freq(state, p->frequency);
|
dst_set_freq(state, p->frequency);
|
||||||
dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
|
dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
|
||||||
|
|
||||||
@ -1364,7 +1369,12 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet
|
|||||||
dst_set_modulation(state, p->u.qam.modulation);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1445,7 +1455,7 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
|
|||||||
|
|
||||||
.release = dst_release,
|
.release = dst_release,
|
||||||
.init = dst_init,
|
.init = dst_init,
|
||||||
.set_frontend = dst_set_frontend,
|
.tune = dst_set_frontend,
|
||||||
.get_frontend = dst_get_frontend,
|
.get_frontend = dst_get_frontend,
|
||||||
.read_status = dst_read_status,
|
.read_status = dst_read_status,
|
||||||
.read_signal_strength = dst_read_signal_strength,
|
.read_signal_strength = dst_read_signal_strength,
|
||||||
@ -1469,7 +1479,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
|
|||||||
|
|
||||||
.release = dst_release,
|
.release = dst_release,
|
||||||
.init = dst_init,
|
.init = dst_init,
|
||||||
.set_frontend = dst_set_frontend,
|
.tune = dst_set_frontend,
|
||||||
.get_frontend = dst_get_frontend,
|
.get_frontend = dst_get_frontend,
|
||||||
.read_status = dst_read_status,
|
.read_status = dst_read_status,
|
||||||
.read_signal_strength = dst_read_signal_strength,
|
.read_signal_strength = dst_read_signal_strength,
|
||||||
@ -1496,7 +1506,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
|
|||||||
|
|
||||||
.release = dst_release,
|
.release = dst_release,
|
||||||
.init = dst_init,
|
.init = dst_init,
|
||||||
.set_frontend = dst_set_frontend,
|
.tune = dst_set_frontend,
|
||||||
.get_frontend = dst_get_frontend,
|
.get_frontend = dst_get_frontend,
|
||||||
.read_status = dst_read_status,
|
.read_status = dst_read_status,
|
||||||
.read_signal_strength = dst_read_signal_strength,
|
.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[4] = 0x03;
|
||||||
hw_buffer->msg[5] = length & 0xff;
|
hw_buffer->msg[5] = length & 0xff;
|
||||||
hw_buffer->msg[6] = 0x00;
|
hw_buffer->msg[6] = 0x00;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Need to compute length for EN50221 section 8.3.2, for the time being
|
* Need to compute length for EN50221 section 8.3.2, for the time being
|
||||||
* assuming 8.3.2 is not applicable
|
* assuming 8.3.2 is not applicable
|
||||||
*/
|
*/
|
||||||
memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
|
memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
|
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) {
|
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;
|
struct dst_state* state = NULL;
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
#ifdef BTTV_BOARD_DVICO_DVBT_LITE
|
|
||||||
case BTTV_BOARD_DVICO_DVBT_LITE:
|
case BTTV_BOARD_DVICO_DVBT_LITE:
|
||||||
card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
|
card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
|
||||||
if (card->fe != NULL) {
|
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;
|
card->fe->ops->info.frequency_max = 862000000;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE
|
|
||||||
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
|
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
|
||||||
lgdt330x_reset(card);
|
lgdt330x_reset(card);
|
||||||
card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
|
card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
|
||||||
if (card->fe != NULL)
|
if (card->fe != NULL)
|
||||||
dprintk ("dvb_bt8xx: lgdt330x detected\n");
|
dprintk ("dvb_bt8xx: lgdt330x detected\n");
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BTTV_BOARD_TWINHAN_VP3021
|
|
||||||
case BTTV_BOARD_TWINHAN_VP3021:
|
|
||||||
#else
|
|
||||||
case BTTV_BOARD_NEBULA_DIGITV:
|
case BTTV_BOARD_NEBULA_DIGITV:
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK);
|
* 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.
|
* 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;
|
card->irq_err_ignore = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef BTTV_BOARD_DVICO_DVBT_LITE
|
|
||||||
case BTTV_BOARD_DVICO_DVBT_LITE:
|
case BTTV_BOARD_DVICO_DVBT_LITE:
|
||||||
#endif
|
|
||||||
card->gpio_mode = 0x0400C060;
|
card->gpio_mode = 0x0400C060;
|
||||||
card->op_sync_orin = 0;
|
card->op_sync_orin = 0;
|
||||||
card->irq_err_ignore = 0;
|
card->irq_err_ignore = 0;
|
||||||
@ -823,19 +813,13 @@ static int dvb_bt8xx_probe(struct device *dev)
|
|||||||
* DA_APP(parallel) */
|
* DA_APP(parallel) */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE
|
|
||||||
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
|
case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
|
||||||
#endif
|
|
||||||
card->gpio_mode = 0x0400c060;
|
card->gpio_mode = 0x0400c060;
|
||||||
card->op_sync_orin = BT878_RISC_SYNC_MASK;
|
card->op_sync_orin = BT878_RISC_SYNC_MASK;
|
||||||
card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
|
card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef BTTV_BOARD_TWINHAN_VP3021
|
|
||||||
case BTTV_BOARD_TWINHAN_VP3021:
|
|
||||||
#else
|
|
||||||
case BTTV_BOARD_NEBULA_DIGITV:
|
case BTTV_BOARD_NEBULA_DIGITV:
|
||||||
#endif
|
|
||||||
case BTTV_BOARD_AVDVBT_761:
|
case BTTV_BOARD_AVDVBT_761:
|
||||||
card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
|
card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
|
||||||
card->op_sync_orin = 0;
|
card->op_sync_orin = 0;
|
||||||
|
@ -131,6 +131,8 @@ struct cinergyt2 {
|
|||||||
|
|
||||||
wait_queue_head_t poll_wq;
|
wait_queue_head_t poll_wq;
|
||||||
int pending_fe_events;
|
int pending_fe_events;
|
||||||
|
int disconnect_pending;
|
||||||
|
atomic_t inuse;
|
||||||
|
|
||||||
void *streambuf;
|
void *streambuf;
|
||||||
dma_addr_t streambuf_dmahandle;
|
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 dvb_demux *demux = dvbdmxfeed->demux;
|
||||||
struct cinergyt2 *cinergyt2 = demux->priv;
|
struct cinergyt2 *cinergyt2 = demux->priv;
|
||||||
|
|
||||||
if (down_interruptible(&cinergyt2->sem))
|
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
if (cinergyt2->streaming == 0)
|
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 dvb_demux *demux = dvbdmxfeed->demux;
|
||||||
struct cinergyt2 *cinergyt2 = demux->priv;
|
struct cinergyt2 *cinergyt2 = demux->priv;
|
||||||
|
|
||||||
if (down_interruptible(&cinergyt2->sem))
|
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
if (--cinergyt2->streaming == 0)
|
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 dvb_device *dvbdev = file->private_data;
|
||||||
struct cinergyt2 *cinergyt2 = dvbdev->priv;
|
struct cinergyt2 *cinergyt2 = dvbdev->priv;
|
||||||
int err;
|
int err = -ERESTARTSYS;
|
||||||
|
|
||||||
if ((err = dvb_generic_open(inode, file)))
|
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
|
||||||
return err;
|
|
||||||
|
|
||||||
if (down_interruptible(&cinergyt2->sem))
|
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
|
if ((err = dvb_generic_open(inode, file))) {
|
||||||
|
up(&cinergyt2->sem);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
|
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
|
||||||
cinergyt2_sleep(cinergyt2, 0);
|
cinergyt2_sleep(cinergyt2, 0);
|
||||||
schedule_delayed_work(&cinergyt2->query_work, HZ/2);
|
schedule_delayed_work(&cinergyt2->query_work, HZ/2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_inc(&cinergyt2->inuse);
|
||||||
|
|
||||||
up(&cinergyt2->sem);
|
up(&cinergyt2->sem);
|
||||||
return 0;
|
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)
|
static int cinergyt2_release (struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct dvb_device *dvbdev = file->private_data;
|
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))
|
if (down_interruptible(&cinergyt2->sem))
|
||||||
return -ERESTARTSYS;
|
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);
|
cancel_delayed_work(&cinergyt2->query_work);
|
||||||
flush_scheduled_work();
|
flush_scheduled_work();
|
||||||
cinergyt2_sleep(cinergyt2, 1);
|
cinergyt2_sleep(cinergyt2, 1);
|
||||||
@ -512,6 +528,11 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
|
|||||||
|
|
||||||
up(&cinergyt2->sem);
|
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);
|
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 dvb_device *dvbdev = file->private_data;
|
||||||
struct cinergyt2 *cinergyt2 = dvbdev->priv;
|
struct cinergyt2 *cinergyt2 = dvbdev->priv;
|
||||||
|
|
||||||
|
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
|
||||||
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
poll_wait(file, &cinergyt2->poll_wq, wait);
|
poll_wait(file, &cinergyt2->poll_wq, wait);
|
||||||
|
|
||||||
|
up(&cinergyt2->sem);
|
||||||
|
|
||||||
return (POLLIN | POLLRDNORM | POLLPRI);
|
return (POLLIN | POLLRDNORM | POLLPRI);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,10 +592,15 @@ static int cinergyt2_ioctl (struct inode *inode, struct file *file,
|
|||||||
(__u16 __user *) arg);
|
(__u16 __user *) arg);
|
||||||
|
|
||||||
case FE_READ_UNCORRECTED_BLOCKS:
|
case FE_READ_UNCORRECTED_BLOCKS:
|
||||||
/* UNC are already converted to host byte order... */
|
{
|
||||||
return put_user(stat->uncorrected_block_count,
|
uint32_t unc_count;
|
||||||
(__u32 __user *) arg);
|
|
||||||
|
|
||||||
|
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:
|
case FE_SET_FRONTEND:
|
||||||
{
|
{
|
||||||
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
|
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)))
|
if (copy_from_user(&p, (void __user*) arg, sizeof(p)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (down_interruptible(&cinergyt2->sem))
|
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
|
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];
|
struct cinergyt2_rc_event rc_events[12];
|
||||||
int n, len, i;
|
int n, len, i;
|
||||||
|
|
||||||
if (down_interruptible(&cinergyt2->sem))
|
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
|
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)
|
static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
|
||||||
{
|
{
|
||||||
cancel_delayed_work(&cinergyt2->rc_query_work);
|
cancel_delayed_work(&cinergyt2->rc_query_work);
|
||||||
flush_scheduled_work();
|
|
||||||
input_unregister_device(cinergyt2->rc_input_dev);
|
input_unregister_device(cinergyt2->rc_input_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -817,7 +849,7 @@ static void cinergyt2_query (void *data)
|
|||||||
uint8_t lock_bits;
|
uint8_t lock_bits;
|
||||||
uint32_t unc;
|
uint32_t unc;
|
||||||
|
|
||||||
if (down_interruptible(&cinergyt2->sem))
|
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unc = s->uncorrected_block_count;
|
unc = s->uncorrected_block_count;
|
||||||
@ -917,28 +949,25 @@ static void cinergyt2_disconnect (struct usb_interface *intf)
|
|||||||
{
|
{
|
||||||
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
|
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
|
||||||
|
|
||||||
if (down_interruptible(&cinergyt2->sem))
|
flush_scheduled_work();
|
||||||
return;
|
|
||||||
|
|
||||||
cinergyt2_unregister_rc(cinergyt2);
|
cinergyt2_unregister_rc(cinergyt2);
|
||||||
|
|
||||||
cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
|
cancel_delayed_work(&cinergyt2->query_work);
|
||||||
dvb_net_release(&cinergyt2->dvbnet);
|
wake_up_interruptible(&cinergyt2->poll_wq);
|
||||||
dvb_dmxdev_release(&cinergyt2->dmxdev);
|
|
||||||
dvb_dmx_release(&cinergyt2->demux);
|
|
||||||
dvb_unregister_device(cinergyt2->fedev);
|
|
||||||
dvb_unregister_adapter(&cinergyt2->adapter);
|
|
||||||
|
|
||||||
cinergyt2_free_stream_urbs(cinergyt2);
|
cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
|
||||||
up(&cinergyt2->sem);
|
cinergyt2->disconnect_pending = 1;
|
||||||
kfree(cinergyt2);
|
|
||||||
|
if (!atomic_read(&cinergyt2->inuse))
|
||||||
|
cinergyt2_unregister(cinergyt2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
|
static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
|
||||||
{
|
{
|
||||||
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
|
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
|
||||||
|
|
||||||
if (down_interruptible(&cinergyt2->sem))
|
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
if (state.event > PM_EVENT_ON) {
|
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 cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
|
||||||
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
|
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
|
||||||
|
|
||||||
if (down_interruptible(&cinergyt2->sem))
|
if (cinergyt2->disconnect_pending || down_interruptible(&cinergyt2->sem))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
if (!cinergyt2->sleeping) {
|
if (!cinergyt2->sleeping) {
|
||||||
@ -1014,4 +1043,3 @@ module_exit (cinergyt2_exit);
|
|||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_AUTHOR("Holger Waechtler, Daniel Mack");
|
MODULE_AUTHOR("Holger Waechtler, Daniel Mack");
|
||||||
|
|
||||||
|
@ -1745,10 +1745,8 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
|
|||||||
|
|
||||||
for (i = 0; i < ca->slot_count; i++) {
|
for (i = 0; i < ca->slot_count; i++) {
|
||||||
dvb_ca_en50221_slot_shutdown(ca, 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);
|
kfree(ca->slot_info);
|
||||||
dvb_unregister_device(ca->dvbdev);
|
dvb_unregister_device(ca->dvbdev);
|
||||||
kfree(ca);
|
kfree(ca);
|
||||||
|
@ -92,6 +92,7 @@ static DECLARE_MUTEX(frontend_mutex);
|
|||||||
|
|
||||||
struct dvb_frontend_private {
|
struct dvb_frontend_private {
|
||||||
|
|
||||||
|
/* thread/frontend values */
|
||||||
struct dvb_device *dvbdev;
|
struct dvb_device *dvbdev;
|
||||||
struct dvb_frontend_parameters parameters;
|
struct dvb_frontend_parameters parameters;
|
||||||
struct dvb_fe_events events;
|
struct dvb_fe_events events;
|
||||||
@ -100,20 +101,25 @@ struct dvb_frontend_private {
|
|||||||
wait_queue_head_t wait_queue;
|
wait_queue_head_t wait_queue;
|
||||||
pid_t thread_pid;
|
pid_t thread_pid;
|
||||||
unsigned long release_jiffies;
|
unsigned long release_jiffies;
|
||||||
int state;
|
unsigned int exit;
|
||||||
int bending;
|
unsigned int wakeup;
|
||||||
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;
|
|
||||||
fe_status_t status;
|
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);
|
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)
|
if (locked)
|
||||||
(*quality) = (*quality * 220 + 36*256) / 256;
|
(fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
|
||||||
else
|
else
|
||||||
(*quality) = (*quality * 220 + 0) / 256;
|
(fepriv->quality) = (fepriv->quality * 220 + 0) / 256;
|
||||||
|
|
||||||
q2 = *quality - 128;
|
q2 = fepriv->quality - 128;
|
||||||
q2 *= q2;
|
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
|
* @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.
|
* @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 autoinversion;
|
||||||
int ready = 0;
|
int ready = 0;
|
||||||
@ -321,6 +327,129 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
|
|||||||
return 0;
|
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)
|
static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
|
||||||
{
|
{
|
||||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||||
@ -355,18 +484,14 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
|
|||||||
wake_up_interruptible(&fepriv->wait_queue);
|
wake_up_interruptible(&fepriv->wait_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: use linux/kthread.h
|
|
||||||
*/
|
|
||||||
static int dvb_frontend_thread(void *data)
|
static int dvb_frontend_thread(void *data)
|
||||||
{
|
{
|
||||||
struct dvb_frontend *fe = data;
|
struct dvb_frontend *fe = data;
|
||||||
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
struct dvb_frontend_private *fepriv = fe->frontend_priv;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
char name [15];
|
char name [15];
|
||||||
int quality = 0, delay = 3*HZ;
|
|
||||||
fe_status_t s;
|
fe_status_t s;
|
||||||
int check_wrapped = 0;
|
struct dvb_frontend_parameters *params;
|
||||||
|
|
||||||
dprintk("%s\n", __FUNCTION__);
|
dprintk("%s\n", __FUNCTION__);
|
||||||
|
|
||||||
@ -377,6 +502,9 @@ static int dvb_frontend_thread(void *data)
|
|||||||
sigfillset(¤t->blocked);
|
sigfillset(¤t->blocked);
|
||||||
unlock_kernel();
|
unlock_kernel();
|
||||||
|
|
||||||
|
fepriv->check_wrapped = 0;
|
||||||
|
fepriv->quality = 0;
|
||||||
|
fepriv->delay = 3*HZ;
|
||||||
fepriv->status = 0;
|
fepriv->status = 0;
|
||||||
dvb_frontend_init(fe);
|
dvb_frontend_init(fe);
|
||||||
fepriv->wakeup = 0;
|
fepriv->wakeup = 0;
|
||||||
@ -386,7 +514,7 @@ static int dvb_frontend_thread(void *data)
|
|||||||
|
|
||||||
timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
|
timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
|
||||||
dvb_frontend_should_wakeup(fe),
|
dvb_frontend_should_wakeup(fe),
|
||||||
delay);
|
fepriv->delay);
|
||||||
if (0 != dvb_frontend_is_exiting(fe)) {
|
if (0 != dvb_frontend_is_exiting(fe)) {
|
||||||
/* got signal or quitting */
|
/* got signal or quitting */
|
||||||
break;
|
break;
|
||||||
@ -397,108 +525,22 @@ static int dvb_frontend_thread(void *data)
|
|||||||
if (down_interruptible(&fepriv->sem))
|
if (down_interruptible(&fepriv->sem))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* if we've got no parameters, just keep idling */
|
/* do an iteration of the tuning loop */
|
||||||
if (fepriv->state & FESTATE_IDLE) {
|
if (fe->ops->tune) {
|
||||||
delay = 3*HZ;
|
/* have we been asked to retune? */
|
||||||
quality = 0;
|
params = NULL;
|
||||||
continue;
|
if (fepriv->state & FESTATE_RETUNE) {
|
||||||
|
params = &fepriv->parameters;
|
||||||
|
fepriv->state = FESTATE_TUNED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the frontend status */
|
fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
|
||||||
if (fepriv->state & FESTATE_RETUNE) {
|
|
||||||
s = 0;
|
|
||||||
} else {
|
|
||||||
if (fe->ops->read_status)
|
|
||||||
fe->ops->read_status(fe, &s);
|
|
||||||
if (s != fepriv->status) {
|
if (s != fepriv->status) {
|
||||||
dvb_frontend_add_event(fe, s);
|
dvb_frontend_add_event(fe, s);
|
||||||
fepriv->status = s;
|
fepriv->status = s;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
/* if we're not tuned, and we have a lock, move to the TUNED state */
|
dvb_frontend_swzigzag(fe);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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);
|
err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
|
||||||
fepriv->state = FESTATE_DISEQC;
|
fepriv->state = FESTATE_DISEQC;
|
||||||
fepriv->status = 0;
|
fepriv->status = 0;
|
||||||
fepriv->tone = (fe_sec_tone_mode_t) parg;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -747,7 +788,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
|
|||||||
|
|
||||||
case FE_DISHNETWORK_SEND_LEGACY_CMD:
|
case FE_DISHNETWORK_SEND_LEGACY_CMD:
|
||||||
if (fe->ops->dishnetwork_send_legacy_command) {
|
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->state = FESTATE_DISEQC;
|
||||||
fepriv->status = 0;
|
fepriv->status = 0;
|
||||||
} else if (fe->ops->set_voltage) {
|
} 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
|
* initialization, so parg is 8 bits and does not
|
||||||
* include the initialization or start bit
|
* 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 nexttime;
|
||||||
struct timeval tv[10];
|
struct timeval tv[10];
|
||||||
int i;
|
int i;
|
||||||
u8 last = 1;
|
u8 last = 1;
|
||||||
if (dvb_frontend_debug)
|
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);
|
do_gettimeofday(&nexttime);
|
||||||
if (dvb_frontend_debug)
|
if (dvb_frontend_debug)
|
||||||
memcpy(&tv[0], &nexttime, sizeof(struct timeval));
|
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:
|
case FE_ENABLE_HIGH_LNB_VOLTAGE:
|
||||||
if (fe->ops->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;
|
break;
|
||||||
|
|
||||||
case FE_SET_FRONTEND: {
|
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);
|
err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FE_SET_FRONTEND_TUNE_MODE:
|
||||||
|
fepriv->tune_mode_flags = (unsigned long) parg;
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
up (&fepriv->sem);
|
up (&fepriv->sem);
|
||||||
@ -932,6 +977,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
|
|||||||
|
|
||||||
/* empty event queue */
|
/* empty event queue */
|
||||||
fepriv->events.eventr = fepriv->events.eventw = 0;
|
fepriv->events.eventr = fepriv->events.eventw = 0;
|
||||||
|
|
||||||
|
/* normal tune mode when opened R/W */
|
||||||
|
fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -990,7 +1038,6 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
|
|||||||
init_MUTEX (&fepriv->events.sem);
|
init_MUTEX (&fepriv->events.sem);
|
||||||
fe->dvb = dvb;
|
fe->dvb = dvb;
|
||||||
fepriv->inversion = INVERSION_OFF;
|
fepriv->inversion = INVERSION_OFF;
|
||||||
fepriv->tone = SEC_TONE_OFF;
|
|
||||||
|
|
||||||
printk ("DVB: registering frontend %i (%s)...\n",
|
printk ("DVB: registering frontend %i (%s)...\n",
|
||||||
fe->dvb->num,
|
fe->dvb->num,
|
||||||
|
@ -58,10 +58,19 @@ struct dvb_frontend_ops {
|
|||||||
int (*init)(struct dvb_frontend* fe);
|
int (*init)(struct dvb_frontend* fe);
|
||||||
int (*sleep)(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 (*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_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_status)(struct dvb_frontend* fe, fe_status_t* status);
|
||||||
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
|
int (*read_ber)(struct dvb_frontend* fe, u32* ber);
|
||||||
int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
|
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 (*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_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
|
||||||
int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
|
int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
|
||||||
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, int arg);
|
int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
|
||||||
int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
|
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
|
#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;
|
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 net_device *net = dvbnet->device[num];
|
||||||
struct dvb_net_priv *priv;
|
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))
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
if ((unsigned int) parg >= DVB_NET_DEVICES_MAX)
|
if ((unsigned long) parg >= DVB_NET_DEVICES_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
ret = dvb_net_remove_if(dvbnet, (unsigned int) parg);
|
ret = dvb_net_remove_if(dvbnet, (unsigned long) parg);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
module_put(dvbdev->adapter->module);
|
module_put(dvbdev->adapter->module);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -37,16 +37,16 @@ config DVB_USB_DIBUSB_MB
|
|||||||
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
|
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
|
||||||
|
|
||||||
Devices supported by this driver:
|
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
|
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
|
The VP7041 seems to be identical to "CTS Portable" (Chinese
|
||||||
Television System).
|
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
|
Say Y if you own such a device and want to use it. You should build it as
|
||||||
a module.
|
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
|
config DVB_USB_DIBUSB_MC
|
||||||
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
|
tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
|
||||||
depends on DVB_USB
|
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.
|
DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
|
||||||
|
|
||||||
Devices supported by this driver:
|
Devices supported by this driver:
|
||||||
DiBcom USB2.0 reference devices (non-public)
|
|
||||||
Artec T1 USB2.0 boxes
|
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
|
Say Y if you own such a device and want to use it. You should build it as
|
||||||
a module.
|
a module.
|
||||||
|
@ -11,10 +11,11 @@
|
|||||||
* design, so it can be reused for the "analogue-only" device (if it will
|
* design, so it can be reused for the "analogue-only" device (if it will
|
||||||
* appear at all).
|
* appear at all).
|
||||||
*
|
*
|
||||||
* TODO: check if the cx25840-driver (from ivtv) can be used for the analogue
|
* TODO: Use the cx25840-driver for the analogue part
|
||||||
* part
|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
|
* 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
|
* 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
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
@ -25,6 +26,9 @@
|
|||||||
#include "cxusb.h"
|
#include "cxusb.h"
|
||||||
|
|
||||||
#include "cx22702.h"
|
#include "cx22702.h"
|
||||||
|
#include "lgdt330x.h"
|
||||||
|
#include "mt352.h"
|
||||||
|
#include "mt352_priv.h"
|
||||||
|
|
||||||
/* debug */
|
/* debug */
|
||||||
int dvb_usb_cxusb_debug;
|
int dvb_usb_cxusb_debug;
|
||||||
@ -156,6 +160,99 @@ static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
|
|||||||
return 0;
|
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 = {
|
struct cx22702_config cxusb_cx22702_config = {
|
||||||
.demod_address = 0x63,
|
.demod_address = 0x63,
|
||||||
|
|
||||||
@ -165,8 +262,20 @@ struct cx22702_config cxusb_cx22702_config = {
|
|||||||
.pll_set = dvb_usb_pll_set_i2c,
|
.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 */
|
/* 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 };
|
u8 bpll[4] = { 0x0b, 0xdc, 0x9c, 0xa0 };
|
||||||
d->pll_addr = 0x61;
|
d->pll_addr = 0x61;
|
||||||
@ -175,7 +284,25 @@ static int cxusb_tuner_attach(struct dvb_usb_device *d)
|
|||||||
return 0;
|
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;
|
u8 b;
|
||||||
if (usb_set_interface(d->udev,0,6) < 0)
|
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;
|
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 */
|
/* 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,
|
static int cxusb_probe(struct usb_interface *intf,
|
||||||
const struct usb_device_id *id)
|
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 [] = {
|
static struct usb_device_id cxusb_table [] = {
|
||||||
{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
|
{ 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 */
|
{} /* Terminating entry */
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE (usb, cxusb_table);
|
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,
|
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||||
|
|
||||||
.usb_ctrl = CYPRESS_FX2,
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
@ -213,8 +402,8 @@ static struct dvb_usb_properties cxusb_properties = {
|
|||||||
|
|
||||||
.streaming_ctrl = cxusb_streaming_ctrl,
|
.streaming_ctrl = cxusb_streaming_ctrl,
|
||||||
.power_ctrl = cxusb_power_ctrl,
|
.power_ctrl = cxusb_power_ctrl,
|
||||||
.frontend_attach = cxusb_frontend_attach,
|
.frontend_attach = cxusb_cx22702_frontend_attach,
|
||||||
.tuner_attach = cxusb_tuner_attach,
|
.tuner_attach = cxusb_fmd1216me_tuner_attach,
|
||||||
|
|
||||||
.i2c_algo = &cxusb_i2c_algo,
|
.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 = {
|
static struct usb_driver cxusb_driver = {
|
||||||
.name = "dvb_usb_cxusb",
|
.name = "dvb_usb_cxusb",
|
||||||
.probe = cxusb_probe,
|
.probe = cxusb_probe,
|
||||||
|
@ -21,6 +21,8 @@ extern int dvb_usb_cxusb_debug;
|
|||||||
#define CMD_STREAMING_ON 0x36
|
#define CMD_STREAMING_ON 0x36
|
||||||
#define CMD_STREAMING_OFF 0x37
|
#define CMD_STREAMING_OFF 0x37
|
||||||
|
|
||||||
|
#define CMD_GET_IR_CODE 0x47
|
||||||
|
|
||||||
#define CMD_ANALOG 0x50
|
#define CMD_ANALOG 0x50
|
||||||
#define CMD_DIGITAL 0x51
|
#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);
|
d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
|
||||||
|
|
||||||
if (b2[0] == 0xfe) {
|
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);
|
dibusb_thomson_tuner_attach(d);
|
||||||
} else {
|
} else {
|
||||||
u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
|
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;
|
d->pll_addr = 0x60;
|
||||||
memcpy(d->pll_init,bpll,4);
|
memcpy(d->pll_init,bpll,4);
|
||||||
d->pll_desc = &dvb_pll_tda665x;
|
d->pll_desc = &dvb_pll_tda665x;
|
||||||
@ -133,11 +133,18 @@ static struct usb_device_id dibusb_dib3000mb_table [] = {
|
|||||||
/* 28 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_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) },
|
/* 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) },
|
/* 30 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
|
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,
|
.num_device_descs = 2,
|
||||||
#else
|
#else
|
||||||
.num_device_descs = 1,
|
.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[20], NULL },
|
||||||
{ &dibusb_dib3000mb_table[21], 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)",
|
{ "Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
|
||||||
{ &dibusb_dib3000mb_table[30], NULL },
|
{ &dibusb_dib3000mb_table[30], NULL },
|
||||||
{ NULL },
|
{ NULL },
|
||||||
},
|
},
|
||||||
|
{ NULL },
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -323,6 +331,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = {
|
|||||||
{ &dibusb_dib3000mb_table[27], NULL },
|
{ &dibusb_dib3000mb_table[27], NULL },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
},
|
},
|
||||||
|
{ NULL },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -369,6 +378,7 @@ static struct dvb_usb_properties artec_t1_usb2_properties = {
|
|||||||
{ &dibusb_dib3000mb_table[28], NULL },
|
{ &dibusb_dib3000mb_table[28], NULL },
|
||||||
{ &dibusb_dib3000mb_table[29], 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[1] = vv;
|
||||||
sndbuf[2] = wo ? wlen : rlen;
|
sndbuf[2] = wo ? wlen : rlen;
|
||||||
|
|
||||||
if (!wo) {
|
if (wo) {
|
||||||
memcpy(&sndbuf[3],wbuf,wlen);
|
memcpy(&sndbuf[3],wbuf,wlen);
|
||||||
dvb_usb_generic_write(d,sndbuf,7);
|
dvb_usb_generic_write(d,sndbuf,7);
|
||||||
} else {
|
} else {
|
||||||
|
@ -151,7 +151,7 @@ static struct dvb_usb_properties dtt200u_properties = {
|
|||||||
.cold_ids = { &dtt200u_usb_table[0], NULL },
|
.cold_ids = { &dtt200u_usb_table[0], NULL },
|
||||||
.warm_ids = { &dtt200u_usb_table[1], 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,
|
.pid_filter_count = 15,
|
||||||
|
|
||||||
.usb_ctrl = CYPRESS_FX2,
|
.usb_ctrl = CYPRESS_FX2,
|
||||||
.firmware = "dvb-usb-wt220u-01.fw",
|
.firmware = "dvb-usb-wt220u-02.fw",
|
||||||
|
|
||||||
.power_ctrl = dtt200u_power_ctrl,
|
.power_ctrl = dtt200u_power_ctrl,
|
||||||
.streaming_ctrl = dtt200u_streaming_ctrl,
|
.streaming_ctrl = dtt200u_streaming_ctrl,
|
||||||
@ -192,7 +192,7 @@ static struct dvb_usb_properties wt220u_properties = {
|
|||||||
.cold_ids = { &dtt200u_usb_table[2], NULL },
|
.cold_ids = { &dtt200u_usb_table[2], NULL },
|
||||||
.warm_ids = { &dtt200u_usb_table[3], NULL },
|
.warm_ids = { &dtt200u_usb_table[3], NULL },
|
||||||
},
|
},
|
||||||
{ NULL },
|
{ 0 },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#define _DVB_USB_DTT200U_H_
|
#define _DVB_USB_DTT200U_H_
|
||||||
|
|
||||||
#define DVB_USB_LOG_PREFIX "dtt200u"
|
#define DVB_USB_LOG_PREFIX "dtt200u"
|
||||||
|
|
||||||
#include "dvb-usb.h"
|
#include "dvb-usb.h"
|
||||||
|
|
||||||
extern int dvb_usb_dtt200u_debug;
|
extern int dvb_usb_dtt200u_debug;
|
||||||
|
@ -24,7 +24,7 @@ extern int dvb_usb_disable_rc_polling;
|
|||||||
#define deb_mem(args...) dprintk(dvb_usb_debug,0x80,args)
|
#define deb_mem(args...) dprintk(dvb_usb_debug,0x80,args)
|
||||||
|
|
||||||
/* commonly used methods */
|
/* 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_submit(struct dvb_usb_device *);
|
||||||
extern int dvb_usb_urb_kill(struct dvb_usb_device *);
|
extern int dvb_usb_urb_kill(struct dvb_usb_device *);
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
#include "dvb-usb-common.h"
|
#include "dvb-usb-common.h"
|
||||||
|
|
||||||
#include <linux/firmware.h>
|
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
|
|
||||||
struct usb_cypress_controller {
|
struct usb_cypress_controller {
|
||||||
@ -19,6 +18,7 @@ struct usb_cypress_controller {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct usb_cypress_controller cypress[] = {
|
static struct usb_cypress_controller cypress[] = {
|
||||||
|
{ .id = DEVICE_SPECIFIC, .name = "Device specific", .cpu_cs_register = 0 },
|
||||||
{ .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
|
{ .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
|
||||||
{ .id = CYPRESS_AN2235, .name = "Cypress AN2235", .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 = 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)
|
static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
|
||||||
{
|
{
|
||||||
return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
|
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;
|
struct hexline hx;
|
||||||
u16 addr;
|
|
||||||
u8 *b,*p;
|
|
||||||
int ret = 0,i;
|
|
||||||
|
|
||||||
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);
|
|
||||||
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;
|
u8 reset;
|
||||||
/*
|
int ret,pos=0;
|
||||||
* 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 */
|
/* stop the CPU */
|
||||||
reset = 1;
|
reset = 1;
|
||||||
if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
|
if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
|
||||||
err("could not stop the USB controller CPU.");
|
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]);
|
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);
|
||||||
|
|
||||||
ret = usb_cypress_writemem(udev,addr,&b[4],b[0]);
|
if (ret != hx.len) {
|
||||||
|
|
||||||
if (ret != b[0]) {
|
|
||||||
err("error while transferring firmware "
|
err("error while transferring firmware "
|
||||||
"(transferred size: %d, block size: %d)",
|
"(transferred size: %d, block size: %d)",
|
||||||
ret,b[0]);
|
ret,hx.len);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i += 5 + b[0];
|
|
||||||
}
|
}
|
||||||
/* length in ret */
|
if (ret < 0) {
|
||||||
if (ret > 0)
|
err("firmware download failed at %d with %d",pos,ret);
|
||||||
ret = 0;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
/* restart the CPU */
|
/* restart the CPU */
|
||||||
reset = 0;
|
reset = 0;
|
||||||
if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
|
if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
|
||||||
err("could not restart the USB controller CPU.");
|
err("could not restart the USB controller CPU.");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
kfree(p);
|
ret = -EIO;
|
||||||
} else {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
}
|
|
||||||
release_firmware(fw);
|
|
||||||
|
|
||||||
return ret;
|
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 };
|
struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* if there is nothing to initialize */
|
/* if pll_desc is not used */
|
||||||
if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 &&
|
if (d->pll_desc == NULL)
|
||||||
d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (d->tuner_pass_ctrl)
|
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;
|
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);
|
deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
|
||||||
|
|
||||||
b[0] = d->pll_addr << 1;
|
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_COLD 0x9300
|
||||||
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
|
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
|
||||||
#define USB_PID_NEBULA_DIGITV 0x0201
|
#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_LGDT 0xd820
|
||||||
#define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01
|
#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500
|
||||||
#define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11
|
#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_MEDION_MD95700 0x0932
|
||||||
#define USB_PID_KYE_DVB_T_COLD 0x701e
|
#define USB_PID_KYE_DVB_T_COLD 0x701e
|
||||||
#define USB_PID_KYE_DVB_T_WARM 0x701f
|
#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;
|
int ret = -ENOMEM,cold=0;
|
||||||
|
|
||||||
|
if (du != NULL)
|
||||||
|
*du = NULL;
|
||||||
|
|
||||||
if ((desc = dvb_usb_find_device(udev,props,&cold)) == 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");
|
deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -145,8 +148,11 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
|
|||||||
|
|
||||||
if (cold) {
|
if (cold) {
|
||||||
info("found a '%s' in cold state, will try to load a firmware",desc->name);
|
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);
|
ret = dvb_usb_download_firmware(udev,props);
|
||||||
} else {
|
if (!props->no_reconnect)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
info("found a '%s' in warm state.",desc->name);
|
info("found a '%s' in warm state.",desc->name);
|
||||||
d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
|
d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
@ -176,7 +182,6 @@ int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
|
|||||||
*du = d;
|
*du = d;
|
||||||
|
|
||||||
ret = dvb_usb_init(d);
|
ret = dvb_usb_init(d);
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
info("%s successfully initialized and connected.",desc->name);
|
info("%s successfully initialized and connected.",desc->name);
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
#include <linux/config.h>
|
#include <linux/config.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
|
#include <linux/firmware.h>
|
||||||
|
|
||||||
#include "dvb_frontend.h"
|
#include "dvb_frontend.h"
|
||||||
#include "dvb_demux.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
|
* @usb_ctrl: which USB device-side controller is in use. Needed for firmware
|
||||||
* download.
|
* download.
|
||||||
* @firmware: name of the firmware file.
|
* @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
|
* @size_of_priv: how many bytes shall be allocated for the private field
|
||||||
* of struct dvb_usb_device.
|
* of struct dvb_usb_device.
|
||||||
*
|
*
|
||||||
@ -142,11 +146,14 @@ struct dvb_usb_properties {
|
|||||||
int caps;
|
int caps;
|
||||||
int pid_filter_count;
|
int pid_filter_count;
|
||||||
|
|
||||||
#define CYPRESS_AN2135 0
|
#define DEVICE_SPECIFIC 0
|
||||||
#define CYPRESS_AN2235 1
|
#define CYPRESS_AN2135 1
|
||||||
#define CYPRESS_FX2 2
|
#define CYPRESS_AN2235 2
|
||||||
|
#define CYPRESS_FX2 3
|
||||||
int usb_ctrl;
|
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;
|
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(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
|
||||||
extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
|
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
|
#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);
|
dibusb_read_eeprom_byte(d,i, &b);
|
||||||
|
|
||||||
mac[5 - (i - 136)] = b;
|
mac[5 - (i - 136)] = b;
|
||||||
|
|
||||||
/* deb_ee("%02x ",b);
|
|
||||||
if ((i+1) % 16 == 0)
|
|
||||||
deb_ee("\n");*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -198,6 +194,7 @@ static struct dvb_usb_properties nova_t_properties = {
|
|||||||
{ &nova_t_table[0], NULL },
|
{ &nova_t_table[0], NULL },
|
||||||
{ &nova_t_table[1], NULL },
|
{ &nova_t_table[1], NULL },
|
||||||
},
|
},
|
||||||
|
{ NULL },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ extern int dvb_usb_vp702x_debug;
|
|||||||
* len X1 X2 X3 X4
|
* len X1 X2 X3 X4
|
||||||
* additional in buffer:
|
* additional in buffer:
|
||||||
* 0 1 2
|
* 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:
|
/* additional out buffer:
|
||||||
@ -45,7 +45,7 @@ extern int dvb_usb_vp702x_debug;
|
|||||||
* 0x00 0xff 1 = on, 0 = off
|
* 0x00 0xff 1 = on, 0 = off
|
||||||
* additional in buffer:
|
* additional in buffer:
|
||||||
* 0 1 2
|
* 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 */
|
/* #define GET_MAC_ADDRESS 0x0B */
|
||||||
@ -64,7 +64,6 @@ extern int dvb_usb_vp702x_debug;
|
|||||||
* freq0 freq1 divstep srate0 srate1 srate2 flag chksum
|
* freq0 freq1 divstep srate0 srate1 srate2 flag chksum
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* one direction requests */
|
/* one direction requests */
|
||||||
#define READ_REMOTE_REQ 0xB4
|
#define READ_REMOTE_REQ 0xB4
|
||||||
/* IN i: 0; v: 0; b[0] == request, b[1] == key */
|
/* IN i: 0; v: 0; b[0] == request, b[1] == key */
|
||||||
|
@ -247,7 +247,7 @@ static struct dvb_usb_properties vp7045_properties = {
|
|||||||
.cold_ids = { &vp7045_usb_table[2], NULL },
|
.cold_ids = { &vp7045_usb_table[2], NULL },
|
||||||
.warm_ids = { &vp7045_usb_table[3], NULL },
|
.warm_ids = { &vp7045_usb_table[3], NULL },
|
||||||
},
|
},
|
||||||
{ NULL },
|
{ 0 },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,6 +16,12 @@ config DVB_CX24110
|
|||||||
help
|
help
|
||||||
A DVB-S tuner module. Say Y when you want to support this frontend.
|
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
|
config DVB_TDA8083
|
||||||
tristate "Philips TDA8083 based"
|
tristate "Philips TDA8083 based"
|
||||||
depends on DVB_CORE
|
depends on DVB_CORE
|
||||||
@ -58,7 +64,8 @@ config DVB_SP8870
|
|||||||
|
|
||||||
This driver needs external firmware. Please use the command
|
This driver needs external firmware. Please use the command
|
||||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp8870" to
|
"<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
|
config DVB_SP887X
|
||||||
tristate "Spase sp887x based"
|
tristate "Spase sp887x based"
|
||||||
@ -69,7 +76,8 @@ config DVB_SP887X
|
|||||||
|
|
||||||
This driver needs external firmware. Please use the command
|
This driver needs external firmware. Please use the command
|
||||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
|
"<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
|
config DVB_CX22700
|
||||||
tristate "Conexant CX22700 based"
|
tristate "Conexant CX22700 based"
|
||||||
@ -99,7 +107,8 @@ config DVB_TDA1004X
|
|||||||
This driver needs external firmware. Please use the commands
|
This driver needs external firmware. Please use the commands
|
||||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
|
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
|
||||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
|
"<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).
|
||||||
|
|
||||||
config DVB_NXT6000
|
config DVB_NXT6000
|
||||||
tristate "NxtWave Communications NXT6000 based"
|
tristate "NxtWave Communications NXT6000 based"
|
||||||
@ -164,6 +173,11 @@ config DVB_NXT2002
|
|||||||
help
|
help
|
||||||
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
|
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
|
config DVB_NXT200X
|
||||||
tristate "Nextwave NXT2002/NXT2004 based"
|
tristate "Nextwave NXT2002/NXT2004 based"
|
||||||
depends on DVB_CORE
|
depends on DVB_CORE
|
||||||
@ -172,6 +186,12 @@ config DVB_NXT200X
|
|||||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||||
to support this frontend.
|
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
|
config DVB_OR51211
|
||||||
tristate "or51211 based (pcHDTV HD2000 card)"
|
tristate "or51211 based (pcHDTV HD2000 card)"
|
||||||
depends on DVB_CORE
|
depends on DVB_CORE
|
||||||
|
@ -32,3 +32,4 @@ obj-$(CONFIG_DVB_OR51132) += or51132.o
|
|||||||
obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
|
obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
|
||||||
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
|
obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
|
||||||
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.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;
|
bcm3510_register_value b;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((ret < bcm3510_readB(st,0xfa,&b)) < 0)
|
if ((ret = bcm3510_readB(st,0xfa,&b)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
|
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);
|
err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
deb_info("got firmware: %d\n",fw->size);
|
deb_info("got firmware: %zd\n",fw->size);
|
||||||
|
|
||||||
b = fw->data;
|
b = fw->data;
|
||||||
for (i = 0; i < fw->size;) {
|
for (i = 0; i < fw->size;) {
|
||||||
addr = le16_to_cpu( *( (u16 *)&b[i] ) );
|
addr = le16_to_cpu( *( (u16 *)&b[i] ) );
|
||||||
len = le16_to_cpu( *( (u16 *)&b[i+2] ) );
|
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) {
|
if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
|
||||||
err("firmware download failed: %d\n",ret);
|
err("firmware download failed: %d\n",ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -195,6 +195,16 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
|
|||||||
return 0;
|
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 */
|
/* 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)
|
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;
|
struct cx22702_state* state = fe->demodulator_priv;
|
||||||
|
|
||||||
/* set PLL */
|
/* set PLL */
|
||||||
cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
|
cx22702_i2c_gate_ctrl(fe, 1);
|
||||||
if (state->config->pll_set) {
|
if (state->config->pll_set) {
|
||||||
state->config->pll_set(fe, p);
|
state->config->pll_set(fe, p);
|
||||||
} else if (state->config->pll_desc) {
|
} else if (state->config->pll_desc) {
|
||||||
@ -216,7 +226,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
|
|||||||
} else {
|
} else {
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
|
cx22702_i2c_gate_ctrl(fe, 0);
|
||||||
|
|
||||||
/* set inversion */
|
/* set inversion */
|
||||||
cx22702_set_inversion (state, p->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);
|
cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
|
||||||
|
|
||||||
/* init PLL */
|
/* init PLL */
|
||||||
if (state->config->pll_init) {
|
if (state->config->pll_init)
|
||||||
cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) & 0xfe);
|
|
||||||
state->config->pll_init(fe);
|
state->config->pll_init(fe);
|
||||||
cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) | 1);
|
|
||||||
}
|
cx22702_i2c_gate_ctrl(fe, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -531,6 +540,7 @@ static struct dvb_frontend_ops cx22702_ops = {
|
|||||||
.read_signal_strength = cx22702_read_signal_strength,
|
.read_signal_strength = cx22702_read_signal_strength,
|
||||||
.read_snr = cx22702_read_snr,
|
.read_snr = cx22702_read_snr,
|
||||||
.read_ucblocks = cx22702_read_ucblocks,
|
.read_ucblocks = cx22702_read_ucblocks,
|
||||||
|
.i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_param(debug, int, 0644);
|
module_param(debug, int, 0644);
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/jiffies.h>
|
|
||||||
|
|
||||||
#include "dvb_frontend.h"
|
#include "dvb_frontend.h"
|
||||||
#include "cx24110.h"
|
#include "cx24110.h"
|
||||||
|
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);
|
EXPORT_SYMBOL(dvb_pll_microtune_4042);
|
||||||
|
|
||||||
struct dvb_pll_desc dvb_pll_thomson_dtt7611 = {
|
struct dvb_pll_desc dvb_pll_thomson_dtt761x = {
|
||||||
.name = "Thomson dtt7611",
|
/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
|
||||||
.min = 44000000,
|
.name = "Thomson dtt761x",
|
||||||
.max = 958000000,
|
.min = 57000000,
|
||||||
|
.max = 863000000,
|
||||||
.count = 3,
|
.count = 3,
|
||||||
.entries = {
|
.entries = {
|
||||||
{ 157250000, 44000000, 62500, 0x8e, 0x39 },
|
{ 147000000, 44000000, 62500, 0x8e, 0x39 },
|
||||||
{ 454000000, 44000000, 62500, 0x8e, 0x3a },
|
{ 417000000, 44000000, 62500, 0x8e, 0x3a },
|
||||||
{ 999999999, 44000000, 62500, 0x8e, 0x3c },
|
{ 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 = {
|
struct dvb_pll_desc dvb_pll_unknown_1 = {
|
||||||
.name = "unknown 1", /* used by dntv live dvb-t */
|
.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_thomson_dtt7610;
|
||||||
extern struct dvb_pll_desc dvb_pll_lg_z201;
|
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_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_unknown_1;
|
||||||
|
|
||||||
extern struct dvb_pll_desc dvb_pll_tua6010xs;
|
extern struct dvb_pll_desc dvb_pll_tua6010xs;
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
* DViCO FusionHDTV 3 Gold-T
|
* DViCO FusionHDTV 3 Gold-T
|
||||||
* DViCO FusionHDTV 5 Gold
|
* DViCO FusionHDTV 5 Gold
|
||||||
* DViCO FusionHDTV 5 Lite
|
* DViCO FusionHDTV 5 Lite
|
||||||
|
* DViCO FusionHDTV 5 USB Gold
|
||||||
* Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
|
* Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
|
||||||
*
|
*
|
||||||
* TODO:
|
* TODO:
|
||||||
@ -402,6 +403,8 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
|
|||||||
state->config->pll_set(fe, param);
|
state->config->pll_set(fe, param);
|
||||||
|
|
||||||
/* Keep track of the new frequency */
|
/* 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;
|
state->current_frequency = param->frequency;
|
||||||
|
|
||||||
lgdt330x_SwReset(state);
|
lgdt330x_SwReset(state);
|
||||||
|
@ -22,7 +22,8 @@
|
|||||||
/*
|
/*
|
||||||
* This driver needs external firmware. Please use the command
|
* This driver needs external firmware. Please use the command
|
||||||
* "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" to
|
* "<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 NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
|
||||||
#define CRC_CCIT_MASK 0x1021
|
#define CRC_CCIT_MASK 0x1021
|
||||||
|
@ -25,7 +25,8 @@
|
|||||||
/*
|
/*
|
||||||
* This driver needs external firmware. Please use the command
|
* This driver needs external firmware. Please use the command
|
||||||
* "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
|
* "<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"
|
#define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw"
|
||||||
|
|
||||||
@ -112,7 +113,7 @@ static int or51211_load_firmware (struct dvb_frontend* fe,
|
|||||||
u8 tudata[585];
|
u8 tudata[585];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
dprintk("Firmware is %d bytes\n",fw->size);
|
dprintk("Firmware is %zd bytes\n",fw->size);
|
||||||
|
|
||||||
/* Get eprom data */
|
/* Get eprom data */
|
||||||
tudata[0] = 17;
|
tudata[0] = 17;
|
||||||
|
@ -22,7 +22,8 @@
|
|||||||
/*
|
/*
|
||||||
* This driver needs external firmware. Please use the command
|
* This driver needs external firmware. Please use the command
|
||||||
* "<kerneldir>/Documentation/dvb/get_dvb_firmware alps_tdlb7" to
|
* "<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"
|
#define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
/*
|
/*
|
||||||
* This driver needs external firmware. Please use the command
|
* This driver needs external firmware. Please use the command
|
||||||
* "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
|
* "<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"
|
#define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw"
|
||||||
|
|
||||||
|
@ -131,6 +131,13 @@ static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len
|
|||||||
return ret == 2 ? 0 : ret;
|
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)
|
static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
|
||||||
{
|
{
|
||||||
dprintk ("%s\n", __FUNCTION__);
|
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;
|
struct stv0299_state* state = fe->demodulator_priv;
|
||||||
u8 reg0x08;
|
u8 reg0x08;
|
||||||
@ -407,7 +414,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
|
|||||||
|
|
||||||
cmd = cmd << 1;
|
cmd = cmd << 1;
|
||||||
if (debug_legacy_dish_switch)
|
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);
|
do_gettimeofday (&nexttime);
|
||||||
if (debug_legacy_dish_switch)
|
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");
|
"Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(stv0299_enable_plli2c);
|
||||||
EXPORT_SYMBOL(stv0299_writereg);
|
EXPORT_SYMBOL(stv0299_writereg);
|
||||||
EXPORT_SYMBOL(stv0299_attach);
|
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_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,
|
extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
|
||||||
struct i2c_adapter* i2c);
|
struct i2c_adapter* i2c);
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
* This driver needs external firmware. Please use the commands
|
* This driver needs external firmware. Please use the commands
|
||||||
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
|
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
|
||||||
* "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
|
* "<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 TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw"
|
||||||
#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.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,
|
static int tda10046h_set_bandwidth(struct tda1004x_state *state,
|
||||||
fe_bandwidth_t bandwidth)
|
fe_bandwidth_t bandwidth)
|
||||||
{
|
{
|
||||||
static u8 bandwidth_6mhz[] = { 0x80, 0x15, 0xfe, 0xab, 0x8e };
|
static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 };
|
||||||
static u8 bandwidth_7mhz[] = { 0x6e, 0x02, 0x53, 0xc8, 0x25 };
|
static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f };
|
||||||
static u8 bandwidth_8mhz[] = { 0x60, 0x12, 0xa8, 0xe4, 0xbd };
|
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) {
|
switch (bandwidth) {
|
||||||
case BANDWIDTH_6_MHZ:
|
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) {
|
if (state->config->if_freq == TDA10046_FREQ_045) {
|
||||||
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x09);
|
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
|
||||||
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x4f);
|
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BANDWIDTH_7_MHZ:
|
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) {
|
if (state->config->if_freq == TDA10046_FREQ_045) {
|
||||||
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
|
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
|
||||||
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x79);
|
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BANDWIDTH_8_MHZ:
|
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) {
|
if (state->config->if_freq == TDA10046_FREQ_045) {
|
||||||
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
|
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
|
||||||
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
|
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -418,9 +444,22 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
|
|||||||
static void tda10046_init_plls(struct dvb_frontend* fe)
|
static void tda10046_init_plls(struct dvb_frontend* fe)
|
||||||
{
|
{
|
||||||
struct tda1004x_state* state = fe->demodulator_priv;
|
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_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 ) {
|
if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
|
||||||
dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
|
dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __FUNCTION__);
|
||||||
tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
|
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__);
|
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_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) {
|
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:
|
case TDA10046_FREQ_045:
|
||||||
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0b);
|
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
|
||||||
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xa3);
|
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
|
||||||
break;
|
break;
|
||||||
case TDA10046_FREQ_052:
|
case TDA10046_FREQ_052:
|
||||||
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
|
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
|
||||||
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x06);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
tda10046h_set_bandwidth(state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz
|
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)
|
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 */
|
/* let the clocks recover from sleep */
|
||||||
msleep(5);
|
msleep(5);
|
||||||
|
|
||||||
|
/* The PLLs need to be reprogrammed after sleep */
|
||||||
|
tda10046_init_plls(fe);
|
||||||
|
|
||||||
/* don't re-upload unless necessary */
|
/* don't re-upload unless necessary */
|
||||||
if (tda1004x_check_upload_ok(state) == 0)
|
if (tda1004x_check_upload_ok(state) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* set parameters */
|
|
||||||
tda10046_init_plls(fe);
|
|
||||||
|
|
||||||
if (state->config->request_firmware != NULL) {
|
if (state->config->request_firmware != NULL) {
|
||||||
/* request the firmware, this will block until someone uploads it */
|
/* request the firmware, this will block until someone uploads it */
|
||||||
printk(KERN_INFO "tda1004x: waiting for firmware upload...\n");
|
printk(KERN_INFO "tda1004x: waiting for firmware upload...\n");
|
||||||
@ -484,7 +529,6 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
|
|||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
/* boot from firmware eeprom */
|
/* boot from firmware eeprom */
|
||||||
/* Hac Note: we might need to do some GPIO Magic here */
|
|
||||||
printk(KERN_INFO "tda1004x: booting from eeprom\n");
|
printk(KERN_INFO "tda1004x: booting from eeprom\n");
|
||||||
tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4);
|
tda1004x_write_mask(state, TDA1004X_CONFC4, 4, 4);
|
||||||
msleep(300);
|
msleep(300);
|
||||||
@ -606,10 +650,9 @@ static int tda10046_init(struct dvb_frontend* fe)
|
|||||||
|
|
||||||
// tda setup
|
// tda setup
|
||||||
tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
|
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_AUTO, 0x87); // 100 ppm crystal, select HP stream
|
||||||
tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
|
tda1004x_write_byteI(state, TDA1004X_CONFC1, 8); // disable pulse killer
|
||||||
|
|
||||||
tda10046_init_plls(fe);
|
|
||||||
switch (state->config->agc_config) {
|
switch (state->config->agc_config) {
|
||||||
case TDA10046_AGC_DEFAULT:
|
case TDA10046_AGC_DEFAULT:
|
||||||
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup
|
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:
|
case TDA10046_AGC_TDA827X:
|
||||||
tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02); // AGC setup
|
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_THR, 0x70); // AGC Threshold
|
||||||
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x0E); // Gain Renormalize
|
tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
|
||||||
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x60); // set AGC polarities
|
tda1004x_write_byteI(state, TDA10046H_CONF_POLARITY, 0x6a); // set AGC polarities
|
||||||
break;
|
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_CONF_TRISTATE1, 0x61); // Turn both AGC outputs on
|
||||||
tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0); // }
|
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_TUN_MAX, 0xff); // } AGC min/max values
|
||||||
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // }
|
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0); // }
|
||||||
tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff); // }
|
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, 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_TS1, 7); // MPEG2 interface config
|
||||||
tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // 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_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;
|
state->initialised = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -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)
|
static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
|
||||||
{
|
{
|
||||||
struct tda1004x_state* state = fe->demodulator_priv;
|
struct tda1004x_state* state = fe->demodulator_priv;
|
||||||
|
|
||||||
dprintk("%s\n", __FUNCTION__);
|
dprintk("%s\n", __FUNCTION__);
|
||||||
|
|
||||||
// inversion status
|
// inversion status
|
||||||
@ -875,16 +916,18 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TDA1004X_DEMOD_TDA10046:
|
case TDA1004X_DEMOD_TDA10046:
|
||||||
switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
|
switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
|
||||||
case 0x60:
|
case 0x5c:
|
||||||
|
case 0x54:
|
||||||
fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
|
fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
|
||||||
break;
|
break;
|
||||||
case 0x6e:
|
case 0x6a:
|
||||||
|
case 0x60:
|
||||||
fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
|
fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
|
||||||
break;
|
break;
|
||||||
case 0x80:
|
case 0x7b:
|
||||||
|
case 0x70:
|
||||||
fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
|
fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,8 @@ config DVB_AV7110
|
|||||||
|
|
||||||
This driver needs an external firmware. Please use the script
|
This driver needs an external firmware. Please use the script
|
||||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
|
"<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" 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).
|
||||||
|
|
||||||
Say Y if you own such a card and want to use it.
|
Say Y if you own such a card and want to use it.
|
||||||
|
|
||||||
|
@ -133,7 +133,13 @@ static void init_av7110_av(struct av7110 *av7110)
|
|||||||
/* remaining inits according to card and frontend type */
|
/* remaining inits according to card and frontend type */
|
||||||
av7110->analog_tuner_flags = 0;
|
av7110->analog_tuner_flags = 0;
|
||||||
av7110->current_input = 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",
|
printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
|
||||||
av7110->dvb_adapter.num);
|
av7110->dvb_adapter.num);
|
||||||
av7110->adac_type = DVB_ADAC_CRYSTAL;
|
av7110->adac_type = DVB_ADAC_CRYSTAL;
|
||||||
@ -156,10 +162,10 @@ static void init_av7110_av(struct av7110 *av7110)
|
|||||||
else {
|
else {
|
||||||
av7110->adac_type = adac;
|
av7110->adac_type = adac;
|
||||||
printk("dvb-ttpci: adac type set to %d @ card %d\n",
|
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
|
// switch DVB SCART on
|
||||||
ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
|
ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -190,19 +196,17 @@ static void recover_arm(struct av7110 *av7110)
|
|||||||
|
|
||||||
av7110_bootarm(av7110);
|
av7110_bootarm(av7110);
|
||||||
msleep(100);
|
msleep(100);
|
||||||
|
|
||||||
|
init_av7110_av(av7110);
|
||||||
|
|
||||||
|
/* card-specific recovery */
|
||||||
|
if (av7110->recover)
|
||||||
|
av7110->recover(av7110);
|
||||||
|
|
||||||
restart_feeds(av7110);
|
restart_feeds(av7110);
|
||||||
av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config);
|
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)
|
static void av7110_arm_sync(struct av7110 *av7110)
|
||||||
{
|
{
|
||||||
av7110->arm_rmmod = 1;
|
av7110->arm_rmmod = 1;
|
||||||
@ -240,26 +244,22 @@ static int arm_thread(void *data)
|
|||||||
|
|
||||||
if (down_interruptible(&av7110->dcomlock))
|
if (down_interruptible(&av7110->dcomlock))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
|
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
|
||||||
up(&av7110->dcomlock);
|
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",
|
printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
|
||||||
av7110->dvb_adapter.num);
|
av7110->dvb_adapter.num);
|
||||||
|
|
||||||
arm_error(av7110);
|
recover_arm(av7110);
|
||||||
av7710_set_video_mode(av7110, vidmode);
|
|
||||||
|
|
||||||
init_av7110_av(av7110);
|
|
||||||
|
|
||||||
if (down_interruptible(&av7110->dcomlock))
|
if (down_interruptible(&av7110->dcomlock))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
|
newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
|
||||||
up(&av7110->dcomlock);
|
up(&av7110->dcomlock);
|
||||||
}
|
}
|
||||||
av7110->arm_loops = newloops;
|
av7110->arm_loops = newloops;
|
||||||
|
av7110->arm_errors = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
av7110->arm_thread = NULL;
|
av7110->arm_thread = NULL;
|
||||||
@ -510,10 +510,6 @@ static void gpioirq(unsigned long data)
|
|||||||
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
|
iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
|
||||||
|
|
||||||
av7110->video_size.h = h_ar & 0xfff;
|
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.type = VIDEO_EVENT_SIZE_CHANGED;
|
||||||
event.u.size.w = av7110->video_size.w;
|
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;
|
event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
|
||||||
av7110->videostate.video_format = 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);
|
dvb_video_add_event(av7110, &event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -714,6 +715,8 @@ static struct dvb_device dvbdev_osd = {
|
|||||||
static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
|
static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
|
||||||
u16 subpid, u16 pcrpid)
|
u16 subpid, u16 pcrpid)
|
||||||
{
|
{
|
||||||
|
u16 aflags = 0;
|
||||||
|
|
||||||
dprintk(4, "%p\n", av7110);
|
dprintk(4, "%p\n", av7110);
|
||||||
|
|
||||||
if (vpid == 0x1fff || apid == 0x1fff ||
|
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;
|
av7110->pids[DMX_PES_PCR] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 5,
|
if (av7110->audiostate.bypass_mode)
|
||||||
pcrpid, vpid, apid, ttpid, subpid);
|
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,
|
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 *dvbdmx = &av7110->demux;
|
||||||
struct dvb_demux_feed *feed;
|
struct dvb_demux_feed *feed;
|
||||||
int mode;
|
int mode;
|
||||||
int i;
|
int i, j;
|
||||||
|
|
||||||
dprintk(4, "%p\n", av7110);
|
dprintk(4, "%p\n", av7110);
|
||||||
|
|
||||||
@ -1051,11 +1057,22 @@ static void restart_feeds(struct av7110 *av7110)
|
|||||||
av7110->playing = 0;
|
av7110->playing = 0;
|
||||||
av7110->rec_mode = 0;
|
av7110->rec_mode = 0;
|
||||||
|
|
||||||
for (i = 0; i < dvbdmx->filternum; i++) {
|
for (i = 0; i < dvbdmx->feednum; i++) {
|
||||||
feed = &dvbdmx->feed[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);
|
av7110_start_feed(feed);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mode)
|
if (mode)
|
||||||
av7110_av_start_play(av7110, mode);
|
av7110_av_start_play(av7110, mode);
|
||||||
@ -1484,8 +1501,8 @@ static int get_firmware(struct av7110* av7110)
|
|||||||
printk(KERN_ERR "dvb-ttpci: could not load firmware,"
|
printk(KERN_ERR "dvb-ttpci: could not load firmware,"
|
||||||
" file not found: dvb-ttpci-01.fw\n");
|
" file not found: dvb-ttpci-01.fw\n");
|
||||||
printk(KERN_ERR "dvb-ttpci: usually this should be in "
|
printk(KERN_ERR "dvb-ttpci: usually this should be in "
|
||||||
" /usr/lib/hotplug/firmware\n");
|
"/usr/lib/hotplug/firmware or /lib/firmware\n");
|
||||||
printk(KERN_ERR "dvb-ttpci: and can be downloaded here"
|
printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
|
||||||
" http://www.linuxtv.org/download/dvb/firmware/\n");
|
" http://www.linuxtv.org/download/dvb/firmware/\n");
|
||||||
} else
|
} else
|
||||||
printk(KERN_ERR "dvb-ttpci: cannot request firmware"
|
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;
|
struct av7110* av7110 = fe->dvb->priv;
|
||||||
|
|
||||||
int ret = av7110_fe_lock_fix(av7110, 0);
|
int ret = av7110_fe_lock_fix(av7110, 0);
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
|
av7110->saved_fe_params = *params;
|
||||||
ret = av7110->fe_set_frontend(fe, params);
|
ret = av7110->fe_set_frontend(fe, params);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2153,8 +2172,10 @@ static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
|
|||||||
struct av7110* av7110 = fe->dvb->priv;
|
struct av7110* av7110 = fe->dvb->priv;
|
||||||
|
|
||||||
int ret = av7110_fe_lock_fix(av7110, 0);
|
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);
|
ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
|
||||||
|
}
|
||||||
return ret;
|
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;
|
struct av7110* av7110 = fe->dvb->priv;
|
||||||
|
|
||||||
int ret = av7110_fe_lock_fix(av7110, 0);
|
int ret = av7110_fe_lock_fix(av7110, 0);
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
|
av7110->saved_minicmd = minicmd;
|
||||||
ret = av7110->fe_diseqc_send_burst(fe, minicmd);
|
ret = av7110->fe_diseqc_send_burst(fe, minicmd);
|
||||||
|
}
|
||||||
return ret;
|
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;
|
struct av7110* av7110 = fe->dvb->priv;
|
||||||
|
|
||||||
int ret = av7110_fe_lock_fix(av7110, 0);
|
int ret = av7110_fe_lock_fix(av7110, 0);
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
|
av7110->saved_tone = tone;
|
||||||
ret = av7110->fe_set_tone(fe, tone);
|
ret = av7110->fe_set_tone(fe, tone);
|
||||||
|
}
|
||||||
return ret;
|
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;
|
struct av7110* av7110 = fe->dvb->priv;
|
||||||
|
|
||||||
int ret = av7110_fe_lock_fix(av7110, 0);
|
int ret = av7110_fe_lock_fix(av7110, 0);
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
|
av7110->saved_voltage = voltage;
|
||||||
ret = av7110->fe_set_voltage(fe, voltage);
|
ret = av7110->fe_set_voltage(fe, voltage);
|
||||||
|
}
|
||||||
return ret;
|
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;
|
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;
|
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)
|
static u8 read_pwm(struct av7110* av7110)
|
||||||
{
|
{
|
||||||
u8 b = 0xff;
|
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_master_cmd = av7110_diseqc_send_master_cmd;
|
||||||
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
||||||
av7110->fe->ops->set_tone = av7110_set_tone;
|
av7110->fe->ops->set_tone = av7110_set_tone;
|
||||||
|
av7110->recover = dvb_s_recover;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2244,6 +2289,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_master_cmd = av7110_diseqc_send_master_cmd;
|
||||||
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
||||||
av7110->fe->ops->set_tone = av7110_set_tone;
|
av7110->fe->ops->set_tone = av7110_set_tone;
|
||||||
|
av7110->recover = dvb_s_recover;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2253,6 +2299,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_master_cmd = av7110_diseqc_send_master_cmd;
|
||||||
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
||||||
av7110->fe->ops->set_tone = av7110_set_tone;
|
av7110->fe->ops->set_tone = av7110_set_tone;
|
||||||
|
av7110->recover = dvb_s_recover;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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_master_cmd = av7110_diseqc_send_master_cmd;
|
||||||
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
|
||||||
av7110->fe->ops->set_tone = av7110_set_tone;
|
av7110->fe->ops->set_tone = av7110_set_tone;
|
||||||
|
av7110->recover = dvb_s_recover;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2314,8 +2362,11 @@ static int frontend_init(struct av7110 *av7110)
|
|||||||
case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
|
case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
|
||||||
/* ALPS BSBE1 */
|
/* ALPS BSBE1 */
|
||||||
av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
|
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->set_voltage = lnbp21_set_voltage;
|
||||||
|
av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
|
||||||
|
av7110->recover = dvb_s_recover;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,8 @@ struct av7110 {
|
|||||||
int adac_type; /* audio DAC type */
|
int adac_type; /* audio DAC type */
|
||||||
#define DVB_ADAC_TI 0
|
#define DVB_ADAC_TI 0
|
||||||
#define DVB_ADAC_CRYSTAL 1
|
#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
|
#define DVB_ADAC_NONE -1
|
||||||
|
|
||||||
|
|
||||||
@ -228,6 +229,9 @@ struct av7110 {
|
|||||||
struct dvb_video_events video_events;
|
struct dvb_video_events video_events;
|
||||||
video_size_t video_size;
|
video_size_t video_size;
|
||||||
|
|
||||||
|
u16 wssMode;
|
||||||
|
u16 wssData;
|
||||||
|
|
||||||
u32 ir_config;
|
u32 ir_config;
|
||||||
u32 ir_command;
|
u32 ir_command;
|
||||||
void (*ir_handler)(struct av7110 *av7110, u32 ircom);
|
void (*ir_handler)(struct av7110 *av7110, u32 ircom);
|
||||||
@ -245,6 +249,15 @@ struct av7110 {
|
|||||||
|
|
||||||
struct dvb_frontend* fe;
|
struct dvb_frontend* fe;
|
||||||
fe_status_t fe_status;
|
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_init)(struct dvb_frontend* fe);
|
||||||
int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status);
|
int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status);
|
||||||
int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe);
|
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_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_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_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);
|
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);
|
i2c_writereg(av7110, 0x20, 0x04, volright);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case DVB_ADAC_MSP:
|
case DVB_ADAC_MSP34x0:
|
||||||
vol = (volleft > volright) ? volleft : volright;
|
vol = (volleft > volright) ? volleft : volright;
|
||||||
val = (vol * 0x73 / 255) << 8;
|
val = (vol * 0x73 / 255) << 8;
|
||||||
if (vol > 0)
|
if (vol > 0)
|
||||||
@ -1256,7 +1256,9 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AUDIO_SET_BYPASS_MODE:
|
case AUDIO_SET_BYPASS_MODE:
|
||||||
|
if (FW_VERSION(av7110->arm_app) < 0x2621)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
av7110->audiostate.bypass_mode = (int)arg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUDIO_CHANNEL_SELECT:
|
case AUDIO_CHANNEL_SELECT:
|
||||||
@ -1295,7 +1297,11 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AUDIO_GET_CAPABILITIES:
|
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;
|
break;
|
||||||
|
|
||||||
case AUDIO_CLEAR_BUFFER:
|
case AUDIO_CLEAR_BUFFER:
|
||||||
|
@ -230,6 +230,8 @@ int av7110_bootarm(struct av7110 *av7110)
|
|||||||
|
|
||||||
dprintk(4, "%p\n", av7110);
|
dprintk(4, "%p\n", av7110);
|
||||||
|
|
||||||
|
av7110->arm_ready = 0;
|
||||||
|
|
||||||
saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
|
saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
|
||||||
|
|
||||||
/* Disable DEBI and GPIO irq */
|
/* Disable DEBI and GPIO irq */
|
||||||
@ -361,6 +363,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
|
|||||||
break;
|
break;
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
|
printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __FUNCTION__);
|
||||||
|
av7110->arm_errors++;
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
msleep(1);
|
msleep(1);
|
||||||
|
@ -167,7 +167,8 @@ enum av7110_encoder_command {
|
|||||||
LoadVidCode,
|
LoadVidCode,
|
||||||
SetMonitorType,
|
SetMonitorType,
|
||||||
SetPanScanType,
|
SetPanScanType,
|
||||||
SetFreezeMode
|
SetFreezeMode,
|
||||||
|
SetWSSConfig
|
||||||
};
|
};
|
||||||
|
|
||||||
enum av7110_rec_play_state {
|
enum av7110_rec_play_state {
|
||||||
|
@ -17,6 +17,8 @@ static int av_cnt;
|
|||||||
static struct av7110 *av_list[4];
|
static struct av7110 *av_list[4];
|
||||||
static struct input_dev *input_dev;
|
static struct input_dev *input_dev;
|
||||||
|
|
||||||
|
static u8 delay_timer_finished;
|
||||||
|
|
||||||
static u16 key_map [256] = {
|
static u16 key_map [256] = {
|
||||||
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
|
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,
|
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)) {
|
if (timer_pending(&keyup_timer)) {
|
||||||
del_timer(&keyup_timer);
|
del_timer(&keyup_timer);
|
||||||
if (keyup_timer.data != keycode || new_toggle != old_toggle) {
|
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, keyup_timer.data, !!0);
|
||||||
input_event(input_dev, EV_KEY, keycode, !0);
|
input_event(input_dev, EV_KEY, keycode, !0);
|
||||||
} else
|
} else
|
||||||
|
if (delay_timer_finished)
|
||||||
input_event(input_dev, EV_KEY, keycode, 2);
|
input_event(input_dev, EV_KEY, keycode, 2);
|
||||||
|
} else {
|
||||||
} else
|
delay_timer_finished = 0;
|
||||||
input_event(input_dev, EV_KEY, keycode, !0);
|
input_event(input_dev, EV_KEY, keycode, !0);
|
||||||
|
}
|
||||||
|
|
||||||
keyup_timer.expires = jiffies + UP_TIMEOUT;
|
keyup_timer.expires = jiffies + UP_TIMEOUT;
|
||||||
keyup_timer.data = keycode;
|
keyup_timer.data = keycode;
|
||||||
@ -145,7 +150,8 @@ static void input_register_keys(void)
|
|||||||
|
|
||||||
static void input_repeat_key(unsigned long data)
|
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);
|
dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
|
||||||
break;
|
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:
|
default:
|
||||||
printk("no such ioctl\n");
|
printk("no such ioctl\n");
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
@ -497,6 +549,46 @@ static int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
|
|||||||
return 0;
|
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
|
* INITIALIZATION
|
||||||
@ -512,6 +604,9 @@ static struct saa7146_extension_ioctls ioctls[] = {
|
|||||||
{ VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
|
{ VIDIOC_S_TUNER, SAA7146_EXCLUSIVE },
|
||||||
{ VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
|
{ VIDIOC_G_AUDIO, SAA7146_EXCLUSIVE },
|
||||||
{ VIDIOC_S_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 }
|
{ 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",
|
printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
|
||||||
av7110->dvb_adapter.num);
|
av7110->dvb_adapter.num);
|
||||||
av7110->adac_type = DVB_ADAC_MSP;
|
av7110->adac_type = DVB_ADAC_MSP34x0;
|
||||||
msleep(100); // the probing above resets the msp...
|
msleep(100); // the probing above resets the msp...
|
||||||
msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
|
msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
|
||||||
msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
|
msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
|
||||||
@ -692,13 +787,12 @@ int av7110_init_v4l(struct av7110 *av7110)
|
|||||||
saa7146_vv_release(dev);
|
saa7146_vv_release(dev);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
if (av7110->analog_tuner_flags) {
|
|
||||||
if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
|
if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI)) {
|
||||||
ERR(("cannot register vbi v4l2 device. skipping.\n"));
|
ERR(("cannot register vbi v4l2 device. skipping.\n"));
|
||||||
} else {
|
} else {
|
||||||
|
if (av7110->analog_tuner_flags)
|
||||||
av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
|
av7110->analog_tuner_flags |= ANALOG_TUNER_VBI;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0;
|
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 = {
|
static struct saa7146_ext_vv av7110_vv_data_st = {
|
||||||
.inputs = 1,
|
.inputs = 1,
|
||||||
.audios = 1,
|
.audios = 1,
|
||||||
.capabilities = 0,
|
.capabilities = V4L2_CAP_SLICED_VBI_OUTPUT,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
|
|
||||||
.stds = &standard[0],
|
.stds = &standard[0],
|
||||||
@ -787,12 +881,16 @@ static struct saa7146_ext_vv av7110_vv_data_st = {
|
|||||||
|
|
||||||
.ioctls = &ioctls[0],
|
.ioctls = &ioctls[0],
|
||||||
.ioctl = av7110_ioctl,
|
.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 = {
|
static struct saa7146_ext_vv av7110_vv_data_c = {
|
||||||
.inputs = 1,
|
.inputs = 1,
|
||||||
.audios = 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,
|
.flags = SAA7146_USE_PORT_B_FOR_VBI,
|
||||||
|
|
||||||
.stds = &standard[0],
|
.stds = &standard[0],
|
||||||
@ -801,5 +899,9 @@ static struct saa7146_ext_vv av7110_vv_data_c = {
|
|||||||
|
|
||||||
.ioctls = &ioctls[0],
|
.ioctls = &ioctls[0],
|
||||||
.ioctl = av7110_ioctl,
|
.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);
|
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
|
||||||
udelay(1);
|
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)
|
if (result == -ETIMEDOUT)
|
||||||
budget_av->slot_status = 0;
|
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);
|
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
|
||||||
udelay(1);
|
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)
|
if (result == -ETIMEDOUT)
|
||||||
budget_av->slot_status = 0;
|
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 budget_av *budget_av = (struct budget_av *) ca->data;
|
||||||
struct saa7146_dev *saa = budget_av->budget.dev;
|
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)
|
if (slot != 0)
|
||||||
return -EINVAL;
|
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 budget_av *budget_av = (struct budget_av *) ca->data;
|
||||||
struct saa7146_dev *saa = budget_av->budget.dev;
|
struct saa7146_dev *saa = budget_av->budget.dev;
|
||||||
|
int cam_present = 0;
|
||||||
|
|
||||||
if (slot != 0)
|
if (slot != 0)
|
||||||
return -EINVAL;
|
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);
|
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
|
||||||
udelay(1);
|
udelay(1);
|
||||||
if (saa7146_read(saa, PSR) & MASK_06)
|
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");
|
printk(KERN_INFO "budget-av: cam inserted\n");
|
||||||
budget_av->slot_status = 1;
|
budget_av->slot_status = 1;
|
||||||
}
|
}
|
||||||
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
|
|
||||||
} else if (!open) {
|
} else if (!open) {
|
||||||
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
|
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
|
||||||
if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
|
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;
|
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[] = {
|
static u8 typhoon_cinergy1200s_inittab[] = {
|
||||||
0x01, 0x15,
|
0x01, 0x15,
|
||||||
0x02, 0x30,
|
0x02, 0x30,
|
||||||
@ -553,6 +705,18 @@ static struct stv0299_config cinergy_1200s_config = {
|
|||||||
.pll_set = philips_su1278_ty_ci_pll_set,
|
.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)
|
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) {
|
switch (saa->pci->subsystem_device) {
|
||||||
|
|
||||||
case SUBID_DVBS_KNC1:
|
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_KNC1_PLUS:
|
||||||
case SUBID_DVBS_TYPHOON:
|
case SUBID_DVBS_TYPHOON:
|
||||||
fe = stv0299_attach(&typhoon_config,
|
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[] = {
|
static struct pci_device_id pci_tbl[] = {
|
||||||
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
|
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
|
||||||
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
|
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
|
||||||
|
MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
|
||||||
MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
|
MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
|
||||||
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
|
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
|
||||||
MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
|
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);
|
tasklet_init(&budget->vpe_tasklet, vpeirq, (unsigned long) budget);
|
||||||
|
|
||||||
/* frontend power on */
|
/* frontend power on */
|
||||||
if (bi->type == BUDGET_FS_ACTIVY)
|
if (bi->type != BUDGET_FS_ACTIVY)
|
||||||
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
|
|
||||||
else
|
|
||||||
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
|
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
|
||||||
|
|
||||||
if (budget_register(budget) == 0) {
|
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
|
* Routines for the Fujitsu Siemens Activy budget card
|
||||||
* 22 kHz tone and DiSEqC are handled by the frontend.
|
* 22 kHz tone and DiSEqC are handled by the frontend.
|
||||||
* Voltage must be set here.
|
* 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)
|
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) {
|
switch (voltage) {
|
||||||
case SEC_VOLTAGE_13:
|
case SEC_VOLTAGE_13:
|
||||||
|
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
|
||||||
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
|
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
|
||||||
break;
|
break;
|
||||||
case SEC_VOLTAGE_18:
|
case SEC_VOLTAGE_18:
|
||||||
|
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
|
||||||
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
|
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
|
||||||
break;
|
break;
|
||||||
|
case SEC_VOLTAGE_OFF:
|
||||||
|
saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -206,7 +212,7 @@ static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
|
|||||||
return 0;
|
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;
|
struct budget* budget = (struct budget*) fe->dvb->priv;
|
||||||
u8 buf;
|
u8 buf;
|
||||||
@ -580,6 +586,7 @@ static void frontend_init(struct budget *budget)
|
|||||||
if (budget->dvb_frontend) {
|
if (budget->dvb_frontend) {
|
||||||
budget->dvb_frontend->ops->set_voltage = lnbp21_set_voltage;
|
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->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
|
||||||
|
budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
|
||||||
if (lnbp21_init(budget)) {
|
if (lnbp21_init(budget)) {
|
||||||
printk("%s: No LNBP21 found!\n", __FUNCTION__);
|
printk("%s: No LNBP21 found!\n", __FUNCTION__);
|
||||||
goto error_out;
|
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);
|
budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
|
||||||
if (budget->dvb_frontend) {
|
if (budget->dvb_frontend) {
|
||||||
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
|
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
|
||||||
break;
|
budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -632,7 +639,7 @@ static void frontend_init(struct budget *budget)
|
|||||||
budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
|
budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
|
||||||
if (budget->dvb_frontend) {
|
if (budget->dvb_frontend) {
|
||||||
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
|
budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
|
||||||
break;
|
budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ config DVB_TTUSB_DEC
|
|||||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
|
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
|
||||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
|
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
|
||||||
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
|
"<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
|
||||||
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).
|
||||||
|
|
||||||
Say Y if you own such a device and want to use it.
|
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)
|
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->cb.ts(data, 188, NULL, 0,
|
||||||
&dec->audio_filter->feed->feed.ts,
|
&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)
|
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->cb.ts(data, 188, NULL, 0,
|
||||||
&dec->video_filter->feed->feed.ts,
|
&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:
|
case DMX_TS_PES_TELETEXT:
|
||||||
dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid;
|
dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid;
|
||||||
dprintk(" pes_type: DMX_TS_PES_TELETEXT\n");
|
dprintk(" pes_type: DMX_TS_PES_TELETEXT(not supported)\n");
|
||||||
break;
|
return -ENOSYS;
|
||||||
|
|
||||||
case DMX_TS_PES_PCR:
|
case DMX_TS_PES_PCR:
|
||||||
dprintk(" pes_type: DMX_TS_PES_PCR\n");
|
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;
|
break;
|
||||||
|
|
||||||
case DMX_TS_PES_OTHER:
|
case DMX_TS_PES_OTHER:
|
||||||
dprintk(" pes_type: DMX_TS_PES_OTHER\n");
|
dprintk(" pes_type: DMX_TS_PES_OTHER(not supported)\n");
|
||||||
break;
|
return -ENOSYS;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
dprintk(" pes_type: unknown (%d)\n", dvbdmxfeed->pes_type);
|
dprintk(" pes_type: unknown (%d)\n", dvbdmxfeed->pes_type);
|
||||||
@ -1209,7 +1209,6 @@ static int ttusb_init_rc(struct ttusb_dec *dec)
|
|||||||
|
|
||||||
if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
|
if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
|
||||||
printk("%s: usb_submit_urb failed\n",__FUNCTION__);
|
printk("%s: usb_submit_urb failed\n",__FUNCTION__);
|
||||||
|
|
||||||
/* enable irq pipe */
|
/* enable irq pipe */
|
||||||
ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
|
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
|
/* We can't trust the USB IDs that some firmwares
|
||||||
give the box */
|
give the box */
|
||||||
switch (model) {
|
switch (model) {
|
||||||
|
case 0x00070001:
|
||||||
case 0x00070008:
|
case 0x00070008:
|
||||||
case 0x0007000c:
|
case 0x0007000c:
|
||||||
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
|
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 param_length, const u8 params[],
|
||||||
int *result_length, u8 cmd_result[])
|
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);
|
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)
|
static int ttusbdecfe_read_status(struct dvb_frontend* fe, fe_status_t* status)
|
||||||
{
|
{
|
||||||
|
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 |
|
*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
|
||||||
FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -64,6 +95,16 @@ static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend* fe, struct dvb_fron
|
|||||||
return 0;
|
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)
|
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;
|
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,
|
.set_frontend = ttusbdecfe_dvbt_set_frontend,
|
||||||
|
|
||||||
|
.get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
|
||||||
|
|
||||||
.read_status = ttusbdecfe_read_status,
|
.read_status = ttusbdecfe_read_status,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -223,11 +266,11 @@ static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
|
|||||||
.frequency_min = 950000,
|
.frequency_min = 950000,
|
||||||
.frequency_max = 2150000,
|
.frequency_max = 2150000,
|
||||||
.frequency_stepsize = 125,
|
.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 |
|
.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_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_QPSK
|
||||||
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
|
|
||||||
FE_CAN_HIERARCHY_AUTO,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
.release = ttusbdecfe_release,
|
.release = ttusbdecfe_release,
|
||||||
|
@ -220,6 +220,7 @@ static struct file_operations pcm20_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = pcm20_ioctl,
|
.ioctl = pcm20_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -299,6 +299,7 @@ static struct file_operations rtrack_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = rt_ioctl,
|
.ioctl = rt_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -256,6 +256,7 @@ static struct file_operations aztech_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = az_ioctl,
|
.ioctl = az_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -490,6 +490,7 @@ static struct file_operations cadet_fops = {
|
|||||||
.release = cadet_release,
|
.release = cadet_release,
|
||||||
.read = cadet_read,
|
.read = cadet_read,
|
||||||
.ioctl = cadet_ioctl,
|
.ioctl = cadet_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -301,6 +301,7 @@ static struct file_operations gemtek_pci_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = gemtek_pci_ioctl,
|
.ioctl = gemtek_pci_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -233,6 +233,7 @@ static struct file_operations gemtek_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = gemtek_ioctl,
|
.ioctl = gemtek_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ static struct file_operations maestro_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = radio_ioctl,
|
.ioctl = radio_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ static struct file_operations maxiradio_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = radio_ioctl,
|
.ioctl = radio_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
static struct video_device maxiradio_radio =
|
static struct video_device maxiradio_radio =
|
||||||
|
@ -199,6 +199,7 @@ static struct file_operations rtrack2_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = rt_ioctl,
|
.ioctl = rt_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -225,6 +225,7 @@ static struct file_operations fmi_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = fmi_ioctl,
|
.ioctl = fmi_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -356,6 +356,7 @@ static struct file_operations fmr2_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = fmr2_ioctl,
|
.ioctl = fmr2_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -276,6 +276,7 @@ static struct file_operations terratec_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = tt_ioctl,
|
.ioctl = tt_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -255,6 +255,7 @@ static struct file_operations trust_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = tr_ioctl,
|
.ioctl = tr_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -261,6 +261,7 @@ static struct file_operations typhoon_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = typhoon_ioctl,
|
.ioctl = typhoon_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -313,6 +313,7 @@ static struct file_operations zoltrix_fops =
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = zol_ioctl,
|
.ioctl = zol_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,15 @@ menu "Video For Linux"
|
|||||||
|
|
||||||
comment "Video Adapters"
|
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
|
config VIDEO_BT848
|
||||||
tristate "BT848 Video For Linux"
|
tristate "BT848 Video For Linux"
|
||||||
depends on VIDEO_DEV && PCI && I2C
|
depends on VIDEO_DEV && PCI && I2C
|
||||||
|
@ -3,15 +3,19 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
|
bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \
|
||||||
bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o
|
bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
|
||||||
|
bttv-input.o
|
||||||
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o
|
zoran-objs := zr36120.o zr36120_i2c.o zr36120_mem.o
|
||||||
zr36067-objs := zoran_procfs.o zoran_device.o \
|
zr36067-objs := zoran_procfs.o zoran_device.o \
|
||||||
zoran_driver.o zoran_card.o
|
zoran_driver.o zoran_card.o
|
||||||
tuner-objs := tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o
|
tuner-objs := tuner-core.o tuner-simple.o mt20xx.o tda8290.o tea5767.o
|
||||||
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o
|
|
||||||
|
msp3400-objs := msp3400-driver.o msp3400-kthreads.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o
|
||||||
|
|
||||||
obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
|
obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \
|
||||||
tda7432.o tda9875.o ir-kbd-i2c.o ir-kbd-gpio.o
|
tda7432.o tda9875.o ir-kbd-i2c.o
|
||||||
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
|
obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
|
||||||
|
|
||||||
obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
|
obj-$(CONFIG_VIDEO_ZR36120) += zoran.o
|
||||||
|
@ -749,6 +749,7 @@ static struct file_operations ar_fops = {
|
|||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.read = ar_read,
|
.read = ar_read,
|
||||||
.ioctl = ar_ioctl,
|
.ioctl = ar_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,8 +30,9 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include <media/audiochip.h>
|
#include <media/audiochip.h>
|
||||||
|
#include <media/v4l2-common.h>
|
||||||
|
|
||||||
#include "bttv.h"
|
#include "bttv.h"
|
||||||
#include "bt832.h"
|
#include "bt832.h"
|
||||||
|
|
||||||
@ -42,9 +43,10 @@ static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1,
|
|||||||
I2C_CLIENT_END };
|
I2C_CLIENT_END };
|
||||||
I2C_CLIENT_INSMOD;
|
I2C_CLIENT_INSMOD;
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
int debug = 0; /* debug output */
|
||||||
|
module_param(debug, int, 0644);
|
||||||
|
|
||||||
#define dprintk if (debug) printk
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int bt832_detach(struct i2c_client *client);
|
static int bt832_detach(struct i2c_client *client);
|
||||||
|
|
||||||
@ -61,23 +63,26 @@ int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf)
|
|||||||
int i,rc;
|
int i,rc;
|
||||||
buf[0]=0x80; // start at register 0 with auto-increment
|
buf[0]=0x80; // start at register 0 with auto-increment
|
||||||
if (1 != (rc = i2c_master_send(i2c_client_s,buf,1)))
|
if (1 != (rc = i2c_master_send(i2c_client_s,buf,1)))
|
||||||
printk("bt832: i2c i/o error: rc == %d (should be 1)\n",rc);
|
v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 1)\n",rc);
|
||||||
|
|
||||||
for(i=0;i<65;i++)
|
for(i=0;i<65;i++)
|
||||||
buf[i]=0;
|
buf[i]=0;
|
||||||
if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65)))
|
if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65)))
|
||||||
printk("bt832: i2c i/o error: rc == %d (should be 65)\n",rc);
|
v4l_err(i2c_client_s,"i2c i/o error: rc == %d (should be 65)\n",rc);
|
||||||
|
|
||||||
// Note: On READ the first byte is the current index
|
// Note: On READ the first byte is the current index
|
||||||
// (e.g. 0x80, what we just wrote)
|
// (e.g. 0x80, what we just wrote)
|
||||||
|
|
||||||
if(1) {
|
if(debug>1) {
|
||||||
int i;
|
int i;
|
||||||
printk("BT832 hexdump:\n");
|
v4l_dbg(2,i2c_client_s,"hexdump:");
|
||||||
for(i=1;i<65;i++) {
|
for(i=1;i<65;i++) {
|
||||||
if(i!=1) {
|
if(i!=1) {
|
||||||
if(((i-1)%8)==0) printk(" ");
|
if(((i-1)%8)==0) printk(" ");
|
||||||
if(((i-1)%16)==0) printk("\n");
|
if(((i-1)%16)==0) {
|
||||||
|
printk("\n");
|
||||||
|
v4l_dbg(2,i2c_client_s,"hexdump:");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printk(" %02x",buf[i]);
|
printk(" %02x",buf[i]);
|
||||||
}
|
}
|
||||||
@ -96,56 +101,56 @@ int bt832_init(struct i2c_client *i2c_client_s)
|
|||||||
bt832_hexdump(i2c_client_s,buf);
|
bt832_hexdump(i2c_client_s,buf);
|
||||||
|
|
||||||
if(buf[0x40] != 0x31) {
|
if(buf[0x40] != 0x31) {
|
||||||
printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
|
v4l_err(i2c_client_s,"This i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("Write 0 tp VPSTATUS\n");
|
v4l_err(i2c_client_s,"Write 0 tp VPSTATUS\n");
|
||||||
buf[0]=BT832_VP_STATUS; // Reg.52
|
buf[0]=BT832_VP_STATUS; // Reg.52
|
||||||
buf[1]= 0x00;
|
buf[1]= 0x00;
|
||||||
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
|
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
|
||||||
printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc);
|
v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc);
|
||||||
|
|
||||||
bt832_hexdump(i2c_client_s,buf);
|
bt832_hexdump(i2c_client_s,buf);
|
||||||
|
|
||||||
|
|
||||||
// Leave low power mode:
|
// Leave low power mode:
|
||||||
printk("Bt832: leave low power mode.\n");
|
v4l_err(i2c_client_s,"leave low power mode.\n");
|
||||||
buf[0]=BT832_CAM_SETUP0; //0x39 57
|
buf[0]=BT832_CAM_SETUP0; //0x39 57
|
||||||
buf[1]=0x08;
|
buf[1]=0x08;
|
||||||
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
|
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
|
||||||
printk("bt832: i2c i/o error LLPM: rc == %d (should be 2)\n",rc);
|
v4l_err(i2c_client_s,"i2c i/o error LLPM: rc == %d (should be 2)\n",rc);
|
||||||
|
|
||||||
bt832_hexdump(i2c_client_s,buf);
|
bt832_hexdump(i2c_client_s,buf);
|
||||||
|
|
||||||
printk("Write 0 tp VPSTATUS\n");
|
v4l_info(i2c_client_s,"Write 0 tp VPSTATUS\n");
|
||||||
buf[0]=BT832_VP_STATUS; // Reg.52
|
buf[0]=BT832_VP_STATUS; // Reg.52
|
||||||
buf[1]= 0x00;
|
buf[1]= 0x00;
|
||||||
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
|
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
|
||||||
printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc);
|
v4l_err(i2c_client_s,"i2c i/o error VPS: rc == %d (should be 2)\n",rc);
|
||||||
|
|
||||||
bt832_hexdump(i2c_client_s,buf);
|
bt832_hexdump(i2c_client_s,buf);
|
||||||
|
|
||||||
|
|
||||||
// Enable Output
|
// Enable Output
|
||||||
printk("Enable Output\n");
|
v4l_info(i2c_client_s,"Enable Output\n");
|
||||||
buf[0]=BT832_VP_CONTROL1; // Reg.40
|
buf[0]=BT832_VP_CONTROL1; // Reg.40
|
||||||
buf[1]= 0x27 & (~0x01); // Default | !skip
|
buf[1]= 0x27 & (~0x01); // Default | !skip
|
||||||
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
|
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
|
||||||
printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc);
|
v4l_err(i2c_client_s,"i2c i/o error EO: rc == %d (should be 2)\n",rc);
|
||||||
|
|
||||||
bt832_hexdump(i2c_client_s,buf);
|
bt832_hexdump(i2c_client_s,buf);
|
||||||
|
|
||||||
|
|
||||||
// for testing (even works when no camera attached)
|
// for testing (even works when no camera attached)
|
||||||
printk("bt832: *** Generate NTSC M Bars *****\n");
|
v4l_info(i2c_client_s,"*** Generate NTSC M Bars *****\n");
|
||||||
buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42
|
buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42
|
||||||
buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally
|
buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally
|
||||||
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
|
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
|
||||||
printk("bt832: i2c i/o error MBAR: rc == %d (should be 2)\n",rc);
|
v4l_info(i2c_client_s,"i2c i/o error MBAR: rc == %d (should be 2)\n",rc);
|
||||||
|
|
||||||
printk("Bt832: Camera Present: %s\n",
|
v4l_info(i2c_client_s,"Camera Present: %s\n",
|
||||||
(buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no");
|
(buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no");
|
||||||
|
|
||||||
bt832_hexdump(i2c_client_s,buf);
|
bt832_hexdump(i2c_client_s,buf);
|
||||||
@ -159,13 +164,9 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
|
|||||||
{
|
{
|
||||||
struct bt832 *t;
|
struct bt832 *t;
|
||||||
|
|
||||||
printk("bt832_attach\n");
|
|
||||||
|
|
||||||
client_template.adapter = adap;
|
client_template.adapter = adap;
|
||||||
client_template.addr = addr;
|
client_template.addr = addr;
|
||||||
|
|
||||||
printk("bt832: chip found @ 0x%x\n", addr<<1);
|
|
||||||
|
|
||||||
if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
|
if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
memset(t,0,sizeof(*t));
|
memset(t,0,sizeof(*t));
|
||||||
@ -173,6 +174,9 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
|
|||||||
i2c_set_clientdata(&t->client, t);
|
i2c_set_clientdata(&t->client, t);
|
||||||
i2c_attach_client(&t->client);
|
i2c_attach_client(&t->client);
|
||||||
|
|
||||||
|
v4l_info(&t->client,"chip found @ 0x%x\n", addr<<1);
|
||||||
|
|
||||||
|
|
||||||
if(! bt832_init(&t->client)) {
|
if(! bt832_init(&t->client)) {
|
||||||
bt832_detach(&t->client);
|
bt832_detach(&t->client);
|
||||||
return -1;
|
return -1;
|
||||||
@ -183,13 +187,8 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
|
|||||||
|
|
||||||
static int bt832_probe(struct i2c_adapter *adap)
|
static int bt832_probe(struct i2c_adapter *adap)
|
||||||
{
|
{
|
||||||
#ifdef I2C_CLASS_TV_ANALOG
|
|
||||||
if (adap->class & I2C_CLASS_TV_ANALOG)
|
if (adap->class & I2C_CLASS_TV_ANALOG)
|
||||||
return i2c_probe(adap, &addr_data, bt832_attach);
|
return i2c_probe(adap, &addr_data, bt832_attach);
|
||||||
#else
|
|
||||||
if (adap->id == I2C_HW_B_BT848)
|
|
||||||
return i2c_probe(adap, &addr_data, bt832_attach);
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +196,7 @@ static int bt832_detach(struct i2c_client *client)
|
|||||||
{
|
{
|
||||||
struct bt832 *t = i2c_get_clientdata(client);
|
struct bt832 *t = i2c_get_clientdata(client);
|
||||||
|
|
||||||
printk("bt832: detach.\n");
|
v4l_info(&t->client,"dettach\n");
|
||||||
i2c_detach_client(client);
|
i2c_detach_client(client);
|
||||||
kfree(t);
|
kfree(t);
|
||||||
return 0;
|
return 0;
|
||||||
@ -208,7 +207,8 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
|||||||
{
|
{
|
||||||
struct bt832 *t = i2c_get_clientdata(client);
|
struct bt832 *t = i2c_get_clientdata(client);
|
||||||
|
|
||||||
printk("bt832: command %x\n",cmd);
|
if (debug>1)
|
||||||
|
v4l_i2c_print_ioctl(&t->client,cmd);
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case BT832_HEXDUMP: {
|
case BT832_HEXDUMP: {
|
||||||
@ -219,7 +219,7 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BT832_REATTACH:
|
case BT832_REATTACH:
|
||||||
printk("bt832: re-attach\n");
|
v4l_info(&t->client,"re-attach\n");
|
||||||
i2c_del_driver(&driver);
|
i2c_del_driver(&driver);
|
||||||
i2c_add_driver(&driver);
|
i2c_add_driver(&driver);
|
||||||
break;
|
break;
|
||||||
@ -231,9 +231,9 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
|||||||
|
|
||||||
static struct i2c_driver driver = {
|
static struct i2c_driver driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "i2c bt832 driver",
|
.name = "bt832",
|
||||||
},
|
},
|
||||||
.id = -1, /* FIXME */
|
.id = 0, /* FIXME */
|
||||||
.attach_adapter = bt832_probe,
|
.attach_adapter = bt832_probe,
|
||||||
.detach_client = bt832_detach,
|
.detach_client = bt832_detach,
|
||||||
.command = bt832_command,
|
.command = bt832_command,
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
#include "bttvp.h"
|
#include "bttvp.h"
|
||||||
|
#include <media/v4l2-common.h>
|
||||||
|
|
||||||
/* fwd decl */
|
/* fwd decl */
|
||||||
static void boot_msp34xx(struct bttv *btv, int pin);
|
static void boot_msp34xx(struct bttv *btv, int pin);
|
||||||
@ -292,6 +293,9 @@ static struct CARD {
|
|||||||
/* likely broken, vendor id doesn't match the other magic views ...
|
/* likely broken, vendor id doesn't match the other magic views ...
|
||||||
* { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */
|
* { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */
|
||||||
|
|
||||||
|
/* Duplicate PCI ID, reconfigure for this board during the eeprom read.
|
||||||
|
* { 0x13eb0070, BTTV_BOARD_HAUPPAUGE_IMPACTVCB, "Hauppauge ImpactVCB" }, */
|
||||||
|
|
||||||
/* DVB cards (using pci function .1 for mpeg data xfer) */
|
/* DVB cards (using pci function .1 for mpeg data xfer) */
|
||||||
{ 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
|
{ 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
|
||||||
{ 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
|
{ 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" },
|
||||||
@ -2136,7 +2140,6 @@ struct tvcard bttv_tvcards[] = {
|
|||||||
.has_remote = 1,
|
.has_remote = 1,
|
||||||
.gpiomask = 0x1b,
|
.gpiomask = 0x1b,
|
||||||
.no_gpioirq = 1,
|
.no_gpioirq = 1,
|
||||||
.any_irq = 1,
|
|
||||||
},
|
},
|
||||||
[BTTV_BOARD_PV143] = {
|
[BTTV_BOARD_PV143] = {
|
||||||
/* Jorge Boncompte - DTI2 <jorge@dti2.net> */
|
/* Jorge Boncompte - DTI2 <jorge@dti2.net> */
|
||||||
@ -2817,6 +2820,22 @@ struct tvcard bttv_tvcards[] = {
|
|||||||
.tuner_addr = ADDR_UNSET,
|
.tuner_addr = ADDR_UNSET,
|
||||||
.has_radio = 1,
|
.has_radio = 1,
|
||||||
},
|
},
|
||||||
|
/* ---- card 0x8f ---------------------------------- */
|
||||||
|
[BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = {
|
||||||
|
.name = "Hauppauge ImpactVCB (bt878)",
|
||||||
|
.video_inputs = 4,
|
||||||
|
.audio_inputs = 0,
|
||||||
|
.tuner = -1,
|
||||||
|
.svhs = -1,
|
||||||
|
.gpiomask = 0x0f, /* old: 7 */
|
||||||
|
.muxsel = { 0, 1, 3, 2}, /* Composite 0-3 */
|
||||||
|
.no_msp34xx = 1,
|
||||||
|
.no_tda9875 = 1,
|
||||||
|
.no_tda7432 = 1,
|
||||||
|
.tuner_type = -1,
|
||||||
|
.tuner_addr = ADDR_UNSET,
|
||||||
|
.radio_addr = ADDR_UNSET,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
|
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
|
||||||
@ -3037,26 +3056,33 @@ static void miro_pinnacle_gpio(struct bttv *btv)
|
|||||||
switch (id) {
|
switch (id) {
|
||||||
case 1:
|
case 1:
|
||||||
info = "PAL / mono";
|
info = "PAL / mono";
|
||||||
|
btv->tda9887_conf = TDA9887_INTERCARRIER;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
info = "PAL+SECAM / stereo";
|
info = "PAL+SECAM / stereo";
|
||||||
btv->has_radio = 1;
|
btv->has_radio = 1;
|
||||||
|
btv->tda9887_conf = TDA9887_QSS;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
info = "NTSC / stereo";
|
info = "NTSC / stereo";
|
||||||
btv->has_radio = 1;
|
btv->has_radio = 1;
|
||||||
|
btv->tda9887_conf = TDA9887_QSS;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
info = "PAL+SECAM / mono";
|
info = "PAL+SECAM / mono";
|
||||||
|
btv->tda9887_conf = TDA9887_QSS;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
info = "NTSC / mono";
|
info = "NTSC / mono";
|
||||||
|
btv->tda9887_conf = TDA9887_INTERCARRIER;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
info = "NTSC / stereo";
|
info = "NTSC / stereo";
|
||||||
|
btv->tda9887_conf = TDA9887_INTERCARRIER;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
info = "PAL / stereo";
|
info = "PAL / stereo";
|
||||||
|
btv->tda9887_conf = TDA9887_INTERCARRIER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
info = "oops: unknown card";
|
info = "oops: unknown card";
|
||||||
@ -3067,8 +3093,7 @@ static void miro_pinnacle_gpio(struct bttv *btv)
|
|||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
|
"bttv%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
|
||||||
btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
|
btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
|
||||||
btv->tuner_type = 33;
|
btv->tuner_type = TUNER_MT2032;
|
||||||
btv->pinnacle_id = id;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3370,9 +3395,9 @@ void __devinit bttv_init_card2(struct bttv *btv)
|
|||||||
bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup);
|
bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btv->pinnacle_id != UNSET) {
|
if (btv->tda9887_conf) {
|
||||||
bttv_call_i2c_clients(btv, AUDC_CONFIG_PINNACLE,
|
bttv_call_i2c_clients(btv, TDA9887_SET_CONFIG,
|
||||||
&btv->pinnacle_id);
|
&btv->tda9887_conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
btv->svhs = bttv_tvcards[btv->c.type].svhs;
|
btv->svhs = bttv_tvcards[btv->c.type].svhs;
|
||||||
@ -3387,8 +3412,6 @@ void __devinit bttv_init_card2(struct bttv *btv)
|
|||||||
btv->has_remote=1;
|
btv->has_remote=1;
|
||||||
if (!bttv_tvcards[btv->c.type].no_gpioirq)
|
if (!bttv_tvcards[btv->c.type].no_gpioirq)
|
||||||
btv->gpioirq=1;
|
btv->gpioirq=1;
|
||||||
if (bttv_tvcards[btv->c.type].any_irq)
|
|
||||||
btv->any_irq = 1;
|
|
||||||
if (bttv_tvcards[btv->c.type].audio_hook)
|
if (bttv_tvcards[btv->c.type].audio_hook)
|
||||||
btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook;
|
btv->audio_hook=bttv_tvcards[btv->c.type].audio_hook;
|
||||||
|
|
||||||
@ -3424,7 +3447,7 @@ void __devinit bttv_init_card2(struct bttv *btv)
|
|||||||
|
|
||||||
/* tuner modules */
|
/* tuner modules */
|
||||||
tda9887 = 0;
|
tda9887 = 0;
|
||||||
if (btv->pinnacle_id != UNSET)
|
if (btv->tda9887_conf)
|
||||||
tda9887 = 1;
|
tda9887 = 1;
|
||||||
if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb &&
|
if (0 == tda9887 && 0 == bttv_tvcards[btv->c.type].has_dvb &&
|
||||||
bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0)
|
bttv_I2CRead(btv, I2C_TDA9887, "TDA9887") >=0)
|
||||||
@ -3471,6 +3494,21 @@ static void __devinit hauppauge_eeprom(struct bttv *btv)
|
|||||||
tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data);
|
tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data);
|
||||||
btv->tuner_type = tv.tuner_type;
|
btv->tuner_type = tv.tuner_type;
|
||||||
btv->has_radio = tv.has_radio;
|
btv->has_radio = tv.has_radio;
|
||||||
|
|
||||||
|
printk("bttv%d: Hauppauge eeprom indicates model#%d\n",
|
||||||
|
btv->c.nr, tv.model);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some of the 878 boards have duplicate PCI IDs. Switch the board
|
||||||
|
* type based on model #.
|
||||||
|
*/
|
||||||
|
if(tv.model == 64900) {
|
||||||
|
printk("bttv%d: Switching board type from %s to %s\n",
|
||||||
|
btv->c.nr,
|
||||||
|
bttv_tvcards[btv->c.type].name,
|
||||||
|
bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name);
|
||||||
|
btv->c.type = BTTV_BOARD_HAUPPAUGE_IMPACTVCB;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int terratec_active_radio_upgrade(struct bttv *btv)
|
static int terratec_active_radio_upgrade(struct bttv *btv)
|
||||||
|
@ -34,13 +34,14 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/kdev_t.h>
|
#include <linux/kdev_t.h>
|
||||||
|
#include "bttvp.h"
|
||||||
|
#include <media/v4l2-common.h>
|
||||||
|
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
#include "bttvp.h"
|
|
||||||
|
|
||||||
#include "rds.h"
|
#include "rds.h"
|
||||||
|
|
||||||
|
|
||||||
@ -210,6 +211,9 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
|
|||||||
.vdelay = 0x20,
|
.vdelay = 0x20,
|
||||||
.vbipack = 255,
|
.vbipack = 255,
|
||||||
.sram = 0,
|
.sram = 0,
|
||||||
|
/* ITU-R frame line number of the first VBI line
|
||||||
|
we can capture, of the first and second field. */
|
||||||
|
.vbistart = { 7,320 },
|
||||||
},{
|
},{
|
||||||
.v4l2_id = V4L2_STD_NTSC_M,
|
.v4l2_id = V4L2_STD_NTSC_M,
|
||||||
.name = "NTSC",
|
.name = "NTSC",
|
||||||
@ -226,6 +230,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
|
|||||||
.vdelay = 0x1a,
|
.vdelay = 0x1a,
|
||||||
.vbipack = 144,
|
.vbipack = 144,
|
||||||
.sram = 1,
|
.sram = 1,
|
||||||
|
.vbistart = { 10, 273 },
|
||||||
},{
|
},{
|
||||||
.v4l2_id = V4L2_STD_SECAM,
|
.v4l2_id = V4L2_STD_SECAM,
|
||||||
.name = "SECAM",
|
.name = "SECAM",
|
||||||
@ -242,6 +247,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
|
|||||||
.vdelay = 0x20,
|
.vdelay = 0x20,
|
||||||
.vbipack = 255,
|
.vbipack = 255,
|
||||||
.sram = 0, /* like PAL, correct? */
|
.sram = 0, /* like PAL, correct? */
|
||||||
|
.vbistart = { 7, 320 },
|
||||||
},{
|
},{
|
||||||
.v4l2_id = V4L2_STD_PAL_Nc,
|
.v4l2_id = V4L2_STD_PAL_Nc,
|
||||||
.name = "PAL-Nc",
|
.name = "PAL-Nc",
|
||||||
@ -258,6 +264,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
|
|||||||
.vdelay = 0x1a,
|
.vdelay = 0x1a,
|
||||||
.vbipack = 144,
|
.vbipack = 144,
|
||||||
.sram = -1,
|
.sram = -1,
|
||||||
|
.vbistart = { 7, 320 },
|
||||||
},{
|
},{
|
||||||
.v4l2_id = V4L2_STD_PAL_M,
|
.v4l2_id = V4L2_STD_PAL_M,
|
||||||
.name = "PAL-M",
|
.name = "PAL-M",
|
||||||
@ -274,6 +281,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
|
|||||||
.vdelay = 0x1a,
|
.vdelay = 0x1a,
|
||||||
.vbipack = 144,
|
.vbipack = 144,
|
||||||
.sram = -1,
|
.sram = -1,
|
||||||
|
.vbistart = { 10, 273 },
|
||||||
},{
|
},{
|
||||||
.v4l2_id = V4L2_STD_PAL_N,
|
.v4l2_id = V4L2_STD_PAL_N,
|
||||||
.name = "PAL-N",
|
.name = "PAL-N",
|
||||||
@ -290,6 +298,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
|
|||||||
.vdelay = 0x20,
|
.vdelay = 0x20,
|
||||||
.vbipack = 144,
|
.vbipack = 144,
|
||||||
.sram = -1,
|
.sram = -1,
|
||||||
|
.vbistart = { 7, 320},
|
||||||
},{
|
},{
|
||||||
.v4l2_id = V4L2_STD_NTSC_M_JP,
|
.v4l2_id = V4L2_STD_NTSC_M_JP,
|
||||||
.name = "NTSC-JP",
|
.name = "NTSC-JP",
|
||||||
@ -306,6 +315,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
|
|||||||
.vdelay = 0x16,
|
.vdelay = 0x16,
|
||||||
.vbipack = 144,
|
.vbipack = 144,
|
||||||
.sram = -1,
|
.sram = -1,
|
||||||
|
.vbistart = {10, 273},
|
||||||
},{
|
},{
|
||||||
/* that one hopefully works with the strange timing
|
/* that one hopefully works with the strange timing
|
||||||
* which video recorders produce when playing a NTSC
|
* which video recorders produce when playing a NTSC
|
||||||
@ -326,6 +336,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
|
|||||||
.vbipack = 255,
|
.vbipack = 255,
|
||||||
.vtotal = 524,
|
.vtotal = 524,
|
||||||
.sram = -1,
|
.sram = -1,
|
||||||
|
.vbistart = { 10, 273 },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
|
static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
|
||||||
@ -1510,14 +1521,6 @@ static struct videobuf_queue_ops bttv_video_qops = {
|
|||||||
.buf_release = buffer_release,
|
.buf_release = buffer_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *v4l1_ioctls[] = {
|
|
||||||
"?", "CGAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
|
|
||||||
"CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
|
|
||||||
"SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
|
|
||||||
"GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
|
|
||||||
"SMICROCODE", "GVBIFMT", "SVBIFMT" };
|
|
||||||
#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
|
|
||||||
|
|
||||||
static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
|
static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
|
||||||
{
|
{
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
@ -2206,22 +2209,9 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
if (bttv_debug > 1) {
|
if (bttv_debug > 1)
|
||||||
switch (_IOC_TYPE(cmd)) {
|
v4l_print_ioctl(btv->c.name, cmd);
|
||||||
case 'v':
|
|
||||||
printk("bttv%d: ioctl 0x%x (v4l1, VIDIOC%s)\n",
|
|
||||||
btv->c.nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
|
|
||||||
v4l1_ioctls[_IOC_NR(cmd)] : "???");
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
printk("bttv%d: ioctl 0x%x (v4l2, %s)\n",
|
|
||||||
btv->c.nr, cmd, v4l2_ioctl_names[_IOC_NR(cmd)]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printk("bttv%d: ioctl 0x%x (???)\n",
|
|
||||||
btv->c.nr, cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (btv->errors)
|
if (btv->errors)
|
||||||
bttv_reinit_bt848(btv);
|
bttv_reinit_bt848(btv);
|
||||||
|
|
||||||
@ -2570,10 +2560,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
|
|||||||
fmt->count[0] = fmt2.fmt.vbi.count[0];
|
fmt->count[0] = fmt2.fmt.vbi.count[0];
|
||||||
fmt->start[1] = fmt2.fmt.vbi.start[1];
|
fmt->start[1] = fmt2.fmt.vbi.start[1];
|
||||||
fmt->count[1] = fmt2.fmt.vbi.count[1];
|
fmt->count[1] = fmt2.fmt.vbi.count[1];
|
||||||
if (fmt2.fmt.vbi.flags & VBI_UNSYNC)
|
if (fmt2.fmt.vbi.flags & V4L2_VBI_UNSYNC)
|
||||||
fmt->flags |= V4L2_VBI_UNSYNC;
|
fmt->flags |= VBI_UNSYNC;
|
||||||
if (fmt2.fmt.vbi.flags & VBI_INTERLACED)
|
if (fmt2.fmt.vbi.flags & V4L2_VBI_INTERLACED)
|
||||||
fmt->flags |= V4L2_VBI_INTERLACED;
|
fmt->flags |= VBI_INTERLACED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case VIDIOCSVBIFMT:
|
case VIDIOCSVBIFMT:
|
||||||
@ -3120,6 +3110,7 @@ static struct file_operations bttv_fops =
|
|||||||
.open = bttv_open,
|
.open = bttv_open,
|
||||||
.release = bttv_release,
|
.release = bttv_release,
|
||||||
.ioctl = bttv_ioctl,
|
.ioctl = bttv_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
.read = bttv_read,
|
.read = bttv_read,
|
||||||
.mmap = bttv_mmap,
|
.mmap = bttv_mmap,
|
||||||
@ -3229,6 +3220,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
|
|||||||
case VIDIOCSFREQ:
|
case VIDIOCSFREQ:
|
||||||
case VIDIOCGAUDIO:
|
case VIDIOCGAUDIO:
|
||||||
case VIDIOCSAUDIO:
|
case VIDIOCSAUDIO:
|
||||||
|
case VIDIOC_LOG_STATUS:
|
||||||
return bttv_common_ioctls(btv,cmd,arg);
|
return bttv_common_ioctls(btv,cmd,arg);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -3701,8 +3693,8 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
|
|||||||
|
|
||||||
btv=(struct bttv *)dev_id;
|
btv=(struct bttv *)dev_id;
|
||||||
|
|
||||||
if (btv->any_irq)
|
if (btv->custom_irq)
|
||||||
handled = bttv_any_irq(&btv->c);
|
handled = btv->custom_irq(btv);
|
||||||
|
|
||||||
count=0;
|
count=0;
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -3738,9 +3730,9 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
|
|||||||
if (astat&BT848_INT_VSYNC)
|
if (astat&BT848_INT_VSYNC)
|
||||||
btv->field_count++;
|
btv->field_count++;
|
||||||
|
|
||||||
if (astat & BT848_INT_GPINT) {
|
if ((astat & BT848_INT_GPINT) && btv->remote) {
|
||||||
wake_up(&btv->gpioq);
|
wake_up(&btv->gpioq);
|
||||||
bttv_gpio_irq(&btv->c);
|
bttv_input_irq(btv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (astat & BT848_INT_I2CDONE) {
|
if (astat & BT848_INT_I2CDONE) {
|
||||||
@ -3946,7 +3938,6 @@ static int __devinit bttv_probe(struct pci_dev *dev,
|
|||||||
|
|
||||||
btv->i2c_rc = -1;
|
btv->i2c_rc = -1;
|
||||||
btv->tuner_type = UNSET;
|
btv->tuner_type = UNSET;
|
||||||
btv->pinnacle_id = UNSET;
|
|
||||||
btv->new_input = UNSET;
|
btv->new_input = UNSET;
|
||||||
btv->has_radio=radio[btv->c.nr];
|
btv->has_radio=radio[btv->c.nr];
|
||||||
|
|
||||||
@ -4065,11 +4056,11 @@ static int __devinit bttv_probe(struct pci_dev *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* add subdevices */
|
/* add subdevices */
|
||||||
if (btv->has_remote)
|
|
||||||
bttv_sub_add_device(&btv->c, "remote");
|
|
||||||
if (bttv_tvcards[btv->c.type].has_dvb)
|
if (bttv_tvcards[btv->c.type].has_dvb)
|
||||||
bttv_sub_add_device(&btv->c, "dvb");
|
bttv_sub_add_device(&btv->c, "dvb");
|
||||||
|
|
||||||
|
bttv_input_init(btv);
|
||||||
|
|
||||||
/* everything is fine */
|
/* everything is fine */
|
||||||
bttv_num++;
|
bttv_num++;
|
||||||
return 0;
|
return 0;
|
||||||
@ -4104,6 +4095,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev)
|
|||||||
/* tell gpio modules we are leaving ... */
|
/* tell gpio modules we are leaving ... */
|
||||||
btv->shutdown=1;
|
btv->shutdown=1;
|
||||||
wake_up(&btv->gpioq);
|
wake_up(&btv->gpioq);
|
||||||
|
bttv_input_fini(btv);
|
||||||
bttv_sub_del_devices(&btv->c);
|
bttv_sub_del_devices(&btv->c);
|
||||||
|
|
||||||
/* unregister i2c_bus + input */
|
/* unregister i2c_bus + input */
|
||||||
@ -4253,7 +4245,7 @@ static int bttv_init_module(void)
|
|||||||
bttv_check_chipset();
|
bttv_check_chipset();
|
||||||
|
|
||||||
bus_register(&bttv_sub_bus_type);
|
bus_register(&bttv_sub_bus_type);
|
||||||
return pci_module_init(&bttv_pci_driver);
|
return pci_register_driver(&bttv_pci_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bttv_cleanup_module(void)
|
static void bttv_cleanup_module(void)
|
||||||
|
@ -113,24 +113,6 @@ void bttv_gpio_irq(struct bttv_core *core)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int bttv_any_irq(struct bttv_core *core)
|
|
||||||
{
|
|
||||||
struct bttv_sub_driver *drv;
|
|
||||||
struct bttv_sub_device *dev;
|
|
||||||
struct list_head *item;
|
|
||||||
int handled = 0;
|
|
||||||
|
|
||||||
list_for_each(item,&core->subs) {
|
|
||||||
dev = list_entry(item,struct bttv_sub_device,list);
|
|
||||||
drv = to_bttv_sub_drv(dev->dev.driver);
|
|
||||||
if (drv && drv->any_irq) {
|
|
||||||
if (drv->any_irq(dev))
|
|
||||||
handled = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
/* external: sub-driver register/unregister */
|
/* external: sub-driver register/unregister */
|
||||||
|
|
||||||
|
@ -28,10 +28,11 @@
|
|||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/jiffies.h>
|
|
||||||
#include <asm/io.h>
|
|
||||||
|
|
||||||
#include "bttvp.h"
|
#include "bttvp.h"
|
||||||
|
#include <media/v4l2-common.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
static struct i2c_algo_bit_data bttv_i2c_algo_bit_template;
|
static struct i2c_algo_bit_data bttv_i2c_algo_bit_template;
|
||||||
static struct i2c_adapter bttv_i2c_adap_sw_template;
|
static struct i2c_adapter bttv_i2c_adap_sw_template;
|
||||||
@ -105,10 +106,8 @@ static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
|
|||||||
|
|
||||||
static struct i2c_adapter bttv_i2c_adap_sw_template = {
|
static struct i2c_adapter bttv_i2c_adap_sw_template = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
#ifdef I2C_CLASS_TV_ANALOG
|
|
||||||
.class = I2C_CLASS_TV_ANALOG,
|
.class = I2C_CLASS_TV_ANALOG,
|
||||||
#endif
|
.name = "bttv",
|
||||||
.name = "bt848",
|
|
||||||
.id = I2C_HW_B_BT848,
|
.id = I2C_HW_B_BT848,
|
||||||
.client_register = attach_inform,
|
.client_register = attach_inform,
|
||||||
};
|
};
|
||||||
@ -276,9 +275,7 @@ static struct i2c_algorithm bttv_algo = {
|
|||||||
|
|
||||||
static struct i2c_adapter bttv_i2c_adap_hw_template = {
|
static struct i2c_adapter bttv_i2c_adap_hw_template = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
#ifdef I2C_CLASS_TV_ANALOG
|
|
||||||
.class = I2C_CLASS_TV_ANALOG,
|
.class = I2C_CLASS_TV_ANALOG,
|
||||||
#endif
|
|
||||||
.name = "bt878",
|
.name = "bt878",
|
||||||
.id = I2C_HW_B_BT848 /* FIXME */,
|
.id = I2C_HW_B_BT848 /* FIXME */,
|
||||||
.algo = &bttv_algo,
|
.algo = &bttv_algo,
|
||||||
@ -441,12 +438,10 @@ int __devinit init_bttv_i2c(struct bttv *btv)
|
|||||||
i2c_set_adapdata(&btv->c.i2c_adap, btv);
|
i2c_set_adapdata(&btv->c.i2c_adap, btv);
|
||||||
btv->i2c_client.adapter = &btv->c.i2c_adap;
|
btv->i2c_client.adapter = &btv->c.i2c_adap;
|
||||||
|
|
||||||
#ifdef I2C_CLASS_TV_ANALOG
|
|
||||||
if (bttv_tvcards[btv->c.type].no_video)
|
if (bttv_tvcards[btv->c.type].no_video)
|
||||||
btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG;
|
btv->c.i2c_adap.class &= ~I2C_CLASS_TV_ANALOG;
|
||||||
if (bttv_tvcards[btv->c.type].has_dvb)
|
if (bttv_tvcards[btv->c.type].has_dvb)
|
||||||
btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
|
btv->c.i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (btv->use_i2c_hw) {
|
if (btv->use_i2c_hw) {
|
||||||
btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
|
btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
|
||||||
|
@ -24,11 +24,9 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/pci.h>
|
|
||||||
|
|
||||||
#include <media/ir-common.h>
|
|
||||||
|
|
||||||
#include "bttv.h"
|
#include "bttv.h"
|
||||||
|
#include "bttvp.h"
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
@ -156,9 +154,6 @@ static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* Ricardo Cerqueira <v4l@cerqueira.org> */
|
|
||||||
/* Weird matching, since the remote has "uncommon" keys */
|
|
||||||
|
|
||||||
static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = {
|
static IR_KEYTAB_TYPE ir_codes_conceptronic[IR_KEYTAB_SIZE] = {
|
||||||
|
|
||||||
[ 30 ] = KEY_POWER, // power
|
[ 30 ] = KEY_POWER, // power
|
||||||
@ -279,34 +274,6 @@ static IR_KEYTAB_TYPE ir_codes_nebula[IR_KEYTAB_SIZE] = {
|
|||||||
[0x36] = KEY_PC
|
[0x36] = KEY_PC
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IR {
|
|
||||||
struct bttv_sub_device *sub;
|
|
||||||
struct input_dev *input;
|
|
||||||
struct ir_input_state ir;
|
|
||||||
char name[32];
|
|
||||||
char phys[32];
|
|
||||||
|
|
||||||
/* Usual gpio signalling */
|
|
||||||
|
|
||||||
u32 mask_keycode;
|
|
||||||
u32 mask_keydown;
|
|
||||||
u32 mask_keyup;
|
|
||||||
u32 polling;
|
|
||||||
u32 last_gpio;
|
|
||||||
struct work_struct work;
|
|
||||||
struct timer_list timer;
|
|
||||||
|
|
||||||
/* RC5 gpio */
|
|
||||||
u32 rc5_gpio;
|
|
||||||
struct timer_list timer_end; /* timer_end for code completion */
|
|
||||||
struct timer_list timer_keyup; /* timer_end for key release */
|
|
||||||
u32 last_rc5; /* last good rc5 code */
|
|
||||||
u32 last_bit; /* last raw bit seen */
|
|
||||||
u32 code; /* raw code under construction */
|
|
||||||
struct timeval base_time; /* time of last seen code */
|
|
||||||
int active; /* building raw code */
|
|
||||||
};
|
|
||||||
|
|
||||||
static int debug;
|
static int debug;
|
||||||
module_param(debug, int, 0644); /* debug level (0,1,2) */
|
module_param(debug, int, 0644); /* debug level (0,1,2) */
|
||||||
static int repeat_delay = 500;
|
static int repeat_delay = 500;
|
||||||
@ -314,31 +281,17 @@ module_param(repeat_delay, int, 0644);
|
|||||||
static int repeat_period = 33;
|
static int repeat_period = 33;
|
||||||
module_param(repeat_period, int, 0644);
|
module_param(repeat_period, int, 0644);
|
||||||
|
|
||||||
#define DEVNAME "ir-kbd-gpio"
|
#define DEVNAME "bttv-input"
|
||||||
#define dprintk(fmt, arg...) if (debug) \
|
|
||||||
printk(KERN_DEBUG DEVNAME ": " fmt , ## arg)
|
|
||||||
|
|
||||||
static void ir_irq(struct bttv_sub_device *sub);
|
|
||||||
static int ir_probe(struct device *dev);
|
|
||||||
static int ir_remove(struct device *dev);
|
|
||||||
|
|
||||||
static struct bttv_sub_driver driver = {
|
|
||||||
.drv = {
|
|
||||||
.name = DEVNAME,
|
|
||||||
.probe = ir_probe,
|
|
||||||
.remove = ir_remove,
|
|
||||||
},
|
|
||||||
.gpio_irq = ir_irq,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void ir_handle_key(struct IR *ir)
|
static void ir_handle_key(struct bttv *btv)
|
||||||
{
|
{
|
||||||
|
struct bttv_ir *ir = btv->remote;
|
||||||
u32 gpio,data;
|
u32 gpio,data;
|
||||||
|
|
||||||
/* read gpio value */
|
/* read gpio value */
|
||||||
gpio = bttv_gpio_read(ir->sub->core);
|
gpio = bttv_gpio_read(&btv->c);
|
||||||
if (ir->polling) {
|
if (ir->polling) {
|
||||||
if (ir->last_gpio == gpio)
|
if (ir->last_gpio == gpio)
|
||||||
return;
|
return;
|
||||||
@ -347,56 +300,36 @@ static void ir_handle_key(struct IR *ir)
|
|||||||
|
|
||||||
/* extract data */
|
/* extract data */
|
||||||
data = ir_extract_bits(gpio, ir->mask_keycode);
|
data = ir_extract_bits(gpio, ir->mask_keycode);
|
||||||
dprintk(DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
|
dprintk(KERN_INFO DEVNAME ": irq gpio=0x%x code=%d | %s%s%s\n",
|
||||||
gpio, data,
|
gpio, data,
|
||||||
ir->polling ? "poll" : "irq",
|
ir->polling ? "poll" : "irq",
|
||||||
(gpio & ir->mask_keydown) ? " down" : "",
|
(gpio & ir->mask_keydown) ? " down" : "",
|
||||||
(gpio & ir->mask_keyup) ? " up" : "");
|
(gpio & ir->mask_keyup) ? " up" : "");
|
||||||
|
|
||||||
if (ir->mask_keydown) {
|
if ((ir->mask_keydown && (0 != (gpio & ir->mask_keydown))) ||
|
||||||
/* bit set on keydown */
|
(ir->mask_keyup && (0 == (gpio & ir->mask_keyup)))) {
|
||||||
if (gpio & ir->mask_keydown) {
|
ir_input_keydown(ir->dev,&ir->ir,data,data);
|
||||||
ir_input_keydown(ir->input, &ir->ir, data, data);
|
|
||||||
} else {
|
} else {
|
||||||
ir_input_nokey(ir->input, &ir->ir);
|
ir_input_nokey(ir->dev,&ir->ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (ir->mask_keyup) {
|
|
||||||
/* bit cleared on keydown */
|
|
||||||
if (0 == (gpio & ir->mask_keyup)) {
|
|
||||||
ir_input_keydown(ir->input, &ir->ir, data, data);
|
|
||||||
} else {
|
|
||||||
ir_input_nokey(ir->input, &ir->ir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
void bttv_input_irq(struct bttv *btv)
|
||||||
/* can't disturgissh keydown/up :-/ */
|
|
||||||
ir_input_keydown(ir->input, &ir->ir, data, data);
|
|
||||||
ir_input_nokey(ir->input, &ir->ir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ir_irq(struct bttv_sub_device *sub)
|
|
||||||
{
|
{
|
||||||
struct IR *ir = dev_get_drvdata(&sub->dev);
|
struct bttv_ir *ir = btv->remote;
|
||||||
|
|
||||||
if (!ir->polling)
|
if (!ir->polling)
|
||||||
ir_handle_key(ir);
|
ir_handle_key(btv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ir_timer(unsigned long data)
|
static void bttv_input_timer(unsigned long data)
|
||||||
{
|
{
|
||||||
struct IR *ir = (struct IR*)data;
|
struct bttv *btv = (struct bttv*)data;
|
||||||
|
struct bttv_ir *ir = btv->remote;
|
||||||
schedule_work(&ir->work);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ir_work(void *data)
|
|
||||||
{
|
|
||||||
struct IR *ir = data;
|
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
ir_handle_key(ir);
|
ir_handle_key(btv);
|
||||||
timeout = jiffies + (ir->polling * HZ / 1000);
|
timeout = jiffies + (ir->polling * HZ / 1000);
|
||||||
mod_timer(&ir->timer, timeout);
|
mod_timer(&ir->timer, timeout);
|
||||||
}
|
}
|
||||||
@ -435,26 +368,26 @@ static u32 rc5_decode(unsigned int code)
|
|||||||
rc5 |= 1;
|
rc5 |= 1;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
dprintk("bad code: %x\n", org_code);
|
dprintk(KERN_WARNING "bad code: %x\n", org_code);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
|
dprintk(KERN_WARNING "code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
|
||||||
"instr=%x\n", rc5, org_code, RC5_START(rc5),
|
"instr=%x\n", rc5, org_code, RC5_START(rc5),
|
||||||
RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
|
RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
|
||||||
return rc5;
|
return rc5;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ir_rc5_irq(struct bttv_sub_device *sub)
|
static int bttv_rc5_irq(struct bttv *btv)
|
||||||
{
|
{
|
||||||
struct IR *ir = dev_get_drvdata(&sub->dev);
|
struct bttv_ir *ir = btv->remote;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
u32 gpio;
|
u32 gpio;
|
||||||
u32 gap;
|
u32 gap;
|
||||||
unsigned long current_jiffies, timeout;
|
unsigned long current_jiffies, timeout;
|
||||||
|
|
||||||
/* read gpio port */
|
/* read gpio port */
|
||||||
gpio = bttv_gpio_read(ir->sub->core);
|
gpio = bttv_gpio_read(&btv->c);
|
||||||
|
|
||||||
/* remote IRQ? */
|
/* remote IRQ? */
|
||||||
if (!(gpio & 0x20))
|
if (!(gpio & 0x20))
|
||||||
@ -493,14 +426,15 @@ static int ir_rc5_irq(struct bttv_sub_device *sub)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* toggle GPIO pin 4 to reset the irq */
|
/* toggle GPIO pin 4 to reset the irq */
|
||||||
bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4));
|
bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
|
||||||
bttv_gpio_write(ir->sub->core, gpio | (1 << 4));
|
bttv_gpio_write(&btv->c, gpio | (1 << 4));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ir_rc5_timer_end(unsigned long data)
|
|
||||||
|
static void bttv_rc5_timer_end(unsigned long data)
|
||||||
{
|
{
|
||||||
struct IR *ir = (struct IR *)data;
|
struct bttv_ir *ir = (struct bttv_ir *)data;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
unsigned long current_jiffies, timeout;
|
unsigned long current_jiffies, timeout;
|
||||||
u32 gap;
|
u32 gap;
|
||||||
@ -519,20 +453,20 @@ static void ir_rc5_timer_end(unsigned long data)
|
|||||||
|
|
||||||
/* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
|
/* Allow some timmer jitter (RC5 is ~24ms anyway so this is ok) */
|
||||||
if (gap < 28000) {
|
if (gap < 28000) {
|
||||||
dprintk("spurious timer_end\n");
|
dprintk(KERN_WARNING "spurious timer_end\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ir->active = 0;
|
ir->active = 0;
|
||||||
if (ir->last_bit < 20) {
|
if (ir->last_bit < 20) {
|
||||||
/* ignore spurious codes (caused by light/other remotes) */
|
/* ignore spurious codes (caused by light/other remotes) */
|
||||||
dprintk("short code: %x\n", ir->code);
|
dprintk(KERN_WARNING "short code: %x\n", ir->code);
|
||||||
} else {
|
} else {
|
||||||
u32 rc5 = rc5_decode(ir->code);
|
u32 rc5 = rc5_decode(ir->code);
|
||||||
|
|
||||||
/* two start bits? */
|
/* two start bits? */
|
||||||
if (RC5_START(rc5) != 3) {
|
if (RC5_START(rc5) != 3) {
|
||||||
dprintk("rc5 start bits invalid: %u\n", RC5_START(rc5));
|
dprintk(KERN_WARNING "rc5 start bits invalid: %u\n", RC5_START(rc5));
|
||||||
|
|
||||||
/* right address? */
|
/* right address? */
|
||||||
} else if (RC5_ADDR(rc5) == 0x0) {
|
} else if (RC5_ADDR(rc5) == 0x0) {
|
||||||
@ -542,10 +476,10 @@ static void ir_rc5_timer_end(unsigned long data)
|
|||||||
/* Good code, decide if repeat/repress */
|
/* Good code, decide if repeat/repress */
|
||||||
if (toggle != RC5_TOGGLE(ir->last_rc5) ||
|
if (toggle != RC5_TOGGLE(ir->last_rc5) ||
|
||||||
instr != RC5_INSTR(ir->last_rc5)) {
|
instr != RC5_INSTR(ir->last_rc5)) {
|
||||||
dprintk("instruction %x, toggle %x\n", instr,
|
dprintk(KERN_WARNING "instruction %x, toggle %x\n", instr,
|
||||||
toggle);
|
toggle);
|
||||||
ir_input_nokey(ir->input, &ir->ir);
|
ir_input_nokey(ir->dev, &ir->ir);
|
||||||
ir_input_keydown(ir->input, &ir->ir, instr,
|
ir_input_keydown(ir->dev, &ir->ir, instr,
|
||||||
instr);
|
instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,24 +494,26 @@ static void ir_rc5_timer_end(unsigned long data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ir_rc5_timer_keyup(unsigned long data)
|
static void bttv_rc5_timer_keyup(unsigned long data)
|
||||||
{
|
{
|
||||||
struct IR *ir = (struct IR *)data;
|
struct bttv_ir *ir = (struct bttv_ir *)data;
|
||||||
|
|
||||||
dprintk("key released\n");
|
dprintk(KERN_DEBUG "key released\n");
|
||||||
ir_input_nokey(ir->input, &ir->ir);
|
ir_input_nokey(ir->dev, &ir->ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int ir_probe(struct device *dev)
|
int bttv_input_init(struct bttv *btv)
|
||||||
{
|
{
|
||||||
struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
|
struct bttv_ir *ir;
|
||||||
struct IR *ir;
|
|
||||||
struct input_dev *input_dev;
|
|
||||||
IR_KEYTAB_TYPE *ir_codes = NULL;
|
IR_KEYTAB_TYPE *ir_codes = NULL;
|
||||||
|
struct input_dev *input_dev;
|
||||||
int ir_type = IR_TYPE_OTHER;
|
int ir_type = IR_TYPE_OTHER;
|
||||||
|
|
||||||
|
if (!btv->has_remote)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
ir = kzalloc(sizeof(*ir),GFP_KERNEL);
|
ir = kzalloc(sizeof(*ir),GFP_KERNEL);
|
||||||
input_dev = input_allocate_device();
|
input_dev = input_allocate_device();
|
||||||
if (!ir || !input_dev) {
|
if (!ir || !input_dev) {
|
||||||
@ -585,9 +521,10 @@ static int ir_probe(struct device *dev)
|
|||||||
input_free_device(input_dev);
|
input_free_device(input_dev);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
memset(ir,0,sizeof(*ir));
|
||||||
|
|
||||||
/* detect & configure */
|
/* detect & configure */
|
||||||
switch (sub->core->type) {
|
switch (btv->c.type) {
|
||||||
case BTTV_BOARD_AVERMEDIA:
|
case BTTV_BOARD_AVERMEDIA:
|
||||||
case BTTV_BOARD_AVPHONE98:
|
case BTTV_BOARD_AVPHONE98:
|
||||||
case BTTV_BOARD_AVERMEDIA98:
|
case BTTV_BOARD_AVERMEDIA98:
|
||||||
@ -643,12 +580,12 @@ static int ir_probe(struct device *dev)
|
|||||||
break;
|
break;
|
||||||
case BTTV_BOARD_NEBULA_DIGITV:
|
case BTTV_BOARD_NEBULA_DIGITV:
|
||||||
ir_codes = ir_codes_nebula;
|
ir_codes = ir_codes_nebula;
|
||||||
driver.any_irq = ir_rc5_irq;
|
btv->custom_irq = bttv_rc5_irq;
|
||||||
driver.gpio_irq = NULL;
|
|
||||||
ir->rc5_gpio = 1;
|
ir->rc5_gpio = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (NULL == ir_codes) {
|
if (NULL == ir_codes) {
|
||||||
|
dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type);
|
||||||
kfree(ir);
|
kfree(ir);
|
||||||
input_free_device(input_dev);
|
input_free_device(input_dev);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -657,109 +594,92 @@ static int ir_probe(struct device *dev)
|
|||||||
if (ir->rc5_gpio) {
|
if (ir->rc5_gpio) {
|
||||||
u32 gpio;
|
u32 gpio;
|
||||||
/* enable remote irq */
|
/* enable remote irq */
|
||||||
bttv_gpio_inout(sub->core, (1 << 4), 1 << 4);
|
bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4);
|
||||||
gpio = bttv_gpio_read(sub->core);
|
gpio = bttv_gpio_read(&btv->c);
|
||||||
bttv_gpio_write(sub->core, gpio & ~(1 << 4));
|
bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
|
||||||
bttv_gpio_write(sub->core, gpio | (1 << 4));
|
bttv_gpio_write(&btv->c, gpio | (1 << 4));
|
||||||
} else {
|
} else {
|
||||||
/* init hardware-specific stuff */
|
/* init hardware-specific stuff */
|
||||||
bttv_gpio_inout(sub->core, ir->mask_keycode | ir->mask_keydown, 0);
|
bttv_gpio_inout(&btv->c, ir->mask_keycode | ir->mask_keydown, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init input device */
|
/* init input device */
|
||||||
|
ir->dev = input_dev;
|
||||||
|
|
||||||
snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
|
snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
|
||||||
sub->core->type);
|
btv->c.type);
|
||||||
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
|
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
|
||||||
pci_name(sub->core->pci));
|
pci_name(btv->c.pci));
|
||||||
|
|
||||||
ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
|
ir_input_init(input_dev, &ir->ir, ir_type, ir_codes);
|
||||||
input_dev->name = ir->name;
|
input_dev->name = ir->name;
|
||||||
input_dev->phys = ir->phys;
|
input_dev->phys = ir->phys;
|
||||||
input_dev->id.bustype = BUS_PCI;
|
input_dev->id.bustype = BUS_PCI;
|
||||||
input_dev->id.version = 1;
|
input_dev->id.version = 1;
|
||||||
if (sub->core->pci->subsystem_vendor) {
|
if (btv->c.pci->subsystem_vendor) {
|
||||||
input_dev->id.vendor = sub->core->pci->subsystem_vendor;
|
input_dev->id.vendor = btv->c.pci->subsystem_vendor;
|
||||||
input_dev->id.product = sub->core->pci->subsystem_device;
|
input_dev->id.product = btv->c.pci->subsystem_device;
|
||||||
} else {
|
} else {
|
||||||
input_dev->id.vendor = sub->core->pci->vendor;
|
input_dev->id.vendor = btv->c.pci->vendor;
|
||||||
input_dev->id.product = sub->core->pci->device;
|
input_dev->id.product = btv->c.pci->device;
|
||||||
}
|
}
|
||||||
input_dev->cdev.dev = &sub->core->pci->dev;
|
input_dev->cdev.dev = &btv->c.pci->dev;
|
||||||
|
|
||||||
ir->input = input_dev;
|
|
||||||
ir->sub = sub;
|
|
||||||
|
|
||||||
|
btv->remote = ir;
|
||||||
if (ir->polling) {
|
if (ir->polling) {
|
||||||
INIT_WORK(&ir->work, ir_work, ir);
|
|
||||||
init_timer(&ir->timer);
|
init_timer(&ir->timer);
|
||||||
ir->timer.function = ir_timer;
|
ir->timer.function = bttv_input_timer;
|
||||||
ir->timer.data = (unsigned long)ir;
|
ir->timer.data = (unsigned long)btv;
|
||||||
schedule_work(&ir->work);
|
ir->timer.expires = jiffies + HZ;
|
||||||
|
add_timer(&ir->timer);
|
||||||
} else if (ir->rc5_gpio) {
|
} else if (ir->rc5_gpio) {
|
||||||
/* set timer_end for code completion */
|
/* set timer_end for code completion */
|
||||||
init_timer(&ir->timer_end);
|
init_timer(&ir->timer_end);
|
||||||
ir->timer_end.function = ir_rc5_timer_end;
|
ir->timer_end.function = bttv_rc5_timer_end;
|
||||||
ir->timer_end.data = (unsigned long)ir;
|
ir->timer_end.data = (unsigned long)ir;
|
||||||
|
|
||||||
init_timer(&ir->timer_keyup);
|
init_timer(&ir->timer_keyup);
|
||||||
ir->timer_keyup.function = ir_rc5_timer_keyup;
|
ir->timer_keyup.function = bttv_rc5_timer_keyup;
|
||||||
ir->timer_keyup.data = (unsigned long)ir;
|
ir->timer_keyup.data = (unsigned long)ir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* all done */
|
/* all done */
|
||||||
dev_set_drvdata(dev, ir);
|
input_register_device(btv->remote->dev);
|
||||||
input_register_device(ir->input);
|
printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys);
|
||||||
|
|
||||||
/* the remote isn't as bouncy as a keyboard */
|
/* the remote isn't as bouncy as a keyboard */
|
||||||
ir->input->rep[REP_DELAY] = repeat_delay;
|
ir->dev->rep[REP_DELAY] = repeat_delay;
|
||||||
ir->input->rep[REP_PERIOD] = repeat_period;
|
ir->dev->rep[REP_PERIOD] = repeat_period;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ir_remove(struct device *dev)
|
void bttv_input_fini(struct bttv *btv)
|
||||||
{
|
{
|
||||||
struct IR *ir = dev_get_drvdata(dev);
|
if (btv->remote == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
if (ir->polling) {
|
if (btv->remote->polling) {
|
||||||
del_timer(&ir->timer);
|
del_timer_sync(&btv->remote->timer);
|
||||||
flush_scheduled_work();
|
flush_scheduled_work();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ir->rc5_gpio) {
|
|
||||||
|
if (btv->remote->rc5_gpio) {
|
||||||
u32 gpio;
|
u32 gpio;
|
||||||
|
|
||||||
del_timer(&ir->timer_end);
|
del_timer_sync(&btv->remote->timer_end);
|
||||||
flush_scheduled_work();
|
flush_scheduled_work();
|
||||||
|
|
||||||
gpio = bttv_gpio_read(ir->sub->core);
|
gpio = bttv_gpio_read(&btv->c);
|
||||||
bttv_gpio_write(ir->sub->core, gpio & ~(1 << 4));
|
bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
input_unregister_device(ir->input);
|
input_unregister_device(btv->remote->dev);
|
||||||
kfree(ir);
|
kfree(btv->remote);
|
||||||
return 0;
|
btv->remote = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Gerd Knorr, Pavel Machek");
|
|
||||||
MODULE_DESCRIPTION("input driver for bt8x8 gpio IR remote controls");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
||||||
static int ir_init(void)
|
|
||||||
{
|
|
||||||
return bttv_sub_register(&driver, "remote");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ir_fini(void)
|
|
||||||
{
|
|
||||||
bttv_sub_unregister(&driver);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(ir_init);
|
|
||||||
module_exit(ir_fini);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local variables:
|
* Local variables:
|
@ -31,6 +31,12 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "bttvp.h"
|
#include "bttvp.h"
|
||||||
|
|
||||||
|
/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate:
|
||||||
|
bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC
|
||||||
|
HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge
|
||||||
|
of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */
|
||||||
|
#define VBI_OFFSET ((64 + 0) * 2)
|
||||||
|
|
||||||
#define VBI_DEFLINES 16
|
#define VBI_DEFLINES 16
|
||||||
#define VBI_MAXLINES 32
|
#define VBI_MAXLINES 32
|
||||||
|
|
||||||
@ -163,40 +169,30 @@ void bttv_vbi_setlines(struct bttv_fh *fh, struct bttv *btv, int lines)
|
|||||||
void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
|
void bttv_vbi_try_fmt(struct bttv_fh *fh, struct v4l2_format *f)
|
||||||
{
|
{
|
||||||
const struct bttv_tvnorm *tvnorm;
|
const struct bttv_tvnorm *tvnorm;
|
||||||
u32 start0,start1;
|
s64 count0,count1,count;
|
||||||
s32 count0,count1,count;
|
|
||||||
|
|
||||||
tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
|
tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
|
||||||
f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
|
f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
|
||||||
f->fmt.vbi.sampling_rate = tvnorm->Fsc;
|
f->fmt.vbi.sampling_rate = tvnorm->Fsc;
|
||||||
f->fmt.vbi.samples_per_line = 2048;
|
f->fmt.vbi.samples_per_line = 2048;
|
||||||
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
|
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
|
||||||
f->fmt.vbi.offset = 244;
|
f->fmt.vbi.offset = VBI_OFFSET;
|
||||||
f->fmt.vbi.flags = 0;
|
f->fmt.vbi.flags = 0;
|
||||||
switch (fh->btv->tvnorm) {
|
|
||||||
case 1: /* NTSC */
|
|
||||||
start0 = 10;
|
|
||||||
start1 = 273;
|
|
||||||
break;
|
|
||||||
case 0: /* PAL */
|
|
||||||
case 2: /* SECAM */
|
|
||||||
default:
|
|
||||||
start0 = 7;
|
|
||||||
start1 = 320;
|
|
||||||
}
|
|
||||||
|
|
||||||
count0 = (f->fmt.vbi.start[0] + f->fmt.vbi.count[0]) - start0;
|
/* s64 to prevent overflow. */
|
||||||
count1 = (f->fmt.vbi.start[1] + f->fmt.vbi.count[1]) - start1;
|
count0 = (s64) f->fmt.vbi.start[0] + f->fmt.vbi.count[0]
|
||||||
count = max(count0,count1);
|
- tvnorm->vbistart[0];
|
||||||
if (count > VBI_MAXLINES)
|
count1 = (s64) f->fmt.vbi.start[1] + f->fmt.vbi.count[1]
|
||||||
count = VBI_MAXLINES;
|
- tvnorm->vbistart[1];
|
||||||
if (count < 1)
|
count = clamp (max (count0, count1), 1LL, (s64) VBI_MAXLINES);
|
||||||
count = 1;
|
|
||||||
|
|
||||||
f->fmt.vbi.start[0] = start0;
|
f->fmt.vbi.start[0] = tvnorm->vbistart[0];
|
||||||
f->fmt.vbi.start[1] = start1;
|
f->fmt.vbi.start[1] = tvnorm->vbistart[1];
|
||||||
f->fmt.vbi.count[0] = count;
|
f->fmt.vbi.count[0] = count;
|
||||||
f->fmt.vbi.count[1] = count;
|
f->fmt.vbi.count[1] = count;
|
||||||
|
|
||||||
|
f->fmt.vbi.reserved[0] = 0;
|
||||||
|
f->fmt.vbi.reserved[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
|
void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
|
||||||
@ -209,21 +205,12 @@ void bttv_vbi_get_fmt(struct bttv_fh *fh, struct v4l2_format *f)
|
|||||||
f->fmt.vbi.sampling_rate = tvnorm->Fsc;
|
f->fmt.vbi.sampling_rate = tvnorm->Fsc;
|
||||||
f->fmt.vbi.samples_per_line = 2048;
|
f->fmt.vbi.samples_per_line = 2048;
|
||||||
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
|
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
|
||||||
f->fmt.vbi.offset = 244;
|
f->fmt.vbi.offset = VBI_OFFSET;
|
||||||
|
f->fmt.vbi.start[0] = tvnorm->vbistart[0];
|
||||||
|
f->fmt.vbi.start[1] = tvnorm->vbistart[1];
|
||||||
f->fmt.vbi.count[0] = fh->lines;
|
f->fmt.vbi.count[0] = fh->lines;
|
||||||
f->fmt.vbi.count[1] = fh->lines;
|
f->fmt.vbi.count[1] = fh->lines;
|
||||||
f->fmt.vbi.flags = 0;
|
f->fmt.vbi.flags = 0;
|
||||||
switch (fh->btv->tvnorm) {
|
|
||||||
case 1: /* NTSC */
|
|
||||||
f->fmt.vbi.start[0] = 10;
|
|
||||||
f->fmt.vbi.start[1] = 273;
|
|
||||||
break;
|
|
||||||
case 0: /* PAL */
|
|
||||||
case 2: /* SECAM */
|
|
||||||
default:
|
|
||||||
f->fmt.vbi.start[0] = 7;
|
|
||||||
f->fmt.vbi.start[1] = 319;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
#include <linux/videodev.h>
|
#include <linux/videodev.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
|
#include <media/ir-common.h>
|
||||||
|
#include <media/ir-kbd-i2c.h>
|
||||||
|
|
||||||
/* ---------------------------------------------------------- */
|
/* ---------------------------------------------------------- */
|
||||||
/* exported by bttv-cards.c */
|
/* exported by bttv-cards.c */
|
||||||
@ -163,6 +165,7 @@
|
|||||||
#define BTTV_BOARD_OSPREY440 0x8c
|
#define BTTV_BOARD_OSPREY440 0x8c
|
||||||
#define BTTV_BOARD_ASOUND_SKYEYE 0x8d
|
#define BTTV_BOARD_ASOUND_SKYEYE 0x8d
|
||||||
#define BTTV_BOARD_SABRENT_TVFM 0x8e
|
#define BTTV_BOARD_SABRENT_TVFM 0x8e
|
||||||
|
#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB 0x8f
|
||||||
|
|
||||||
/* i2c address list */
|
/* i2c address list */
|
||||||
#define I2C_TSA5522 0xc2
|
#define I2C_TSA5522 0xc2
|
||||||
@ -210,6 +213,34 @@ struct bttv_core {
|
|||||||
|
|
||||||
struct bttv;
|
struct bttv;
|
||||||
|
|
||||||
|
|
||||||
|
struct bttv_ir {
|
||||||
|
struct input_dev *dev;
|
||||||
|
struct ir_input_state ir;
|
||||||
|
char name[32];
|
||||||
|
char phys[32];
|
||||||
|
|
||||||
|
/* Usual gpio signalling */
|
||||||
|
|
||||||
|
u32 mask_keycode;
|
||||||
|
u32 mask_keydown;
|
||||||
|
u32 mask_keyup;
|
||||||
|
u32 polling;
|
||||||
|
u32 last_gpio;
|
||||||
|
struct work_struct work;
|
||||||
|
struct timer_list timer;
|
||||||
|
|
||||||
|
/* RC5 gpio */
|
||||||
|
u32 rc5_gpio;
|
||||||
|
struct timer_list timer_end; /* timer_end for code completion */
|
||||||
|
struct timer_list timer_keyup; /* timer_end for key release */
|
||||||
|
u32 last_rc5; /* last good rc5 code */
|
||||||
|
u32 last_bit; /* last raw bit seen */
|
||||||
|
u32 code; /* raw code under construction */
|
||||||
|
struct timeval base_time; /* time of last seen code */
|
||||||
|
int active; /* building raw code */
|
||||||
|
};
|
||||||
|
|
||||||
struct tvcard
|
struct tvcard
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
@ -235,7 +266,6 @@ struct tvcard
|
|||||||
unsigned int has_dvb:1;
|
unsigned int has_dvb:1;
|
||||||
unsigned int has_remote:1;
|
unsigned int has_remote:1;
|
||||||
unsigned int no_gpioirq:1;
|
unsigned int no_gpioirq:1;
|
||||||
unsigned int any_irq:1;
|
|
||||||
|
|
||||||
/* other settings */
|
/* other settings */
|
||||||
unsigned int pll;
|
unsigned int pll;
|
||||||
@ -335,7 +365,6 @@ struct bttv_sub_driver {
|
|||||||
struct device_driver drv;
|
struct device_driver drv;
|
||||||
char wanted[BUS_ID_SIZE];
|
char wanted[BUS_ID_SIZE];
|
||||||
void (*gpio_irq)(struct bttv_sub_device *sub);
|
void (*gpio_irq)(struct bttv_sub_device *sub);
|
||||||
int (*any_irq)(struct bttv_sub_device *sub);
|
|
||||||
};
|
};
|
||||||
#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
|
#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
|
||||||
|
|
||||||
@ -363,6 +392,10 @@ extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
|
|||||||
unsigned char b2, int both);
|
unsigned char b2, int both);
|
||||||
extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
|
extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
|
||||||
|
|
||||||
|
extern int bttv_input_init(struct bttv *dev);
|
||||||
|
extern void bttv_input_fini(struct bttv *dev);
|
||||||
|
extern void bttv_input_irq(struct bttv *dev);
|
||||||
|
|
||||||
#endif /* _BTTV_H_ */
|
#endif /* _BTTV_H_ */
|
||||||
/*
|
/*
|
||||||
* Local variables:
|
* Local variables:
|
||||||
|
@ -73,6 +73,8 @@
|
|||||||
|
|
||||||
#define UNSET (-1U)
|
#define UNSET (-1U)
|
||||||
|
|
||||||
|
#define clamp(x, low, high) min (max (low, x), high)
|
||||||
|
|
||||||
/* ---------------------------------------------------------- */
|
/* ---------------------------------------------------------- */
|
||||||
|
|
||||||
struct bttv_tvnorm {
|
struct bttv_tvnorm {
|
||||||
@ -88,6 +90,9 @@ struct bttv_tvnorm {
|
|||||||
u8 vbipack;
|
u8 vbipack;
|
||||||
u16 vtotal;
|
u16 vtotal;
|
||||||
int sram;
|
int sram;
|
||||||
|
/* ITU-R frame line number of the first VBI line we can
|
||||||
|
capture, of the first and second field. */
|
||||||
|
u16 vbistart[2];
|
||||||
};
|
};
|
||||||
extern const struct bttv_tvnorm bttv_tvnorms[];
|
extern const struct bttv_tvnorm bttv_tvnorms[];
|
||||||
|
|
||||||
@ -209,7 +214,6 @@ extern struct bus_type bttv_sub_bus_type;
|
|||||||
int bttv_sub_add_device(struct bttv_core *core, char *name);
|
int bttv_sub_add_device(struct bttv_core *core, char *name);
|
||||||
int bttv_sub_del_devices(struct bttv_core *core);
|
int bttv_sub_del_devices(struct bttv_core *core);
|
||||||
void bttv_gpio_irq(struct bttv_core *core);
|
void bttv_gpio_irq(struct bttv_core *core);
|
||||||
int bttv_any_irq(struct bttv_core *core);
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------- */
|
/* ---------------------------------------------------------- */
|
||||||
@ -270,12 +274,13 @@ struct bttv {
|
|||||||
/* card configuration info */
|
/* card configuration info */
|
||||||
unsigned int cardid; /* pci subsystem id (bt878 based ones) */
|
unsigned int cardid; /* pci subsystem id (bt878 based ones) */
|
||||||
unsigned int tuner_type; /* tuner chip type */
|
unsigned int tuner_type; /* tuner chip type */
|
||||||
unsigned int pinnacle_id;
|
unsigned int tda9887_conf;
|
||||||
unsigned int svhs;
|
unsigned int svhs;
|
||||||
struct bttv_pll_info pll;
|
struct bttv_pll_info pll;
|
||||||
int triton1;
|
int triton1;
|
||||||
int gpioirq;
|
int gpioirq;
|
||||||
int any_irq;
|
int (*custom_irq)(struct bttv *btv);
|
||||||
|
|
||||||
int use_i2c_hw;
|
int use_i2c_hw;
|
||||||
|
|
||||||
/* old gpio interface */
|
/* old gpio interface */
|
||||||
@ -300,7 +305,7 @@ struct bttv {
|
|||||||
|
|
||||||
/* infrared remote */
|
/* infrared remote */
|
||||||
int has_remote;
|
int has_remote;
|
||||||
struct bttv_input *remote;
|
struct bttv_ir *remote;
|
||||||
|
|
||||||
/* locking */
|
/* locking */
|
||||||
spinlock_t s_lock;
|
spinlock_t s_lock;
|
||||||
|
@ -875,6 +875,7 @@ static struct file_operations qcam_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = qcam_ioctl,
|
.ioctl = qcam_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.read = qcam_read,
|
.read = qcam_read,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
@ -687,6 +687,7 @@ static struct file_operations qcam_fops = {
|
|||||||
.open = video_exclusive_open,
|
.open = video_exclusive_open,
|
||||||
.release = video_exclusive_release,
|
.release = video_exclusive_release,
|
||||||
.ioctl = qcam_ioctl,
|
.ioctl = qcam_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.read = qcam_read,
|
.read = qcam_read,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
732
drivers/media/video/compat_ioctl32.c
Normal file
732
drivers/media/video/compat_ioctl32.c
Normal file
@ -0,0 +1,732 @@
|
|||||||
|
/*
|
||||||
|
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
|
||||||
|
* Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
|
||||||
|
*
|
||||||
|
* Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
|
||||||
|
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
|
||||||
|
* Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
|
||||||
|
* Copyright (C) 2003 Pavel Machek (pavel@suse.cz)
|
||||||
|
* Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be)
|
||||||
|
*
|
||||||
|
* These routines maintain argument size conversion between 32bit and 64bit
|
||||||
|
* ioctls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
|
#include <linux/compat.h>
|
||||||
|
#include <linux/videodev.h>
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/smp_lock.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
struct video_tuner32 {
|
||||||
|
compat_int_t tuner;
|
||||||
|
char name[32];
|
||||||
|
compat_ulong_t rangelow, rangehigh;
|
||||||
|
u32 flags; /* It is really u32 in videodev.h */
|
||||||
|
u16 mode, signal;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
|
||||||
|
{
|
||||||
|
if(get_user(kp->tuner, &up->tuner))
|
||||||
|
return -EFAULT;
|
||||||
|
__copy_from_user(kp->name, up->name, 32);
|
||||||
|
__get_user(kp->rangelow, &up->rangelow);
|
||||||
|
__get_user(kp->rangehigh, &up->rangehigh);
|
||||||
|
__get_user(kp->flags, &up->flags);
|
||||||
|
__get_user(kp->mode, &up->mode);
|
||||||
|
__get_user(kp->signal, &up->signal);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
|
||||||
|
{
|
||||||
|
if(put_user(kp->tuner, &up->tuner))
|
||||||
|
return -EFAULT;
|
||||||
|
__copy_to_user(up->name, kp->name, 32);
|
||||||
|
__put_user(kp->rangelow, &up->rangelow);
|
||||||
|
__put_user(kp->rangehigh, &up->rangehigh);
|
||||||
|
__put_user(kp->flags, &up->flags);
|
||||||
|
__put_user(kp->mode, &up->mode);
|
||||||
|
__put_user(kp->signal, &up->signal);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct video_buffer32 {
|
||||||
|
compat_caddr_t base;
|
||||||
|
compat_int_t height, width, depth, bytesperline;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
if (get_user(tmp, &up->base))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
/* This is actually a physical address stored
|
||||||
|
* as a void pointer.
|
||||||
|
*/
|
||||||
|
kp->base = (void *)(unsigned long) tmp;
|
||||||
|
|
||||||
|
__get_user(kp->height, &up->height);
|
||||||
|
__get_user(kp->width, &up->width);
|
||||||
|
__get_user(kp->depth, &up->depth);
|
||||||
|
__get_user(kp->bytesperline, &up->bytesperline);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
|
||||||
|
{
|
||||||
|
u32 tmp = (u32)((unsigned long)kp->base);
|
||||||
|
|
||||||
|
if(put_user(tmp, &up->base))
|
||||||
|
return -EFAULT;
|
||||||
|
__put_user(kp->height, &up->height);
|
||||||
|
__put_user(kp->width, &up->width);
|
||||||
|
__put_user(kp->depth, &up->depth);
|
||||||
|
__put_user(kp->bytesperline, &up->bytesperline);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct video_clip32 {
|
||||||
|
s32 x, y, width, height; /* Its really s32 in videodev.h */
|
||||||
|
compat_caddr_t next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct video_window32 {
|
||||||
|
u32 x, y, width, height, chromakey, flags;
|
||||||
|
compat_caddr_t clips;
|
||||||
|
compat_int_t clipcount;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
int ret = -ENOIOCTLCMD;
|
||||||
|
|
||||||
|
if (file->f_op->unlocked_ioctl)
|
||||||
|
ret = file->f_op->unlocked_ioctl(file, cmd, arg);
|
||||||
|
else if (file->f_op->ioctl) {
|
||||||
|
lock_kernel();
|
||||||
|
ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg);
|
||||||
|
unlock_kernel();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* You get back everything except the clips... */
|
||||||
|
static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
|
||||||
|
{
|
||||||
|
if(put_user(kp->x, &up->x))
|
||||||
|
return -EFAULT;
|
||||||
|
__put_user(kp->y, &up->y);
|
||||||
|
__put_user(kp->width, &up->width);
|
||||||
|
__put_user(kp->height, &up->height);
|
||||||
|
__put_user(kp->chromakey, &up->chromakey);
|
||||||
|
__put_user(kp->flags, &up->flags);
|
||||||
|
__put_user(kp->clipcount, &up->clipcount);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct v4l2_clip32
|
||||||
|
{
|
||||||
|
struct v4l2_rect c;
|
||||||
|
compat_caddr_t next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct v4l2_window32
|
||||||
|
{
|
||||||
|
struct v4l2_rect w;
|
||||||
|
enum v4l2_field field;
|
||||||
|
__u32 chromakey;
|
||||||
|
compat_caddr_t clips; /* actually struct v4l2_clip32 * */
|
||||||
|
__u32 clipcount;
|
||||||
|
compat_caddr_t bitmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
|
||||||
|
{
|
||||||
|
if (copy_from_user(&kp->w, &up->w, sizeof(up->w)))
|
||||||
|
return -EFAULT;
|
||||||
|
__get_user(kp->field, &up->field);
|
||||||
|
__get_user(kp->chromakey, &up->chromakey);
|
||||||
|
__get_user(kp->clipcount, &up->clipcount);
|
||||||
|
if (kp->clipcount > 2048)
|
||||||
|
return -EINVAL;
|
||||||
|
if (kp->clipcount) {
|
||||||
|
struct v4l2_clip32 *uclips = compat_ptr(up->clips);
|
||||||
|
struct v4l2_clip *kclips;
|
||||||
|
int n = kp->clipcount;
|
||||||
|
|
||||||
|
kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
|
||||||
|
kp->clips = kclips;
|
||||||
|
while (--n >= 0) {
|
||||||
|
copy_from_user(&kclips->c, &uclips->c, sizeof(uclips->c));
|
||||||
|
kclips->next = n ? kclips + 1 : 0;
|
||||||
|
uclips += 1;
|
||||||
|
kclips += 1;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
kp->clips = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
|
||||||
|
{
|
||||||
|
if (copy_to_user(&up->w, &kp->w, sizeof(up->w)))
|
||||||
|
return -EFAULT;
|
||||||
|
__put_user(kp->field, &up->field);
|
||||||
|
__put_user(kp->chromakey, &up->chromakey);
|
||||||
|
__put_user(kp->clipcount, &up->clipcount);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
|
||||||
|
{
|
||||||
|
return copy_from_user(kp, up, sizeof(struct v4l2_pix_format));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
|
||||||
|
{
|
||||||
|
return copy_to_user(up, kp, sizeof(struct v4l2_pix_format));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
|
||||||
|
{
|
||||||
|
return copy_from_user(kp, up, sizeof(struct v4l2_vbi_format));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
|
||||||
|
{
|
||||||
|
return copy_to_user(up, kp, sizeof(struct v4l2_vbi_format));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct v4l2_format32
|
||||||
|
{
|
||||||
|
enum v4l2_buf_type type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE
|
||||||
|
struct v4l2_window32 win; // V4L2_BUF_TYPE_VIDEO_OVERLAY
|
||||||
|
struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE
|
||||||
|
__u8 raw_data[200]; // user-defined
|
||||||
|
} fmt;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
|
||||||
|
{
|
||||||
|
if(get_user(kp->type, &up->type))
|
||||||
|
return -EFAULT;
|
||||||
|
switch (kp->type) {
|
||||||
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||||
|
return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
|
||||||
|
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
||||||
|
return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
|
||||||
|
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
||||||
|
return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
|
||||||
|
default:
|
||||||
|
printk("compat_ioctl : unexpected VIDIOC_FMT type %d\n",
|
||||||
|
kp->type);
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
|
||||||
|
{
|
||||||
|
if(put_user(kp->type, &up->type))
|
||||||
|
return -EFAULT;
|
||||||
|
switch (kp->type) {
|
||||||
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||||
|
return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
|
||||||
|
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
|
||||||
|
return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
|
||||||
|
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
||||||
|
return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
|
||||||
|
default:
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct v4l2_standard32
|
||||||
|
{
|
||||||
|
__u32 index;
|
||||||
|
__u32 id[2]; /* __u64 would get the alignment wrong */
|
||||||
|
__u8 name[24];
|
||||||
|
struct v4l2_fract frameperiod; /* Frames, not fields */
|
||||||
|
__u32 framelines;
|
||||||
|
__u32 reserved[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
|
||||||
|
{
|
||||||
|
/* other fields are not set by the user, nor used by the driver */
|
||||||
|
return get_user(kp->index, &up->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
|
||||||
|
{
|
||||||
|
if(put_user(kp->index, &up->index))
|
||||||
|
return -EFAULT;
|
||||||
|
__copy_to_user(up->id, &kp->id, sizeof(__u64));
|
||||||
|
__copy_to_user(up->name, kp->name, 24);
|
||||||
|
__put_user(kp->frameperiod, &up->frameperiod);
|
||||||
|
__put_user(kp->framelines, &up->framelines);
|
||||||
|
__copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct v4l2_buffer32
|
||||||
|
{
|
||||||
|
__u32 index;
|
||||||
|
enum v4l2_buf_type type;
|
||||||
|
__u32 bytesused;
|
||||||
|
__u32 flags;
|
||||||
|
enum v4l2_field field;
|
||||||
|
struct compat_timeval timestamp;
|
||||||
|
struct v4l2_timecode timecode;
|
||||||
|
__u32 sequence;
|
||||||
|
|
||||||
|
/* memory location */
|
||||||
|
enum v4l2_memory memory;
|
||||||
|
union {
|
||||||
|
__u32 offset;
|
||||||
|
compat_long_t userptr;
|
||||||
|
} m;
|
||||||
|
__u32 length;
|
||||||
|
__u32 input;
|
||||||
|
__u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (get_user(kp->index, &up->index))
|
||||||
|
return -EFAULT;
|
||||||
|
__get_user(kp->type, &up->type);
|
||||||
|
__get_user(kp->flags, &up->flags);
|
||||||
|
__get_user(kp->memory, &up->memory);
|
||||||
|
__get_user(kp->input, &up->input);
|
||||||
|
switch(kp->memory) {
|
||||||
|
case V4L2_MEMORY_MMAP:
|
||||||
|
break;
|
||||||
|
case V4L2_MEMORY_USERPTR:
|
||||||
|
{
|
||||||
|
unsigned long tmp = (unsigned long)compat_ptr(up->m.userptr);
|
||||||
|
|
||||||
|
__get_user(kp->length, &up->length);
|
||||||
|
__get_user(kp->m.userptr, &tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case V4L2_MEMORY_OVERLAY:
|
||||||
|
__get_user(kp->m.offset, &up->m.offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
|
||||||
|
{
|
||||||
|
if (put_user(kp->index, &up->index))
|
||||||
|
return -EFAULT;
|
||||||
|
__put_user(kp->type, &up->type);
|
||||||
|
__put_user(kp->flags, &up->flags);
|
||||||
|
__put_user(kp->memory, &up->memory);
|
||||||
|
__put_user(kp->input, &up->input);
|
||||||
|
switch(kp->memory) {
|
||||||
|
case V4L2_MEMORY_MMAP:
|
||||||
|
__put_user(kp->length, &up->length);
|
||||||
|
__put_user(kp->m.offset, &up->m.offset);
|
||||||
|
break;
|
||||||
|
case V4L2_MEMORY_USERPTR:
|
||||||
|
__put_user(kp->length, &up->length);
|
||||||
|
__put_user(kp->m.userptr, &up->m.userptr);
|
||||||
|
break;
|
||||||
|
case V4L2_MEMORY_OVERLAY:
|
||||||
|
__put_user(kp->m.offset, &up->m.offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
__put_user(kp->bytesused, &up->bytesused);
|
||||||
|
__put_user(kp->field, &up->field);
|
||||||
|
__put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec);
|
||||||
|
__put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec);
|
||||||
|
__copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode));
|
||||||
|
__put_user(kp->sequence, &up->sequence);
|
||||||
|
__put_user(kp->reserved, &up->reserved);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct v4l2_framebuffer32
|
||||||
|
{
|
||||||
|
__u32 capability;
|
||||||
|
__u32 flags;
|
||||||
|
compat_caddr_t base;
|
||||||
|
struct v4l2_pix_format fmt;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
if (get_user(tmp, &up->base))
|
||||||
|
return -EFAULT;
|
||||||
|
kp->base = compat_ptr(tmp);
|
||||||
|
__get_user(kp->capability, &up->capability);
|
||||||
|
__get_user(kp->flags, &up->flags);
|
||||||
|
get_v4l2_pix_format(&kp->fmt, &up->fmt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
|
||||||
|
{
|
||||||
|
u32 tmp = (u32)((unsigned long)kp->base);
|
||||||
|
|
||||||
|
if(put_user(tmp, &up->base))
|
||||||
|
return -EFAULT;
|
||||||
|
__put_user(kp->capability, &up->capability);
|
||||||
|
__put_user(kp->flags, &up->flags);
|
||||||
|
put_v4l2_pix_format(&kp->fmt, &up->fmt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct v4l2_input32 /* identical layout, but different size */
|
||||||
|
{
|
||||||
|
__u32 index; /* Which input */
|
||||||
|
__u8 name[32]; /* Label */
|
||||||
|
__u32 type; /* Type of input */
|
||||||
|
__u32 audioset; /* Associated audios (bitfield) */
|
||||||
|
__u32 tuner; /* Associated tuner */
|
||||||
|
__u32 std[2]; /* __u64 would get the padding wrong */
|
||||||
|
__u32 status;
|
||||||
|
__u32 reserved[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32)
|
||||||
|
#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32)
|
||||||
|
#define VIDIOCGWIN32 _IOR('v',9, struct video_window32)
|
||||||
|
#define VIDIOCSWIN32 _IOW('v',10, struct video_window32)
|
||||||
|
#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32)
|
||||||
|
#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32)
|
||||||
|
#define VIDIOCGFREQ32 _IOR('v',14, u32)
|
||||||
|
#define VIDIOCSFREQ32 _IOW('v',15, u32)
|
||||||
|
|
||||||
|
#define VIDIOC_G_FMT32 _IOWR ('V', 4, struct v4l2_format32)
|
||||||
|
#define VIDIOC_S_FMT32 _IOWR ('V', 5, struct v4l2_format32)
|
||||||
|
#define VIDIOC_QUERYBUF32 _IOWR ('V', 9, struct v4l2_buffer32)
|
||||||
|
#define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
|
||||||
|
#define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
|
||||||
|
/* VIDIOC_OVERLAY is now _IOW, but was _IOWR */
|
||||||
|
#define VIDIOC_OVERLAY32 _IOWR ('V', 14, compat_int_t)
|
||||||
|
#define VIDIOC_QBUF32 _IOWR ('V', 15, struct v4l2_buffer32)
|
||||||
|
#define VIDIOC_DQBUF32 _IOWR ('V', 17, struct v4l2_buffer32)
|
||||||
|
#define VIDIOC_STREAMON32 _IOW ('V', 18, compat_int_t)
|
||||||
|
#define VIDIOC_STREAMOFF32 _IOW ('V', 19, compat_int_t)
|
||||||
|
#define VIDIOC_ENUMSTD32 _IOWR ('V', 25, struct v4l2_standard32)
|
||||||
|
#define VIDIOC_ENUMINPUT32 _IOWR ('V', 26, struct v4l2_input32)
|
||||||
|
/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */
|
||||||
|
#define VIDIOC_S_CTRL32 _IOW ('V', 28, struct v4l2_control)
|
||||||
|
#define VIDIOC_G_INPUT32 _IOR ('V', 38, compat_int_t)
|
||||||
|
#define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t)
|
||||||
|
#define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
struct video_window32 __user *up = compat_ptr(arg);
|
||||||
|
struct video_window __user *vw;
|
||||||
|
struct video_clip __user *p;
|
||||||
|
int nclips;
|
||||||
|
u32 n;
|
||||||
|
|
||||||
|
if (get_user(nclips, &up->clipcount))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
/* Peculiar interface... */
|
||||||
|
if (nclips < 0)
|
||||||
|
nclips = VIDEO_CLIPMAP_SIZE;
|
||||||
|
|
||||||
|
if (nclips > MaxClips)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
vw = compat_alloc_user_space(sizeof(struct video_window) +
|
||||||
|
nclips * sizeof(struct video_clip));
|
||||||
|
|
||||||
|
p = nclips ? (struct video_clip __user *)(vw + 1) : NULL;
|
||||||
|
|
||||||
|
if (get_user(n, &up->x) || put_user(n, &vw->x) ||
|
||||||
|
get_user(n, &up->y) || put_user(n, &vw->y) ||
|
||||||
|
get_user(n, &up->width) || put_user(n, &vw->width) ||
|
||||||
|
get_user(n, &up->height) || put_user(n, &vw->height) ||
|
||||||
|
get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) ||
|
||||||
|
get_user(n, &up->flags) || put_user(n, &vw->flags) ||
|
||||||
|
get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) ||
|
||||||
|
get_user(n, &up->clips) || put_user(p, &vw->clips))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
if (nclips) {
|
||||||
|
struct video_clip32 __user *u = compat_ptr(n);
|
||||||
|
int i;
|
||||||
|
if (!u)
|
||||||
|
return -EINVAL;
|
||||||
|
for (i = 0; i < nclips; i++, u++, p++) {
|
||||||
|
s32 v;
|
||||||
|
if (get_user(v, &u->x) ||
|
||||||
|
put_user(v, &p->x) ||
|
||||||
|
get_user(v, &u->y) ||
|
||||||
|
put_user(v, &p->y) ||
|
||||||
|
get_user(v, &u->width) ||
|
||||||
|
put_user(v, &p->width) ||
|
||||||
|
get_user(v, &u->height) ||
|
||||||
|
put_user(v, &p->height) ||
|
||||||
|
put_user(NULL, &p->next))
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
struct video_tuner vt;
|
||||||
|
struct video_buffer vb;
|
||||||
|
struct video_window vw;
|
||||||
|
struct v4l2_format v2f;
|
||||||
|
struct v4l2_buffer v2b;
|
||||||
|
struct v4l2_framebuffer v2fb;
|
||||||
|
struct v4l2_standard v2s;
|
||||||
|
unsigned long vx;
|
||||||
|
} karg;
|
||||||
|
void __user *up = compat_ptr(arg);
|
||||||
|
int compatible_arg = 1;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
/* First, convert the command. */
|
||||||
|
switch(cmd) {
|
||||||
|
case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
|
||||||
|
case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
|
||||||
|
case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
|
||||||
|
case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
|
||||||
|
case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
|
||||||
|
case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
|
||||||
|
case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
|
||||||
|
case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
|
||||||
|
case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
|
||||||
|
case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
|
||||||
|
case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
|
||||||
|
case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
|
||||||
|
case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
|
||||||
|
case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
|
||||||
|
case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
|
||||||
|
case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
|
||||||
|
case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
|
||||||
|
case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
|
||||||
|
case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
|
||||||
|
case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break;
|
||||||
|
case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
|
||||||
|
case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
|
||||||
|
case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch(cmd) {
|
||||||
|
case VIDIOCSTUNER:
|
||||||
|
case VIDIOCGTUNER:
|
||||||
|
err = get_video_tuner32(&karg.vt, up);
|
||||||
|
compatible_arg = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOCSFBUF:
|
||||||
|
err = get_video_buffer32(&karg.vb, up);
|
||||||
|
compatible_arg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOCSFREQ:
|
||||||
|
case VIDIOC_S_INPUT:
|
||||||
|
case VIDIOC_OVERLAY:
|
||||||
|
case VIDIOC_STREAMON:
|
||||||
|
case VIDIOC_STREAMOFF:
|
||||||
|
err = get_user(karg.vx, (u32 __user *)up);
|
||||||
|
compatible_arg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_S_FBUF:
|
||||||
|
err = get_v4l2_framebuffer32(&karg.v2fb, up);
|
||||||
|
compatible_arg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_G_FMT:
|
||||||
|
case VIDIOC_S_FMT:
|
||||||
|
case VIDIOC_TRY_FMT:
|
||||||
|
err = get_v4l2_format32(&karg.v2f, up);
|
||||||
|
compatible_arg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_QUERYBUF:
|
||||||
|
case VIDIOC_QBUF:
|
||||||
|
case VIDIOC_DQBUF:
|
||||||
|
err = get_v4l2_buffer32(&karg.v2b, up);
|
||||||
|
compatible_arg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_ENUMSTD:
|
||||||
|
err = get_v4l2_standard32(&karg.v2s, up);
|
||||||
|
compatible_arg = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOCGWIN:
|
||||||
|
case VIDIOCGFBUF:
|
||||||
|
case VIDIOCGFREQ:
|
||||||
|
case VIDIOC_G_FBUF:
|
||||||
|
case VIDIOC_G_INPUT:
|
||||||
|
compatible_arg = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if(compatible_arg)
|
||||||
|
err = native_ioctl(file, cmd, (unsigned long)up);
|
||||||
|
else {
|
||||||
|
mm_segment_t old_fs = get_fs();
|
||||||
|
|
||||||
|
set_fs(KERNEL_DS);
|
||||||
|
err = native_ioctl(file, cmd, (unsigned long)&karg);
|
||||||
|
set_fs(old_fs);
|
||||||
|
}
|
||||||
|
if(err == 0) {
|
||||||
|
switch(cmd) {
|
||||||
|
case VIDIOCGTUNER:
|
||||||
|
err = put_video_tuner32(&karg.vt, up);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOCGWIN:
|
||||||
|
err = put_video_window32(&karg.vw, up);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOCGFBUF:
|
||||||
|
err = put_video_buffer32(&karg.vb, up);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_G_FBUF:
|
||||||
|
err = put_v4l2_framebuffer32(&karg.v2fb, up);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_G_FMT:
|
||||||
|
case VIDIOC_S_FMT:
|
||||||
|
case VIDIOC_TRY_FMT:
|
||||||
|
err = put_v4l2_format32(&karg.v2f, up);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_QUERYBUF:
|
||||||
|
case VIDIOC_QBUF:
|
||||||
|
case VIDIOC_DQBUF:
|
||||||
|
err = put_v4l2_buffer32(&karg.v2b, up);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_ENUMSTD:
|
||||||
|
err = put_v4l2_standard32(&karg.v2s, up);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOCGFREQ:
|
||||||
|
case VIDIOC_G_INPUT:
|
||||||
|
err = put_user(((u32)karg.vx), (u32 __user *)up);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
int ret = -ENOIOCTLCMD;
|
||||||
|
|
||||||
|
if (!file->f_op->ioctl)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case VIDIOCSWIN32:
|
||||||
|
ret = do_set_window(file, cmd, arg);
|
||||||
|
break;
|
||||||
|
case VIDIOCGTUNER32:
|
||||||
|
case VIDIOCSTUNER32:
|
||||||
|
case VIDIOCGWIN32:
|
||||||
|
case VIDIOCGFBUF32:
|
||||||
|
case VIDIOCSFBUF32:
|
||||||
|
case VIDIOCGFREQ32:
|
||||||
|
case VIDIOCSFREQ32:
|
||||||
|
case VIDIOC_QUERYCAP:
|
||||||
|
case VIDIOC_ENUM_FMT:
|
||||||
|
case VIDIOC_G_FMT32:
|
||||||
|
case VIDIOC_S_FMT32:
|
||||||
|
case VIDIOC_REQBUFS:
|
||||||
|
case VIDIOC_QUERYBUF32:
|
||||||
|
case VIDIOC_G_FBUF32:
|
||||||
|
case VIDIOC_S_FBUF32:
|
||||||
|
case VIDIOC_OVERLAY32:
|
||||||
|
case VIDIOC_QBUF32:
|
||||||
|
case VIDIOC_DQBUF32:
|
||||||
|
case VIDIOC_STREAMON32:
|
||||||
|
case VIDIOC_STREAMOFF32:
|
||||||
|
case VIDIOC_G_PARM:
|
||||||
|
case VIDIOC_G_STD:
|
||||||
|
case VIDIOC_S_STD:
|
||||||
|
case VIDIOC_ENUMSTD32:
|
||||||
|
case VIDIOC_ENUMINPUT32:
|
||||||
|
case VIDIOC_G_CTRL:
|
||||||
|
case VIDIOC_S_CTRL32:
|
||||||
|
case VIDIOC_QUERYCTRL:
|
||||||
|
case VIDIOC_G_INPUT32:
|
||||||
|
case VIDIOC_S_INPUT32:
|
||||||
|
case VIDIOC_TRY_FMT32:
|
||||||
|
ret = do_video_ioctl(file, cmd, arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Little v, the video4linux ioctls (conflict?) */
|
||||||
|
case VIDIOCGCAP:
|
||||||
|
case VIDIOCGCHAN:
|
||||||
|
case VIDIOCSCHAN:
|
||||||
|
case VIDIOCGPICT:
|
||||||
|
case VIDIOCSPICT:
|
||||||
|
case VIDIOCCAPTURE:
|
||||||
|
case VIDIOCKEY:
|
||||||
|
case VIDIOCGAUDIO:
|
||||||
|
case VIDIOCSAUDIO:
|
||||||
|
case VIDIOCSYNC:
|
||||||
|
case VIDIOCMCAPTURE:
|
||||||
|
case VIDIOCGMBUF:
|
||||||
|
case VIDIOCGUNIT:
|
||||||
|
case VIDIOCGCAPTURE:
|
||||||
|
case VIDIOCSCAPTURE:
|
||||||
|
|
||||||
|
/* BTTV specific... */
|
||||||
|
case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]):
|
||||||
|
case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]):
|
||||||
|
case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
|
||||||
|
case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
|
||||||
|
case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
|
||||||
|
case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
|
||||||
|
case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
|
||||||
|
case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
|
||||||
|
ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
@ -3807,6 +3807,7 @@ static struct file_operations cpia_fops = {
|
|||||||
.read = cpia_read,
|
.read = cpia_read,
|
||||||
.mmap = cpia_mmap,
|
.mmap = cpia_mmap,
|
||||||
.ioctl = cpia_ioctl,
|
.ioctl = cpia_ioctl,
|
||||||
|
.compat_ioctl = v4l_compat_ioctl32,
|
||||||
.llseek = no_llseek,
|
.llseek = no_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/i2c-id.h>
|
#include <linux/i2c-id.h>
|
||||||
#include <linux/videodev.h>
|
#include <linux/videodev.h>
|
||||||
#include <media/audiochip.h>
|
#include <media/v4l2-common.h>
|
||||||
|
|
||||||
MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
|
MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
|
||||||
MODULE_AUTHOR("Martin Vaughan");
|
MODULE_AUTHOR("Martin Vaughan");
|
||||||
@ -39,21 +39,6 @@ module_param(debug, bool, 0644);
|
|||||||
|
|
||||||
MODULE_PARM_DESC(debug, "Debugging messages\n\t\t\t0=Off (default), 1=On");
|
MODULE_PARM_DESC(debug, "Debugging messages\n\t\t\t0=Off (default), 1=On");
|
||||||
|
|
||||||
#define cs53l32a_dbg(fmt, arg...) \
|
|
||||||
do { \
|
|
||||||
if (debug) \
|
|
||||||
printk(KERN_INFO "%s debug %d-%04x: " fmt, \
|
|
||||||
client->driver->driver.name, \
|
|
||||||
i2c_adapter_id(client->adapter), client->addr , ## arg); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define cs53l32a_err(fmt, arg...) do { \
|
|
||||||
printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->driver.name, \
|
|
||||||
i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
|
|
||||||
#define cs53l32a_info(fmt, arg...) do { \
|
|
||||||
printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->driver.name, \
|
|
||||||
i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0)
|
|
||||||
|
|
||||||
static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
|
static unsigned short normal_i2c[] = { 0x22 >> 1, I2C_CLIENT_END };
|
||||||
|
|
||||||
|
|
||||||
@ -74,50 +59,59 @@ static int cs53l32a_read(struct i2c_client *client, u8 reg)
|
|||||||
static int cs53l32a_command(struct i2c_client *client, unsigned int cmd,
|
static int cs53l32a_command(struct i2c_client *client, unsigned int cmd,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
int *input = arg;
|
struct v4l2_audio *input = arg;
|
||||||
|
struct v4l2_control *ctrl = arg;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case AUDC_SET_INPUT:
|
case VIDIOC_S_AUDIO:
|
||||||
switch (*input) {
|
/* There are 2 physical inputs, but the second input can be
|
||||||
case AUDIO_TUNER:
|
placed in two modes, the first mode bypasses the PGA (gain),
|
||||||
cs53l32a_write(client, 0x01, 0x01);
|
the second goes through the PGA. Hence there are three
|
||||||
break;
|
possible inputs to choose from. */
|
||||||
case AUDIO_EXTERN:
|
if (input->index > 2) {
|
||||||
cs53l32a_write(client, 0x01, 0x21);
|
v4l_err(client, "Invalid input %d.\n", input->index);
|
||||||
break;
|
|
||||||
case AUDIO_MUTE:
|
|
||||||
cs53l32a_write(client, 0x03, 0xF0);
|
|
||||||
break;
|
|
||||||
case AUDIO_UNMUTE:
|
|
||||||
cs53l32a_write(client, 0x03, 0x30);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cs53l32a_err("Invalid input %d.\n", *input);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
cs53l32a_write(client, 0x01, 0x01 + (input->index << 4));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_G_AUDIO:
|
||||||
|
memset(input, 0, sizeof(*input));
|
||||||
|
input->index = (cs53l32a_read(client, 0x01) >> 4) & 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIDIOC_G_CTRL:
|
||||||
|
if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
|
||||||
|
ctrl->value = (cs53l32a_read(client, 0x03) & 0xc0) != 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
|
||||||
|
return -EINVAL;
|
||||||
|
ctrl->value = (s8)cs53l32a_read(client, 0x04);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIDIOC_S_CTRL:
|
case VIDIOC_S_CTRL:
|
||||||
{
|
if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
|
||||||
struct v4l2_control *ctrl = arg;
|
cs53l32a_write(client, 0x03, ctrl->value ? 0xf0 : 0x30);
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
|
if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (ctrl->value > 12 || ctrl->value < -90)
|
if (ctrl->value > 12 || ctrl->value < -96)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
cs53l32a_write(client, 0x04, (u8) ctrl->value);
|
cs53l32a_write(client, 0x04, (u8) ctrl->value);
|
||||||
cs53l32a_write(client, 0x05, (u8) ctrl->value);
|
cs53l32a_write(client, 0x05, (u8) ctrl->value);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case VIDIOC_LOG_STATUS:
|
case VIDIOC_LOG_STATUS:
|
||||||
{
|
{
|
||||||
u8 v = cs53l32a_read(client, 0x01);
|
u8 v = cs53l32a_read(client, 0x01);
|
||||||
u8 m = cs53l32a_read(client, 0x03);
|
u8 m = cs53l32a_read(client, 0x03);
|
||||||
|
s8 vol = cs53l32a_read(client, 0x04);
|
||||||
|
|
||||||
cs53l32a_info("Input: %s%s\n",
|
v4l_info(client, "Input: %d%s\n", (v >> 4) & 3,
|
||||||
v == 0x21 ? "external line in" : "tuner",
|
|
||||||
(m & 0xC0) ? " (muted)" : "");
|
(m & 0xC0) ? " (muted)" : "");
|
||||||
|
v4l_info(client, "Volume: %d dB\n", vol);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,12 +151,12 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
|
|||||||
client->driver = &i2c_driver;
|
client->driver = &i2c_driver;
|
||||||
snprintf(client->name, sizeof(client->name) - 1, "cs53l32a");
|
snprintf(client->name, sizeof(client->name) - 1, "cs53l32a");
|
||||||
|
|
||||||
cs53l32a_info("chip found @ 0x%x (%s)\n", address << 1, adapter->name);
|
v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
|
||||||
|
|
||||||
for (i = 1; i <= 7; i++) {
|
for (i = 1; i <= 7; i++) {
|
||||||
u8 v = cs53l32a_read(client, i);
|
u8 v = cs53l32a_read(client, i);
|
||||||
|
|
||||||
cs53l32a_dbg("Read Reg %d %02x\n", i, v);
|
v4l_dbg(1, client, "Read Reg %d %02x\n", i, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set cs53l32a internal register for Adaptec 2010/2410 setup */
|
/* Set cs53l32a internal register for Adaptec 2010/2410 setup */
|
||||||
@ -180,7 +174,7 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
|
|||||||
for (i = 1; i <= 7; i++) {
|
for (i = 1; i <= 7; i++) {
|
||||||
u8 v = cs53l32a_read(client, i);
|
u8 v = cs53l32a_read(client, i);
|
||||||
|
|
||||||
cs53l32a_dbg("Read Reg %d %02x\n", i, v);
|
v4l_dbg(1, client, "Read Reg %d %02x\n", i, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_attach_client(client);
|
i2c_attach_client(client);
|
||||||
@ -190,11 +184,7 @@ static int cs53l32a_attach(struct i2c_adapter *adapter, int address, int kind)
|
|||||||
|
|
||||||
static int cs53l32a_probe(struct i2c_adapter *adapter)
|
static int cs53l32a_probe(struct i2c_adapter *adapter)
|
||||||
{
|
{
|
||||||
#ifdef I2C_CLASS_TV_ANALOG
|
|
||||||
if (adapter->class & I2C_CLASS_TV_ANALOG)
|
if (adapter->class & I2C_CLASS_TV_ANALOG)
|
||||||
#else
|
|
||||||
if (adapter->id == I2C_HW_B_BT848)
|
|
||||||
#endif
|
|
||||||
return i2c_probe(adapter, &addr_data, cs53l32a_attach);
|
return i2c_probe(adapter, &addr_data, cs53l32a_attach);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,13 @@
|
|||||||
|
|
||||||
#include "cx25840.h"
|
#include "cx25840.h"
|
||||||
|
|
||||||
inline static int set_audclk_freq(struct i2c_client *client,
|
static int set_audclk_freq(struct i2c_client *client, u32 freq)
|
||||||
enum v4l2_audio_clock_freq freq)
|
|
||||||
{
|
{
|
||||||
struct cx25840_state *state = i2c_get_clientdata(client);
|
struct cx25840_state *state = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
if (freq != 32000 && freq != 44100 && freq != 48000)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* assert soft reset */
|
/* assert soft reset */
|
||||||
cx25840_and_or(client, 0x810, ~0x1, 0x01);
|
cx25840_and_or(client, 0x810, ~0x1, 0x01);
|
||||||
|
|
||||||
@ -35,10 +37,9 @@ inline static int set_audclk_freq(struct i2c_client *client,
|
|||||||
/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
|
/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
|
||||||
cx25840_write(client, 0x127, 0x50);
|
cx25840_write(client, 0x127, 0x50);
|
||||||
|
|
||||||
switch (state->audio_input) {
|
if (state->aud_input != CX25840_AUDIO_SERIAL) {
|
||||||
case AUDIO_TUNER:
|
|
||||||
switch (freq) {
|
switch (freq) {
|
||||||
case V4L2_AUDCLK_32_KHZ:
|
case 32000:
|
||||||
/* VID_PLL and AUX_PLL */
|
/* VID_PLL and AUX_PLL */
|
||||||
cx25840_write4(client, 0x108, 0x0f040610);
|
cx25840_write4(client, 0x108, 0x0f040610);
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
|
|||||||
cx25840_write4(client, 0x90c, 0x7ff70108);
|
cx25840_write4(client, 0x90c, 0x7ff70108);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V4L2_AUDCLK_441_KHZ:
|
case 44100:
|
||||||
/* VID_PLL and AUX_PLL */
|
/* VID_PLL and AUX_PLL */
|
||||||
cx25840_write4(client, 0x108, 0x0f040910);
|
cx25840_write4(client, 0x108, 0x0f040910);
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
|
|||||||
cx25840_write4(client, 0x90c, 0x596d0108);
|
cx25840_write4(client, 0x90c, 0x596d0108);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V4L2_AUDCLK_48_KHZ:
|
case 48000:
|
||||||
/* VID_PLL and AUX_PLL */
|
/* VID_PLL and AUX_PLL */
|
||||||
cx25840_write4(client, 0x108, 0x0f040a10);
|
cx25840_write4(client, 0x108, 0x0f040a10);
|
||||||
|
|
||||||
@ -77,14 +78,9 @@ inline static int set_audclk_freq(struct i2c_client *client,
|
|||||||
cx25840_write4(client, 0x90c, 0xaa4f0108);
|
cx25840_write4(client, 0x90c, 0xaa4f0108);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
|
|
||||||
case AUDIO_EXTERN_1:
|
|
||||||
case AUDIO_EXTERN_2:
|
|
||||||
case AUDIO_INTERN:
|
|
||||||
case AUDIO_RADIO:
|
|
||||||
switch (freq) {
|
switch (freq) {
|
||||||
case V4L2_AUDCLK_32_KHZ:
|
case 32000:
|
||||||
/* VID_PLL and AUX_PLL */
|
/* VID_PLL and AUX_PLL */
|
||||||
cx25840_write4(client, 0x108, 0x0f04081e);
|
cx25840_write4(client, 0x108, 0x0f04081e);
|
||||||
|
|
||||||
@ -103,7 +99,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
|
|||||||
cx25840_write(client, 0x127, 0x54);
|
cx25840_write(client, 0x127, 0x54);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V4L2_AUDCLK_441_KHZ:
|
case 44100:
|
||||||
/* VID_PLL and AUX_PLL */
|
/* VID_PLL and AUX_PLL */
|
||||||
cx25840_write4(client, 0x108, 0x0f040918);
|
cx25840_write4(client, 0x108, 0x0f040918);
|
||||||
|
|
||||||
@ -119,7 +115,7 @@ inline static int set_audclk_freq(struct i2c_client *client,
|
|||||||
cx25840_write4(client, 0x90c, 0x85730108);
|
cx25840_write4(client, 0x90c, 0x85730108);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V4L2_AUDCLK_48_KHZ:
|
case 48000:
|
||||||
/* VID_PLL and AUX_PLL */
|
/* VID_PLL and AUX_PLL */
|
||||||
cx25840_write4(client, 0x108, 0x0f040a18);
|
cx25840_write4(client, 0x108, 0x0f040a18);
|
||||||
|
|
||||||
@ -135,7 +131,6 @@ inline static int set_audclk_freq(struct i2c_client *client,
|
|||||||
cx25840_write4(client, 0x90c, 0x55550108);
|
cx25840_write4(client, 0x90c, 0x55550108);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deassert soft reset */
|
/* deassert soft reset */
|
||||||
@ -146,51 +141,36 @@ inline static int set_audclk_freq(struct i2c_client *client,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_input(struct i2c_client *client, int audio_input)
|
void cx25840_audio_set_path(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct cx25840_state *state = i2c_get_clientdata(client);
|
struct cx25840_state *state = i2c_get_clientdata(client);
|
||||||
|
|
||||||
cx25840_dbg("set audio input (%d)\n", audio_input);
|
|
||||||
|
|
||||||
/* stop microcontroller */
|
/* stop microcontroller */
|
||||||
cx25840_and_or(client, 0x803, ~0x10, 0);
|
cx25840_and_or(client, 0x803, ~0x10, 0);
|
||||||
|
|
||||||
/* Mute everything to prevent the PFFT! */
|
/* Mute everything to prevent the PFFT! */
|
||||||
cx25840_write(client, 0x8d3, 0x1f);
|
cx25840_write(client, 0x8d3, 0x1f);
|
||||||
|
|
||||||
switch (audio_input) {
|
if (state->aud_input == CX25840_AUDIO_SERIAL) {
|
||||||
case AUDIO_TUNER:
|
|
||||||
/* Set Path1 to Analog Demod Main Channel */
|
|
||||||
cx25840_write4(client, 0x8d0, 0x7038061f);
|
|
||||||
|
|
||||||
/* When the microcontroller detects the
|
|
||||||
* audio format, it will unmute the lines */
|
|
||||||
cx25840_and_or(client, 0x803, ~0x10, 0x10);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AUDIO_EXTERN_1:
|
|
||||||
case AUDIO_EXTERN_2:
|
|
||||||
case AUDIO_INTERN:
|
|
||||||
case AUDIO_RADIO:
|
|
||||||
/* Set Path1 to Serial Audio Input */
|
/* Set Path1 to Serial Audio Input */
|
||||||
cx25840_write4(client, 0x8d0, 0x12100101);
|
cx25840_write4(client, 0x8d0, 0x12100101);
|
||||||
|
|
||||||
/* The microcontroller should not be started for the
|
/* The microcontroller should not be started for the
|
||||||
* non-tuner inputs: autodetection is specific for
|
* non-tuner inputs: autodetection is specific for
|
||||||
* TV audio. */
|
* TV audio. */
|
||||||
break;
|
} else {
|
||||||
|
/* Set Path1 to Analog Demod Main Channel */
|
||||||
|
cx25840_write4(client, 0x8d0, 0x7038061f);
|
||||||
|
|
||||||
default:
|
/* When the microcontroller detects the
|
||||||
cx25840_dbg("Invalid audio input selection %d\n", audio_input);
|
* audio format, it will unmute the lines */
|
||||||
return -EINVAL;
|
cx25840_and_or(client, 0x803, ~0x10, 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->audio_input = audio_input;
|
set_audclk_freq(client, state->audclk_freq);
|
||||||
|
|
||||||
return set_audclk_freq(client, state->audclk_freq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int get_volume(struct i2c_client *client)
|
static int get_volume(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
/* Volume runs +18dB to -96dB in 1/2dB steps
|
/* Volume runs +18dB to -96dB in 1/2dB steps
|
||||||
* change to fit the msp3400 -114dB to +12dB range */
|
* change to fit the msp3400 -114dB to +12dB range */
|
||||||
@ -201,7 +181,7 @@ inline static int get_volume(struct i2c_client *client)
|
|||||||
return vol << 9;
|
return vol << 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void set_volume(struct i2c_client *client, int volume)
|
static void set_volume(struct i2c_client *client, int volume)
|
||||||
{
|
{
|
||||||
/* First convert the volume to msp3400 values (0-127) */
|
/* First convert the volume to msp3400 values (0-127) */
|
||||||
int vol = volume >> 9;
|
int vol = volume >> 9;
|
||||||
@ -218,7 +198,7 @@ inline static void set_volume(struct i2c_client *client, int volume)
|
|||||||
cx25840_write(client, 0x8d4, 228 - (vol * 2));
|
cx25840_write(client, 0x8d4, 228 - (vol * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int get_bass(struct i2c_client *client)
|
static int get_bass(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
/* bass is 49 steps +12dB to -12dB */
|
/* bass is 49 steps +12dB to -12dB */
|
||||||
|
|
||||||
@ -228,13 +208,13 @@ inline static int get_bass(struct i2c_client *client)
|
|||||||
return bass;
|
return bass;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void set_bass(struct i2c_client *client, int bass)
|
static void set_bass(struct i2c_client *client, int bass)
|
||||||
{
|
{
|
||||||
/* PATH1_EQ_BASS_VOL */
|
/* PATH1_EQ_BASS_VOL */
|
||||||
cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
|
cx25840_and_or(client, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int get_treble(struct i2c_client *client)
|
static int get_treble(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
/* treble is 49 steps +12dB to -12dB */
|
/* treble is 49 steps +12dB to -12dB */
|
||||||
|
|
||||||
@ -244,13 +224,13 @@ inline static int get_treble(struct i2c_client *client)
|
|||||||
return treble;
|
return treble;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void set_treble(struct i2c_client *client, int treble)
|
static void set_treble(struct i2c_client *client, int treble)
|
||||||
{
|
{
|
||||||
/* PATH1_EQ_TREBLE_VOL */
|
/* PATH1_EQ_TREBLE_VOL */
|
||||||
cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
|
cx25840_and_or(client, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int get_balance(struct i2c_client *client)
|
static int get_balance(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
/* balance is 7 bit, 0 to -96dB */
|
/* balance is 7 bit, 0 to -96dB */
|
||||||
|
|
||||||
@ -264,7 +244,7 @@ inline static int get_balance(struct i2c_client *client)
|
|||||||
return balance << 8;
|
return balance << 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void set_balance(struct i2c_client *client, int balance)
|
static void set_balance(struct i2c_client *client, int balance)
|
||||||
{
|
{
|
||||||
int bal = balance >> 8;
|
int bal = balance >> 8;
|
||||||
if (bal > 0x80) {
|
if (bal > 0x80) {
|
||||||
@ -280,17 +260,17 @@ inline static void set_balance(struct i2c_client *client, int balance)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int get_mute(struct i2c_client *client)
|
static int get_mute(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
/* check SRC1_MUTE_EN */
|
/* check SRC1_MUTE_EN */
|
||||||
return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0;
|
return cx25840_read(client, 0x8d3) & 0x2 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void set_mute(struct i2c_client *client, int mute)
|
static void set_mute(struct i2c_client *client, int mute)
|
||||||
{
|
{
|
||||||
struct cx25840_state *state = i2c_get_clientdata(client);
|
struct cx25840_state *state = i2c_get_clientdata(client);
|
||||||
|
|
||||||
if (state->audio_input == AUDIO_TUNER) {
|
if (state->aud_input != CX25840_AUDIO_SERIAL) {
|
||||||
/* Must turn off microcontroller in order to mute sound.
|
/* Must turn off microcontroller in order to mute sound.
|
||||||
* Not sure if this is the best method, but it does work.
|
* Not sure if this is the best method, but it does work.
|
||||||
* If the microcontroller is running, then it will undo any
|
* If the microcontroller is running, then it will undo any
|
||||||
@ -314,10 +294,9 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
|
|||||||
struct v4l2_control *ctrl = arg;
|
struct v4l2_control *ctrl = arg;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case AUDC_SET_INPUT:
|
|
||||||
return set_input(client, *(int *)arg);
|
|
||||||
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
|
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
|
||||||
return set_audclk_freq(client, *(enum v4l2_audio_clock_freq *)arg);
|
return set_audclk_freq(client, *(u32 *)arg);
|
||||||
|
|
||||||
case VIDIOC_G_CTRL:
|
case VIDIOC_G_CTRL:
|
||||||
switch (ctrl->id) {
|
switch (ctrl->id) {
|
||||||
case V4L2_CID_AUDIO_VOLUME:
|
case V4L2_CID_AUDIO_VOLUME:
|
||||||
@ -339,6 +318,7 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIDIOC_S_CTRL:
|
case VIDIOC_S_CTRL:
|
||||||
switch (ctrl->id) {
|
switch (ctrl->id) {
|
||||||
case V4L2_CID_AUDIO_VOLUME:
|
case V4L2_CID_AUDIO_VOLUME:
|
||||||
@ -360,6 +340,7 @@ int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user