diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-08-08 08:10:02 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-09-26 10:53:14 -0400 |
commit | acda0e71857c8ec4e5348d08b53a52d35b92e6aa (patch) | |
tree | 1e54fff32a3220be7cbd832d574410c31d5427d8 /drivers | |
parent | fa38ad6592558660086e8ed4b12e5fdf90e78f90 (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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/radio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/radio/radio-sf16fmr2.c | 222 |
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 | ||
226 | config RADIO_SF16FMR2 | 226 | config 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 | |||
29 | static 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 | |||
25 | static struct mutex lock; | 48 | static 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); |