aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ivtv/ivtv-irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ivtv/ivtv-irq.c')
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c95
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)
302void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) 302void 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