aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv/ivtv-fileops.c
diff options
context:
space:
mode:
authorIan Armstrong <ian@iarmst.demon.co.uk>2007-10-16 02:21:46 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:03:09 -0500
commitc240ad00af78228726e6301ad6ffc54d3adce2a0 (patch)
tree5dbb5b9336a2ed515987f30f9618101a720caa56 /drivers/media/video/ivtv/ivtv-fileops.c
parent9de982d3117a3f83e4e7b14016a1df25b4a693d6 (diff)
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 <ian@iarmst.demon.co.uk> Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-fileops.c')
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index a200a8a95a2d..58ad0d9c680a 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
542 struct ivtv_open_id *id = filp->private_data; 542 struct ivtv_open_id *id = filp->private_data;
543 struct ivtv *itv = id->itv; 543 struct ivtv *itv = id->itv;
544 struct ivtv_stream *s = &itv->streams[id->type]; 544 struct ivtv_stream *s = &itv->streams[id->type];
545 struct yuv_playback_info *yi = &itv->yuv_info;
545 struct ivtv_buffer *buf; 546 struct ivtv_buffer *buf;
546 struct ivtv_queue q; 547 struct ivtv_queue q;
547 int bytes_written = 0; 548 int bytes_written = 0;
@@ -604,9 +605,16 @@ retry:
604 605
605 /* copy user data into buffers */ 606 /* copy user data into buffers */
606 while ((buf = ivtv_dequeue(s, &q))) { 607 while ((buf = ivtv_dequeue(s, &q))) {
607 /* Make sure we really got all the user data */ 608 /* yuv is a pain. Don't copy more data than needed for a single
608 rc = ivtv_buf_copy_from_user(s, buf, user_buf, count); 609 frame, otherwise we lose sync with the incoming stream */
610 if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
611 yi->stream_size + count > itv->dma_data_req_size)
612 rc = ivtv_buf_copy_from_user(s, buf, user_buf,
613 itv->dma_data_req_size - yi->stream_size);
614 else
615 rc = ivtv_buf_copy_from_user(s, buf, user_buf, count);
609 616
617 /* Make sure we really got all the user data */
610 if (rc < 0) { 618 if (rc < 0) {
611 ivtv_queue_move(s, &q, NULL, &s->q_free, 0); 619 ivtv_queue_move(s, &q, NULL, &s->q_free, 0);
612 return rc; 620 return rc;
@@ -615,6 +623,16 @@ retry:
615 count -= rc; 623 count -= rc;
616 bytes_written += rc; 624 bytes_written += rc;
617 625
626 if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
627 yi->stream_size += rc;
628 /* If we have a complete yuv frame, break loop now */
629 if (yi->stream_size == itv->dma_data_req_size) {
630 ivtv_enqueue(s, buf, &s->q_full);
631 yi->stream_size = 0;
632 break;
633 }
634 }
635
618 if (buf->bytesused != s->buf_size) { 636 if (buf->bytesused != s->buf_size) {
619 /* incomplete, leave in q_io for next time */ 637 /* incomplete, leave in q_io for next time */
620 ivtv_enqueue(s, buf, &s->q_io); 638 ivtv_enqueue(s, buf, &s->q_io);
@@ -922,10 +940,15 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
922 } 940 }
923 941
924 /* YUV or MPG Decoding Mode? */ 942 /* YUV or MPG Decoding Mode? */
925 if (s->type == IVTV_DEC_STREAM_TYPE_MPG) 943 if (s->type == IVTV_DEC_STREAM_TYPE_MPG) {
926 clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); 944 clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
927 else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) 945 } else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
928 set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); 946 set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
947 /* For yuv, we need to know the dma size before we start */
948 itv->dma_data_req_size =
949 itv->params.width * itv->params.height * 3 / 2;
950 itv->yuv_info.stream_size = 0;
951 }
929 return 0; 952 return 0;
930} 953}
931 954