|
@@ -71,7 +71,7 @@ struct cadet {
|
|
|
int sigstrength;
|
|
|
wait_queue_head_t read_queue;
|
|
|
struct timer_list readtimer;
|
|
|
- __u8 rdsin, rdsout, rdsstat;
|
|
|
+ u8 rdsin, rdsout, rdsstat;
|
|
|
unsigned char rdsbuf[RDS_BUFFER];
|
|
|
struct mutex lock;
|
|
|
int reading;
|
|
@@ -85,8 +85,8 @@ static struct cadet cadet_card;
|
|
|
* strength value. These values are in microvolts of RF at the tuner's input.
|
|
|
*/
|
|
|
static __u16 sigtable[2][4] = {
|
|
|
- { 5, 10, 30, 150 },
|
|
|
- { 28, 40, 63, 1000 }
|
|
|
+ { 2185, 4369, 13107, 65535 },
|
|
|
+ { 1835, 2621, 4128, 65535 }
|
|
|
};
|
|
|
|
|
|
|
|
@@ -240,10 +240,13 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq)
|
|
|
cadet_gettune(dev);
|
|
|
if ((dev->tunestat & 0x40) == 0) { /* Tuned */
|
|
|
dev->sigstrength = sigtable[dev->curtuner][j];
|
|
|
- return;
|
|
|
+ goto reset_rds;
|
|
|
}
|
|
|
}
|
|
|
dev->sigstrength = 0;
|
|
|
+reset_rds:
|
|
|
+ outb(3, dev->io);
|
|
|
+ outb(inb(dev->io + 1) & 0x7f, dev->io + 1);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -259,7 +262,7 @@ static void cadet_handler(unsigned long data)
|
|
|
outb(0x80, dev->io); /* Select RDS fifo */
|
|
|
while ((inb(dev->io) & 0x80) != 0) {
|
|
|
dev->rdsbuf[dev->rdsin] = inb(dev->io + 1);
|
|
|
- if (dev->rdsin == dev->rdsout)
|
|
|
+ if (dev->rdsin + 1 == dev->rdsout)
|
|
|
printk(KERN_WARNING "cadet: RDS buffer overflow\n");
|
|
|
else
|
|
|
dev->rdsin++;
|
|
@@ -278,11 +281,21 @@ static void cadet_handler(unsigned long data)
|
|
|
*/
|
|
|
init_timer(&dev->readtimer);
|
|
|
dev->readtimer.function = cadet_handler;
|
|
|
- dev->readtimer.data = (unsigned long)0;
|
|
|
+ dev->readtimer.data = data;
|
|
|
dev->readtimer.expires = jiffies + msecs_to_jiffies(50);
|
|
|
add_timer(&dev->readtimer);
|
|
|
}
|
|
|
|
|
|
+static void cadet_start_rds(struct cadet *dev)
|
|
|
+{
|
|
|
+ dev->rdsstat = 1;
|
|
|
+ outb(0x80, dev->io); /* Select RDS fifo */
|
|
|
+ init_timer(&dev->readtimer);
|
|
|
+ dev->readtimer.function = cadet_handler;
|
|
|
+ dev->readtimer.data = (unsigned long)dev;
|
|
|
+ dev->readtimer.expires = jiffies + msecs_to_jiffies(50);
|
|
|
+ add_timer(&dev->readtimer);
|
|
|
+}
|
|
|
|
|
|
static ssize_t cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
|
|
|
{
|
|
@@ -291,26 +304,21 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
|
|
|
int i = 0;
|
|
|
|
|
|
mutex_lock(&dev->lock);
|
|
|
- if (dev->rdsstat == 0) {
|
|
|
- dev->rdsstat = 1;
|
|
|
- outb(0x80, dev->io); /* Select RDS fifo */
|
|
|
- init_timer(&dev->readtimer);
|
|
|
- dev->readtimer.function = cadet_handler;
|
|
|
- dev->readtimer.data = (unsigned long)dev;
|
|
|
- dev->readtimer.expires = jiffies + msecs_to_jiffies(50);
|
|
|
- add_timer(&dev->readtimer);
|
|
|
- }
|
|
|
+ if (dev->rdsstat == 0)
|
|
|
+ cadet_start_rds(dev);
|
|
|
if (dev->rdsin == dev->rdsout) {
|
|
|
if (file->f_flags & O_NONBLOCK) {
|
|
|
i = -EWOULDBLOCK;
|
|
|
goto unlock;
|
|
|
}
|
|
|
+ mutex_unlock(&dev->lock);
|
|
|
interruptible_sleep_on(&dev->read_queue);
|
|
|
+ mutex_lock(&dev->lock);
|
|
|
}
|
|
|
while (i < count && dev->rdsin != dev->rdsout)
|
|
|
readbuf[i++] = dev->rdsbuf[dev->rdsout++];
|
|
|
|
|
|
- if (copy_to_user(data, readbuf, i))
|
|
|
+ if (i && copy_to_user(data, readbuf, i))
|
|
|
i = -EFAULT;
|
|
|
unlock:
|
|
|
mutex_unlock(&dev->lock);
|
|
@@ -345,7 +353,12 @@ static int vidioc_g_tuner(struct file *file, void *priv,
|
|
|
v->rangehigh = 1728000; /* 108.0 MHz */
|
|
|
v->rxsubchans = cadet_getstereo(dev);
|
|
|
v->audmode = V4L2_TUNER_MODE_STEREO;
|
|
|
- v->rxsubchans |= V4L2_TUNER_SUB_RDS;
|
|
|
+ outb(3, dev->io);
|
|
|
+ outb(inb(dev->io + 1) & 0x7f, dev->io + 1);
|
|
|
+ mdelay(100);
|
|
|
+ outb(3, dev->io);
|
|
|
+ if (inb(dev->io + 1) & 0x80)
|
|
|
+ v->rxsubchans |= V4L2_TUNER_SUB_RDS;
|
|
|
break;
|
|
|
case 1:
|
|
|
strlcpy(v->name, "AM", sizeof(v->name));
|
|
@@ -455,9 +468,16 @@ static int cadet_release(struct file *file)
|
|
|
static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait)
|
|
|
{
|
|
|
struct cadet *dev = video_drvdata(file);
|
|
|
+ unsigned long req_events = poll_requested_events(wait);
|
|
|
unsigned int res = v4l2_ctrl_poll(file, wait);
|
|
|
|
|
|
poll_wait(file, &dev->read_queue, wait);
|
|
|
+ if (dev->rdsstat == 0 && (req_events & (POLLIN | POLLRDNORM))) {
|
|
|
+ mutex_lock(&dev->lock);
|
|
|
+ if (dev->rdsstat == 0)
|
|
|
+ cadet_start_rds(dev);
|
|
|
+ mutex_unlock(&dev->lock);
|
|
|
+ }
|
|
|
if (dev->rdsin != dev->rdsout)
|
|
|
res |= POLLIN | POLLRDNORM;
|
|
|
return res;
|
|
@@ -628,6 +648,8 @@ static void __exit cadet_exit(void)
|
|
|
video_unregister_device(&dev->vdev);
|
|
|
v4l2_ctrl_handler_free(&dev->ctrl_handler);
|
|
|
v4l2_device_unregister(&dev->v4l2_dev);
|
|
|
+ outb(7, dev->io); /* Mute */
|
|
|
+ outb(0x00, dev->io + 1);
|
|
|
release_region(dev->io, 2);
|
|
|
pnp_unregister_driver(&cadet_pnp_driver);
|
|
|
}
|