V4L/DVB (10459): radio-mr800: fix amradio_set_freq
[deliverable/linux.git] / drivers / media / radio / radio-mr800.c
CommitLineData
2aa72f3b
AK
1/*
2 * A driver for the AverMedia MR 800 USB FM radio. This device plugs
3 * into both the USB and an analog audio input, so this thing
4 * only deals with initialization and frequency setting, the
5 * audio data has to be handled by a sound driver.
6 *
7 * Copyright (c) 2008 Alexey Klimov <klimov.linux@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24/*
25 * Big thanks to authors of dsbr100.c and radio-si470x.c
26 *
27 * When work was looked pretty good, i discover this:
28 * http://av-usbradio.sourceforge.net/index.php
29 * http://sourceforge.net/projects/av-usbradio/
30 * Latest release of theirs project was in 2005.
31 * Probably, this driver could be improved trough using their
32 * achievements (specifications given).
33 * So, we have smth to begin with.
34 *
35 * History:
36 * Version 0.01: First working version.
37 * It's required to blacklist AverMedia USB Radio
38 * in usbhid/hid-quirks.c
39 *
40 * Many things to do:
41 * - Correct power managment of device (suspend & resume)
42 * - Make x86 independance (little-endian and big-endian stuff)
43 * - Add code for scanning and smooth tuning
44 * - Checked and add stereo&mono stuff
45 * - Add code for sensitivity value
46 * - Correct mistakes
47 * - In Japan another FREQ_MIN and FREQ_MAX
48 */
49
50/* kernel includes */
51#include <linux/kernel.h>
52#include <linux/module.h>
53#include <linux/init.h>
54#include <linux/slab.h>
55#include <linux/input.h>
56#include <linux/videodev2.h>
57#include <media/v4l2-common.h>
58#include <media/v4l2-ioctl.h>
59#include <linux/usb.h>
60#include <linux/version.h> /* for KERNEL_VERSION MACRO */
61
62/* driver and module definitions */
63#define DRIVER_AUTHOR "Alexey Klimov <klimov.linux@gmail.com>"
64#define DRIVER_DESC "AverMedia MR 800 USB FM radio driver"
65#define DRIVER_VERSION "0.01"
66#define RADIO_VERSION KERNEL_VERSION(0, 0, 1)
67
68MODULE_AUTHOR(DRIVER_AUTHOR);
69MODULE_DESCRIPTION(DRIVER_DESC);
70MODULE_LICENSE("GPL");
71
72#define USB_AMRADIO_VENDOR 0x07ca
73#define USB_AMRADIO_PRODUCT 0xb800
74
e60b022e
AK
75/* dev_warn macro with driver name */
76#define MR800_DRIVER_NAME "radio-mr800"
77#define amradio_dev_warn(dev, fmt, arg...) \
78 dev_warn(dev, MR800_DRIVER_NAME " - " fmt, ##arg)
79
2aa72f3b
AK
80/* Probably USB_TIMEOUT should be modified in module parameter */
81#define BUFFER_LENGTH 8
82#define USB_TIMEOUT 500
83
84/* Frequency limits in MHz -- these are European values. For Japanese
85devices, that would be 76 and 91. */
86#define FREQ_MIN 87.5
87#define FREQ_MAX 108.0
88#define FREQ_MUL 16000
89
db821804
AK
90/*
91 * Commands that device should understand
92 * List isnt full and will be updated with implementation of new functions
93 */
f7c1a380 94#define AMRADIO_SET_FREQ 0xa4
db821804
AK
95#define AMRADIO_SET_MUTE 0xab
96
97/* Comfortable defines for amradio_set_mute */
98#define AMRADIO_START 0x00
99#define AMRADIO_STOP 0x01
100
2aa72f3b
AK
101/* module parameter */
102static int radio_nr = -1;
103module_param(radio_nr, int, 0);
104MODULE_PARM_DESC(radio_nr, "Radio Nr");
105
106static struct v4l2_queryctrl radio_qctrl[] = {
107 {
108 .id = V4L2_CID_AUDIO_MUTE,
109 .name = "Mute",
110 .minimum = 0,
111 .maximum = 1,
112 .step = 1,
113 .default_value = 1,
114 .type = V4L2_CTRL_TYPE_BOOLEAN,
115 },
116/* HINT: the disabled controls are only here to satify kradio and such apps */
117 { .id = V4L2_CID_AUDIO_VOLUME,
118 .flags = V4L2_CTRL_FLAG_DISABLED,
119 },
120 {
121 .id = V4L2_CID_AUDIO_BALANCE,
122 .flags = V4L2_CTRL_FLAG_DISABLED,
123 },
124 {
125 .id = V4L2_CID_AUDIO_BASS,
126 .flags = V4L2_CTRL_FLAG_DISABLED,
127 },
128 {
129 .id = V4L2_CID_AUDIO_TREBLE,
130 .flags = V4L2_CTRL_FLAG_DISABLED,
131 },
132 {
133 .id = V4L2_CID_AUDIO_LOUDNESS,
134 .flags = V4L2_CTRL_FLAG_DISABLED,
135 },
136};
137
138static int usb_amradio_probe(struct usb_interface *intf,
139 const struct usb_device_id *id);
140static void usb_amradio_disconnect(struct usb_interface *intf);
bec43661
HV
141static int usb_amradio_open(struct file *file);
142static int usb_amradio_close(struct file *file);
2aa72f3b
AK
143static int usb_amradio_suspend(struct usb_interface *intf,
144 pm_message_t message);
145static int usb_amradio_resume(struct usb_interface *intf);
146
147/* Data for one (physical) device */
148struct amradio_device {
149 /* reference to USB and video device */
150 struct usb_device *usbdev;
151 struct video_device *videodev;
152
153 unsigned char *buffer;
154 struct mutex lock; /* buffer locking */
155 int curfreq;
156 int stereo;
157 int users;
158 int removed;
159 int muted;
160};
161
162/* USB Device ID List */
163static struct usb_device_id usb_amradio_device_table[] = {
164 {USB_DEVICE_AND_INTERFACE_INFO(USB_AMRADIO_VENDOR, USB_AMRADIO_PRODUCT,
165 USB_CLASS_HID, 0, 0) },
166 { } /* Terminating entry */
167};
168
169MODULE_DEVICE_TABLE(usb, usb_amradio_device_table);
170
171/* USB subsystem interface */
172static struct usb_driver usb_amradio_driver = {
e60b022e 173 .name = MR800_DRIVER_NAME,
2aa72f3b
AK
174 .probe = usb_amradio_probe,
175 .disconnect = usb_amradio_disconnect,
176 .suspend = usb_amradio_suspend,
177 .resume = usb_amradio_resume,
178 .reset_resume = usb_amradio_resume,
179 .id_table = usb_amradio_device_table,
f2ce9179 180 .supports_autosuspend = 0,
2aa72f3b
AK
181};
182
db821804
AK
183/* switch on/off the radio. Send 8 bytes to device */
184static int amradio_set_mute(struct amradio_device *radio, char argument)
2aa72f3b
AK
185{
186 int retval;
187 int size;
188
3480130a
AK
189 /* safety check */
190 if (radio->removed)
191 return -EIO;
192
2aa72f3b
AK
193 mutex_lock(&radio->lock);
194
195 radio->buffer[0] = 0x00;
196 radio->buffer[1] = 0x55;
197 radio->buffer[2] = 0xaa;
198 radio->buffer[3] = 0x00;
db821804
AK
199 radio->buffer[4] = AMRADIO_SET_MUTE;
200 radio->buffer[5] = argument;
2aa72f3b
AK
201 radio->buffer[6] = 0x00;
202 radio->buffer[7] = 0x00;
203
204 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
205 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
206
207 if (retval) {
208 mutex_unlock(&radio->lock);
209 return retval;
210 }
211
db821804 212 radio->muted = argument;
2aa72f3b 213
7f03a585
AK
214 mutex_unlock(&radio->lock);
215
2aa72f3b
AK
216 return retval;
217}
218
219/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
220static int amradio_setfreq(struct amradio_device *radio, int freq)
221{
222 int retval;
223 int size;
f7c1a380 224 unsigned short freq_send = 0x10 + (freq >> 3) / 25;
2aa72f3b 225
3480130a
AK
226 /* safety check */
227 if (radio->removed)
228 return -EIO;
229
2aa72f3b
AK
230 mutex_lock(&radio->lock);
231
232 radio->buffer[0] = 0x00;
233 radio->buffer[1] = 0x55;
234 radio->buffer[2] = 0xaa;
235 radio->buffer[3] = 0x03;
f7c1a380 236 radio->buffer[4] = AMRADIO_SET_FREQ;
2aa72f3b
AK
237 radio->buffer[5] = 0x00;
238 radio->buffer[6] = 0x00;
239 radio->buffer[7] = 0x08;
240
241 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
242 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
243
244 if (retval) {
245 mutex_unlock(&radio->lock);
246 return retval;
247 }
248
249 /* frequency is calculated from freq_send and placed in first 2 bytes */
250 radio->buffer[0] = (freq_send >> 8) & 0xff;
251 radio->buffer[1] = freq_send & 0xff;
252 radio->buffer[2] = 0x01;
253 radio->buffer[3] = 0x00;
254 radio->buffer[4] = 0x00;
255 /* 5 and 6 bytes of buffer already = 0x00 */
256 radio->buffer[7] = 0x00;
257
258 retval = usb_bulk_msg(radio->usbdev, usb_sndintpipe(radio->usbdev, 2),
259 (void *) (radio->buffer), BUFFER_LENGTH, &size, USB_TIMEOUT);
260
261 if (retval) {
262 mutex_unlock(&radio->lock);
263 return retval;
264 }
265
2aa72f3b
AK
266 radio->stereo = 0;
267
7f03a585
AK
268 mutex_unlock(&radio->lock);
269
2aa72f3b
AK
270 return retval;
271}
272
273/* USB subsystem interface begins here */
274
275/* handle unplugging of the device, release data structures
276if nothing keeps us from doing it. If something is still
277keeping us busy, the release callback of v4l will take care
278of releasing it. */
279static void usb_amradio_disconnect(struct usb_interface *intf)
280{
281 struct amradio_device *radio = usb_get_intfdata(intf);
282
f4e9043e 283 mutex_lock(&radio->lock);
3480130a 284 radio->removed = 1;
f4e9043e 285 mutex_unlock(&radio->lock);
2aa72f3b 286
f4e9043e
AK
287 usb_set_intfdata(intf, NULL);
288 video_unregister_device(radio->videodev);
2aa72f3b
AK
289}
290
291/* vidioc_querycap - query device capabilities */
292static int vidioc_querycap(struct file *file, void *priv,
293 struct v4l2_capability *v)
294{
c7181cfa
AK
295 struct amradio_device *radio = video_drvdata(file);
296
2aa72f3b
AK
297 strlcpy(v->driver, "radio-mr800", sizeof(v->driver));
298 strlcpy(v->card, "AverMedia MR 800 USB FM Radio", sizeof(v->card));
c7181cfa 299 usb_make_path(radio->usbdev, v->bus_info, sizeof(v->bus_info));
2aa72f3b
AK
300 v->version = RADIO_VERSION;
301 v->capabilities = V4L2_CAP_TUNER;
302 return 0;
303}
304
305/* vidioc_g_tuner - get tuner attributes */
306static int vidioc_g_tuner(struct file *file, void *priv,
307 struct v4l2_tuner *v)
308{
309 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
310
3480130a
AK
311 /* safety check */
312 if (radio->removed)
313 return -EIO;
314
2aa72f3b
AK
315 if (v->index > 0)
316 return -EINVAL;
317
318/* TODO: Add function which look is signal stereo or not
319 * amradio_getstat(radio);
320 */
321 radio->stereo = -1;
322 strcpy(v->name, "FM");
323 v->type = V4L2_TUNER_RADIO;
324 v->rangelow = FREQ_MIN * FREQ_MUL;
325 v->rangehigh = FREQ_MAX * FREQ_MUL;
326 v->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
327 v->capability = V4L2_TUNER_CAP_LOW;
328 if (radio->stereo)
329 v->audmode = V4L2_TUNER_MODE_STEREO;
330 else
331 v->audmode = V4L2_TUNER_MODE_MONO;
332 v->signal = 0xffff; /* Can't get the signal strength, sad.. */
333 v->afc = 0; /* Don't know what is this */
334 return 0;
335}
336
337/* vidioc_s_tuner - set tuner attributes */
338static int vidioc_s_tuner(struct file *file, void *priv,
339 struct v4l2_tuner *v)
340{
3480130a
AK
341 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
342
343 /* safety check */
344 if (radio->removed)
345 return -EIO;
346
2aa72f3b
AK
347 if (v->index > 0)
348 return -EINVAL;
349 return 0;
350}
351
352/* vidioc_s_frequency - set tuner radio frequency */
353static int vidioc_s_frequency(struct file *file, void *priv,
354 struct v4l2_frequency *f)
355{
356 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
a5d69475 357 int retval;
2aa72f3b 358
3480130a
AK
359 /* safety check */
360 if (radio->removed)
361 return -EIO;
362
2aa72f3b 363 radio->curfreq = f->frequency;
a5d69475
AK
364 retval = amradio_setfreq(radio, radio->curfreq);
365 if (retval < 0)
e60b022e
AK
366 amradio_dev_warn(&radio->videodev->dev,
367 "set frequency failed\n");
2aa72f3b
AK
368 return 0;
369}
370
371/* vidioc_g_frequency - get tuner radio frequency */
372static int vidioc_g_frequency(struct file *file, void *priv,
373 struct v4l2_frequency *f)
374{
375 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
376
3480130a
AK
377 /* safety check */
378 if (radio->removed)
379 return -EIO;
380
2aa72f3b
AK
381 f->type = V4L2_TUNER_RADIO;
382 f->frequency = radio->curfreq;
383 return 0;
384}
385
386/* vidioc_queryctrl - enumerate control items */
387static int vidioc_queryctrl(struct file *file, void *priv,
388 struct v4l2_queryctrl *qc)
389{
390 int i;
391
392 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
393 if (qc->id && qc->id == radio_qctrl[i].id) {
e60b022e 394 memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
2aa72f3b
AK
395 return 0;
396 }
397 }
398 return -EINVAL;
399}
400
401/* vidioc_g_ctrl - get the value of a control */
402static int vidioc_g_ctrl(struct file *file, void *priv,
403 struct v4l2_control *ctrl)
404{
405 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
406
3480130a
AK
407 /* safety check */
408 if (radio->removed)
409 return -EIO;
410
2aa72f3b
AK
411 switch (ctrl->id) {
412 case V4L2_CID_AUDIO_MUTE:
413 ctrl->value = radio->muted;
414 return 0;
415 }
416 return -EINVAL;
417}
418
419/* vidioc_s_ctrl - set the value of a control */
420static int vidioc_s_ctrl(struct file *file, void *priv,
421 struct v4l2_control *ctrl)
422{
423 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
a5d69475 424 int retval;
2aa72f3b 425
3480130a
AK
426 /* safety check */
427 if (radio->removed)
428 return -EIO;
429
2aa72f3b
AK
430 switch (ctrl->id) {
431 case V4L2_CID_AUDIO_MUTE:
432 if (ctrl->value) {
db821804 433 retval = amradio_set_mute(radio, AMRADIO_STOP);
a5d69475 434 if (retval < 0) {
e60b022e
AK
435 amradio_dev_warn(&radio->videodev->dev,
436 "amradio_stop failed\n");
2aa72f3b
AK
437 return -1;
438 }
439 } else {
db821804 440 retval = amradio_set_mute(radio, AMRADIO_START);
a5d69475 441 if (retval < 0) {
e60b022e
AK
442 amradio_dev_warn(&radio->videodev->dev,
443 "amradio_start failed\n");
2aa72f3b
AK
444 return -1;
445 }
446 }
447 return 0;
448 }
449 return -EINVAL;
450}
451
452/* vidioc_g_audio - get audio attributes */
453static int vidioc_g_audio(struct file *file, void *priv,
454 struct v4l2_audio *a)
455{
456 if (a->index > 1)
457 return -EINVAL;
458
459 strcpy(a->name, "Radio");
460 a->capability = V4L2_AUDCAP_STEREO;
461 return 0;
462}
463
464/* vidioc_s_audio - set audio attributes */
465static int vidioc_s_audio(struct file *file, void *priv,
466 struct v4l2_audio *a)
467{
468 if (a->index != 0)
469 return -EINVAL;
470 return 0;
471}
472
473/* vidioc_g_input - get input */
474static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
475{
476 *i = 0;
477 return 0;
478}
479
480/* vidioc_s_input - set input */
481static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
482{
483 if (i != 0)
484 return -EINVAL;
485 return 0;
486}
487
488/* open device - amradio_start() and amradio_setfreq() */
bec43661 489static int usb_amradio_open(struct file *file)
2aa72f3b
AK
490{
491 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
a5d69475 492 int retval;
2aa72f3b 493
0fabb783
AK
494 lock_kernel();
495
2aa72f3b
AK
496 radio->users = 1;
497 radio->muted = 1;
498
db821804 499 retval = amradio_set_mute(radio, AMRADIO_START);
a5d69475 500 if (retval < 0) {
e60b022e
AK
501 amradio_dev_warn(&radio->videodev->dev,
502 "radio did not start up properly\n");
2aa72f3b 503 radio->users = 0;
0fabb783 504 unlock_kernel();
2aa72f3b
AK
505 return -EIO;
506 }
a5d69475
AK
507
508 retval = amradio_setfreq(radio, radio->curfreq);
509 if (retval < 0)
e60b022e
AK
510 amradio_dev_warn(&radio->videodev->dev,
511 "set frequency failed\n");
0fabb783
AK
512
513 unlock_kernel();
2aa72f3b
AK
514 return 0;
515}
516
f4e9043e 517/*close device */
bec43661 518static int usb_amradio_close(struct file *file)
2aa72f3b
AK
519{
520 struct amradio_device *radio = video_get_drvdata(video_devdata(file));
3480130a 521 int retval;
2aa72f3b
AK
522
523 if (!radio)
524 return -ENODEV;
3480130a 525
2aa72f3b 526 radio->users = 0;
3480130a 527
f4e9043e 528 if (!radio->removed) {
db821804 529 retval = amradio_set_mute(radio, AMRADIO_STOP);
3480130a
AK
530 if (retval < 0)
531 amradio_dev_warn(&radio->videodev->dev,
532 "amradio_stop failed\n");
2aa72f3b 533 }
3480130a 534
2aa72f3b
AK
535 return 0;
536}
537
538/* Suspend device - stop device. Need to be checked and fixed */
539static int usb_amradio_suspend(struct usb_interface *intf, pm_message_t message)
540{
541 struct amradio_device *radio = usb_get_intfdata(intf);
a5d69475 542 int retval;
2aa72f3b 543
db821804 544 retval = amradio_set_mute(radio, AMRADIO_STOP);
a5d69475 545 if (retval < 0)
e60b022e 546 dev_warn(&intf->dev, "amradio_stop failed\n");
2aa72f3b 547
e60b022e 548 dev_info(&intf->dev, "going into suspend..\n");
2aa72f3b
AK
549
550 return 0;
551}
552
553/* Resume device - start device. Need to be checked and fixed */
554static int usb_amradio_resume(struct usb_interface *intf)
555{
556 struct amradio_device *radio = usb_get_intfdata(intf);
a5d69475 557 int retval;
2aa72f3b 558
db821804 559 retval = amradio_set_mute(radio, AMRADIO_START);
a5d69475 560 if (retval < 0)
e60b022e 561 dev_warn(&intf->dev, "amradio_start failed\n");
2aa72f3b 562
e60b022e 563 dev_info(&intf->dev, "coming out of suspend..\n");
2aa72f3b
AK
564
565 return 0;
566}
567
568/* File system interface */
bec43661 569static const struct v4l2_file_operations usb_amradio_fops = {
2aa72f3b
AK
570 .owner = THIS_MODULE,
571 .open = usb_amradio_open,
572 .release = usb_amradio_close,
573 .ioctl = video_ioctl2,
2aa72f3b
AK
574};
575
576static const struct v4l2_ioctl_ops usb_amradio_ioctl_ops = {
577 .vidioc_querycap = vidioc_querycap,
578 .vidioc_g_tuner = vidioc_g_tuner,
579 .vidioc_s_tuner = vidioc_s_tuner,
580 .vidioc_g_frequency = vidioc_g_frequency,
581 .vidioc_s_frequency = vidioc_s_frequency,
582 .vidioc_queryctrl = vidioc_queryctrl,
583 .vidioc_g_ctrl = vidioc_g_ctrl,
584 .vidioc_s_ctrl = vidioc_s_ctrl,
585 .vidioc_g_audio = vidioc_g_audio,
586 .vidioc_s_audio = vidioc_s_audio,
587 .vidioc_g_input = vidioc_g_input,
588 .vidioc_s_input = vidioc_s_input,
589};
590
f4e9043e
AK
591static void usb_amradio_device_release(struct video_device *videodev)
592{
593 struct amradio_device *radio = video_get_drvdata(videodev);
594
595 /* we call v4l to free radio->videodev */
596 video_device_release(videodev);
597
598 /* free rest memory */
599 kfree(radio->buffer);
600 kfree(radio);
601}
602
2aa72f3b
AK
603/* V4L2 interface */
604static struct video_device amradio_videodev_template = {
605 .name = "AverMedia MR 800 USB FM Radio",
606 .fops = &usb_amradio_fops,
607 .ioctl_ops = &usb_amradio_ioctl_ops,
f4e9043e 608 .release = usb_amradio_device_release,
2aa72f3b
AK
609};
610
a5d69475 611/* check if the device is present and register with v4l and usb if it is */
2aa72f3b
AK
612static int usb_amradio_probe(struct usb_interface *intf,
613 const struct usb_device_id *id)
614{
615 struct amradio_device *radio;
a5d69475 616 int retval;
2aa72f3b
AK
617
618 radio = kmalloc(sizeof(struct amradio_device), GFP_KERNEL);
619
8edafcc6
AK
620 if (!radio) {
621 dev_err(&intf->dev, "kmalloc for amradio_device failed\n");
2aa72f3b 622 return -ENOMEM;
8edafcc6 623 }
2aa72f3b
AK
624
625 radio->buffer = kmalloc(BUFFER_LENGTH, GFP_KERNEL);
626
8edafcc6
AK
627 if (!radio->buffer) {
628 dev_err(&intf->dev, "kmalloc for radio->buffer failed\n");
2aa72f3b
AK
629 kfree(radio);
630 return -ENOMEM;
631 }
632
633 radio->videodev = video_device_alloc();
634
8edafcc6
AK
635 if (!radio->videodev) {
636 dev_err(&intf->dev, "video_device_alloc failed\n");
2aa72f3b
AK
637 kfree(radio->buffer);
638 kfree(radio);
639 return -ENOMEM;
640 }
641
642 memcpy(radio->videodev, &amradio_videodev_template,
643 sizeof(amradio_videodev_template));
644
645 radio->removed = 0;
646 radio->users = 0;
647 radio->usbdev = interface_to_usbdev(intf);
648 radio->curfreq = 95.16 * FREQ_MUL;
649
650 mutex_init(&radio->lock);
651
652 video_set_drvdata(radio->videodev, radio);
a5d69475
AK
653 retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
654 if (retval < 0) {
65c51dc9 655 dev_err(&intf->dev, "could not register video device\n");
2aa72f3b
AK
656 video_device_release(radio->videodev);
657 kfree(radio->buffer);
658 kfree(radio);
659 return -EIO;
660 }
661
662 usb_set_intfdata(intf, radio);
663 return 0;
664}
665
666static int __init amradio_init(void)
667{
668 int retval = usb_register(&usb_amradio_driver);
669
e60b022e
AK
670 pr_info(KBUILD_MODNAME
671 ": version " DRIVER_VERSION " " DRIVER_DESC "\n");
672
2aa72f3b 673 if (retval)
e60b022e
AK
674 pr_err(KBUILD_MODNAME
675 ": usb_register failed. Error number %d\n", retval);
676
2aa72f3b
AK
677 return retval;
678}
679
680static void __exit amradio_exit(void)
681{
682 usb_deregister(&usb_amradio_driver);
683}
684
685module_init(amradio_init);
686module_exit(amradio_exit);
687
This page took 0.105353 seconds and 5 git commands to generate.