diff options
Diffstat (limited to 'drivers/media/radio/radio-mr800.c')
-rw-r--r-- | drivers/media/radio/radio-mr800.c | 85 |
1 files changed, 31 insertions, 54 deletions
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c index ded25bfb366e..cab19d05e02f 100644 --- a/drivers/media/radio/radio-mr800.c +++ b/drivers/media/radio/radio-mr800.c | |||
@@ -43,6 +43,7 @@ | |||
43 | * Douglas Schilling Landgraf <dougsland@gmail.com> and | 43 | * Douglas Schilling Landgraf <dougsland@gmail.com> and |
44 | * David Ellingsworth <david@identd.dyndns.org> | 44 | * David Ellingsworth <david@identd.dyndns.org> |
45 | * for discussion, help and support. | 45 | * for discussion, help and support. |
46 | * Version 0.11: Converted to v4l2_device. | ||
46 | * | 47 | * |
47 | * Many things to do: | 48 | * Many things to do: |
48 | * - Correct power managment of device (suspend & resume) | 49 | * - Correct power managment of device (suspend & resume) |
@@ -59,7 +60,7 @@ | |||
59 | #include <linux/slab.h> | 60 | #include <linux/slab.h> |
60 | #include <linux/input.h> | 61 | #include <linux/input.h> |
61 | #include <linux/videodev2.h> | 62 | #include <linux/videodev2.h> |
62 | #include <media/v4l2-common.h> | 63 | #include <media/v4l2-device.h> |
63 | #include <media/v4l2-ioctl.h> | 64 | #include <media/v4l2-ioctl.h> |
64 | #include <linux/usb.h> | 65 | #include <linux/usb.h> |
65 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | 66 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ |
@@ -67,8 +68,8 @@ | |||
67 | /* driver and module definitions */ | 68 | /* driver and module definitions */ |
68 | #define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>" | 69 | #define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>" |
69 | #define DRIVER_DESC "AverMedia MR 800 USB FM radio driver" | 70 | #define DRIVER_DESC "AverMedia MR 800 USB FM radio driver" |
70 | #define DRIVER_VERSION "0.10" | 71 | #define DRIVER_VERSION "0.11" |
71 | #define RADIO_VERSION KERNEL_VERSION(0, 1, 0) | 72 | #define RADIO_VERSION KERNEL_VERSION(0, 1, 1) |
72 | 73 | ||
73 | MODULE_AUTHOR(DRIVER_AUTHOR); | 74 | MODULE_AUTHOR(DRIVER_AUTHOR); |
74 | MODULE_DESCRIPTION(DRIVER_DESC); | 75 | MODULE_DESCRIPTION(DRIVER_DESC); |
@@ -113,38 +114,6 @@ static int radio_nr = -1; | |||
113 | module_param(radio_nr, int, 0); | 114 | module_param(radio_nr, int, 0); |
114 | MODULE_PARM_DESC(radio_nr, "Radio Nr"); | 115 | MODULE_PARM_DESC(radio_nr, "Radio Nr"); |
115 | 116 | ||
116 | static struct v4l2_queryctrl radio_qctrl[] = { | ||
117 | { | ||
118 | .id = V4L2_CID_AUDIO_MUTE, | ||
119 | .name = "Mute", | ||
120 | .minimum = 0, | ||
121 | .maximum = 1, | ||
122 | .step = 1, | ||
123 | .default_value = 1, | ||
124 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
125 | }, | ||
126 | /* HINT: the disabled controls are only here to satify kradio and such apps */ | ||
127 | { .id = V4L2_CID_AUDIO_VOLUME, | ||
128 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
129 | }, | ||
130 | { | ||
131 | .id = V4L2_CID_AUDIO_BALANCE, | ||
132 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
133 | }, | ||
134 | { | ||
135 | .id = V4L2_CID_AUDIO_BASS, | ||
136 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
137 | }, | ||
138 | { | ||
139 | .id = V4L2_CID_AUDIO_TREBLE, | ||
140 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
141 | }, | ||
142 | { | ||
143 | .id = V4L2_CID_AUDIO_LOUDNESS, | ||
144 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
145 | }, | ||
146 | }; | ||
147 | |||
148 | static int usb_amradio_probe(struct usb_interface *intf, | 117 | static int usb_amradio_probe(struct usb_interface *intf, |
149 | const struct usb_device_id *id); | 118 | const struct usb_device_id *id); |
150 | static void usb_amradio_disconnect(struct usb_interface *intf); | 119 | static void usb_amradio_disconnect(struct usb_interface *intf); |
@@ -159,6 +128,7 @@ struct amradio_device { | |||
159 | /* reference to USB and video device */ | 128 | /* reference to USB and video device */ |
160 | struct usb_device *usbdev; | 129 | struct usb_device *usbdev; |
161 | struct video_device *videodev; | 130 | struct video_device *videodev; |
131 | struct v4l2_device v4l2_dev; | ||
162 | 132 | ||
163 | unsigned char *buffer; | 133 | unsigned char *buffer; |
164 | struct mutex lock; /* buffer locking */ | 134 | struct mutex lock; /* buffer locking */ |
@@ -329,6 +299,7 @@ static void usb_amradio_disconnect(struct usb_interface *intf) | |||
329 | 299 | ||
330 | usb_set_intfdata(intf, NULL); | 300 | usb_set_intfdata(intf, NULL); |
331 | video_unregister_device(radio->videodev); | 301 | video_unregister_device(radio->videodev); |
302 | v4l2_device_disconnect(&radio->v4l2_dev); | ||
332 | } | 303 | } |
333 | 304 | ||
334 | /* vidioc_querycap - query device capabilities */ | 305 | /* vidioc_querycap - query device capabilities */ |
@@ -463,14 +434,11 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
463 | static int vidioc_queryctrl(struct file *file, void *priv, | 434 | static int vidioc_queryctrl(struct file *file, void *priv, |
464 | struct v4l2_queryctrl *qc) | 435 | struct v4l2_queryctrl *qc) |
465 | { | 436 | { |
466 | int i; | 437 | switch (qc->id) { |
467 | 438 | case V4L2_CID_AUDIO_MUTE: | |
468 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { | 439 | return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); |
469 | if (qc->id && qc->id == radio_qctrl[i].id) { | ||
470 | memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); | ||
471 | return 0; | ||
472 | } | ||
473 | } | 440 | } |
441 | |||
474 | return -EINVAL; | 442 | return -EINVAL; |
475 | } | 443 | } |
476 | 444 | ||
@@ -671,34 +639,29 @@ static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = { | |||
671 | .vidioc_s_input = vidioc_s_input, | 639 | .vidioc_s_input = vidioc_s_input, |
672 | }; | 640 | }; |
673 | 641 | ||
674 | static void usb_amradio_device_release(struct video_device *videodev) | 642 | static void usb_amradio_video_device_release(struct video_device *videodev) |
675 | { | 643 | { |
676 | struct amradio_device *radio = video_get_drvdata(videodev); | 644 | struct amradio_device *radio = video_get_drvdata(videodev); |
677 | 645 | ||
678 | /* we call v4l to free radio->videodev */ | 646 | /* we call v4l to free radio->videodev */ |
679 | video_device_release(videodev); | 647 | video_device_release(videodev); |
680 | 648 | ||
649 | v4l2_device_unregister(&radio->v4l2_dev); | ||
650 | |||
681 | /* free rest memory */ | 651 | /* free rest memory */ |
682 | kfree(radio->buffer); | 652 | kfree(radio->buffer); |
683 | kfree(radio); | 653 | kfree(radio); |
684 | } | 654 | } |
685 | 655 | ||
686 | /* V4L2 interface */ | ||
687 | static struct video_device amradio_videodev_template = { | ||
688 | .name = "AverMedia MR 800 USB FM Radio", | ||
689 | .fops = &usb_amradio_fops, | ||
690 | .ioctl_ops = &usb_amradio_ioctl_ops, | ||
691 | .release = usb_amradio_device_release, | ||
692 | }; | ||
693 | |||
694 | /* check if the device is present and register with v4l and usb if it is */ | 656 | /* check if the device is present and register with v4l and usb if it is */ |
695 | static int usb_amradio_probe(struct usb_interface *intf, | 657 | static int usb_amradio_probe(struct usb_interface *intf, |
696 | const struct usb_device_id *id) | 658 | const struct usb_device_id *id) |
697 | { | 659 | { |
698 | struct amradio_device *radio; | 660 | struct amradio_device *radio; |
661 | struct v4l2_device *v4l2_dev; | ||
699 | int retval; | 662 | int retval; |
700 | 663 | ||
701 | radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL); | 664 | radio = kzalloc(sizeof(struct amradio_device), GFP_KERNEL); |
702 | 665 | ||
703 | if (!radio) { | 666 | if (!radio) { |
704 | dev_err(&intf->dev, "kmalloc for amradio_device failed\n"); | 667 | dev_err(&intf->dev, "kmalloc for amradio_device failed\n"); |
@@ -713,6 +676,15 @@ static int usb_amradio_probe(struct usb_interface *intf, | |||
713 | return -ENOMEM; | 676 | return -ENOMEM; |
714 | } | 677 | } |
715 | 678 | ||
679 | v4l2_dev = &radio->v4l2_dev; | ||
680 | retval = v4l2_device_register(&intf->dev, v4l2_dev); | ||
681 | if (retval < 0) { | ||
682 | dev_err(&intf->dev, "couldn't register v4l2_device\n"); | ||
683 | kfree(radio->buffer); | ||
684 | kfree(radio); | ||
685 | return retval; | ||
686 | } | ||
687 | |||
716 | radio->videodev = video_device_alloc(); | 688 | radio->videodev = video_device_alloc(); |
717 | 689 | ||
718 | if (!radio->videodev) { | 690 | if (!radio->videodev) { |
@@ -722,8 +694,11 @@ static int usb_amradio_probe(struct usb_interface *intf, | |||
722 | return -ENOMEM; | 694 | return -ENOMEM; |
723 | } | 695 | } |
724 | 696 | ||
725 | memcpy(radio->videodev, &amradio_videodev_template, | 697 | strlcpy(radio->videodev->name, v4l2_dev->name, sizeof(radio->videodev->name)); |
726 | sizeof(amradio_videodev_template)); | 698 | radio->videodev->v4l2_dev = v4l2_dev; |
699 | radio->videodev->fops = &usb_amradio_fops; | ||
700 | radio->videodev->ioctl_ops = &usb_amradio_ioctl_ops; | ||
701 | radio->videodev->release = usb_amradio_video_device_release; | ||
727 | 702 | ||
728 | radio->removed = 0; | 703 | radio->removed = 0; |
729 | radio->users = 0; | 704 | radio->users = 0; |
@@ -734,10 +709,12 @@ static int usb_amradio_probe(struct usb_interface *intf, | |||
734 | mutex_init(&radio->lock); | 709 | mutex_init(&radio->lock); |
735 | 710 | ||
736 | video_set_drvdata(radio->videodev, radio); | 711 | video_set_drvdata(radio->videodev, radio); |
712 | |||
737 | retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); | 713 | retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr); |
738 | if (retval < 0) { | 714 | if (retval < 0) { |
739 | dev_err(&intf->dev, "could not register video device\n"); | 715 | dev_err(&intf->dev, "could not register video device\n"); |
740 | video_device_release(radio->videodev); | 716 | video_device_release(radio->videodev); |
717 | v4l2_device_unregister(v4l2_dev); | ||
741 | kfree(radio->buffer); | 718 | kfree(radio->buffer); |
742 | kfree(radio); | 719 | kfree(radio); |
743 | return -EIO; | 720 | return -EIO; |