diff options
Diffstat (limited to 'drivers/media/radio/radio-cadet.c')
-rw-r--r-- | drivers/media/radio/radio-cadet.c | 297 |
1 files changed, 179 insertions, 118 deletions
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 8fbf0d8bd278..8cf2e9df5c8a 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c | |||
@@ -48,6 +48,25 @@ | |||
48 | 48 | ||
49 | #define CADET_VERSION KERNEL_VERSION(0,3,3) | 49 | #define CADET_VERSION KERNEL_VERSION(0,3,3) |
50 | 50 | ||
51 | static struct v4l2_queryctrl radio_qctrl[] = { | ||
52 | { | ||
53 | .id = V4L2_CID_AUDIO_MUTE, | ||
54 | .name = "Mute", | ||
55 | .minimum = 0, | ||
56 | .maximum = 1, | ||
57 | .default_value = 1, | ||
58 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
59 | },{ | ||
60 | .id = V4L2_CID_AUDIO_VOLUME, | ||
61 | .name = "Volume", | ||
62 | .minimum = 0, | ||
63 | .maximum = 0xff, | ||
64 | .step = 1, | ||
65 | .default_value = 0xff, | ||
66 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
67 | } | ||
68 | }; | ||
69 | |||
51 | static int io=-1; /* default to isapnp activation */ | 70 | static int io=-1; /* default to isapnp activation */ |
52 | static int radio_nr = -1; | 71 | static int radio_nr = -1; |
53 | static int users=0; | 72 | static int users=0; |
@@ -347,135 +366,165 @@ cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | |||
347 | } | 366 | } |
348 | 367 | ||
349 | 368 | ||
369 | static int vidioc_querycap(struct file *file, void *priv, | ||
370 | struct v4l2_capability *v) | ||
371 | { | ||
372 | v->capabilities = | ||
373 | V4L2_CAP_TUNER | | ||
374 | V4L2_CAP_READWRITE; | ||
375 | v->version = CADET_VERSION; | ||
376 | strcpy(v->driver, "ADS Cadet"); | ||
377 | strcpy(v->card, "ADS Cadet"); | ||
378 | return 0; | ||
379 | } | ||
350 | 380 | ||
351 | static int cadet_do_ioctl(struct inode *inode, struct file *file, | 381 | static int vidioc_g_tuner(struct file *file, void *priv, |
352 | unsigned int cmd, void *arg) | 382 | struct v4l2_tuner *v) |
353 | { | 383 | { |
354 | switch(cmd) | 384 | v->type = V4L2_TUNER_RADIO; |
355 | { | 385 | switch (v->index) { |
356 | case VIDIOC_QUERYCAP: | 386 | case 0: |
357 | { | 387 | strcpy(v->name, "FM"); |
358 | struct v4l2_capability *cap = arg; | 388 | v->capability = V4L2_TUNER_CAP_STEREO; |
359 | memset(cap,0,sizeof(*cap)); | 389 | v->rangelow = 1400; /* 87.5 MHz */ |
360 | cap->capabilities = | 390 | v->rangehigh = 1728; /* 108.0 MHz */ |
361 | V4L2_CAP_TUNER | | 391 | v->rxsubchans=cadet_getstereo(); |
362 | V4L2_CAP_READWRITE; | 392 | switch (v->rxsubchans){ |
363 | cap->version = CADET_VERSION; | 393 | case V4L2_TUNER_SUB_MONO: |
364 | strcpy(cap->driver, "ADS Cadet"); | 394 | v->audmode = V4L2_TUNER_MODE_MONO; |
365 | strcpy(cap->card, "ADS Cadet"); | 395 | break; |
366 | return 0; | 396 | case V4L2_TUNER_SUB_STEREO: |
397 | v->audmode = V4L2_TUNER_MODE_STEREO; | ||
398 | break; | ||
399 | default: ; | ||
367 | } | 400 | } |
368 | case VIDIOC_G_TUNER: | 401 | break; |
369 | { | 402 | case 1: |
370 | struct v4l2_tuner *t = arg; | 403 | strcpy(v->name, "AM"); |
371 | memset(t,0,sizeof(*t)); | 404 | v->capability = V4L2_TUNER_CAP_LOW; |
372 | t->type = V4L2_TUNER_RADIO; | 405 | v->rangelow = 8320; /* 520 kHz */ |
373 | switch (t->index) | 406 | v->rangehigh = 26400; /* 1650 kHz */ |
374 | { | 407 | v->rxsubchans = V4L2_TUNER_SUB_MONO; |
375 | case 0: strcpy(t->name, "FM"); | 408 | v->audmode = V4L2_TUNER_MODE_MONO; |
376 | t->capability = V4L2_TUNER_CAP_STEREO; | 409 | break; |
377 | t->rangelow = 1400; /* 87.5 MHz */ | 410 | default: |
378 | t->rangehigh = 1728; /* 108.0 MHz */ | 411 | return -EINVAL; |
379 | t->rxsubchans=cadet_getstereo(); | 412 | } |
380 | switch (t->rxsubchans){ | 413 | v->signal = sigstrength; /* We might need to modify scaling of this */ |
381 | case V4L2_TUNER_SUB_MONO: | 414 | return 0; |
382 | t->audmode = V4L2_TUNER_MODE_MONO; | 415 | } |
383 | break; | ||
384 | case V4L2_TUNER_SUB_STEREO: | ||
385 | t->audmode = V4L2_TUNER_MODE_STEREO; | ||
386 | break; | ||
387 | default: ; | ||
388 | } | ||
389 | break; | ||
390 | case 1: strcpy(t->name, "AM"); | ||
391 | t->capability = V4L2_TUNER_CAP_LOW; | ||
392 | t->rangelow = 8320; /* 520 kHz */ | ||
393 | t->rangehigh = 26400; /* 1650 kHz */ | ||
394 | t->rxsubchans = V4L2_TUNER_SUB_MONO; | ||
395 | t->audmode = V4L2_TUNER_MODE_MONO; | ||
396 | break; | ||
397 | default: | ||
398 | return -EINVAL; | ||
399 | } | ||
400 | 416 | ||
401 | t->signal = sigstrength; /* We might need to modify scaling of this */ | 417 | static int vidioc_s_tuner(struct file *file, void *priv, |
402 | return 0; | 418 | struct v4l2_tuner *v) |
403 | } | 419 | { |
404 | case VIDIOC_S_TUNER: | 420 | if((v->index != 0)&&(v->index != 1)) |
405 | { | 421 | return -EINVAL; |
406 | struct v4l2_tuner *t = arg; | 422 | curtuner = v->index; |
407 | if((t->index != 0)&&(t->index != 1)) | 423 | return 0; |
408 | return -EINVAL; | 424 | } |
409 | 425 | ||
410 | curtuner = t->index; | 426 | static int vidioc_g_frequency(struct file *file, void *priv, |
411 | return 0; | 427 | struct v4l2_frequency *f) |
412 | } | 428 | { |
413 | case VIDIOC_G_FREQUENCY: | 429 | f->tuner = curtuner; |
414 | { | 430 | f->type = V4L2_TUNER_RADIO; |
415 | struct v4l2_frequency *f = arg; | 431 | f->frequency = cadet_getfreq(); |
416 | memset(f,0,sizeof(*f)); | 432 | return 0; |
417 | f->tuner = curtuner; | 433 | } |
418 | f->type = V4L2_TUNER_RADIO; | 434 | |
419 | f->frequency = cadet_getfreq(); | 435 | |
420 | return 0; | 436 | static int vidioc_s_frequency(struct file *file, void *priv, |
421 | } | 437 | struct v4l2_frequency *f) |
422 | case VIDIOC_S_FREQUENCY: | 438 | { |
423 | { | 439 | if (f->type != V4L2_TUNER_RADIO) |
424 | struct v4l2_frequency *f = arg; | 440 | return -EINVAL; |
425 | if (f->type != V4L2_TUNER_RADIO){ | 441 | if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) |
426 | return -EINVAL; | 442 | return -EINVAL; |
427 | } | 443 | if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) |
428 | if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) { | 444 | return -EINVAL; |
429 | return -EINVAL; | 445 | cadet_setfreq(f->frequency); |
430 | } | 446 | return 0; |
431 | if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) { | 447 | } |
432 | return -EINVAL; | 448 | |
433 | } | 449 | static int vidioc_queryctrl(struct file *file, void *priv, |
434 | cadet_setfreq(f->frequency); | 450 | struct v4l2_queryctrl *qc) |
435 | return 0; | 451 | { |
436 | } | 452 | int i; |
437 | case VIDIOC_G_CTRL: | 453 | |
438 | { | 454 | for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { |
439 | struct v4l2_control *c = arg; | 455 | if (qc->id && qc->id == radio_qctrl[i].id) { |
440 | switch (c->id){ | 456 | memcpy(qc, &(radio_qctrl[i]), |
441 | case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ | 457 | sizeof(*qc)); |
442 | c->value = (cadet_getvol() == 0); | ||
443 | break; | ||
444 | case V4L2_CID_AUDIO_VOLUME: | ||
445 | c->value = cadet_getvol(); | ||
446 | break; | ||
447 | default: | ||
448 | return -EINVAL; | ||
449 | } | ||
450 | return 0; | ||
451 | } | ||
452 | case VIDIOC_S_CTRL: | ||
453 | { | ||
454 | struct v4l2_control *c = arg; | ||
455 | switch (c->id){ | ||
456 | case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ | ||
457 | if (c->value) cadet_setvol(0); | ||
458 | else cadet_setvol(0xffff); | ||
459 | break; | ||
460 | case V4L2_CID_AUDIO_VOLUME: | ||
461 | cadet_setvol(c->value); | ||
462 | break; | ||
463 | default: | ||
464 | return -EINVAL; | ||
465 | } | ||
466 | return 0; | 458 | return 0; |
467 | } | 459 | } |
460 | } | ||
461 | return -EINVAL; | ||
462 | } | ||
468 | 463 | ||
469 | default: | 464 | static int vidioc_g_ctrl(struct file *file, void *priv, |
470 | return -ENOIOCTLCMD; | 465 | struct v4l2_control *ctrl) |
466 | { | ||
467 | switch (ctrl->id){ | ||
468 | case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ | ||
469 | ctrl->value = (cadet_getvol() == 0); | ||
470 | break; | ||
471 | case V4L2_CID_AUDIO_VOLUME: | ||
472 | ctrl->value = cadet_getvol(); | ||
473 | break; | ||
474 | default: | ||
475 | return -EINVAL; | ||
471 | } | 476 | } |
477 | return 0; | ||
472 | } | 478 | } |
473 | 479 | ||
474 | static int | 480 | static int vidioc_s_ctrl(struct file *file, void *priv, |
475 | cadet_ioctl(struct inode *inode, struct file *file, | 481 | struct v4l2_control *ctrl) |
476 | unsigned int cmd, unsigned long arg) | ||
477 | { | 482 | { |
478 | return video_usercopy(inode, file, cmd, arg, cadet_do_ioctl); | 483 | switch (ctrl->id){ |
484 | case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */ | ||
485 | if (ctrl->value) | ||
486 | cadet_setvol(0); | ||
487 | else | ||
488 | cadet_setvol(0xffff); | ||
489 | break; | ||
490 | case V4L2_CID_AUDIO_VOLUME: | ||
491 | cadet_setvol(ctrl->value); | ||
492 | break; | ||
493 | default: | ||
494 | return -EINVAL; | ||
495 | } | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static int vidioc_g_audio(struct file *file, void *priv, | ||
500 | struct v4l2_audio *a) | ||
501 | { | ||
502 | if (a->index > 1) | ||
503 | return -EINVAL; | ||
504 | strcpy(a->name, "Radio"); | ||
505 | a->capability = V4L2_AUDCAP_STEREO; | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i) | ||
510 | { | ||
511 | *i = 0; | ||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | static int vidioc_s_input(struct file *filp, void *priv, unsigned int i) | ||
516 | { | ||
517 | if (i != 0) | ||
518 | return -EINVAL; | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int vidioc_s_audio(struct file *file, void *priv, | ||
523 | struct v4l2_audio *a) | ||
524 | { | ||
525 | if (a->index != 0) | ||
526 | return -EINVAL; | ||
527 | return 0; | ||
479 | } | 528 | } |
480 | 529 | ||
481 | static int | 530 | static int |
@@ -512,7 +561,7 @@ static const struct file_operations cadet_fops = { | |||
512 | .open = cadet_open, | 561 | .open = cadet_open, |
513 | .release = cadet_release, | 562 | .release = cadet_release, |
514 | .read = cadet_read, | 563 | .read = cadet_read, |
515 | .ioctl = cadet_ioctl, | 564 | .ioctl = video_ioctl2, |
516 | .poll = cadet_poll, | 565 | .poll = cadet_poll, |
517 | .compat_ioctl = v4l_compat_ioctl32, | 566 | .compat_ioctl = v4l_compat_ioctl32, |
518 | .llseek = no_llseek, | 567 | .llseek = no_llseek, |
@@ -524,6 +573,18 @@ static struct video_device cadet_radio= | |||
524 | .name = "Cadet radio", | 573 | .name = "Cadet radio", |
525 | .type = VID_TYPE_TUNER, | 574 | .type = VID_TYPE_TUNER, |
526 | .fops = &cadet_fops, | 575 | .fops = &cadet_fops, |
576 | .vidioc_querycap = vidioc_querycap, | ||
577 | .vidioc_g_tuner = vidioc_g_tuner, | ||
578 | .vidioc_s_tuner = vidioc_s_tuner, | ||
579 | .vidioc_g_frequency = vidioc_g_frequency, | ||
580 | .vidioc_s_frequency = vidioc_s_frequency, | ||
581 | .vidioc_queryctrl = vidioc_queryctrl, | ||
582 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
583 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
584 | .vidioc_g_audio = vidioc_g_audio, | ||
585 | .vidioc_s_audio = vidioc_s_audio, | ||
586 | .vidioc_g_input = vidioc_g_input, | ||
587 | .vidioc_s_input = vidioc_s_input, | ||
527 | }; | 588 | }; |
528 | 589 | ||
529 | static struct pnp_device_id cadet_pnp_devices[] = { | 590 | static struct pnp_device_id cadet_pnp_devices[] = { |