aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/dsbr100.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio/dsbr100.c')
-rw-r--r--drivers/media/radio/dsbr100.c109
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
126static int usb_dsbr100_probe(struct usb_interface *intf, 134static int usb_dsbr100_probe(struct usb_interface *intf,
127 const struct usb_device_id *id); 135 const struct usb_device_id *id);
128static void usb_dsbr100_disconnect(struct usb_interface *intf); 136static void usb_dsbr100_disconnect(struct usb_interface *intf);
129static int usb_dsbr100_open(struct file *file);
130static int usb_dsbr100_close(struct file *file);
131static int usb_dsbr100_suspend(struct usb_interface *intf, 137static int usb_dsbr100_suspend(struct usb_interface *intf,
132 pm_message_t message); 138 pm_message_t message);
133static int usb_dsbr100_resume(struct usb_interface *intf); 139static 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
153static struct usb_device_id usb_dsbr100_device_table [] = { 158static 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 */
261static int dsbr100_setfreq(struct dsbr100_device *radio, int freq) 266static 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
546static 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
573static 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. */
597static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) 552static 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 */
637static const struct v4l2_file_operations usb_dsbr100_fops = { 606static 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