diff options
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 6 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 7 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 23 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 120 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-irq.c | 26 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-streams.c | 17 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-yuv.c | 58 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-yuv.h | 5 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtvfb.c | 4 |
9 files changed, 196 insertions, 70 deletions
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index e3020f456641..7c600d0f48cd 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -1117,6 +1117,12 @@ static int __devinit ivtv_probe(struct pci_dev *dev, | |||
1117 | itv->is_50hz = 1; | 1117 | itv->is_50hz = 1; |
1118 | itv->is_out_50hz = 1; | 1118 | itv->is_out_50hz = 1; |
1119 | } | 1119 | } |
1120 | |||
1121 | itv->yuv_info.osd_full_w = 720; | ||
1122 | itv->yuv_info.osd_full_h = itv->is_out_50hz ? 576 : 480; | ||
1123 | itv->yuv_info.v4l2_src_w = itv->yuv_info.osd_full_w; | ||
1124 | itv->yuv_info.v4l2_src_h = itv->yuv_info.osd_full_h; | ||
1125 | |||
1120 | itv->params.video_gop_size = itv->is_60hz ? 15 : 12; | 1126 | itv->params.video_gop_size = itv->is_60hz ? 15 : 12; |
1121 | 1127 | ||
1122 | itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000; | 1128 | itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000; |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 0e4ad29821e0..19a9b3bac190 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -466,6 +466,9 @@ struct yuv_playback_info | |||
466 | u32 osd_vis_w; | 466 | u32 osd_vis_w; |
467 | u32 osd_vis_h; | 467 | u32 osd_vis_h; |
468 | 468 | ||
469 | u32 osd_full_w; | ||
470 | u32 osd_full_h; | ||
471 | |||
469 | int decode_height; | 472 | int decode_height; |
470 | 473 | ||
471 | int lace_mode; | 474 | int lace_mode; |
@@ -491,6 +494,10 @@ struct yuv_playback_info | |||
491 | 494 | ||
492 | u8 draw_frame; /* PVR350 buffer to draw into */ | 495 | u8 draw_frame; /* PVR350 buffer to draw into */ |
493 | u8 max_frames_buffered; /* Maximum number of frames to buffer */ | 496 | u8 max_frames_buffered; /* Maximum number of frames to buffer */ |
497 | |||
498 | struct v4l2_rect main_rect; | ||
499 | u32 v4l2_src_w; | ||
500 | u32 v4l2_src_h; | ||
494 | }; | 501 | }; |
495 | 502 | ||
496 | #define IVTV_VBI_FRAMES 32 | 503 | #define IVTV_VBI_FRAMES 32 |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 58ad0d9c680a..6fb96f19a866 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -581,6 +581,24 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c | |||
581 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); | 581 | set_bit(IVTV_F_S_APPL_IO, &s->s_flags); |
582 | 582 | ||
583 | retry: | 583 | retry: |
584 | /* If possible, just DMA the entire frame - Check the data transfer size | ||
585 | since we may get here before the stream has been fully set-up */ | ||
586 | if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) { | ||
587 | while (count >= itv->dma_data_req_size) { | ||
588 | if (!ivtv_yuv_udma_stream_frame (itv, (void *)user_buf)) { | ||
589 | bytes_written += itv->dma_data_req_size; | ||
590 | user_buf += itv->dma_data_req_size; | ||
591 | count -= itv->dma_data_req_size; | ||
592 | } else { | ||
593 | break; | ||
594 | } | ||
595 | } | ||
596 | if (count == 0) { | ||
597 | IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); | ||
598 | return bytes_written; | ||
599 | } | ||
600 | } | ||
601 | |||
584 | for (;;) { | 602 | for (;;) { |
585 | /* Gather buffers */ | 603 | /* Gather buffers */ |
586 | while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_io))) | 604 | while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_io))) |
@@ -660,6 +678,9 @@ retry: | |||
660 | if (s->q_full.length >= itv->dma_data_req_size) { | 678 | if (s->q_full.length >= itv->dma_data_req_size) { |
661 | int got_sig; | 679 | int got_sig; |
662 | 680 | ||
681 | if (mode == OUT_YUV) | ||
682 | ivtv_yuv_setup_stream_frame(itv); | ||
683 | |||
663 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); | 684 | prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); |
664 | while (!(got_sig = signal_pending(current)) && | 685 | while (!(got_sig = signal_pending(current)) && |
665 | test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { | 686 | test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { |
@@ -946,7 +967,7 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) | |||
946 | set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); | 967 | set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); |
947 | /* For yuv, we need to know the dma size before we start */ | 968 | /* For yuv, we need to know the dma size before we start */ |
948 | itv->dma_data_req_size = | 969 | itv->dma_data_req_size = |
949 | itv->params.width * itv->params.height * 3 / 2; | 970 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); |
950 | itv->yuv_info.stream_size = 0; | 971 | itv->yuv_info.stream_size = 0; |
951 | } | 972 | } |
952 | return 0; | 973 | return 0; |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index fd6826f472e3..57eb8dfe53fa 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -372,7 +372,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm | |||
372 | fmt->fmt.pix.height = itv->main_rect.height; | 372 | fmt->fmt.pix.height = itv->main_rect.height; |
373 | fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 373 | fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
374 | fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; | 374 | fmt->fmt.pix.field = V4L2_FIELD_INTERLACED; |
375 | if (itv->output_mode == OUT_UDMA_YUV) { | 375 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { |
376 | switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) { | 376 | switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) { |
377 | case IVTV_YUV_MODE_INTERLACED: | 377 | case IVTV_YUV_MODE_INTERLACED: |
378 | fmt->fmt.pix.field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ? | 378 | fmt->fmt.pix.field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ? |
@@ -386,14 +386,13 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm | |||
386 | break; | 386 | break; |
387 | } | 387 | } |
388 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; | 388 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; |
389 | fmt->fmt.pix.bytesperline = 720; | ||
390 | fmt->fmt.pix.width = itv->yuv_info.v4l2_src_w; | ||
391 | fmt->fmt.pix.height = itv->yuv_info.v4l2_src_h; | ||
389 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ | 392 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ |
390 | fmt->fmt.pix.sizeimage = | 393 | fmt->fmt.pix.sizeimage = |
391 | fmt->fmt.pix.height * fmt->fmt.pix.width + | 394 | 1080 * ((fmt->fmt.pix.height + 31) & ~31); |
392 | fmt->fmt.pix.height * (fmt->fmt.pix.width / 2); | 395 | } else if (streamtype == IVTV_ENC_STREAM_TYPE_YUV) { |
393 | } | ||
394 | else if (itv->output_mode == OUT_YUV || | ||
395 | streamtype == IVTV_ENC_STREAM_TYPE_YUV || | ||
396 | streamtype == IVTV_DEC_STREAM_TYPE_YUV) { | ||
397 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; | 396 | fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12; |
398 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ | 397 | /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ |
399 | fmt->fmt.pix.sizeimage = | 398 | fmt->fmt.pix.sizeimage = |
@@ -490,6 +489,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm | |||
490 | static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, | 489 | static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, |
491 | struct v4l2_format *fmt, int set_fmt) | 490 | struct v4l2_format *fmt, int set_fmt) |
492 | { | 491 | { |
492 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
493 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; | 493 | struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; |
494 | u16 set; | 494 | u16 set; |
495 | 495 | ||
@@ -505,39 +505,52 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, | |||
505 | r.width = fmt->fmt.pix.width; | 505 | r.width = fmt->fmt.pix.width; |
506 | r.height = fmt->fmt.pix.height; | 506 | r.height = fmt->fmt.pix.height; |
507 | ivtv_get_fmt(itv, streamtype, fmt); | 507 | ivtv_get_fmt(itv, streamtype, fmt); |
508 | if (itv->output_mode != OUT_UDMA_YUV) { | 508 | fmt->fmt.pix.width = r.width; |
509 | /* TODO: would setting the rect also be valid for this mode? */ | 509 | fmt->fmt.pix.height = r.height; |
510 | fmt->fmt.pix.width = r.width; | 510 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { |
511 | fmt->fmt.pix.height = r.height; | ||
512 | } | ||
513 | if (itv->output_mode == OUT_UDMA_YUV) { | ||
514 | /* TODO: add checks for validity */ | ||
515 | fmt->fmt.pix.field = field; | 511 | fmt->fmt.pix.field = field; |
512 | if (fmt->fmt.pix.width < 2) | ||
513 | fmt->fmt.pix.width = 2; | ||
514 | if (fmt->fmt.pix.width > 720) | ||
515 | fmt->fmt.pix.width = 720; | ||
516 | if (fmt->fmt.pix.height < 2) | ||
517 | fmt->fmt.pix.height = 2; | ||
518 | if (fmt->fmt.pix.height > 576) | ||
519 | fmt->fmt.pix.height = 576; | ||
516 | } | 520 | } |
517 | if (set_fmt) { | 521 | if (set_fmt && streamtype == IVTV_DEC_STREAM_TYPE_YUV) { |
518 | if (itv->output_mode == OUT_UDMA_YUV) { | 522 | /* Return now if we already have some frame data */ |
519 | switch (field) { | 523 | if (yi->stream_size) |
520 | case V4L2_FIELD_NONE: | 524 | return -EBUSY; |
521 | itv->yuv_info.lace_mode = IVTV_YUV_MODE_PROGRESSIVE; | ||
522 | break; | ||
523 | case V4L2_FIELD_ANY: | ||
524 | itv->yuv_info.lace_mode = IVTV_YUV_MODE_AUTO; | ||
525 | break; | ||
526 | case V4L2_FIELD_INTERLACED_BT: | ||
527 | itv->yuv_info.lace_mode = | ||
528 | IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD; | ||
529 | break; | ||
530 | case V4L2_FIELD_INTERLACED_TB: | ||
531 | default: | ||
532 | itv->yuv_info.lace_mode = IVTV_YUV_MODE_INTERLACED; | ||
533 | break; | ||
534 | } | ||
535 | itv->yuv_info.lace_sync_field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1; | ||
536 | 525 | ||
537 | /* Force update of yuv registers */ | 526 | yi->v4l2_src_w = r.width; |
538 | itv->yuv_info.yuv_forced_update = 1; | 527 | yi->v4l2_src_h = r.height; |
539 | return 0; | 528 | |
529 | switch (field) { | ||
530 | case V4L2_FIELD_NONE: | ||
531 | yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE; | ||
532 | break; | ||
533 | case V4L2_FIELD_ANY: | ||
534 | yi->lace_mode = IVTV_YUV_MODE_AUTO; | ||
535 | break; | ||
536 | case V4L2_FIELD_INTERLACED_BT: | ||
537 | yi->lace_mode = | ||
538 | IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD; | ||
539 | break; | ||
540 | case V4L2_FIELD_INTERLACED_TB: | ||
541 | default: | ||
542 | yi->lace_mode = IVTV_YUV_MODE_INTERLACED; | ||
543 | break; | ||
540 | } | 544 | } |
545 | yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1; | ||
546 | |||
547 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) | ||
548 | itv->dma_data_req_size = | ||
549 | 1080 * ((yi->v4l2_src_h + 31) & ~31); | ||
550 | |||
551 | /* Force update of yuv registers */ | ||
552 | yi->yuv_forced_update = 1; | ||
553 | return 0; | ||
541 | } | 554 | } |
542 | return 0; | 555 | return 0; |
543 | } | 556 | } |
@@ -703,8 +716,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
703 | { | 716 | { |
704 | struct ivtv_open_id *id = NULL; | 717 | struct ivtv_open_id *id = NULL; |
705 | u32 data[CX2341X_MBOX_MAX_DATA]; | 718 | u32 data[CX2341X_MBOX_MAX_DATA]; |
719 | int streamtype = 0; | ||
706 | 720 | ||
707 | if (filp) id = (struct ivtv_open_id *)filp->private_data; | 721 | if (filp) { |
722 | id = (struct ivtv_open_id *)filp->private_data; | ||
723 | streamtype = id->type; | ||
724 | } | ||
708 | 725 | ||
709 | switch (cmd) { | 726 | switch (cmd) { |
710 | case VIDIOC_G_PRIORITY: | 727 | case VIDIOC_G_PRIORITY: |
@@ -822,6 +839,11 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
822 | cropcap->bounds.height = itv->is_50hz ? 576 : 480; | 839 | cropcap->bounds.height = itv->is_50hz ? 576 : 480; |
823 | cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; | 840 | cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; |
824 | cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; | 841 | cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; |
842 | } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { | ||
843 | cropcap->bounds.width = itv->yuv_info.osd_full_w; | ||
844 | cropcap->bounds.height = itv->yuv_info.osd_full_h; | ||
845 | cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; | ||
846 | cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; | ||
825 | } else { | 847 | } else { |
826 | cropcap->bounds.height = itv->is_out_50hz ? 576 : 480; | 848 | cropcap->bounds.height = itv->is_out_50hz ? 576 : 480; |
827 | cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; | 849 | cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; |
@@ -836,10 +858,15 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
836 | 858 | ||
837 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && | 859 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && |
838 | (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { | 860 | (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { |
839 | if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, | 861 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { |
840 | crop->c.width, crop->c.height, crop->c.left, crop->c.top)) { | 862 | itv->yuv_info.main_rect = crop->c; |
841 | itv->main_rect = crop->c; | ||
842 | return 0; | 863 | return 0; |
864 | } else { | ||
865 | if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, | ||
866 | crop->c.width, crop->c.height, crop->c.left, crop->c.top)) { | ||
867 | itv->main_rect = crop->c; | ||
868 | return 0; | ||
869 | } | ||
843 | } | 870 | } |
844 | return -EINVAL; | 871 | return -EINVAL; |
845 | } | 872 | } |
@@ -853,7 +880,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
853 | 880 | ||
854 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && | 881 | if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && |
855 | (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { | 882 | (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { |
856 | crop->c = itv->main_rect; | 883 | if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) |
884 | crop->c = itv->yuv_info.main_rect; | ||
885 | else | ||
886 | crop->c = itv->main_rect; | ||
857 | return 0; | 887 | return 0; |
858 | } | 888 | } |
859 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 889 | if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
@@ -864,7 +894,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
864 | case VIDIOC_ENUM_FMT: { | 894 | case VIDIOC_ENUM_FMT: { |
865 | static struct v4l2_fmtdesc formats[] = { | 895 | static struct v4l2_fmtdesc formats[] = { |
866 | { 0, 0, 0, | 896 | { 0, 0, 0, |
867 | "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, | 897 | "HM12 (YUV 4:2:2)", V4L2_PIX_FMT_HM12, |
868 | { 0, 0, 0, 0 } | 898 | { 0, 0, 0, 0 } |
869 | }, | 899 | }, |
870 | { 1, 0, V4L2_FMT_FLAG_COMPRESSED, | 900 | { 1, 0, V4L2_FMT_FLAG_COMPRESSED, |
@@ -1043,6 +1073,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1043 | itv->main_rect.height = itv->params.height; | 1073 | itv->main_rect.height = itv->params.height; |
1044 | ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, | 1074 | ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, |
1045 | 720, itv->main_rect.height, 0, 0); | 1075 | 720, itv->main_rect.height, 0, 0); |
1076 | itv->yuv_info.main_rect = itv->main_rect; | ||
1077 | if (!itv->osd_info) { | ||
1078 | itv->yuv_info.osd_full_w = 720; | ||
1079 | itv->yuv_info.osd_full_h = | ||
1080 | itv->is_out_50hz ? 576 : 480; | ||
1081 | } | ||
1046 | } | 1082 | } |
1047 | break; | 1083 | break; |
1048 | } | 1084 | } |
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index dd0dd8d126de..ebc200320e6f 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -302,8 +302,11 @@ static void dma_post(struct ivtv_stream *s) | |||
302 | void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) | 302 | void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) |
303 | { | 303 | { |
304 | struct ivtv *itv = s->itv; | 304 | struct ivtv *itv = s->itv; |
305 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
306 | u8 frame = yi->draw_frame; | ||
307 | struct yuv_frame_info *f = &yi->new_frame_info[frame]; | ||
305 | struct ivtv_buffer *buf; | 308 | struct ivtv_buffer *buf; |
306 | u32 y_size = itv->params.height * itv->params.width; | 309 | u32 y_size = 720 * ((f->src_h + 31) & ~31); |
307 | u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET; | 310 | u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET; |
308 | int y_done = 0; | 311 | int y_done = 0; |
309 | int bytes_written = 0; | 312 | int bytes_written = 0; |
@@ -311,6 +314,18 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) | |||
311 | int idx = 0; | 314 | int idx = 0; |
312 | 315 | ||
313 | IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); | 316 | IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); |
317 | |||
318 | /* Insert buffer block for YUV if needed */ | ||
319 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) { | ||
320 | if (yi->blanking_dmaptr) { | ||
321 | s->sg_pending[idx].src = yi->blanking_dmaptr; | ||
322 | s->sg_pending[idx].dst = offset; | ||
323 | s->sg_pending[idx].size = 720 * 16; | ||
324 | } | ||
325 | offset += 720 * 16; | ||
326 | idx++; | ||
327 | } | ||
328 | |||
314 | list_for_each_entry(buf, &s->q_predma.list, list) { | 329 | list_for_each_entry(buf, &s->q_predma.list, list) { |
315 | /* YUV UV Offset from Y Buffer */ | 330 | /* YUV UV Offset from Y Buffer */ |
316 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done && | 331 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done && |
@@ -713,8 +728,11 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) | |||
713 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); | 728 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); |
714 | 729 | ||
715 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { | 730 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { |
716 | itv->dma_data_req_size = itv->params.width * itv->params.height * 3 / 2; | 731 | itv->dma_data_req_size = |
717 | itv->dma_data_req_offset = data[1] ? data[1] : yuv_offset[0]; | 732 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); |
733 | itv->dma_data_req_offset = data[1]; | ||
734 | if (atomic_read(&itv->yuv_info.next_dma_frame) >= 0) | ||
735 | ivtv_yuv_frame_complete(itv); | ||
718 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; | 736 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; |
719 | } | 737 | } |
720 | else { | 738 | else { |
@@ -728,6 +746,8 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) | |||
728 | set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | 746 | set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); |
729 | } | 747 | } |
730 | else { | 748 | else { |
749 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) | ||
750 | ivtv_yuv_setup_stream_frame(itv); | ||
731 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | 751 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); |
732 | ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size); | 752 | ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size); |
733 | ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0); | 753 | ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0); |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index a5bfbd98a490..3ca2a1a62a71 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -661,27 +661,12 @@ int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) | |||
661 | 661 | ||
662 | IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset); | 662 | IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset); |
663 | 663 | ||
664 | /* Clear Streamoff */ | ||
665 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV) { | ||
666 | /* Initialize Decoder */ | ||
667 | /* Reprogram Decoder YUV Buffers for YUV */ | ||
668 | write_reg(yuv_offset[0] >> 4, 0x82c); | ||
669 | write_reg((yuv_offset[0] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); | ||
670 | write_reg(yuv_offset[0] >> 4, 0x834); | ||
671 | write_reg((yuv_offset[0] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); | ||
672 | |||
673 | write_reg_sync(0x00000000 | (0x0c << 16) | (0x0b << 8), 0x2d24); | ||
674 | |||
675 | write_reg_sync(0x00108080, 0x2898); | ||
676 | /* Enable YUV decoder output */ | ||
677 | write_reg_sync(0x01, IVTV_REG_VDM); | ||
678 | } | ||
679 | |||
680 | ivtv_setup_v4l2_decode_stream(s); | 664 | ivtv_setup_v4l2_decode_stream(s); |
681 | 665 | ||
682 | /* set dma size to 65536 bytes */ | 666 | /* set dma size to 65536 bytes */ |
683 | ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536); | 667 | ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536); |
684 | 668 | ||
669 | /* Clear Streamoff */ | ||
685 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); | 670 | clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); |
686 | 671 | ||
687 | /* Zero out decoder counters */ | 672 | /* Zero out decoder counters */ |
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index cd42db9b5a15..711ce5b5a20f 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c | |||
@@ -1035,17 +1035,11 @@ void ivtv_yuv_frame_complete(struct ivtv *itv) | |||
1035 | (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS); | 1035 | (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS); |
1036 | } | 1036 | } |
1037 | 1037 | ||
1038 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | 1038 | int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) |
1039 | { | 1039 | { |
1040 | DEFINE_WAIT(wait); | 1040 | DEFINE_WAIT(wait); |
1041 | int rc = 0; | 1041 | int rc = 0; |
1042 | int got_sig = 0; | 1042 | int got_sig = 0; |
1043 | |||
1044 | IVTV_DEBUG_INFO("yuv_prep_frame\n"); | ||
1045 | |||
1046 | ivtv_yuv_next_free(itv); | ||
1047 | ivtv_yuv_setup_frame(itv, args); | ||
1048 | |||
1049 | /* DMA the frame */ | 1043 | /* DMA the frame */ |
1050 | mutex_lock(&itv->udma.lock); | 1044 | mutex_lock(&itv->udma.lock); |
1051 | 1045 | ||
@@ -1084,6 +1078,56 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | |||
1084 | return rc; | 1078 | return rc; |
1085 | } | 1079 | } |
1086 | 1080 | ||
1081 | /* Setup frame according to V4L2 parameters */ | ||
1082 | void ivtv_yuv_setup_stream_frame(struct ivtv *itv) | ||
1083 | { | ||
1084 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
1085 | struct ivtv_dma_frame dma_args; | ||
1086 | |||
1087 | ivtv_yuv_next_free(itv); | ||
1088 | |||
1089 | /* Copy V4L2 parameters to an ivtv_dma_frame struct... */ | ||
1090 | dma_args.y_source = 0L; | ||
1091 | dma_args.uv_source = 0L; | ||
1092 | dma_args.src.left = 0; | ||
1093 | dma_args.src.top = 0; | ||
1094 | dma_args.src.width = yi->v4l2_src_w; | ||
1095 | dma_args.src.height = yi->v4l2_src_h; | ||
1096 | dma_args.dst = yi->main_rect; | ||
1097 | dma_args.src_width = yi->v4l2_src_w; | ||
1098 | dma_args.src_height = yi->v4l2_src_h; | ||
1099 | |||
1100 | /* ... and use the same setup routine as ivtv_yuv_prep_frame */ | ||
1101 | ivtv_yuv_setup_frame(itv, &dma_args); | ||
1102 | |||
1103 | if (!itv->dma_data_req_offset) | ||
1104 | itv->dma_data_req_offset = yuv_offset[yi->draw_frame]; | ||
1105 | } | ||
1106 | |||
1107 | /* Attempt to dma a frame from a user buffer */ | ||
1108 | int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src) | ||
1109 | { | ||
1110 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
1111 | struct ivtv_dma_frame dma_args; | ||
1112 | |||
1113 | ivtv_yuv_setup_stream_frame(itv); | ||
1114 | |||
1115 | /* We only need to supply source addresses for this */ | ||
1116 | dma_args.y_source = src; | ||
1117 | dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31); | ||
1118 | return ivtv_yuv_udma_frame(itv, &dma_args); | ||
1119 | } | ||
1120 | |||
1121 | /* IVTV_IOC_DMA_FRAME ioctl handler */ | ||
1122 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) | ||
1123 | { | ||
1124 | IVTV_DEBUG_INFO("yuv_prep_frame\n"); | ||
1125 | |||
1126 | ivtv_yuv_next_free(itv); | ||
1127 | ivtv_yuv_setup_frame(itv, args); | ||
1128 | return ivtv_yuv_udma_frame(itv, args); | ||
1129 | } | ||
1130 | |||
1087 | void ivtv_yuv_close(struct ivtv *itv) | 1131 | void ivtv_yuv_close(struct ivtv *itv) |
1088 | { | 1132 | { |
1089 | int h_filter, v_filter_1, v_filter_2; | 1133 | int h_filter, v_filter_1, v_filter_2; |
diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h index 3b290927d367..2fe5f1250762 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.h +++ b/drivers/media/video/ivtv/ivtv-yuv.h | |||
@@ -34,8 +34,11 @@ | |||
34 | extern const u32 yuv_offset[IVTV_YUV_BUFFERS]; | 34 | extern const u32 yuv_offset[IVTV_YUV_BUFFERS]; |
35 | 35 | ||
36 | int ivtv_yuv_filter_check(struct ivtv *itv); | 36 | int ivtv_yuv_filter_check(struct ivtv *itv); |
37 | void ivtv_yuv_setup_stream_frame(struct ivtv *itv); | ||
38 | int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src); | ||
39 | void ivtv_yuv_frame_complete(struct ivtv *itv); | ||
37 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); | 40 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); |
38 | void ivtv_yuv_close(struct ivtv *itv); | 41 | void ivtv_yuv_close(struct ivtv *itv); |
39 | void ivtv_yuv_work_handler (struct ivtv *itv); | 42 | void ivtv_yuv_work_handler(struct ivtv *itv); |
40 | 43 | ||
41 | #endif | 44 | #endif |
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index 52ffd154a3d8..1a73038ea811 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c | |||
@@ -504,6 +504,10 @@ static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var) | |||
504 | 504 | ||
505 | ivtvfb_set_display_window(itv, &ivtv_window); | 505 | ivtvfb_set_display_window(itv, &ivtv_window); |
506 | 506 | ||
507 | /* Pass screen size back to yuv handler */ | ||
508 | itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride; | ||
509 | itv->yuv_info.osd_full_h = ivtv_osd.lines; | ||
510 | |||
507 | /* Force update of yuv registers */ | 511 | /* Force update of yuv registers */ |
508 | itv->yuv_info.yuv_forced_update = 1; | 512 | itv->yuv_info.yuv_forced_update = 1; |
509 | 513 | ||