aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2006-08-08 08:10:02 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-09-26 10:53:14 -0400
commitacda0e71857c8ec4e5348d08b53a52d35b92e6aa (patch)
tree1e54fff32a3220be7cbd832d574410c31d5427d8
parentfa38ad6592558660086e8ed4b12e5fdf90e78f90 (diff)
V4L/DVB (4355): V4L2 conversion: radio-sf16fmr2
Driver conversion to V4L2 API. Require some testing, since this obsolete hardware is not common those days. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/radio/Kconfig2
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c222
2 files changed, 140 insertions, 84 deletions
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 60a5bea47509..fddfd5c32233 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -225,7 +225,7 @@ config RADIO_SF16FMI
225 225
226config RADIO_SF16FMR2 226config RADIO_SF16FMR2
227 tristate "SF16FMR2 Radio" 227 tristate "SF16FMR2 Radio"
228 depends on ISA && VIDEO_V4L1 228 depends on ISA && VIDEO_V4L2
229 ---help--- 229 ---help---
230 Choose Y here if you have one of these FM radio cards. 230 Choose Y here if you have one of these FM radio cards.
231 231
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 3483b2c7bc9d..3f4ee625b4c9 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -10,6 +10,8 @@
10 * For read stereo/mono you must wait 0.1 sec after set frequency and 10 * For read stereo/mono you must wait 0.1 sec after set frequency and
11 * card unmuted so I set frequency on unmute 11 * card unmuted so I set frequency on unmute
12 * Signal handling seem to work only on autoscanning (not implemented) 12 * Signal handling seem to work only on autoscanning (not implemented)
13 *
14 * Converted to V4L2 API by Mauro Carvalho Chehab <mchehab@infradead.org>
13 */ 15 */
14 16
15#include <linux/module.h> /* Modules */ 17#include <linux/module.h> /* Modules */
@@ -18,10 +20,31 @@
18#include <linux/delay.h> /* udelay */ 20#include <linux/delay.h> /* udelay */
19#include <asm/io.h> /* outb, outb_p */ 21#include <asm/io.h> /* outb, outb_p */
20#include <asm/uaccess.h> /* copy to/from user */ 22#include <asm/uaccess.h> /* copy to/from user */
21#include <linux/videodev.h> /* kernel radio structs */ 23#include <linux/videodev2.h> /* kernel radio structs */
22#include <media/v4l2-common.h> 24#include <media/v4l2-common.h>
23#include <linux/mutex.h> 25#include <linux/mutex.h>
24 26
27#define RADIO_VERSION KERNEL_VERSION(0,0,2)
28
29static struct v4l2_queryctrl radio_qctrl[] = {
30 {
31 .id = V4L2_CID_AUDIO_MUTE,
32 .name = "Mute",
33 .minimum = 0,
34 .maximum = 1,
35 .default_value = 1,
36 .type = V4L2_CTRL_TYPE_BOOLEAN,
37 },{
38 .id = V4L2_CID_AUDIO_VOLUME,
39 .name = "Volume",
40 .minimum = 0,
41 .maximum = 65535,
42 .step = 1<<12,
43 .default_value = 0xff,
44 .type = V4L2_CTRL_TYPE_INTEGER,
45 }
46};
47
25static struct mutex lock; 48static struct mutex lock;
26 49
27#undef DEBUG 50#undef DEBUG
@@ -214,63 +237,65 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file,
214 237
215 switch(cmd) 238 switch(cmd)
216 { 239 {
217 case VIDIOCGCAP: 240 case VIDIOC_QUERYCAP:
218 { 241 {
219 struct video_capability *v = arg; 242 struct v4l2_capability *v = arg;
220 memset(v,0,sizeof(*v)); 243 memset(v,0,sizeof(*v));
221 strcpy(v->name, "SF16-FMR2 radio"); 244 strlcpy(v->driver, "radio-sf16fmr2", sizeof (v->driver));
222 v->type=VID_TYPE_TUNER; 245 strlcpy(v->card, "SF16-FMR2 radio", sizeof (v->card));
223 v->channels=1; 246 sprintf(v->bus_info,"ISA");
224 v->audios=1; 247 v->version = RADIO_VERSION;
248 v->capabilities = V4L2_CAP_TUNER;
249
225 return 0; 250 return 0;
226 } 251 }
227 case VIDIOCGTUNER: 252 case VIDIOC_G_TUNER:
228 { 253 {
229 struct video_tuner *v = arg; 254 struct v4l2_tuner *v = arg;
230 int mult; 255 int mult;
231 256
232 if(v->tuner) /* Only 1 tuner */ 257 if (v->index > 0)
233 return -EINVAL; 258 return -EINVAL;
259
260 memset(v,0,sizeof(*v));
234 strcpy(v->name, "FM"); 261 strcpy(v->name, "FM");
235 mult = (fmr2->flags & VIDEO_TUNER_LOW) ? 1 : 1000; 262 v->type = V4L2_TUNER_RADIO;
263
264 mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000;
236 v->rangelow = RSF16_MINFREQ/mult; 265 v->rangelow = RSF16_MINFREQ/mult;
237 v->rangehigh = RSF16_MAXFREQ/mult; 266 v->rangehigh = RSF16_MAXFREQ/mult;
238 v->flags = fmr2->flags | VIDEO_AUDIO_MUTABLE; 267 v->rxsubchans =V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO;
239 if (fmr2->mute) 268 v->capability=fmr2->flags&V4L2_TUNER_CAP_LOW;
240 v->flags |= VIDEO_AUDIO_MUTE; 269
241 v->mode=VIDEO_MODE_AUTO; 270 v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO:
271 V4L2_TUNER_MODE_MONO;
242 mutex_lock(&lock); 272 mutex_lock(&lock);
243 v->signal = fmr2_getsigstr(fmr2); 273 v->signal = fmr2_getsigstr(fmr2);
244 mutex_unlock(&lock); 274 mutex_unlock(&lock);
275
245 return 0; 276 return 0;
246 } 277 }
247 case VIDIOCSTUNER: 278 case VIDIOC_S_TUNER:
248 { 279 {
249 struct video_tuner *v = arg; 280 struct v4l2_tuner *v = arg;
250 if (v->tuner!=0) 281
282 if (v->index > 0)
251 return -EINVAL; 283 return -EINVAL;
252 fmr2->flags = v->flags & VIDEO_TUNER_LOW; 284
253 return 0;
254 }
255 case VIDIOCGFREQ:
256 {
257 unsigned long *freq = arg;
258 *freq = fmr2->curfreq;
259 if (!(fmr2->flags & VIDEO_TUNER_LOW))
260 *freq /= 1000;
261 return 0; 285 return 0;
262 } 286 }
263 case VIDIOCSFREQ: 287 case VIDIOC_S_FREQUENCY:
264 { 288 {
265 unsigned long *freq = arg; 289 struct v4l2_frequency *f = arg;
266 if (!(fmr2->flags & VIDEO_TUNER_LOW)) 290
267 *freq *= 1000; 291 if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
268 if ( *freq < RSF16_MINFREQ || *freq > RSF16_MAXFREQ ) 292 f->frequency *= 1000;
293 if (f->frequency < RSF16_MINFREQ ||
294 f->frequency > RSF16_MAXFREQ )
269 return -EINVAL; 295 return -EINVAL;
270 /* rounding in steps of 200 to match th freq 296 /*rounding in steps of 200 to match th freq
271 * that will be used 297 that will be used */
272 */ 298 fmr2->curfreq = (f->frequency/200)*200;
273 fmr2->curfreq = (*freq/200)*200;
274 299
275 /* set card freq (if not muted) */ 300 /* set card freq (if not muted) */
276 if (fmr2->curvol && !fmr2->mute) 301 if (fmr2->curvol && !fmr2->mute)
@@ -279,40 +304,81 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file,
279 fmr2_setfreq(fmr2); 304 fmr2_setfreq(fmr2);
280 mutex_unlock(&lock); 305 mutex_unlock(&lock);
281 } 306 }
307
282 return 0; 308 return 0;
283 } 309 }
284 case VIDIOCGAUDIO: 310 case VIDIOC_G_FREQUENCY:
285 { 311 {
286 struct video_audio *v = arg; 312 struct v4l2_frequency *f = arg;
287 memset(v,0,sizeof(*v)); 313
288 /* !!! do not return VIDEO_AUDIO_MUTE */ 314 f->type = V4L2_TUNER_RADIO;
289 v->flags = VIDEO_AUDIO_MUTABLE; 315 f->frequency = fmr2->curfreq;
290 strcpy(v->name, "Radio"); 316 if (!(fmr2->flags & V4L2_TUNER_CAP_LOW))
291 /* get current stereo mode */ 317 f->frequency /= 1000;
292 v->mode = fmr2->stereo ? VIDEO_SOUND_STEREO: VIDEO_SOUND_MONO; 318
293 /* volume supported ? */
294 if (fmr2->card_type == 11)
295 {
296 v->flags |= VIDEO_AUDIO_VOLUME;
297 v->step = 1 << 12;
298 v->volume = fmr2->curvol;
299 }
300 debug_print((KERN_DEBUG "Get flags %d vol %d\n", v->flags, v->volume));
301 return 0; 319 return 0;
302 } 320 }
303 case VIDIOCSAUDIO: 321 case VIDIOC_QUERYCTRL:
304 { 322 {
305 struct video_audio *v = arg; 323 struct v4l2_queryctrl *qc = arg;
306 if(v->audio) 324 int i;
307 return -EINVAL; 325
308 debug_print((KERN_DEBUG "Set flags %d vol %d\n", v->flags, v->volume)); 326 for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
309 /* set volume */ 327 if ((fmr2->card_type != 11)
310 if (v->flags & VIDEO_AUDIO_VOLUME) 328 && V4L2_CID_AUDIO_VOLUME)
311 fmr2->curvol = v->volume; /* !!! set with precision */ 329 radio_qctrl[i].step=65535;
312 if (fmr2->card_type != 11) fmr2->curvol = 65535; 330 if (qc->id && qc->id == radio_qctrl[i].id) {
313 fmr2->mute = 0; 331 memcpy(qc, &(radio_qctrl[i]),
314 if (v->flags & VIDEO_AUDIO_MUTE) 332 sizeof(*qc));
315 fmr2->mute = 1; 333 return (0);
334 }
335 }
336 return -EINVAL;
337 }
338 case VIDIOC_G_CTRL:
339 {
340 struct v4l2_control *ctrl= arg;
341
342 switch (ctrl->id) {
343 case V4L2_CID_AUDIO_MUTE:
344 ctrl->value=fmr2->mute;
345 return (0);
346 case V4L2_CID_AUDIO_VOLUME:
347 ctrl->value=fmr2->curvol;
348 return (0);
349 }
350 return -EINVAL;
351 }
352 case VIDIOC_S_CTRL:
353 {
354 struct v4l2_control *ctrl= arg;
355
356 switch (ctrl->id) {
357 case V4L2_CID_AUDIO_MUTE:
358 fmr2->mute=ctrl->value;
359 if (fmr2->card_type != 11) {
360 if (!fmr2->mute) {
361 fmr2->curvol = 65535;
362 } else {
363 fmr2->curvol = 0;
364 }
365 }
366 break;
367 case V4L2_CID_AUDIO_VOLUME:
368 fmr2->curvol = ctrl->value;
369 if (fmr2->card_type != 11) {
370 if (fmr2->curvol) {
371 fmr2->curvol = 65535;
372 fmr2->mute = 0;
373 } else {
374 fmr2->curvol = 0;
375 fmr2->mute = 1;
376 }
377 }
378 break;
379 default:
380 return -EINVAL;
381 }
316#ifdef DEBUG 382#ifdef DEBUG
317 if (fmr2->curvol && !fmr2->mute) 383 if (fmr2->curvol && !fmr2->mute)
318 printk(KERN_DEBUG "unmute\n"); 384 printk(KERN_DEBUG "unmute\n");
@@ -320,27 +386,18 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file,
320 printk(KERN_DEBUG "mute\n"); 386 printk(KERN_DEBUG "mute\n");
321#endif 387#endif
322 mutex_lock(&lock); 388 mutex_lock(&lock);
323 if (fmr2->curvol && !fmr2->mute) 389 if (fmr2->curvol && !fmr2->mute) {
324 {
325 fmr2_setvolume(fmr2); 390 fmr2_setvolume(fmr2);
326 fmr2_setfreq(fmr2); 391 fmr2_setfreq(fmr2);
327 } 392 } else
328 else fmr2_mute(fmr2->port); 393 fmr2_mute(fmr2->port);
329 mutex_unlock(&lock); 394 mutex_unlock(&lock);
330 return 0; 395 return (0);
331 }
332 case VIDIOCGUNIT:
333 {
334 struct video_unit *v = arg;
335 v->video=VIDEO_NO_UNIT;
336 v->vbi=VIDEO_NO_UNIT;
337 v->radio=dev->minor;
338 v->audio=0; /* How do we find out this??? */
339 v->teletext=VIDEO_NO_UNIT;
340 return 0;
341 } 396 }
342 default: 397 default:
343 return -ENOIOCTLCMD; 398 return v4l_compat_translate_ioctl(inode,file,cmd,arg,
399 az_do_ioctl);
400
344 } 401 }
345} 402}
346 403
@@ -366,7 +423,7 @@ static struct video_device fmr2_radio=
366 .owner = THIS_MODULE, 423 .owner = THIS_MODULE,
367 .name = "SF16FMR2 radio", 424 .name = "SF16FMR2 radio",
368 . type = VID_TYPE_TUNER, 425 . type = VID_TYPE_TUNER,
369 .hardware = VID_HARDWARE_SF16FMR2, 426 .hardware = 0,
370 .fops = &fmr2_fops, 427 .fops = &fmr2_fops,
371}; 428};
372 429
@@ -377,7 +434,7 @@ static int __init fmr2_init(void)
377 fmr2_unit.mute = 0; 434 fmr2_unit.mute = 0;
378 fmr2_unit.curfreq = 0; 435 fmr2_unit.curfreq = 0;
379 fmr2_unit.stereo = 1; 436 fmr2_unit.stereo = 1;
380 fmr2_unit.flags = VIDEO_TUNER_LOW; 437 fmr2_unit.flags = V4L2_TUNER_CAP_LOW;
381 fmr2_unit.card_type = 0; 438 fmr2_unit.card_type = 0;
382 fmr2_radio.priv = &fmr2_unit; 439 fmr2_radio.priv = &fmr2_unit;
383 440
@@ -396,7 +453,6 @@ static int __init fmr2_init(void)
396 } 453 }
397 454
398 printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); 455 printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io);
399 debug_print((KERN_DEBUG "Mute %d Low %d\n",VIDEO_AUDIO_MUTE,VIDEO_TUNER_LOW));
400 /* mute card - prevents noisy bootups */ 456 /* mute card - prevents noisy bootups */
401 mutex_lock(&lock); 457 mutex_lock(&lock);
402 fmr2_mute(io); 458 fmr2_mute(io);