diff options
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); |