aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c6
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h7
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c23
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c120
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c26
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c17
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.c58
-rw-r--r--drivers/media/video/ivtv/ivtv-yuv.h5
-rw-r--r--drivers/media/video/ivtv/ivtvfb.c4
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
583retry: 583retry:
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
490static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, 489static 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)
302void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) 302void 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
1038int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) 1038int 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 */
1082void 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 */
1108int 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 */
1122int 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
1087void ivtv_yuv_close(struct ivtv *itv) 1131void 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 @@
34extern const u32 yuv_offset[IVTV_YUV_BUFFERS]; 34extern const u32 yuv_offset[IVTV_YUV_BUFFERS];
35 35
36int ivtv_yuv_filter_check(struct ivtv *itv); 36int ivtv_yuv_filter_check(struct ivtv *itv);
37void ivtv_yuv_setup_stream_frame(struct ivtv *itv);
38int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src);
39void ivtv_yuv_frame_complete(struct ivtv *itv);
37int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); 40int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args);
38void ivtv_yuv_close(struct ivtv *itv); 41void ivtv_yuv_close(struct ivtv *itv);
39void ivtv_yuv_work_handler (struct ivtv *itv); 42void 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