aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/radio')
-rw-r--r--drivers/media/radio/dsbr100.c2
-rw-r--r--drivers/media/radio/miropcm20-radio.c2
-rw-r--r--drivers/media/radio/miropcm20-rds.c2
-rw-r--r--drivers/media/radio/radio-aimslab.c2
-rw-r--r--drivers/media/radio/radio-aztech.c2
-rw-r--r--drivers/media/radio/radio-cadet.c12
-rw-r--r--drivers/media/radio/radio-gemtek-pci.c2
-rw-r--r--drivers/media/radio/radio-gemtek.c2
-rw-r--r--drivers/media/radio/radio-maestro.c2
-rw-r--r--drivers/media/radio/radio-maxiradio.c2
-rw-r--r--drivers/media/radio/radio-rtrack2.c2
-rw-r--r--drivers/media/radio/radio-sf16fmi.c2
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c104
-rw-r--r--drivers/media/radio/radio-si470x.c59
-rw-r--r--drivers/media/radio/radio-terratec.c2
-rw-r--r--drivers/media/radio/radio-trust.c2
-rw-r--r--drivers/media/radio/radio-typhoon.c44
-rw-r--r--drivers/media/radio/radio-zoltrix.c2
18 files changed, 151 insertions, 96 deletions
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 36c0e3651502..4e3f83e4e48f 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -438,7 +438,9 @@ static const struct file_operations usb_dsbr100_fops = {
438 .open = usb_dsbr100_open, 438 .open = usb_dsbr100_open,
439 .release = usb_dsbr100_close, 439 .release = usb_dsbr100_close,
440 .ioctl = video_ioctl2, 440 .ioctl = video_ioctl2,
441#ifdef CONFIG_COMPAT
441 .compat_ioctl = v4l_compat_ioctl32, 442 .compat_ioctl = v4l_compat_ioctl32,
443#endif
442 .llseek = no_llseek, 444 .llseek = no_llseek,
443}; 445};
444 446
diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
index 3ae56fef8c92..09fe6f1cdf14 100644
--- a/drivers/media/radio/miropcm20-radio.c
+++ b/drivers/media/radio/miropcm20-radio.c
@@ -221,7 +221,9 @@ static const struct file_operations pcm20_fops = {
221 .open = video_exclusive_open, 221 .open = video_exclusive_open,
222 .release = video_exclusive_release, 222 .release = video_exclusive_release,
223 .ioctl = pcm20_ioctl, 223 .ioctl = pcm20_ioctl,
224#ifdef CONFIG_COMPAT
224 .compat_ioctl = v4l_compat_ioctl32, 225 .compat_ioctl = v4l_compat_ioctl32,
226#endif
225 .llseek = no_llseek, 227 .llseek = no_llseek,
226}; 228};
227 229
diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
index aed11477378b..06dfed9ef4c7 100644
--- a/drivers/media/radio/miropcm20-rds.c
+++ b/drivers/media/radio/miropcm20-rds.c
@@ -19,7 +19,7 @@
19#include "miropcm20-rds-core.h" 19#include "miropcm20-rds-core.h"
20 20
21static char * text_buffer; 21static char * text_buffer;
22static int rds_users = 0; 22static int rds_users;
23 23
24 24
25static int rds_f_open(struct inode *in, struct file *fi) 25static int rds_f_open(struct inode *in, struct file *fi)
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index c69bde39a233..1ec18ed1a733 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -382,7 +382,9 @@ static const struct file_operations rtrack_fops = {
382 .open = video_exclusive_open, 382 .open = video_exclusive_open,
383 .release = video_exclusive_release, 383 .release = video_exclusive_release,
384 .ioctl = video_ioctl2, 384 .ioctl = video_ioctl2,
385#ifdef CONFIG_COMPAT
385 .compat_ioctl = v4l_compat_ioctl32, 386 .compat_ioctl = v4l_compat_ioctl32,
387#endif
386 .llseek = no_llseek, 388 .llseek = no_llseek,
387}; 389};
388 390
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 9b1f7a99dac0..46cdb549eac7 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -346,7 +346,9 @@ static const struct file_operations aztech_fops = {
346 .open = video_exclusive_open, 346 .open = video_exclusive_open,
347 .release = video_exclusive_release, 347 .release = video_exclusive_release,
348 .ioctl = video_ioctl2, 348 .ioctl = video_ioctl2,
349#ifdef CONFIG_COMPAT
349 .compat_ioctl = v4l_compat_ioctl32, 350 .compat_ioctl = v4l_compat_ioctl32,
351#endif
350 .llseek = no_llseek, 352 .llseek = no_llseek,
351}; 353};
352 354
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 57b9e3adc8f0..b14db53ea456 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -69,13 +69,13 @@ static struct v4l2_queryctrl radio_qctrl[] = {
69 69
70static int io=-1; /* default to isapnp activation */ 70static int io=-1; /* default to isapnp activation */
71static int radio_nr = -1; 71static int radio_nr = -1;
72static int users=0; 72static int users;
73static int curtuner=0; 73static int curtuner;
74static int tunestat=0; 74static int tunestat;
75static int sigstrength=0; 75static int sigstrength;
76static wait_queue_head_t read_queue; 76static wait_queue_head_t read_queue;
77static struct timer_list readtimer; 77static struct timer_list readtimer;
78static __u8 rdsin=0,rdsout=0,rdsstat=0; 78static __u8 rdsin, rdsout, rdsstat;
79static unsigned char rdsbuf[RDS_BUFFER]; 79static unsigned char rdsbuf[RDS_BUFFER];
80static spinlock_t cadet_io_lock; 80static spinlock_t cadet_io_lock;
81 81
@@ -563,7 +563,9 @@ static const struct file_operations cadet_fops = {
563 .read = cadet_read, 563 .read = cadet_read,
564 .ioctl = video_ioctl2, 564 .ioctl = video_ioctl2,
565 .poll = cadet_poll, 565 .poll = cadet_poll,
566#ifdef CONFIG_COMPAT
566 .compat_ioctl = v4l_compat_ioctl32, 567 .compat_ioctl = v4l_compat_ioctl32,
568#endif
567 .llseek = no_llseek, 569 .llseek = no_llseek,
568}; 570};
569 571
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index 99a323131333..de49be971480 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -368,7 +368,9 @@ static const struct file_operations gemtek_pci_fops = {
368 .open = video_exclusive_open, 368 .open = video_exclusive_open,
369 .release = video_exclusive_release, 369 .release = video_exclusive_release,
370 .ioctl = video_ioctl2, 370 .ioctl = video_ioctl2,
371#ifdef CONFIG_COMPAT
371 .compat_ioctl = v4l_compat_ioctl32, 372 .compat_ioctl = v4l_compat_ioctl32,
373#endif
372 .llseek = no_llseek, 374 .llseek = no_llseek,
373}; 375};
374 376
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 246422b49267..81f6aeb1cd11 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -397,7 +397,9 @@ static const struct file_operations gemtek_fops = {
397 .open = video_exclusive_open, 397 .open = video_exclusive_open,
398 .release = video_exclusive_release, 398 .release = video_exclusive_release,
399 .ioctl = video_ioctl2, 399 .ioctl = video_ioctl2,
400#ifdef CONFIG_COMPAT
400 .compat_ioctl = v4l_compat_ioctl32, 401 .compat_ioctl = v4l_compat_ioctl32,
402#endif
401 .llseek = no_llseek 403 .llseek = no_llseek
402}; 404};
403 405
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index bc51f4d23a5a..bddd3c409aa9 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -100,7 +100,9 @@ static const struct file_operations maestro_fops = {
100 .open = video_exclusive_open, 100 .open = video_exclusive_open,
101 .release = video_exclusive_release, 101 .release = video_exclusive_release,
102 .ioctl = video_ioctl2, 102 .ioctl = video_ioctl2,
103#ifdef CONFIG_COMPAT
103 .compat_ioctl = v4l_compat_ioctl32, 104 .compat_ioctl = v4l_compat_ioctl32,
105#endif
104 .llseek = no_llseek, 106 .llseek = no_llseek,
105}; 107};
106 108
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index 8e184cfc1c94..0133ecf3e040 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -103,7 +103,9 @@ static const struct file_operations maxiradio_fops = {
103 .open = video_exclusive_open, 103 .open = video_exclusive_open,
104 .release = video_exclusive_release, 104 .release = video_exclusive_release,
105 .ioctl = video_ioctl2, 105 .ioctl = video_ioctl2,
106#ifdef CONFIG_COMPAT
106 .compat_ioctl = v4l_compat_ioctl32, 107 .compat_ioctl = v4l_compat_ioctl32,
108#endif
107 .llseek = no_llseek, 109 .llseek = no_llseek,
108}; 110};
109 111
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index 82aedfc95d4f..070802103dc3 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -288,7 +288,9 @@ static const struct file_operations rtrack2_fops = {
288 .open = video_exclusive_open, 288 .open = video_exclusive_open,
289 .release = video_exclusive_release, 289 .release = video_exclusive_release,
290 .ioctl = video_ioctl2, 290 .ioctl = video_ioctl2,
291#ifdef CONFIG_COMPAT
291 .compat_ioctl = v4l_compat_ioctl32, 292 .compat_ioctl = v4l_compat_ioctl32,
293#endif
292 .llseek = no_llseek, 294 .llseek = no_llseek,
293}; 295};
294 296
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 53e114857377..66e052fd3909 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -288,7 +288,9 @@ static const struct file_operations fmi_fops = {
288 .open = video_exclusive_open, 288 .open = video_exclusive_open,
289 .release = video_exclusive_release, 289 .release = video_exclusive_release,
290 .ioctl = video_ioctl2, 290 .ioctl = video_ioctl2,
291#ifdef CONFIG_COMPAT
291 .compat_ioctl = v4l_compat_ioctl32, 292 .compat_ioctl = v4l_compat_ioctl32,
293#endif
292 .llseek = no_llseek, 294 .llseek = no_llseek,
293}; 295};
294 296
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index ebc5fbbc38bb..b0ccf7cb5952 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -29,6 +29,8 @@ static struct mutex lock;
29#include <linux/version.h> /* for KERNEL_VERSION MACRO */ 29#include <linux/version.h> /* for KERNEL_VERSION MACRO */
30#define RADIO_VERSION KERNEL_VERSION(0,0,2) 30#define RADIO_VERSION KERNEL_VERSION(0,0,2)
31 31
32#define AUD_VOL_INDEX 1
33
32static struct v4l2_queryctrl radio_qctrl[] = { 34static struct v4l2_queryctrl radio_qctrl[] = {
33 { 35 {
34 .id = V4L2_CID_AUDIO_MUTE, 36 .id = V4L2_CID_AUDIO_MUTE,
@@ -37,13 +39,14 @@ static struct v4l2_queryctrl radio_qctrl[] = {
37 .maximum = 1, 39 .maximum = 1,
38 .default_value = 1, 40 .default_value = 1,
39 .type = V4L2_CTRL_TYPE_BOOLEAN, 41 .type = V4L2_CTRL_TYPE_BOOLEAN,
40 },{ 42 },
43 [AUD_VOL_INDEX] = {
41 .id = V4L2_CID_AUDIO_VOLUME, 44 .id = V4L2_CID_AUDIO_VOLUME,
42 .name = "Volume", 45 .name = "Volume",
43 .minimum = 0, 46 .minimum = 0,
44 .maximum = 65535, 47 .maximum = 15,
45 .step = 1<<12, 48 .step = 1,
46 .default_value = 0xff, 49 .default_value = 0,
47 .type = V4L2_CTRL_TYPE_INTEGER, 50 .type = V4L2_CTRL_TYPE_INTEGER,
48 } 51 }
49}; 52};
@@ -61,7 +64,7 @@ static struct v4l2_queryctrl radio_qctrl[] = {
61struct fmr2_device 64struct fmr2_device
62{ 65{
63 int port; 66 int port;
64 int curvol; /* 0-65535, if not volume 0 or 65535 */ 67 int curvol; /* 0-15 */
65 int mute; 68 int mute;
66 int stereo; /* card is producing stereo audio */ 69 int stereo; /* card is producing stereo audio */
67 unsigned long curfreq; /* freq in kHz */ 70 unsigned long curfreq; /* freq in kHz */
@@ -176,51 +179,35 @@ static int fmr2_setfreq(struct fmr2_device *dev)
176/* !!! not tested, in my card this does't work !!! */ 179/* !!! not tested, in my card this does't work !!! */
177static int fmr2_setvolume(struct fmr2_device *dev) 180static int fmr2_setvolume(struct fmr2_device *dev)
178{ 181{
179 int i,a,n, port = dev->port; 182 int vol[16] = { 0x021, 0x084, 0x090, 0x104,
183 0x110, 0x204, 0x210, 0x402,
184 0x404, 0x408, 0x410, 0x801,
185 0x802, 0x804, 0x808, 0x810 };
186 int i, a, port = dev->port;
187 int n = vol[dev->curvol & 0x0f];
180 188
181 if (dev->card_type != 11) return 1; 189 if (dev->card_type != 11)
190 return 1;
182 191
183 switch( (dev->curvol+(1<<11)) >> 12 ) 192 for (i = 12; --i >= 0; ) {
184 {
185 case 0: case 1: n = 0x21; break;
186 case 2: n = 0x84; break;
187 case 3: n = 0x90; break;
188 case 4: n = 0x104; break;
189 case 5: n = 0x110; break;
190 case 6: n = 0x204; break;
191 case 7: n = 0x210; break;
192 case 8: n = 0x402; break;
193 case 9: n = 0x404; break;
194 default:
195 case 10: n = 0x408; break;
196 case 11: n = 0x410; break;
197 case 12: n = 0x801; break;
198 case 13: n = 0x802; break;
199 case 14: n = 0x804; break;
200 case 15: n = 0x808; break;
201 case 16: n = 0x810; break;
202 }
203 for(i=12;--i>=0;)
204 {
205 a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */ 193 a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */
206 outb(a|4, port); 194 outb(a | 4, port);
207 wait(4,port); 195 wait(4, port);
208 outb(a|0x24, port); 196 outb(a | 0x24, port);
209 wait(4,port); 197 wait(4, port);
210 outb(a|4, port); 198 outb(a | 4, port);
211 wait(4,port); 199 wait(4, port);
212 } 200 }
213 for(i=6;--i>=0;) 201 for (i = 6; --i >= 0; ) {
214 {
215 a = ((0x18 >> i) & 1) << 6; 202 a = ((0x18 >> i) & 1) << 6;
216 outb(a|4, port); 203 outb(a | 4, port);
217 wait(4,port); 204 wait(4,port);
218 outb(a|0x24, port); 205 outb(a | 0x24, port);
219 wait(4,port); 206 wait(4,port);
220 outb(a|4, port); 207 outb(a|4, port);
221 wait(4,port); 208 wait(4,port);
222 } 209 }
223 wait(4,port); 210 wait(4, port);
224 outb(0x14, port); 211 outb(0x14, port);
225 212
226 return 0; 213 return 0;
@@ -312,16 +299,10 @@ static int vidioc_queryctrl(struct file *file, void *priv,
312 struct v4l2_queryctrl *qc) 299 struct v4l2_queryctrl *qc)
313{ 300{
314 int i; 301 int i;
315 struct video_device *dev = video_devdata(file);
316 struct fmr2_device *fmr2 = dev->priv;
317 302
318 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { 303 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
319 if ((fmr2->card_type != 11)
320 && V4L2_CID_AUDIO_VOLUME)
321 radio_qctrl[i].step = 65535;
322 if (qc->id && qc->id == radio_qctrl[i].id) { 304 if (qc->id && qc->id == radio_qctrl[i].id) {
323 memcpy(qc, &(radio_qctrl[i]), 305 memcpy(qc, &radio_qctrl[i], sizeof(*qc));
324 sizeof(*qc));
325 return 0; 306 return 0;
326 } 307 }
327 } 308 }
@@ -354,24 +335,13 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
354 switch (ctrl->id) { 335 switch (ctrl->id) {
355 case V4L2_CID_AUDIO_MUTE: 336 case V4L2_CID_AUDIO_MUTE:
356 fmr2->mute = ctrl->value; 337 fmr2->mute = ctrl->value;
357 if (fmr2->card_type != 11) {
358 if (!fmr2->mute)
359 fmr2->curvol = 65535;
360 else
361 fmr2->curvol = 0;
362 }
363 break; 338 break;
364 case V4L2_CID_AUDIO_VOLUME: 339 case V4L2_CID_AUDIO_VOLUME:
365 fmr2->curvol = ctrl->value; 340 if (ctrl->value > radio_qctrl[AUD_VOL_INDEX].maximum)
366 if (fmr2->card_type != 11) { 341 fmr2->curvol = radio_qctrl[AUD_VOL_INDEX].maximum;
367 if (fmr2->curvol) { 342 else
368 fmr2->curvol = 65535; 343 fmr2->curvol = ctrl->value;
369 fmr2->mute = 0; 344
370 } else {
371 fmr2->curvol = 0;
372 fmr2->mute = 1;
373 }
374 }
375 break; 345 break;
376 default: 346 default:
377 return -EINVAL; 347 return -EINVAL;
@@ -387,6 +357,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
387 mutex_lock(&lock); 357 mutex_lock(&lock);
388 if (fmr2->curvol && !fmr2->mute) { 358 if (fmr2->curvol && !fmr2->mute) {
389 fmr2_setvolume(fmr2); 359 fmr2_setvolume(fmr2);
360 /* Set frequency and unmute card */
390 fmr2_setfreq(fmr2); 361 fmr2_setfreq(fmr2);
391 } else 362 } else
392 fmr2_mute(fmr2->port); 363 fmr2_mute(fmr2->port);
@@ -433,7 +404,9 @@ static const struct file_operations fmr2_fops = {
433 .open = video_exclusive_open, 404 .open = video_exclusive_open,
434 .release = video_exclusive_release, 405 .release = video_exclusive_release,
435 .ioctl = video_ioctl2, 406 .ioctl = video_ioctl2,
407#ifdef CONFIG_COMPAT
436 .compat_ioctl = v4l_compat_ioctl32, 408 .compat_ioctl = v4l_compat_ioctl32,
409#endif
437 .llseek = no_llseek, 410 .llseek = no_llseek,
438}; 411};
439 412
@@ -487,6 +460,11 @@ static int __init fmr2_init(void)
487 fmr2_product_info(&fmr2_unit); 460 fmr2_product_info(&fmr2_unit);
488 mutex_unlock(&lock); 461 mutex_unlock(&lock);
489 debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); 462 debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type));
463
464 /* Only card_type == 11 implements volume */
465 if (fmr2_unit.card_type != 11)
466 radio_qctrl[AUD_VOL_INDEX].maximum = 1;
467
490 return 0; 468 return 0;
491} 469}
492 470
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index 649f14d2c013..77354ca6e8e9 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -85,6 +85,7 @@
85 * Oliver Neukum <oliver@neukum.org> 85 * Oliver Neukum <oliver@neukum.org>
86 * Version 1.0.7 86 * Version 1.0.7
87 * - usb autosuspend support 87 * - usb autosuspend support
88 * - unplugging fixed
88 * 89 *
89 * ToDo: 90 * ToDo:
90 * - add seeking support 91 * - add seeking support
@@ -97,10 +98,10 @@
97/* driver definitions */ 98/* driver definitions */
98#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" 99#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
99#define DRIVER_NAME "radio-si470x" 100#define DRIVER_NAME "radio-si470x"
100#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 6) 101#define DRIVER_KERNEL_VERSION KERNEL_VERSION(1, 0, 7)
101#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" 102#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
102#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" 103#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
103#define DRIVER_VERSION "1.0.6" 104#define DRIVER_VERSION "1.0.7"
104 105
105 106
106/* kernel includes */ 107/* kernel includes */
@@ -424,6 +425,7 @@ struct si470x_device {
424 425
425 /* driver management */ 426 /* driver management */
426 unsigned int users; 427 unsigned int users;
428 unsigned char disconnected;
427 429
428 /* Silabs internal registers (0..15) */ 430 /* Silabs internal registers (0..15) */
429 unsigned short registers[RADIO_REGISTER_NUM]; 431 unsigned short registers[RADIO_REGISTER_NUM];
@@ -440,6 +442,12 @@ struct si470x_device {
440 442
441 443
442/* 444/*
445 * Lock to prevent kfree of data before all users have releases the device.
446 */
447static DEFINE_MUTEX(open_close_lock);
448
449
450/*
443 * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW, 451 * The frequency is set in units of 62.5 Hz when using V4L2_TUNER_CAP_LOW,
444 * 62.5 kHz otherwise. 452 * 62.5 kHz otherwise.
445 * The tuner is able to have a channel spacing of 50, 100 or 200 kHz. 453 * The tuner is able to have a channel spacing of 50, 100 or 200 kHz.
@@ -577,7 +585,7 @@ static int si470x_get_rds_registers(struct si470x_device *radio)
577 usb_rcvintpipe(radio->usbdev, 1), 585 usb_rcvintpipe(radio->usbdev, 1),
578 (void *) &buf, sizeof(buf), &size, usb_timeout); 586 (void *) &buf, sizeof(buf), &size, usb_timeout);
579 if (size != sizeof(buf)) 587 if (size != sizeof(buf))
580 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_register: " 588 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
581 "return size differs: %d != %zu\n", size, sizeof(buf)); 589 "return size differs: %d != %zu\n", size, sizeof(buf));
582 if (retval < 0) 590 if (retval < 0)
583 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: " 591 printk(KERN_WARNING DRIVER_NAME ": si470x_get_rds_registers: "
@@ -875,6 +883,8 @@ static void si470x_work(struct work_struct *work)
875 struct si470x_device *radio = container_of(work, struct si470x_device, 883 struct si470x_device *radio = container_of(work, struct si470x_device,
876 work.work); 884 work.work);
877 885
886 if (radio->disconnected)
887 return;
878 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) 888 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
879 return; 889 return;
880 890
@@ -1001,13 +1011,21 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
1001static int si470x_fops_release(struct inode *inode, struct file *file) 1011static int si470x_fops_release(struct inode *inode, struct file *file)
1002{ 1012{
1003 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1013 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1004 int retval; 1014 int retval = 0;
1005 1015
1006 if (!radio) 1016 if (!radio)
1007 return -ENODEV; 1017 return -ENODEV;
1008 1018
1019 mutex_lock(&open_close_lock);
1009 radio->users--; 1020 radio->users--;
1010 if (radio->users == 0) { 1021 if (radio->users == 0) {
1022 if (radio->disconnected) {
1023 video_unregister_device(radio->videodev);
1024 kfree(radio->buffer);
1025 kfree(radio);
1026 goto done;
1027 }
1028
1011 /* stop rds reception */ 1029 /* stop rds reception */
1012 cancel_delayed_work_sync(&radio->work); 1030 cancel_delayed_work_sync(&radio->work);
1013 1031
@@ -1016,10 +1034,11 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
1016 1034
1017 retval = si470x_stop(radio); 1035 retval = si470x_stop(radio);
1018 usb_autopm_put_interface(radio->intf); 1036 usb_autopm_put_interface(radio->intf);
1019 return retval;
1020 } 1037 }
1021 1038
1022 return 0; 1039done:
1040 mutex_unlock(&open_close_lock);
1041 return retval;
1023} 1042}
1024 1043
1025 1044
@@ -1032,7 +1051,9 @@ static const struct file_operations si470x_fops = {
1032 .read = si470x_fops_read, 1051 .read = si470x_fops_read,
1033 .poll = si470x_fops_poll, 1052 .poll = si470x_fops_poll,
1034 .ioctl = video_ioctl2, 1053 .ioctl = video_ioctl2,
1054#ifdef CONFIG_COMPAT
1035 .compat_ioctl = v4l_compat_ioctl32, 1055 .compat_ioctl = v4l_compat_ioctl32,
1056#endif
1036 .open = si470x_fops_open, 1057 .open = si470x_fops_open,
1037 .release = si470x_fops_release, 1058 .release = si470x_fops_release,
1038}; 1059};
@@ -1157,6 +1178,9 @@ static int si470x_vidioc_g_ctrl(struct file *file, void *priv,
1157{ 1178{
1158 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1179 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1159 1180
1181 if (radio->disconnected)
1182 return -EIO;
1183
1160 switch (ctrl->id) { 1184 switch (ctrl->id) {
1161 case V4L2_CID_AUDIO_VOLUME: 1185 case V4L2_CID_AUDIO_VOLUME:
1162 ctrl->value = radio->registers[SYSCONFIG2] & 1186 ctrl->value = radio->registers[SYSCONFIG2] &
@@ -1181,6 +1205,9 @@ static int si470x_vidioc_s_ctrl(struct file *file, void *priv,
1181 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1205 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1182 int retval; 1206 int retval;
1183 1207
1208 if (radio->disconnected)
1209 return -EIO;
1210
1184 switch (ctrl->id) { 1211 switch (ctrl->id) {
1185 case V4L2_CID_AUDIO_VOLUME: 1212 case V4L2_CID_AUDIO_VOLUME:
1186 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME; 1213 radio->registers[SYSCONFIG2] &= ~SYSCONFIG2_VOLUME;
@@ -1243,6 +1270,8 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
1243 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1270 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1244 int retval; 1271 int retval;
1245 1272
1273 if (radio->disconnected)
1274 return -EIO;
1246 if (tuner->index > 0) 1275 if (tuner->index > 0)
1247 return -EINVAL; 1276 return -EINVAL;
1248 1277
@@ -1299,6 +1328,8 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
1299 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1328 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1300 int retval; 1329 int retval;
1301 1330
1331 if (radio->disconnected)
1332 return -EIO;
1302 if (tuner->index > 0) 1333 if (tuner->index > 0)
1303 return -EINVAL; 1334 return -EINVAL;
1304 1335
@@ -1324,6 +1355,9 @@ static int si470x_vidioc_g_frequency(struct file *file, void *priv,
1324{ 1355{
1325 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1356 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1326 1357
1358 if (radio->disconnected)
1359 return -EIO;
1360
1327 freq->type = V4L2_TUNER_RADIO; 1361 freq->type = V4L2_TUNER_RADIO;
1328 freq->frequency = si470x_get_freq(radio); 1362 freq->frequency = si470x_get_freq(radio);
1329 1363
@@ -1340,6 +1374,8 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
1340 struct si470x_device *radio = video_get_drvdata(video_devdata(file)); 1374 struct si470x_device *radio = video_get_drvdata(video_devdata(file));
1341 int retval; 1375 int retval;
1342 1376
1377 if (radio->disconnected)
1378 return -EIO;
1343 if (freq->type != V4L2_TUNER_RADIO) 1379 if (freq->type != V4L2_TUNER_RADIO)
1344 return -EINVAL; 1380 return -EINVAL;
1345 1381
@@ -1510,11 +1546,16 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
1510{ 1546{
1511 struct si470x_device *radio = usb_get_intfdata(intf); 1547 struct si470x_device *radio = usb_get_intfdata(intf);
1512 1548
1549 mutex_lock(&open_close_lock);
1550 radio->disconnected = 1;
1513 cancel_delayed_work_sync(&radio->work); 1551 cancel_delayed_work_sync(&radio->work);
1514 usb_set_intfdata(intf, NULL); 1552 usb_set_intfdata(intf, NULL);
1515 video_unregister_device(radio->videodev); 1553 if (radio->users == 0) {
1516 kfree(radio->buffer); 1554 video_unregister_device(radio->videodev);
1517 kfree(radio); 1555 kfree(radio->buffer);
1556 kfree(radio);
1557 }
1558 mutex_unlock(&open_close_lock);
1518} 1559}
1519 1560
1520 1561
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index 535ffe8c8102..acc32080e9bd 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -360,7 +360,9 @@ static const struct file_operations terratec_fops = {
360 .open = video_exclusive_open, 360 .open = video_exclusive_open,
361 .release = video_exclusive_release, 361 .release = video_exclusive_release,
362 .ioctl = video_ioctl2, 362 .ioctl = video_ioctl2,
363#ifdef CONFIG_COMPAT
363 .compat_ioctl = v4l_compat_ioctl32, 364 .compat_ioctl = v4l_compat_ioctl32,
365#endif
364 .llseek = no_llseek, 366 .llseek = no_llseek,
365}; 367};
366 368
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index c11981fed827..4ebdfbadeb9c 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -340,7 +340,9 @@ static const struct file_operations trust_fops = {
340 .open = video_exclusive_open, 340 .open = video_exclusive_open,
341 .release = video_exclusive_release, 341 .release = video_exclusive_release,
342 .ioctl = video_ioctl2, 342 .ioctl = video_ioctl2,
343#ifdef CONFIG_COMPAT
343 .compat_ioctl = v4l_compat_ioctl32, 344 .compat_ioctl = v4l_compat_ioctl32,
345#endif
344 .llseek = no_llseek, 346 .llseek = no_llseek,
345}; 347};
346 348
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index 1366326474e5..18f2abd7e255 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -35,6 +35,7 @@
35#include <linux/init.h> /* Initdata */ 35#include <linux/init.h> /* Initdata */
36#include <linux/ioport.h> /* request_region */ 36#include <linux/ioport.h> /* request_region */
37#include <linux/proc_fs.h> /* radio card status report */ 37#include <linux/proc_fs.h> /* radio card status report */
38#include <linux/seq_file.h>
38#include <asm/io.h> /* outb, outb_p */ 39#include <asm/io.h> /* outb, outb_p */
39#include <asm/uaccess.h> /* copy to/from user */ 40#include <asm/uaccess.h> /* copy to/from user */
40#include <linux/videodev2.h> /* kernel radio structs */ 41#include <linux/videodev2.h> /* kernel radio structs */
@@ -93,9 +94,6 @@ static int typhoon_setfreq(struct typhoon_device *dev, unsigned long frequency);
93static void typhoon_mute(struct typhoon_device *dev); 94static void typhoon_mute(struct typhoon_device *dev);
94static void typhoon_unmute(struct typhoon_device *dev); 95static void typhoon_unmute(struct typhoon_device *dev);
95static int typhoon_setvol(struct typhoon_device *dev, int vol); 96static int typhoon_setvol(struct typhoon_device *dev, int vol);
96#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
97static int typhoon_get_info(char *buf, char **start, off_t offset, int len);
98#endif
99 97
100static void typhoon_setvol_generic(struct typhoon_device *dev, int vol) 98static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
101{ 99{
@@ -340,7 +338,9 @@ static const struct file_operations typhoon_fops = {
340 .open = video_exclusive_open, 338 .open = video_exclusive_open,
341 .release = video_exclusive_release, 339 .release = video_exclusive_release,
342 .ioctl = video_ioctl2, 340 .ioctl = video_ioctl2,
341#ifdef CONFIG_COMPAT
343 .compat_ioctl = v4l_compat_ioctl32, 342 .compat_ioctl = v4l_compat_ioctl32,
343#endif
344 .llseek = no_llseek, 344 .llseek = no_llseek,
345}; 345};
346 346
@@ -366,30 +366,39 @@ static struct video_device typhoon_radio =
366 366
367#ifdef CONFIG_RADIO_TYPHOON_PROC_FS 367#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
368 368
369static int typhoon_get_info(char *buf, char **start, off_t offset, int len) 369static int typhoon_proc_show(struct seq_file *m, void *v)
370{ 370{
371 char *out = buf;
372
373 #ifdef MODULE 371 #ifdef MODULE
374 #define MODULEPROCSTRING "Driver loaded as a module" 372 #define MODULEPROCSTRING "Driver loaded as a module"
375 #else 373 #else
376 #define MODULEPROCSTRING "Driver compiled into kernel" 374 #define MODULEPROCSTRING "Driver compiled into kernel"
377 #endif 375 #endif
378 376
379 /* output must be kept under PAGE_SIZE */ 377 seq_puts(m, BANNER);
380 out += sprintf(out, BANNER); 378 seq_puts(m, "Load type: " MODULEPROCSTRING "\n\n");
381 out += sprintf(out, "Load type: " MODULEPROCSTRING "\n\n"); 379 seq_printf(m, "frequency = %lu kHz\n",
382 out += sprintf(out, "frequency = %lu kHz\n",
383 typhoon_unit.curfreq >> 4); 380 typhoon_unit.curfreq >> 4);
384 out += sprintf(out, "volume = %d\n", typhoon_unit.curvol); 381 seq_printf(m, "volume = %d\n", typhoon_unit.curvol);
385 out += sprintf(out, "mute = %s\n", typhoon_unit.muted ? 382 seq_printf(m, "mute = %s\n", typhoon_unit.muted ?
386 "on" : "off"); 383 "on" : "off");
387 out += sprintf(out, "iobase = 0x%x\n", typhoon_unit.iobase); 384 seq_printf(m, "iobase = 0x%x\n", typhoon_unit.iobase);
388 out += sprintf(out, "mute frequency = %lu kHz\n", 385 seq_printf(m, "mute frequency = %lu kHz\n",
389 typhoon_unit.mutefreq >> 4); 386 typhoon_unit.mutefreq >> 4);
390 return out - buf; 387 return 0;
391} 388}
392 389
390static int typhoon_proc_open(struct inode *inode, struct file *file)
391{
392 return single_open(file, typhoon_proc_show, NULL);
393}
394
395static const struct file_operations typhoon_proc_fops = {
396 .owner = THIS_MODULE,
397 .open = typhoon_proc_open,
398 .read = seq_read,
399 .llseek = seq_lseek,
400 .release = single_release,
401};
393#endif /* CONFIG_RADIO_TYPHOON_PROC_FS */ 402#endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
394 403
395MODULE_AUTHOR("Dr. Henrik Seidel"); 404MODULE_AUTHOR("Dr. Henrik Seidel");
@@ -404,7 +413,7 @@ MODULE_PARM_DESC(io, "I/O address of the Typhoon card (0x316 or 0x336)");
404module_param(radio_nr, int, 0); 413module_param(radio_nr, int, 0);
405 414
406#ifdef MODULE 415#ifdef MODULE
407static unsigned long mutefreq = 0; 416static unsigned long mutefreq;
408module_param(mutefreq, ulong, 0); 417module_param(mutefreq, ulong, 0);
409MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)"); 418MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
410#endif 419#endif
@@ -450,8 +459,7 @@ static int __init typhoon_init(void)
450 typhoon_mute(&typhoon_unit); 459 typhoon_mute(&typhoon_unit);
451 460
452#ifdef CONFIG_RADIO_TYPHOON_PROC_FS 461#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
453 if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL, 462 if (!proc_create("driver/radio-typhoon", 0, NULL, &typhoon_proc_fops))
454 typhoon_get_info))
455 printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n"); 463 printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
456#endif 464#endif
457 465
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 203f4373eeb8..43773c56c62f 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -401,7 +401,9 @@ static const struct file_operations zoltrix_fops =
401 .open = video_exclusive_open, 401 .open = video_exclusive_open,
402 .release = video_exclusive_release, 402 .release = video_exclusive_release,
403 .ioctl = video_ioctl2, 403 .ioctl = video_ioctl2,
404#ifdef CONFIG_COMPAT
404 .compat_ioctl = v4l_compat_ioctl32, 405 .compat_ioctl = v4l_compat_ioctl32,
406#endif
405 .llseek = no_llseek, 407 .llseek = no_llseek,
406}; 408};
407 409