aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-07-02 08:46:46 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-07-30 19:23:09 -0400
commitcc0d32665f9f8d4e7297a470e91b8848c7f0436c (patch)
tree9520764083b3d4db657b30840ed2bf5b92324f85 /drivers/media/radio
parentb54c97db7f51c47c361533956db18c8b191033b5 (diff)
[media] radio-cadet: fix RDS handling
The current RDS code suffered from bit rot. Clean it up and make it work again. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/radio')
-rw-r--r--drivers/media/radio/radio-cadet.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 93536b7e75c7..d1fb42746fc2 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -71,7 +71,7 @@ struct cadet {
71 int sigstrength; 71 int sigstrength;
72 wait_queue_head_t read_queue; 72 wait_queue_head_t read_queue;
73 struct timer_list readtimer; 73 struct timer_list readtimer;
74 __u8 rdsin, rdsout, rdsstat; 74 u8 rdsin, rdsout, rdsstat;
75 unsigned char rdsbuf[RDS_BUFFER]; 75 unsigned char rdsbuf[RDS_BUFFER];
76 struct mutex lock; 76 struct mutex lock;
77 int reading; 77 int reading;
@@ -85,8 +85,8 @@ static struct cadet cadet_card;
85 * strength value. These values are in microvolts of RF at the tuner's input. 85 * strength value. These values are in microvolts of RF at the tuner's input.
86 */ 86 */
87static __u16 sigtable[2][4] = { 87static __u16 sigtable[2][4] = {
88 { 5, 10, 30, 150 }, 88 { 2185, 4369, 13107, 65535 },
89 { 28, 40, 63, 1000 } 89 { 1835, 2621, 4128, 65535 }
90}; 90};
91 91
92 92
@@ -240,10 +240,13 @@ static void cadet_setfreq(struct cadet *dev, unsigned freq)
240 cadet_gettune(dev); 240 cadet_gettune(dev);
241 if ((dev->tunestat & 0x40) == 0) { /* Tuned */ 241 if ((dev->tunestat & 0x40) == 0) { /* Tuned */
242 dev->sigstrength = sigtable[dev->curtuner][j]; 242 dev->sigstrength = sigtable[dev->curtuner][j];
243 return; 243 goto reset_rds;
244 } 244 }
245 } 245 }
246 dev->sigstrength = 0; 246 dev->sigstrength = 0;
247reset_rds:
248 outb(3, dev->io);
249 outb(inb(dev->io + 1) & 0x7f, dev->io + 1);
247} 250}
248 251
249 252
@@ -259,7 +262,7 @@ static void cadet_handler(unsigned long data)
259 outb(0x80, dev->io); /* Select RDS fifo */ 262 outb(0x80, dev->io); /* Select RDS fifo */
260 while ((inb(dev->io) & 0x80) != 0) { 263 while ((inb(dev->io) & 0x80) != 0) {
261 dev->rdsbuf[dev->rdsin] = inb(dev->io + 1); 264 dev->rdsbuf[dev->rdsin] = inb(dev->io + 1);
262 if (dev->rdsin == dev->rdsout) 265 if (dev->rdsin + 1 == dev->rdsout)
263 printk(KERN_WARNING "cadet: RDS buffer overflow\n"); 266 printk(KERN_WARNING "cadet: RDS buffer overflow\n");
264 else 267 else
265 dev->rdsin++; 268 dev->rdsin++;
@@ -278,11 +281,21 @@ static void cadet_handler(unsigned long data)
278 */ 281 */
279 init_timer(&dev->readtimer); 282 init_timer(&dev->readtimer);
280 dev->readtimer.function = cadet_handler; 283 dev->readtimer.function = cadet_handler;
281 dev->readtimer.data = (unsigned long)0; 284 dev->readtimer.data = data;
282 dev->readtimer.expires = jiffies + msecs_to_jiffies(50); 285 dev->readtimer.expires = jiffies + msecs_to_jiffies(50);
283 add_timer(&dev->readtimer); 286 add_timer(&dev->readtimer);
284} 287}
285 288
289static void cadet_start_rds(struct cadet *dev)
290{
291 dev->rdsstat = 1;
292 outb(0x80, dev->io); /* Select RDS fifo */
293 init_timer(&dev->readtimer);
294 dev->readtimer.function = cadet_handler;
295 dev->readtimer.data = (unsigned long)dev;
296 dev->readtimer.expires = jiffies + msecs_to_jiffies(50);
297 add_timer(&dev->readtimer);
298}
286 299
287static ssize_t cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) 300static ssize_t cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
288{ 301{
@@ -291,26 +304,21 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
291 int i = 0; 304 int i = 0;
292 305
293 mutex_lock(&dev->lock); 306 mutex_lock(&dev->lock);
294 if (dev->rdsstat == 0) { 307 if (dev->rdsstat == 0)
295 dev->rdsstat = 1; 308 cadet_start_rds(dev);
296 outb(0x80, dev->io); /* Select RDS fifo */
297 init_timer(&dev->readtimer);
298 dev->readtimer.function = cadet_handler;
299 dev->readtimer.data = (unsigned long)dev;
300 dev->readtimer.expires = jiffies + msecs_to_jiffies(50);
301 add_timer(&dev->readtimer);
302 }
303 if (dev->rdsin == dev->rdsout) { 309 if (dev->rdsin == dev->rdsout) {
304 if (file->f_flags & O_NONBLOCK) { 310 if (file->f_flags & O_NONBLOCK) {
305 i = -EWOULDBLOCK; 311 i = -EWOULDBLOCK;
306 goto unlock; 312 goto unlock;
307 } 313 }
314 mutex_unlock(&dev->lock);
308 interruptible_sleep_on(&dev->read_queue); 315 interruptible_sleep_on(&dev->read_queue);
316 mutex_lock(&dev->lock);
309 } 317 }
310 while (i < count && dev->rdsin != dev->rdsout) 318 while (i < count && dev->rdsin != dev->rdsout)
311 readbuf[i++] = dev->rdsbuf[dev->rdsout++]; 319 readbuf[i++] = dev->rdsbuf[dev->rdsout++];
312 320
313 if (copy_to_user(data, readbuf, i)) 321 if (i && copy_to_user(data, readbuf, i))
314 i = -EFAULT; 322 i = -EFAULT;
315unlock: 323unlock:
316 mutex_unlock(&dev->lock); 324 mutex_unlock(&dev->lock);
@@ -345,7 +353,12 @@ static int vidioc_g_tuner(struct file *file, void *priv,
345 v->rangehigh = 1728000; /* 108.0 MHz */ 353 v->rangehigh = 1728000; /* 108.0 MHz */
346 v->rxsubchans = cadet_getstereo(dev); 354 v->rxsubchans = cadet_getstereo(dev);
347 v->audmode = V4L2_TUNER_MODE_STEREO; 355 v->audmode = V4L2_TUNER_MODE_STEREO;
348 v->rxsubchans |= V4L2_TUNER_SUB_RDS; 356 outb(3, dev->io);
357 outb(inb(dev->io + 1) & 0x7f, dev->io + 1);
358 mdelay(100);
359 outb(3, dev->io);
360 if (inb(dev->io + 1) & 0x80)
361 v->rxsubchans |= V4L2_TUNER_SUB_RDS;
349 break; 362 break;
350 case 1: 363 case 1:
351 strlcpy(v->name, "AM", sizeof(v->name)); 364 strlcpy(v->name, "AM", sizeof(v->name));
@@ -455,9 +468,16 @@ static int cadet_release(struct file *file)
455static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait) 468static unsigned int cadet_poll(struct file *file, struct poll_table_struct *wait)
456{ 469{
457 struct cadet *dev = video_drvdata(file); 470 struct cadet *dev = video_drvdata(file);
471 unsigned long req_events = poll_requested_events(wait);
458 unsigned int res = v4l2_ctrl_poll(file, wait); 472 unsigned int res = v4l2_ctrl_poll(file, wait);
459 473
460 poll_wait(file, &dev->read_queue, wait); 474 poll_wait(file, &dev->read_queue, wait);
475 if (dev->rdsstat == 0 && (req_events & (POLLIN | POLLRDNORM))) {
476 mutex_lock(&dev->lock);
477 if (dev->rdsstat == 0)
478 cadet_start_rds(dev);
479 mutex_unlock(&dev->lock);
480 }
461 if (dev->rdsin != dev->rdsout) 481 if (dev->rdsin != dev->rdsout)
462 res |= POLLIN | POLLRDNORM; 482 res |= POLLIN | POLLRDNORM;
463 return res; 483 return res;
@@ -628,6 +648,8 @@ static void __exit cadet_exit(void)
628 video_unregister_device(&dev->vdev); 648 video_unregister_device(&dev->vdev);
629 v4l2_ctrl_handler_free(&dev->ctrl_handler); 649 v4l2_ctrl_handler_free(&dev->ctrl_handler);
630 v4l2_device_unregister(&dev->v4l2_dev); 650 v4l2_device_unregister(&dev->v4l2_dev);
651 outb(7, dev->io); /* Mute */
652 outb(0x00, dev->io + 1);
631 release_region(dev->io, 2); 653 release_region(dev->io, 2);
632 pnp_unregister_driver(&cadet_pnp_driver); 654 pnp_unregister_driver(&cadet_pnp_driver);
633} 655}