Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / media / video / ivtv / ivtv-irq.c
index dd0dd8d..fba150a 100644 (file)
@@ -204,7 +204,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
                s->sg_pending[idx].dst = buf->dma_handle;
                s->sg_pending[idx].src = offset;
                s->sg_pending[idx].size = s->buf_size;
-               buf->bytesused = (size < s->buf_size) ? size : s->buf_size;
+               buf->bytesused = min(size, s->buf_size);
                buf->dma_xfer_cnt = s->dma_xfer_cnt;
 
                s->q_predma.bytesused += buf->bytesused;
@@ -231,14 +231,14 @@ static void dma_post(struct ivtv_stream *s)
        struct ivtv_buffer *buf = NULL;
        struct list_head *p;
        u32 offset;
-       u32 *u32buf;
+       __le32 *u32buf;
        int x = 0;
 
        IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
                        s->name, s->dma_offset);
        list_for_each(p, &s->q_dma.list) {
                buf = list_entry(p, struct ivtv_buffer, list);
-               u32buf = (u32 *)buf->buf;
+               u32buf = (__le32 *)buf->buf;
 
                /* Sync Buffer */
                ivtv_buf_sync_for_cpu(s, buf);
@@ -302,8 +302,11 @@ static void dma_post(struct ivtv_stream *s)
 void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
 {
        struct ivtv *itv = s->itv;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       u8 frame = yi->draw_frame;
+       struct yuv_frame_info *f = &yi->new_frame_info[frame];
        struct ivtv_buffer *buf;
-       u32 y_size = itv->params.height * itv->params.width;
+       u32 y_size = 720 * ((f->src_h + 31) & ~31);
        u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET;
        int y_done = 0;
        int bytes_written = 0;
@@ -311,6 +314,18 @@ void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
        int idx = 0;
 
        IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset);
+
+       /* Insert buffer block for YUV if needed */
+       if (s->type == IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) {
+               if (yi->blanking_dmaptr) {
+                       s->sg_pending[idx].src = yi->blanking_dmaptr;
+                       s->sg_pending[idx].dst = offset;
+                       s->sg_pending[idx].size = 720 * 16;
+               }
+               offset += 720 * 16;
+               idx++;
+       }
+
        list_for_each_entry(buf, &s->q_predma.list, list) {
                /* YUV UV Offset from Y Buffer */
                if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done &&
@@ -369,6 +384,8 @@ static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
        ivtv_stream_sync_for_device(s);
        write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR);
        write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
+       itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
+       add_timer(&itv->dma_timer);
 }
 
 static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
@@ -383,6 +400,8 @@ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
        ivtv_stream_sync_for_device(s);
        write_reg(s->sg_handle, IVTV_REG_DECDMAADDR);
        write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
+       itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
+       add_timer(&itv->dma_timer);
 }
 
 /* start the encoder DMA */
@@ -421,11 +440,11 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
                s_vbi->sg_pending_size = 0;
                s_vbi->dma_xfer_cnt++;
                set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags);
-               IVTV_DEBUG_HI_DMA("include DMA for %s\n", s->name);
+               IVTV_DEBUG_HI_DMA("include DMA for %s\n", s_vbi->name);
        }
 
        s->dma_xfer_cnt++;
-       memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size);
+       memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
        s->sg_processing_size = s->sg_pending_size;
        s->sg_pending_size = 0;
        s->sg_processed = 0;
@@ -444,8 +463,6 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
                ivtv_dma_enc_start_xfer(s);
                set_bit(IVTV_F_I_DMA, &itv->i_flags);
                itv->cur_dma_stream = s->type;
-               itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
-               add_timer(&itv->dma_timer);
        }
 }
 
@@ -456,7 +473,7 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s)
        if (s->q_predma.bytesused)
                ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
        s->dma_xfer_cnt++;
-       memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size);
+       memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
        s->sg_processing_size = s->sg_pending_size;
        s->sg_pending_size = 0;
        s->sg_processed = 0;
@@ -466,8 +483,6 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s)
        ivtv_dma_dec_start_xfer(s);
        set_bit(IVTV_F_I_DMA, &itv->i_flags);
        itv->cur_dma_stream = s->type;
-       itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
-       add_timer(&itv->dma_timer);
 }
 
 static void ivtv_irq_dma_read(struct ivtv *itv)
@@ -477,10 +492,11 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
        int hw_stream_type = 0;
 
        IVTV_DEBUG_HI_IRQ("DEC DMA READ\n");
-       if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) {
-               del_timer(&itv->dma_timer);
+
+       del_timer(&itv->dma_timer);
+
+       if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0)
                return;
-       }
 
        if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
                s = &itv->streams[itv->cur_dma_stream];
@@ -528,7 +544,6 @@ static void ivtv_irq_dma_read(struct ivtv *itv)
                }
                wake_up(&s->waitq);
        }
-       del_timer(&itv->dma_timer);
        clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
        clear_bit(IVTV_F_I_DMA, &itv->i_flags);
        itv->cur_dma_stream = -1;
@@ -542,10 +557,12 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
 
        ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data);
        IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream);
-       if (itv->cur_dma_stream < 0) {
-               del_timer(&itv->dma_timer);
+
+       del_timer(&itv->dma_timer);
+
+       if (itv->cur_dma_stream < 0)
                return;
-       }
+
        s = &itv->streams[itv->cur_dma_stream];
        ivtv_stream_sync_for_cpu(s);
 
@@ -570,7 +587,6 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
                ivtv_dma_enc_start_xfer(s);
                return;
        }
-       del_timer(&itv->dma_timer);
        clear_bit(IVTV_F_I_DMA, &itv->i_flags);
        itv->cur_dma_stream = -1;
        dma_post(s);
@@ -713,12 +729,15 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv)
        ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data);
 
        if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) {
-               itv->dma_data_req_size = itv->params.width * itv->params.height * 3 / 2;
-               itv->dma_data_req_offset = data[1] ? data[1] : yuv_offset[0];
+               itv->dma_data_req_size =
+                                1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
+               itv->dma_data_req_offset = data[1];
+               if (atomic_read(&itv->yuv_info.next_dma_frame) >= 0)
+                       ivtv_yuv_frame_complete(itv);
                s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
        }
        else {
-               itv->dma_data_req_size = data[2] >= 0x10000 ? 0x10000 : data[2];
+               itv->dma_data_req_size = min_t(u32, data[2], 0x10000);
                itv->dma_data_req_offset = data[1];
                s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
        }
@@ -728,6 +747,8 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv)
                set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
        }
        else {
+               if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
+                       ivtv_yuv_setup_stream_frame(itv);
                clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
                ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size);
                ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0);