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.c305
1 files changed, 62 insertions, 243 deletions
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c
index 0e740c98786c..969cf494d85b 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -196,9 +196,9 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
196 } 196 }
197 197
198 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) 198 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
199 dev_warn(&radio->videodev->dev, "tune does not complete\n"); 199 dev_warn(&radio->videodev.dev, "tune does not complete\n");
200 if (timed_out) 200 if (timed_out)
201 dev_warn(&radio->videodev->dev, 201 dev_warn(&radio->videodev.dev,
202 "tune timed out after %u ms\n", tune_timeout); 202 "tune timed out after %u ms\n", tune_timeout);
203 203
204stop: 204stop:
@@ -262,7 +262,7 @@ static int si470x_get_freq(struct si470x_device *radio, unsigned int *freq)
262 */ 262 */
263int si470x_set_freq(struct si470x_device *radio, unsigned int freq) 263int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
264{ 264{
265 unsigned int spacing, band_bottom; 265 unsigned int spacing, band_bottom, band_top;
266 unsigned short chan; 266 unsigned short chan;
267 267
268 /* Spacing (kHz) */ 268 /* Spacing (kHz) */
@@ -278,19 +278,26 @@ int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
278 spacing = 0.050 * FREQ_MUL; break; 278 spacing = 0.050 * FREQ_MUL; break;
279 }; 279 };
280 280
281 /* Bottom of Band (MHz) */ 281 /* Bottom/Top of Band (MHz) */
282 switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) { 282 switch ((radio->registers[SYSCONFIG2] & SYSCONFIG2_BAND) >> 6) {
283 /* 0: 87.5 - 108 MHz (USA, Europe) */ 283 /* 0: 87.5 - 108 MHz (USA, Europe) */
284 case 0: 284 case 0:
285 band_bottom = 87.5 * FREQ_MUL; break; 285 band_bottom = 87.5 * FREQ_MUL;
286 band_top = 108 * FREQ_MUL;
287 break;
286 /* 1: 76 - 108 MHz (Japan wide band) */ 288 /* 1: 76 - 108 MHz (Japan wide band) */
287 default: 289 default:
288 band_bottom = 76 * FREQ_MUL; break; 290 band_bottom = 76 * FREQ_MUL;
291 band_top = 108 * FREQ_MUL;
292 break;
289 /* 2: 76 - 90 MHz (Japan) */ 293 /* 2: 76 - 90 MHz (Japan) */
290 case 2: 294 case 2:
291 band_bottom = 76 * FREQ_MUL; break; 295 band_bottom = 76 * FREQ_MUL;
296 band_top = 90 * FREQ_MUL;
297 break;
292 }; 298 };
293 299
300 freq = clamp(freq, band_bottom, band_top);
294 /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */ 301 /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / Spacing (kHz) */
295 chan = (freq - band_bottom) / spacing; 302 chan = (freq - band_bottom) / spacing;
296 303
@@ -320,7 +327,7 @@ static int si470x_set_seek(struct si470x_device *radio,
320 radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP; 327 radio->registers[POWERCFG] &= ~POWERCFG_SEEKUP;
321 retval = si470x_set_register(radio, POWERCFG); 328 retval = si470x_set_register(radio, POWERCFG);
322 if (retval < 0) 329 if (retval < 0)
323 goto done; 330 return retval;
324 331
325 /* currently I2C driver only uses interrupt way to seek */ 332 /* currently I2C driver only uses interrupt way to seek */
326 if (radio->stci_enabled) { 333 if (radio->stci_enabled) {
@@ -344,24 +351,19 @@ static int si470x_set_seek(struct si470x_device *radio,
344 } 351 }
345 352
346 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) 353 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
347 dev_warn(&radio->videodev->dev, "seek does not complete\n"); 354 dev_warn(&radio->videodev.dev, "seek does not complete\n");
348 if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) 355 if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
349 dev_warn(&radio->videodev->dev, 356 dev_warn(&radio->videodev.dev,
350 "seek failed / band limit reached\n"); 357 "seek failed / band limit reached\n");
351 if (timed_out)
352 dev_warn(&radio->videodev->dev,
353 "seek timed out after %u ms\n", seek_timeout);
354 358
355stop: 359stop:
356 /* stop seeking */ 360 /* stop seeking */
357 radio->registers[POWERCFG] &= ~POWERCFG_SEEK; 361 radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
358 retval = si470x_set_register(radio, POWERCFG); 362 retval = si470x_set_register(radio, POWERCFG);
359 363
360done:
361 /* try again, if timed out */ 364 /* try again, if timed out */
362 if ((retval == 0) && timed_out) 365 if (retval == 0 && timed_out)
363 retval = -EAGAIN; 366 return -EAGAIN;
364
365 return retval; 367 return retval;
366} 368}
367 369
@@ -463,7 +465,6 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
463 unsigned int block_count = 0; 465 unsigned int block_count = 0;
464 466
465 /* switch on rds reception */ 467 /* switch on rds reception */
466 mutex_lock(&radio->lock);
467 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 468 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
468 si470x_rds_on(radio); 469 si470x_rds_on(radio);
469 470
@@ -505,7 +506,6 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
505 } 506 }
506 507
507done: 508done:
508 mutex_unlock(&radio->lock);
509 return retval; 509 return retval;
510} 510}
511 511
@@ -517,19 +517,19 @@ static unsigned int si470x_fops_poll(struct file *file,
517 struct poll_table_struct *pts) 517 struct poll_table_struct *pts)
518{ 518{
519 struct si470x_device *radio = video_drvdata(file); 519 struct si470x_device *radio = video_drvdata(file);
520 int retval = 0; 520 unsigned long req_events = poll_requested_events(pts);
521 int retval = v4l2_ctrl_poll(file, pts);
521 522
522 /* switch on rds reception */ 523 if (req_events & (POLLIN | POLLRDNORM)) {
523 524 /* switch on rds reception */
524 mutex_lock(&radio->lock); 525 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
525 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 526 si470x_rds_on(radio);
526 si470x_rds_on(radio);
527 mutex_unlock(&radio->lock);
528 527
529 poll_wait(file, &radio->read_queue, pts); 528 poll_wait(file, &radio->read_queue, pts);
530 529
531 if (radio->rd_index != radio->wr_index) 530 if (radio->rd_index != radio->wr_index)
532 retval = POLLIN | POLLRDNORM; 531 retval |= POLLIN | POLLRDNORM;
532 }
533 533
534 return retval; 534 return retval;
535} 535}
@@ -553,134 +553,26 @@ static const struct v4l2_file_operations si470x_fops = {
553 * Video4Linux Interface 553 * Video4Linux Interface
554 **************************************************************************/ 554 **************************************************************************/
555 555
556/*
557 * si470x_vidioc_queryctrl - enumerate control items
558 */
559static int si470x_vidioc_queryctrl(struct file *file, void *priv,
560 struct v4l2_queryctrl *qc)
561{
562 struct si470x_device *radio = video_drvdata(file);
563 int retval = -EINVAL;
564
565 /* abort if qc->id is below V4L2_CID_BASE */
566 if (qc->id < V4L2_CID_BASE)
567 goto done;
568
569 /* search video control */
570 switch (qc->id) {
571 case V4L2_CID_AUDIO_VOLUME:
572 return v4l2_ctrl_query_fill(qc, 0, 15, 1, 15);
573 case V4L2_CID_AUDIO_MUTE:
574 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
575 }
576
577 /* disable unsupported base controls */
578 /* to satisfy kradio and such apps */
579 if ((retval == -EINVAL) && (qc->id < V4L2_CID_LASTP1)) {
580 qc->flags = V4L2_CTRL_FLAG_DISABLED;
581 retval = 0;
582 }
583 556
584done: 557static int si470x_s_ctrl(struct v4l2_ctrl *ctrl)
585 if (retval < 0)
586 dev_warn(&radio->videodev->dev,
587 "query controls failed with %d\n", retval);
588 return retval;
589}
590
591
592/*
593 * si470x_vidioc_g_ctrl - get the value of a control
594 */
595static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
596 struct v4l2_control *ctrl)
597{
598 struct si470x_device *radio = video_drvdata(file);
599 int retval = 0;
600
601 mutex_lock(&radio->lock);
602 /* safety checks */
603 retval = si470x_disconnect_check(radio);
604 if (retval)
605 goto done;
606
607 switch (ctrl->id) {
608 case V4L2_CID_AUDIO_VOLUME:
609 ctrl->value = radio->registers[SYSCONFIG2] &
610 SYSCONFIG2_VOLUME;
611 break;
612 case V4L2_CID_AUDIO_MUTE:
613 ctrl->value = ((radio->registers[POWERCFG] &
614 POWERCFG_DMUTE) == 0) ? 1 : 0;
615 break;
616 default:
617 retval = -EINVAL;
618 }
619
620done:
621 if (retval < 0)
622 dev_warn(&radio->videodev->dev,
623 "get control failed with %d\n", retval);
624
625 mutex_unlock(&radio->lock);
626 return retval;
627}
628
629
630/*
631 * si470x_vidioc_s_ctrl - set the value of a control
632 */
633static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
634 struct v4l2_control *ctrl)
635{ 558{
636 struct si470x_device *radio = video_drvdata(file); 559 struct si470x_device *radio =
637 int retval = 0; 560 container_of(ctrl->handler, struct si470x_device, hdl);
638
639 mutex_lock(&radio->lock);
640 /* safety checks */
641 retval = si470x_disconnect_check(radio);
642 if (retval)
643 goto done;
644 561
645 switch (ctrl->id) { 562 switch (ctrl->id) {
646 case V4L2_CID_AUDIO_VOLUME: 563 case V4L2_CID_AUDIO_VOLUME:
647 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; 564 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
648 radio->registers[SYSCONFIG2] |= ctrl->value; 565 radio->registers[SYSCONFIG2] |= ctrl->val;
649 retval = si470x_set_register(radio, SYSCONFIG2); 566 return si470x_set_register(radio, SYSCONFIG2);
650 break;
651 case V4L2_CID_AUDIO_MUTE: 567 case V4L2_CID_AUDIO_MUTE:
652 if (ctrl->value == 1) 568 if (ctrl->val)
653 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; 569 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
654 else 570 else
655 radio->registers[POWERCFG] |= POWERCFG_DMUTE; 571 radio->registers[POWERCFG] |= POWERCFG_DMUTE;
656 retval = si470x_set_register(radio, POWERCFG); 572 return si470x_set_register(radio, POWERCFG);
657 break;
658 default: 573 default:
659 retval = -EINVAL; 574 return -EINVAL;
660 } 575 }
661
662done:
663 if (retval < 0)
664 dev_warn(&radio->videodev->dev,
665 "set control failed with %d\n", retval);
666 mutex_unlock(&radio->lock);
667 return retval;
668}
669
670
671/*
672 * si470x_vidioc_g_audio - get audio attributes
673 */
674static int si470x_vidioc_g_audio(struct file *file, void *priv,
675 struct v4l2_audio *audio)
676{
677 /* driver constants */
678 audio->index = 0;
679 strcpy(audio->name, "Radio");
680 audio->capability = V4L2_AUDCAP_STEREO;
681 audio->mode = 0;
682
683 return 0;
684} 576}
685 577
686 578
@@ -691,22 +583,14 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
691 struct v4l2_tuner *tuner) 583 struct v4l2_tuner *tuner)
692{ 584{
693 struct si470x_device *radio = video_drvdata(file); 585 struct si470x_device *radio = video_drvdata(file);
694 int retval = 0; 586 int retval;
695
696 mutex_lock(&radio->lock);
697 /* safety checks */
698 retval = si470x_disconnect_check(radio);
699 if (retval)
700 goto done;
701 587
702 if (tuner->index != 0) { 588 if (tuner->index != 0)
703 retval = -EINVAL; 589 return -EINVAL;
704 goto done;
705 }
706 590
707 retval = si470x_get_register(radio, STATUSRSSI); 591 retval = si470x_get_register(radio, STATUSRSSI);
708 if (retval < 0) 592 if (retval < 0)
709 goto done; 593 return retval;
710 594
711 /* driver constants */ 595 /* driver constants */
712 strcpy(tuner->name, "FM"); 596 strcpy(tuner->name, "FM");
@@ -737,7 +621,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
737 if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0) 621 if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
738 tuner->rxsubchans = V4L2_TUNER_SUB_MONO; 622 tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
739 else 623 else
740 tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; 624 tuner->rxsubchans = V4L2_TUNER_SUB_STEREO;
741 /* If there is a reliable method of detecting an RDS channel, 625 /* If there is a reliable method of detecting an RDS channel,
742 then this code should check for that before setting this 626 then this code should check for that before setting this
743 RDS subchannel. */ 627 RDS subchannel. */
@@ -754,16 +638,13 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
754 tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI); 638 tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
755 /* the ideal factor is 0xffff/75 = 873,8 */ 639 /* the ideal factor is 0xffff/75 = 873,8 */
756 tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10); 640 tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
641 if (tuner->signal > 0xffff)
642 tuner->signal = 0xffff;
757 643
758 /* automatic frequency control: -1: freq to low, 1 freq to high */ 644 /* automatic frequency control: -1: freq to low, 1 freq to high */
759 /* AFCRL does only indicate that freq. differs, not if too low/high */ 645 /* AFCRL does only indicate that freq. differs, not if too low/high */
760 tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0; 646 tuner->afc = (radio->registers[STATUSRSSI] & STATUSRSSI_AFCRL) ? 1 : 0;
761 647
762done:
763 if (retval < 0)
764 dev_warn(&radio->videodev->dev,
765 "get tuner failed with %d\n", retval);
766 mutex_unlock(&radio->lock);
767 return retval; 648 return retval;
768} 649}
769 650
@@ -775,16 +656,9 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
775 struct v4l2_tuner *tuner) 656 struct v4l2_tuner *tuner)
776{ 657{
777 struct si470x_device *radio = video_drvdata(file); 658 struct si470x_device *radio = video_drvdata(file);
778 int retval = 0;
779
780 mutex_lock(&radio->lock);
781 /* safety checks */
782 retval = si470x_disconnect_check(radio);
783 if (retval)
784 goto done;
785 659
786 if (tuner->index != 0) 660 if (tuner->index != 0)
787 goto done; 661 return -EINVAL;
788 662
789 /* mono/stereo selector */ 663 /* mono/stereo selector */
790 switch (tuner->audmode) { 664 switch (tuner->audmode) {
@@ -792,20 +666,12 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
792 radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */ 666 radio->registers[POWERCFG] |= POWERCFG_MONO; /* force mono */
793 break; 667 break;
794 case V4L2_TUNER_MODE_STEREO: 668 case V4L2_TUNER_MODE_STEREO:
669 default:
795 radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */ 670 radio->registers[POWERCFG] &= ~POWERCFG_MONO; /* try stereo */
796 break; 671 break;
797 default:
798 goto done;
799 } 672 }
800 673
801 retval = si470x_set_register(radio, POWERCFG); 674 return si470x_set_register(radio, POWERCFG);
802
803done:
804 if (retval < 0)
805 dev_warn(&radio->videodev->dev,
806 "set tuner failed with %d\n", retval);
807 mutex_unlock(&radio->lock);
808 return retval;
809} 675}
810 676
811 677
@@ -816,28 +682,12 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
816 struct v4l2_frequency *freq) 682 struct v4l2_frequency *freq)
817{ 683{
818 struct si470x_device *radio = video_drvdata(file); 684 struct si470x_device *radio = video_drvdata(file);
819 int retval = 0;
820
821 /* safety checks */
822 mutex_lock(&radio->lock);
823 retval = si470x_disconnect_check(radio);
824 if (retval)
825 goto done;
826 685
827 if (freq->tuner != 0) { 686 if (freq->tuner != 0)
828 retval = -EINVAL; 687 return -EINVAL;
829 goto done;
830 }
831 688
832 freq->type = V4L2_TUNER_RADIO; 689 freq->type = V4L2_TUNER_RADIO;
833 retval = si470x_get_freq(radio, &freq->frequency); 690 return si470x_get_freq(radio, &freq->frequency);
834
835done:
836 if (retval < 0)
837 dev_warn(&radio->videodev->dev,
838 "get frequency failed with %d\n", retval);
839 mutex_unlock(&radio->lock);
840 return retval;
841} 691}
842 692
843 693
@@ -848,27 +698,11 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
848 struct v4l2_frequency *freq) 698 struct v4l2_frequency *freq)
849{ 699{
850 struct si470x_device *radio = video_drvdata(file); 700 struct si470x_device *radio = video_drvdata(file);
851 int retval = 0;
852
853 mutex_lock(&radio->lock);
854 /* safety checks */
855 retval = si470x_disconnect_check(radio);
856 if (retval)
857 goto done;
858 701
859 if (freq->tuner != 0) { 702 if (freq->tuner != 0)
860 retval = -EINVAL; 703 return -EINVAL;
861 goto done;
862 }
863 704
864 retval = si470x_set_freq(radio, freq->frequency); 705 return si470x_set_freq(radio, freq->frequency);
865
866done:
867 if (retval < 0)
868 dev_warn(&radio->videodev->dev,
869 "set frequency failed with %d\n", retval);
870 mutex_unlock(&radio->lock);
871 return retval;
872} 706}
873 707
874 708
@@ -879,44 +713,29 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
879 struct v4l2_hw_freq_seek *seek) 713 struct v4l2_hw_freq_seek *seek)
880{ 714{
881 struct si470x_device *radio = video_drvdata(file); 715 struct si470x_device *radio = video_drvdata(file);
882 int retval = 0;
883
884 mutex_lock(&radio->lock);
885 /* safety checks */
886 retval = si470x_disconnect_check(radio);
887 if (retval)
888 goto done;
889
890 if (seek->tuner != 0) {
891 retval = -EINVAL;
892 goto done;
893 }
894 716
895 retval = si470x_set_seek(radio, seek->wrap_around, seek->seek_upward); 717 if (seek->tuner != 0)
718 return -EINVAL;
896 719
897done: 720 return si470x_set_seek(radio, seek->wrap_around, seek->seek_upward);
898 if (retval < 0)
899 dev_warn(&radio->videodev->dev,
900 "set hardware frequency seek failed with %d\n", retval);
901 mutex_unlock(&radio->lock);
902 return retval;
903} 721}
904 722
723const struct v4l2_ctrl_ops si470x_ctrl_ops = {
724 .s_ctrl = si470x_s_ctrl,
725};
905 726
906/* 727/*
907 * si470x_ioctl_ops - video device ioctl operations 728 * si470x_ioctl_ops - video device ioctl operations
908 */ 729 */
909static const struct v4l2_ioctl_ops si470x_ioctl_ops = { 730static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
910 .vidioc_querycap = si470x_vidioc_querycap, 731 .vidioc_querycap = si470x_vidioc_querycap,
911 .vidioc_queryctrl = si470x_vidioc_queryctrl,
912 .vidioc_g_ctrl = si470x_vidioc_g_ctrl,
913 .vidioc_s_ctrl = si470x_vidioc_s_ctrl,
914 .vidioc_g_audio = si470x_vidioc_g_audio,
915 .vidioc_g_tuner = si470x_vidioc_g_tuner, 732 .vidioc_g_tuner = si470x_vidioc_g_tuner,
916 .vidioc_s_tuner = si470x_vidioc_s_tuner, 733 .vidioc_s_tuner = si470x_vidioc_s_tuner,
917 .vidioc_g_frequency = si470x_vidioc_g_frequency, 734 .vidioc_g_frequency = si470x_vidioc_g_frequency,
918 .vidioc_s_frequency = si470x_vidioc_s_frequency, 735 .vidioc_s_frequency = si470x_vidioc_s_frequency,
919 .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek, 736 .vidioc_s_hw_freq_seek = si470x_vidioc_s_hw_freq_seek,
737 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
738 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
920}; 739};
921 740
922 741
@@ -926,6 +745,6 @@ static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
926struct video_device si470x_viddev_template = { 745struct video_device si470x_viddev_template = {
927 .fops = &si470x_fops, 746 .fops = &si470x_fops,
928 .name = DRIVER_NAME, 747 .name = DRIVER_NAME,
929 .release = video_device_release, 748 .release = video_device_release_empty,
930 .ioctl_ops = &si470x_ioctl_ops, 749 .ioctl_ops = &si470x_ioctl_ops,
931}; 750};