aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-streams.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx18/cx18-streams.c')
-rw-r--r--drivers/media/video/cx18/cx18-streams.c82
1 files changed, 5 insertions, 77 deletions
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index e1934e9cfdc8..41a1b2618aac 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -124,6 +124,8 @@ static void cx18_stream_init(struct cx18 *cx, int type)
124 cx18_queue_init(&s->q_busy); 124 cx18_queue_init(&s->q_busy);
125 spin_lock_init(&s->q_full.lock); 125 spin_lock_init(&s->q_full.lock);
126 cx18_queue_init(&s->q_full); 126 cx18_queue_init(&s->q_full);
127
128 INIT_WORK(&s->out_work_order, cx18_out_work_handler);
127} 129}
128 130
129static int cx18_prep_dev(struct cx18 *cx, int type) 131static int cx18_prep_dev(struct cx18 *cx, int type)
@@ -477,86 +479,12 @@ void _cx18_stream_load_fw_queue(struct cx18_stream *s)
477 && q == &s->q_busy); 479 && q == &s->q_busy);
478} 480}
479 481
480static inline
481void free_out_work_order(struct cx18_out_work_order *order)
482{
483 atomic_set(&order->pending, 0);
484}
485
486void cx18_out_work_handler(struct work_struct *work) 482void cx18_out_work_handler(struct work_struct *work)
487{ 483{
488 struct cx18_out_work_order *order = 484 struct cx18_stream *s =
489 container_of(work, struct cx18_out_work_order, work); 485 container_of(work, struct cx18_stream, out_work_order);
490 struct cx18_stream *s = order->s;
491 struct cx18_buffer *buf = order->buf;
492
493 free_out_work_order(order);
494
495 if (buf == NULL)
496 _cx18_stream_load_fw_queue(s);
497 else
498 _cx18_stream_put_buf_fw(s, buf);
499}
500
501static
502struct cx18_out_work_order *alloc_out_work_order(struct cx18 *cx)
503{
504 int i;
505 struct cx18_out_work_order *order = NULL;
506
507 for (i = 0; i < CX18_MAX_OUT_WORK_ORDERS; i++) {
508 /*
509 * We need "pending" to be atomic to inspect & set its contents
510 * 1. "pending" is only set to 1 here, but needs multiple access
511 * protection
512 * 2. work handler threads only clear "pending" and only
513 * on one, particular work order at a time, per handler thread.
514 */
515 if (atomic_add_unless(&cx->out_work_order[i].pending, 1, 1)) {
516 order = &cx->out_work_order[i];
517 break;
518 }
519 }
520 return order;
521}
522
523struct cx18_queue *cx18_stream_put_buf_fw(struct cx18_stream *s,
524 struct cx18_buffer *buf)
525{
526 struct cx18 *cx = s->cx;
527 struct cx18_out_work_order *order;
528
529 order = alloc_out_work_order(cx);
530 if (order == NULL) {
531 CX18_DEBUG_WARN("No blank, outgoing-mailbox, deferred-work, "
532 "order forms available; sending buffer %u back "
533 "to the firmware immediately for stream %s\n",
534 buf->id, s->name);
535 return _cx18_stream_put_buf_fw(s, buf);
536 }
537 order->s = s;
538 order->buf = buf;
539 queue_work(cx->out_work_queue, &order->work);
540 return NULL;
541}
542
543void cx18_stream_load_fw_queue(struct cx18_stream *s)
544{
545 struct cx18 *cx = s->cx;
546 struct cx18_out_work_order *order;
547 486
548 order = alloc_out_work_order(cx); 487 _cx18_stream_load_fw_queue(s);
549 if (order == NULL) {
550 CX18_DEBUG_WARN("No blank, outgoing-mailbox, deferred-work, "
551 "order forms available; filling the firmware "
552 "buffer queue immediately for stream %s\n",
553 s->name);
554 _cx18_stream_load_fw_queue(s);
555 return;
556 }
557 order->s = s;
558 order->buf = NULL; /* Indicates to load the fw queue */
559 queue_work(cx->out_work_queue, &order->work);
560} 488}
561 489
562int cx18_start_v4l2_encode_stream(struct cx18_stream *s) 490int cx18_start_v4l2_encode_stream(struct cx18_stream *s)