Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=c240ad00af78228726e6301ad6ffc54d3adce2a0
Commit:     c240ad00af78228726e6301ad6ffc54d3adce2a0
Parent:     9de982d3117a3f83e4e7b14016a1df25b4a693d6
Author:     Ian Armstrong <[EMAIL PROTECTED]>
AuthorDate: Tue Oct 16 03:21:46 2007 -0300
Committer:  Mauro Carvalho Chehab <[EMAIL PROTECTED]>
CommitDate: Fri Jan 25 19:03:09 2008 -0200

    V4L/DVB (6712): ivtv: ivtv yuv stream handling change
    
    Currently the yuv output stream buffer is divided into blocks whose size
    depend on the broadcast standard selected during the driver init phase.
    However, the standard can be changed after the init phase. This effectively
    breaks the yuv output stream handler, since it relies on the different yuv
    planes being block aligned.
    
    This patch changes the setup, so that the block size is always the same. The
    decoder dma function has been modified to cope with the fact that the second
    yuv plane may no longer be block aligned. The start of the yuv frame must
    still be at the beginning of a block, so the stream write function has also
    been modified to ensure this is always true.
    
    Also, the stream write function will now initiate a yuv dma transfer as soon
    as a full frame is ready. It will not wait until the current write request
    has completed, or the stream buffer becomes full.
    
    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  |    8 ++------
 drivers/media/video/ivtv/ivtv-driver.h  |    2 ++
 drivers/media/video/ivtv/ivtv-fileops.c |   31 +++++++++++++++++++++++++++----
 drivers/media/video/ivtv/ivtv-irq.c     |   25 +++++++++++++++++++------
 4 files changed, 50 insertions(+), 16 deletions(-)

diff --git a/drivers/media/video/ivtv/ivtv-driver.c 
b/drivers/media/video/ivtv/ivtv-driver.c
index 04179b7..48db22c 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -970,7 +970,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
                                const struct pci_device_id *pci_id)
 {
        int retval = 0;
-       int yuv_buf_size;
        int vbi_buf_size;
        struct ivtv *itv;
 
@@ -1122,11 +1121,8 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
        itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000;
        itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200;
        itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_MPG] = 0x10000;
-
-       /* 0x15180 == 720 * 480 / 4, 0x19500 == 720 * 576 / 4 */
-       yuv_buf_size = itv->is_60hz ? 0x15180 : 0x19500;
-       itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_YUV] = yuv_buf_size / 2;
-       itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_YUV] = yuv_buf_size / 8;
+       itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_YUV] = 0x10000;
+       itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_YUV] = 0x08000;
 
        /* Setup VBI Raw Size. Should be big enough to hold PAL.
           It is possible to switch between PAL and NTSC, so we need to
diff --git a/drivers/media/video/ivtv/ivtv-driver.h 
b/drivers/media/video/ivtv/ivtv-driver.h
index 49ce14d..b6dd236 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -485,6 +485,8 @@ struct yuv_playback_info
 
        void *blanking_ptr;
        dma_addr_t blanking_dmaptr;
+
+       int stream_size;
 };
 
 #define IVTV_VBI_FRAMES 32
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c 
b/drivers/media/video/ivtv/ivtv-fileops.c
index a200a8a..58ad0d9 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -542,6 +542,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char 
__user *user_buf, size_t c
        struct ivtv_open_id *id = filp->private_data;
        struct ivtv *itv = id->itv;
        struct ivtv_stream *s = &itv->streams[id->type];
+       struct yuv_playback_info *yi = &itv->yuv_info;
        struct ivtv_buffer *buf;
        struct ivtv_queue q;
        int bytes_written = 0;
@@ -604,9 +605,16 @@ retry:
 
        /* copy user data into buffers */
        while ((buf = ivtv_dequeue(s, &q))) {
-               /* Make sure we really got all the user data */
-               rc = ivtv_buf_copy_from_user(s, buf, user_buf, count);
+               /* yuv is a pain. Don't copy more data than needed for a single
+                  frame, otherwise we lose sync with the incoming stream */
+               if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
+                   yi->stream_size + count > itv->dma_data_req_size)
+                       rc  = ivtv_buf_copy_from_user(s, buf, user_buf,
+                               itv->dma_data_req_size - yi->stream_size);
+               else
+                       rc = ivtv_buf_copy_from_user(s, buf, user_buf, count);
 
+               /* Make sure we really got all the user data */
                if (rc < 0) {
                        ivtv_queue_move(s, &q, NULL, &s->q_free, 0);
                        return rc;
@@ -615,6 +623,16 @@ retry:
                count -= rc;
                bytes_written += rc;
 
+               if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
+                       yi->stream_size += rc;
+                       /* If we have a complete yuv frame, break loop now */
+                       if (yi->stream_size == itv->dma_data_req_size) {
+                               ivtv_enqueue(s, buf, &s->q_full);
+                               yi->stream_size = 0;
+                               break;
+                       }
+               }
+
                if (buf->bytesused != s->buf_size) {
                        /* incomplete, leave in q_io for next time */
                        ivtv_enqueue(s, buf, &s->q_io);
@@ -922,10 +940,15 @@ static int ivtv_serialized_open(struct ivtv_stream *s, 
struct file *filp)
        }
 
        /* YUV or MPG Decoding Mode? */
-       if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
+       if (s->type == IVTV_DEC_STREAM_TYPE_MPG) {
                clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
-       else if (s->type == IVTV_DEC_STREAM_TYPE_YUV)
+       } else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
                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;
+               itv->yuv_info.stream_size = 0;
+       }
        return 0;
 }
 
diff --git a/drivers/media/video/ivtv/ivtv-irq.c 
b/drivers/media/video/ivtv/ivtv-irq.c
index fd1688e..bcf1c85 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -313,15 +313,28 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, 
u32 offset, int lock)
        IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, 
s->q_predma.bytesused, offset);
        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 && 
bytes_written >= y_size) {
+               if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done &&
+                               (bytes_written + buf->bytesused) >= y_size) {
+                       s->sg_pending[idx].src = buf->dma_handle;
+                       s->sg_pending[idx].dst = offset;
+                       s->sg_pending[idx].size = y_size - bytes_written;
                        offset = uv_offset;
+                       if (s->sg_pending[idx].size != buf->bytesused) {
+                               idx++;
+                               s->sg_pending[idx].src =
+                                 buf->dma_handle + s->sg_pending[idx - 1].size;
+                               s->sg_pending[idx].dst = offset;
+                               s->sg_pending[idx].size =
+                                  buf->bytesused - s->sg_pending[idx - 1].size;
+                               offset += s->sg_pending[idx].size;
+                       }
                        y_done = 1;
+               } else {
+                       s->sg_pending[idx].src = buf->dma_handle;
+                       s->sg_pending[idx].dst = offset;
+                       s->sg_pending[idx].size = buf->bytesused;
+                       offset += buf->bytesused;
                }
-               s->sg_pending[idx].src = buf->dma_handle;
-               s->sg_pending[idx].dst = offset;
-               s->sg_pending[idx].size = buf->bytesused;
-
-               offset += buf->bytesused;
                bytes_written += buf->bytesused;
 
                /* Sync SG buffers */
-
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