Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=77aded6ba51f01335840ce8e18b413067810b68e
Commit:     77aded6ba51f01335840ce8e18b413067810b68e
Parent:     3b5c1c8e71eb8fe2297a5884db59108e3c8b44c5
Author:     Ian Armstrong <[EMAIL PROTECTED]>
AuthorDate: Mon Nov 5 14:27:09 2007 -0300
Committer:  Mauro Carvalho Chehab <[EMAIL PROTECTED]>
CommitDate: Fri Jan 25 19:03:11 2008 -0200

    V4L/DVB (6717): ivtv: Initial merge of video48 yuv handling into the 
IVTV_IOC_DMA_FRAME framework
    
    Previously, all yuv data written to /dev/video48 had only basic support with
    no double buffering to avoid display tearing.
    
    With this patch, yuv frames written to video48 are now handled by the 
existing
    IVTV_IOC_DMA_FRAME framework. As such, the frames are hardware buffered to
    avoid tearing, and honour scaling mode & field order options. Unlike the
    proprietary IVTV_IOC_DMA_FRAME ioctl, all parameters are controlled by the
    V4L2 API.
    
    Due to mpeg & yuv output restrictions being different, their V4L2 output
    controls have been separated. To control the yuv output, the V4L2 calls must
    be done via video48.
    
    If the ivtvfb module is loaded, there will be one side effect to this merge.
    The yuv output window will be constrained to the visible framebuffer area. 
In
    the event that a virtual framebuffer size is being used, the limit to the
    output size will be the virtual dimensions, but only the portion that falls
    within the currently visible area of the framebuffer will be shown.
    
    Like the IVTV_IOC_DMA_FRAME ioctl, the supplied frames must be padded to 720
    pixels wide. However the height must only be padded up the nearest multiple
    of 32. This would mean an image of 102 lines must be padded to 128. As long
    as the true source image size is given, the padding will not be visible in
    the final output.
    
    Signed-off-by: Ian Armstrong <[EMAIL PROTECTED]>
    Signed-off-by: Hans Verkuil <[EMAIL PROTECTED]>
    Signed-off-by: Mauro Carvalho Chehab <[EMAIL PROTECTED]>
---
 drivers/media/video/ivtv/ivtv-driver.c  |    6 ++
 drivers/media/video/ivtv/ivtv-driver.h  |    7 ++
 drivers/media/video/ivtv/ivtv-fileops.c |   23 ++++++-
 drivers/media/video/ivtv/ivtv-ioctl.c   |  120 ++++++++++++++++++++-----------
 drivers/media/video/ivtv/ivtv-irq.c     |   26 ++++++-
 drivers/media/video/ivtv/ivtv-streams.c |   17 +----
 drivers/media/video/ivtv/ivtv-yuv.c     |   58 +++++++++++++--
 drivers/media/video/ivtv/ivtv-yuv.h     |    5 +-
 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 e3020f4..7c600d0 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,
                itv->is_50hz = 1;
                itv->is_out_50hz = 1;
        }
+
+       itv->yuv_info.osd_full_w = 720;
+       itv->yuv_info.osd_full_h = itv->is_out_50hz ? 576 : 480;
+       itv->yuv_info.v4l2_src_w = itv->yuv_info.osd_full_w;
+       itv->yuv_info.v4l2_src_h = itv->yuv_info.osd_full_h;
+
        itv->params.video_gop_size = itv->is_60hz ? 15 : 12;
 
        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 0e4ad29..19a9b3b 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
        u32 osd_vis_w;
        u32 osd_vis_h;
 
+       u32 osd_full_w;
+       u32 osd_full_h;
+
        int decode_height;
 
        int lace_mode;
@@ -491,6 +494,10 @@ struct yuv_playback_info
 
        u8 draw_frame; /* PVR350 buffer to draw into */
        u8 max_frames_buffered; /* Maximum number of frames to buffer */
+
+       struct v4l2_rect main_rect;
+       u32 v4l2_src_w;
+       u32 v4l2_src_h;
 };
 
 #define IVTV_VBI_FRAMES 32
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c 
b/drivers/media/video/ivtv/ivtv-fileops.c
index 58ad0d9..6fb96f1 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
        set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
 
 retry:
+       /* If possible, just DMA the entire frame - Check the data transfer size
+       since we may get here before the stream has been fully set-up */
+       if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) 
{
+               while (count >= itv->dma_data_req_size) {
+                       if (!ivtv_yuv_udma_stream_frame (itv, (void 
*)user_buf)) {
+                               bytes_written += itv->dma_data_req_size;
+                               user_buf += itv->dma_data_req_size;
+                               count -= itv->dma_data_req_size;
+                       } else {
+                               break;
+                       }
+               }
+               if (count == 0) {
+                       IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", 
bytes_written, s->name, s->q_full.bytesused);
+                       return bytes_written;
+               }
+       }
+
        for (;;) {
                /* Gather buffers */
                while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, 
&s->q_io)))
@@ -660,6 +678,9 @@ retry:
                if (s->q_full.length >= itv->dma_data_req_size) {
                        int got_sig;
 
+                       if (mode == OUT_YUV)
+                               ivtv_yuv_setup_stream_frame(itv);
+
                        prepare_to_wait(&itv->dma_waitq, &wait, 
TASK_INTERRUPTIBLE);
                        while (!(got_sig = signal_pending(current)) &&
                                        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)
                set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
                /* For yuv, we need to know the dma size before we start */
                itv->dma_data_req_size =
-                               itv->params.width * itv->params.height * 3 / 2;
+                               1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
                itv->yuv_info.stream_size = 0;
        }
        return 0;
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c 
b/drivers/media/video/ivtv/ivtv-ioctl.c
index fd6826f..57eb8df 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
                fmt->fmt.pix.height = itv->main_rect.height;
                fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
                fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
-               if (itv->output_mode == OUT_UDMA_YUV) {
+               if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
                        switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
                        case IVTV_YUV_MODE_INTERLACED:
                                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
                                break;
                        }
                        fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
+                       fmt->fmt.pix.bytesperline = 720;
+                       fmt->fmt.pix.width = itv->yuv_info.v4l2_src_w;
+                       fmt->fmt.pix.height = itv->yuv_info.v4l2_src_h;
                        /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
                        fmt->fmt.pix.sizeimage =
-                               fmt->fmt.pix.height * fmt->fmt.pix.width +
-                               fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
-               }
-               else if (itv->output_mode == OUT_YUV ||
-                               streamtype == IVTV_ENC_STREAM_TYPE_YUV ||
-                               streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+                               1080 * ((fmt->fmt.pix.height + 31) & ~31);
+               } else if (streamtype == IVTV_ENC_STREAM_TYPE_YUV) {
                        fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
                        /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
                        fmt->fmt.pix.sizeimage =
@@ -490,6 +489,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, 
struct v4l2_format *fm
 static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
                struct v4l2_format *fmt, int set_fmt)
 {
+       struct yuv_playback_info *yi = &itv->yuv_info;
        struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
        u16 set;
 
@@ -505,39 +505,52 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int 
streamtype,
                r.width = fmt->fmt.pix.width;
                r.height = fmt->fmt.pix.height;
                ivtv_get_fmt(itv, streamtype, fmt);
-               if (itv->output_mode != OUT_UDMA_YUV) {
-                       /* TODO: would setting the rect also be valid for this 
mode? */
-                       fmt->fmt.pix.width = r.width;
-                       fmt->fmt.pix.height = r.height;
-               }
-               if (itv->output_mode == OUT_UDMA_YUV) {
-                       /* TODO: add checks for validity */
+               fmt->fmt.pix.width = r.width;
+               fmt->fmt.pix.height = r.height;
+               if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
                        fmt->fmt.pix.field = field;
+                       if (fmt->fmt.pix.width < 2)
+                               fmt->fmt.pix.width = 2;
+                       if (fmt->fmt.pix.width > 720)
+                               fmt->fmt.pix.width = 720;
+                       if (fmt->fmt.pix.height < 2)
+                               fmt->fmt.pix.height = 2;
+                       if (fmt->fmt.pix.height > 576)
+                               fmt->fmt.pix.height = 576;
                }
-               if (set_fmt) {
-                       if (itv->output_mode == OUT_UDMA_YUV) {
-                               switch (field) {
-                               case V4L2_FIELD_NONE:
-                                       itv->yuv_info.lace_mode = 
IVTV_YUV_MODE_PROGRESSIVE;
-                                       break;
-                               case V4L2_FIELD_ANY:
-                                       itv->yuv_info.lace_mode = 
IVTV_YUV_MODE_AUTO;
-                                       break;
-                               case V4L2_FIELD_INTERLACED_BT:
-                                       itv->yuv_info.lace_mode =
-                                               
IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
-                                       break;
-                               case V4L2_FIELD_INTERLACED_TB:
-                               default:
-                                       itv->yuv_info.lace_mode = 
IVTV_YUV_MODE_INTERLACED;
-                                       break;
-                               }
-                               itv->yuv_info.lace_sync_field = 
(itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
+               if (set_fmt && streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+                       /* Return now if we already have some frame data */
+                       if (yi->stream_size)
+                               return -EBUSY;
 
-                               /* Force update of yuv registers */
-                               itv->yuv_info.yuv_forced_update = 1;
-                               return 0;
+                       yi->v4l2_src_w = r.width;
+                       yi->v4l2_src_h = r.height;
+
+                       switch (field) {
+                       case V4L2_FIELD_NONE:
+                               yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
+                               break;
+                       case V4L2_FIELD_ANY:
+                               yi->lace_mode = IVTV_YUV_MODE_AUTO;
+                               break;
+                       case V4L2_FIELD_INTERLACED_BT:
+                               yi->lace_mode =
+                                    IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
+                               break;
+                       case V4L2_FIELD_INTERLACED_TB:
+                       default:
+                               yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
+                               break;
                        }
+                       yi->lace_sync_field = (yi->lace_mode & 
IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
+
+                       if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
+                               itv->dma_data_req_size =
+                                          1080 * ((yi->v4l2_src_h + 31) & ~31);
+
+                       /* Force update of yuv registers */
+                       yi->yuv_forced_update = 1;
+                       return 0;
                }
                return 0;
        }
@@ -703,8 +716,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, 
unsigned int cmd, void
 {
        struct ivtv_open_id *id = NULL;
        u32 data[CX2341X_MBOX_MAX_DATA];
+       int streamtype = 0;
 
-       if (filp) id = (struct ivtv_open_id *)filp->private_data;
+       if (filp) {
+               id = (struct ivtv_open_id *)filp->private_data;
+               streamtype = id->type;
+       }
 
        switch (cmd) {
        case VIDIOC_G_PRIORITY:
@@ -822,6 +839,11 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, 
unsigned int cmd, void
                        cropcap->bounds.height = itv->is_50hz ? 576 : 480;
                        cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
                        cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 
11;
+               } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+                       cropcap->bounds.width = itv->yuv_info.osd_full_w;
+                       cropcap->bounds.height = itv->yuv_info.osd_full_h;
+                       cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 
: 10;
+                       cropcap->pixelaspect.denominator = itv->is_out_50hz ? 
54 : 11;
                } else {
                        cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
                        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
 
                if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
                    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
-                       if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 
4,
-                                crop->c.width, crop->c.height, crop->c.left, 
crop->c.top)) {
-                               itv->main_rect = crop->c;
+                       if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+                               itv->yuv_info.main_rect = crop->c;
                                return 0;
+                       } else {
+                               if (!ivtv_vapi(itv, 
CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+                                       crop->c.width, crop->c.height, 
crop->c.left, crop->c.top)) {
+                                       itv->main_rect = crop->c;
+                                       return 0;
+                               }
                        }
                        return -EINVAL;
                }
@@ -853,7 +880,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, 
unsigned int cmd, void
 
                if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
                    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
-                       crop->c = itv->main_rect;
+                       if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
+                               crop->c = itv->yuv_info.main_rect;
+                       else
+                               crop->c = itv->main_rect;
                        return 0;
                }
                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
        case VIDIOC_ENUM_FMT: {
                static struct v4l2_fmtdesc formats[] = {
                        { 0, 0, 0,
-                         "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12,
+                         "HM12 (YUV 4:2:2)", V4L2_PIX_FMT_HM12,
                          { 0, 0, 0, 0 }
                        },
                        { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
@@ -1043,6 +1073,12 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file 
*filp, unsigned int cmd, void
                        itv->main_rect.height = itv->params.height;
                        ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
                                720, itv->main_rect.height, 0, 0);
+                       itv->yuv_info.main_rect = itv->main_rect;
+                       if (!itv->osd_info) {
+                               itv->yuv_info.osd_full_w = 720;
+                               itv->yuv_info.osd_full_h =
+                                               itv->is_out_50hz ? 576 : 480;
+                       }
                }
                break;
        }
diff --git a/drivers/media/video/ivtv/ivtv-irq.c 
b/drivers/media/video/ivtv/ivtv-irq.c
index dd0dd8d..ebc2003 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)
 void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
 {
        struct ivtv *itv = s->itv;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       u8 frame = yi->draw_frame;
+       struct yuv_frame_info *f = &yi->new_frame_info[frame];
        struct ivtv_buffer *buf;
-       u32 y_size = itv->params.height * itv->params.width;
+       u32 y_size = 720 * ((f->src_h + 31) & ~31);
        u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET;
        int y_done = 0;
        int bytes_written = 0;
@@ -311,6 +314,18 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, 
u32 offset, int lock)
        int idx = 0;
 
        IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, 
s->q_predma.bytesused, offset);
+
+       /* Insert buffer block for YUV if needed */
+       if (s->type == IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) {
+               if (yi->blanking_dmaptr) {
+                       s->sg_pending[idx].src = yi->blanking_dmaptr;
+                       s->sg_pending[idx].dst = offset;
+                       s->sg_pending[idx].size = 720 * 16;
+               }
+               offset += 720 * 16;
+               idx++;
+       }
+
        list_for_each_entry(buf, &s->q_predma.list, list) {
                /* YUV UV Offset from Y Buffer */
                if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done &&
@@ -713,8 +728,11 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv)
        ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data);
 
        if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) {
-               itv->dma_data_req_size = itv->params.width * itv->params.height 
* 3 / 2;
-               itv->dma_data_req_offset = data[1] ? data[1] : yuv_offset[0];
+               itv->dma_data_req_size =
+                                1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
+               itv->dma_data_req_offset = data[1];
+               if (atomic_read(&itv->yuv_info.next_dma_frame) >= 0)
+                       ivtv_yuv_frame_complete(itv);
                s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
        }
        else {
@@ -728,6 +746,8 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv)
                set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
        }
        else {
+               if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
+                       ivtv_yuv_setup_stream_frame(itv);
                clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
                ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, 
itv->dma_data_req_size);
                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 a5bfbd9..3ca2a1a 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)
 
        IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, 
gop_offset);
 
-       /* Clear Streamoff */
-       if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
-               /* Initialize Decoder */
-               /* Reprogram Decoder YUV Buffers for YUV */
-               write_reg(yuv_offset[0] >> 4, 0x82c);
-               write_reg((yuv_offset[0] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 
0x830);
-               write_reg(yuv_offset[0] >> 4, 0x834);
-               write_reg((yuv_offset[0] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 
0x838);
-
-               write_reg_sync(0x00000000 | (0x0c << 16) | (0x0b << 8), 0x2d24);
-
-               write_reg_sync(0x00108080, 0x2898);
-               /* Enable YUV decoder output */
-               write_reg_sync(0x01, IVTV_REG_VDM);
-       }
-
        ivtv_setup_v4l2_decode_stream(s);
 
        /* set dma size to 65536 bytes */
        ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536);
 
+       /* Clear Streamoff */
        clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
 
        /* Zero out decoder counters */
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c 
b/drivers/media/video/ivtv/ivtv-yuv.c
index cd42db9..711ce5b 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)
                        (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
 }
 
-int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
 {
        DEFINE_WAIT(wait);
        int rc = 0;
        int got_sig = 0;
-
-       IVTV_DEBUG_INFO("yuv_prep_frame\n");
-
-       ivtv_yuv_next_free(itv);
-       ivtv_yuv_setup_frame(itv, args);
-
        /* DMA the frame */
        mutex_lock(&itv->udma.lock);
 
@@ -1084,6 +1078,56 @@ int ivtv_yuv_prep_frame(struct ivtv *itv, struct 
ivtv_dma_frame *args)
        return rc;
 }
 
+/* Setup frame according to V4L2 parameters */
+void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       struct ivtv_dma_frame dma_args;
+
+       ivtv_yuv_next_free(itv);
+
+       /* Copy V4L2 parameters to an ivtv_dma_frame struct... */
+       dma_args.y_source = 0L;
+       dma_args.uv_source = 0L;
+       dma_args.src.left = 0;
+       dma_args.src.top = 0;
+       dma_args.src.width = yi->v4l2_src_w;
+       dma_args.src.height = yi->v4l2_src_h;
+       dma_args.dst = yi->main_rect;
+       dma_args.src_width = yi->v4l2_src_w;
+       dma_args.src_height = yi->v4l2_src_h;
+
+       /* ... and use the same setup routine as ivtv_yuv_prep_frame */
+       ivtv_yuv_setup_frame(itv, &dma_args);
+
+       if (!itv->dma_data_req_offset)
+               itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
+}
+
+/* Attempt to dma a frame from a user buffer */
+int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       struct ivtv_dma_frame dma_args;
+
+       ivtv_yuv_setup_stream_frame(itv);
+
+       /* We only need to supply source addresses for this */
+       dma_args.y_source = src;
+       dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
+       return ivtv_yuv_udma_frame(itv, &dma_args);
+}
+
+/* IVTV_IOC_DMA_FRAME ioctl handler */
+int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+{
+       IVTV_DEBUG_INFO("yuv_prep_frame\n");
+
+       ivtv_yuv_next_free(itv);
+       ivtv_yuv_setup_frame(itv, args);
+       return ivtv_yuv_udma_frame(itv, args);
+}
+
 void ivtv_yuv_close(struct ivtv *itv)
 {
        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 3b29092..2fe5f12 100644
--- a/drivers/media/video/ivtv/ivtv-yuv.h
+++ b/drivers/media/video/ivtv/ivtv-yuv.h
@@ -34,8 +34,11 @@
 extern const u32 yuv_offset[IVTV_YUV_BUFFERS];
 
 int ivtv_yuv_filter_check(struct ivtv *itv);
+void ivtv_yuv_setup_stream_frame(struct ivtv *itv);
+int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src);
+void ivtv_yuv_frame_complete(struct ivtv *itv);
 int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args);
 void ivtv_yuv_close(struct ivtv *itv);
-void ivtv_yuv_work_handler (struct ivtv *itv);
+void ivtv_yuv_work_handler(struct ivtv *itv);
 
 #endif
diff --git a/drivers/media/video/ivtv/ivtvfb.c 
b/drivers/media/video/ivtv/ivtvfb.c
index 52ffd15..1a73038 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)
 
        ivtvfb_set_display_window(itv, &ivtv_window);
 
+       /* Pass screen size back to yuv handler */
+       itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
+       itv->yuv_info.osd_full_h = ivtv_osd.lines;
+
        /* Force update of yuv registers */
        itv->yuv_info.yuv_forced_update = 1;
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to