aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/si470x
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-05-04 08:16:57 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-14 12:44:02 -0400
commit4967d53dbbcebf590c5ae07c0aea38619ac51954 (patch)
tree0591424809d99161f6c420d263c6e23cedd8b724 /drivers/media/radio/si470x
parent528f0f785c042c80294708c5ae2c8005b4a0ee60 (diff)
[media] si470x: Clean up, introduce the control framework
This cleans up the code and si470x now uses the proper v4l2 frameworks and passes most of the v4l2-compliance tests. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Tobias Lorenz <tobias.lorenz@gmx.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/radio/si470x')
-rw-r--r--drivers/media/radio/si470x/radio-si470x-common.c193
-rw-r--r--drivers/media/radio/si470x/radio-si470x-i2c.c65
-rw-r--r--drivers/media/radio/si470x/radio-si470x-usb.c146
-rw-r--r--drivers/media/radio/si470x/radio-si470x.h14
4 files changed, 105 insertions, 313 deletions
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c
index 0e740c98786c..de9475f4139e 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:
@@ -344,12 +344,12 @@ static int si470x_set_seek(struct si470x_device *radio,
344 } 344 }
345 345
346 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) 346 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
347 dev_warn(&radio->videodev->dev, "seek does not complete\n"); 347 dev_warn(&radio->videodev.dev, "seek does not complete\n");
348 if (radio->registers[STATUSRSSI] & STATUSRSSI_SF) 348 if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
349 dev_warn(&radio->videodev->dev, 349 dev_warn(&radio->videodev.dev,
350 "seek failed / band limit reached\n"); 350 "seek failed / band limit reached\n");
351 if (timed_out) 351 if (timed_out)
352 dev_warn(&radio->videodev->dev, 352 dev_warn(&radio->videodev.dev,
353 "seek timed out after %u ms\n", seek_timeout); 353 "seek timed out after %u ms\n", seek_timeout);
354 354
355stop: 355stop:
@@ -463,7 +463,6 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
463 unsigned int block_count = 0; 463 unsigned int block_count = 0;
464 464
465 /* switch on rds reception */ 465 /* switch on rds reception */
466 mutex_lock(&radio->lock);
467 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 466 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
468 si470x_rds_on(radio); 467 si470x_rds_on(radio);
469 468
@@ -505,7 +504,6 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
505 } 504 }
506 505
507done: 506done:
508 mutex_unlock(&radio->lock);
509 return retval; 507 return retval;
510} 508}
511 509
@@ -521,10 +519,8 @@ static unsigned int si470x_fops_poll(struct file *file,
521 519
522 /* switch on rds reception */ 520 /* switch on rds reception */
523 521
524 mutex_lock(&radio->lock);
525 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 522 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
526 si470x_rds_on(radio); 523 si470x_rds_on(radio);
527 mutex_unlock(&radio->lock);
528 524
529 poll_wait(file, &radio->read_queue, pts); 525 poll_wait(file, &radio->read_queue, pts);
530 526
@@ -553,134 +549,27 @@ static const struct v4l2_file_operations si470x_fops = {
553 * Video4Linux Interface 549 * Video4Linux Interface
554 **************************************************************************/ 550 **************************************************************************/
555 551
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 552
577 /* disable unsupported base controls */ 553static int si470x_s_ctrl(struct v4l2_ctrl *ctrl)
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
584done:
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{ 554{
598 struct si470x_device *radio = video_drvdata(file); 555 struct si470x_device *radio =
599 int retval = 0; 556 container_of(ctrl->handler, struct si470x_device, hdl);
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{
636 struct si470x_device *radio = video_drvdata(file);
637 int retval = 0;
638
639 mutex_lock(&radio->lock);
640 /* safety checks */
641 retval = si470x_disconnect_check(radio);
642 if (retval)
643 goto done;
644 557
645 switch (ctrl->id) { 558 switch (ctrl->id) {
646 case V4L2_CID_AUDIO_VOLUME: 559 case V4L2_CID_AUDIO_VOLUME:
647 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; 560 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
648 radio->registers[SYSCONFIG2] |= ctrl->value; 561 radio->registers[SYSCONFIG2] |= ctrl->val;
649 retval = si470x_set_register(radio, SYSCONFIG2); 562 return si470x_set_register(radio, SYSCONFIG2);
650 break;
651 case V4L2_CID_AUDIO_MUTE: 563 case V4L2_CID_AUDIO_MUTE:
652 if (ctrl->value == 1) 564 if (ctrl->val)
653 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE; 565 radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
654 else 566 else
655 radio->registers[POWERCFG] |= POWERCFG_DMUTE; 567 radio->registers[POWERCFG] |= POWERCFG_DMUTE;
656 retval = si470x_set_register(radio, POWERCFG); 568 return si470x_set_register(radio, POWERCFG);
657 break; 569 break;
658 default: 570 default:
659 retval = -EINVAL; 571 return -EINVAL;
660 } 572 }
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} 573}
685 574
686 575
@@ -693,12 +582,6 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
693 struct si470x_device *radio = video_drvdata(file); 582 struct si470x_device *radio = video_drvdata(file);
694 int retval = 0; 583 int retval = 0;
695 584
696 mutex_lock(&radio->lock);
697 /* safety checks */
698 retval = si470x_disconnect_check(radio);
699 if (retval)
700 goto done;
701
702 if (tuner->index != 0) { 585 if (tuner->index != 0) {
703 retval = -EINVAL; 586 retval = -EINVAL;
704 goto done; 587 goto done;
@@ -737,7 +620,7 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
737 if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0) 620 if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
738 tuner->rxsubchans = V4L2_TUNER_SUB_MONO; 621 tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
739 else 622 else
740 tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; 623 tuner->rxsubchans = V4L2_TUNER_SUB_STEREO;
741 /* If there is a reliable method of detecting an RDS channel, 624 /* If there is a reliable method of detecting an RDS channel,
742 then this code should check for that before setting this 625 then this code should check for that before setting this
743 RDS subchannel. */ 626 RDS subchannel. */
@@ -761,9 +644,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
761 644
762done: 645done:
763 if (retval < 0) 646 if (retval < 0)
764 dev_warn(&radio->videodev->dev, 647 dev_warn(&radio->videodev.dev,
765 "get tuner failed with %d\n", retval); 648 "get tuner failed with %d\n", retval);
766 mutex_unlock(&radio->lock);
767 return retval; 649 return retval;
768} 650}
769 651
@@ -777,12 +659,6 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
777 struct si470x_device *radio = video_drvdata(file); 659 struct si470x_device *radio = video_drvdata(file);
778 int retval = 0; 660 int retval = 0;
779 661
780 mutex_lock(&radio->lock);
781 /* safety checks */
782 retval = si470x_disconnect_check(radio);
783 if (retval)
784 goto done;
785
786 if (tuner->index != 0) 662 if (tuner->index != 0)
787 goto done; 663 goto done;
788 664
@@ -802,9 +678,8 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
802 678
803done: 679done:
804 if (retval < 0) 680 if (retval < 0)
805 dev_warn(&radio->videodev->dev, 681 dev_warn(&radio->videodev.dev,
806 "set tuner failed with %d\n", retval); 682 "set tuner failed with %d\n", retval);
807 mutex_unlock(&radio->lock);
808 return retval; 683 return retval;
809} 684}
810 685
@@ -818,12 +693,6 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
818 struct si470x_device *radio = video_drvdata(file); 693 struct si470x_device *radio = video_drvdata(file);
819 int retval = 0; 694 int retval = 0;
820 695
821 /* safety checks */
822 mutex_lock(&radio->lock);
823 retval = si470x_disconnect_check(radio);
824 if (retval)
825 goto done;
826
827 if (freq->tuner != 0) { 696 if (freq->tuner != 0) {
828 retval = -EINVAL; 697 retval = -EINVAL;
829 goto done; 698 goto done;
@@ -834,9 +703,8 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
834 703
835done: 704done:
836 if (retval < 0) 705 if (retval < 0)
837 dev_warn(&radio->videodev->dev, 706 dev_warn(&radio->videodev.dev,
838 "get frequency failed with %d\n", retval); 707 "get frequency failed with %d\n", retval);
839 mutex_unlock(&radio->lock);
840 return retval; 708 return retval;
841} 709}
842 710
@@ -850,12 +718,6 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
850 struct si470x_device *radio = video_drvdata(file); 718 struct si470x_device *radio = video_drvdata(file);
851 int retval = 0; 719 int retval = 0;
852 720
853 mutex_lock(&radio->lock);
854 /* safety checks */
855 retval = si470x_disconnect_check(radio);
856 if (retval)
857 goto done;
858
859 if (freq->tuner != 0) { 721 if (freq->tuner != 0) {
860 retval = -EINVAL; 722 retval = -EINVAL;
861 goto done; 723 goto done;
@@ -865,9 +727,8 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
865 727
866done: 728done:
867 if (retval < 0) 729 if (retval < 0)
868 dev_warn(&radio->videodev->dev, 730 dev_warn(&radio->videodev.dev,
869 "set frequency failed with %d\n", retval); 731 "set frequency failed with %d\n", retval);
870 mutex_unlock(&radio->lock);
871 return retval; 732 return retval;
872} 733}
873 734
@@ -881,12 +742,6 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
881 struct si470x_device *radio = video_drvdata(file); 742 struct si470x_device *radio = video_drvdata(file);
882 int retval = 0; 743 int retval = 0;
883 744
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) { 745 if (seek->tuner != 0) {
891 retval = -EINVAL; 746 retval = -EINVAL;
892 goto done; 747 goto done;
@@ -896,22 +751,20 @@ static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
896 751
897done: 752done:
898 if (retval < 0) 753 if (retval < 0)
899 dev_warn(&radio->videodev->dev, 754 dev_warn(&radio->videodev.dev,
900 "set hardware frequency seek failed with %d\n", retval); 755 "set hardware frequency seek failed with %d\n", retval);
901 mutex_unlock(&radio->lock);
902 return retval; 756 return retval;
903} 757}
904 758
759const struct v4l2_ctrl_ops si470x_ctrl_ops = {
760 .s_ctrl = si470x_s_ctrl,
761};
905 762
906/* 763/*
907 * si470x_ioctl_ops - video device ioctl operations 764 * si470x_ioctl_ops - video device ioctl operations
908 */ 765 */
909static const struct v4l2_ioctl_ops si470x_ioctl_ops = { 766static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
910 .vidioc_querycap = si470x_vidioc_querycap, 767 .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, 768 .vidioc_g_tuner = si470x_vidioc_g_tuner,
916 .vidioc_s_tuner = si470x_vidioc_s_tuner, 769 .vidioc_s_tuner = si470x_vidioc_s_tuner,
917 .vidioc_g_frequency = si470x_vidioc_g_frequency, 770 .vidioc_g_frequency = si470x_vidioc_g_frequency,
@@ -926,6 +779,6 @@ static const struct v4l2_ioctl_ops si470x_ioctl_ops = {
926struct video_device si470x_viddev_template = { 779struct video_device si470x_viddev_template = {
927 .fops = &si470x_fops, 780 .fops = &si470x_fops,
928 .name = DRIVER_NAME, 781 .name = DRIVER_NAME,
929 .release = video_device_release, 782 .release = video_device_release_empty,
930 .ioctl_ops = &si470x_ioctl_ops, 783 .ioctl_ops = &si470x_ioctl_ops,
931}; 784};
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c
index 9b546a5523f3..a80044c5874e 100644
--- a/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -162,20 +162,6 @@ static int si470x_get_all_registers(struct si470x_device *radio)
162 162
163 163
164/************************************************************************** 164/**************************************************************************
165 * General Driver Functions - DISCONNECT_CHECK
166 **************************************************************************/
167
168/*
169 * si470x_disconnect_check - check whether radio disconnects
170 */
171int si470x_disconnect_check(struct si470x_device *radio)
172{
173 return 0;
174}
175
176
177
178/**************************************************************************
179 * File Operations Interface 165 * File Operations Interface
180 **************************************************************************/ 166 **************************************************************************/
181 167
@@ -185,12 +171,12 @@ int si470x_disconnect_check(struct si470x_device *radio)
185int si470x_fops_open(struct file *file) 171int si470x_fops_open(struct file *file)
186{ 172{
187 struct si470x_device *radio = video_drvdata(file); 173 struct si470x_device *radio = video_drvdata(file);
188 int retval = 0; 174 int retval = v4l2_fh_open(file);
189 175
190 mutex_lock(&radio->lock); 176 if (retval)
191 radio->users++; 177 return retval;
192 178
193 if (radio->users == 1) { 179 if (v4l2_fh_is_singular_file(file)) {
194 /* start radio */ 180 /* start radio */
195 retval = si470x_start(radio); 181 retval = si470x_start(radio);
196 if (retval < 0) 182 if (retval < 0)
@@ -205,7 +191,8 @@ int si470x_fops_open(struct file *file)
205 } 191 }
206 192
207done: 193done:
208 mutex_unlock(&radio->lock); 194 if (retval)
195 v4l2_fh_release(file);
209 return retval; 196 return retval;
210} 197}
211 198
@@ -216,21 +203,12 @@ done:
216int si470x_fops_release(struct file *file) 203int si470x_fops_release(struct file *file)
217{ 204{
218 struct si470x_device *radio = video_drvdata(file); 205 struct si470x_device *radio = video_drvdata(file);
219 int retval = 0;
220
221 /* safety check */
222 if (!radio)
223 return -ENODEV;
224 206
225 mutex_lock(&radio->lock); 207 if (v4l2_fh_is_singular_file(file))
226 radio->users--;
227 if (radio->users == 0)
228 /* stop radio */ 208 /* stop radio */
229 retval = si470x_stop(radio); 209 si470x_stop(radio);
230 210
231 mutex_unlock(&radio->lock); 211 return v4l2_fh_release(file);
232
233 return retval;
234} 212}
235 213
236 214
@@ -371,32 +349,25 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
371 goto err_initial; 349 goto err_initial;
372 } 350 }
373 351
374 radio->users = 0;
375 radio->client = client; 352 radio->client = client;
376 mutex_init(&radio->lock); 353 mutex_init(&radio->lock);
377 354
378 /* video device allocation and initialization */ 355 /* video device initialization */
379 radio->videodev = video_device_alloc(); 356 radio->videodev = si470x_viddev_template;
380 if (!radio->videodev) { 357 video_set_drvdata(&radio->videodev, radio);
381 retval = -ENOMEM;
382 goto err_radio;
383 }
384 memcpy(radio->videodev, &si470x_viddev_template,
385 sizeof(si470x_viddev_template));
386 video_set_drvdata(radio->videodev, radio);
387 358
388 /* power up : need 110ms */ 359 /* power up : need 110ms */
389 radio->registers[POWERCFG] = POWERCFG_ENABLE; 360 radio->registers[POWERCFG] = POWERCFG_ENABLE;
390 if (si470x_set_register(radio, POWERCFG) < 0) { 361 if (si470x_set_register(radio, POWERCFG) < 0) {
391 retval = -EIO; 362 retval = -EIO;
392 goto err_video; 363 goto err_radio;
393 } 364 }
394 msleep(110); 365 msleep(110);
395 366
396 /* get device and chip versions */ 367 /* get device and chip versions */
397 if (si470x_get_all_registers(radio) < 0) { 368 if (si470x_get_all_registers(radio) < 0) {
398 retval = -EIO; 369 retval = -EIO;
399 goto err_video; 370 goto err_radio;
400 } 371 }
401 dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", 372 dev_info(&client->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
402 radio->registers[DEVICEID], radio->registers[CHIPID]); 373 radio->registers[DEVICEID], radio->registers[CHIPID]);
@@ -427,7 +398,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
427 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); 398 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
428 if (!radio->buffer) { 399 if (!radio->buffer) {
429 retval = -EIO; 400 retval = -EIO;
430 goto err_video; 401 goto err_radio;
431 } 402 }
432 403
433 /* rds buffer configuration */ 404 /* rds buffer configuration */
@@ -447,7 +418,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
447 } 418 }
448 419
449 /* register video device */ 420 /* register video device */
450 retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, 421 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
451 radio_nr); 422 radio_nr);
452 if (retval) { 423 if (retval) {
453 dev_warn(&client->dev, "Could not register video device\n"); 424 dev_warn(&client->dev, "Could not register video device\n");
@@ -460,8 +431,6 @@ err_all:
460 free_irq(client->irq, radio); 431 free_irq(client->irq, radio);
461err_rds: 432err_rds:
462 kfree(radio->buffer); 433 kfree(radio->buffer);
463err_video:
464 video_device_release(radio->videodev);
465err_radio: 434err_radio:
466 kfree(radio); 435 kfree(radio);
467err_initial: 436err_initial:
@@ -477,7 +446,7 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client)
477 struct si470x_device *radio = i2c_get_clientdata(client); 446 struct si470x_device *radio = i2c_get_clientdata(client);
478 447
479 free_irq(client->irq, radio); 448 free_irq(client->irq, radio);
480 video_unregister_device(radio->videodev); 449 video_unregister_device(&radio->videodev);
481 kfree(radio); 450 kfree(radio);
482 451
483 return 0; 452 return 0;
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c
index b7debb67932a..f133c3dea648 100644
--- a/drivers/media/radio/si470x/radio-si470x-usb.c
+++ b/drivers/media/radio/si470x/radio-si470x-usb.c
@@ -367,23 +367,6 @@ static int si470x_get_scratch_page_versions(struct si470x_device *radio)
367 367
368 368
369/************************************************************************** 369/**************************************************************************
370 * General Driver Functions - DISCONNECT_CHECK
371 **************************************************************************/
372
373/*
374 * si470x_disconnect_check - check whether radio disconnects
375 */
376int si470x_disconnect_check(struct si470x_device *radio)
377{
378 if (radio->disconnected)
379 return -EIO;
380 else
381 return 0;
382}
383
384
385
386/**************************************************************************
387 * RDS Driver Functions 370 * RDS Driver Functions
388 **************************************************************************/ 371 **************************************************************************/
389 372
@@ -414,9 +397,6 @@ static void si470x_int_in_callback(struct urb *urb)
414 } 397 }
415 } 398 }
416 399
417 /* safety checks */
418 if (radio->disconnected)
419 return;
420 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 400 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
421 goto resubmit; 401 goto resubmit;
422 402
@@ -512,19 +492,16 @@ resubmit:
512int si470x_fops_open(struct file *file) 492int si470x_fops_open(struct file *file)
513{ 493{
514 struct si470x_device *radio = video_drvdata(file); 494 struct si470x_device *radio = video_drvdata(file);
515 int retval; 495 int retval = v4l2_fh_open(file);
516 496
517 mutex_lock(&radio->lock); 497 if (retval)
518 radio->users++; 498 return retval;
519 499
520 retval = usb_autopm_get_interface(radio->intf); 500 retval = usb_autopm_get_interface(radio->intf);
521 if (retval < 0) { 501 if (retval < 0)
522 radio->users--;
523 retval = -EIO;
524 goto done; 502 goto done;
525 }
526 503
527 if (radio->users == 1) { 504 if (v4l2_fh_is_singular_file(file)) {
528 /* start radio */ 505 /* start radio */
529 retval = si470x_start(radio); 506 retval = si470x_start(radio);
530 if (retval < 0) { 507 if (retval < 0) {
@@ -555,7 +532,8 @@ int si470x_fops_open(struct file *file)
555 } 532 }
556 533
557done: 534done:
558 mutex_unlock(&radio->lock); 535 if (retval)
536 v4l2_fh_release(file);
559 return retval; 537 return retval;
560} 538}
561 539
@@ -566,45 +544,36 @@ done:
566int si470x_fops_release(struct file *file) 544int si470x_fops_release(struct file *file)
567{ 545{
568 struct si470x_device *radio = video_drvdata(file); 546 struct si470x_device *radio = video_drvdata(file);
569 int retval = 0;
570 547
571 /* safety check */ 548 if (v4l2_fh_is_singular_file(file)) {
572 if (!radio) {
573 retval = -ENODEV;
574 goto done;
575 }
576
577 mutex_lock(&radio->lock);
578 radio->users--;
579 if (radio->users == 0) {
580 /* shutdown interrupt handler */ 549 /* shutdown interrupt handler */
581 if (radio->int_in_running) { 550 if (radio->int_in_running) {
582 radio->int_in_running = 0; 551 radio->int_in_running = 0;
583 if (radio->int_in_urb) 552 if (radio->int_in_urb)
584 usb_kill_urb(radio->int_in_urb); 553 usb_kill_urb(radio->int_in_urb);
585 }
586
587 if (radio->disconnected) {
588 video_unregister_device(radio->videodev);
589 kfree(radio->int_in_buffer);
590 kfree(radio->buffer);
591 mutex_unlock(&radio->lock);
592 kfree(radio);
593 goto done;
594 } 554 }
595 555
596 /* cancel read processes */ 556 /* cancel read processes */
597 wake_up_interruptible(&radio->read_queue); 557 wake_up_interruptible(&radio->read_queue);
598 558
599 /* stop radio */ 559 /* stop radio */
600 retval = si470x_stop(radio); 560 si470x_stop(radio);
601 usb_autopm_put_interface(radio->intf); 561 usb_autopm_put_interface(radio->intf);
602 } 562 }
603 mutex_unlock(&radio->lock); 563 return v4l2_fh_release(file);
604done:
605 return retval;
606} 564}
607 565
566static void si470x_usb_release(struct video_device *vdev)
567{
568 struct si470x_device *radio = video_get_drvdata(vdev);
569
570 usb_free_urb(radio->int_in_urb);
571 v4l2_ctrl_handler_free(&radio->hdl);
572 v4l2_device_unregister(&radio->v4l2_dev);
573 kfree(radio->int_in_buffer);
574 kfree(radio->buffer);
575 kfree(radio);
576}
608 577
609 578
610/************************************************************************** 579/**************************************************************************
@@ -623,9 +592,9 @@ int si470x_vidioc_querycap(struct file *file, void *priv,
623 strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); 592 strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
624 usb_make_path(radio->usbdev, capability->bus_info, 593 usb_make_path(radio->usbdev, capability->bus_info,
625 sizeof(capability->bus_info)); 594 sizeof(capability->bus_info));
626 capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | 595 capability->device_caps = V4L2_CAP_HW_FREQ_SEEK |
627 V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; 596 V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;
628 597 capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS;
629 return 0; 598 return 0;
630} 599}
631 600
@@ -653,8 +622,6 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
653 retval = -ENOMEM; 622 retval = -ENOMEM;
654 goto err_initial; 623 goto err_initial;
655 } 624 }
656 radio->users = 0;
657 radio->disconnected = 0;
658 radio->usbdev = interface_to_usbdev(intf); 625 radio->usbdev = interface_to_usbdev(intf);
659 radio->intf = intf; 626 radio->intf = intf;
660 mutex_init(&radio->lock); 627 mutex_init(&radio->lock);
@@ -691,20 +658,34 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
691 goto err_intbuffer; 658 goto err_intbuffer;
692 } 659 }
693 660
694 /* video device allocation and initialization */ 661 retval = v4l2_device_register(&intf->dev, &radio->v4l2_dev);
695 radio->videodev = video_device_alloc(); 662 if (retval < 0) {
696 if (!radio->videodev) { 663 dev_err(&intf->dev, "couldn't register v4l2_device\n");
697 retval = -ENOMEM;
698 goto err_urb; 664 goto err_urb;
699 } 665 }
700 memcpy(radio->videodev, &si470x_viddev_template, 666
701 sizeof(si470x_viddev_template)); 667 v4l2_ctrl_handler_init(&radio->hdl, 2);
702 video_set_drvdata(radio->videodev, radio); 668 v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,
669 V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
670 v4l2_ctrl_new_std(&radio->hdl, &si470x_ctrl_ops,
671 V4L2_CID_AUDIO_VOLUME, 0, 15, 1, 15);
672 if (radio->hdl.error) {
673 retval = radio->hdl.error;
674 dev_err(&intf->dev, "couldn't register control\n");
675 goto err_dev;
676 }
677 radio->videodev = si470x_viddev_template;
678 radio->videodev.ctrl_handler = &radio->hdl;
679 radio->videodev.lock = &radio->lock;
680 radio->videodev.v4l2_dev = &radio->v4l2_dev;
681 radio->videodev.release = si470x_usb_release;
682 set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
683 video_set_drvdata(&radio->videodev, radio);
703 684
704 /* get device and chip versions */ 685 /* get device and chip versions */
705 if (si470x_get_all_registers(radio) < 0) { 686 if (si470x_get_all_registers(radio) < 0) {
706 retval = -EIO; 687 retval = -EIO;
707 goto err_video; 688 goto err_ctrl;
708 } 689 }
709 dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n", 690 dev_info(&intf->dev, "DeviceID=0x%4.4hx ChipID=0x%4.4hx\n",
710 radio->registers[DEVICEID], radio->registers[CHIPID]); 691 radio->registers[DEVICEID], radio->registers[CHIPID]);
@@ -721,7 +702,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
721 /* get software and hardware versions */ 702 /* get software and hardware versions */
722 if (si470x_get_scratch_page_versions(radio) < 0) { 703 if (si470x_get_scratch_page_versions(radio) < 0) {
723 retval = -EIO; 704 retval = -EIO;
724 goto err_video; 705 goto err_ctrl;
725 } 706 }
726 dev_info(&intf->dev, "software version %d, hardware version %d\n", 707 dev_info(&intf->dev, "software version %d, hardware version %d\n",
727 radio->software_version, radio->hardware_version); 708 radio->software_version, radio->hardware_version);
@@ -764,28 +745,30 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
764 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL); 745 radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
765 if (!radio->buffer) { 746 if (!radio->buffer) {
766 retval = -EIO; 747 retval = -EIO;
767 goto err_video; 748 goto err_ctrl;
768 } 749 }
769 750
770 /* rds buffer configuration */ 751 /* rds buffer configuration */
771 radio->wr_index = 0; 752 radio->wr_index = 0;
772 radio->rd_index = 0; 753 radio->rd_index = 0;
773 init_waitqueue_head(&radio->read_queue); 754 init_waitqueue_head(&radio->read_queue);
755 usb_set_intfdata(intf, radio);
774 756
775 /* register video device */ 757 /* register video device */
776 retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, 758 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
777 radio_nr); 759 radio_nr);
778 if (retval) { 760 if (retval) {
779 dev_warn(&intf->dev, "Could not register video device\n"); 761 dev_warn(&intf->dev, "Could not register video device\n");
780 goto err_all; 762 goto err_all;
781 } 763 }
782 usb_set_intfdata(intf, radio);
783 764
784 return 0; 765 return 0;
785err_all: 766err_all:
786 kfree(radio->buffer); 767 kfree(radio->buffer);
787err_video: 768err_ctrl:
788 video_device_release(radio->videodev); 769 v4l2_ctrl_handler_free(&radio->hdl);
770err_dev:
771 v4l2_device_unregister(&radio->v4l2_dev);
789err_urb: 772err_urb:
790 usb_free_urb(radio->int_in_urb); 773 usb_free_urb(radio->int_in_urb);
791err_intbuffer: 774err_intbuffer:
@@ -828,23 +811,10 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
828 struct si470x_device *radio = usb_get_intfdata(intf); 811 struct si470x_device *radio = usb_get_intfdata(intf);
829 812
830 mutex_lock(&radio->lock); 813 mutex_lock(&radio->lock);
831 radio->disconnected = 1; 814 v4l2_device_disconnect(&radio->v4l2_dev);
815 video_unregister_device(&radio->videodev);
832 usb_set_intfdata(intf, NULL); 816 usb_set_intfdata(intf, NULL);
833 if (radio->users == 0) { 817 mutex_unlock(&radio->lock);
834 /* set led to disconnect state */
835 si470x_set_led_state(radio, BLINK_ORANGE_LED);
836
837 /* Free data structures. */
838 usb_free_urb(radio->int_in_urb);
839
840 kfree(radio->int_in_buffer);
841 video_unregister_device(radio->videodev);
842 kfree(radio->buffer);
843 mutex_unlock(&radio->lock);
844 kfree(radio);
845 } else {
846 mutex_unlock(&radio->lock);
847 }
848} 818}
849 819
850 820
diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h
index f300a55ed85c..4921cab8e0fa 100644
--- a/drivers/media/radio/si470x/radio-si470x.h
+++ b/drivers/media/radio/si470x/radio-si470x.h
@@ -36,6 +36,9 @@
36#include <linux/mutex.h> 36#include <linux/mutex.h>
37#include <media/v4l2-common.h> 37#include <media/v4l2-common.h>
38#include <media/v4l2-ioctl.h> 38#include <media/v4l2-ioctl.h>
39#include <media/v4l2-ctrls.h>
40#include <media/v4l2-event.h>
41#include <media/v4l2-device.h>
39#include <asm/unaligned.h> 42#include <asm/unaligned.h>
40 43
41 44
@@ -141,10 +144,9 @@
141 * si470x_device - private data 144 * si470x_device - private data
142 */ 145 */
143struct si470x_device { 146struct si470x_device {
144 struct video_device *videodev; 147 struct v4l2_device v4l2_dev;
145 148 struct video_device videodev;
146 /* driver management */ 149 struct v4l2_ctrl_handler hdl;
147 unsigned int users;
148 150
149 /* Silabs internal registers (0..15) */ 151 /* Silabs internal registers (0..15) */
150 unsigned short registers[RADIO_REGISTER_NUM]; 152 unsigned short registers[RADIO_REGISTER_NUM];
@@ -174,9 +176,6 @@ struct si470x_device {
174 /* scratch page */ 176 /* scratch page */
175 unsigned char software_version; 177 unsigned char software_version;
176 unsigned char hardware_version; 178 unsigned char hardware_version;
177
178 /* driver management */
179 unsigned char disconnected;
180#endif 179#endif
181 180
182#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) 181#if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE)
@@ -213,6 +212,7 @@ struct si470x_device {
213 * Common Functions 212 * Common Functions
214 **************************************************************************/ 213 **************************************************************************/
215extern struct video_device si470x_viddev_template; 214extern struct video_device si470x_viddev_template;
215extern const struct v4l2_ctrl_ops si470x_ctrl_ops;
216int si470x_get_register(struct si470x_device *radio, int regnr); 216int si470x_get_register(struct si470x_device *radio, int regnr);
217int si470x_set_register(struct si470x_device *radio, int regnr); 217int si470x_set_register(struct si470x_device *radio, int regnr);
218int si470x_disconnect_check(struct si470x_device *radio); 218int si470x_disconnect_check(struct si470x_device *radio);