aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/si470x/radio-si470x-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio/si470x/radio-si470x-common.c')
-rw-r--r--drivers/media/radio/si470x/radio-si470x-common.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c
index f33315f2c543..4da0f150c6e2 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -426,6 +426,104 @@ int si470x_rds_on(struct si470x_device *radio)
426 426
427 427
428/************************************************************************** 428/**************************************************************************
429 * File Operations Interface
430 **************************************************************************/
431
432/*
433 * si470x_fops_read - read RDS data
434 */
435static ssize_t si470x_fops_read(struct file *file, char __user *buf,
436 size_t count, loff_t *ppos)
437{
438 struct si470x_device *radio = video_drvdata(file);
439 int retval = 0;
440 unsigned int block_count = 0;
441
442 /* switch on rds reception */
443 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
444 si470x_rds_on(radio);
445
446 /* block if no new data available */
447 while (radio->wr_index == radio->rd_index) {
448 if (file->f_flags & O_NONBLOCK) {
449 retval = -EWOULDBLOCK;
450 goto done;
451 }
452 if (wait_event_interruptible(radio->read_queue,
453 radio->wr_index != radio->rd_index) < 0) {
454 retval = -EINTR;
455 goto done;
456 }
457 }
458
459 /* calculate block count from byte count */
460 count /= 3;
461
462 /* copy RDS block out of internal buffer and to user buffer */
463 mutex_lock(&radio->lock);
464 while (block_count < count) {
465 if (radio->rd_index == radio->wr_index)
466 break;
467
468 /* always transfer rds complete blocks */
469 if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
470 /* retval = -EFAULT; */
471 break;
472
473 /* increment and wrap read pointer */
474 radio->rd_index += 3;
475 if (radio->rd_index >= radio->buf_size)
476 radio->rd_index = 0;
477
478 /* increment counters */
479 block_count++;
480 buf += 3;
481 retval += 3;
482 }
483 mutex_unlock(&radio->lock);
484
485done:
486 return retval;
487}
488
489
490/*
491 * si470x_fops_poll - poll RDS data
492 */
493static unsigned int si470x_fops_poll(struct file *file,
494 struct poll_table_struct *pts)
495{
496 struct si470x_device *radio = video_drvdata(file);
497 int retval = 0;
498
499 /* switch on rds reception */
500 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
501 si470x_rds_on(radio);
502
503 poll_wait(file, &radio->read_queue, pts);
504
505 if (radio->rd_index != radio->wr_index)
506 retval = POLLIN | POLLRDNORM;
507
508 return retval;
509}
510
511
512/*
513 * si470x_fops - file operations interface
514 */
515static const struct v4l2_file_operations si470x_fops = {
516 .owner = THIS_MODULE,
517 .read = si470x_fops_read,
518 .poll = si470x_fops_poll,
519 .ioctl = video_ioctl2,
520 .open = si470x_fops_open,
521 .release = si470x_fops_release,
522};
523
524
525
526/**************************************************************************
429 * Video4Linux Interface 527 * Video4Linux Interface
430 **************************************************************************/ 528 **************************************************************************/
431 529