diff options
-rw-r--r-- | drivers/media/video/cx18/cx18-mailbox.c | 15 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-queue.c | 13 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 37 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.h | 2 |
4 files changed, 30 insertions, 37 deletions
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 9d8220539be8..ca8d5f4b731a 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
@@ -163,7 +163,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order) | |||
163 | * it's filled in). | 163 | * it's filled in). |
164 | * | 164 | * |
165 | * cx18_queue_get buf() will detect the lost buffers | 165 | * cx18_queue_get buf() will detect the lost buffers |
166 | * and put them back in rotation eventually. | 166 | * and send them back to q_free for fw rotation eventually. |
167 | */ | 167 | */ |
168 | if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) && | 168 | if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) && |
169 | !(id >= s->mdl_offset && | 169 | !(id >= s->mdl_offset && |
@@ -174,24 +174,27 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order) | |||
174 | break; | 174 | break; |
175 | } | 175 | } |
176 | buf = cx18_queue_get_buf(s, id, mdl_ack->data_used); | 176 | buf = cx18_queue_get_buf(s, id, mdl_ack->data_used); |
177 | |||
177 | CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); | 178 | CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id); |
178 | if (buf == NULL) { | 179 | if (buf == NULL) { |
179 | CX18_WARN("Could not find buf %d for stream %s\n", | 180 | CX18_WARN("Could not find buf %d for stream %s\n", |
180 | id, s->name); | 181 | id, s->name); |
182 | /* Put as many buffers as possible back into fw use */ | ||
183 | cx18_stream_load_fw_queue(s); | ||
181 | continue; | 184 | continue; |
182 | } | 185 | } |
183 | 186 | ||
184 | cx18_buf_sync_for_cpu(s, buf); | ||
185 | if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) { | 187 | if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) { |
186 | CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n", | 188 | CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n", |
187 | buf->bytesused); | 189 | buf->bytesused); |
188 | |||
189 | dvb_dmx_swfilter(&s->dvb.demux, buf->buf, | 190 | dvb_dmx_swfilter(&s->dvb.demux, buf->buf, |
190 | buf->bytesused); | 191 | buf->bytesused); |
191 | 192 | } | |
193 | /* Put as many buffers as possible back into fw use */ | ||
194 | cx18_stream_load_fw_queue(s); | ||
195 | /* Put back TS buffer, since it was removed from all queues */ | ||
196 | if (s->type == CX18_ENC_STREAM_TYPE_TS) | ||
192 | cx18_stream_put_buf_fw(s, buf); | 197 | cx18_stream_put_buf_fw(s, buf); |
193 | } else | ||
194 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); | ||
195 | } | 198 | } |
196 | wake_up(&cx->dma_waitq); | 199 | wake_up(&cx->dma_waitq); |
197 | if (s->id != -1) | 200 | if (s->id != -1) |
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 40379d807cef..a6b0666f0ba3 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c | |||
@@ -117,16 +117,18 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, | |||
117 | } | 117 | } |
118 | 118 | ||
119 | buf->bytesused = bytesused; | 119 | buf->bytesused = bytesused; |
120 | /* Sync the buffer before we release the qlock */ | ||
121 | cx18_buf_sync_for_cpu(s, buf); | ||
120 | if (s->type == CX18_ENC_STREAM_TYPE_TS) { | 122 | if (s->type == CX18_ENC_STREAM_TYPE_TS) { |
121 | /* | 123 | /* |
122 | * TS doesn't use q_full, but for sweeping up lost | 124 | * TS doesn't use q_full. As we pull the buffer off of |
123 | * buffers, we want the TS to requeue the buffer just | 125 | * the queue here, the caller will have to put it back. |
124 | * before sending the MDL back to the firmware, so we | ||
125 | * pull it off the list here. | ||
126 | */ | 126 | */ |
127 | list_del_init(&buf->list); | 127 | list_del_init(&buf->list); |
128 | } else { | 128 | } else { |
129 | /* Move buffer from q_busy to q_full */ | ||
129 | list_move_tail(&buf->list, &s->q_full.list); | 130 | list_move_tail(&buf->list, &s->q_full.list); |
131 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); | ||
130 | s->q_full.bytesused += buf->bytesused; | 132 | s->q_full.bytesused += buf->bytesused; |
131 | atomic_inc(&s->q_full.buffers); | 133 | atomic_inc(&s->q_full.buffers); |
132 | } | 134 | } |
@@ -135,9 +137,6 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, | |||
135 | ret = buf; | 137 | ret = buf; |
136 | break; | 138 | break; |
137 | } | 139 | } |
138 | |||
139 | /* Put more buffers into the transfer rotation from q_free, if we can */ | ||
140 | cx18_stream_load_fw_queue_nolock(s); | ||
141 | mutex_unlock(&s->qlock); | 140 | mutex_unlock(&s->qlock); |
142 | return ret; | 141 | return ret; |
143 | } | 142 | } |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index d2690ccdf327..9ead4591b1d2 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -419,31 +419,22 @@ struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, | |||
419 | return q; | 419 | return q; |
420 | } | 420 | } |
421 | 421 | ||
422 | /* Must hold s->qlock when calling */ | 422 | void cx18_stream_load_fw_queue(struct cx18_stream *s) |
423 | void cx18_stream_load_fw_queue_nolock(struct cx18_stream *s) | ||
424 | { | 423 | { |
424 | struct cx18_queue *q; | ||
425 | struct cx18_buffer *buf; | 425 | struct cx18_buffer *buf; |
426 | struct cx18 *cx = s->cx; | ||
427 | 426 | ||
428 | /* Move from q_free to q_busy notifying the firmware: 63 buf limit */ | 427 | if (atomic_read(&s->q_free.buffers) == 0 || |
429 | while (s->handle != CX18_INVALID_TASK_HANDLE && | 428 | atomic_read(&s->q_busy.buffers) >= 63) |
430 | test_bit(CX18_F_S_STREAMING, &s->s_flags) && | 429 | return; |
431 | atomic_read(&s->q_busy.buffers) < 63 && | 430 | |
432 | !list_empty(&s->q_free.list)) { | 431 | /* Move from q_free to q_busy notifying the firmware, until the limit */ |
433 | 432 | do { | |
434 | /* Move from q_free to q_busy */ | 433 | buf = cx18_dequeue(s, &s->q_free); |
435 | buf = list_entry(s->q_free.list.next, struct cx18_buffer, list); | 434 | if (buf == NULL) |
436 | list_move_tail(&buf->list, &s->q_busy.list); | 435 | break; |
437 | buf->bytesused = buf->readpos = buf->b_flags = buf->skipped = 0; | 436 | q = cx18_stream_put_buf_fw(s, buf); |
438 | atomic_dec(&s->q_free.buffers); | 437 | } while (atomic_read(&s->q_busy.buffers) < 63 && q == &s->q_busy); |
439 | atomic_inc(&s->q_busy.buffers); | ||
440 | |||
441 | /* Notify firmware */ | ||
442 | cx18_buf_sync_for_device(s, buf); | ||
443 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | ||
444 | (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | ||
445 | 1, buf->id, s->buf_size); | ||
446 | } | ||
447 | } | 438 | } |
448 | 439 | ||
449 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | 440 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) |
@@ -543,8 +534,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
543 | &cx->scb->cpu_mdl[buf->id].paddr); | 534 | &cx->scb->cpu_mdl[buf->id].paddr); |
544 | cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); | 535 | cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); |
545 | } | 536 | } |
546 | cx18_stream_load_fw_queue_nolock(s); | ||
547 | mutex_unlock(&s->qlock); | 537 | mutex_unlock(&s->qlock); |
538 | cx18_stream_load_fw_queue(s); | ||
548 | 539 | ||
549 | /* begin_capture */ | 540 | /* begin_capture */ |
550 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { | 541 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { |
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 635d34b75ab1..420e0a172945 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h | |||
@@ -29,7 +29,7 @@ int cx18_streams_register(struct cx18 *cx); | |||
29 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); | 29 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); |
30 | 30 | ||
31 | /* Capture related */ | 31 | /* Capture related */ |
32 | void cx18_stream_load_fw_queue_nolock(struct cx18_stream *s); | 32 | void cx18_stream_load_fw_queue(struct cx18_stream *s); |
33 | struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, | 33 | struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, |
34 | struct cx18_buffer *buf); | 34 | struct cx18_buffer *buf); |
35 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s); | 35 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s); |