0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/module.h>
0013 #include <linux/sched.h>
0014 #include <linux/slab.h>
0015
0016 #include <media/media-device.h>
0017 #include <media/videobuf2-v4l2.h>
0018 #include <media/v4l2-mem2mem.h>
0019 #include <media/v4l2-dev.h>
0020 #include <media/v4l2-device.h>
0021 #include <media/v4l2-fh.h>
0022 #include <media/v4l2-event.h>
0023
0024 MODULE_DESCRIPTION("Mem to mem device framework for videobuf");
0025 MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
0026 MODULE_LICENSE("GPL");
0027
0028 static bool debug;
0029 module_param(debug, bool, 0644);
0030
0031 #define dprintk(fmt, arg...) \
0032 do { \
0033 if (debug) \
0034 printk(KERN_DEBUG "%s: " fmt, __func__, ## arg);\
0035 } while (0)
0036
0037
0038
0039 #define TRANS_QUEUED (1 << 0)
0040
0041 #define TRANS_RUNNING (1 << 1)
0042
0043 #define TRANS_ABORT (1 << 2)
0044
0045
0046
0047 #define QUEUE_PAUSED (1 << 0)
0048
0049
0050
0051
0052
0053 #define DST_QUEUE_OFF_BASE (1 << 30)
0054
0055 enum v4l2_m2m_entity_type {
0056 MEM2MEM_ENT_TYPE_SOURCE,
0057 MEM2MEM_ENT_TYPE_SINK,
0058 MEM2MEM_ENT_TYPE_PROC
0059 };
0060
0061 static const char * const m2m_entity_name[] = {
0062 "source",
0063 "sink",
0064 "proc"
0065 };
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 struct v4l2_m2m_dev {
0095 struct v4l2_m2m_ctx *curr_ctx;
0096 #ifdef CONFIG_MEDIA_CONTROLLER
0097 struct media_entity *source;
0098 struct media_pad source_pad;
0099 struct media_entity sink;
0100 struct media_pad sink_pad;
0101 struct media_entity proc;
0102 struct media_pad proc_pads[2];
0103 struct media_intf_devnode *intf_devnode;
0104 #endif
0105
0106 struct list_head job_queue;
0107 spinlock_t job_spinlock;
0108 struct work_struct job_work;
0109 unsigned long job_queue_flags;
0110
0111 const struct v4l2_m2m_ops *m2m_ops;
0112 };
0113
0114 static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx,
0115 enum v4l2_buf_type type)
0116 {
0117 if (V4L2_TYPE_IS_OUTPUT(type))
0118 return &m2m_ctx->out_q_ctx;
0119 else
0120 return &m2m_ctx->cap_q_ctx;
0121 }
0122
0123 struct vb2_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
0124 enum v4l2_buf_type type)
0125 {
0126 struct v4l2_m2m_queue_ctx *q_ctx;
0127
0128 q_ctx = get_queue_ctx(m2m_ctx, type);
0129 if (!q_ctx)
0130 return NULL;
0131
0132 return &q_ctx->q;
0133 }
0134 EXPORT_SYMBOL(v4l2_m2m_get_vq);
0135
0136 struct vb2_v4l2_buffer *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx)
0137 {
0138 struct v4l2_m2m_buffer *b;
0139 unsigned long flags;
0140
0141 spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
0142
0143 if (list_empty(&q_ctx->rdy_queue)) {
0144 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
0145 return NULL;
0146 }
0147
0148 b = list_first_entry(&q_ctx->rdy_queue, struct v4l2_m2m_buffer, list);
0149 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
0150 return &b->vb;
0151 }
0152 EXPORT_SYMBOL_GPL(v4l2_m2m_next_buf);
0153
0154 struct vb2_v4l2_buffer *v4l2_m2m_last_buf(struct v4l2_m2m_queue_ctx *q_ctx)
0155 {
0156 struct v4l2_m2m_buffer *b;
0157 unsigned long flags;
0158
0159 spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
0160
0161 if (list_empty(&q_ctx->rdy_queue)) {
0162 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
0163 return NULL;
0164 }
0165
0166 b = list_last_entry(&q_ctx->rdy_queue, struct v4l2_m2m_buffer, list);
0167 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
0168 return &b->vb;
0169 }
0170 EXPORT_SYMBOL_GPL(v4l2_m2m_last_buf);
0171
0172 struct vb2_v4l2_buffer *v4l2_m2m_buf_remove(struct v4l2_m2m_queue_ctx *q_ctx)
0173 {
0174 struct v4l2_m2m_buffer *b;
0175 unsigned long flags;
0176
0177 spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
0178 if (list_empty(&q_ctx->rdy_queue)) {
0179 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
0180 return NULL;
0181 }
0182 b = list_first_entry(&q_ctx->rdy_queue, struct v4l2_m2m_buffer, list);
0183 list_del(&b->list);
0184 q_ctx->num_rdy--;
0185 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
0186
0187 return &b->vb;
0188 }
0189 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove);
0190
0191 void v4l2_m2m_buf_remove_by_buf(struct v4l2_m2m_queue_ctx *q_ctx,
0192 struct vb2_v4l2_buffer *vbuf)
0193 {
0194 struct v4l2_m2m_buffer *b;
0195 unsigned long flags;
0196
0197 spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
0198 b = container_of(vbuf, struct v4l2_m2m_buffer, vb);
0199 list_del(&b->list);
0200 q_ctx->num_rdy--;
0201 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
0202 }
0203 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove_by_buf);
0204
0205 struct vb2_v4l2_buffer *
0206 v4l2_m2m_buf_remove_by_idx(struct v4l2_m2m_queue_ctx *q_ctx, unsigned int idx)
0207
0208 {
0209 struct v4l2_m2m_buffer *b, *tmp;
0210 struct vb2_v4l2_buffer *ret = NULL;
0211 unsigned long flags;
0212
0213 spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
0214 list_for_each_entry_safe(b, tmp, &q_ctx->rdy_queue, list) {
0215 if (b->vb.vb2_buf.index == idx) {
0216 list_del(&b->list);
0217 q_ctx->num_rdy--;
0218 ret = &b->vb;
0219 break;
0220 }
0221 }
0222 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
0223
0224 return ret;
0225 }
0226 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove_by_idx);
0227
0228
0229
0230
0231
0232 void *v4l2_m2m_get_curr_priv(struct v4l2_m2m_dev *m2m_dev)
0233 {
0234 unsigned long flags;
0235 void *ret = NULL;
0236
0237 spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
0238 if (m2m_dev->curr_ctx)
0239 ret = m2m_dev->curr_ctx->priv;
0240 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0241
0242 return ret;
0243 }
0244 EXPORT_SYMBOL(v4l2_m2m_get_curr_priv);
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255 static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev)
0256 {
0257 unsigned long flags;
0258
0259 spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
0260 if (NULL != m2m_dev->curr_ctx) {
0261 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0262 dprintk("Another instance is running, won't run now\n");
0263 return;
0264 }
0265
0266 if (list_empty(&m2m_dev->job_queue)) {
0267 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0268 dprintk("No job pending\n");
0269 return;
0270 }
0271
0272 if (m2m_dev->job_queue_flags & QUEUE_PAUSED) {
0273 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0274 dprintk("Running new jobs is paused\n");
0275 return;
0276 }
0277
0278 m2m_dev->curr_ctx = list_first_entry(&m2m_dev->job_queue,
0279 struct v4l2_m2m_ctx, queue);
0280 m2m_dev->curr_ctx->job_flags |= TRANS_RUNNING;
0281 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0282
0283 dprintk("Running job on m2m_ctx: %p\n", m2m_dev->curr_ctx);
0284 m2m_dev->m2m_ops->device_run(m2m_dev->curr_ctx->priv);
0285 }
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296 static void __v4l2_m2m_try_queue(struct v4l2_m2m_dev *m2m_dev,
0297 struct v4l2_m2m_ctx *m2m_ctx)
0298 {
0299 unsigned long flags_job;
0300 struct vb2_v4l2_buffer *dst, *src;
0301
0302 dprintk("Trying to schedule a job for m2m_ctx: %p\n", m2m_ctx);
0303
0304 if (!m2m_ctx->out_q_ctx.q.streaming
0305 || !m2m_ctx->cap_q_ctx.q.streaming) {
0306 dprintk("Streaming needs to be on for both queues\n");
0307 return;
0308 }
0309
0310 spin_lock_irqsave(&m2m_dev->job_spinlock, flags_job);
0311
0312
0313 if (m2m_ctx->job_flags & TRANS_ABORT) {
0314 dprintk("Aborted context\n");
0315 goto job_unlock;
0316 }
0317
0318 if (m2m_ctx->job_flags & TRANS_QUEUED) {
0319 dprintk("On job queue already\n");
0320 goto job_unlock;
0321 }
0322
0323 src = v4l2_m2m_next_src_buf(m2m_ctx);
0324 dst = v4l2_m2m_next_dst_buf(m2m_ctx);
0325 if (!src && !m2m_ctx->out_q_ctx.buffered) {
0326 dprintk("No input buffers available\n");
0327 goto job_unlock;
0328 }
0329 if (!dst && !m2m_ctx->cap_q_ctx.buffered) {
0330 dprintk("No output buffers available\n");
0331 goto job_unlock;
0332 }
0333
0334 m2m_ctx->new_frame = true;
0335
0336 if (src && dst && dst->is_held &&
0337 dst->vb2_buf.copied_timestamp &&
0338 dst->vb2_buf.timestamp != src->vb2_buf.timestamp) {
0339 dprintk("Timestamp mismatch, returning held capture buffer\n");
0340 dst->is_held = false;
0341 v4l2_m2m_dst_buf_remove(m2m_ctx);
0342 v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE);
0343 dst = v4l2_m2m_next_dst_buf(m2m_ctx);
0344
0345 if (!dst && !m2m_ctx->cap_q_ctx.buffered) {
0346 dprintk("No output buffers available after returning held buffer\n");
0347 goto job_unlock;
0348 }
0349 }
0350
0351 if (src && dst && (m2m_ctx->out_q_ctx.q.subsystem_flags &
0352 VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF))
0353 m2m_ctx->new_frame = !dst->vb2_buf.copied_timestamp ||
0354 dst->vb2_buf.timestamp != src->vb2_buf.timestamp;
0355
0356 if (m2m_ctx->has_stopped) {
0357 dprintk("Device has stopped\n");
0358 goto job_unlock;
0359 }
0360
0361 if (m2m_dev->m2m_ops->job_ready
0362 && (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) {
0363 dprintk("Driver not ready\n");
0364 goto job_unlock;
0365 }
0366
0367 list_add_tail(&m2m_ctx->queue, &m2m_dev->job_queue);
0368 m2m_ctx->job_flags |= TRANS_QUEUED;
0369
0370 job_unlock:
0371 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
0372 }
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386 void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
0387 {
0388 struct v4l2_m2m_dev *m2m_dev = m2m_ctx->m2m_dev;
0389
0390 __v4l2_m2m_try_queue(m2m_dev, m2m_ctx);
0391 v4l2_m2m_try_run(m2m_dev);
0392 }
0393 EXPORT_SYMBOL_GPL(v4l2_m2m_try_schedule);
0394
0395
0396
0397
0398
0399 static void v4l2_m2m_device_run_work(struct work_struct *work)
0400 {
0401 struct v4l2_m2m_dev *m2m_dev =
0402 container_of(work, struct v4l2_m2m_dev, job_work);
0403
0404 v4l2_m2m_try_run(m2m_dev);
0405 }
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416 static void v4l2_m2m_cancel_job(struct v4l2_m2m_ctx *m2m_ctx)
0417 {
0418 struct v4l2_m2m_dev *m2m_dev;
0419 unsigned long flags;
0420
0421 m2m_dev = m2m_ctx->m2m_dev;
0422 spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
0423
0424 m2m_ctx->job_flags |= TRANS_ABORT;
0425 if (m2m_ctx->job_flags & TRANS_RUNNING) {
0426 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0427 if (m2m_dev->m2m_ops->job_abort)
0428 m2m_dev->m2m_ops->job_abort(m2m_ctx->priv);
0429 dprintk("m2m_ctx %p running, will wait to complete\n", m2m_ctx);
0430 wait_event(m2m_ctx->finished,
0431 !(m2m_ctx->job_flags & TRANS_RUNNING));
0432 } else if (m2m_ctx->job_flags & TRANS_QUEUED) {
0433 list_del(&m2m_ctx->queue);
0434 m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
0435 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0436 dprintk("m2m_ctx: %p had been on queue and was removed\n",
0437 m2m_ctx);
0438 } else {
0439
0440 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0441 }
0442 }
0443
0444
0445
0446
0447
0448 static void v4l2_m2m_schedule_next_job(struct v4l2_m2m_dev *m2m_dev,
0449 struct v4l2_m2m_ctx *m2m_ctx)
0450 {
0451
0452
0453
0454
0455
0456 __v4l2_m2m_try_queue(m2m_dev, m2m_ctx);
0457
0458
0459
0460
0461
0462 schedule_work(&m2m_dev->job_work);
0463 }
0464
0465
0466
0467
0468
0469 static bool _v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev,
0470 struct v4l2_m2m_ctx *m2m_ctx)
0471 {
0472 if (!m2m_dev->curr_ctx || m2m_dev->curr_ctx != m2m_ctx) {
0473 dprintk("Called by an instance not currently running\n");
0474 return false;
0475 }
0476
0477 list_del(&m2m_dev->curr_ctx->queue);
0478 m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
0479 wake_up(&m2m_dev->curr_ctx->finished);
0480 m2m_dev->curr_ctx = NULL;
0481 return true;
0482 }
0483
0484 void v4l2_m2m_job_finish(struct v4l2_m2m_dev *m2m_dev,
0485 struct v4l2_m2m_ctx *m2m_ctx)
0486 {
0487 unsigned long flags;
0488 bool schedule_next;
0489
0490
0491
0492
0493
0494
0495 WARN_ON(m2m_ctx->out_q_ctx.q.subsystem_flags &
0496 VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF);
0497 spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
0498 schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx);
0499 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0500
0501 if (schedule_next)
0502 v4l2_m2m_schedule_next_job(m2m_dev, m2m_ctx);
0503 }
0504 EXPORT_SYMBOL(v4l2_m2m_job_finish);
0505
0506 void v4l2_m2m_buf_done_and_job_finish(struct v4l2_m2m_dev *m2m_dev,
0507 struct v4l2_m2m_ctx *m2m_ctx,
0508 enum vb2_buffer_state state)
0509 {
0510 struct vb2_v4l2_buffer *src_buf, *dst_buf;
0511 bool schedule_next = false;
0512 unsigned long flags;
0513
0514 spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
0515 src_buf = v4l2_m2m_src_buf_remove(m2m_ctx);
0516 dst_buf = v4l2_m2m_next_dst_buf(m2m_ctx);
0517
0518 if (WARN_ON(!src_buf || !dst_buf))
0519 goto unlock;
0520 dst_buf->is_held = src_buf->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF;
0521 if (!dst_buf->is_held) {
0522 v4l2_m2m_dst_buf_remove(m2m_ctx);
0523 v4l2_m2m_buf_done(dst_buf, state);
0524 }
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534 v4l2_m2m_buf_done(src_buf, state);
0535 schedule_next = _v4l2_m2m_job_finish(m2m_dev, m2m_ctx);
0536 unlock:
0537 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0538
0539 if (schedule_next)
0540 v4l2_m2m_schedule_next_job(m2m_dev, m2m_ctx);
0541 }
0542 EXPORT_SYMBOL(v4l2_m2m_buf_done_and_job_finish);
0543
0544 void v4l2_m2m_suspend(struct v4l2_m2m_dev *m2m_dev)
0545 {
0546 unsigned long flags;
0547 struct v4l2_m2m_ctx *curr_ctx;
0548
0549 spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
0550 m2m_dev->job_queue_flags |= QUEUE_PAUSED;
0551 curr_ctx = m2m_dev->curr_ctx;
0552 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0553
0554 if (curr_ctx)
0555 wait_event(curr_ctx->finished,
0556 !(curr_ctx->job_flags & TRANS_RUNNING));
0557 }
0558 EXPORT_SYMBOL(v4l2_m2m_suspend);
0559
0560 void v4l2_m2m_resume(struct v4l2_m2m_dev *m2m_dev)
0561 {
0562 unsigned long flags;
0563
0564 spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
0565 m2m_dev->job_queue_flags &= ~QUEUE_PAUSED;
0566 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
0567
0568 v4l2_m2m_try_run(m2m_dev);
0569 }
0570 EXPORT_SYMBOL(v4l2_m2m_resume);
0571
0572 int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0573 struct v4l2_requestbuffers *reqbufs)
0574 {
0575 struct vb2_queue *vq;
0576 int ret;
0577
0578 vq = v4l2_m2m_get_vq(m2m_ctx, reqbufs->type);
0579 ret = vb2_reqbufs(vq, reqbufs);
0580
0581
0582 if (ret == 0)
0583 vq->owner = reqbufs->count ? file->private_data : NULL;
0584
0585 return ret;
0586 }
0587 EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs);
0588
0589 static void v4l2_m2m_adjust_mem_offset(struct vb2_queue *vq,
0590 struct v4l2_buffer *buf)
0591 {
0592
0593 if (buf->memory == V4L2_MEMORY_MMAP && V4L2_TYPE_IS_CAPTURE(vq->type)) {
0594 if (V4L2_TYPE_IS_MULTIPLANAR(vq->type)) {
0595 unsigned int i;
0596
0597 for (i = 0; i < buf->length; ++i)
0598 buf->m.planes[i].m.mem_offset
0599 += DST_QUEUE_OFF_BASE;
0600 } else {
0601 buf->m.offset += DST_QUEUE_OFF_BASE;
0602 }
0603 }
0604 }
0605
0606 int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0607 struct v4l2_buffer *buf)
0608 {
0609 struct vb2_queue *vq;
0610 int ret;
0611
0612 vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
0613 ret = vb2_querybuf(vq, buf);
0614 if (ret)
0615 return ret;
0616
0617
0618 v4l2_m2m_adjust_mem_offset(vq, buf);
0619
0620 return 0;
0621 }
0622 EXPORT_SYMBOL_GPL(v4l2_m2m_querybuf);
0623
0624
0625
0626
0627
0628
0629
0630
0631 void v4l2_m2m_last_buffer_done(struct v4l2_m2m_ctx *m2m_ctx,
0632 struct vb2_v4l2_buffer *vbuf)
0633 {
0634 vbuf->flags |= V4L2_BUF_FLAG_LAST;
0635 vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
0636
0637 v4l2_m2m_mark_stopped(m2m_ctx);
0638 }
0639 EXPORT_SYMBOL_GPL(v4l2_m2m_last_buffer_done);
0640
0641
0642 static int v4l2_update_last_buf_state(struct v4l2_m2m_ctx *m2m_ctx)
0643 {
0644 struct vb2_v4l2_buffer *next_dst_buf;
0645
0646 if (m2m_ctx->is_draining)
0647 return -EBUSY;
0648
0649 if (m2m_ctx->has_stopped)
0650 return 0;
0651
0652 m2m_ctx->last_src_buf = v4l2_m2m_last_src_buf(m2m_ctx);
0653 m2m_ctx->is_draining = true;
0654
0655
0656
0657
0658
0659
0660 if (m2m_ctx->last_src_buf)
0661 return 0;
0662
0663
0664
0665
0666
0667 next_dst_buf = v4l2_m2m_dst_buf_remove(m2m_ctx);
0668 if (!next_dst_buf) {
0669
0670
0671
0672
0673
0674
0675 m2m_ctx->next_buf_last = true;
0676 return 0;
0677 }
0678
0679 v4l2_m2m_last_buffer_done(m2m_ctx, next_dst_buf);
0680
0681 return 0;
0682 }
0683
0684
0685
0686
0687
0688 void v4l2_m2m_update_start_streaming_state(struct v4l2_m2m_ctx *m2m_ctx,
0689 struct vb2_queue *q)
0690 {
0691
0692 if (V4L2_TYPE_IS_OUTPUT(q->type))
0693 m2m_ctx->last_src_buf = NULL;
0694 }
0695 EXPORT_SYMBOL_GPL(v4l2_m2m_update_start_streaming_state);
0696
0697
0698
0699
0700
0701 void v4l2_m2m_update_stop_streaming_state(struct v4l2_m2m_ctx *m2m_ctx,
0702 struct vb2_queue *q)
0703 {
0704 if (V4L2_TYPE_IS_OUTPUT(q->type)) {
0705
0706
0707
0708
0709
0710
0711
0712 if (m2m_ctx->is_draining) {
0713 struct vb2_v4l2_buffer *next_dst_buf;
0714
0715 m2m_ctx->last_src_buf = NULL;
0716 next_dst_buf = v4l2_m2m_dst_buf_remove(m2m_ctx);
0717 if (!next_dst_buf)
0718 m2m_ctx->next_buf_last = true;
0719 else
0720 v4l2_m2m_last_buffer_done(m2m_ctx,
0721 next_dst_buf);
0722 }
0723 } else {
0724 v4l2_m2m_clear_state(m2m_ctx);
0725 }
0726 }
0727 EXPORT_SYMBOL_GPL(v4l2_m2m_update_stop_streaming_state);
0728
0729 static void v4l2_m2m_force_last_buf_done(struct v4l2_m2m_ctx *m2m_ctx,
0730 struct vb2_queue *q)
0731 {
0732 struct vb2_buffer *vb;
0733 struct vb2_v4l2_buffer *vbuf;
0734 unsigned int i;
0735
0736 if (WARN_ON(q->is_output))
0737 return;
0738 if (list_empty(&q->queued_list))
0739 return;
0740
0741 vb = list_first_entry(&q->queued_list, struct vb2_buffer, queued_entry);
0742 for (i = 0; i < vb->num_planes; i++)
0743 vb2_set_plane_payload(vb, i, 0);
0744
0745
0746
0747
0748
0749 vb->state = VB2_BUF_STATE_ACTIVE;
0750 atomic_inc(&q->owned_by_drv_count);
0751
0752 vbuf = to_vb2_v4l2_buffer(vb);
0753 vbuf->field = V4L2_FIELD_NONE;
0754
0755 v4l2_m2m_last_buffer_done(m2m_ctx, vbuf);
0756 }
0757
0758 int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0759 struct v4l2_buffer *buf)
0760 {
0761 struct video_device *vdev = video_devdata(file);
0762 struct vb2_queue *vq;
0763 int ret;
0764
0765 vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
0766 if (V4L2_TYPE_IS_CAPTURE(vq->type) &&
0767 (buf->flags & V4L2_BUF_FLAG_REQUEST_FD)) {
0768 dprintk("%s: requests cannot be used with capture buffers\n",
0769 __func__);
0770 return -EPERM;
0771 }
0772
0773 ret = vb2_qbuf(vq, vdev->v4l2_dev->mdev, buf);
0774 if (ret)
0775 return ret;
0776
0777
0778 v4l2_m2m_adjust_mem_offset(vq, buf);
0779
0780
0781
0782
0783
0784
0785
0786 if (V4L2_TYPE_IS_CAPTURE(vq->type) &&
0787 vb2_is_streaming(vq) && !vb2_start_streaming_called(vq) &&
0788 (v4l2_m2m_has_stopped(m2m_ctx) || v4l2_m2m_dst_buf_is_last(m2m_ctx)))
0789 v4l2_m2m_force_last_buf_done(m2m_ctx, vq);
0790 else if (!(buf->flags & V4L2_BUF_FLAG_IN_REQUEST))
0791 v4l2_m2m_try_schedule(m2m_ctx);
0792
0793 return 0;
0794 }
0795 EXPORT_SYMBOL_GPL(v4l2_m2m_qbuf);
0796
0797 int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0798 struct v4l2_buffer *buf)
0799 {
0800 struct vb2_queue *vq;
0801 int ret;
0802
0803 vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
0804 ret = vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
0805 if (ret)
0806 return ret;
0807
0808
0809 v4l2_m2m_adjust_mem_offset(vq, buf);
0810
0811 return 0;
0812 }
0813 EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
0814
0815 int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0816 struct v4l2_buffer *buf)
0817 {
0818 struct video_device *vdev = video_devdata(file);
0819 struct vb2_queue *vq;
0820 int ret;
0821
0822 vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
0823 ret = vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
0824 if (ret)
0825 return ret;
0826
0827
0828 v4l2_m2m_adjust_mem_offset(vq, buf);
0829
0830 return 0;
0831 }
0832 EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
0833
0834 int v4l2_m2m_create_bufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0835 struct v4l2_create_buffers *create)
0836 {
0837 struct vb2_queue *vq;
0838
0839 vq = v4l2_m2m_get_vq(m2m_ctx, create->format.type);
0840 return vb2_create_bufs(vq, create);
0841 }
0842 EXPORT_SYMBOL_GPL(v4l2_m2m_create_bufs);
0843
0844 int v4l2_m2m_expbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0845 struct v4l2_exportbuffer *eb)
0846 {
0847 struct vb2_queue *vq;
0848
0849 vq = v4l2_m2m_get_vq(m2m_ctx, eb->type);
0850 return vb2_expbuf(vq, eb);
0851 }
0852 EXPORT_SYMBOL_GPL(v4l2_m2m_expbuf);
0853
0854 int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0855 enum v4l2_buf_type type)
0856 {
0857 struct vb2_queue *vq;
0858 int ret;
0859
0860 vq = v4l2_m2m_get_vq(m2m_ctx, type);
0861 ret = vb2_streamon(vq, type);
0862 if (!ret)
0863 v4l2_m2m_try_schedule(m2m_ctx);
0864
0865 return ret;
0866 }
0867 EXPORT_SYMBOL_GPL(v4l2_m2m_streamon);
0868
0869 int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0870 enum v4l2_buf_type type)
0871 {
0872 struct v4l2_m2m_dev *m2m_dev;
0873 struct v4l2_m2m_queue_ctx *q_ctx;
0874 unsigned long flags_job, flags;
0875 int ret;
0876
0877
0878 v4l2_m2m_cancel_job(m2m_ctx);
0879
0880 q_ctx = get_queue_ctx(m2m_ctx, type);
0881 ret = vb2_streamoff(&q_ctx->q, type);
0882 if (ret)
0883 return ret;
0884
0885 m2m_dev = m2m_ctx->m2m_dev;
0886 spin_lock_irqsave(&m2m_dev->job_spinlock, flags_job);
0887
0888 if (m2m_ctx->job_flags & TRANS_QUEUED)
0889 list_del(&m2m_ctx->queue);
0890 m2m_ctx->job_flags = 0;
0891
0892 spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
0893
0894
0895 INIT_LIST_HEAD(&q_ctx->rdy_queue);
0896 q_ctx->num_rdy = 0;
0897 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
0898
0899 if (m2m_dev->curr_ctx == m2m_ctx) {
0900 m2m_dev->curr_ctx = NULL;
0901 wake_up(&m2m_ctx->finished);
0902 }
0903 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
0904
0905 return 0;
0906 }
0907 EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff);
0908
0909 static __poll_t v4l2_m2m_poll_for_data(struct file *file,
0910 struct v4l2_m2m_ctx *m2m_ctx,
0911 struct poll_table_struct *wait)
0912 {
0913 struct vb2_queue *src_q, *dst_q;
0914 __poll_t rc = 0;
0915 unsigned long flags;
0916
0917 src_q = v4l2_m2m_get_src_vq(m2m_ctx);
0918 dst_q = v4l2_m2m_get_dst_vq(m2m_ctx);
0919
0920
0921
0922
0923
0924
0925 if ((!src_q->streaming || src_q->error ||
0926 list_empty(&src_q->queued_list)) &&
0927 (!dst_q->streaming || dst_q->error ||
0928 (list_empty(&dst_q->queued_list) && !dst_q->last_buffer_dequeued)))
0929 return EPOLLERR;
0930
0931 spin_lock_irqsave(&src_q->done_lock, flags);
0932 if (!list_empty(&src_q->done_list))
0933 rc |= EPOLLOUT | EPOLLWRNORM;
0934 spin_unlock_irqrestore(&src_q->done_lock, flags);
0935
0936 spin_lock_irqsave(&dst_q->done_lock, flags);
0937
0938
0939
0940
0941 if (!list_empty(&dst_q->done_list) || dst_q->last_buffer_dequeued)
0942 rc |= EPOLLIN | EPOLLRDNORM;
0943 spin_unlock_irqrestore(&dst_q->done_lock, flags);
0944
0945 return rc;
0946 }
0947
0948 __poll_t v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0949 struct poll_table_struct *wait)
0950 {
0951 struct video_device *vfd = video_devdata(file);
0952 struct vb2_queue *src_q = v4l2_m2m_get_src_vq(m2m_ctx);
0953 struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(m2m_ctx);
0954 __poll_t req_events = poll_requested_events(wait);
0955 __poll_t rc = 0;
0956
0957
0958
0959
0960
0961
0962
0963
0964 poll_wait(file, &src_q->done_wq, wait);
0965 poll_wait(file, &dst_q->done_wq, wait);
0966
0967 if (req_events & (EPOLLOUT | EPOLLWRNORM | EPOLLIN | EPOLLRDNORM))
0968 rc = v4l2_m2m_poll_for_data(file, m2m_ctx, wait);
0969
0970 if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
0971 struct v4l2_fh *fh = file->private_data;
0972
0973 poll_wait(file, &fh->wait, wait);
0974 if (v4l2_event_pending(fh))
0975 rc |= EPOLLPRI;
0976 }
0977
0978 return rc;
0979 }
0980 EXPORT_SYMBOL_GPL(v4l2_m2m_poll);
0981
0982 int v4l2_m2m_mmap(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
0983 struct vm_area_struct *vma)
0984 {
0985 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
0986 struct vb2_queue *vq;
0987
0988 if (offset < DST_QUEUE_OFF_BASE) {
0989 vq = v4l2_m2m_get_src_vq(m2m_ctx);
0990 } else {
0991 vq = v4l2_m2m_get_dst_vq(m2m_ctx);
0992 vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT);
0993 }
0994
0995 return vb2_mmap(vq, vma);
0996 }
0997 EXPORT_SYMBOL(v4l2_m2m_mmap);
0998
0999 #ifndef CONFIG_MMU
1000 unsigned long v4l2_m2m_get_unmapped_area(struct file *file, unsigned long addr,
1001 unsigned long len, unsigned long pgoff,
1002 unsigned long flags)
1003 {
1004 struct v4l2_fh *fh = file->private_data;
1005 unsigned long offset = pgoff << PAGE_SHIFT;
1006 struct vb2_queue *vq;
1007
1008 if (offset < DST_QUEUE_OFF_BASE) {
1009 vq = v4l2_m2m_get_src_vq(fh->m2m_ctx);
1010 } else {
1011 vq = v4l2_m2m_get_dst_vq(fh->m2m_ctx);
1012 pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT);
1013 }
1014
1015 return vb2_get_unmapped_area(vq, addr, len, pgoff, flags);
1016 }
1017 EXPORT_SYMBOL_GPL(v4l2_m2m_get_unmapped_area);
1018 #endif
1019
1020 #if defined(CONFIG_MEDIA_CONTROLLER)
1021 void v4l2_m2m_unregister_media_controller(struct v4l2_m2m_dev *m2m_dev)
1022 {
1023 media_remove_intf_links(&m2m_dev->intf_devnode->intf);
1024 media_devnode_remove(m2m_dev->intf_devnode);
1025
1026 media_entity_remove_links(m2m_dev->source);
1027 media_entity_remove_links(&m2m_dev->sink);
1028 media_entity_remove_links(&m2m_dev->proc);
1029 media_device_unregister_entity(m2m_dev->source);
1030 media_device_unregister_entity(&m2m_dev->sink);
1031 media_device_unregister_entity(&m2m_dev->proc);
1032 kfree(m2m_dev->source->name);
1033 kfree(m2m_dev->sink.name);
1034 kfree(m2m_dev->proc.name);
1035 }
1036 EXPORT_SYMBOL_GPL(v4l2_m2m_unregister_media_controller);
1037
1038 static int v4l2_m2m_register_entity(struct media_device *mdev,
1039 struct v4l2_m2m_dev *m2m_dev, enum v4l2_m2m_entity_type type,
1040 struct video_device *vdev, int function)
1041 {
1042 struct media_entity *entity;
1043 struct media_pad *pads;
1044 char *name;
1045 unsigned int len;
1046 int num_pads;
1047 int ret;
1048
1049 switch (type) {
1050 case MEM2MEM_ENT_TYPE_SOURCE:
1051 entity = m2m_dev->source;
1052 pads = &m2m_dev->source_pad;
1053 pads[0].flags = MEDIA_PAD_FL_SOURCE;
1054 num_pads = 1;
1055 break;
1056 case MEM2MEM_ENT_TYPE_SINK:
1057 entity = &m2m_dev->sink;
1058 pads = &m2m_dev->sink_pad;
1059 pads[0].flags = MEDIA_PAD_FL_SINK;
1060 num_pads = 1;
1061 break;
1062 case MEM2MEM_ENT_TYPE_PROC:
1063 entity = &m2m_dev->proc;
1064 pads = m2m_dev->proc_pads;
1065 pads[0].flags = MEDIA_PAD_FL_SINK;
1066 pads[1].flags = MEDIA_PAD_FL_SOURCE;
1067 num_pads = 2;
1068 break;
1069 default:
1070 return -EINVAL;
1071 }
1072
1073 entity->obj_type = MEDIA_ENTITY_TYPE_BASE;
1074 if (type != MEM2MEM_ENT_TYPE_PROC) {
1075 entity->info.dev.major = VIDEO_MAJOR;
1076 entity->info.dev.minor = vdev->minor;
1077 }
1078 len = strlen(vdev->name) + 2 + strlen(m2m_entity_name[type]);
1079 name = kmalloc(len, GFP_KERNEL);
1080 if (!name)
1081 return -ENOMEM;
1082 snprintf(name, len, "%s-%s", vdev->name, m2m_entity_name[type]);
1083 entity->name = name;
1084 entity->function = function;
1085
1086 ret = media_entity_pads_init(entity, num_pads, pads);
1087 if (ret)
1088 return ret;
1089 ret = media_device_register_entity(mdev, entity);
1090 if (ret)
1091 return ret;
1092
1093 return 0;
1094 }
1095
1096 int v4l2_m2m_register_media_controller(struct v4l2_m2m_dev *m2m_dev,
1097 struct video_device *vdev, int function)
1098 {
1099 struct media_device *mdev = vdev->v4l2_dev->mdev;
1100 struct media_link *link;
1101 int ret;
1102
1103 if (!mdev)
1104 return 0;
1105
1106
1107
1108
1109
1110
1111
1112 m2m_dev->source = &vdev->entity;
1113 ret = v4l2_m2m_register_entity(mdev, m2m_dev,
1114 MEM2MEM_ENT_TYPE_SOURCE, vdev, MEDIA_ENT_F_IO_V4L);
1115 if (ret)
1116 return ret;
1117 ret = v4l2_m2m_register_entity(mdev, m2m_dev,
1118 MEM2MEM_ENT_TYPE_PROC, vdev, function);
1119 if (ret)
1120 goto err_rel_entity0;
1121 ret = v4l2_m2m_register_entity(mdev, m2m_dev,
1122 MEM2MEM_ENT_TYPE_SINK, vdev, MEDIA_ENT_F_IO_V4L);
1123 if (ret)
1124 goto err_rel_entity1;
1125
1126
1127 ret = media_create_pad_link(m2m_dev->source, 0, &m2m_dev->proc, 0,
1128 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
1129 if (ret)
1130 goto err_rel_entity2;
1131
1132 ret = media_create_pad_link(&m2m_dev->proc, 1, &m2m_dev->sink, 0,
1133 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
1134 if (ret)
1135 goto err_rm_links0;
1136
1137
1138 m2m_dev->intf_devnode = media_devnode_create(mdev,
1139 MEDIA_INTF_T_V4L_VIDEO, 0,
1140 VIDEO_MAJOR, vdev->minor);
1141 if (!m2m_dev->intf_devnode) {
1142 ret = -ENOMEM;
1143 goto err_rm_links1;
1144 }
1145
1146
1147 link = media_create_intf_link(m2m_dev->source,
1148 &m2m_dev->intf_devnode->intf,
1149 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
1150 if (!link) {
1151 ret = -ENOMEM;
1152 goto err_rm_devnode;
1153 }
1154
1155 link = media_create_intf_link(&m2m_dev->sink,
1156 &m2m_dev->intf_devnode->intf,
1157 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
1158 if (!link) {
1159 ret = -ENOMEM;
1160 goto err_rm_intf_link;
1161 }
1162 return 0;
1163
1164 err_rm_intf_link:
1165 media_remove_intf_links(&m2m_dev->intf_devnode->intf);
1166 err_rm_devnode:
1167 media_devnode_remove(m2m_dev->intf_devnode);
1168 err_rm_links1:
1169 media_entity_remove_links(&m2m_dev->sink);
1170 err_rm_links0:
1171 media_entity_remove_links(&m2m_dev->proc);
1172 media_entity_remove_links(m2m_dev->source);
1173 err_rel_entity2:
1174 media_device_unregister_entity(&m2m_dev->proc);
1175 kfree(m2m_dev->proc.name);
1176 err_rel_entity1:
1177 media_device_unregister_entity(&m2m_dev->sink);
1178 kfree(m2m_dev->sink.name);
1179 err_rel_entity0:
1180 media_device_unregister_entity(m2m_dev->source);
1181 kfree(m2m_dev->source->name);
1182 return ret;
1183 return 0;
1184 }
1185 EXPORT_SYMBOL_GPL(v4l2_m2m_register_media_controller);
1186 #endif
1187
1188 struct v4l2_m2m_dev *v4l2_m2m_init(const struct v4l2_m2m_ops *m2m_ops)
1189 {
1190 struct v4l2_m2m_dev *m2m_dev;
1191
1192 if (!m2m_ops || WARN_ON(!m2m_ops->device_run))
1193 return ERR_PTR(-EINVAL);
1194
1195 m2m_dev = kzalloc(sizeof *m2m_dev, GFP_KERNEL);
1196 if (!m2m_dev)
1197 return ERR_PTR(-ENOMEM);
1198
1199 m2m_dev->curr_ctx = NULL;
1200 m2m_dev->m2m_ops = m2m_ops;
1201 INIT_LIST_HEAD(&m2m_dev->job_queue);
1202 spin_lock_init(&m2m_dev->job_spinlock);
1203 INIT_WORK(&m2m_dev->job_work, v4l2_m2m_device_run_work);
1204
1205 return m2m_dev;
1206 }
1207 EXPORT_SYMBOL_GPL(v4l2_m2m_init);
1208
1209 void v4l2_m2m_release(struct v4l2_m2m_dev *m2m_dev)
1210 {
1211 kfree(m2m_dev);
1212 }
1213 EXPORT_SYMBOL_GPL(v4l2_m2m_release);
1214
1215 struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
1216 void *drv_priv,
1217 int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq))
1218 {
1219 struct v4l2_m2m_ctx *m2m_ctx;
1220 struct v4l2_m2m_queue_ctx *out_q_ctx, *cap_q_ctx;
1221 int ret;
1222
1223 m2m_ctx = kzalloc(sizeof *m2m_ctx, GFP_KERNEL);
1224 if (!m2m_ctx)
1225 return ERR_PTR(-ENOMEM);
1226
1227 m2m_ctx->priv = drv_priv;
1228 m2m_ctx->m2m_dev = m2m_dev;
1229 init_waitqueue_head(&m2m_ctx->finished);
1230
1231 out_q_ctx = &m2m_ctx->out_q_ctx;
1232 cap_q_ctx = &m2m_ctx->cap_q_ctx;
1233
1234 INIT_LIST_HEAD(&out_q_ctx->rdy_queue);
1235 INIT_LIST_HEAD(&cap_q_ctx->rdy_queue);
1236 spin_lock_init(&out_q_ctx->rdy_spinlock);
1237 spin_lock_init(&cap_q_ctx->rdy_spinlock);
1238
1239 INIT_LIST_HEAD(&m2m_ctx->queue);
1240
1241 ret = queue_init(drv_priv, &out_q_ctx->q, &cap_q_ctx->q);
1242
1243 if (ret)
1244 goto err;
1245
1246
1247
1248
1249 if (WARN_ON(out_q_ctx->q.lock != cap_q_ctx->q.lock)) {
1250 ret = -EINVAL;
1251 goto err;
1252 }
1253 m2m_ctx->q_lock = out_q_ctx->q.lock;
1254
1255 return m2m_ctx;
1256 err:
1257 kfree(m2m_ctx);
1258 return ERR_PTR(ret);
1259 }
1260 EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init);
1261
1262 void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx)
1263 {
1264
1265 v4l2_m2m_cancel_job(m2m_ctx);
1266
1267 vb2_queue_release(&m2m_ctx->cap_q_ctx.q);
1268 vb2_queue_release(&m2m_ctx->out_q_ctx.q);
1269
1270 kfree(m2m_ctx);
1271 }
1272 EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_release);
1273
1274 void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx,
1275 struct vb2_v4l2_buffer *vbuf)
1276 {
1277 struct v4l2_m2m_buffer *b = container_of(vbuf,
1278 struct v4l2_m2m_buffer, vb);
1279 struct v4l2_m2m_queue_ctx *q_ctx;
1280 unsigned long flags;
1281
1282 q_ctx = get_queue_ctx(m2m_ctx, vbuf->vb2_buf.vb2_queue->type);
1283 if (!q_ctx)
1284 return;
1285
1286 spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
1287 list_add_tail(&b->list, &q_ctx->rdy_queue);
1288 q_ctx->num_rdy++;
1289 spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
1290 }
1291 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue);
1292
1293 void v4l2_m2m_buf_copy_metadata(const struct vb2_v4l2_buffer *out_vb,
1294 struct vb2_v4l2_buffer *cap_vb,
1295 bool copy_frame_flags)
1296 {
1297 u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
1298
1299 if (copy_frame_flags)
1300 mask |= V4L2_BUF_FLAG_KEYFRAME | V4L2_BUF_FLAG_PFRAME |
1301 V4L2_BUF_FLAG_BFRAME;
1302
1303 cap_vb->vb2_buf.timestamp = out_vb->vb2_buf.timestamp;
1304
1305 if (out_vb->flags & V4L2_BUF_FLAG_TIMECODE)
1306 cap_vb->timecode = out_vb->timecode;
1307 cap_vb->field = out_vb->field;
1308 cap_vb->flags &= ~mask;
1309 cap_vb->flags |= out_vb->flags & mask;
1310 cap_vb->vb2_buf.copied_timestamp = 1;
1311 }
1312 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_copy_metadata);
1313
1314 void v4l2_m2m_request_queue(struct media_request *req)
1315 {
1316 struct media_request_object *obj, *obj_safe;
1317 struct v4l2_m2m_ctx *m2m_ctx = NULL;
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327 list_for_each_entry_safe(obj, obj_safe, &req->objects, list) {
1328 struct v4l2_m2m_ctx *m2m_ctx_obj;
1329 struct vb2_buffer *vb;
1330
1331 if (!obj->ops->queue)
1332 continue;
1333
1334 if (vb2_request_object_is_buffer(obj)) {
1335
1336 vb = container_of(obj, struct vb2_buffer, req_obj);
1337 WARN_ON(!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type));
1338 m2m_ctx_obj = container_of(vb->vb2_queue,
1339 struct v4l2_m2m_ctx,
1340 out_q_ctx.q);
1341 WARN_ON(m2m_ctx && m2m_ctx_obj != m2m_ctx);
1342 m2m_ctx = m2m_ctx_obj;
1343 }
1344
1345
1346
1347
1348
1349
1350 obj->ops->queue(obj);
1351 }
1352
1353 WARN_ON(!m2m_ctx);
1354
1355 if (m2m_ctx)
1356 v4l2_m2m_try_schedule(m2m_ctx);
1357 }
1358 EXPORT_SYMBOL_GPL(v4l2_m2m_request_queue);
1359
1360
1361
1362 int v4l2_m2m_ioctl_reqbufs(struct file *file, void *priv,
1363 struct v4l2_requestbuffers *rb)
1364 {
1365 struct v4l2_fh *fh = file->private_data;
1366
1367 return v4l2_m2m_reqbufs(file, fh->m2m_ctx, rb);
1368 }
1369 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_reqbufs);
1370
1371 int v4l2_m2m_ioctl_create_bufs(struct file *file, void *priv,
1372 struct v4l2_create_buffers *create)
1373 {
1374 struct v4l2_fh *fh = file->private_data;
1375
1376 return v4l2_m2m_create_bufs(file, fh->m2m_ctx, create);
1377 }
1378 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_create_bufs);
1379
1380 int v4l2_m2m_ioctl_querybuf(struct file *file, void *priv,
1381 struct v4l2_buffer *buf)
1382 {
1383 struct v4l2_fh *fh = file->private_data;
1384
1385 return v4l2_m2m_querybuf(file, fh->m2m_ctx, buf);
1386 }
1387 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_querybuf);
1388
1389 int v4l2_m2m_ioctl_qbuf(struct file *file, void *priv,
1390 struct v4l2_buffer *buf)
1391 {
1392 struct v4l2_fh *fh = file->private_data;
1393
1394 return v4l2_m2m_qbuf(file, fh->m2m_ctx, buf);
1395 }
1396 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_qbuf);
1397
1398 int v4l2_m2m_ioctl_dqbuf(struct file *file, void *priv,
1399 struct v4l2_buffer *buf)
1400 {
1401 struct v4l2_fh *fh = file->private_data;
1402
1403 return v4l2_m2m_dqbuf(file, fh->m2m_ctx, buf);
1404 }
1405 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_dqbuf);
1406
1407 int v4l2_m2m_ioctl_prepare_buf(struct file *file, void *priv,
1408 struct v4l2_buffer *buf)
1409 {
1410 struct v4l2_fh *fh = file->private_data;
1411
1412 return v4l2_m2m_prepare_buf(file, fh->m2m_ctx, buf);
1413 }
1414 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_prepare_buf);
1415
1416 int v4l2_m2m_ioctl_expbuf(struct file *file, void *priv,
1417 struct v4l2_exportbuffer *eb)
1418 {
1419 struct v4l2_fh *fh = file->private_data;
1420
1421 return v4l2_m2m_expbuf(file, fh->m2m_ctx, eb);
1422 }
1423 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_expbuf);
1424
1425 int v4l2_m2m_ioctl_streamon(struct file *file, void *priv,
1426 enum v4l2_buf_type type)
1427 {
1428 struct v4l2_fh *fh = file->private_data;
1429
1430 return v4l2_m2m_streamon(file, fh->m2m_ctx, type);
1431 }
1432 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamon);
1433
1434 int v4l2_m2m_ioctl_streamoff(struct file *file, void *priv,
1435 enum v4l2_buf_type type)
1436 {
1437 struct v4l2_fh *fh = file->private_data;
1438
1439 return v4l2_m2m_streamoff(file, fh->m2m_ctx, type);
1440 }
1441 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_streamoff);
1442
1443 int v4l2_m2m_ioctl_try_encoder_cmd(struct file *file, void *fh,
1444 struct v4l2_encoder_cmd *ec)
1445 {
1446 if (ec->cmd != V4L2_ENC_CMD_STOP && ec->cmd != V4L2_ENC_CMD_START)
1447 return -EINVAL;
1448
1449 ec->flags = 0;
1450 return 0;
1451 }
1452 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_try_encoder_cmd);
1453
1454 int v4l2_m2m_ioctl_try_decoder_cmd(struct file *file, void *fh,
1455 struct v4l2_decoder_cmd *dc)
1456 {
1457 if (dc->cmd != V4L2_DEC_CMD_STOP && dc->cmd != V4L2_DEC_CMD_START)
1458 return -EINVAL;
1459
1460 dc->flags = 0;
1461
1462 if (dc->cmd == V4L2_DEC_CMD_STOP) {
1463 dc->stop.pts = 0;
1464 } else if (dc->cmd == V4L2_DEC_CMD_START) {
1465 dc->start.speed = 0;
1466 dc->start.format = V4L2_DEC_START_FMT_NONE;
1467 }
1468 return 0;
1469 }
1470 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_try_decoder_cmd);
1471
1472
1473
1474
1475
1476 int v4l2_m2m_encoder_cmd(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
1477 struct v4l2_encoder_cmd *ec)
1478 {
1479 if (ec->cmd != V4L2_ENC_CMD_STOP && ec->cmd != V4L2_ENC_CMD_START)
1480 return -EINVAL;
1481
1482 if (ec->cmd == V4L2_ENC_CMD_STOP)
1483 return v4l2_update_last_buf_state(m2m_ctx);
1484
1485 if (m2m_ctx->is_draining)
1486 return -EBUSY;
1487
1488 if (m2m_ctx->has_stopped)
1489 m2m_ctx->has_stopped = false;
1490
1491 return 0;
1492 }
1493 EXPORT_SYMBOL_GPL(v4l2_m2m_encoder_cmd);
1494
1495
1496
1497
1498
1499 int v4l2_m2m_decoder_cmd(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
1500 struct v4l2_decoder_cmd *dc)
1501 {
1502 if (dc->cmd != V4L2_DEC_CMD_STOP && dc->cmd != V4L2_DEC_CMD_START)
1503 return -EINVAL;
1504
1505 if (dc->cmd == V4L2_DEC_CMD_STOP)
1506 return v4l2_update_last_buf_state(m2m_ctx);
1507
1508 if (m2m_ctx->is_draining)
1509 return -EBUSY;
1510
1511 if (m2m_ctx->has_stopped)
1512 m2m_ctx->has_stopped = false;
1513
1514 return 0;
1515 }
1516 EXPORT_SYMBOL_GPL(v4l2_m2m_decoder_cmd);
1517
1518 int v4l2_m2m_ioctl_encoder_cmd(struct file *file, void *priv,
1519 struct v4l2_encoder_cmd *ec)
1520 {
1521 struct v4l2_fh *fh = file->private_data;
1522
1523 return v4l2_m2m_encoder_cmd(file, fh->m2m_ctx, ec);
1524 }
1525 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_encoder_cmd);
1526
1527 int v4l2_m2m_ioctl_decoder_cmd(struct file *file, void *priv,
1528 struct v4l2_decoder_cmd *dc)
1529 {
1530 struct v4l2_fh *fh = file->private_data;
1531
1532 return v4l2_m2m_decoder_cmd(file, fh->m2m_ctx, dc);
1533 }
1534 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_decoder_cmd);
1535
1536 int v4l2_m2m_ioctl_stateless_try_decoder_cmd(struct file *file, void *fh,
1537 struct v4l2_decoder_cmd *dc)
1538 {
1539 if (dc->cmd != V4L2_DEC_CMD_FLUSH)
1540 return -EINVAL;
1541
1542 dc->flags = 0;
1543
1544 return 0;
1545 }
1546 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_stateless_try_decoder_cmd);
1547
1548 int v4l2_m2m_ioctl_stateless_decoder_cmd(struct file *file, void *priv,
1549 struct v4l2_decoder_cmd *dc)
1550 {
1551 struct v4l2_fh *fh = file->private_data;
1552 struct vb2_v4l2_buffer *out_vb, *cap_vb;
1553 struct v4l2_m2m_dev *m2m_dev = fh->m2m_ctx->m2m_dev;
1554 unsigned long flags;
1555 int ret;
1556
1557 ret = v4l2_m2m_ioctl_stateless_try_decoder_cmd(file, priv, dc);
1558 if (ret < 0)
1559 return ret;
1560
1561 spin_lock_irqsave(&m2m_dev->job_spinlock, flags);
1562 out_vb = v4l2_m2m_last_src_buf(fh->m2m_ctx);
1563 cap_vb = v4l2_m2m_last_dst_buf(fh->m2m_ctx);
1564
1565
1566
1567
1568
1569
1570
1571 if (out_vb) {
1572 out_vb->flags &= ~V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF;
1573 } else if (cap_vb && cap_vb->is_held) {
1574
1575
1576
1577
1578
1579 cap_vb->is_held = false;
1580 v4l2_m2m_dst_buf_remove(fh->m2m_ctx);
1581 v4l2_m2m_buf_done(cap_vb, VB2_BUF_STATE_DONE);
1582 }
1583 spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
1584
1585 return 0;
1586 }
1587 EXPORT_SYMBOL_GPL(v4l2_m2m_ioctl_stateless_decoder_cmd);
1588
1589
1590
1591
1592
1593
1594 int v4l2_m2m_fop_mmap(struct file *file, struct vm_area_struct *vma)
1595 {
1596 struct v4l2_fh *fh = file->private_data;
1597
1598 return v4l2_m2m_mmap(file, fh->m2m_ctx, vma);
1599 }
1600 EXPORT_SYMBOL_GPL(v4l2_m2m_fop_mmap);
1601
1602 __poll_t v4l2_m2m_fop_poll(struct file *file, poll_table *wait)
1603 {
1604 struct v4l2_fh *fh = file->private_data;
1605 struct v4l2_m2m_ctx *m2m_ctx = fh->m2m_ctx;
1606 __poll_t ret;
1607
1608 if (m2m_ctx->q_lock)
1609 mutex_lock(m2m_ctx->q_lock);
1610
1611 ret = v4l2_m2m_poll(file, m2m_ctx, wait);
1612
1613 if (m2m_ctx->q_lock)
1614 mutex_unlock(m2m_ctx->q_lock);
1615
1616 return ret;
1617 }
1618 EXPORT_SYMBOL_GPL(v4l2_m2m_fop_poll);
1619