aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c44
-rw-r--r--drivers/media/video/em28xx/em28xx-reg.h4
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c127
-rw-r--r--drivers/media/video/em28xx/em28xx.h7
4 files changed, 173 insertions, 9 deletions
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 98e140b5d95e..d4107f6933f8 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -54,6 +54,10 @@ static int alt = EM28XX_PINOUT;
54module_param(alt, int, 0644); 54module_param(alt, int, 0644);
55MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); 55MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
56 56
57static unsigned int disable_vbi;
58module_param(disable_vbi, int, 0644);
59MODULE_PARM_DESC(disable_vbi, "disable vbi support");
60
57/* FIXME */ 61/* FIXME */
58#define em28xx_isocdbg(fmt, arg...) do {\ 62#define em28xx_isocdbg(fmt, arg...) do {\
59 if (core_debug) \ 63 if (core_debug) \
@@ -648,9 +652,24 @@ int em28xx_capture_start(struct em28xx *dev, int start)
648 return rc; 652 return rc;
649} 653}
650 654
655int em28xx_vbi_supported(struct em28xx *dev)
656{
657 /* Modprobe option to manually disable */
658 if (disable_vbi == 1)
659 return 0;
660
661 if (dev->chip_id == CHIP_ID_EM2860 ||
662 dev->chip_id == CHIP_ID_EM2883)
663 return 1;
664
665 /* Version of em28xx that does not support VBI */
666 return 0;
667}
668
651int em28xx_set_outfmt(struct em28xx *dev) 669int em28xx_set_outfmt(struct em28xx *dev)
652{ 670{
653 int ret; 671 int ret;
672 u8 vinctrl;
654 673
655 ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT, 674 ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
656 dev->format->reg | 0x20, 0xff); 675 dev->format->reg | 0x20, 0xff);
@@ -661,7 +680,16 @@ int em28xx_set_outfmt(struct em28xx *dev)
661 if (ret < 0) 680 if (ret < 0)
662 return ret; 681 return ret;
663 682
664 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, dev->vinctl); 683 vinctrl = dev->vinctl;
684 if (em28xx_vbi_supported(dev) == 1) {
685 vinctrl |= EM28XX_VINCTRL_VBI_RAW;
686 em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
687 em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
688 em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, 0xb4);
689 em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, 0x0c);
690 }
691
692 return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
665} 693}
666 694
667static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, 695static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
@@ -732,7 +760,14 @@ int em28xx_resolution_set(struct em28xx *dev)
732 760
733 761
734 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2); 762 em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
735 em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2); 763
764 /* If we don't set the start position to 4 in VBI mode, we end up
765 with line 21 being YUYV encoded instead of being in 8-bit
766 greyscale */
767 if (em28xx_vbi_supported(dev) == 1)
768 em28xx_capture_area_set(dev, 0, 4, width >> 2, height >> 2);
769 else
770 em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);
736 771
737 return em28xx_scaler_set(dev, dev->hscale, dev->vscale); 772 return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
738} 773}
@@ -844,8 +879,7 @@ EXPORT_SYMBOL_GPL(em28xx_set_mode);
844 */ 879 */
845static void em28xx_irq_callback(struct urb *urb) 880static void em28xx_irq_callback(struct urb *urb)
846{ 881{
847 struct em28xx_dmaqueue *dma_q = urb->context; 882 struct em28xx *dev = urb->context;
848 struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
849 int rc, i; 883 int rc, i;
850 884
851 switch (urb->status) { 885 switch (urb->status) {
@@ -994,7 +1028,7 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets,
994 1028
995 usb_fill_int_urb(urb, dev->udev, pipe, 1029 usb_fill_int_urb(urb, dev->udev, pipe,
996 dev->isoc_ctl.transfer_buffer[i], sb_size, 1030 dev->isoc_ctl.transfer_buffer[i], sb_size,
997 em28xx_irq_callback, dma_q, 1); 1031 em28xx_irq_callback, dev, 1);
998 1032
999 urb->number_of_packets = max_packets; 1033 urb->number_of_packets = max_packets;
1000 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; 1034 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h
index 3bf69f9ec375..ed12e7ffcbd0 100644
--- a/drivers/media/video/em28xx/em28xx-reg.h
+++ b/drivers/media/video/em28xx/em28xx-reg.h
@@ -147,6 +147,10 @@
147#define EM28XX_R31_HSCALEHIGH 0x31 147#define EM28XX_R31_HSCALEHIGH 0x31
148#define EM28XX_R32_VSCALELOW 0x32 148#define EM28XX_R32_VSCALELOW 0x32
149#define EM28XX_R33_VSCALEHIGH 0x33 149#define EM28XX_R33_VSCALEHIGH 0x33
150#define EM28XX_R34_VBI_START_H 0x34
151#define EM28XX_R35_VBI_START_V 0x35
152#define EM28XX_R36_VBI_WIDTH 0x36
153#define EM28XX_R37_VBI_HEIGHT 0x37
150 154
151#define EM28XX_R40_AC97LSB 0x40 155#define EM28XX_R40_AC97LSB 0x40
152#define EM28XX_R41_AC97MSB 0x41 156#define EM28XX_R41_AC97MSB 0x41
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index a6bdbc21410e..04c9ecc3c22a 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -329,7 +329,7 @@ static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
329static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) 329static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
330{ 330{
331 struct em28xx_buffer *buf; 331 struct em28xx_buffer *buf;
332 struct em28xx_dmaqueue *dma_q = urb->context; 332 struct em28xx_dmaqueue *dma_q = &dev->vidq;
333 unsigned char *outp = NULL; 333 unsigned char *outp = NULL;
334 int i, len = 0, rc = 1; 334 int i, len = 0, rc = 1;
335 unsigned char *p; 335 unsigned char *p;
@@ -410,6 +410,118 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
410 return rc; 410 return rc;
411} 411}
412 412
413/* Version of isoc handler that takes into account a mixture of video and
414 VBI data */
415static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb)
416{
417 struct em28xx_buffer *buf, *vbi_buf;
418 struct em28xx_dmaqueue *dma_q = &dev->vidq;
419 unsigned char *outp = NULL;
420 unsigned char *vbioutp = NULL;
421 int i, len = 0, rc = 1;
422 unsigned char *p;
423 int vbi_size;
424
425 if (!dev)
426 return 0;
427
428 if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
429 return 0;
430
431 if (urb->status < 0) {
432 print_err_status(dev, -1, urb->status);
433 if (urb->status == -ENOENT)
434 return 0;
435 }
436
437 buf = dev->isoc_ctl.buf;
438 if (buf != NULL)
439 outp = videobuf_to_vmalloc(&buf->vb);
440 for (i = 0; i < urb->number_of_packets; i++) {
441 int status = urb->iso_frame_desc[i].status;
442
443 if (status < 0) {
444 print_err_status(dev, i, status);
445 if (urb->iso_frame_desc[i].status != -EPROTO)
446 continue;
447 }
448
449 len = urb->iso_frame_desc[i].actual_length - 4;
450
451 if (urb->iso_frame_desc[i].actual_length <= 0) {
452 /* em28xx_isocdbg("packet %d is empty",i); - spammy */
453 continue;
454 }
455 if (urb->iso_frame_desc[i].actual_length >
456 dev->max_pkt_size) {
457 em28xx_isocdbg("packet bigger than packet size");
458 continue;
459 }
460
461 p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
462
463 /* capture type 0 = vbi start
464 capture type 1 = video start
465 capture type 2 = video in progress */
466 if (p[0] == 0x33 && p[1] == 0x95) {
467 dev->capture_type = 0;
468 dev->vbi_read = 0;
469 em28xx_isocdbg("VBI START HEADER!!!\n");
470 dev->cur_field = p[2];
471 }
472
473 /* FIXME: get rid of hard-coded value */
474 vbi_size = 720 * 0x0c;
475
476 if (dev->capture_type == 0) {
477 if (dev->vbi_read >= vbi_size) {
478 /* We've already read all the VBI data, so
479 treat the rest as video */
480 printk("djh c should never happen\n");
481 } else if ((dev->vbi_read + len) < vbi_size) {
482 /* This entire frame is VBI data */
483 dev->vbi_read += len;
484 } else {
485 /* Some of this frame is VBI data and some is
486 video data */
487 int vbi_data_len = vbi_size - dev->vbi_read;
488 dev->vbi_read += vbi_data_len;
489 dev->capture_type = 1;
490 p += vbi_data_len;
491 len -= vbi_data_len;
492 }
493 }
494
495 if (dev->capture_type == 1) {
496 dev->capture_type = 2;
497 em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
498 len, (p[2] & 1) ? "odd" : "even");
499
500 if (dev->progressive || !(dev->cur_field & 1)) {
501 if (buf != NULL)
502 buffer_filled(dev, dma_q, buf);
503 get_next_buf(dma_q, &buf);
504 if (buf == NULL)
505 outp = NULL;
506 else
507 outp = videobuf_to_vmalloc(&buf->vb);
508 }
509 if (buf != NULL) {
510 if (dev->cur_field & 1)
511 buf->top_field = 0;
512 else
513 buf->top_field = 1;
514 }
515
516 dma_q->pos = 0;
517 }
518 if (buf != NULL && dev->capture_type == 2)
519 em28xx_copy_video(dev, dma_q, buf, p, outp, len);
520 }
521 return rc;
522}
523
524
413/* ------------------------------------------------------------------ 525/* ------------------------------------------------------------------
414 Videobuf operations 526 Videobuf operations
415 ------------------------------------------------------------------*/ 527 ------------------------------------------------------------------*/
@@ -494,9 +606,16 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
494 urb_init = 1; 606 urb_init = 1;
495 607
496 if (urb_init) { 608 if (urb_init) {
497 rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS, 609 if (em28xx_vbi_supported(dev) == 1)
498 EM28XX_NUM_BUFS, dev->max_pkt_size, 610 rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
499 em28xx_isoc_copy); 611 EM28XX_NUM_BUFS,
612 dev->max_pkt_size,
613 em28xx_isoc_copy_vbi);
614 else
615 rc = em28xx_init_isoc(dev, EM28XX_NUM_PACKETS,
616 EM28XX_NUM_BUFS,
617 dev->max_pkt_size,
618 em28xx_isoc_copy);
500 if (rc < 0) 619 if (rc < 0)
501 goto fail; 620 goto fail;
502 } 621 }
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 0f2ba9a40d17..1656d2cf34a9 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -544,6 +544,12 @@ struct em28xx {
544 enum em28xx_dev_state state; 544 enum em28xx_dev_state state;
545 enum em28xx_io_method io; 545 enum em28xx_io_method io;
546 546
547 /* vbi related state tracking */
548 int capture_type;
549 int vbi_read;
550 unsigned char cur_field;
551
552
547 struct work_struct request_module_wk; 553 struct work_struct request_module_wk;
548 554
549 /* locks */ 555 /* locks */
@@ -639,6 +645,7 @@ int em28xx_audio_setup(struct em28xx *dev);
639 645
640int em28xx_colorlevels_set_default(struct em28xx *dev); 646int em28xx_colorlevels_set_default(struct em28xx *dev);
641int em28xx_capture_start(struct em28xx *dev, int start); 647int em28xx_capture_start(struct em28xx *dev, int start);
648int em28xx_vbi_supported(struct em28xx *dev);
642int em28xx_set_outfmt(struct em28xx *dev); 649int em28xx_set_outfmt(struct em28xx *dev);
643int em28xx_resolution_set(struct em28xx *dev); 650int em28xx_resolution_set(struct em28xx *dev);
644int em28xx_set_alternate(struct em28xx *dev); 651int em28xx_set_alternate(struct em28xx *dev);