header cleaning: don't include smp_lock.h when not used
[linux-drm-fsl-dcu.git] / drivers / media / radio / dsbr100.c
1 /* A driver for the D-Link DSB-R100 USB radio.  The R100 plugs
2  into both the USB and an analog audio input, so this thing
3  only deals with initialisation and frequency setting, the
4  audio data has to be handled by a sound driver.
5
6  Major issue: I can't find out where the device reports the signal
7  strength, and indeed the windows software appearantly just looks
8  at the stereo indicator as well.  So, scanning will only find
9  stereo stations.  Sad, but I can't help it.
10
11  Also, the windows program sends oodles of messages over to the
12  device, and I couldn't figure out their meaning.  My suspicion
13  is that they don't have any:-)
14
15  You might find some interesting stuff about this module at
16  http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr
17
18  Copyright (c) 2000 Markus Demleitner <msdemlei@cl.uni-heidelberg.de>
19
20  This program is free software; you can redistribute it and/or modify
21  it under the terms of the GNU General Public License as published by
22  the Free Software Foundation; either version 2 of the License, or
23  (at your option) any later version.
24
25  This program is distributed in the hope that it will be useful,
26  but WITHOUT ANY WARRANTY; without even the implied warranty of
27  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  GNU General Public License for more details.
29
30  You should have received a copy of the GNU General Public License
31  along with this program; if not, write to the Free Software
32  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33
34  History:
35
36  Version 0.41-ac1:
37         Alan Cox: Some cleanups and fixes
38
39  Version 0.41:
40         Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
41
42  Version 0.40:
43         Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing
44
45  Version 0.30:
46         Markus: Updates for 2.5.x kernel and more ISO compliant source
47
48  Version 0.25:
49         PSL and Markus: Cleanup, radio now doesn't stop on device close
50
51  Version 0.24:
52         Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
53         right.  Some minor cleanup, improved standalone compilation
54
55  Version 0.23:
56         Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
57
58  Version 0.22:
59         Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns,
60         thanks to Mike Cox for pointing the problem out.
61
62  Version 0.21:
63         Markus: Minor cleanup, warnings if something goes wrong, lame attempt
64         to adhere to Documentation/CodingStyle
65
66  Version 0.2:
67         Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module
68         Markus: Copyright clarification
69
70  Version 0.01: Markus: initial release
71
72 */
73
74 #include <linux/kernel.h>
75 #include <linux/module.h>
76 #include <linux/init.h>
77 #include <linux/slab.h>
78 #include <linux/input.h>
79 #include <linux/videodev2.h>
80 #include <media/v4l2-common.h>
81 #include <linux/usb.h>
82
83 /*
84  * Version Information
85  */
86 #include <linux/version.h>      /* for KERNEL_VERSION MACRO     */
87
88 #define DRIVER_VERSION "v0.41"
89 #define RADIO_VERSION KERNEL_VERSION(0,4,1)
90
91 static struct v4l2_queryctrl radio_qctrl[] = {
92         {
93                 .id            = V4L2_CID_AUDIO_MUTE,
94                 .name          = "Mute",
95                 .minimum       = 0,
96                 .maximum       = 1,
97                 .default_value = 1,
98                 .type          = V4L2_CTRL_TYPE_BOOLEAN,
99         }
100 };
101
102 #define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>"
103 #define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver"
104
105 #define DSB100_VENDOR 0x04b4
106 #define DSB100_PRODUCT 0x1002
107
108 /* Commands the device appears to understand */
109 #define DSB100_TUNE 1
110 #define DSB100_ONOFF 2
111
112 #define TB_LEN 16
113
114 /* Frequency limits in MHz -- these are European values.  For Japanese
115 devices, that would be 76 and 91.  */
116 #define FREQ_MIN  87.5
117 #define FREQ_MAX 108.0
118 #define FREQ_MUL 16000
119
120
121 static int usb_dsbr100_probe(struct usb_interface *intf,
122                              const struct usb_device_id *id);
123 static void usb_dsbr100_disconnect(struct usb_interface *intf);
124 static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
125                              unsigned int cmd, unsigned long arg);
126 static int usb_dsbr100_open(struct inode *inode, struct file *file);
127 static int usb_dsbr100_close(struct inode *inode, struct file *file);
128
129 static int radio_nr = -1;
130 module_param(radio_nr, int, 0);
131
132 /* Data for one (physical) device */
133 struct dsbr100_device {
134         struct usb_device *usbdev;
135         struct video_device *videodev;
136         unsigned char transfer_buffer[TB_LEN];
137         int curfreq;
138         int stereo;
139         int users;
140         int removed;
141         int muted;
142 };
143
144
145 /* File system interface */
146 static const struct file_operations usb_dsbr100_fops = {
147         .owner =        THIS_MODULE,
148         .open =         usb_dsbr100_open,
149         .release =      usb_dsbr100_close,
150         .ioctl =        usb_dsbr100_ioctl,
151         .compat_ioctl = v4l_compat_ioctl32,
152         .llseek =       no_llseek,
153 };
154
155 /* V4L interface */
156 static struct video_device dsbr100_videodev_template=
157 {
158         .owner =        THIS_MODULE,
159         .name =         "D-Link DSB-R 100",
160         .type =         VID_TYPE_TUNER,
161         .fops =         &usb_dsbr100_fops,
162         .release = video_device_release,
163 };
164
165 static struct usb_device_id usb_dsbr100_device_table [] = {
166         { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
167         { }                                             /* Terminating entry */
168 };
169
170 MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table);
171
172 /* USB subsystem interface */
173 static struct usb_driver usb_dsbr100_driver = {
174         .name =         "dsbr100",
175         .probe =        usb_dsbr100_probe,
176         .disconnect =   usb_dsbr100_disconnect,
177         .id_table =     usb_dsbr100_device_table,
178 };
179
180 /* Low-level device interface begins here */
181
182 /* switch on radio */
183 static int dsbr100_start(struct dsbr100_device *radio)
184 {
185         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
186                         USB_REQ_GET_STATUS,
187                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
188                         0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 ||
189         usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
190                         DSB100_ONOFF,
191                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
192                         0x01, 0x00, radio->transfer_buffer, 8, 300)<0)
193                 return -1;
194         radio->muted=0;
195         return (radio->transfer_buffer)[0];
196 }
197
198
199 /* switch off radio */
200 static int dsbr100_stop(struct dsbr100_device *radio)
201 {
202         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
203                         USB_REQ_GET_STATUS,
204                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
205                         0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 ||
206         usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
207                         DSB100_ONOFF,
208                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
209                         0x00, 0x00, radio->transfer_buffer, 8, 300)<0)
210                 return -1;
211         radio->muted=1;
212         return (radio->transfer_buffer)[0];
213 }
214
215 /* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
216 static int dsbr100_setfreq(struct dsbr100_device *radio, int freq)
217 {
218         freq = (freq/16*80)/1000+856;
219         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
220                         DSB100_TUNE,
221                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
222                         (freq>>8)&0x00ff, freq&0xff,
223                         radio->transfer_buffer, 8, 300)<0 ||
224            usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
225                         USB_REQ_GET_STATUS,
226                         USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
227                         0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
228         usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
229                         USB_REQ_GET_STATUS,
230                         USB_TYPE_VENDOR | USB_RECIP_DEVICE |  USB_DIR_IN,
231                         0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
232                 radio->stereo = -1;
233                 return -1;
234         }
235         radio->stereo = ! ((radio->transfer_buffer)[0]&0x01);
236         return (radio->transfer_buffer)[0];
237 }
238
239 /* return the device status.  This is, in effect, just whether it
240 sees a stereo signal or not.  Pity. */
241 static void dsbr100_getstat(struct dsbr100_device *radio)
242 {
243         if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0),
244                 USB_REQ_GET_STATUS,
245                 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
246                 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0)
247                 radio->stereo = -1;
248         else
249                 radio->stereo = ! (radio->transfer_buffer[0]&0x01);
250 }
251
252
253 /* USB subsystem interface begins here */
254
255 /* check if the device is present and register with v4l and
256 usb if it is */
257 static int usb_dsbr100_probe(struct usb_interface *intf,
258                          const struct usb_device_id *id)
259 {
260         struct dsbr100_device *radio;
261
262         if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
263                 return -ENOMEM;
264         if (!(radio->videodev = video_device_alloc())) {
265                 kfree(radio);
266                 return -ENOMEM;
267         }
268         memcpy(radio->videodev, &dsbr100_videodev_template,
269                 sizeof(dsbr100_videodev_template));
270         radio->removed = 0;
271         radio->users = 0;
272         radio->usbdev = interface_to_usbdev(intf);
273         radio->curfreq = FREQ_MIN*FREQ_MUL;
274         video_set_drvdata(radio->videodev, radio);
275         if (video_register_device(radio->videodev, VFL_TYPE_RADIO,
276                 radio_nr)) {
277                 warn("Could not register video device");
278                 video_device_release(radio->videodev);
279                 kfree(radio);
280                 return -EIO;
281         }
282         usb_set_intfdata(intf, radio);
283         return 0;
284 }
285
286 /* handle unplugging of the device, release data structures
287 if nothing keeps us from doing it.  If something is still
288 keeping us busy, the release callback of v4l will take care
289 of releasing it.  stv680.c does not relase its private
290 data, so I don't do this here either.  Checking out the
291 code I'd expect I better did that, but if there's a memory
292 leak here it's tiny (~50 bytes per disconnect) */
293 static void usb_dsbr100_disconnect(struct usb_interface *intf)
294 {
295         struct dsbr100_device *radio = usb_get_intfdata(intf);
296
297         usb_set_intfdata (intf, NULL);
298         if (radio) {
299                 video_unregister_device(radio->videodev);
300                 radio->videodev = NULL;
301                 if (radio->users) {
302                         kfree(radio);
303                 } else {
304                         radio->removed = 1;
305                 }
306         }
307 }
308
309
310 /* Video for Linux interface */
311
312 static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
313                                 unsigned int cmd, void *arg)
314 {
315         struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
316
317         if (!radio)
318                 return -EIO;
319
320         switch(cmd) {
321                 case VIDIOC_QUERYCAP:
322                 {
323                         struct v4l2_capability *v = arg;
324                         memset(v,0,sizeof(*v));
325                         strlcpy(v->driver, "dsbr100", sizeof (v->driver));
326                         strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof (v->card));
327                         sprintf(v->bus_info,"ISA");
328                         v->version = RADIO_VERSION;
329                         v->capabilities = V4L2_CAP_TUNER;
330
331                         return 0;
332                 }
333                 case VIDIOC_G_TUNER:
334                 {
335                         struct v4l2_tuner *v = arg;
336
337                         if (v->index > 0)
338                                 return -EINVAL;
339
340                         dsbr100_getstat(radio);
341
342                         memset(v,0,sizeof(*v));
343                         strcpy(v->name, "FM");
344                         v->type = V4L2_TUNER_RADIO;
345
346                         v->rangelow = FREQ_MIN*FREQ_MUL;
347                         v->rangehigh = FREQ_MAX*FREQ_MUL;
348                         v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
349                         v->capability=V4L2_TUNER_CAP_LOW;
350                         if(radio->stereo)
351                                 v->audmode = V4L2_TUNER_MODE_STEREO;
352                         else
353                                 v->audmode = V4L2_TUNER_MODE_MONO;
354                         v->signal = 0xFFFF;     /* We can't get the signal strength */
355
356                         return 0;
357                 }
358                 case VIDIOC_S_TUNER:
359                 {
360                         struct v4l2_tuner *v = arg;
361
362                         if (v->index > 0)
363                                 return -EINVAL;
364
365                         return 0;
366                 }
367                 case VIDIOC_S_FREQUENCY:
368                 {
369                         struct v4l2_frequency *f = arg;
370
371                         radio->curfreq = f->frequency;
372                         if (dsbr100_setfreq(radio, radio->curfreq)==-1)
373                                 warn("Set frequency failed");
374                         return 0;
375                 }
376                 case VIDIOC_G_FREQUENCY:
377                 {
378                         struct v4l2_frequency *f = arg;
379
380                         f->type = V4L2_TUNER_RADIO;
381                         f->frequency = radio->curfreq;
382
383                         return 0;
384                 }
385                 case VIDIOC_QUERYCTRL:
386                 {
387                         struct v4l2_queryctrl *qc = arg;
388                         int i;
389
390                         for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
391                                 if (qc->id && qc->id == radio_qctrl[i].id) {
392                                         memcpy(qc, &(radio_qctrl[i]),
393                                                                 sizeof(*qc));
394                                         return 0;
395                                 }
396                         }
397                         return -EINVAL;
398                 }
399                 case VIDIOC_G_CTRL:
400                 {
401                         struct v4l2_control *ctrl= arg;
402
403                         switch (ctrl->id) {
404                         case V4L2_CID_AUDIO_MUTE:
405                                 ctrl->value=radio->muted;
406                                 return 0;
407                         }
408                         return -EINVAL;
409                 }
410                 case VIDIOC_S_CTRL:
411                 {
412                         struct v4l2_control *ctrl= arg;
413
414                         switch (ctrl->id) {
415                         case V4L2_CID_AUDIO_MUTE:
416                                 if (ctrl->value) {
417                                         if (dsbr100_stop(radio)==-1)
418                                                 warn("Radio did not respond properly");
419                                 } else {
420                                         if (dsbr100_start(radio)==-1)
421                                                 warn("Radio did not respond properly");
422                                 }
423                                 return 0;
424                         }
425                         return -EINVAL;
426                 }
427                 default:
428                         return v4l_compat_translate_ioctl(inode,file,cmd,arg,
429                                                           usb_dsbr100_do_ioctl);
430         }
431 }
432
433 static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
434                              unsigned int cmd, unsigned long arg)
435 {
436         return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl);
437 }
438
439 static int usb_dsbr100_open(struct inode *inode, struct file *file)
440 {
441         struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
442
443         radio->users = 1;
444         radio->muted = 1;
445
446         if (dsbr100_start(radio)<0) {
447                 warn("Radio did not start up properly");
448                 radio->users = 0;
449                 return -EIO;
450         }
451         dsbr100_setfreq(radio, radio->curfreq);
452         return 0;
453 }
454
455 static int usb_dsbr100_close(struct inode *inode, struct file *file)
456 {
457         struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
458
459         if (!radio)
460                 return -ENODEV;
461         radio->users = 0;
462         if (radio->removed) {
463                 kfree(radio);
464         }
465         return 0;
466 }
467
468 static int __init dsbr100_init(void)
469 {
470         int retval = usb_register(&usb_dsbr100_driver);
471         info(DRIVER_VERSION ":" DRIVER_DESC);
472         return retval;
473 }
474
475 static void __exit dsbr100_exit(void)
476 {
477         usb_deregister(&usb_dsbr100_driver);
478 }
479
480 module_init (dsbr100_init);
481 module_exit (dsbr100_exit);
482
483 MODULE_AUTHOR( DRIVER_AUTHOR );
484 MODULE_DESCRIPTION( DRIVER_DESC );
485 MODULE_LICENSE("GPL");