diff options
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-irq.c')
-rw-r--r-- | drivers/media/video/ivtv/ivtv-irq.c | 95 |
1 files changed, 66 insertions, 29 deletions
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index fd1688e4757d..65604dde9726 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -204,7 +204,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA | |||
204 | s->sg_pending[idx].dst = buf->dma_handle; | 204 | s->sg_pending[idx].dst = buf->dma_handle; |
205 | s->sg_pending[idx].src = offset; | 205 | s->sg_pending[idx].src = offset; |
206 | s->sg_pending[idx].size = s->buf_size; | 206 | s->sg_pending[idx].size = s->buf_size; |
207 | buf->bytesused = (size < s->buf_size) ? size : s->buf_size; | 207 | buf->bytesused = min(size, s->buf_size); |
208 | buf->dma_xfer_cnt = s->dma_xfer_cnt; | 208 | buf->dma_xfer_cnt = s->dma_xfer_cnt; |
209 | 209 | ||
210 | s->q_predma.bytesused += buf->bytesused; | 210 | s->q_predma.bytesused += buf->bytesused; |
@@ -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,17 +314,42 @@ 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 && bytes_written >= y_size) { | 331 | if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done && |
332 | (bytes_written + buf->bytesused) >= y_size) { | ||
333 | s->sg_pending[idx].src = buf->dma_handle; | ||
334 | s->sg_pending[idx].dst = offset; | ||
335 | s->sg_pending[idx].size = y_size - bytes_written; | ||
317 | offset = uv_offset; | 336 | offset = uv_offset; |
337 | if (s->sg_pending[idx].size != buf->bytesused) { | ||
338 | idx++; | ||
339 | s->sg_pending[idx].src = | ||
340 | buf->dma_handle + s->sg_pending[idx - 1].size; | ||
341 | s->sg_pending[idx].dst = offset; | ||
342 | s->sg_pending[idx].size = | ||
343 | buf->bytesused - s->sg_pending[idx - 1].size; | ||
344 | offset += s->sg_pending[idx].size; | ||
345 | } | ||
318 | y_done = 1; | 346 | y_done = 1; |
347 | } else { | ||
348 | s->sg_pending[idx].src = buf->dma_handle; | ||
349 | s->sg_pending[idx].dst = offset; | ||
350 | s->sg_pending[idx].size = buf->bytesused; | ||
351 | offset += buf->bytesused; | ||
319 | } | 352 | } |
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; | 353 | bytes_written += buf->bytesused; |
326 | 354 | ||
327 | /* Sync SG buffers */ | 355 | /* Sync SG buffers */ |
@@ -408,7 +436,7 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) | |||
408 | s_vbi->sg_pending_size = 0; | 436 | s_vbi->sg_pending_size = 0; |
409 | s_vbi->dma_xfer_cnt++; | 437 | s_vbi->dma_xfer_cnt++; |
410 | set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); | 438 | set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); |
411 | IVTV_DEBUG_HI_DMA("include DMA for %s\n", s->name); | 439 | IVTV_DEBUG_HI_DMA("include DMA for %s\n", s_vbi->name); |
412 | } | 440 | } |
413 | 441 | ||
414 | s->dma_xfer_cnt++; | 442 | s->dma_xfer_cnt++; |
@@ -700,12 +728,15 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) | |||
700 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); | 728 | ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data); |
701 | 729 | ||
702 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { | 730 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { |
703 | itv->dma_data_req_size = itv->params.width * itv->params.height * 3 / 2; | 731 | itv->dma_data_req_size = |
704 | 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); | ||
705 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; | 736 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; |
706 | } | 737 | } |
707 | else { | 738 | else { |
708 | itv->dma_data_req_size = data[2] >= 0x10000 ? 0x10000 : data[2]; | 739 | itv->dma_data_req_size = min_t(u32, data[2], 0x10000); |
709 | itv->dma_data_req_offset = data[1]; | 740 | itv->dma_data_req_offset = data[1]; |
710 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; | 741 | s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; |
711 | } | 742 | } |
@@ -715,6 +746,8 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv) | |||
715 | set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | 746 | set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); |
716 | } | 747 | } |
717 | else { | 748 | else { |
749 | if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) | ||
750 | ivtv_yuv_setup_stream_frame(itv); | ||
718 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); | 751 | clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); |
719 | 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); |
720 | 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); |
@@ -731,24 +764,26 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
731 | * one vsync per frame. | 764 | * one vsync per frame. |
732 | */ | 765 | */ |
733 | unsigned int frame = read_reg(0x28c0) & 1; | 766 | unsigned int frame = read_reg(0x28c0) & 1; |
767 | struct yuv_playback_info *yi = &itv->yuv_info; | ||
734 | int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame); | 768 | int last_dma_frame = atomic_read(&itv->yuv_info.next_dma_frame); |
769 | struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame]; | ||
735 | 770 | ||
736 | if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); | 771 | if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); |
737 | 772 | ||
738 | if (((frame ^ itv->yuv_info.sync_field[last_dma_frame]) == 0 && | 773 | if (((frame ^ f->sync_field) == 0 && |
739 | ((itv->last_vsync_field & 1) ^ itv->yuv_info.sync_field[last_dma_frame])) || | 774 | ((itv->last_vsync_field & 1) ^ f->sync_field)) || |
740 | (frame != (itv->last_vsync_field & 1) && !itv->yuv_info.frame_interlaced)) { | 775 | (frame != (itv->last_vsync_field & 1) && !f->interlaced)) { |
741 | int next_dma_frame = last_dma_frame; | 776 | int next_dma_frame = last_dma_frame; |
742 | 777 | ||
743 | if (!(itv->yuv_info.frame_interlaced && itv->yuv_info.field_delay[next_dma_frame] && itv->yuv_info.fields_lapsed < 1)) { | 778 | if (!(f->interlaced && f->delay && yi->fields_lapsed < 1)) { |
744 | if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&itv->yuv_info.next_fill_frame)) { | 779 | if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&yi->next_fill_frame)) { |
745 | write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); | 780 | write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); |
746 | write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); | 781 | write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); |
747 | write_reg(yuv_offset[next_dma_frame] >> 4, 0x834); | 782 | write_reg(yuv_offset[next_dma_frame] >> 4, 0x834); |
748 | write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); | 783 | write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); |
749 | next_dma_frame = (next_dma_frame + 1) & 0x3; | 784 | next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS; |
750 | atomic_set(&itv->yuv_info.next_dma_frame, next_dma_frame); | 785 | atomic_set(&yi->next_dma_frame, next_dma_frame); |
751 | itv->yuv_info.fields_lapsed = -1; | 786 | yi->fields_lapsed = -1; |
752 | } | 787 | } |
753 | } | 788 | } |
754 | } | 789 | } |
@@ -781,20 +816,22 @@ static void ivtv_irq_vsync(struct ivtv *itv) | |||
781 | } | 816 | } |
782 | 817 | ||
783 | /* Check if we need to update the yuv registers */ | 818 | /* Check if we need to update the yuv registers */ |
784 | if ((itv->yuv_info.yuv_forced_update || itv->yuv_info.new_frame_info[last_dma_frame].update) && last_dma_frame != -1) { | 819 | if ((yi->yuv_forced_update || f->update) && last_dma_frame != -1) { |
785 | if (!itv->yuv_info.new_frame_info[last_dma_frame].update) | 820 | if (!f->update) { |
786 | last_dma_frame = (last_dma_frame - 1) & 3; | 821 | last_dma_frame = (u8)(last_dma_frame - 1) % IVTV_YUV_BUFFERS; |
787 | 822 | f = &yi->new_frame_info[last_dma_frame]; | |
788 | if (itv->yuv_info.new_frame_info[last_dma_frame].src_w) { | 823 | } |
789 | itv->yuv_info.update_frame = last_dma_frame; | 824 | |
790 | itv->yuv_info.new_frame_info[last_dma_frame].update = 0; | 825 | if (f->src_w) { |
791 | itv->yuv_info.yuv_forced_update = 0; | 826 | yi->update_frame = last_dma_frame; |
827 | f->update = 0; | ||
828 | yi->yuv_forced_update = 0; | ||
792 | set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags); | 829 | set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags); |
793 | set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); | 830 | set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); |
794 | } | 831 | } |
795 | } | 832 | } |
796 | 833 | ||
797 | itv->yuv_info.fields_lapsed ++; | 834 | yi->fields_lapsed++; |
798 | } | 835 | } |
799 | } | 836 | } |
800 | 837 | ||