aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c8
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h2
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c31
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c25
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 04179b7d1af0..48db22cc1bd8 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,
970 const struct pci_device_id *pci_id) 970 const struct pci_device_id *pci_id)
971{ 971{
972 int retval = 0; 972 int retval = 0;
973 int yuv_buf_size;
974 int vbi_buf_size; 973 int vbi_buf_size;
975 struct ivtv *itv; 974 struct ivtv *itv;
976 975
@@ -1122,11 +1121,8 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
1122 itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000; 1121 itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000;
1123 itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200; 1122 itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200;
1124 itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_MPG] = 0x10000; 1123 itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_MPG] = 0x10000;
1125 1124 itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_YUV] = 0x10000;
1126 /* 0x15180 == 720 * 480 / 4, 0x19500 == 720 * 576 / 4 */ 1125 itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_YUV] = 0x08000;
1127 yuv_buf_size = itv->is_60hz ? 0x15180 : 0x19500;
1128 itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_YUV] = yuv_buf_size / 2;
1129 itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_YUV] = yuv_buf_size / 8;
1130 1126
1131 /* Setup VBI Raw Size. Should be big enough to hold PAL. 1127 /* Setup VBI Raw Size. Should be big enough to hold PAL.
1132 It is possible to switch between PAL and NTSC, so we need to 1128 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 49ce14d14a54..b6dd2360e610 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
485 485
486 void *blanking_ptr; 486 void *blanking_ptr;
487 dma_addr_t blanking_dmaptr; 487 dma_addr_t blanking_dmaptr;
488
489 int stream_size;
488}; 490};
489 491
490#define IVTV_VBI_FRAMES 32 492#define IVTV_VBI_FRAMES 32
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
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index fd1688e4757d..bcf1c85991af 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)
313 IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); 313 IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset);
314 list_for_each_entry(buf, &s->q_predma.list, list) { 314 list_for_each_entry(buf, &s->q_predma.list, list) {
315 /* YUV UV Offset from Y Buffer */ 315 /* YUV UV Offset from Y Buffer */
316 if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done && bytes_written >= y_size) { 316 if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done &&
317 (bytes_written + buf->bytesused) >= y_size) {
318 s->sg_pending[idx].src = buf->dma_handle;
319 s->sg_pending[idx].dst = offset;
320 s->sg_pending[idx].size = y_size - bytes_written;
317 offset = uv_offset; 321 offset = uv_offset;
322 if (s->sg_pending[idx].size != buf->bytesused) {
323 idx++;
324 s->sg_pending[idx].src =
325 buf->dma_handle + s->sg_pending[idx - 1].size;
326 s->sg_pending[idx].dst = offset;
327 s->sg_pending[idx].size =
328 buf->bytesused - s->sg_pending[idx - 1].size;
329 offset += s->sg_pending[idx].size;
330 }
318 y_done = 1; 331 y_done = 1;
332 } else {
333 s->sg_pending[idx].src = buf->dma_handle;
334 s->sg_pending[idx].dst = offset;
335 s->sg_pending[idx].size = buf->bytesused;
336 offset += buf->bytesused;
319 } 337 }
320 s->sg_pending[idx].src = buf->dma_handle;
321 s->sg_pending[idx].dst = offset;
322 s->sg_pending[idx].size = buf->bytesused;
323
324 offset += buf->bytesused;
325 bytes_written += buf->bytesused; 338 bytes_written += buf->bytesused;
326 339
327 /* Sync SG buffers */ 340 /* Sync SG buffers */