aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-video.c
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2009-09-01 00:19:46 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-18 22:47:40 -0400
commitda52a55cff643b8e0b346b9894adf5b93946040d (patch)
tree3cc434722b23e5fcc748de24f37054030ef90e8d /drivers/media/video/em28xx/em28xx-video.c
parent206313db83641022c5ee213ac5f619973a9b427b (diff)
V4L/DVB (12741): em28xx: make video isoc stream work when VBI is enabled
Add code enabling the VBI registers for variants of the em28xx chip that support VBI, and make sure the isoc streaming code continues to work for the video component of the stream (note the video and vbi data arrive intermixed on the same isoc pipe). Note that this version just drops the actual VBI data onto the floor as opposed to processing it. The "#ifdef 0" tags are for the videobuf code that appears in the next patch in this series. We created a separate version of the isoc_copy version for parsing the version of the stream that includes VBI data. In theory, they might be able to be merged at some point in the future, but the initial goal is to ensure that we do not cause any regressions with devices that do not have VBI support. This work was sponsored by EyeMagnet Limited. Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c127
1 files changed, 123 insertions, 4 deletions
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 }