diff options
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 1935 |
1 files changed, 1011 insertions, 924 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8a4d221a4fe4..022afb7b98c4 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -47,7 +47,7 @@ | |||
47 | 47 | ||
48 | #define DRIVER_NAME "em28xx" | 48 | #define DRIVER_NAME "em28xx" |
49 | #define DRIVER_DESC "Empia em28xx based USB video device driver" | 49 | #define DRIVER_DESC "Empia em28xx based USB video device driver" |
50 | #define EM28XX_VERSION_CODE KERNEL_VERSION(0, 0, 1) | 50 | #define EM28XX_VERSION_CODE KERNEL_VERSION(0, 1, 0) |
51 | 51 | ||
52 | #define em28xx_videodbg(fmt, arg...) do {\ | 52 | #define em28xx_videodbg(fmt, arg...) do {\ |
53 | if (video_debug) \ | 53 | if (video_debug) \ |
@@ -202,8 +202,6 @@ static void video_mux(struct em28xx *dev, int index) | |||
202 | 202 | ||
203 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); | 203 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
204 | 204 | ||
205 | em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,route.input,dev->ctl_ainput); | ||
206 | |||
207 | if (dev->has_msp34xx) { | 205 | if (dev->has_msp34xx) { |
208 | if (dev->i2s_speed) | 206 | if (dev->i2s_speed) |
209 | em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); | 207 | em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed); |
@@ -264,6 +262,944 @@ static void res_free(struct em28xx_fh *fh) | |||
264 | } | 262 | } |
265 | 263 | ||
266 | /* | 264 | /* |
265 | * em28xx_vm_open() | ||
266 | */ | ||
267 | static void em28xx_vm_open(struct vm_area_struct *vma) | ||
268 | { | ||
269 | struct em28xx_frame_t *f = vma->vm_private_data; | ||
270 | f->vma_use_count++; | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * em28xx_vm_close() | ||
275 | */ | ||
276 | static void em28xx_vm_close(struct vm_area_struct *vma) | ||
277 | { | ||
278 | /* NOTE: buffers are not freed here */ | ||
279 | struct em28xx_frame_t *f = vma->vm_private_data; | ||
280 | |||
281 | if (f->vma_use_count) | ||
282 | f->vma_use_count--; | ||
283 | } | ||
284 | |||
285 | static struct vm_operations_struct em28xx_vm_ops = { | ||
286 | .open = em28xx_vm_open, | ||
287 | .close = em28xx_vm_close, | ||
288 | }; | ||
289 | |||
290 | |||
291 | /* | ||
292 | * em28xx_get_ctrl() | ||
293 | * return the current saturation, brightness or contrast, mute state | ||
294 | */ | ||
295 | static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) | ||
296 | { | ||
297 | switch (ctrl->id) { | ||
298 | case V4L2_CID_AUDIO_MUTE: | ||
299 | ctrl->value = dev->mute; | ||
300 | return 0; | ||
301 | case V4L2_CID_AUDIO_VOLUME: | ||
302 | ctrl->value = dev->volume; | ||
303 | return 0; | ||
304 | default: | ||
305 | return -EINVAL; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | /* | ||
310 | * em28xx_set_ctrl() | ||
311 | * mute or set new saturation, brightness or contrast | ||
312 | */ | ||
313 | static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) | ||
314 | { | ||
315 | switch (ctrl->id) { | ||
316 | case V4L2_CID_AUDIO_MUTE: | ||
317 | if (ctrl->value != dev->mute) { | ||
318 | dev->mute = ctrl->value; | ||
319 | em28xx_audio_usb_mute(dev, ctrl->value); | ||
320 | return em28xx_audio_analog_set(dev); | ||
321 | } | ||
322 | return 0; | ||
323 | case V4L2_CID_AUDIO_VOLUME: | ||
324 | dev->volume = ctrl->value; | ||
325 | return em28xx_audio_analog_set(dev); | ||
326 | default: | ||
327 | return -EINVAL; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | /* | ||
332 | * em28xx_stream_interrupt() | ||
333 | * stops streaming | ||
334 | */ | ||
335 | static int em28xx_stream_interrupt(struct em28xx *dev) | ||
336 | { | ||
337 | int rc = 0; | ||
338 | |||
339 | /* stop reading from the device */ | ||
340 | |||
341 | dev->stream = STREAM_INTERRUPT; | ||
342 | rc = wait_event_timeout(dev->wait_stream, | ||
343 | (dev->stream == STREAM_OFF) || | ||
344 | (dev->state & DEV_DISCONNECTED), | ||
345 | EM28XX_URB_TIMEOUT); | ||
346 | |||
347 | if (rc) { | ||
348 | dev->state |= DEV_MISCONFIGURED; | ||
349 | em28xx_videodbg("device is misconfigured; close and " | ||
350 | "open /dev/video%d again\n", | ||
351 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN); | ||
352 | return rc; | ||
353 | } | ||
354 | |||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | |||
359 | static int check_dev(struct em28xx *dev) | ||
360 | { | ||
361 | if (dev->state & DEV_DISCONNECTED) { | ||
362 | em28xx_errdev("v4l2 ioctl: device not present\n"); | ||
363 | return -ENODEV; | ||
364 | } | ||
365 | |||
366 | if (dev->state & DEV_MISCONFIGURED) { | ||
367 | em28xx_errdev("v4l2 ioctl: device is misconfigured; " | ||
368 | "close and open it again\n"); | ||
369 | return -EIO; | ||
370 | } | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static void get_scale(struct em28xx *dev, | ||
375 | unsigned int width, unsigned int height, | ||
376 | unsigned int *hscale, unsigned int *vscale) | ||
377 | { | ||
378 | unsigned int maxw = norm_maxw(dev); | ||
379 | unsigned int maxh = norm_maxh(dev); | ||
380 | |||
381 | *hscale = (((unsigned long)maxw) << 12) / width - 4096L; | ||
382 | if (*hscale >= 0x4000) | ||
383 | *hscale = 0x3fff; | ||
384 | |||
385 | *vscale = (((unsigned long)maxh) << 12) / height - 4096L; | ||
386 | if (*vscale >= 0x4000) | ||
387 | *vscale = 0x3fff; | ||
388 | } | ||
389 | |||
390 | /* ------------------------------------------------------------------ | ||
391 | IOCTL vidioc handling | ||
392 | ------------------------------------------------------------------*/ | ||
393 | |||
394 | static int vidioc_g_fmt_cap(struct file *file, void *priv, | ||
395 | struct v4l2_format *f) | ||
396 | { | ||
397 | struct em28xx_fh *fh = priv; | ||
398 | struct em28xx *dev = fh->dev; | ||
399 | |||
400 | mutex_lock(&dev->lock); | ||
401 | |||
402 | f->fmt.pix.width = dev->width; | ||
403 | f->fmt.pix.height = dev->height; | ||
404 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | ||
405 | f->fmt.pix.bytesperline = dev->bytesperline; | ||
406 | f->fmt.pix.sizeimage = dev->frame_size; | ||
407 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
408 | |||
409 | /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ | ||
410 | f->fmt.pix.field = dev->interlaced ? | ||
411 | V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; | ||
412 | |||
413 | mutex_unlock(&dev->lock); | ||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static int vidioc_try_fmt_cap(struct file *file, void *priv, | ||
418 | struct v4l2_format *f) | ||
419 | { | ||
420 | struct em28xx_fh *fh = priv; | ||
421 | struct em28xx *dev = fh->dev; | ||
422 | int width = f->fmt.pix.width; | ||
423 | int height = f->fmt.pix.height; | ||
424 | unsigned int maxw = norm_maxw(dev); | ||
425 | unsigned int maxh = norm_maxh(dev); | ||
426 | unsigned int hscale, vscale; | ||
427 | |||
428 | /* width must even because of the YUYV format | ||
429 | height must be even because of interlacing */ | ||
430 | height &= 0xfffe; | ||
431 | width &= 0xfffe; | ||
432 | |||
433 | if (height < 32) | ||
434 | height = 32; | ||
435 | if (height > maxh) | ||
436 | height = maxh; | ||
437 | if (width < 48) | ||
438 | width = 48; | ||
439 | if (width > maxw) | ||
440 | width = maxw; | ||
441 | |||
442 | mutex_lock(&dev->lock); | ||
443 | |||
444 | if (dev->is_em2800) { | ||
445 | /* the em2800 can only scale down to 50% */ | ||
446 | if (height % (maxh / 2)) | ||
447 | height = maxh; | ||
448 | if (width % (maxw / 2)) | ||
449 | width = maxw; | ||
450 | /* according to empiatech support */ | ||
451 | /* the MaxPacketSize is to small to support */ | ||
452 | /* framesizes larger than 640x480 @ 30 fps */ | ||
453 | /* or 640x576 @ 25 fps. As this would cut */ | ||
454 | /* of a part of the image we prefer */ | ||
455 | /* 360x576 or 360x480 for now */ | ||
456 | if (width == maxw && height == maxh) | ||
457 | width /= 2; | ||
458 | } | ||
459 | |||
460 | get_scale(dev, width, height, &hscale, &vscale); | ||
461 | |||
462 | width = (((unsigned long)maxw) << 12) / (hscale + 4096L); | ||
463 | height = (((unsigned long)maxh) << 12) / (vscale + 4096L); | ||
464 | |||
465 | f->fmt.pix.width = width; | ||
466 | f->fmt.pix.height = height; | ||
467 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | ||
468 | f->fmt.pix.bytesperline = width * 2; | ||
469 | f->fmt.pix.sizeimage = width * 2 * height; | ||
470 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
471 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; | ||
472 | |||
473 | mutex_unlock(&dev->lock); | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static int vidioc_s_fmt_cap(struct file *file, void *priv, | ||
478 | struct v4l2_format *f) | ||
479 | { | ||
480 | struct em28xx_fh *fh = priv; | ||
481 | struct em28xx *dev = fh->dev; | ||
482 | int rc, i; | ||
483 | |||
484 | rc = check_dev(dev); | ||
485 | if (rc < 0) | ||
486 | return rc; | ||
487 | |||
488 | vidioc_try_fmt_cap(file, priv, f); | ||
489 | |||
490 | mutex_lock(&dev->lock); | ||
491 | |||
492 | for (i = 0; i < dev->num_frames; i++) | ||
493 | if (dev->frame[i].vma_use_count) { | ||
494 | em28xx_videodbg("VIDIOC_S_FMT failed. " | ||
495 | "Unmap the buffers first.\n"); | ||
496 | rc = -EINVAL; | ||
497 | goto err; | ||
498 | } | ||
499 | |||
500 | /* stop io in case it is already in progress */ | ||
501 | if (dev->stream == STREAM_ON) { | ||
502 | em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n"); | ||
503 | rc = em28xx_stream_interrupt(dev); | ||
504 | if (rc < 0) | ||
505 | goto err; | ||
506 | } | ||
507 | |||
508 | em28xx_release_buffers(dev); | ||
509 | dev->io = IO_NONE; | ||
510 | |||
511 | /* set new image size */ | ||
512 | dev->width = f->fmt.pix.width; | ||
513 | dev->height = f->fmt.pix.height; | ||
514 | dev->frame_size = dev->width * dev->height * 2; | ||
515 | dev->field_size = dev->frame_size >> 1; | ||
516 | dev->bytesperline = dev->width * 2; | ||
517 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
518 | |||
519 | /* FIXME: This is really weird! Why capture is starting with | ||
520 | this ioctl ??? | ||
521 | */ | ||
522 | em28xx_uninit_isoc(dev); | ||
523 | em28xx_set_alternate(dev); | ||
524 | em28xx_capture_start(dev, 1); | ||
525 | em28xx_resolution_set(dev); | ||
526 | em28xx_init_isoc(dev); | ||
527 | rc = 0; | ||
528 | |||
529 | err: | ||
530 | mutex_unlock(&dev->lock); | ||
531 | return rc; | ||
532 | } | ||
533 | |||
534 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm) | ||
535 | { | ||
536 | struct em28xx_fh *fh = priv; | ||
537 | struct em28xx *dev = fh->dev; | ||
538 | struct v4l2_format f; | ||
539 | unsigned int i; | ||
540 | int rc; | ||
541 | |||
542 | rc = check_dev(dev); | ||
543 | if (rc < 0) | ||
544 | return rc; | ||
545 | |||
546 | for (i = 0; i < TVNORMS; i++) | ||
547 | if (*norm == tvnorms[i].id) | ||
548 | break; | ||
549 | if (i == TVNORMS) | ||
550 | for (i = 0; i < TVNORMS; i++) | ||
551 | if (*norm & tvnorms[i].id) | ||
552 | break; | ||
553 | if (i == TVNORMS) | ||
554 | return -EINVAL; | ||
555 | |||
556 | *norm = tvnorms[i].id; | ||
557 | |||
558 | mutex_lock(&dev->lock); | ||
559 | dev->tvnorm = &tvnorms[i]; | ||
560 | mutex_unlock(&dev->lock); | ||
561 | |||
562 | /* Adjusts width/height, if needed */ | ||
563 | f.fmt.pix.width = dev->width; | ||
564 | f.fmt.pix.height = dev->height; | ||
565 | vidioc_try_fmt_cap(file, priv, &f); | ||
566 | |||
567 | mutex_lock(&dev->lock); | ||
568 | |||
569 | /* set new image size */ | ||
570 | dev->width = f.fmt.pix.width; | ||
571 | dev->height = f.fmt.pix.height; | ||
572 | dev->frame_size = dev->width * dev->height * 2; | ||
573 | dev->field_size = dev->frame_size >> 1; | ||
574 | dev->bytesperline = dev->width * 2; | ||
575 | get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale); | ||
576 | |||
577 | em28xx_resolution_set(dev); | ||
578 | em28xx_i2c_call_clients(dev, VIDIOC_S_STD, &dev->tvnorm->id); | ||
579 | |||
580 | mutex_unlock(&dev->lock); | ||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | static const char *iname[] = { | ||
585 | [EM28XX_VMUX_COMPOSITE1] = "Composite1", | ||
586 | [EM28XX_VMUX_COMPOSITE2] = "Composite2", | ||
587 | [EM28XX_VMUX_COMPOSITE3] = "Composite3", | ||
588 | [EM28XX_VMUX_COMPOSITE4] = "Composite4", | ||
589 | [EM28XX_VMUX_SVIDEO] = "S-Video", | ||
590 | [EM28XX_VMUX_TELEVISION] = "Television", | ||
591 | [EM28XX_VMUX_CABLE] = "Cable TV", | ||
592 | [EM28XX_VMUX_DVB] = "DVB", | ||
593 | [EM28XX_VMUX_DEBUG] = "for debug only", | ||
594 | }; | ||
595 | |||
596 | static int vidioc_enum_input(struct file *file, void *priv, | ||
597 | struct v4l2_input *i) | ||
598 | { | ||
599 | struct em28xx_fh *fh = priv; | ||
600 | struct em28xx *dev = fh->dev; | ||
601 | unsigned int n; | ||
602 | |||
603 | n = i->index; | ||
604 | if (n >= MAX_EM28XX_INPUT) | ||
605 | return -EINVAL; | ||
606 | if (0 == INPUT(n)->type) | ||
607 | return -EINVAL; | ||
608 | |||
609 | i->index = n; | ||
610 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
611 | |||
612 | strcpy(i->name, iname[INPUT(n)->type]); | ||
613 | |||
614 | if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) || | ||
615 | (EM28XX_VMUX_CABLE == INPUT(n)->type)) | ||
616 | i->type = V4L2_INPUT_TYPE_TUNER; | ||
617 | |||
618 | for (n = 0; n < ARRAY_SIZE(tvnorms); n++) | ||
619 | i->std |= tvnorms[n].id; | ||
620 | |||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | ||
625 | { | ||
626 | struct em28xx_fh *fh = priv; | ||
627 | struct em28xx *dev = fh->dev; | ||
628 | |||
629 | *i = dev->ctl_input; | ||
630 | |||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | ||
635 | { | ||
636 | struct em28xx_fh *fh = priv; | ||
637 | struct em28xx *dev = fh->dev; | ||
638 | int rc; | ||
639 | |||
640 | rc = check_dev(dev); | ||
641 | if (rc < 0) | ||
642 | return rc; | ||
643 | |||
644 | if (i >= MAX_EM28XX_INPUT) | ||
645 | return -EINVAL; | ||
646 | if (0 == INPUT(i)->type) | ||
647 | return -EINVAL; | ||
648 | |||
649 | mutex_lock(&dev->lock); | ||
650 | |||
651 | video_mux(dev, i); | ||
652 | |||
653 | mutex_unlock(&dev->lock); | ||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a) | ||
658 | { | ||
659 | struct em28xx_fh *fh = priv; | ||
660 | struct em28xx *dev = fh->dev; | ||
661 | unsigned int index = a->index; | ||
662 | |||
663 | if (a->index > 1) | ||
664 | return -EINVAL; | ||
665 | |||
666 | index = dev->ctl_ainput; | ||
667 | |||
668 | if (index == 0) { | ||
669 | strcpy(a->name, "Television"); | ||
670 | } else { | ||
671 | strcpy(a->name, "Line In"); | ||
672 | } | ||
673 | a->capability = V4L2_AUDCAP_STEREO; | ||
674 | a->index = index; | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) | ||
680 | { | ||
681 | struct em28xx_fh *fh = priv; | ||
682 | struct em28xx *dev = fh->dev; | ||
683 | |||
684 | if (a->index != dev->ctl_ainput) | ||
685 | return -EINVAL; | ||
686 | |||
687 | return 0; | ||
688 | } | ||
689 | |||
690 | static int vidioc_queryctrl(struct file *file, void *priv, | ||
691 | struct v4l2_queryctrl *qc) | ||
692 | { | ||
693 | struct em28xx_fh *fh = priv; | ||
694 | struct em28xx *dev = fh->dev; | ||
695 | int id = qc->id; | ||
696 | int i; | ||
697 | int rc; | ||
698 | |||
699 | rc = check_dev(dev); | ||
700 | if (rc < 0) | ||
701 | return rc; | ||
702 | |||
703 | memset(qc, 0, sizeof(*qc)); | ||
704 | |||
705 | qc->id = id; | ||
706 | |||
707 | if (!dev->has_msp34xx) { | ||
708 | for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { | ||
709 | if (qc->id && qc->id == em28xx_qctrl[i].id) { | ||
710 | memcpy(qc, &(em28xx_qctrl[i]), sizeof(*qc)); | ||
711 | return 0; | ||
712 | } | ||
713 | } | ||
714 | } | ||
715 | mutex_lock(&dev->lock); | ||
716 | em28xx_i2c_call_clients(dev, VIDIOC_QUERYCTRL, qc); | ||
717 | mutex_unlock(&dev->lock); | ||
718 | |||
719 | if (qc->type) | ||
720 | return 0; | ||
721 | else | ||
722 | return -EINVAL; | ||
723 | } | ||
724 | |||
725 | static int vidioc_g_ctrl(struct file *file, void *priv, | ||
726 | struct v4l2_control *ctrl) | ||
727 | { | ||
728 | struct em28xx_fh *fh = priv; | ||
729 | struct em28xx *dev = fh->dev; | ||
730 | int rc; | ||
731 | |||
732 | rc = check_dev(dev); | ||
733 | if (rc < 0) | ||
734 | return rc; | ||
735 | mutex_lock(&dev->lock); | ||
736 | |||
737 | if (!dev->has_msp34xx) | ||
738 | rc = em28xx_get_ctrl(dev, ctrl); | ||
739 | else | ||
740 | rc = -EINVAL; | ||
741 | |||
742 | if (rc == -EINVAL) { | ||
743 | em28xx_i2c_call_clients(dev, VIDIOC_G_CTRL, ctrl); | ||
744 | rc = 0; | ||
745 | } | ||
746 | |||
747 | mutex_unlock(&dev->lock); | ||
748 | return rc; | ||
749 | } | ||
750 | |||
751 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
752 | struct v4l2_control *ctrl) | ||
753 | { | ||
754 | struct em28xx_fh *fh = priv; | ||
755 | struct em28xx *dev = fh->dev; | ||
756 | u8 i; | ||
757 | int rc; | ||
758 | |||
759 | rc = check_dev(dev); | ||
760 | if (rc < 0) | ||
761 | return rc; | ||
762 | |||
763 | mutex_lock(&dev->lock); | ||
764 | |||
765 | if (dev->has_msp34xx) | ||
766 | em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl); | ||
767 | else { | ||
768 | rc = 1; | ||
769 | for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { | ||
770 | if (ctrl->id == em28xx_qctrl[i].id) { | ||
771 | if (ctrl->value < em28xx_qctrl[i].minimum || | ||
772 | ctrl->value > em28xx_qctrl[i].maximum) { | ||
773 | rc = -ERANGE; | ||
774 | break; | ||
775 | } | ||
776 | |||
777 | rc = em28xx_set_ctrl(dev, ctrl); | ||
778 | break; | ||
779 | } | ||
780 | } | ||
781 | } | ||
782 | |||
783 | /* Control not found - try to send it to the attached devices */ | ||
784 | if (rc == 1) { | ||
785 | em28xx_i2c_call_clients(dev, VIDIOC_S_CTRL, ctrl); | ||
786 | rc = 0; | ||
787 | } | ||
788 | |||
789 | mutex_unlock(&dev->lock); | ||
790 | return rc; | ||
791 | } | ||
792 | |||
793 | static int vidioc_g_tuner(struct file *file, void *priv, | ||
794 | struct v4l2_tuner *t) | ||
795 | { | ||
796 | struct em28xx_fh *fh = priv; | ||
797 | struct em28xx *dev = fh->dev; | ||
798 | int rc; | ||
799 | |||
800 | rc = check_dev(dev); | ||
801 | if (rc < 0) | ||
802 | return rc; | ||
803 | |||
804 | if (0 != t->index) | ||
805 | return -EINVAL; | ||
806 | |||
807 | strcpy(t->name, "Tuner"); | ||
808 | |||
809 | mutex_lock(&dev->lock); | ||
810 | |||
811 | em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t); | ||
812 | |||
813 | mutex_unlock(&dev->lock); | ||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | static int vidioc_s_tuner(struct file *file, void *priv, | ||
818 | struct v4l2_tuner *t) | ||
819 | { | ||
820 | struct em28xx_fh *fh = priv; | ||
821 | struct em28xx *dev = fh->dev; | ||
822 | int rc; | ||
823 | |||
824 | rc = check_dev(dev); | ||
825 | if (rc < 0) | ||
826 | return rc; | ||
827 | |||
828 | if (0 != t->index) | ||
829 | return -EINVAL; | ||
830 | |||
831 | mutex_lock(&dev->lock); | ||
832 | |||
833 | em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t); | ||
834 | |||
835 | mutex_unlock(&dev->lock); | ||
836 | return 0; | ||
837 | } | ||
838 | |||
839 | static int vidioc_g_frequency(struct file *file, void *priv, | ||
840 | struct v4l2_frequency *f) | ||
841 | { | ||
842 | struct em28xx_fh *fh = priv; | ||
843 | struct em28xx *dev = fh->dev; | ||
844 | |||
845 | f->type = V4L2_TUNER_ANALOG_TV; | ||
846 | f->frequency = dev->ctl_freq; | ||
847 | |||
848 | return 0; | ||
849 | } | ||
850 | |||
851 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
852 | struct v4l2_frequency *f) | ||
853 | { | ||
854 | struct em28xx_fh *fh = priv; | ||
855 | struct em28xx *dev = fh->dev; | ||
856 | int rc; | ||
857 | |||
858 | rc = check_dev(dev); | ||
859 | if (rc < 0) | ||
860 | return rc; | ||
861 | |||
862 | if (0 != f->tuner) | ||
863 | return -EINVAL; | ||
864 | |||
865 | if (V4L2_TUNER_ANALOG_TV != f->type) | ||
866 | return -EINVAL; | ||
867 | |||
868 | mutex_lock(&dev->lock); | ||
869 | |||
870 | dev->ctl_freq = f->frequency; | ||
871 | em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); | ||
872 | |||
873 | mutex_unlock(&dev->lock); | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static int vidioc_cropcap(struct file *file, void *priv, | ||
878 | struct v4l2_cropcap *cc) | ||
879 | { | ||
880 | struct em28xx_fh *fh = priv; | ||
881 | struct em28xx *dev = fh->dev; | ||
882 | |||
883 | if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
884 | return -EINVAL; | ||
885 | |||
886 | cc->bounds.left = 0; | ||
887 | cc->bounds.top = 0; | ||
888 | cc->bounds.width = dev->width; | ||
889 | cc->bounds.height = dev->height; | ||
890 | cc->defrect = cc->bounds; | ||
891 | cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ | ||
892 | cc->pixelaspect.denominator = 59; | ||
893 | |||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | static int vidioc_streamon(struct file *file, void *priv, | ||
898 | enum v4l2_buf_type type) | ||
899 | { | ||
900 | struct em28xx_fh *fh = priv; | ||
901 | struct em28xx *dev = fh->dev; | ||
902 | int rc; | ||
903 | |||
904 | rc = check_dev(dev); | ||
905 | if (rc < 0) | ||
906 | return rc; | ||
907 | |||
908 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP) | ||
909 | return -EINVAL; | ||
910 | |||
911 | if (list_empty(&dev->inqueue)) | ||
912 | return -EINVAL; | ||
913 | |||
914 | mutex_lock(&dev->lock); | ||
915 | |||
916 | if (unlikely(res_get(fh) < 0)) { | ||
917 | mutex_unlock(&dev->lock); | ||
918 | return -EBUSY; | ||
919 | } | ||
920 | |||
921 | dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ | ||
922 | |||
923 | mutex_unlock(&dev->lock); | ||
924 | return 0; | ||
925 | } | ||
926 | |||
927 | static int vidioc_streamoff(struct file *file, void *priv, | ||
928 | enum v4l2_buf_type type) | ||
929 | { | ||
930 | struct em28xx_fh *fh = priv; | ||
931 | struct em28xx *dev = fh->dev; | ||
932 | int rc; | ||
933 | |||
934 | rc = check_dev(dev); | ||
935 | if (rc < 0) | ||
936 | return rc; | ||
937 | |||
938 | if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP) | ||
939 | return -EINVAL; | ||
940 | |||
941 | mutex_lock(&dev->lock); | ||
942 | |||
943 | if (dev->stream == STREAM_ON) { | ||
944 | em28xx_videodbg("VIDIOC_STREAMOFF: interrupting stream\n"); | ||
945 | rc = em28xx_stream_interrupt(dev); | ||
946 | if (rc < 0) { | ||
947 | mutex_unlock(&dev->lock); | ||
948 | return rc; | ||
949 | } | ||
950 | } | ||
951 | |||
952 | em28xx_empty_framequeues(dev); | ||
953 | |||
954 | mutex_unlock(&dev->lock); | ||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static int vidioc_querycap(struct file *file, void *priv, | ||
959 | struct v4l2_capability *cap) | ||
960 | { | ||
961 | struct em28xx_fh *fh = priv; | ||
962 | struct em28xx *dev = fh->dev; | ||
963 | |||
964 | strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); | ||
965 | strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card)); | ||
966 | strlcpy(cap->bus_info, dev->udev->dev.bus_id, sizeof(cap->bus_info)); | ||
967 | |||
968 | cap->version = EM28XX_VERSION_CODE; | ||
969 | |||
970 | cap->capabilities = | ||
971 | V4L2_CAP_SLICED_VBI_CAPTURE | | ||
972 | V4L2_CAP_VIDEO_CAPTURE | | ||
973 | V4L2_CAP_AUDIO | | ||
974 | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; | ||
975 | |||
976 | if (dev->has_tuner) | ||
977 | cap->capabilities |= V4L2_CAP_TUNER; | ||
978 | |||
979 | return 0; | ||
980 | } | ||
981 | |||
982 | static int vidioc_enum_fmt_cap(struct file *file, void *priv, | ||
983 | struct v4l2_fmtdesc *fmtd) | ||
984 | { | ||
985 | if (fmtd->index != 0) | ||
986 | return -EINVAL; | ||
987 | |||
988 | fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
989 | strcpy(fmtd->description, "Packed YUY2"); | ||
990 | fmtd->pixelformat = V4L2_PIX_FMT_YUYV; | ||
991 | memset(fmtd->reserved, 0, sizeof(fmtd->reserved)); | ||
992 | |||
993 | return 0; | ||
994 | } | ||
995 | |||
996 | /* Sliced VBI ioctls */ | ||
997 | static int vidioc_g_fmt_vbi_capture(struct file *file, void *priv, | ||
998 | struct v4l2_format *f) | ||
999 | { | ||
1000 | struct em28xx_fh *fh = priv; | ||
1001 | struct em28xx *dev = fh->dev; | ||
1002 | int rc; | ||
1003 | |||
1004 | rc = check_dev(dev); | ||
1005 | if (rc < 0) | ||
1006 | return rc; | ||
1007 | |||
1008 | mutex_lock(&dev->lock); | ||
1009 | |||
1010 | f->fmt.sliced.service_set = 0; | ||
1011 | |||
1012 | em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f); | ||
1013 | |||
1014 | if (f->fmt.sliced.service_set == 0) | ||
1015 | rc = -EINVAL; | ||
1016 | |||
1017 | mutex_unlock(&dev->lock); | ||
1018 | return rc; | ||
1019 | } | ||
1020 | |||
1021 | static int vidioc_try_set_vbi_capture(struct file *file, void *priv, | ||
1022 | struct v4l2_format *f) | ||
1023 | { | ||
1024 | struct em28xx_fh *fh = priv; | ||
1025 | struct em28xx *dev = fh->dev; | ||
1026 | int rc; | ||
1027 | |||
1028 | rc = check_dev(dev); | ||
1029 | if (rc < 0) | ||
1030 | return rc; | ||
1031 | |||
1032 | mutex_lock(&dev->lock); | ||
1033 | em28xx_i2c_call_clients(dev, VIDIOC_G_FMT, f); | ||
1034 | mutex_unlock(&dev->lock); | ||
1035 | |||
1036 | if (f->fmt.sliced.service_set == 0) | ||
1037 | return -EINVAL; | ||
1038 | |||
1039 | return 0; | ||
1040 | } | ||
1041 | |||
1042 | |||
1043 | static int vidioc_reqbufs(struct file *file, void *priv, | ||
1044 | struct v4l2_requestbuffers *rb) | ||
1045 | { | ||
1046 | struct em28xx_fh *fh = priv; | ||
1047 | struct em28xx *dev = fh->dev; | ||
1048 | u32 i; | ||
1049 | int rc; | ||
1050 | |||
1051 | rc = check_dev(dev); | ||
1052 | if (rc < 0) | ||
1053 | return rc; | ||
1054 | |||
1055 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
1056 | rb->memory != V4L2_MEMORY_MMAP) | ||
1057 | return -EINVAL; | ||
1058 | |||
1059 | if (dev->io == IO_READ) { | ||
1060 | em28xx_videodbg("method is set to read;" | ||
1061 | " close and open the device again to" | ||
1062 | " choose the mmap I/O method\n"); | ||
1063 | return -EINVAL; | ||
1064 | } | ||
1065 | |||
1066 | for (i = 0; i < dev->num_frames; i++) | ||
1067 | if (dev->frame[i].vma_use_count) { | ||
1068 | em28xx_videodbg("VIDIOC_REQBUFS failed; " | ||
1069 | "previous buffers are still mapped\n"); | ||
1070 | return -EINVAL; | ||
1071 | } | ||
1072 | |||
1073 | mutex_lock(&dev->lock); | ||
1074 | |||
1075 | if (dev->stream == STREAM_ON) { | ||
1076 | em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n"); | ||
1077 | rc = em28xx_stream_interrupt(dev); | ||
1078 | if (rc < 0) { | ||
1079 | mutex_unlock(&dev->lock); | ||
1080 | return rc; | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | em28xx_empty_framequeues(dev); | ||
1085 | |||
1086 | em28xx_release_buffers(dev); | ||
1087 | if (rb->count) | ||
1088 | rb->count = em28xx_request_buffers(dev, rb->count); | ||
1089 | |||
1090 | dev->frame_current = NULL; | ||
1091 | dev->io = rb->count ? IO_MMAP : IO_NONE; | ||
1092 | |||
1093 | mutex_unlock(&dev->lock); | ||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | static int vidioc_querybuf(struct file *file, void *priv, | ||
1098 | struct v4l2_buffer *b) | ||
1099 | { | ||
1100 | struct em28xx_fh *fh = priv; | ||
1101 | struct em28xx *dev = fh->dev; | ||
1102 | int rc; | ||
1103 | |||
1104 | rc = check_dev(dev); | ||
1105 | if (rc < 0) | ||
1106 | return rc; | ||
1107 | |||
1108 | if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
1109 | b->index >= dev->num_frames || dev->io != IO_MMAP) | ||
1110 | return -EINVAL; | ||
1111 | |||
1112 | mutex_lock(&dev->lock); | ||
1113 | |||
1114 | memcpy(b, &dev->frame[b->index].buf, sizeof(*b)); | ||
1115 | |||
1116 | if (dev->frame[b->index].vma_use_count) | ||
1117 | b->flags |= V4L2_BUF_FLAG_MAPPED; | ||
1118 | |||
1119 | if (dev->frame[b->index].state == F_DONE) | ||
1120 | b->flags |= V4L2_BUF_FLAG_DONE; | ||
1121 | else if (dev->frame[b->index].state != F_UNUSED) | ||
1122 | b->flags |= V4L2_BUF_FLAG_QUEUED; | ||
1123 | |||
1124 | mutex_unlock(&dev->lock); | ||
1125 | return 0; | ||
1126 | } | ||
1127 | |||
1128 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) | ||
1129 | { | ||
1130 | struct em28xx_fh *fh = priv; | ||
1131 | struct em28xx *dev = fh->dev; | ||
1132 | unsigned long lock_flags; | ||
1133 | int rc; | ||
1134 | |||
1135 | rc = check_dev(dev); | ||
1136 | if (rc < 0) | ||
1137 | return rc; | ||
1138 | |||
1139 | if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP || | ||
1140 | b->index >= dev->num_frames) | ||
1141 | return -EINVAL; | ||
1142 | |||
1143 | if (dev->frame[b->index].state != F_UNUSED) | ||
1144 | return -EAGAIN; | ||
1145 | |||
1146 | dev->frame[b->index].state = F_QUEUED; | ||
1147 | |||
1148 | /* add frame to fifo */ | ||
1149 | spin_lock_irqsave(&dev->queue_lock, lock_flags); | ||
1150 | list_add_tail(&dev->frame[b->index].frame, &dev->inqueue); | ||
1151 | spin_unlock_irqrestore(&dev->queue_lock, lock_flags); | ||
1152 | |||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1156 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | ||
1157 | { | ||
1158 | struct em28xx_fh *fh = priv; | ||
1159 | struct em28xx *dev = fh->dev; | ||
1160 | int rc; | ||
1161 | struct em28xx_frame_t *f; | ||
1162 | unsigned long lock_flags; | ||
1163 | |||
1164 | rc = check_dev(dev); | ||
1165 | if (rc < 0) | ||
1166 | return rc; | ||
1167 | |||
1168 | if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || dev->io != IO_MMAP) | ||
1169 | return -EINVAL; | ||
1170 | |||
1171 | if (list_empty(&dev->outqueue)) { | ||
1172 | if (dev->stream == STREAM_OFF) | ||
1173 | return -EINVAL; | ||
1174 | |||
1175 | if (file->f_flags & O_NONBLOCK) | ||
1176 | return -EAGAIN; | ||
1177 | |||
1178 | rc = wait_event_interruptible(dev->wait_frame, | ||
1179 | (!list_empty(&dev->outqueue)) || | ||
1180 | (dev->state & DEV_DISCONNECTED)); | ||
1181 | if (rc) | ||
1182 | return rc; | ||
1183 | |||
1184 | if (dev->state & DEV_DISCONNECTED) | ||
1185 | return -ENODEV; | ||
1186 | } | ||
1187 | |||
1188 | spin_lock_irqsave(&dev->queue_lock, lock_flags); | ||
1189 | f = list_entry(dev->outqueue.next, struct em28xx_frame_t, frame); | ||
1190 | list_del(dev->outqueue.next); | ||
1191 | spin_unlock_irqrestore(&dev->queue_lock, lock_flags); | ||
1192 | |||
1193 | f->state = F_UNUSED; | ||
1194 | memcpy(b, &f->buf, sizeof(*b)); | ||
1195 | |||
1196 | if (f->vma_use_count) | ||
1197 | b->flags |= V4L2_BUF_FLAG_MAPPED; | ||
1198 | |||
1199 | return 0; | ||
1200 | } | ||
1201 | |||
1202 | /* | ||
267 | * em28xx_v4l2_open() | 1203 | * em28xx_v4l2_open() |
268 | * inits the device and starts isoc transfer | 1204 | * inits the device and starts isoc transfer |
269 | */ | 1205 | */ |
@@ -587,32 +1523,6 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) | |||
587 | } | 1523 | } |
588 | 1524 | ||
589 | /* | 1525 | /* |
590 | * em28xx_vm_open() | ||
591 | */ | ||
592 | static void em28xx_vm_open(struct vm_area_struct *vma) | ||
593 | { | ||
594 | struct em28xx_frame_t *f = vma->vm_private_data; | ||
595 | f->vma_use_count++; | ||
596 | } | ||
597 | |||
598 | /* | ||
599 | * em28xx_vm_close() | ||
600 | */ | ||
601 | static void em28xx_vm_close(struct vm_area_struct *vma) | ||
602 | { | ||
603 | /* NOTE: buffers are not freed here */ | ||
604 | struct em28xx_frame_t *f = vma->vm_private_data; | ||
605 | |||
606 | if (f->vma_use_count) | ||
607 | f->vma_use_count--; | ||
608 | } | ||
609 | |||
610 | static struct vm_operations_struct em28xx_vm_ops = { | ||
611 | .open = em28xx_vm_open, | ||
612 | .close = em28xx_vm_close, | ||
613 | }; | ||
614 | |||
615 | /* | ||
616 | * em28xx_v4l2_mmap() | 1526 | * em28xx_v4l2_mmap() |
617 | */ | 1527 | */ |
618 | static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) | 1528 | static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) |
@@ -642,12 +1552,14 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) | |||
642 | return -EIO; | 1552 | return -EIO; |
643 | } | 1553 | } |
644 | 1554 | ||
645 | if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) || | 1555 | if (dev->io != IO_MMAP || !(vma->vm_flags & VM_WRITE)) { |
646 | size != PAGE_ALIGN(dev->frame[0].buf.length)) { | ||
647 | mutex_unlock(&dev->lock); | 1556 | mutex_unlock(&dev->lock); |
648 | return -EINVAL; | 1557 | return -EINVAL; |
649 | } | 1558 | } |
650 | 1559 | ||
1560 | if (size > PAGE_ALIGN(dev->frame[0].buf.length)) | ||
1561 | size = PAGE_ALIGN(dev->frame[0].buf.length); | ||
1562 | |||
651 | for (i = 0; i < dev->num_frames; i++) { | 1563 | for (i = 0; i < dev->num_frames; i++) { |
652 | if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) | 1564 | if ((dev->frame[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) |
653 | break; | 1565 | break; |
@@ -682,879 +1594,59 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) | |||
682 | return 0; | 1594 | return 0; |
683 | } | 1595 | } |
684 | 1596 | ||
685 | /* | ||
686 | * em28xx_get_ctrl() | ||
687 | * return the current saturation, brightness or contrast, mute state | ||
688 | */ | ||
689 | static int em28xx_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) | ||
690 | { | ||
691 | switch (ctrl->id) { | ||
692 | case V4L2_CID_AUDIO_MUTE: | ||
693 | ctrl->value = dev->mute; | ||
694 | return 0; | ||
695 | case V4L2_CID_AUDIO_VOLUME: | ||
696 | ctrl->value = dev->volume; | ||
697 | return 0; | ||
698 | default: | ||
699 | return -EINVAL; | ||
700 | } | ||
701 | } | ||
702 | |||
703 | /* | ||
704 | * em28xx_set_ctrl() | ||
705 | * mute or set new saturation, brightness or contrast | ||
706 | */ | ||
707 | static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) | ||
708 | { | ||
709 | switch (ctrl->id) { | ||
710 | case V4L2_CID_AUDIO_MUTE: | ||
711 | if (ctrl->value != dev->mute) { | ||
712 | dev->mute = ctrl->value; | ||
713 | em28xx_audio_usb_mute(dev, ctrl->value); | ||
714 | return em28xx_audio_analog_set(dev); | ||
715 | } | ||
716 | return 0; | ||
717 | case V4L2_CID_AUDIO_VOLUME: | ||
718 | dev->volume = ctrl->value; | ||
719 | return em28xx_audio_analog_set(dev); | ||
720 | default: | ||
721 | return -EINVAL; | ||
722 | } | ||
723 | } | ||
724 | |||
725 | /* | ||
726 | * em28xx_stream_interrupt() | ||
727 | * stops streaming | ||
728 | */ | ||
729 | static int em28xx_stream_interrupt(struct em28xx *dev) | ||
730 | { | ||
731 | int ret = 0; | ||
732 | |||
733 | /* stop reading from the device */ | ||
734 | |||
735 | dev->stream = STREAM_INTERRUPT; | ||
736 | ret = wait_event_timeout(dev->wait_stream, | ||
737 | (dev->stream == STREAM_OFF) || | ||
738 | (dev->state & DEV_DISCONNECTED), | ||
739 | EM28XX_URB_TIMEOUT); | ||
740 | if (dev->state & DEV_DISCONNECTED) | ||
741 | return -ENODEV; | ||
742 | else if (ret) { | ||
743 | dev->state |= DEV_MISCONFIGURED; | ||
744 | em28xx_videodbg("device is misconfigured; close and " | ||
745 | "open /dev/video%d again\n", | ||
746 | dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN); | ||
747 | return ret; | ||
748 | } | ||
749 | |||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | static int em28xx_set_norm(struct em28xx *dev, int width, int height) | ||
754 | { | ||
755 | unsigned int hscale, vscale; | ||
756 | unsigned int maxh, maxw; | ||
757 | |||
758 | maxw = norm_maxw(dev); | ||
759 | maxh = norm_maxh(dev); | ||
760 | |||
761 | /* width must even because of the YUYV format */ | ||
762 | /* height must be even because of interlacing */ | ||
763 | height &= 0xfffe; | ||
764 | width &= 0xfffe; | ||
765 | |||
766 | if (height < 32) | ||
767 | height = 32; | ||
768 | if (height > maxh) | ||
769 | height = maxh; | ||
770 | if (width < 48) | ||
771 | width = 48; | ||
772 | if (width > maxw) | ||
773 | width = maxw; | ||
774 | |||
775 | if ((hscale = (((unsigned long)maxw) << 12) / width - 4096L) >= 0x4000) | ||
776 | hscale = 0x3fff; | ||
777 | width = (((unsigned long)maxw) << 12) / (hscale + 4096L); | ||
778 | |||
779 | if ((vscale = (((unsigned long)maxh) << 12) / height - 4096L) >= 0x4000) | ||
780 | vscale = 0x3fff; | ||
781 | height = (((unsigned long)maxh) << 12) / (vscale + 4096L); | ||
782 | |||
783 | /* set new image size */ | ||
784 | dev->width = width; | ||
785 | dev->height = height; | ||
786 | dev->frame_size = dev->width * dev->height * 2; | ||
787 | dev->field_size = dev->frame_size >> 1; /*both_fileds ? dev->frame_size>>1 : dev->frame_size; */ | ||
788 | dev->bytesperline = dev->width * 2; | ||
789 | dev->hscale = hscale; | ||
790 | dev->vscale = vscale; | ||
791 | |||
792 | em28xx_resolution_set(dev); | ||
793 | |||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | static int em28xx_get_fmt(struct em28xx *dev, struct v4l2_format *format) | ||
798 | { | ||
799 | em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", | ||
800 | (format->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE) ? | ||
801 | "V4L2_BUF_TYPE_VIDEO_CAPTURE" : | ||
802 | (format->type ==V4L2_BUF_TYPE_VBI_CAPTURE) ? | ||
803 | "V4L2_BUF_TYPE_VBI_CAPTURE" : | ||
804 | (format->type ==V4L2_CAP_SLICED_VBI_CAPTURE) ? | ||
805 | "V4L2_BUF_TYPE_SLICED_VBI_CAPTURE " : | ||
806 | "not supported"); | ||
807 | |||
808 | switch (format->type) { | ||
809 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
810 | { | ||
811 | format->fmt.pix.width = dev->width; | ||
812 | format->fmt.pix.height = dev->height; | ||
813 | format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | ||
814 | format->fmt.pix.bytesperline = dev->bytesperline; | ||
815 | format->fmt.pix.sizeimage = dev->frame_size; | ||
816 | format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
817 | format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ | ||
818 | |||
819 | em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, | ||
820 | dev->height); | ||
821 | break; | ||
822 | } | ||
823 | |||
824 | case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: | ||
825 | { | ||
826 | format->fmt.sliced.service_set=0; | ||
827 | |||
828 | em28xx_i2c_call_clients(dev,VIDIOC_G_FMT,format); | ||
829 | |||
830 | if (format->fmt.sliced.service_set==0) | ||
831 | return -EINVAL; | ||
832 | |||
833 | break; | ||
834 | } | ||
835 | |||
836 | default: | ||
837 | return -EINVAL; | ||
838 | } | ||
839 | return (0); | ||
840 | } | ||
841 | |||
842 | static int em28xx_set_fmt(struct em28xx *dev, unsigned int cmd, struct v4l2_format *format) | ||
843 | { | ||
844 | u32 i; | ||
845 | int ret = 0; | ||
846 | int width = format->fmt.pix.width; | ||
847 | int height = format->fmt.pix.height; | ||
848 | unsigned int hscale, vscale; | ||
849 | unsigned int maxh, maxw; | ||
850 | |||
851 | maxw = norm_maxw(dev); | ||
852 | maxh = norm_maxh(dev); | ||
853 | |||
854 | em28xx_videodbg("%s: type=%s\n", | ||
855 | cmd == VIDIOC_TRY_FMT ? | ||
856 | "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", | ||
857 | format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? | ||
858 | "V4L2_BUF_TYPE_VIDEO_CAPTURE" : | ||
859 | format->type == V4L2_BUF_TYPE_VBI_CAPTURE ? | ||
860 | "V4L2_BUF_TYPE_VBI_CAPTURE " : | ||
861 | "not supported"); | ||
862 | |||
863 | if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { | ||
864 | em28xx_i2c_call_clients(dev,VIDIOC_G_FMT,format); | ||
865 | |||
866 | if (format->fmt.sliced.service_set==0) | ||
867 | return -EINVAL; | ||
868 | |||
869 | return 0; | ||
870 | } | ||
871 | |||
872 | |||
873 | if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
874 | return -EINVAL; | ||
875 | |||
876 | em28xx_videodbg("%s: requested %dx%d\n", | ||
877 | cmd == VIDIOC_TRY_FMT ? | ||
878 | "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", | ||
879 | format->fmt.pix.width, format->fmt.pix.height); | ||
880 | |||
881 | /* FIXME: Move some code away from here */ | ||
882 | /* width must even because of the YUYV format */ | ||
883 | /* height must be even because of interlacing */ | ||
884 | height &= 0xfffe; | ||
885 | width &= 0xfffe; | ||
886 | |||
887 | if (height < 32) | ||
888 | height = 32; | ||
889 | if (height > maxh) | ||
890 | height = maxh; | ||
891 | if (width < 48) | ||
892 | width = 48; | ||
893 | if (width > maxw) | ||
894 | width = maxw; | ||
895 | |||
896 | if(dev->is_em2800){ | ||
897 | /* the em2800 can only scale down to 50% */ | ||
898 | if(height % (maxh / 2)) | ||
899 | height=maxh; | ||
900 | if(width % (maxw / 2)) | ||
901 | width=maxw; | ||
902 | /* according to empiatech support */ | ||
903 | /* the MaxPacketSize is to small to support */ | ||
904 | /* framesizes larger than 640x480 @ 30 fps */ | ||
905 | /* or 640x576 @ 25 fps. As this would cut */ | ||
906 | /* of a part of the image we prefer */ | ||
907 | /* 360x576 or 360x480 for now */ | ||
908 | if(width == maxw && height == maxh) | ||
909 | width /= 2; | ||
910 | } | ||
911 | |||
912 | if ((hscale = (((unsigned long)maxw) << 12) / width - 4096L) >= 0x4000) | ||
913 | hscale = 0x3fff; | ||
914 | |||
915 | width = (((unsigned long)maxw) << 12) / (hscale + 4096L); | ||
916 | |||
917 | if ((vscale = (((unsigned long)maxh) << 12) / height - 4096L) >= 0x4000) | ||
918 | vscale = 0x3fff; | ||
919 | |||
920 | height = (((unsigned long)maxh) << 12) / (vscale + 4096L); | ||
921 | |||
922 | format->fmt.pix.width = width; | ||
923 | format->fmt.pix.height = height; | ||
924 | format->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; | ||
925 | format->fmt.pix.bytesperline = width * 2; | ||
926 | format->fmt.pix.sizeimage = width * 2 * height; | ||
927 | format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
928 | format->fmt.pix.field = V4L2_FIELD_INTERLACED; | ||
929 | |||
930 | em28xx_videodbg("%s: returned %dx%d (%d, %d)\n", | ||
931 | cmd == VIDIOC_TRY_FMT ? | ||
932 | "VIDIOC_TRY_FMT" :"VIDIOC_S_FMT", | ||
933 | format->fmt.pix.width, format->fmt.pix.height, hscale, vscale); | ||
934 | |||
935 | if (cmd == VIDIOC_TRY_FMT) | ||
936 | return 0; | ||
937 | |||
938 | for (i = 0; i < dev->num_frames; i++) | ||
939 | if (dev->frame[i].vma_use_count) { | ||
940 | em28xx_videodbg("VIDIOC_S_FMT failed. " | ||
941 | "Unmap the buffers first.\n"); | ||
942 | return -EINVAL; | ||
943 | } | ||
944 | |||
945 | /* stop io in case it is already in progress */ | ||
946 | if (dev->stream == STREAM_ON) { | ||
947 | em28xx_videodbg("VIDIOC_SET_FMT: interrupting stream\n"); | ||
948 | if ((ret = em28xx_stream_interrupt(dev))) | ||
949 | return ret; | ||
950 | } | ||
951 | |||
952 | em28xx_release_buffers(dev); | ||
953 | dev->io = IO_NONE; | ||
954 | |||
955 | /* set new image size */ | ||
956 | dev->width = width; | ||
957 | dev->height = height; | ||
958 | dev->frame_size = dev->width * dev->height * 2; | ||
959 | dev->field_size = dev->frame_size >> 1; | ||
960 | dev->bytesperline = dev->width * 2; | ||
961 | dev->hscale = hscale; | ||
962 | dev->vscale = vscale; | ||
963 | em28xx_uninit_isoc(dev); | ||
964 | em28xx_set_alternate(dev); | ||
965 | em28xx_capture_start(dev, 1); | ||
966 | em28xx_resolution_set(dev); | ||
967 | em28xx_init_isoc(dev); | ||
968 | |||
969 | return 0; | ||
970 | } | ||
971 | |||
972 | /* | ||
973 | * em28xx_v4l2_do_ioctl() | ||
974 | * This function is _not_ called directly, but from | ||
975 | * em28xx_v4l2_ioctl. Userspace | ||
976 | * copying is done already, arg is a kernel pointer. | ||
977 | */ | ||
978 | static int em28xx_do_ioctl(struct inode *inode, struct file *filp, | ||
979 | struct em28xx *dev, unsigned int cmd, void *arg, | ||
980 | v4l2_kioctl driver_ioctl) | ||
981 | { | ||
982 | struct em28xx_fh *fh = filp->private_data; | ||
983 | int ret; | ||
984 | |||
985 | switch (cmd) { | ||
986 | /* ---------- tv norms ---------- */ | ||
987 | case VIDIOC_ENUMSTD: | ||
988 | { | ||
989 | struct v4l2_standard *e = arg; | ||
990 | unsigned int i; | ||
991 | |||
992 | i = e->index; | ||
993 | if (i >= TVNORMS) | ||
994 | return -EINVAL; | ||
995 | ret = v4l2_video_std_construct(e, tvnorms[e->index].id, | ||
996 | tvnorms[e->index].name); | ||
997 | e->index = i; | ||
998 | if (ret < 0) | ||
999 | return ret; | ||
1000 | return 0; | ||
1001 | } | ||
1002 | case VIDIOC_G_STD: | ||
1003 | { | ||
1004 | v4l2_std_id *id = arg; | ||
1005 | |||
1006 | *id = dev->tvnorm->id; | ||
1007 | return 0; | ||
1008 | } | ||
1009 | case VIDIOC_S_STD: | ||
1010 | { | ||
1011 | v4l2_std_id *id = arg; | ||
1012 | unsigned int i; | ||
1013 | |||
1014 | for (i = 0; i < TVNORMS; i++) | ||
1015 | if (*id == tvnorms[i].id) | ||
1016 | break; | ||
1017 | if (i == TVNORMS) | ||
1018 | for (i = 0; i < TVNORMS; i++) | ||
1019 | if (*id & tvnorms[i].id) | ||
1020 | break; | ||
1021 | if (i == TVNORMS) | ||
1022 | return -EINVAL; | ||
1023 | |||
1024 | mutex_lock(&dev->lock); | ||
1025 | dev->tvnorm = &tvnorms[i]; | ||
1026 | |||
1027 | em28xx_set_norm(dev, dev->width, dev->height); | ||
1028 | |||
1029 | em28xx_i2c_call_clients(dev, VIDIOC_S_STD, | ||
1030 | &dev->tvnorm->id); | ||
1031 | |||
1032 | mutex_unlock(&dev->lock); | ||
1033 | |||
1034 | return 0; | ||
1035 | } | ||
1036 | |||
1037 | /* ------ input switching ---------- */ | ||
1038 | case VIDIOC_ENUMINPUT: | ||
1039 | { | ||
1040 | struct v4l2_input *i = arg; | ||
1041 | unsigned int n; | ||
1042 | static const char *iname[] = { | ||
1043 | [EM28XX_VMUX_COMPOSITE1] = "Composite1", | ||
1044 | [EM28XX_VMUX_COMPOSITE2] = "Composite2", | ||
1045 | [EM28XX_VMUX_COMPOSITE3] = "Composite3", | ||
1046 | [EM28XX_VMUX_COMPOSITE4] = "Composite4", | ||
1047 | [EM28XX_VMUX_SVIDEO] = "S-Video", | ||
1048 | [EM28XX_VMUX_TELEVISION] = "Television", | ||
1049 | [EM28XX_VMUX_CABLE] = "Cable TV", | ||
1050 | [EM28XX_VMUX_DVB] = "DVB", | ||
1051 | [EM28XX_VMUX_DEBUG] = "for debug only", | ||
1052 | }; | ||
1053 | |||
1054 | n = i->index; | ||
1055 | if (n >= MAX_EM28XX_INPUT) | ||
1056 | return -EINVAL; | ||
1057 | if (0 == INPUT(n)->type) | ||
1058 | return -EINVAL; | ||
1059 | memset(i, 0, sizeof(*i)); | ||
1060 | i->index = n; | ||
1061 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
1062 | strcpy(i->name, iname[INPUT(n)->type]); | ||
1063 | if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) || | ||
1064 | (EM28XX_VMUX_CABLE == INPUT(n)->type)) | ||
1065 | i->type = V4L2_INPUT_TYPE_TUNER; | ||
1066 | for (n = 0; n < ARRAY_SIZE(tvnorms); n++) | ||
1067 | i->std |= tvnorms[n].id; | ||
1068 | return 0; | ||
1069 | } | ||
1070 | case VIDIOC_G_INPUT: | ||
1071 | { | ||
1072 | int *i = arg; | ||
1073 | *i = dev->ctl_input; | ||
1074 | |||
1075 | return 0; | ||
1076 | } | ||
1077 | case VIDIOC_S_INPUT: | ||
1078 | { | ||
1079 | int *index = arg; | ||
1080 | |||
1081 | if (*index >= MAX_EM28XX_INPUT) | ||
1082 | return -EINVAL; | ||
1083 | if (0 == INPUT(*index)->type) | ||
1084 | return -EINVAL; | ||
1085 | |||
1086 | mutex_lock(&dev->lock); | ||
1087 | video_mux(dev, *index); | ||
1088 | mutex_unlock(&dev->lock); | ||
1089 | |||
1090 | return 0; | ||
1091 | } | ||
1092 | case VIDIOC_G_AUDIO: | ||
1093 | { | ||
1094 | struct v4l2_audio *a = arg; | ||
1095 | unsigned int index = a->index; | ||
1096 | |||
1097 | if (a->index > 1) | ||
1098 | return -EINVAL; | ||
1099 | memset(a, 0, sizeof(*a)); | ||
1100 | index = dev->ctl_ainput; | ||
1101 | |||
1102 | if (index == 0) { | ||
1103 | strcpy(a->name, "Television"); | ||
1104 | } else { | ||
1105 | strcpy(a->name, "Line In"); | ||
1106 | } | ||
1107 | a->capability = V4L2_AUDCAP_STEREO; | ||
1108 | a->index = index; | ||
1109 | return 0; | ||
1110 | } | ||
1111 | case VIDIOC_S_AUDIO: | ||
1112 | { | ||
1113 | struct v4l2_audio *a = arg; | ||
1114 | |||
1115 | if (a->index != dev->ctl_ainput) | ||
1116 | return -EINVAL; | ||
1117 | |||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1121 | /* --- controls ---------------------------------------------- */ | ||
1122 | case VIDIOC_QUERYCTRL: | ||
1123 | { | ||
1124 | struct v4l2_queryctrl *qc = arg; | ||
1125 | int i, id=qc->id; | ||
1126 | |||
1127 | memset(qc,0,sizeof(*qc)); | ||
1128 | qc->id=id; | ||
1129 | |||
1130 | if (!dev->has_msp34xx) { | ||
1131 | for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { | ||
1132 | if (qc->id && qc->id == em28xx_qctrl[i].id) { | ||
1133 | memcpy(qc, &(em28xx_qctrl[i]), | ||
1134 | sizeof(*qc)); | ||
1135 | return 0; | ||
1136 | } | ||
1137 | } | ||
1138 | } | ||
1139 | mutex_lock(&dev->lock); | ||
1140 | em28xx_i2c_call_clients(dev,cmd,qc); | ||
1141 | mutex_unlock(&dev->lock); | ||
1142 | if (qc->type) | ||
1143 | return 0; | ||
1144 | else | ||
1145 | return -EINVAL; | ||
1146 | } | ||
1147 | case VIDIOC_G_CTRL: | ||
1148 | { | ||
1149 | struct v4l2_control *ctrl = arg; | ||
1150 | int retval=-EINVAL; | ||
1151 | |||
1152 | if (!dev->has_msp34xx) | ||
1153 | retval=em28xx_get_ctrl(dev, ctrl); | ||
1154 | if (retval==-EINVAL) { | ||
1155 | mutex_lock(&dev->lock); | ||
1156 | em28xx_i2c_call_clients(dev,cmd,arg); | ||
1157 | mutex_unlock(&dev->lock); | ||
1158 | return 0; | ||
1159 | } else return retval; | ||
1160 | } | ||
1161 | case VIDIOC_S_CTRL: | ||
1162 | { | ||
1163 | struct v4l2_control *ctrl = arg; | ||
1164 | u8 i; | ||
1165 | mutex_lock(&dev->lock); | ||
1166 | |||
1167 | if (!dev->has_msp34xx){ | ||
1168 | for (i = 0; i < ARRAY_SIZE(em28xx_qctrl); i++) { | ||
1169 | if (ctrl->id == em28xx_qctrl[i].id) { | ||
1170 | int retval=-EINVAL; | ||
1171 | if (ctrl->value < | ||
1172 | em28xx_qctrl[i].minimum | ||
1173 | || ctrl->value > | ||
1174 | em28xx_qctrl[i].maximum) | ||
1175 | return -ERANGE; | ||
1176 | retval = em28xx_set_ctrl(dev, ctrl); | ||
1177 | mutex_unlock(&dev->lock); | ||
1178 | return retval; | ||
1179 | } | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | em28xx_i2c_call_clients(dev,cmd,arg); | ||
1184 | mutex_unlock(&dev->lock); | ||
1185 | return 0; | ||
1186 | } | ||
1187 | /* --- tuner ioctls ------------------------------------------ */ | ||
1188 | case VIDIOC_G_TUNER: | ||
1189 | { | ||
1190 | struct v4l2_tuner *t = arg; | ||
1191 | |||
1192 | if (0 != t->index) | ||
1193 | return -EINVAL; | ||
1194 | |||
1195 | memset(t, 0, sizeof(*t)); | ||
1196 | strcpy(t->name, "Tuner"); | ||
1197 | mutex_lock(&dev->lock); | ||
1198 | /* let clients fill in the remainder of this struct */ | ||
1199 | em28xx_i2c_call_clients(dev, cmd, t); | ||
1200 | mutex_unlock(&dev->lock); | ||
1201 | em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal, | ||
1202 | t->afc); | ||
1203 | return 0; | ||
1204 | } | ||
1205 | case VIDIOC_S_TUNER: | ||
1206 | { | ||
1207 | struct v4l2_tuner *t = arg; | ||
1208 | |||
1209 | if (0 != t->index) | ||
1210 | return -EINVAL; | ||
1211 | mutex_lock(&dev->lock); | ||
1212 | /* let clients handle this */ | ||
1213 | em28xx_i2c_call_clients(dev, cmd, t); | ||
1214 | mutex_unlock(&dev->lock); | ||
1215 | return 0; | ||
1216 | } | ||
1217 | case VIDIOC_G_FREQUENCY: | ||
1218 | { | ||
1219 | struct v4l2_frequency *f = arg; | ||
1220 | |||
1221 | memset(f, 0, sizeof(*f)); | ||
1222 | f->type = V4L2_TUNER_ANALOG_TV; | ||
1223 | f->frequency = dev->ctl_freq; | ||
1224 | |||
1225 | return 0; | ||
1226 | } | ||
1227 | case VIDIOC_S_FREQUENCY: | ||
1228 | { | ||
1229 | struct v4l2_frequency *f = arg; | ||
1230 | |||
1231 | if (0 != f->tuner) | ||
1232 | return -EINVAL; | ||
1233 | |||
1234 | if (V4L2_TUNER_ANALOG_TV != f->type) | ||
1235 | return -EINVAL; | ||
1236 | |||
1237 | mutex_lock(&dev->lock); | ||
1238 | dev->ctl_freq = f->frequency; | ||
1239 | em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); | ||
1240 | mutex_unlock(&dev->lock); | ||
1241 | return 0; | ||
1242 | } | ||
1243 | case VIDIOC_CROPCAP: | ||
1244 | { | ||
1245 | struct v4l2_cropcap *cc = arg; | ||
1246 | |||
1247 | if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1248 | return -EINVAL; | ||
1249 | cc->bounds.left = 0; | ||
1250 | cc->bounds.top = 0; | ||
1251 | cc->bounds.width = dev->width; | ||
1252 | cc->bounds.height = dev->height; | ||
1253 | cc->defrect = cc->bounds; | ||
1254 | cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */ | ||
1255 | cc->pixelaspect.denominator = 59; | ||
1256 | return 0; | ||
1257 | } | ||
1258 | case VIDIOC_STREAMON: | ||
1259 | { | ||
1260 | int *type = arg; | ||
1261 | |||
1262 | if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE | ||
1263 | || dev->io != IO_MMAP) | ||
1264 | return -EINVAL; | ||
1265 | |||
1266 | if (list_empty(&dev->inqueue)) | ||
1267 | return -EINVAL; | ||
1268 | |||
1269 | if (unlikely(res_get(fh) < 0)) | ||
1270 | return -EBUSY; | ||
1271 | |||
1272 | dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ | ||
1273 | |||
1274 | em28xx_videodbg("VIDIOC_STREAMON: starting stream\n"); | ||
1275 | |||
1276 | return 0; | ||
1277 | } | ||
1278 | case VIDIOC_STREAMOFF: | ||
1279 | { | ||
1280 | int *type = arg; | ||
1281 | int ret; | ||
1282 | |||
1283 | if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE | ||
1284 | || dev->io != IO_MMAP) | ||
1285 | return -EINVAL; | ||
1286 | |||
1287 | mutex_lock(&dev->lock); | ||
1288 | if (dev->stream == STREAM_ON) { | ||
1289 | em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream\n"); | ||
1290 | if ((ret = em28xx_stream_interrupt(dev))){ | ||
1291 | mutex_unlock(&dev->lock); | ||
1292 | return ret; | ||
1293 | } | ||
1294 | } | ||
1295 | |||
1296 | em28xx_empty_framequeues(dev); | ||
1297 | mutex_unlock(&dev->lock); | ||
1298 | |||
1299 | return 0; | ||
1300 | } | ||
1301 | default: | ||
1302 | return v4l_compat_translate_ioctl(inode, filp, cmd, arg, | ||
1303 | driver_ioctl); | ||
1304 | } | ||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | /* | ||
1309 | * em28xx_v4l2_do_ioctl() | ||
1310 | * This function is _not_ called directly, but from | ||
1311 | * em28xx_v4l2_ioctl. Userspace | ||
1312 | * copying is done already, arg is a kernel pointer. | ||
1313 | */ | ||
1314 | static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, | ||
1315 | unsigned int cmd, void *arg) | ||
1316 | { | ||
1317 | struct em28xx_fh *fh = filp->private_data; | ||
1318 | struct em28xx *dev = fh->dev; | ||
1319 | |||
1320 | if (!dev) | ||
1321 | return -ENODEV; | ||
1322 | |||
1323 | if (video_debug > 1) | ||
1324 | v4l_print_ioctl(dev->name,cmd); | ||
1325 | |||
1326 | switch (cmd) { | ||
1327 | |||
1328 | /* --- capabilities ------------------------------------------ */ | ||
1329 | case VIDIOC_QUERYCAP: | ||
1330 | { | ||
1331 | struct v4l2_capability *cap = arg; | ||
1332 | |||
1333 | memset(cap, 0, sizeof(*cap)); | ||
1334 | strlcpy(cap->driver, "em28xx", sizeof(cap->driver)); | ||
1335 | strlcpy(cap->card, em28xx_boards[dev->model].name, | ||
1336 | sizeof(cap->card)); | ||
1337 | strlcpy(cap->bus_info, dev->udev->dev.bus_id, | ||
1338 | sizeof(cap->bus_info)); | ||
1339 | cap->version = EM28XX_VERSION_CODE; | ||
1340 | cap->capabilities = | ||
1341 | V4L2_CAP_SLICED_VBI_CAPTURE | | ||
1342 | V4L2_CAP_VIDEO_CAPTURE | | ||
1343 | V4L2_CAP_AUDIO | | ||
1344 | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; | ||
1345 | if (dev->has_tuner) | ||
1346 | cap->capabilities |= V4L2_CAP_TUNER; | ||
1347 | return 0; | ||
1348 | } | ||
1349 | /* --- capture ioctls ---------------------------------------- */ | ||
1350 | case VIDIOC_ENUM_FMT: | ||
1351 | { | ||
1352 | struct v4l2_fmtdesc *fmtd = arg; | ||
1353 | |||
1354 | if (fmtd->index != 0) | ||
1355 | return -EINVAL; | ||
1356 | memset(fmtd, 0, sizeof(*fmtd)); | ||
1357 | fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1358 | strcpy(fmtd->description, "Packed YUY2"); | ||
1359 | fmtd->pixelformat = V4L2_PIX_FMT_YUYV; | ||
1360 | memset(fmtd->reserved, 0, sizeof(fmtd->reserved)); | ||
1361 | return 0; | ||
1362 | } | ||
1363 | case VIDIOC_G_FMT: | ||
1364 | { | ||
1365 | int retval; | ||
1366 | mutex_lock(&dev->lock); | ||
1367 | retval = em28xx_get_fmt(dev, (struct v4l2_format *) arg); | ||
1368 | mutex_unlock(&dev->lock); | ||
1369 | return retval; | ||
1370 | |||
1371 | } | ||
1372 | case VIDIOC_TRY_FMT: | ||
1373 | case VIDIOC_S_FMT: | ||
1374 | { | ||
1375 | int retval; | ||
1376 | mutex_lock(&dev->lock); | ||
1377 | retval = em28xx_set_fmt(dev, cmd, (struct v4l2_format *)arg); | ||
1378 | mutex_unlock(&dev->lock); | ||
1379 | return retval; | ||
1380 | } | ||
1381 | |||
1382 | case VIDIOC_REQBUFS: | ||
1383 | { | ||
1384 | struct v4l2_requestbuffers *rb = arg; | ||
1385 | u32 i; | ||
1386 | int ret; | ||
1387 | |||
1388 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
1389 | rb->memory != V4L2_MEMORY_MMAP) | ||
1390 | return -EINVAL; | ||
1391 | |||
1392 | if (dev->io == IO_READ) { | ||
1393 | em28xx_videodbg ("method is set to read;" | ||
1394 | " close and open the device again to" | ||
1395 | " choose the mmap I/O method\n"); | ||
1396 | return -EINVAL; | ||
1397 | } | ||
1398 | |||
1399 | for (i = 0; i < dev->num_frames; i++) | ||
1400 | if (dev->frame[i].vma_use_count) { | ||
1401 | em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped\n"); | ||
1402 | return -EINVAL; | ||
1403 | } | ||
1404 | |||
1405 | mutex_lock(&dev->lock); | ||
1406 | if (dev->stream == STREAM_ON) { | ||
1407 | em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n"); | ||
1408 | if ((ret = em28xx_stream_interrupt(dev))){ | ||
1409 | mutex_unlock(&dev->lock); | ||
1410 | return ret; | ||
1411 | } | ||
1412 | } | ||
1413 | |||
1414 | em28xx_empty_framequeues(dev); | ||
1415 | |||
1416 | em28xx_release_buffers(dev); | ||
1417 | if (rb->count) | ||
1418 | rb->count = | ||
1419 | em28xx_request_buffers(dev, rb->count); | ||
1420 | |||
1421 | dev->frame_current = NULL; | ||
1422 | |||
1423 | em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n", | ||
1424 | rb->count); | ||
1425 | dev->io = rb->count ? IO_MMAP : IO_NONE; | ||
1426 | mutex_unlock(&dev->lock); | ||
1427 | return 0; | ||
1428 | } | ||
1429 | case VIDIOC_QUERYBUF: | ||
1430 | { | ||
1431 | struct v4l2_buffer *b = arg; | ||
1432 | |||
1433 | if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
1434 | b->index >= dev->num_frames || dev->io != IO_MMAP) | ||
1435 | return -EINVAL; | ||
1436 | |||
1437 | memcpy(b, &dev->frame[b->index].buf, sizeof(*b)); | ||
1438 | |||
1439 | if (dev->frame[b->index].vma_use_count) { | ||
1440 | b->flags |= V4L2_BUF_FLAG_MAPPED; | ||
1441 | } | ||
1442 | if (dev->frame[b->index].state == F_DONE) | ||
1443 | b->flags |= V4L2_BUF_FLAG_DONE; | ||
1444 | else if (dev->frame[b->index].state != F_UNUSED) | ||
1445 | b->flags |= V4L2_BUF_FLAG_QUEUED; | ||
1446 | return 0; | ||
1447 | } | ||
1448 | case VIDIOC_QBUF: | ||
1449 | { | ||
1450 | struct v4l2_buffer *b = arg; | ||
1451 | unsigned long lock_flags; | ||
1452 | |||
1453 | if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
1454 | b->index >= dev->num_frames || dev->io != IO_MMAP) { | ||
1455 | return -EINVAL; | ||
1456 | } | ||
1457 | |||
1458 | if (dev->frame[b->index].state != F_UNUSED) { | ||
1459 | return -EAGAIN; | ||
1460 | } | ||
1461 | dev->frame[b->index].state = F_QUEUED; | ||
1462 | |||
1463 | /* add frame to fifo */ | ||
1464 | spin_lock_irqsave(&dev->queue_lock, lock_flags); | ||
1465 | list_add_tail(&dev->frame[b->index].frame, | ||
1466 | &dev->inqueue); | ||
1467 | spin_unlock_irqrestore(&dev->queue_lock, lock_flags); | ||
1468 | |||
1469 | return 0; | ||
1470 | } | ||
1471 | case VIDIOC_DQBUF: | ||
1472 | { | ||
1473 | struct v4l2_buffer *b = arg; | ||
1474 | struct em28xx_frame_t *f; | ||
1475 | unsigned long lock_flags; | ||
1476 | int ret = 0; | ||
1477 | |||
1478 | if (b->type != V4L2_BUF_TYPE_VIDEO_CAPTURE | ||
1479 | || dev->io != IO_MMAP) | ||
1480 | return -EINVAL; | ||
1481 | |||
1482 | if (list_empty(&dev->outqueue)) { | ||
1483 | if (dev->stream == STREAM_OFF) | ||
1484 | return -EINVAL; | ||
1485 | if (filp->f_flags & O_NONBLOCK) | ||
1486 | return -EAGAIN; | ||
1487 | ret = wait_event_interruptible | ||
1488 | (dev->wait_frame, | ||
1489 | (!list_empty(&dev->outqueue)) || | ||
1490 | (dev->state & DEV_DISCONNECTED)); | ||
1491 | if (ret) | ||
1492 | return ret; | ||
1493 | if (dev->state & DEV_DISCONNECTED) | ||
1494 | return -ENODEV; | ||
1495 | } | ||
1496 | |||
1497 | spin_lock_irqsave(&dev->queue_lock, lock_flags); | ||
1498 | f = list_entry(dev->outqueue.next, | ||
1499 | struct em28xx_frame_t, frame); | ||
1500 | list_del(dev->outqueue.next); | ||
1501 | spin_unlock_irqrestore(&dev->queue_lock, lock_flags); | ||
1502 | |||
1503 | f->state = F_UNUSED; | ||
1504 | memcpy(b, &f->buf, sizeof(*b)); | ||
1505 | |||
1506 | if (f->vma_use_count) | ||
1507 | b->flags |= V4L2_BUF_FLAG_MAPPED; | ||
1508 | |||
1509 | return 0; | ||
1510 | } | ||
1511 | default: | ||
1512 | return em28xx_do_ioctl(inode, filp, dev, cmd, arg, | ||
1513 | em28xx_video_do_ioctl); | ||
1514 | } | ||
1515 | return 0; | ||
1516 | } | ||
1517 | |||
1518 | /* | ||
1519 | * em28xx_v4l2_ioctl() | ||
1520 | * handle v4l2 ioctl the main action happens in em28xx_v4l2_do_ioctl() | ||
1521 | */ | ||
1522 | static int em28xx_v4l2_ioctl(struct inode *inode, struct file *filp, | ||
1523 | unsigned int cmd, unsigned long arg) | ||
1524 | { | ||
1525 | int ret = 0; | ||
1526 | struct em28xx_fh *fh = filp->private_data; | ||
1527 | struct em28xx *dev = fh->dev; | ||
1528 | |||
1529 | if (dev->state & DEV_DISCONNECTED) { | ||
1530 | em28xx_errdev("v4l2 ioctl: device not present\n"); | ||
1531 | return -ENODEV; | ||
1532 | } | ||
1533 | |||
1534 | if (dev->state & DEV_MISCONFIGURED) { | ||
1535 | em28xx_errdev | ||
1536 | ("v4l2 ioctl: device is misconfigured; close and open it again\n"); | ||
1537 | return -EIO; | ||
1538 | } | ||
1539 | |||
1540 | ret = video_usercopy(inode, filp, cmd, arg, em28xx_video_do_ioctl); | ||
1541 | |||
1542 | return ret; | ||
1543 | } | ||
1544 | |||
1545 | static const struct file_operations em28xx_v4l_fops = { | 1597 | static const struct file_operations em28xx_v4l_fops = { |
1546 | .owner = THIS_MODULE, | 1598 | .owner = THIS_MODULE, |
1547 | .open = em28xx_v4l2_open, | 1599 | .open = em28xx_v4l2_open, |
1548 | .release = em28xx_v4l2_close, | 1600 | .release = em28xx_v4l2_close, |
1549 | .ioctl = em28xx_v4l2_ioctl, | 1601 | .read = em28xx_v4l2_read, |
1550 | .read = em28xx_v4l2_read, | 1602 | .poll = em28xx_v4l2_poll, |
1551 | .poll = em28xx_v4l2_poll, | 1603 | .mmap = em28xx_v4l2_mmap, |
1552 | .mmap = em28xx_v4l2_mmap, | 1604 | .ioctl = video_ioctl2, |
1553 | .llseek = no_llseek, | 1605 | .llseek = no_llseek, |
1554 | .compat_ioctl = v4l_compat_ioctl32, | 1606 | .compat_ioctl = v4l_compat_ioctl32, |
1607 | }; | ||
1555 | 1608 | ||
1609 | static const struct video_device em28xx_video_template = { | ||
1610 | .fops = &em28xx_v4l_fops, | ||
1611 | .release = video_device_release, | ||
1612 | |||
1613 | .minor = -1, | ||
1614 | .vidioc_querycap = vidioc_querycap, | ||
1615 | .vidioc_enum_fmt_cap = vidioc_enum_fmt_cap, | ||
1616 | .vidioc_g_fmt_cap = vidioc_g_fmt_cap, | ||
1617 | .vidioc_try_fmt_cap = vidioc_try_fmt_cap, | ||
1618 | .vidioc_s_fmt_cap = vidioc_s_fmt_cap, | ||
1619 | .vidioc_g_audio = vidioc_g_audio, | ||
1620 | .vidioc_s_audio = vidioc_s_audio, | ||
1621 | .vidioc_cropcap = vidioc_cropcap, | ||
1622 | |||
1623 | .vidioc_g_fmt_vbi_capture = vidioc_g_fmt_vbi_capture, | ||
1624 | .vidioc_try_fmt_vbi_capture = vidioc_try_set_vbi_capture, | ||
1625 | .vidioc_s_fmt_vbi_capture = vidioc_try_set_vbi_capture, | ||
1626 | |||
1627 | .vidioc_reqbufs = vidioc_reqbufs, | ||
1628 | .vidioc_querybuf = vidioc_querybuf, | ||
1629 | .vidioc_qbuf = vidioc_qbuf, | ||
1630 | .vidioc_dqbuf = vidioc_dqbuf, | ||
1631 | .vidioc_s_std = vidioc_s_std, | ||
1632 | .vidioc_enum_input = vidioc_enum_input, | ||
1633 | .vidioc_g_input = vidioc_g_input, | ||
1634 | .vidioc_s_input = vidioc_s_input, | ||
1635 | .vidioc_queryctrl = vidioc_queryctrl, | ||
1636 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1637 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1638 | .vidioc_streamon = vidioc_streamon, | ||
1639 | .vidioc_streamoff = vidioc_streamoff, | ||
1640 | .vidioc_g_tuner = vidioc_g_tuner, | ||
1641 | .vidioc_s_tuner = vidioc_s_tuner, | ||
1642 | .vidioc_g_frequency = vidioc_g_frequency, | ||
1643 | .vidioc_s_frequency = vidioc_s_frequency, | ||
1644 | |||
1645 | .tvnorms = V4L2_STD_ALL, | ||
1646 | .current_norm = V4L2_STD_NTSC_M, | ||
1556 | }; | 1647 | }; |
1557 | 1648 | ||
1649 | |||
1558 | /******************************** usb interface *****************************************/ | 1650 | /******************************** usb interface *****************************************/ |
1559 | 1651 | ||
1560 | /* | 1652 | /* |
@@ -1639,7 +1731,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1639 | 1731 | ||
1640 | errCode = em28xx_config(dev); | 1732 | errCode = em28xx_config(dev); |
1641 | 1733 | ||
1642 | /* allocate and fill v4l2 device struct */ | 1734 | /* allocate and fill video video_device struct */ |
1643 | dev->vdev = video_device_alloc(); | 1735 | dev->vdev = video_device_alloc(); |
1644 | if (NULL == dev->vdev) { | 1736 | if (NULL == dev->vdev) { |
1645 | em28xx_errdev("cannot allocate video_device.\n"); | 1737 | em28xx_errdev("cannot allocate video_device.\n"); |
@@ -1647,7 +1739,17 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1647 | kfree(dev); | 1739 | kfree(dev); |
1648 | return -ENOMEM; | 1740 | return -ENOMEM; |
1649 | } | 1741 | } |
1742 | memcpy(dev->vdev, &em28xx_video_template, | ||
1743 | sizeof(em28xx_video_template)); | ||
1744 | dev->vdev->type = VID_TYPE_CAPTURE; | ||
1745 | if (dev->has_tuner) | ||
1746 | dev->vdev->type |= VID_TYPE_TUNER; | ||
1747 | dev->vdev->dev = &dev->udev->dev; | ||
1748 | snprintf(dev->vdev->name, sizeof(dev->vbi_dev->name), | ||
1749 | "%s#%d %s", "em28xx", dev->devno, "video"); | ||
1750 | dev->vdev->current_norm = dev->tvnorm->id; | ||
1650 | 1751 | ||
1752 | /* Allocate and fill vbi video_device struct */ | ||
1651 | dev->vbi_dev = video_device_alloc(); | 1753 | dev->vbi_dev = video_device_alloc(); |
1652 | if (NULL == dev->vbi_dev) { | 1754 | if (NULL == dev->vbi_dev) { |
1653 | em28xx_errdev("cannot allocate video_device.\n"); | 1755 | em28xx_errdev("cannot allocate video_device.\n"); |
@@ -1656,41 +1758,27 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1656 | kfree(dev); | 1758 | kfree(dev); |
1657 | return -ENOMEM; | 1759 | return -ENOMEM; |
1658 | } | 1760 | } |
1659 | 1761 | memcpy(dev->vbi_dev, &em28xx_video_template, | |
1660 | /* Fills VBI device info */ | 1762 | sizeof(em28xx_video_template)); |
1661 | dev->vbi_dev->type = VFL_TYPE_VBI; | 1763 | dev->vbi_dev->type = VFL_TYPE_VBI; |
1662 | dev->vbi_dev->fops = &em28xx_v4l_fops; | ||
1663 | dev->vbi_dev->minor = -1; | ||
1664 | dev->vbi_dev->dev = &dev->udev->dev; | 1764 | dev->vbi_dev->dev = &dev->udev->dev; |
1665 | dev->vbi_dev->release = video_device_release; | 1765 | snprintf(dev->vbi_dev->name, sizeof(dev->vbi_dev->name), |
1666 | snprintf(dev->vbi_dev->name, sizeof(dev->vbi_dev->name), "%s#%d %s", | 1766 | "%s#%d %s", "em28xx", dev->devno, "vbi"); |
1667 | "em28xx",dev->devno,"vbi"); | 1767 | dev->vbi_dev->current_norm = dev->tvnorm->id; |
1668 | |||
1669 | /* Fills CAPTURE device info */ | ||
1670 | dev->vdev->type = VID_TYPE_CAPTURE; | ||
1671 | if (dev->has_tuner) | ||
1672 | dev->vdev->type |= VID_TYPE_TUNER; | ||
1673 | dev->vdev->fops = &em28xx_v4l_fops; | ||
1674 | dev->vdev->minor = -1; | ||
1675 | dev->vdev->dev = &dev->udev->dev; | ||
1676 | dev->vdev->release = video_device_release; | ||
1677 | snprintf(dev->vdev->name, sizeof(dev->vbi_dev->name), "%s#%d %s", | ||
1678 | "em28xx",dev->devno,"video"); | ||
1679 | 1768 | ||
1680 | list_add_tail(&dev->devlist,&em28xx_devlist); | 1769 | list_add_tail(&dev->devlist,&em28xx_devlist); |
1681 | 1770 | ||
1682 | |||
1683 | if (dev->has_msp34xx) { | 1771 | if (dev->has_msp34xx) { |
1684 | /* Send a reset to other chips via gpio */ | 1772 | /* Send a reset to other chips via gpio */ |
1685 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); | 1773 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xf7", 1); |
1686 | msleep(3); | 1774 | msleep(3); |
1687 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1); | 1775 | em28xx_write_regs_req(dev, 0x00, 0x08, "\xff", 1); |
1688 | msleep(3); | 1776 | msleep(3); |
1689 | |||
1690 | } | 1777 | } |
1778 | |||
1691 | video_mux(dev, 0); | 1779 | video_mux(dev, 0); |
1692 | 1780 | ||
1693 | /* register v4l2 device */ | 1781 | /* register v4l2 video video_device */ |
1694 | if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, | 1782 | if ((retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, |
1695 | video_nr[dev->devno]))) { | 1783 | video_nr[dev->devno]))) { |
1696 | em28xx_errdev("unable to register video device (error=%i).\n", | 1784 | em28xx_errdev("unable to register video device (error=%i).\n", |
@@ -1703,6 +1791,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1703 | return -ENODEV; | 1791 | return -ENODEV; |
1704 | } | 1792 | } |
1705 | 1793 | ||
1794 | /* register v4l2 vbi video_device */ | ||
1706 | if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, | 1795 | if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, |
1707 | vbi_nr[dev->devno]) < 0) { | 1796 | vbi_nr[dev->devno]) < 0) { |
1708 | printk("unable to register vbi device\n"); | 1797 | printk("unable to register vbi device\n"); |
@@ -1713,8 +1802,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
1713 | em28xx_devused&=~(1<<dev->devno); | 1802 | em28xx_devused&=~(1<<dev->devno); |
1714 | kfree(dev); | 1803 | kfree(dev); |
1715 | return -ENODEV; | 1804 | return -ENODEV; |
1716 | } else { | ||
1717 | printk("registered VBI\n"); | ||
1718 | } | 1805 | } |
1719 | 1806 | ||
1720 | em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", | 1807 | em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", |