diff options
author | Andy Walls <awalls@radix.net> | 2008-12-08 21:02:45 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-30 06:38:29 -0500 |
commit | 66c2a6b0bc0b394d215768610d96f44cf97052ac (patch) | |
tree | a88946e764eb5a829a920c5027b4d92922cc54ee /drivers/media/video/cx18 | |
parent | b80e1074c734416987486b7b76b6479faa73f1e2 (diff) |
V4L/DVB (9801): cx18: Allow more than 63 capture buffers in rotation per stream
cx18: Allow more than 63 capture buffers in rotation per stream. Implement
q_busy to hold buffers the firmware has for use. q_free holds truly unused
buffers in a pool. New buffers are given to the firmware as soon as the
firmware returns one, if there are any to give to the firmware.
Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18')
-rw-r--r-- | drivers/media/video/cx18/cx18-driver.h | 3 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-fileops.c | 14 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-ioctl.c | 3 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-mailbox.c | 11 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-queue.c | 56 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-queue.h | 16 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.c | 77 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-streams.h | 3 |
8 files changed, 113 insertions, 70 deletions
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index f88d82348293..4d56d07195b6 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
@@ -289,7 +289,8 @@ struct cx18_stream { | |||
289 | 289 | ||
290 | /* Buffer Queues */ | 290 | /* Buffer Queues */ |
291 | struct cx18_queue q_free; /* free buffers */ | 291 | struct cx18_queue q_free; /* free buffers */ |
292 | struct cx18_queue q_full; /* full buffers */ | 292 | struct cx18_queue q_busy; /* busy buffers - in use by firmware */ |
293 | struct cx18_queue q_full; /* full buffers - data for user apps */ | ||
293 | 294 | ||
294 | /* DVB / Digital Transport */ | 295 | /* DVB / Digital Transport */ |
295 | struct cx18_dvb dvb; | 296 | struct cx18_dvb dvb; |
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 504a1f9edec6..61192e62a80f 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
@@ -187,7 +187,7 @@ static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, | |||
187 | while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) { | 187 | while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) { |
188 | /* byteswap and process VBI data */ | 188 | /* byteswap and process VBI data */ |
189 | /* cx18_process_vbi_data(cx, buf, s_vbi->dma_pts, s_vbi->type); */ | 189 | /* cx18_process_vbi_data(cx, buf, s_vbi->dma_pts, s_vbi->type); */ |
190 | cx18_enqueue(s_vbi, buf, &s_vbi->q_free); | 190 | cx18_stream_put_buf_fw(s_vbi, buf); |
191 | } | 191 | } |
192 | } | 192 | } |
193 | buf = &cx->vbi.sliced_mpeg_buf; | 193 | buf = &cx->vbi.sliced_mpeg_buf; |
@@ -361,15 +361,9 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, | |||
361 | tot_count - tot_written); | 361 | tot_count - tot_written); |
362 | 362 | ||
363 | if (buf != &cx->vbi.sliced_mpeg_buf) { | 363 | if (buf != &cx->vbi.sliced_mpeg_buf) { |
364 | if (buf->readpos == buf->bytesused) { | 364 | if (buf->readpos == buf->bytesused) |
365 | cx18_buf_sync_for_device(s, buf); | 365 | cx18_stream_put_buf_fw(s, buf); |
366 | cx18_enqueue(s, buf, &s->q_free); | 366 | else |
367 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, | ||
368 | s->handle, | ||
369 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - | ||
370 | cx->enc_mem, | ||
371 | 1, buf->id, s->buf_size); | ||
372 | } else | ||
373 | cx18_push(s, buf, &s->q_full); | 367 | cx18_push(s, buf, &s->q_full); |
374 | } else if (buf->readpos == buf->bytesused) { | 368 | } else if (buf->readpos == buf->bytesused) { |
375 | int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; | 369 | int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES; |
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index 8b2ec31b9421..ece799ec37aa 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -746,8 +746,7 @@ static int cx18_log_status(struct file *file, void *fh) | |||
746 | continue; | 746 | continue; |
747 | CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", | 747 | CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", |
748 | s->name, s->s_flags, | 748 | s->name, s->s_flags, |
749 | (s->buffers - atomic_read(&s->q_free.buffers)) | 749 | atomic_read(&s->q_full.buffers) * 100 / s->buffers, |
750 | * 100 / s->buffers, | ||
751 | (s->buffers * s->buf_size) / 1024, s->buffers); | 750 | (s->buffers * s->buf_size) / 1024, s->buffers); |
752 | } | 751 | } |
753 | CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", | 752 | CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", |
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index b013e817926a..9d8220539be8 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
@@ -189,16 +189,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_epu_work_order *order) | |||
189 | dvb_dmx_swfilter(&s->dvb.demux, buf->buf, | 189 | dvb_dmx_swfilter(&s->dvb.demux, buf->buf, |
190 | buf->bytesused); | 190 | buf->bytesused); |
191 | 191 | ||
192 | cx18_buf_sync_for_device(s, buf); | 192 | cx18_stream_put_buf_fw(s, buf); |
193 | cx18_enqueue(s, buf, &s->q_free); | ||
194 | |||
195 | if (s->handle != CX18_INVALID_TASK_HANDLE && | ||
196 | test_bit(CX18_F_S_STREAMING, &s->s_flags)) | ||
197 | cx18_vapi(cx, | ||
198 | CX18_CPU_DE_SET_MDL, 5, s->handle, | ||
199 | (void __iomem *) | ||
200 | &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | ||
201 | 1, buf->id, s->buf_size); | ||
202 | } else | 193 | } else |
203 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); | 194 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); |
204 | } | 195 | } |
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index fdfc83ee3d4e..40379d807cef 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c | |||
@@ -42,24 +42,32 @@ void cx18_queue_init(struct cx18_queue *q) | |||
42 | q->bytesused = 0; | 42 | q->bytesused = 0; |
43 | } | 43 | } |
44 | 44 | ||
45 | void _cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, | 45 | struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, |
46 | struct cx18_queue *q, int to_front) | 46 | struct cx18_queue *q, int to_front) |
47 | { | 47 | { |
48 | /* clear the buffer if it is going to be enqueued to the free queue */ | 48 | /* clear the buffer if it is not to be enqueued to the full queue */ |
49 | if (q == &s->q_free) { | 49 | if (q != &s->q_full) { |
50 | buf->bytesused = 0; | 50 | buf->bytesused = 0; |
51 | buf->readpos = 0; | 51 | buf->readpos = 0; |
52 | buf->b_flags = 0; | 52 | buf->b_flags = 0; |
53 | buf->skipped = 0; | 53 | buf->skipped = 0; |
54 | } | 54 | } |
55 | |||
55 | mutex_lock(&s->qlock); | 56 | mutex_lock(&s->qlock); |
57 | |||
58 | /* q_busy is restricted to 63 buffers to stay within firmware limits */ | ||
59 | if (q == &s->q_busy && atomic_read(&q->buffers) >= 63) | ||
60 | q = &s->q_free; | ||
61 | |||
56 | if (to_front) | 62 | if (to_front) |
57 | list_add(&buf->list, &q->list); /* LIFO */ | 63 | list_add(&buf->list, &q->list); /* LIFO */ |
58 | else | 64 | else |
59 | list_add_tail(&buf->list, &q->list); /* FIFO */ | 65 | list_add_tail(&buf->list, &q->list); /* FIFO */ |
60 | atomic_inc(&q->buffers); | ||
61 | q->bytesused += buf->bytesused - buf->readpos; | 66 | q->bytesused += buf->bytesused - buf->readpos; |
67 | atomic_inc(&q->buffers); | ||
68 | |||
62 | mutex_unlock(&s->qlock); | 69 | mutex_unlock(&s->qlock); |
70 | return q; | ||
63 | } | 71 | } |
64 | 72 | ||
65 | struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) | 73 | struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) |
@@ -70,9 +78,9 @@ struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q) | |||
70 | if (!list_empty(&q->list)) { | 78 | if (!list_empty(&q->list)) { |
71 | buf = list_entry(q->list.next, struct cx18_buffer, list); | 79 | buf = list_entry(q->list.next, struct cx18_buffer, list); |
72 | list_del_init(q->list.next); | 80 | list_del_init(q->list.next); |
73 | atomic_dec(&q->buffers); | ||
74 | q->bytesused -= buf->bytesused - buf->readpos; | 81 | q->bytesused -= buf->bytesused - buf->readpos; |
75 | buf->skipped = 0; | 82 | buf->skipped = 0; |
83 | atomic_dec(&q->buffers); | ||
76 | } | 84 | } |
77 | mutex_unlock(&s->qlock); | 85 | mutex_unlock(&s->qlock); |
78 | return buf; | 86 | return buf; |
@@ -85,28 +93,30 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, | |||
85 | struct cx18_buffer *buf; | 93 | struct cx18_buffer *buf; |
86 | struct cx18_buffer *ret = NULL; | 94 | struct cx18_buffer *ret = NULL; |
87 | struct list_head *p, *t; | 95 | struct list_head *p, *t; |
88 | LIST_HEAD(r); | ||
89 | 96 | ||
90 | mutex_lock(&s->qlock); | 97 | mutex_lock(&s->qlock); |
91 | list_for_each_safe(p, t, &s->q_free.list) { | 98 | list_for_each_safe(p, t, &s->q_busy.list) { |
92 | buf = list_entry(p, struct cx18_buffer, list); | 99 | buf = list_entry(p, struct cx18_buffer, list); |
93 | 100 | ||
94 | if (buf->id != id) { | 101 | if (buf->id != id) { |
95 | buf->skipped++; | 102 | buf->skipped++; |
96 | if (buf->skipped >= atomic_read(&s->q_free.buffers)-1) { | 103 | if (buf->skipped >= atomic_read(&s->q_busy.buffers)-1) { |
97 | /* buffer must have fallen out of rotation */ | 104 | /* buffer must have fallen out of rotation */ |
98 | atomic_dec(&s->q_free.buffers); | ||
99 | list_move_tail(&buf->list, &r); | ||
100 | CX18_WARN("Skipped %s, buffer %d, %d " | 105 | CX18_WARN("Skipped %s, buffer %d, %d " |
101 | "times - it must have dropped out of " | 106 | "times - it must have dropped out of " |
102 | "rotation\n", s->name, buf->id, | 107 | "rotation\n", s->name, buf->id, |
103 | buf->skipped); | 108 | buf->skipped); |
109 | /* move it to q_free */ | ||
110 | list_move_tail(&buf->list, &s->q_free.list); | ||
111 | buf->bytesused = buf->readpos = buf->b_flags = | ||
112 | buf->skipped = 0; | ||
113 | atomic_dec(&s->q_busy.buffers); | ||
114 | atomic_inc(&s->q_free.buffers); | ||
104 | } | 115 | } |
105 | continue; | 116 | continue; |
106 | } | 117 | } |
107 | 118 | ||
108 | buf->bytesused = bytesused; | 119 | buf->bytesused = bytesused; |
109 | atomic_dec(&s->q_free.buffers); | ||
110 | if (s->type == CX18_ENC_STREAM_TYPE_TS) { | 120 | if (s->type == CX18_ENC_STREAM_TYPE_TS) { |
111 | /* | 121 | /* |
112 | * TS doesn't use q_full, but for sweeping up lost | 122 | * TS doesn't use q_full, but for sweeping up lost |
@@ -116,28 +126,19 @@ struct cx18_buffer *cx18_queue_get_buf(struct cx18_stream *s, u32 id, | |||
116 | */ | 126 | */ |
117 | list_del_init(&buf->list); | 127 | list_del_init(&buf->list); |
118 | } else { | 128 | } else { |
119 | atomic_inc(&s->q_full.buffers); | ||
120 | s->q_full.bytesused += buf->bytesused; | ||
121 | list_move_tail(&buf->list, &s->q_full.list); | 129 | list_move_tail(&buf->list, &s->q_full.list); |
130 | s->q_full.bytesused += buf->bytesused; | ||
131 | atomic_inc(&s->q_full.buffers); | ||
122 | } | 132 | } |
133 | atomic_dec(&s->q_busy.buffers); | ||
123 | 134 | ||
124 | ret = buf; | 135 | ret = buf; |
125 | break; | 136 | break; |
126 | } | 137 | } |
127 | mutex_unlock(&s->qlock); | ||
128 | 138 | ||
129 | /* Put lost buffers back into firmware transfer rotation */ | 139 | /* Put more buffers into the transfer rotation from q_free, if we can */ |
130 | while (!list_empty(&r)) { | 140 | cx18_stream_load_fw_queue_nolock(s); |
131 | buf = list_entry(r.next, struct cx18_buffer, list); | 141 | mutex_unlock(&s->qlock); |
132 | list_del_init(r.next); | ||
133 | cx18_enqueue(s, buf, &s->q_free); | ||
134 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | ||
135 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | ||
136 | 1, buf->id, s->buf_size); | ||
137 | CX18_INFO("Returning %s, buffer %d back to transfer rotation\n", | ||
138 | s->name, buf->id); | ||
139 | /* and there was much rejoicing... */ | ||
140 | } | ||
141 | return ret; | 142 | return ret; |
142 | } | 143 | } |
143 | 144 | ||
@@ -162,6 +163,7 @@ static void cx18_queue_flush(struct cx18_stream *s, struct cx18_queue *q) | |||
162 | 163 | ||
163 | void cx18_flush_queues(struct cx18_stream *s) | 164 | void cx18_flush_queues(struct cx18_stream *s) |
164 | { | 165 | { |
166 | cx18_queue_flush(s, &s->q_busy); | ||
165 | cx18_queue_flush(s, &s->q_full); | 167 | cx18_queue_flush(s, &s->q_full); |
166 | } | 168 | } |
167 | 169 | ||
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index d184e55ce624..456cec3bc28f 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h | |||
@@ -43,21 +43,21 @@ static inline void cx18_buf_sync_for_device(struct cx18_stream *s, | |||
43 | void cx18_buf_swap(struct cx18_buffer *buf); | 43 | void cx18_buf_swap(struct cx18_buffer *buf); |
44 | 44 | ||
45 | /* cx18_queue utility functions */ | 45 | /* cx18_queue utility functions */ |
46 | void _cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, | 46 | struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, |
47 | struct cx18_queue *q, int to_front); | 47 | struct cx18_queue *q, int to_front); |
48 | 48 | ||
49 | static inline | 49 | static inline |
50 | void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, | 50 | struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, |
51 | struct cx18_queue *q) | 51 | struct cx18_queue *q) |
52 | { | 52 | { |
53 | _cx18_enqueue(s, buf, q, 0); /* FIFO */ | 53 | return _cx18_enqueue(s, buf, q, 0); /* FIFO */ |
54 | } | 54 | } |
55 | 55 | ||
56 | static inline | 56 | static inline |
57 | void cx18_push(struct cx18_stream *s, struct cx18_buffer *buf, | 57 | struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_buffer *buf, |
58 | struct cx18_queue *q) | 58 | struct cx18_queue *q) |
59 | { | 59 | { |
60 | _cx18_enqueue(s, buf, q, 1); /* LIFO */ | 60 | return _cx18_enqueue(s, buf, q, 1); /* LIFO */ |
61 | } | 61 | } |
62 | 62 | ||
63 | void cx18_queue_init(struct cx18_queue *q); | 63 | void cx18_queue_init(struct cx18_queue *q); |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index a1cf434f7975..6b0b7f751f20 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -127,16 +127,11 @@ static void cx18_stream_init(struct cx18 *cx, int type) | |||
127 | s->buf_size = cx->stream_buf_size[type]; | 127 | s->buf_size = cx->stream_buf_size[type]; |
128 | if (s->buf_size) | 128 | if (s->buf_size) |
129 | s->buffers = max_size / s->buf_size; | 129 | s->buffers = max_size / s->buf_size; |
130 | if (s->buffers > 63) { | ||
131 | /* Each stream has a maximum of 63 buffers, | ||
132 | ensure we do not exceed that. */ | ||
133 | s->buffers = 63; | ||
134 | s->buf_size = (max_size / s->buffers) & ~0xfff; | ||
135 | } | ||
136 | mutex_init(&s->qlock); | 130 | mutex_init(&s->qlock); |
137 | init_waitqueue_head(&s->waitq); | 131 | init_waitqueue_head(&s->waitq); |
138 | s->id = -1; | 132 | s->id = -1; |
139 | cx18_queue_init(&s->q_free); | 133 | cx18_queue_init(&s->q_free); |
134 | cx18_queue_init(&s->q_busy); | ||
140 | cx18_queue_init(&s->q_full); | 135 | cx18_queue_init(&s->q_full); |
141 | } | 136 | } |
142 | 137 | ||
@@ -401,11 +396,61 @@ static void cx18_vbi_setup(struct cx18_stream *s) | |||
401 | cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); | 396 | cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data); |
402 | } | 397 | } |
403 | 398 | ||
399 | struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, | ||
400 | struct cx18_buffer *buf) | ||
401 | { | ||
402 | struct cx18 *cx = s->cx; | ||
403 | struct cx18_queue *q; | ||
404 | |||
405 | /* Don't give it to the firmware, if we're not running a capture */ | ||
406 | if (s->handle == CX18_INVALID_TASK_HANDLE || | ||
407 | !test_bit(CX18_F_S_STREAMING, &s->s_flags)) | ||
408 | return cx18_enqueue(s, buf, &s->q_free); | ||
409 | |||
410 | q = cx18_enqueue(s, buf, &s->q_busy); | ||
411 | if (q != &s->q_busy) | ||
412 | return q; /* The firmware has the max buffers it can handle */ | ||
413 | |||
414 | cx18_buf_sync_for_device(s, buf); | ||
415 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | ||
416 | (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | ||
417 | 1, buf->id, s->buf_size); | ||
418 | return q; | ||
419 | } | ||
420 | |||
421 | /* Must hold s->qlock when calling */ | ||
422 | void cx18_stream_load_fw_queue_nolock(struct cx18_stream *s) | ||
423 | { | ||
424 | struct cx18_buffer *buf; | ||
425 | struct cx18 *cx = s->cx; | ||
426 | |||
427 | /* Move from q_free to q_busy notifying the firmware: 63 buf limit */ | ||
428 | while (s->handle != CX18_INVALID_TASK_HANDLE && | ||
429 | test_bit(CX18_F_S_STREAMING, &s->s_flags) && | ||
430 | atomic_read(&s->q_busy.buffers) < 63 && | ||
431 | !list_empty(&s->q_free.list)) { | ||
432 | |||
433 | /* Move from q_free to q_busy */ | ||
434 | buf = list_entry(s->q_free.list.next, struct cx18_buffer, list); | ||
435 | list_move_tail(&buf->list, &s->q_busy.list); | ||
436 | buf->bytesused = buf->readpos = buf->b_flags = buf->skipped = 0; | ||
437 | atomic_dec(&s->q_free.buffers); | ||
438 | atomic_inc(&s->q_busy.buffers); | ||
439 | |||
440 | /* Notify firmware */ | ||
441 | cx18_buf_sync_for_device(s, buf); | ||
442 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | ||
443 | (void __iomem *) &cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | ||
444 | 1, buf->id, s->buf_size); | ||
445 | } | ||
446 | } | ||
447 | |||
404 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | 448 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s) |
405 | { | 449 | { |
406 | u32 data[MAX_MB_ARGUMENTS]; | 450 | u32 data[MAX_MB_ARGUMENTS]; |
407 | struct cx18 *cx = s->cx; | 451 | struct cx18 *cx = s->cx; |
408 | struct list_head *p; | 452 | struct list_head *p; |
453 | struct cx18_buffer *buf; | ||
409 | int ts = 0; | 454 | int ts = 0; |
410 | int captype = 0; | 455 | int captype = 0; |
411 | 456 | ||
@@ -488,16 +533,18 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
488 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem, | 533 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem, |
489 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); | 534 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); |
490 | 535 | ||
536 | /* Init all the cpu_mdls for this stream */ | ||
537 | cx18_flush_queues(s); | ||
538 | mutex_lock(&s->qlock); | ||
491 | list_for_each(p, &s->q_free.list) { | 539 | list_for_each(p, &s->q_free.list) { |
492 | struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); | 540 | buf = list_entry(p, struct cx18_buffer, list); |
493 | |||
494 | cx18_writel(cx, buf->dma_handle, | 541 | cx18_writel(cx, buf->dma_handle, |
495 | &cx->scb->cpu_mdl[buf->id].paddr); | 542 | &cx->scb->cpu_mdl[buf->id].paddr); |
496 | cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); | 543 | cx18_writel(cx, s->buf_size, &cx->scb->cpu_mdl[buf->id].length); |
497 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | ||
498 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | ||
499 | 1, buf->id, s->buf_size); | ||
500 | } | 544 | } |
545 | cx18_stream_load_fw_queue_nolock(s); | ||
546 | mutex_unlock(&s->qlock); | ||
547 | |||
501 | /* begin_capture */ | 548 | /* begin_capture */ |
502 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { | 549 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { |
503 | CX18_DEBUG_WARN("Error starting capture!\n"); | 550 | CX18_DEBUG_WARN("Error starting capture!\n"); |
@@ -506,9 +553,15 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
506 | cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1); | 553 | cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1); |
507 | else | 554 | else |
508 | cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle); | 555 | cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle); |
556 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | ||
557 | /* FIXME - CX18_F_S_STREAMOFF as well? */ | ||
509 | cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); | 558 | cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle); |
510 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); | 559 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); |
511 | /* FIXME - clean-up DSP0_INT mask, i_flags, s_flags, etc. */ | 560 | s->handle = CX18_INVALID_TASK_HANDLE; |
561 | if (atomic_read(&cx->tot_capturing) == 0) { | ||
562 | set_bit(CX18_F_I_EOS, &cx->i_flags); | ||
563 | cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK); | ||
564 | } | ||
512 | return -EINVAL; | 565 | return -EINVAL; |
513 | } | 566 | } |
514 | 567 | ||
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 7218b15045bf..635d34b75ab1 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h | |||
@@ -29,6 +29,9 @@ 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); | ||
33 | struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s, | ||
34 | struct cx18_buffer *buf); | ||
32 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s); | 35 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s); |
33 | int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end); | 36 | int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end); |
34 | 37 | ||