aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c15
-rw-r--r--drivers/media/video/cx18/cx18-queue.c13
-rw-r--r--drivers/media/video/cx18/cx18-streams.c37
-rw-r--r--drivers/media/video/cx18/cx18-streams.h2
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 */ 422void cx18_stream_load_fw_queue(struct cx18_stream *s)
423void 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
449int cx18_start_v4l2_encode_stream(struct cx18_stream *s) 440int 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);
29void cx18_streams_cleanup(struct cx18 *cx, int unregister); 29void cx18_streams_cleanup(struct cx18 *cx, int unregister);
30 30
31/* Capture related */ 31/* Capture related */
32void cx18_stream_load_fw_queue_nolock(struct cx18_stream *s); 32void cx18_stream_load_fw_queue(struct cx18_stream *s);
33struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, 33struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s,
34 struct cx18_buffer *buf); 34 struct cx18_buffer *buf);
35int cx18_start_v4l2_encode_stream(struct cx18_stream *s); 35int cx18_start_v4l2_encode_stream(struct cx18_stream *s);