diff options
Diffstat (limited to 'drivers/media/radio/dsbr100.c')
-rw-r--r-- | drivers/media/radio/dsbr100.c | 109 |
1 files changed, 38 insertions, 71 deletions
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index 613576202294..ed9cd7ad0604 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c | |||
@@ -33,6 +33,10 @@ | |||
33 | 33 | ||
34 | History: | 34 | History: |
35 | 35 | ||
36 | Version 0.46: | ||
37 | Removed usb_dsbr100_open/close calls and radio->users counter. Also, | ||
38 | radio->muted changed to radio->status and suspend/resume calls updated. | ||
39 | |||
36 | Version 0.45: | 40 | Version 0.45: |
37 | Converted to v4l2_device. | 41 | Converted to v4l2_device. |
38 | 42 | ||
@@ -100,8 +104,8 @@ | |||
100 | */ | 104 | */ |
101 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | 105 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ |
102 | 106 | ||
103 | #define DRIVER_VERSION "v0.45" | 107 | #define DRIVER_VERSION "v0.46" |
104 | #define RADIO_VERSION KERNEL_VERSION(0, 4, 5) | 108 | #define RADIO_VERSION KERNEL_VERSION(0, 4, 6) |
105 | 109 | ||
106 | #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>" | 110 | #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>" |
107 | #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" | 111 | #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" |
@@ -121,13 +125,15 @@ devices, that would be 76 and 91. */ | |||
121 | #define FREQ_MAX 108.0 | 125 | #define FREQ_MAX 108.0 |
122 | #define FREQ_MUL 16000 | 126 | #define FREQ_MUL 16000 |
123 | 127 | ||
128 | /* defines for radio->status */ | ||
129 | #define STARTED 0 | ||
130 | #define STOPPED 1 | ||
131 | |||
124 | #define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev) | 132 | #define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev) |
125 | 133 | ||
126 | static int usb_dsbr100_probe(struct usb_interface *intf, | 134 | static int usb_dsbr100_probe(struct usb_interface *intf, |
127 | const struct usb_device_id *id); | 135 | const struct usb_device_id *id); |
128 | static void usb_dsbr100_disconnect(struct usb_interface *intf); | 136 | static void usb_dsbr100_disconnect(struct usb_interface *intf); |
129 | static int usb_dsbr100_open(struct file *file); | ||
130 | static int usb_dsbr100_close(struct file *file); | ||
131 | static int usb_dsbr100_suspend(struct usb_interface *intf, | 137 | static int usb_dsbr100_suspend(struct usb_interface *intf, |
132 | pm_message_t message); | 138 | pm_message_t message); |
133 | static int usb_dsbr100_resume(struct usb_interface *intf); | 139 | static int usb_dsbr100_resume(struct usb_interface *intf); |
@@ -145,9 +151,8 @@ struct dsbr100_device { | |||
145 | struct mutex lock; /* buffer locking */ | 151 | struct mutex lock; /* buffer locking */ |
146 | int curfreq; | 152 | int curfreq; |
147 | int stereo; | 153 | int stereo; |
148 | int users; | ||
149 | int removed; | 154 | int removed; |
150 | int muted; | 155 | int status; |
151 | }; | 156 | }; |
152 | 157 | ||
153 | static struct usb_device_id usb_dsbr100_device_table [] = { | 158 | static struct usb_device_id usb_dsbr100_device_table [] = { |
@@ -201,7 +206,7 @@ static int dsbr100_start(struct dsbr100_device *radio) | |||
201 | goto usb_control_msg_failed; | 206 | goto usb_control_msg_failed; |
202 | } | 207 | } |
203 | 208 | ||
204 | radio->muted = 0; | 209 | radio->status = STARTED; |
205 | mutex_unlock(&radio->lock); | 210 | mutex_unlock(&radio->lock); |
206 | return (radio->transfer_buffer)[0]; | 211 | return (radio->transfer_buffer)[0]; |
207 | 212 | ||
@@ -244,7 +249,7 @@ static int dsbr100_stop(struct dsbr100_device *radio) | |||
244 | goto usb_control_msg_failed; | 249 | goto usb_control_msg_failed; |
245 | } | 250 | } |
246 | 251 | ||
247 | radio->muted = 1; | 252 | radio->status = STOPPED; |
248 | mutex_unlock(&radio->lock); | 253 | mutex_unlock(&radio->lock); |
249 | return (radio->transfer_buffer)[0]; | 254 | return (radio->transfer_buffer)[0]; |
250 | 255 | ||
@@ -258,12 +263,12 @@ usb_control_msg_failed: | |||
258 | } | 263 | } |
259 | 264 | ||
260 | /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ | 265 | /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ |
261 | static int dsbr100_setfreq(struct dsbr100_device *radio, int freq) | 266 | static int dsbr100_setfreq(struct dsbr100_device *radio) |
262 | { | 267 | { |
263 | int retval; | 268 | int retval; |
264 | int request; | 269 | int request; |
270 | int freq = (radio->curfreq / 16 * 80) / 1000 + 856; | ||
265 | 271 | ||
266 | freq = (freq / 16 * 80) / 1000 + 856; | ||
267 | mutex_lock(&radio->lock); | 272 | mutex_lock(&radio->lock); |
268 | 273 | ||
269 | retval = usb_control_msg(radio->usbdev, | 274 | retval = usb_control_msg(radio->usbdev, |
@@ -431,7 +436,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
431 | radio->curfreq = f->frequency; | 436 | radio->curfreq = f->frequency; |
432 | mutex_unlock(&radio->lock); | 437 | mutex_unlock(&radio->lock); |
433 | 438 | ||
434 | retval = dsbr100_setfreq(radio, radio->curfreq); | 439 | retval = dsbr100_setfreq(radio); |
435 | if (retval < 0) | 440 | if (retval < 0) |
436 | dev_warn(&radio->usbdev->dev, "Set frequency failed\n"); | 441 | dev_warn(&radio->usbdev->dev, "Set frequency failed\n"); |
437 | return 0; | 442 | return 0; |
@@ -473,7 +478,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
473 | 478 | ||
474 | switch (ctrl->id) { | 479 | switch (ctrl->id) { |
475 | case V4L2_CID_AUDIO_MUTE: | 480 | case V4L2_CID_AUDIO_MUTE: |
476 | ctrl->value = radio->muted; | 481 | ctrl->value = radio->status; |
477 | return 0; | 482 | return 0; |
478 | } | 483 | } |
479 | return -EINVAL; | 484 | return -EINVAL; |
@@ -543,65 +548,27 @@ static int vidioc_s_audio(struct file *file, void *priv, | |||
543 | return 0; | 548 | return 0; |
544 | } | 549 | } |
545 | 550 | ||
546 | static int usb_dsbr100_open(struct file *file) | ||
547 | { | ||
548 | struct dsbr100_device *radio = video_drvdata(file); | ||
549 | int retval; | ||
550 | |||
551 | lock_kernel(); | ||
552 | radio->users = 1; | ||
553 | radio->muted = 1; | ||
554 | |||
555 | retval = dsbr100_start(radio); | ||
556 | if (retval < 0) { | ||
557 | dev_warn(&radio->usbdev->dev, | ||
558 | "Radio did not start up properly\n"); | ||
559 | radio->users = 0; | ||
560 | unlock_kernel(); | ||
561 | return -EIO; | ||
562 | } | ||
563 | |||
564 | retval = dsbr100_setfreq(radio, radio->curfreq); | ||
565 | if (retval < 0) | ||
566 | dev_warn(&radio->usbdev->dev, | ||
567 | "set frequency failed\n"); | ||
568 | |||
569 | unlock_kernel(); | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static int usb_dsbr100_close(struct file *file) | ||
574 | { | ||
575 | struct dsbr100_device *radio = video_drvdata(file); | ||
576 | int retval; | ||
577 | |||
578 | if (!radio) | ||
579 | return -ENODEV; | ||
580 | |||
581 | mutex_lock(&radio->lock); | ||
582 | radio->users = 0; | ||
583 | mutex_unlock(&radio->lock); | ||
584 | |||
585 | if (!radio->removed) { | ||
586 | retval = dsbr100_stop(radio); | ||
587 | if (retval < 0) { | ||
588 | dev_warn(&radio->usbdev->dev, | ||
589 | "dsbr100_stop failed\n"); | ||
590 | } | ||
591 | |||
592 | } | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | /* Suspend device - stop device. */ | 551 | /* Suspend device - stop device. */ |
597 | static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) | 552 | static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) |
598 | { | 553 | { |
599 | struct dsbr100_device *radio = usb_get_intfdata(intf); | 554 | struct dsbr100_device *radio = usb_get_intfdata(intf); |
600 | int retval; | 555 | int retval; |
601 | 556 | ||
602 | retval = dsbr100_stop(radio); | 557 | if (radio->status == STARTED) { |
603 | if (retval < 0) | 558 | retval = dsbr100_stop(radio); |
604 | dev_warn(&intf->dev, "dsbr100_stop failed\n"); | 559 | if (retval < 0) |
560 | dev_warn(&intf->dev, "dsbr100_stop failed\n"); | ||
561 | |||
562 | /* After dsbr100_stop() status set to STOPPED. | ||
563 | * If we want driver to start radio on resume | ||
564 | * we set status equal to STARTED. | ||
565 | * On resume we will check status and run radio if needed. | ||
566 | */ | ||
567 | |||
568 | mutex_lock(&radio->lock); | ||
569 | radio->status = STARTED; | ||
570 | mutex_unlock(&radio->lock); | ||
571 | } | ||
605 | 572 | ||
606 | dev_info(&intf->dev, "going into suspend..\n"); | 573 | dev_info(&intf->dev, "going into suspend..\n"); |
607 | 574 | ||
@@ -614,9 +581,11 @@ static int usb_dsbr100_resume(struct usb_interface *intf) | |||
614 | struct dsbr100_device *radio = usb_get_intfdata(intf); | 581 | struct dsbr100_device *radio = usb_get_intfdata(intf); |
615 | int retval; | 582 | int retval; |
616 | 583 | ||
617 | retval = dsbr100_start(radio); | 584 | if (radio->status == STARTED) { |
618 | if (retval < 0) | 585 | retval = dsbr100_start(radio); |
619 | dev_warn(&intf->dev, "dsbr100_start failed\n"); | 586 | if (retval < 0) |
587 | dev_warn(&intf->dev, "dsbr100_start failed\n"); | ||
588 | } | ||
620 | 589 | ||
621 | dev_info(&intf->dev, "coming out of suspend..\n"); | 590 | dev_info(&intf->dev, "coming out of suspend..\n"); |
622 | 591 | ||
@@ -636,8 +605,6 @@ static void usb_dsbr100_video_device_release(struct video_device *videodev) | |||
636 | /* File system interface */ | 605 | /* File system interface */ |
637 | static const struct v4l2_file_operations usb_dsbr100_fops = { | 606 | static const struct v4l2_file_operations usb_dsbr100_fops = { |
638 | .owner = THIS_MODULE, | 607 | .owner = THIS_MODULE, |
639 | .open = usb_dsbr100_open, | ||
640 | .release = usb_dsbr100_close, | ||
641 | .ioctl = video_ioctl2, | 608 | .ioctl = video_ioctl2, |
642 | }; | 609 | }; |
643 | 610 | ||
@@ -695,9 +662,9 @@ static int usb_dsbr100_probe(struct usb_interface *intf, | |||
695 | mutex_init(&radio->lock); | 662 | mutex_init(&radio->lock); |
696 | 663 | ||
697 | radio->removed = 0; | 664 | radio->removed = 0; |
698 | radio->users = 0; | ||
699 | radio->usbdev = interface_to_usbdev(intf); | 665 | radio->usbdev = interface_to_usbdev(intf); |
700 | radio->curfreq = FREQ_MIN * FREQ_MUL; | 666 | radio->curfreq = FREQ_MIN * FREQ_MUL; |
667 | radio->status = STOPPED; | ||
701 | 668 | ||
702 | video_set_drvdata(&radio->videodev, radio); | 669 | video_set_drvdata(&radio->videodev, radio); |
703 | 670 | ||