diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-30 12:39:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-30 12:39:15 -0400 |
commit | 5ffd1a6aaacc25be8cd0770a51ec6d46add3a276 (patch) | |
tree | 5b076c44f8b7ff88dba9a554d7748c6f083c9071 /drivers/media/radio/radio-sf16fmr2.c | |
parent | 0cd43f83d381c4246a08cd775834833d6fd64805 (diff) | |
parent | 8dd86eebc5315910ebfd9f30f1674254308be4b3 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
* master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (180 commits)
V4L/DVB (4641): Trivial: use lowercase letters in hex subsystem ids
V4L/DVB (4639): Cx88: add autodetection for alternate revision of Leadtek PVR
V4L/DVB (4638): Basic DVB-T and analog TV support for the HVR1300.
V4L/DVB (4637): Add a default method for VIDIOC_G_PARM
V4L/DVB (4635): Extend bttv and saa7134 to check for both AGP and PCI PCI failure case
V4L/DVB (4634): Zr36120: implement pcipci checks
V4L/DVB (4632): Zoran: Implement pcipci failure check
V4L/DVB (4631): Av7110: remove V4L2_CAP_VBI_CAPTURE flag
V4L/DVB (4630): Av7110: FW_LOADER depemdency fixed
V4L/DVB (4629): Saa7134: add card support for Proteus Pro 2309
V4L/DVB (4628): Fix VIDIOC_ENUMSTD ioctl in videodev.c
V4L/DVB (4627): Vivi crashes with mplayer
V4L/DVB (4626): On saa7111/7113, LUMA_CTRL need a different value
V4L/DVB (4624): Tvaudio: Replaced kernel_thread() with kthread_run()
V4L/DVB (4622): Copy-paste bug in videodev.c
V4L/DVB (4620): Fix AGC configuration for MOD3000P-based boards
V4L/DVB (4619): Fixes some I2C dependencies on V4L devices
V4L/DVB (4617): Problem with dibusb-mb.c USB IDs
V4L/DVB (4616): [PATCH] Nebula DigiTV USB RC support
V4L/DVB (4614): Export symbol saa7134_tvaudio_setmute from saa7134 for saa7134-alsa
...
Diffstat (limited to 'drivers/media/radio/radio-sf16fmr2.c')
-rw-r--r-- | drivers/media/radio/radio-sf16fmr2.c | 223 |
1 files changed, 140 insertions, 83 deletions
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 3483b2c7bc9d..4444dce864a9 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,12 +20,34 @@ | |||
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 | ||
25 | static struct mutex lock; | 27 | static struct mutex lock; |
26 | 28 | ||
29 | #include <linux/version.h> /* for KERNEL_VERSION MACRO */ | ||
30 | #define RADIO_VERSION KERNEL_VERSION(0,0,2) | ||
31 | |||
32 | static struct v4l2_queryctrl radio_qctrl[] = { | ||
33 | { | ||
34 | .id = V4L2_CID_AUDIO_MUTE, | ||
35 | .name = "Mute", | ||
36 | .minimum = 0, | ||
37 | .maximum = 1, | ||
38 | .default_value = 1, | ||
39 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
40 | },{ | ||
41 | .id = V4L2_CID_AUDIO_VOLUME, | ||
42 | .name = "Volume", | ||
43 | .minimum = 0, | ||
44 | .maximum = 65535, | ||
45 | .step = 1<<12, | ||
46 | .default_value = 0xff, | ||
47 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
48 | } | ||
49 | }; | ||
50 | |||
27 | #undef DEBUG | 51 | #undef DEBUG |
28 | //#define DEBUG 1 | 52 | //#define DEBUG 1 |
29 | 53 | ||
@@ -214,63 +238,65 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file, | |||
214 | 238 | ||
215 | switch(cmd) | 239 | switch(cmd) |
216 | { | 240 | { |
217 | case VIDIOCGCAP: | 241 | case VIDIOC_QUERYCAP: |
218 | { | 242 | { |
219 | struct video_capability *v = arg; | 243 | struct v4l2_capability *v = arg; |
220 | memset(v,0,sizeof(*v)); | 244 | memset(v,0,sizeof(*v)); |
221 | strcpy(v->name, "SF16-FMR2 radio"); | 245 | strlcpy(v->driver, "radio-sf16fmr2", sizeof (v->driver)); |
222 | v->type=VID_TYPE_TUNER; | 246 | strlcpy(v->card, "SF16-FMR2 radio", sizeof (v->card)); |
223 | v->channels=1; | 247 | sprintf(v->bus_info,"ISA"); |
224 | v->audios=1; | 248 | v->version = RADIO_VERSION; |
249 | v->capabilities = V4L2_CAP_TUNER; | ||
250 | |||
225 | return 0; | 251 | return 0; |
226 | } | 252 | } |
227 | case VIDIOCGTUNER: | 253 | case VIDIOC_G_TUNER: |
228 | { | 254 | { |
229 | struct video_tuner *v = arg; | 255 | struct v4l2_tuner *v = arg; |
230 | int mult; | 256 | int mult; |
231 | 257 | ||
232 | if(v->tuner) /* Only 1 tuner */ | 258 | if (v->index > 0) |
233 | return -EINVAL; | 259 | return -EINVAL; |
260 | |||
261 | memset(v,0,sizeof(*v)); | ||
234 | strcpy(v->name, "FM"); | 262 | strcpy(v->name, "FM"); |
235 | mult = (fmr2->flags & VIDEO_TUNER_LOW) ? 1 : 1000; | 263 | v->type = V4L2_TUNER_RADIO; |
264 | |||
265 | mult = (fmr2->flags & V4L2_TUNER_CAP_LOW) ? 1 : 1000; | ||
236 | v->rangelow = RSF16_MINFREQ/mult; | 266 | v->rangelow = RSF16_MINFREQ/mult; |
237 | v->rangehigh = RSF16_MAXFREQ/mult; | 267 | v->rangehigh = RSF16_MAXFREQ/mult; |
238 | v->flags = fmr2->flags | VIDEO_AUDIO_MUTABLE; | 268 | v->rxsubchans =V4L2_TUNER_SUB_MONO | V4L2_TUNER_MODE_STEREO; |
239 | if (fmr2->mute) | 269 | v->capability=fmr2->flags&V4L2_TUNER_CAP_LOW; |
240 | v->flags |= VIDEO_AUDIO_MUTE; | 270 | |
241 | v->mode=VIDEO_MODE_AUTO; | 271 | v->audmode = fmr2->stereo ? V4L2_TUNER_MODE_STEREO: |
272 | V4L2_TUNER_MODE_MONO; | ||
242 | mutex_lock(&lock); | 273 | mutex_lock(&lock); |
243 | v->signal = fmr2_getsigstr(fmr2); | 274 | v->signal = fmr2_getsigstr(fmr2); |
244 | mutex_unlock(&lock); | 275 | mutex_unlock(&lock); |
276 | |||
245 | return 0; | 277 | return 0; |
246 | } | 278 | } |
247 | case VIDIOCSTUNER: | 279 | case VIDIOC_S_TUNER: |
248 | { | 280 | { |
249 | struct video_tuner *v = arg; | 281 | struct v4l2_tuner *v = arg; |
250 | if (v->tuner!=0) | 282 | |
283 | if (v->index > 0) | ||
251 | return -EINVAL; | 284 | return -EINVAL; |
252 | fmr2->flags = v->flags & VIDEO_TUNER_LOW; | 285 | |
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; | 286 | return 0; |
262 | } | 287 | } |
263 | case VIDIOCSFREQ: | 288 | case VIDIOC_S_FREQUENCY: |
264 | { | 289 | { |
265 | unsigned long *freq = arg; | 290 | struct v4l2_frequency *f = arg; |
266 | if (!(fmr2->flags & VIDEO_TUNER_LOW)) | 291 | |
267 | *freq *= 1000; | 292 | if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) |
268 | if ( *freq < RSF16_MINFREQ || *freq > RSF16_MAXFREQ ) | 293 | f->frequency *= 1000; |
294 | if (f->frequency < RSF16_MINFREQ || | ||
295 | f->frequency > RSF16_MAXFREQ ) | ||
269 | return -EINVAL; | 296 | return -EINVAL; |
270 | /* rounding in steps of 200 to match th freq | 297 | /*rounding in steps of 200 to match th freq |
271 | * that will be used | 298 | that will be used */ |
272 | */ | 299 | fmr2->curfreq = (f->frequency/200)*200; |
273 | fmr2->curfreq = (*freq/200)*200; | ||
274 | 300 | ||
275 | /* set card freq (if not muted) */ | 301 | /* set card freq (if not muted) */ |
276 | if (fmr2->curvol && !fmr2->mute) | 302 | if (fmr2->curvol && !fmr2->mute) |
@@ -279,40 +305,81 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file, | |||
279 | fmr2_setfreq(fmr2); | 305 | fmr2_setfreq(fmr2); |
280 | mutex_unlock(&lock); | 306 | mutex_unlock(&lock); |
281 | } | 307 | } |
308 | |||
282 | return 0; | 309 | return 0; |
283 | } | 310 | } |
284 | case VIDIOCGAUDIO: | 311 | case VIDIOC_G_FREQUENCY: |
285 | { | 312 | { |
286 | struct video_audio *v = arg; | 313 | struct v4l2_frequency *f = arg; |
287 | memset(v,0,sizeof(*v)); | 314 | |
288 | /* !!! do not return VIDEO_AUDIO_MUTE */ | 315 | f->type = V4L2_TUNER_RADIO; |
289 | v->flags = VIDEO_AUDIO_MUTABLE; | 316 | f->frequency = fmr2->curfreq; |
290 | strcpy(v->name, "Radio"); | 317 | if (!(fmr2->flags & V4L2_TUNER_CAP_LOW)) |
291 | /* get current stereo mode */ | 318 | f->frequency /= 1000; |
292 | v->mode = fmr2->stereo ? VIDEO_SOUND_STEREO: VIDEO_SOUND_MONO; | 319 | |
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; | 320 | return 0; |
302 | } | 321 | } |
303 | case VIDIOCSAUDIO: | 322 | case VIDIOC_QUERYCTRL: |
304 | { | 323 | { |
305 | struct video_audio *v = arg; | 324 | struct v4l2_queryctrl *qc = arg; |
306 | if(v->audio) | 325 | int i; |
307 | return -EINVAL; | 326 | |
308 | debug_print((KERN_DEBUG "Set flags %d vol %d\n", v->flags, v->volume)); | 327 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { |
309 | /* set volume */ | 328 | if ((fmr2->card_type != 11) |
310 | if (v->flags & VIDEO_AUDIO_VOLUME) | 329 | && V4L2_CID_AUDIO_VOLUME) |
311 | fmr2->curvol = v->volume; /* !!! set with precision */ | 330 | radio_qctrl[i].step=65535; |
312 | if (fmr2->card_type != 11) fmr2->curvol = 65535; | 331 | if (qc->id && qc->id == radio_qctrl[i].id) { |
313 | fmr2->mute = 0; | 332 | memcpy(qc, &(radio_qctrl[i]), |
314 | if (v->flags & VIDEO_AUDIO_MUTE) | 333 | sizeof(*qc)); |
315 | fmr2->mute = 1; | 334 | return (0); |
335 | } | ||
336 | } | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | case VIDIOC_G_CTRL: | ||
340 | { | ||
341 | struct v4l2_control *ctrl= arg; | ||
342 | |||
343 | switch (ctrl->id) { | ||
344 | case V4L2_CID_AUDIO_MUTE: | ||
345 | ctrl->value=fmr2->mute; | ||
346 | return (0); | ||
347 | case V4L2_CID_AUDIO_VOLUME: | ||
348 | ctrl->value=fmr2->curvol; | ||
349 | return (0); | ||
350 | } | ||
351 | return -EINVAL; | ||
352 | } | ||
353 | case VIDIOC_S_CTRL: | ||
354 | { | ||
355 | struct v4l2_control *ctrl= arg; | ||
356 | |||
357 | switch (ctrl->id) { | ||
358 | case V4L2_CID_AUDIO_MUTE: | ||
359 | fmr2->mute=ctrl->value; | ||
360 | if (fmr2->card_type != 11) { | ||
361 | if (!fmr2->mute) { | ||
362 | fmr2->curvol = 65535; | ||
363 | } else { | ||
364 | fmr2->curvol = 0; | ||
365 | } | ||
366 | } | ||
367 | break; | ||
368 | case V4L2_CID_AUDIO_VOLUME: | ||
369 | fmr2->curvol = ctrl->value; | ||
370 | if (fmr2->card_type != 11) { | ||
371 | if (fmr2->curvol) { | ||
372 | fmr2->curvol = 65535; | ||
373 | fmr2->mute = 0; | ||
374 | } else { | ||
375 | fmr2->curvol = 0; | ||
376 | fmr2->mute = 1; | ||
377 | } | ||
378 | } | ||
379 | break; | ||
380 | default: | ||
381 | return -EINVAL; | ||
382 | } | ||
316 | #ifdef DEBUG | 383 | #ifdef DEBUG |
317 | if (fmr2->curvol && !fmr2->mute) | 384 | if (fmr2->curvol && !fmr2->mute) |
318 | printk(KERN_DEBUG "unmute\n"); | 385 | printk(KERN_DEBUG "unmute\n"); |
@@ -320,27 +387,18 @@ static int fmr2_do_ioctl(struct inode *inode, struct file *file, | |||
320 | printk(KERN_DEBUG "mute\n"); | 387 | printk(KERN_DEBUG "mute\n"); |
321 | #endif | 388 | #endif |
322 | mutex_lock(&lock); | 389 | mutex_lock(&lock); |
323 | if (fmr2->curvol && !fmr2->mute) | 390 | if (fmr2->curvol && !fmr2->mute) { |
324 | { | ||
325 | fmr2_setvolume(fmr2); | 391 | fmr2_setvolume(fmr2); |
326 | fmr2_setfreq(fmr2); | 392 | fmr2_setfreq(fmr2); |
327 | } | 393 | } else |
328 | else fmr2_mute(fmr2->port); | 394 | fmr2_mute(fmr2->port); |
329 | mutex_unlock(&lock); | 395 | mutex_unlock(&lock); |
330 | return 0; | 396 | 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 | } | 397 | } |
342 | default: | 398 | default: |
343 | return -ENOIOCTLCMD; | 399 | return v4l_compat_translate_ioctl(inode,file,cmd,arg, |
400 | fmr2_do_ioctl); | ||
401 | |||
344 | } | 402 | } |
345 | } | 403 | } |
346 | 404 | ||
@@ -366,7 +424,7 @@ static struct video_device fmr2_radio= | |||
366 | .owner = THIS_MODULE, | 424 | .owner = THIS_MODULE, |
367 | .name = "SF16FMR2 radio", | 425 | .name = "SF16FMR2 radio", |
368 | . type = VID_TYPE_TUNER, | 426 | . type = VID_TYPE_TUNER, |
369 | .hardware = VID_HARDWARE_SF16FMR2, | 427 | .hardware = 0, |
370 | .fops = &fmr2_fops, | 428 | .fops = &fmr2_fops, |
371 | }; | 429 | }; |
372 | 430 | ||
@@ -377,7 +435,7 @@ static int __init fmr2_init(void) | |||
377 | fmr2_unit.mute = 0; | 435 | fmr2_unit.mute = 0; |
378 | fmr2_unit.curfreq = 0; | 436 | fmr2_unit.curfreq = 0; |
379 | fmr2_unit.stereo = 1; | 437 | fmr2_unit.stereo = 1; |
380 | fmr2_unit.flags = VIDEO_TUNER_LOW; | 438 | fmr2_unit.flags = V4L2_TUNER_CAP_LOW; |
381 | fmr2_unit.card_type = 0; | 439 | fmr2_unit.card_type = 0; |
382 | fmr2_radio.priv = &fmr2_unit; | 440 | fmr2_radio.priv = &fmr2_unit; |
383 | 441 | ||
@@ -396,7 +454,6 @@ static int __init fmr2_init(void) | |||
396 | } | 454 | } |
397 | 455 | ||
398 | printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); | 456 | 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 */ | 457 | /* mute card - prevents noisy bootups */ |
401 | mutex_lock(&lock); | 458 | mutex_lock(&lock); |
402 | fmr2_mute(io); | 459 | fmr2_mute(io); |