diff options
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.c | 8 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-driver.h | 2 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 31 | ||||
-rw-r--r-- | 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 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 */ |