diff options
author | Ian Armstrong <ian@iarmst.demon.co.uk> | 2007-11-05 12:27:09 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:03:11 -0500 |
commit | 77aded6ba51f01335840ce8e18b413067810b68e (patch) | |
tree | 2763dd287dd0f40bed5a1ba5262e0e13f58bf4e4 /drivers/media/video/ivtv/ivtv-irq.c | |
parent | 3b5c1c8e71eb8fe2297a5884db59108e3c8b44c5 (diff) |
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 <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-irq.c')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-irq.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index dd0dd8d126de..ebc200320e6f 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) | |||
302 | void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) | 302 | void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) |
303 | { | 303 | { |
304 | struct ivtv *itv = s->itv; | 304 | struct ivtv *itv = s->itv; |
305 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
306 | u8 frame = yi->draw_frame; | ||
307 | struct yuv_frame_info *f = &yi->new_frame_info[frame]; | ||
305 | struct ivtv_buffer *buf; | 308 | struct ivtv_buffer *buf; |
306 | u32 y_size = itv->params.height * itv->params.width; | 309 | u32 y_size = 720 * ((f->src_h + 31) & ~31); |
307 | u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET; | 310 | u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET; |
308 | int y_done = 0; | 311 | int y_done = 0; |
309 | int bytes_written = 0; | 312 | int bytes_written = 0; |
@@ -311,6 +314,18 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) | |||
311 | int idx = 0; | 314 | int idx = 0; |
312 | 315 | ||
313 | IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); | 316 | IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); |
317 | |||
318 | /* Insert buffer block for YUV if needed */ | ||
319 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) { | ||
320 | if (yi->blanking_dmaptr) { | ||
321 | s->sg_pending[idx].src = yi->blanking_dmaptr; | ||
322 | s->sg_pending[idx].dst = offset; | ||
323 | s->sg_pending[idx].size = 720 * 16; | ||
324 | } | ||
325 | offset += 720 * 16; | ||
326 | idx++; | ||
327 | } | ||
328 | |||
314 | list_for_each_entry(buf, &s->q_predma.list, list) { | 329 | list_for_each_entry(buf, &s->q_predma.list, list) { |
315 | /* YUV UV Offset from Y Buffer */ | 330 | /* YUV UV Offset from Y Buffer */ |
316 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done && | 331 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done && |
@@ -713,8 +728,11 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) | |||
713 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); | 728 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); |
714 | 729 | ||
715 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { | 730 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { |
716 | itv->dma_data_req_size = itv->params.width * itv->params.height * 3 / 2; | 731 | itv->dma_data_req_size = |
717 | itv->dma_data_req_offset = data[1] ? data[1] : yuv_offset[0]; | 732 | 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); |
733 | itv->dma_data_req_offset = data[1]; | ||
734 | if (atomic_read(&itv->yuv_info.next_dma_frame) >= 0) | ||
735 | ivtv_yuv_frame_complete(itv); | ||
718 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; | 736 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; |
719 | } | 737 | } |
720 | else { | 738 | else { |
@@ -728,6 +746,8 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) | |||
728 | set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | 746 | set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); |
729 | } | 747 | } |
730 | else { | 748 | else { |
749 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) | ||
750 | ivtv_yuv_setup_stream_frame(itv); | ||
731 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | 751 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); |
732 | ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size); | 752 | ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size); |
733 | ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0); | 753 | ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0); |